json-schema-to-typescript
Advanced tools
Comparing version 10.1.5 to 11.0.0
@@ -5,2 +5,16 @@ # Changelog | ||
## 11.0.0 | ||
This is a major release with lots of bugfixes, some of which may change emitted types. | ||
- 2ca6e50 Bugfix: Fix crash that may happen when emitting types for cyclical schemas (#323, #376) | ||
- 8fa728e Bugfix: Fix tests on Windows, make snapshot ordering consistent | ||
- b78a616 Bugfix: Make `compile()` non-mutating (#370, #443) | ||
- a89ffe1 Bugfix: Add maximum size heuristic for tuple types (#438) | ||
- 6fbcbc8 Bugfix: Improve performance & stability issue caused by JSON serialization (#422) | ||
- 7aa353d Feat: Add support for `$id` (#436) | ||
- 59747b1 Feat: Add support for specifying a default for `additionalProperties` (#335) | ||
- 966cca5 Cleanup: Drop support for Node 10 | ||
## 10.1.0 | ||
@@ -7,0 +21,0 @@ |
@@ -5,3 +5,7 @@ #!/usr/bin/env node | ||
if (k2 === undefined) k2 = k; | ||
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
@@ -95,3 +99,3 @@ if (k2 === undefined) k2 = k; | ||
if ((ISGLOB || ISDIR) && argOut && argOut.includes('.d.ts')) { | ||
throw new ReferenceError("You have specified a single file " + argOut + " output for a multi file input " + argIn + ". This feature is not yet supported, refer to issue #272 (https://github.com/bcherny/json-schema-to-typescript/issues/272)"); | ||
throw new ReferenceError("You have specified a single file ".concat(argOut, " output for a multi file input ").concat(argIn, ". This feature is not yet supported, refer to issue #272 (https://github.com/bcherny/json-schema-to-typescript/issues/272)")); | ||
} | ||
@@ -120,3 +124,3 @@ _a.label = 1; | ||
e_1 = _a.sent(); | ||
utils_1.error(e_1); | ||
(0, utils_1.error)(e_1); | ||
process.exit(1); | ||
@@ -131,3 +135,3 @@ return [3 /*break*/, 9]; | ||
function isDir(path) { | ||
return fs_1.existsSync(path) && fs_1.lstatSync(path).isDirectory(); | ||
return (0, fs_1.existsSync)(path) && (0, fs_1.lstatSync)(path).isDirectory(); | ||
} | ||
@@ -140,3 +144,3 @@ function processGlob(argIn, argOut, argv) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, glob_promise_1.default(argIn)]; // execute glob pattern match | ||
case 0: return [4 /*yield*/, (0, glob_promise_1.default)(argIn)]; // execute glob pattern match | ||
case 1: | ||
@@ -146,3 +150,3 @@ files = _a.sent() // execute glob pattern match | ||
if (files.length === 0) { | ||
throw ReferenceError("You passed a glob pattern \"" + argIn + "\", but there are no files that match that pattern in " + process.cwd()); | ||
throw ReferenceError("You passed a glob pattern \"".concat(argIn, "\", but there are no files that match that pattern in ").concat(process.cwd())); | ||
} | ||
@@ -167,3 +171,3 @@ return [4 /*yield*/, Promise.all(files.map(function (file) { return __awaiter(_this, void 0, void 0, function () { | ||
var file = _a[0], result = _a[1]; | ||
var outputPath = argOut && argOut + "/" + path_1.basename(file, '.json') + ".d.ts"; | ||
var outputPath = argOut && "".concat(argOut, "/").concat((0, path_1.basename)(file, '.json'), ".d.ts"); | ||
outputResult(result, outputPath); | ||
@@ -194,3 +198,3 @@ }); | ||
case 2: | ||
outputPath = utils_1.pathTransform(argOut, argIn, file); | ||
outputPath = (0, utils_1.pathTransform)(argOut, argIn, file); | ||
_b = [file]; | ||
@@ -209,3 +213,3 @@ return [4 /*yield*/, processFile(file, argv)]; | ||
var file = _a[0], result = _a[1], outputPath = _a[2]; | ||
return outputResult(result, outputPath ? outputPath + "/" + path_1.basename(file, '.json') + ".d.ts" : undefined); | ||
return outputResult(result, outputPath ? "".concat(outputPath, "/").concat((0, path_1.basename)(file, '.json'), ".d.ts") : undefined); | ||
}); | ||
@@ -226,6 +230,6 @@ return [2 /*return*/]; | ||
case 1: | ||
if (!isDir(path_1.dirname(outputPath))) { | ||
mkdirp.sync(path_1.dirname(outputPath)); | ||
if (!isDir((0, path_1.dirname)(outputPath))) { | ||
mkdirp.sync((0, path_1.dirname)(outputPath)); | ||
} | ||
return [4 /*yield*/, fs_1.writeFile(outputPath, result)]; | ||
return [4 /*yield*/, (0, fs_1.writeFile)(outputPath, result)]; | ||
case 2: return [2 /*return*/, _a.sent()]; | ||
@@ -247,3 +251,3 @@ case 3: return [2 /*return*/]; | ||
schema = _b.apply(_a, [_c.sent()]); | ||
return [2 /*return*/, index_1.compile(schema, argIn, argv)]; | ||
return [2 /*return*/, (0, index_1.compile)(schema, argIn, argv)]; | ||
} | ||
@@ -255,4 +259,4 @@ }); | ||
if (paths === void 0) { paths = []; } | ||
if (fs_1.existsSync(path) && fs_1.lstatSync(path).isDirectory()) { | ||
fs_1.readdirSync(path_1.resolve(path)).forEach(function (item) { return getPaths(path_1.join(path, item), paths); }); | ||
if ((0, fs_1.existsSync)(path) && (0, fs_1.lstatSync)(path).isDirectory()) { | ||
(0, fs_1.readdirSync)((0, path_1.resolve)(path)).forEach(function (item) { return getPaths((0, path_1.join)(path, item), paths); }); | ||
} | ||
@@ -266,10 +270,10 @@ else { | ||
if (!argIn) { | ||
return get_stdin_1.default(); | ||
return (0, get_stdin_1.default)(); | ||
} | ||
return fs_1.readFile(path_1.resolve(process.cwd(), argIn), 'utf-8'); | ||
return (0, fs_1.readFile)((0, path_1.resolve)(process.cwd(), argIn), 'utf-8'); | ||
} | ||
function printHelp() { | ||
var pkg = require('../../package.json'); | ||
process.stdout.write("\n" + pkg.name + " " + pkg.version + "\nUsage: json2ts [--input, -i] [IN_FILE] [--output, -o] [OUT_FILE] [OPTIONS]\n\nWith no IN_FILE, or when IN_FILE is -, read standard input.\nWith no OUT_FILE and when IN_FILE is specified, create .d.ts file in the same directory.\nWith no OUT_FILE nor IN_FILE, write to standard output.\n\nYou can use any of the following options by adding them at the end.\nBoolean values can be set to false using the 'no-' prefix.\n\n --cwd=XXX\n Root directory for resolving $ref\n --declareExternallyReferenced\n Declare external schemas referenced via '$ref'?\n --enableConstEnums\n Prepend enums with 'const'?\n --format\n Format code? Set this to false to improve performance.\n --style.XXX=YYY\n Prettier configuration\n --unknownAny\n Output unknown type instead of any type\n --unreachableDefinitions\n Generates code for definitions that aren't referenced by the schema\n"); | ||
process.stdout.write("\n".concat(pkg.name, " ").concat(pkg.version, "\nUsage: json2ts [--input, -i] [IN_FILE] [--output, -o] [OUT_FILE] [OPTIONS]\n\nWith no IN_FILE, or when IN_FILE is -, read standard input.\nWith no OUT_FILE and when IN_FILE is specified, create .d.ts file in the same directory.\nWith no OUT_FILE nor IN_FILE, write to standard output.\n\nYou can use any of the following options by adding them at the end.\nBoolean values can be set to false using the 'no-' prefix.\n\n --additionalProperties\n Default value for additionalProperties, when it is not explicitly set\n --cwd=XXX\n Root directory for resolving $ref\n --declareExternallyReferenced\n Declare external schemas referenced via '$ref'?\n --enableConstEnums\n Prepend enums with 'const'?\n --format\n Format code? Set this to false to improve performance.\n --maxItems\n Maximum number of unioned tuples to emit when representing bounded-size\n array types, before falling back to emitting unbounded arrays. Increase\n this to improve precision of emitted types, decrease it to improve\n performance, or set it to -1 to ignore minItems and maxItems.\n --style.XXX=YYY\n Prettier configuration\n --unknownAny\n Output unknown type instead of any type\n --unreachableDefinitions\n Generates code for definitions that aren't referenced by the schema\n")); | ||
} | ||
//# sourceMappingURL=cli.js.map |
@@ -20,5 +20,5 @@ "use strict"; | ||
} | ||
return prettier_1.format(code, __assign({ parser: 'typescript' }, options.style)); | ||
return (0, prettier_1.format)(code, __assign({ parser: 'typescript' }, options.style)); | ||
} | ||
exports.format = format; | ||
//# sourceMappingURL=formatter.js.map |
@@ -0,3 +1,7 @@ | ||
/// <reference types="lodash" /> | ||
import { Options } from './index'; | ||
import { AST } from './types/AST'; | ||
export declare function generate(ast: AST, options?: Options): string; | ||
declare function generateTypeUnmemoized(ast: AST, options: Options): string; | ||
export declare const generateType: typeof generateTypeUnmemoized & import("lodash").MemoizedFunction; | ||
export {}; |
"use strict"; | ||
var __spreadArrays = (this && this.__spreadArrays) || function () { | ||
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; | ||
for (var r = Array(s), k = 0, i = 0; i < il; i++) | ||
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) | ||
r[k] = a[j]; | ||
return r; | ||
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { | ||
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { | ||
if (ar || !(i in from)) { | ||
if (!ar) ar = Array.prototype.slice.call(from, 0, i); | ||
ar[i] = from[i]; | ||
} | ||
} | ||
return to.concat(ar || Array.prototype.slice.call(from)); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.generate = void 0; | ||
exports.generateType = exports.generate = void 0; | ||
var lodash_1 = require("lodash"); | ||
@@ -67,3 +69,3 @@ var index_1 = require("./index"); | ||
type = [ | ||
AST_1.hasStandaloneName(ast) && | ||
(0, AST_1.hasStandaloneName)(ast) && | ||
(ast.standaloneName === rootASTName || options.declareExternallyReferenced) && | ||
@@ -101,17 +103,14 @@ generateStandaloneInterface(ast, options), | ||
processed.add(ast); | ||
var type = ''; | ||
switch (ast.type) { | ||
case 'ARRAY': | ||
type = [ | ||
return [ | ||
declareNamedTypes(ast.params, options, rootASTName, processed), | ||
AST_1.hasStandaloneName(ast) ? generateStandaloneType(ast, options) : undefined | ||
(0, AST_1.hasStandaloneName)(ast) ? generateStandaloneType(ast, options) : undefined | ||
] | ||
.filter(Boolean) | ||
.join('\n'); | ||
break; | ||
case 'ENUM': | ||
type = ''; | ||
break; | ||
return ''; | ||
case 'INTERFACE': | ||
type = getSuperTypesAndParams(ast) | ||
return getSuperTypesAndParams(ast) | ||
.map(function (ast) { | ||
@@ -123,8 +122,7 @@ return (ast.standaloneName === rootASTName || options.declareExternallyReferenced) && | ||
.join('\n'); | ||
break; | ||
case 'INTERSECTION': | ||
case 'TUPLE': | ||
case 'UNION': | ||
type = [ | ||
AST_1.hasStandaloneName(ast) ? generateStandaloneType(ast, options) : undefined, | ||
return [ | ||
(0, AST_1.hasStandaloneName)(ast) ? generateStandaloneType(ast, options) : undefined, | ||
ast.params | ||
@@ -140,21 +138,21 @@ .map(function (ast) { return declareNamedTypes(ast, options, rootASTName, processed); }) | ||
.join('\n'); | ||
break; | ||
default: | ||
if (AST_1.hasStandaloneName(ast)) { | ||
type = generateStandaloneType(ast, options); | ||
if ((0, AST_1.hasStandaloneName)(ast)) { | ||
return generateStandaloneType(ast, options); | ||
} | ||
return ''; | ||
} | ||
return type; | ||
} | ||
function generateType(ast, options) { | ||
function generateTypeUnmemoized(ast, options) { | ||
var type = generateRawType(ast, options); | ||
if (options.strictIndexSignatures && ast.keyName === '[k: string]') { | ||
return type + " | undefined"; | ||
return "".concat(type, " | undefined"); | ||
} | ||
return type; | ||
} | ||
exports.generateType = (0, lodash_1.memoize)(generateTypeUnmemoized); | ||
function generateRawType(ast, options) { | ||
utils_1.log('magenta', 'generator', ast); | ||
if (AST_1.hasStandaloneName(ast)) { | ||
return utils_1.toSafeString(ast.standaloneName); | ||
(0, utils_1.log)('magenta', 'generator', ast); | ||
if ((0, AST_1.hasStandaloneName)(ast)) { | ||
return (0, utils_1.toSafeString)(ast.standaloneName); | ||
} | ||
@@ -166,3 +164,3 @@ switch (ast.type) { | ||
return (function () { | ||
var type = generateType(ast.params, options); | ||
var type = (0, exports.generateType)(ast.params, options); | ||
return type.endsWith('"') ? '(' + type + ')[]' : type + '[]'; | ||
@@ -193,3 +191,3 @@ })(); | ||
var spreadParam = ast.spreadParam; | ||
var astParams = __spreadArrays(ast.params); | ||
var astParams = __spreadArray([], ast.params, true); | ||
if (minItems > 0 && minItems > astParams.length && ast.spreadParam === undefined) { | ||
@@ -211,3 +209,3 @@ // this is a valid state, and JSONSchema doesn't care about the item type | ||
if (spreadParam) { | ||
var spread = '...(' + generateType(spreadParam, options) + ')[]'; | ||
var spread = '...(' + (0, exports.generateType)(spreadParam, options) + ')[]'; | ||
params.push(spread); | ||
@@ -220,3 +218,3 @@ } | ||
} | ||
var paramsList = astParams.map(function (param) { return generateType(param, options); }); | ||
var paramsList = astParams.map(function (param) { return (0, exports.generateType)(param, options); }); | ||
if (paramsList.length > minItems) { | ||
@@ -270,3 +268,3 @@ /* | ||
function generateSetOperation(ast, options) { | ||
var members = ast.params.map(function (_) { return generateType(_, options); }); | ||
var members = ast.params.map(function (_) { return (0, exports.generateType)(_, options); }); | ||
var separator = ast.type === 'UNION' ? '|' : '&'; | ||
@@ -282,11 +280,11 @@ return members.length === 1 ? members[0] : '(' + members.join(' ' + separator + ' ') + ')'; | ||
var isRequired = _a.isRequired, keyName = _a.keyName, ast = _a.ast; | ||
return [isRequired, keyName, ast, generateType(ast, options)]; | ||
return [isRequired, keyName, ast, (0, exports.generateType)(ast, options)]; | ||
}) | ||
.map(function (_a) { | ||
var isRequired = _a[0], keyName = _a[1], ast = _a[2], type = _a[3]; | ||
return (AST_1.hasComment(ast) && !ast.standaloneName ? generateComment(ast.comment) + '\n' : '') + | ||
return ((0, AST_1.hasComment)(ast) && !ast.standaloneName ? generateComment(ast.comment) + '\n' : '') + | ||
escapeKeyName(keyName) + | ||
(isRequired ? '' : '?') + | ||
': ' + | ||
(AST_1.hasStandaloneName(ast) ? utils_1.toSafeString(type) : type); | ||
((0, AST_1.hasStandaloneName)(ast) ? (0, utils_1.toSafeString)(type) : type); | ||
}) | ||
@@ -298,13 +296,13 @@ .join('\n') + | ||
function generateComment(comment) { | ||
return __spreadArrays(['/**'], comment.split('\n').map(function (_) { return ' * ' + _; }), [' */']).join('\n'); | ||
return __spreadArray(__spreadArray(['/**'], comment.split('\n').map(function (_) { return ' * ' + _; }), true), [' */'], false).join('\n'); | ||
} | ||
function generateStandaloneEnum(ast, options) { | ||
return ((AST_1.hasComment(ast) ? generateComment(ast.comment) + '\n' : '') + | ||
return (((0, AST_1.hasComment)(ast) ? generateComment(ast.comment) + '\n' : '') + | ||
'export ' + | ||
(options.enableConstEnums ? 'const ' : '') + | ||
("enum " + utils_1.toSafeString(ast.standaloneName) + " {") + | ||
"enum ".concat((0, utils_1.toSafeString)(ast.standaloneName), " {") + | ||
'\n' + | ||
ast.params.map(function (_a) { | ||
var ast = _a.ast, keyName = _a.keyName; | ||
return keyName + ' = ' + generateType(ast, options); | ||
return keyName + ' = ' + (0, exports.generateType)(ast, options); | ||
}).join(',\n') + | ||
@@ -315,6 +313,6 @@ '\n' + | ||
function generateStandaloneInterface(ast, options) { | ||
return ((AST_1.hasComment(ast) ? generateComment(ast.comment) + '\n' : '') + | ||
("export interface " + utils_1.toSafeString(ast.standaloneName) + " ") + | ||
return (((0, AST_1.hasComment)(ast) ? generateComment(ast.comment) + '\n' : '') + | ||
"export interface ".concat((0, utils_1.toSafeString)(ast.standaloneName), " ") + | ||
(ast.superTypes.length > 0 | ||
? "extends " + ast.superTypes.map(function (superType) { return utils_1.toSafeString(superType.standaloneName); }).join(', ') + " " | ||
? "extends ".concat(ast.superTypes.map(function (superType) { return (0, utils_1.toSafeString)(superType.standaloneName); }).join(', '), " ") | ||
: '') + | ||
@@ -324,4 +322,4 @@ generateInterface(ast, options)); | ||
function generateStandaloneType(ast, options) { | ||
return ((AST_1.hasComment(ast) ? generateComment(ast.comment) + '\n' : '') + | ||
("export type " + utils_1.toSafeString(ast.standaloneName) + " = " + generateType(lodash_1.omit(ast, 'standaloneName') /* TODO */, options))); | ||
return (((0, AST_1.hasComment)(ast) ? generateComment(ast.comment) + '\n' : '') + | ||
"export type ".concat((0, utils_1.toSafeString)(ast.standaloneName), " = ").concat((0, exports.generateType)((0, lodash_1.omit)(ast, 'standaloneName') /* TODO */, options))); | ||
} | ||
@@ -328,0 +326,0 @@ function escapeKeyName(keyName) { |
import { JSONSchema4 } from 'json-schema'; | ||
import { Options as $RefOptions } from 'json-schema-ref-parser'; | ||
import { Options as $RefOptions } from '@apidevtools/json-schema-ref-parser'; | ||
import { Options as PrettierOptions } from 'prettier'; | ||
@@ -7,2 +7,10 @@ export { EnumJSONSchema, JSONSchema, NamedEnumJSONSchema, CustomTypeJSONSchema } from './types/JSONSchema'; | ||
/** | ||
* [$RefParser](https://github.com/BigstickCarpet/json-schema-ref-parser) Options, used when resolving `$ref`s | ||
*/ | ||
$refOptions: $RefOptions; | ||
/** | ||
* Default value for additionalProperties, when it is not explicitly set. | ||
*/ | ||
additionalProperties: boolean; | ||
/** | ||
* Disclaimer comment prepended to the top of each generated file. | ||
@@ -32,2 +40,9 @@ */ | ||
/** | ||
* Maximum number of unioned tuples to emit when representing bounded-size array types, | ||
* before falling back to emitting unbounded arrays. Increase this to improve precision | ||
* of emitted types, decrease it to improve performance, or set it to `-1` to ignore | ||
* `minItems` and `maxItems`. | ||
*/ | ||
maxItems: number; | ||
/** | ||
* Append all index signatures with `| undefined` so that they are strictly typed. | ||
@@ -50,6 +65,2 @@ * | ||
unknownAny: boolean; | ||
/** | ||
* [$RefParser](https://github.com/BigstickCarpet/json-schema-ref-parser) Options, used when resolving `$ref`s | ||
*/ | ||
$refOptions: $RefOptions; | ||
} | ||
@@ -56,0 +67,0 @@ export declare const DEFAULT_OPTIONS: Options; |
@@ -10,2 +10,4 @@ "use strict"; | ||
return function (d, b) { | ||
if (typeof b !== "function" && b !== null) | ||
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); | ||
extendStatics(d, b); | ||
@@ -78,4 +80,6 @@ function __() { this.constructor = d; } | ||
var linker_1 = require("./linker"); | ||
var optionValidator_1 = require("./optionValidator"); | ||
exports.DEFAULT_OPTIONS = { | ||
$refOptions: {}, | ||
additionalProperties: true, | ||
bannerComment: "/* tslint:disable */\n/**\n* This file was automatically generated by json-schema-to-typescript.\n* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,\n* and run json-schema-to-typescript to regenerate this file.\n*/", | ||
@@ -87,2 +91,3 @@ cwd: process.cwd(), | ||
ignoreMinAndMaxItems: false, | ||
maxItems: 20, | ||
strictIndexSignatures: false, | ||
@@ -103,9 +108,9 @@ style: { | ||
if (options === void 0) { options = exports.DEFAULT_OPTIONS; } | ||
var contents = utils_1.Try(function () { return fs_1.readFileSync(filename); }, function () { | ||
throw new ReferenceError("Unable to read file \"" + filename + "\""); | ||
var contents = (0, utils_1.Try)(function () { return (0, fs_1.readFileSync)(filename); }, function () { | ||
throw new ReferenceError("Unable to read file \"".concat(filename, "\"")); | ||
}); | ||
var schema = utils_1.Try(function () { return JSON.parse(contents.toString()); }, function () { | ||
throw new TypeError("Error parsing JSON in file \"" + filename + "\""); | ||
var schema = (0, utils_1.Try)(function () { return JSON.parse(contents.toString()); }, function () { | ||
throw new TypeError("Error parsing JSON in file \"".concat(filename, "\"")); | ||
}); | ||
return compile(schema, utils_1.stripExtension(filename), __assign({ cwd: path_1.dirname(filename) }, options)); | ||
return compile(schema, (0, utils_1.stripExtension)(filename), __assign({ cwd: (0, path_1.dirname)(filename) }, options)); | ||
} | ||
@@ -117,61 +122,49 @@ exports.compileFromFile = compileFromFile; | ||
function time() { | ||
return "(" + (Date.now() - start) + "ms)"; | ||
return "(".concat(Date.now() - start, "ms)"); | ||
} | ||
var _options, start, errors, dereferenced, linked, normalized, parsed, optimized, generated, formatted; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
var _options, start, _schema, _a, dereferencedPaths, dereferencedSchema, linked, errors, normalized, parsed, optimized, generated, formatted; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
_options = lodash_1.merge({}, exports.DEFAULT_OPTIONS, options); | ||
(0, optionValidator_1.validateOptions)(options); | ||
_options = (0, lodash_1.merge)({}, exports.DEFAULT_OPTIONS, options); | ||
start = Date.now(); | ||
errors = validator_1.validate(schema, name); | ||
if (errors.length) { | ||
errors.forEach(function (_) { return utils_1.error(_); }); | ||
throw new ValidationError(); | ||
} | ||
if (process.env.VERBOSE) { | ||
utils_1.log('green', 'validator', time(), '✅ No change'); | ||
} | ||
// normalize options | ||
if (!lodash_1.endsWith(_options.cwd, '/')) { | ||
if (!(0, lodash_1.endsWith)(_options.cwd, '/')) { | ||
_options.cwd += '/'; | ||
} | ||
return [4 /*yield*/, resolver_1.dereference(schema, _options)]; | ||
_schema = (0, lodash_1.cloneDeep)(schema); | ||
return [4 /*yield*/, (0, resolver_1.dereference)(_schema, _options)]; | ||
case 1: | ||
dereferenced = _a.sent(); | ||
_a = _b.sent(), dereferencedPaths = _a.dereferencedPaths, dereferencedSchema = _a.dereferencedSchema; | ||
if (process.env.VERBOSE) { | ||
if (util_1.isDeepStrictEqual(schema, dereferenced)) { | ||
utils_1.log('green', 'dereferencer', time(), '✅ No change'); | ||
if ((0, util_1.isDeepStrictEqual)(_schema, dereferencedSchema)) { | ||
(0, utils_1.log)('green', 'dereferencer', time(), '✅ No change'); | ||
} | ||
else { | ||
utils_1.log('green', 'dereferencer', time(), '✅ Result:', dereferenced); | ||
(0, utils_1.log)('green', 'dereferencer', time(), '✅ Result:', dereferencedSchema); | ||
} | ||
} | ||
linked = linker_1.link(dereferenced); | ||
linked = (0, linker_1.link)(dereferencedSchema); | ||
if (process.env.VERBOSE) { | ||
utils_1.log('green', 'linker', time(), '✅ No change'); | ||
(0, utils_1.log)('green', 'linker', time(), '✅ No change'); | ||
} | ||
normalized = normalizer_1.normalize(linked, name, _options); | ||
if (process.env.VERBOSE) { | ||
if (util_1.isDeepStrictEqual(linked, normalized)) { | ||
utils_1.log('yellow', 'normalizer', time(), '✅ No change'); | ||
} | ||
else { | ||
utils_1.log('yellow', 'normalizer', time(), '✅ Result:', normalized); | ||
} | ||
errors = (0, validator_1.validate)(linked, name); | ||
if (errors.length) { | ||
errors.forEach(function (_) { return (0, utils_1.error)(_); }); | ||
throw new ValidationError(); | ||
} | ||
parsed = parser_1.parse(normalized, _options); | ||
utils_1.log('blue', 'parser', time(), '✅ Result:', parsed); | ||
optimized = optimizer_1.optimize(parsed); | ||
if (process.env.VERBOSE) { | ||
if (util_1.isDeepStrictEqual(parsed, optimized)) { | ||
utils_1.log('cyan', 'optimizer', time(), '✅ No change'); | ||
} | ||
else { | ||
utils_1.log('cyan', 'optimizer', time(), '✅ Result:', optimized); | ||
} | ||
(0, utils_1.log)('green', 'validator', time(), '✅ No change'); | ||
} | ||
generated = generator_1.generate(optimized, _options); | ||
utils_1.log('magenta', 'generator', time(), '✅ Result:', generated); | ||
formatted = formatter_1.format(generated, _options); | ||
utils_1.log('white', 'formatter', time(), '✅ Result:', formatted); | ||
normalized = (0, normalizer_1.normalize)(linked, dereferencedPaths, name, _options); | ||
(0, utils_1.log)('yellow', 'normalizer', time(), '✅ Result:', normalized); | ||
parsed = (0, parser_1.parse)(normalized, _options); | ||
(0, utils_1.log)('blue', 'parser', time(), '✅ Result:', parsed); | ||
optimized = (0, optimizer_1.optimize)(parsed, _options); | ||
(0, utils_1.log)('cyan', 'optimizer', time(), '✅ Result:', optimized); | ||
generated = (0, generator_1.generate)(optimized, _options); | ||
(0, utils_1.log)('magenta', 'generator', time(), '✅ Result:', generated); | ||
formatted = (0, formatter_1.format)(generated, _options); | ||
(0, utils_1.log)('white', 'formatter', time(), '✅ Result:', formatted); | ||
return [2 /*return*/, formatted]; | ||
@@ -178,0 +171,0 @@ } |
@@ -12,3 +12,3 @@ "use strict"; | ||
if (parent === void 0) { parent = null; } | ||
if (!Array.isArray(schema) && !lodash_1.isPlainObject(schema)) { | ||
if (!Array.isArray(schema) && !(0, lodash_1.isPlainObject)(schema)) { | ||
return schema; | ||
@@ -15,0 +15,0 @@ } |
import { LinkedJSONSchema, NormalizedJSONSchema } from './types/JSONSchema'; | ||
import { Options } from './'; | ||
export declare function normalize(rootSchema: LinkedJSONSchema, filename: string, options: Options): NormalizedJSONSchema; | ||
import { DereferencedPaths } from './resolver'; | ||
export declare function normalize(rootSchema: LinkedJSONSchema, dereferencedPaths: DereferencedPaths, filename: string, options: Options): NormalizedJSONSchema; |
"use strict"; | ||
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { | ||
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { | ||
if (ar || !(i in from)) { | ||
if (!ar) ar = Array.prototype.slice.call(from, 0, i); | ||
ar[i] = from[i]; | ||
} | ||
} | ||
return to.concat(ar || Array.prototype.slice.call(from)); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -39,26 +48,67 @@ exports.normalize = void 0; | ||
}); | ||
// TODO: default to empty schema (as per spec) instead | ||
rules.set('Default additionalProperties to true', function (schema) { | ||
rules.set('Default additionalProperties', function (schema, _, options) { | ||
if (isObjectType(schema) && !('additionalProperties' in schema) && schema.patternProperties === undefined) { | ||
schema.additionalProperties = true; | ||
schema.additionalProperties = options.additionalProperties; | ||
} | ||
}); | ||
rules.set('Default top level `id`', function (schema, fileName) { | ||
var isRoot = schema[JSONSchema_1.Parent] === null; | ||
if (isRoot && !schema.id) { | ||
schema.id = utils_1.toSafeString(utils_1.justName(fileName)); | ||
rules.set('Transform id to $id', function (schema, fileName) { | ||
if (!(0, utils_1.isSchemaLike)(schema)) { | ||
return; | ||
} | ||
if (schema.id && schema.$id && schema.id !== schema.$id) { | ||
throw ReferenceError("Schema must define either id or $id, not both. Given id=".concat(schema.id, ", $id=").concat(schema.$id, " in ").concat(fileName)); | ||
} | ||
if (schema.id) { | ||
schema.$id = schema.id; | ||
delete schema.id; | ||
} | ||
}); | ||
rules.set('Escape closing JSDoc Comment', function (schema) { | ||
utils_1.escapeBlockComment(schema); | ||
rules.set('Add an $id to anything that needs it', function (schema, fileName, _options, _key, dereferencedPaths) { | ||
if (!(0, utils_1.isSchemaLike)(schema)) { | ||
return; | ||
} | ||
// Top-level schema | ||
if (!schema.$id && !schema[JSONSchema_1.Parent]) { | ||
schema.$id = (0, utils_1.toSafeString)((0, utils_1.justName)(fileName)); | ||
return; | ||
} | ||
// Sub-schemas with references | ||
if (!isArrayType(schema) && !isObjectType(schema)) { | ||
return; | ||
} | ||
// We'll infer from $id and title downstream | ||
// TODO: Normalize upstream | ||
var dereferencedName = dereferencedPaths.get(schema); | ||
if (!schema.$id && !schema.title && dereferencedName) { | ||
schema.$id = (0, utils_1.toSafeString)((0, utils_1.justName)(dereferencedName)); | ||
} | ||
if (dereferencedName) { | ||
dereferencedPaths.delete(schema); | ||
} | ||
}); | ||
rules.set('Escape closing JSDoc comment', function (schema) { | ||
(0, utils_1.escapeBlockComment)(schema); | ||
}); | ||
rules.set('Add JSDoc comments for minItems and maxItems', function (schema) { | ||
if (!isArrayType(schema)) { | ||
return; | ||
} | ||
var commentsToAppend = [ | ||
'minItems' in schema ? "@minItems ".concat(schema.minItems) : '', | ||
'maxItems' in schema ? "@maxItems ".concat(schema.maxItems) : '' | ||
].filter(Boolean); | ||
if (commentsToAppend.length) { | ||
schema.description = utils_1.appendToDescription.apply(void 0, __spreadArray([schema.description], commentsToAppend, false)); | ||
} | ||
}); | ||
rules.set('Optionally remove maxItems and minItems', function (schema, _fileName, options) { | ||
if (options.ignoreMinAndMaxItems) { | ||
if ('maxItems' in schema) { | ||
delete schema.maxItems; | ||
} | ||
if ('minItems' in schema) { | ||
delete schema.minItems; | ||
} | ||
if (!isArrayType(schema)) { | ||
return; | ||
} | ||
if ('minItems' in schema && options.ignoreMinAndMaxItems) { | ||
delete schema.minItems; | ||
} | ||
if ('maxItems' in schema && (options.ignoreMinAndMaxItems || options.maxItems === -1)) { | ||
delete schema.maxItems; | ||
} | ||
}); | ||
@@ -70,8 +120,22 @@ rules.set('Normalize schema.minItems', function (schema, _fileName, options) { | ||
// make sure we only add the props onto array types | ||
if (isArrayType(schema)) { | ||
var minItems = schema.minItems; | ||
schema.minItems = typeof minItems === 'number' ? minItems : 0; | ||
if (!isArrayType(schema)) { | ||
return; | ||
} | ||
var minItems = schema.minItems; | ||
schema.minItems = typeof minItems === 'number' ? minItems : 0; | ||
// cannot normalize maxItems because maxItems = 0 has an actual meaning | ||
}); | ||
rules.set('Remove maxItems if it is big enough to likely cause OOMs', function (schema, _fileName, options) { | ||
if (options.ignoreMinAndMaxItems || options.maxItems === -1) { | ||
return; | ||
} | ||
if (!isArrayType(schema)) { | ||
return; | ||
} | ||
var maxItems = schema.maxItems, minItems = schema.minItems; | ||
// minItems is guaranteed to be a number after the previous rule runs | ||
if (maxItems !== undefined && maxItems - minItems > options.maxItems) { | ||
delete schema.maxItems; | ||
} | ||
}); | ||
rules.set('Normalize schema.items', function (schema, _fileName, options) { | ||
@@ -129,4 +193,4 @@ if (options.ignoreMinAndMaxItems) { | ||
}); | ||
function normalize(rootSchema, filename, options) { | ||
rules.forEach(function (rule) { return utils_1.traverse(rootSchema, function (schema) { return rule(schema, filename, options); }); }); | ||
function normalize(rootSchema, dereferencedPaths, filename, options) { | ||
rules.forEach(function (rule) { return (0, utils_1.traverse)(rootSchema, function (schema, key) { return rule(schema, filename, options, key, dereferencedPaths); }); }); | ||
return rootSchema; | ||
@@ -133,0 +197,0 @@ } |
@@ -0,2 +1,3 @@ | ||
import { Options } from '.'; | ||
import { AST } from './types/AST'; | ||
export declare function optimize(ast: AST, processed?: Set<AST>): AST; | ||
export declare function optimize(ast: AST, options: Options, processed?: Set<AST>): AST; |
"use strict"; | ||
var __assign = (this && this.__assign) || function () { | ||
__assign = Object.assign || function(t) { | ||
for (var s, i = 1, n = arguments.length; i < n; i++) { | ||
s = arguments[i]; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) | ||
t[p] = s[p]; | ||
} | ||
return t; | ||
}; | ||
return __assign.apply(this, arguments); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.optimize = void 0; | ||
var stringify = require("json-stringify-safe"); | ||
var lodash_1 = require("lodash"); | ||
var generator_1 = require("./generator"); | ||
var AST_1 = require("./types/AST"); | ||
var utils_1 = require("./utils"); | ||
function optimize(ast, processed) { | ||
function optimize(ast, options, processed) { | ||
if (processed === void 0) { processed = new Set(); } | ||
utils_1.log('cyan', 'optimizer', ast, processed.has(ast) ? '(FROM CACHE)' : ''); | ||
if (processed.has(ast)) { | ||
@@ -18,25 +28,38 @@ return ast; | ||
return Object.assign(ast, { | ||
params: ast.params.map(function (_) { return Object.assign(_, { ast: optimize(_.ast, processed) }); }) | ||
params: ast.params.map(function (_) { return Object.assign(_, { ast: optimize(_.ast, options, processed) }); }) | ||
}); | ||
case 'INTERSECTION': | ||
case 'UNION': | ||
// Start with the leaves... | ||
var optimizedAST_1 = Object.assign(ast, { | ||
params: ast.params.map(function (_) { return optimize(_, options, processed); }) | ||
}); | ||
// [A, B, C, Any] -> Any | ||
if (ast.params.some(function (_) { return _.type === 'ANY'; })) { | ||
utils_1.log('cyan', 'optimizer', '[A, B, C, Any] -> Any', ast); | ||
if (optimizedAST_1.params.some(function (_) { return _.type === 'ANY'; })) { | ||
(0, utils_1.log)('cyan', 'optimizer', '[A, B, C, Any] -> Any', optimizedAST_1); | ||
return AST_1.T_ANY; | ||
} | ||
// [A, B, C, Unknown] -> Unknown | ||
if (ast.params.some(function (_) { return _.type === 'UNKNOWN'; })) { | ||
utils_1.log('cyan', 'optimizer', '[A, B, C, Unknown] -> Unknown', ast); | ||
if (optimizedAST_1.params.some(function (_) { return _.type === 'UNKNOWN'; })) { | ||
(0, utils_1.log)('cyan', 'optimizer', '[A, B, C, Unknown] -> Unknown', optimizedAST_1); | ||
return AST_1.T_UNKNOWN; | ||
} | ||
// [A (named), A] -> [A (named)] | ||
if (optimizedAST_1.params.every(function (_) { | ||
var a = (0, generator_1.generateType)(omitStandaloneName(_), options); | ||
var b = (0, generator_1.generateType)(omitStandaloneName(optimizedAST_1.params[0]), options); | ||
return a === b; | ||
}) && | ||
optimizedAST_1.params.some(function (_) { return _.standaloneName !== undefined; })) { | ||
(0, utils_1.log)('cyan', 'optimizer', '[A (named), A] -> [A (named)]', optimizedAST_1); | ||
optimizedAST_1.params = optimizedAST_1.params.filter(function (_) { return _.standaloneName !== undefined; }); | ||
} | ||
// [A, B, B] -> [A, B] | ||
var shouldTakeStandaloneNameIntoAccount_1 = ast.params.filter(function (_) { return _.standaloneName; }).length > 1; | ||
var params = lodash_1.uniqBy(ast.params, function (_) { return "\n " + _.type + "-\n " + (shouldTakeStandaloneNameIntoAccount_1 ? _.standaloneName : '') + "-\n " + stringify(_.params) + "\n "; }); | ||
if (params.length !== ast.params.length) { | ||
utils_1.log('cyan', 'optimizer', '[A, B, B] -> [A, B]', ast); | ||
ast.params = params; | ||
var params = (0, lodash_1.uniqBy)(optimizedAST_1.params, function (_) { return (0, generator_1.generateType)(_, options); }); | ||
if (params.length !== optimizedAST_1.params.length) { | ||
(0, utils_1.log)('cyan', 'optimizer', '[A, B, B] -> [A, B]', optimizedAST_1); | ||
optimizedAST_1.params = params; | ||
} | ||
return Object.assign(ast, { | ||
params: ast.params.map(function (_) { return optimize(_, processed); }) | ||
return Object.assign(optimizedAST_1, { | ||
params: optimizedAST_1.params.map(function (_) { return optimize(_, options, processed); }) | ||
}); | ||
@@ -48,2 +71,11 @@ default: | ||
exports.optimize = optimize; | ||
// TODO: More clearly disambiguate standalone names vs. aliased names instead. | ||
function omitStandaloneName(ast) { | ||
switch (ast.type) { | ||
case 'ENUM': | ||
return ast; | ||
default: | ||
return __assign(__assign({}, ast), { standaloneName: undefined }); | ||
} | ||
} | ||
//# sourceMappingURL=optimizer.js.map |
@@ -24,9 +24,9 @@ "use strict"; | ||
if (usedNames === void 0) { usedNames = new Set(); } | ||
if (JSONSchema_1.isPrimitive(schema)) { | ||
if ((0, JSONSchema_1.isPrimitive)(schema)) { | ||
return parseLiteral(schema, keyName); | ||
} | ||
var types = typesOfSchema_1.typesOfSchema(schema); | ||
var types = (0, typesOfSchema_1.typesOfSchema)(schema); | ||
if (types.length === 1) { | ||
var ast_1 = parseAsTypeWithCache(schema, types[0], options, keyName, processed, usedNames); | ||
utils_1.log('blue', 'parser', 'Types:', types, 'Input:', schema, 'Output:', ast_1); | ||
(0, utils_1.log)('blue', 'parser', 'Types:', types, 'Input:', schema, 'Output:', ast_1); | ||
return ast_1; | ||
@@ -37,5 +37,5 @@ } | ||
var ast = parseAsTypeWithCache({ | ||
$id: schema.$id, | ||
allOf: [], | ||
description: schema.description, | ||
id: schema.id, | ||
title: schema.title | ||
@@ -46,5 +46,5 @@ }, 'ALL_OF', options, keyName, processed, usedNames); | ||
// to the parent intersection type, so we remove it from the children. | ||
return parseAsTypeWithCache(utils_1.maybeStripNameHints(schema), type, options, keyName, processed, usedNames); | ||
return parseAsTypeWithCache((0, utils_1.maybeStripNameHints)(schema), type, options, keyName, processed, usedNames); | ||
}); | ||
utils_1.log('blue', 'parser', 'Types:', types, 'Input:', schema, 'Output:', ast); | ||
(0, utils_1.log)('blue', 'parser', 'Types:', types, 'Input:', schema, 'Output:', ast); | ||
return ast; | ||
@@ -83,4 +83,4 @@ } | ||
function parseNonLiteral(schema, type, options, keyName, processed, usedNames) { | ||
var definitions = getDefinitionsMemoized(JSONSchema_1.getRootSchema(schema)); // TODO | ||
var keyNameFromDefinition = lodash_1.findKey(definitions, function (_) { return _ === schema; }); | ||
var definitions = getDefinitionsMemoized((0, JSONSchema_1.getRootSchema)(schema)); // TODO | ||
var keyNameFromDefinition = (0, lodash_1.findKey)(definitions, function (_) { return _ === schema; }); | ||
switch (type) { | ||
@@ -163,3 +163,3 @@ case 'ALL_OF': | ||
case 'REFERENCE': | ||
throw Error(util_1.format('Refs should have been resolved by the resolver!', schema)); | ||
throw Error((0, util_1.format)('Refs should have been resolved by the resolver!', schema)); | ||
case 'STRING': | ||
@@ -209,4 +209,4 @@ return { | ||
params: schema.type.map(function (type) { | ||
var member = __assign(__assign({}, lodash_1.omit(schema, 'description', 'id', 'title')), { type: type }); | ||
return parse(utils_1.maybeStripDefault(member), options, undefined, processed, usedNames); | ||
var member = __assign(__assign({}, (0, lodash_1.omit)(schema, '$id', 'description', 'title')), { type: type }); | ||
return parse((0, utils_1.maybeStripDefault)(member), options, undefined, processed, usedNames); | ||
}), | ||
@@ -257,5 +257,5 @@ type: 'UNION' | ||
function standaloneName(schema, keyNameFromDefinition, usedNames) { | ||
var name = schema.title || schema.id || keyNameFromDefinition; | ||
var name = schema.title || schema.$id || keyNameFromDefinition; | ||
if (name) { | ||
return utils_1.generateName(name, usedNames); | ||
return (0, utils_1.generateName)(name, usedNames); | ||
} | ||
@@ -287,6 +287,6 @@ } | ||
function parseSchema(schema, options, processed, usedNames, parentSchemaName) { | ||
var asts = lodash_1.map(schema.properties, function (value, key) { return ({ | ||
var asts = (0, lodash_1.map)(schema.properties, function (value, key) { return ({ | ||
ast: parse(value, options, key, processed, usedNames), | ||
isPatternProperty: false, | ||
isRequired: lodash_1.includes(schema.required || [], key), | ||
isRequired: (0, lodash_1.includes)(schema.required || [], key), | ||
isUnreachableDefinition: false, | ||
@@ -301,10 +301,10 @@ keyName: key | ||
singlePatternProperty = !schema.additionalProperties && Object.keys(schema.patternProperties).length === 1; | ||
asts = asts.concat(lodash_1.map(schema.patternProperties, function (value, key) { | ||
asts = asts.concat((0, lodash_1.map)(schema.patternProperties, function (value, key) { | ||
var ast = parse(value, options, key, processed, usedNames); | ||
var comment = "This interface was referenced by `" + parentSchemaName + "`'s JSON-Schema definition\nvia the `patternProperty` \"" + key + "\"."; | ||
ast.comment = ast.comment ? ast.comment + "\n\n" + comment : comment; | ||
var comment = "This interface was referenced by `".concat(parentSchemaName, "`'s JSON-Schema definition\nvia the `patternProperty` \"").concat(key, "\"."); | ||
ast.comment = ast.comment ? "".concat(ast.comment, "\n\n").concat(comment) : comment; | ||
return { | ||
ast: ast, | ||
isPatternProperty: !singlePatternProperty, | ||
isRequired: singlePatternProperty || lodash_1.includes(schema.required || [], key), | ||
isRequired: singlePatternProperty || (0, lodash_1.includes)(schema.required || [], key), | ||
isUnreachableDefinition: false, | ||
@@ -316,10 +316,10 @@ keyName: singlePatternProperty ? '[k: string]' : key | ||
if (options.unreachableDefinitions) { | ||
asts = asts.concat(lodash_1.map(schema.definitions, function (value, key) { | ||
asts = asts.concat((0, lodash_1.map)(schema.definitions, function (value, key) { | ||
var ast = parse(value, options, key, processed, usedNames); | ||
var comment = "This interface was referenced by `" + parentSchemaName + "`'s JSON-Schema\nvia the `definition` \"" + key + "\"."; | ||
ast.comment = ast.comment ? ast.comment + "\n\n" + comment : comment; | ||
var comment = "This interface was referenced by `".concat(parentSchemaName, "`'s JSON-Schema\nvia the `definition` \"").concat(key, "\"."); | ||
ast.comment = ast.comment ? "".concat(ast.comment, "\n\n").concat(comment) : comment; | ||
return { | ||
ast: ast, | ||
isPatternProperty: false, | ||
isRequired: lodash_1.includes(schema.required || [], key), | ||
isRequired: (0, lodash_1.includes)(schema.required || [], key), | ||
isUnreachableDefinition: true, | ||
@@ -368,3 +368,3 @@ keyName: key | ||
} | ||
if (lodash_1.isPlainObject(schema)) { | ||
if ((0, lodash_1.isPlainObject)(schema)) { | ||
return __assign(__assign({}, (isSchema && hasDefinitions(schema) ? schema.definitions : {})), Object.keys(schema).reduce(function (prev, cur) { return (__assign(__assign({}, prev), getDefinitions(schema[cur], false, processed))); }, {})); | ||
@@ -374,3 +374,3 @@ } | ||
} | ||
var getDefinitionsMemoized = lodash_1.memoize(getDefinitions); | ||
var getDefinitionsMemoized = (0, lodash_1.memoize)(getDefinitions); | ||
/** | ||
@@ -377,0 +377,0 @@ * TODO: Reduce rate of false positives |
@@ -1,6 +0,10 @@ | ||
import $RefParser = require('json-schema-ref-parser'); | ||
import $RefParser = require('@apidevtools/json-schema-ref-parser'); | ||
import { JSONSchema } from './types/JSONSchema'; | ||
export declare type DereferencedPaths = WeakMap<$RefParser.JSONSchemaObject, string>; | ||
export declare function dereference(schema: JSONSchema, { cwd, $refOptions }: { | ||
cwd: string; | ||
$refOptions: $RefParser.Options; | ||
}): Promise<JSONSchema>; | ||
}): Promise<{ | ||
dereferencedPaths: DereferencedPaths; | ||
dereferencedSchema: JSONSchema; | ||
}>; |
"use strict"; | ||
var __assign = (this && this.__assign) || function () { | ||
__assign = Object.assign || function(t) { | ||
for (var s, i = 1, n = arguments.length; i < n; i++) { | ||
s = arguments[i]; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) | ||
t[p] = s[p]; | ||
} | ||
return t; | ||
}; | ||
return __assign.apply(this, arguments); | ||
}; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
@@ -40,3 +51,3 @@ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
exports.dereference = void 0; | ||
var $RefParser = require("json-schema-ref-parser"); | ||
var $RefParser = require("@apidevtools/json-schema-ref-parser"); | ||
var utils_1 = require("./utils"); | ||
@@ -46,7 +57,17 @@ function dereference(schema, _a) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var parser; | ||
var parser, dereferencedPaths, dereferencedSchema; | ||
return __generator(this, function (_b) { | ||
utils_1.log('green', 'dereferencer', 'Dereferencing input schema:', cwd, schema); | ||
parser = new $RefParser(); | ||
return [2 /*return*/, parser.dereference(cwd, schema, $refOptions)]; | ||
switch (_b.label) { | ||
case 0: | ||
(0, utils_1.log)('green', 'dereferencer', 'Dereferencing input schema:', cwd, schema); | ||
parser = new $RefParser(); | ||
dereferencedPaths = new WeakMap(); | ||
return [4 /*yield*/, parser.dereference(cwd, schema, __assign(__assign({}, $refOptions), { dereference: __assign(__assign({}, $refOptions.dereference), { onDereference: function ($ref, schema) { | ||
dereferencedPaths.set(schema, $ref); | ||
} }) }))]; | ||
case 1: | ||
dereferencedSchema = _b.sent() // TODO: fix types | ||
; | ||
return [2 /*return*/, { dereferencedPaths: dereferencedPaths, dereferencedSchema: dereferencedSchema }]; | ||
} | ||
}); | ||
@@ -53,0 +74,0 @@ }); |
@@ -65,2 +65,3 @@ /// <reference types="lodash" /> | ||
required: string[]; | ||
id: never; | ||
} | ||
@@ -67,0 +68,0 @@ export interface EnumJSONSchema extends NormalizedJSONSchema { |
@@ -6,3 +6,3 @@ "use strict"; | ||
exports.Parent = Symbol('Parent'); | ||
exports.getRootSchema = lodash_1.memoize(function (schema) { | ||
exports.getRootSchema = (0, lodash_1.memoize)(function (schema) { | ||
var parent = schema[exports.Parent]; | ||
@@ -12,6 +12,6 @@ if (!parent) { | ||
} | ||
return exports.getRootSchema(parent); | ||
return (0, exports.getRootSchema)(parent); | ||
}); | ||
function isPrimitive(schema) { | ||
return !lodash_1.isPlainObject(schema); | ||
return !(0, lodash_1.isPlainObject)(schema); | ||
} | ||
@@ -18,0 +18,0 @@ exports.isPrimitive = isPrimitive; |
@@ -56,3 +56,3 @@ "use strict"; | ||
} | ||
if (!JSONSchema_1.isCompound(schema) && typeof schema.default === 'boolean') { | ||
if (!(0, JSONSchema_1.isCompound)(schema) && typeof schema.default === 'boolean') { | ||
return true; | ||
@@ -69,3 +69,4 @@ } | ||
NAMED_SCHEMA: function (schema) { | ||
return 'id' in schema && ('patternProperties' in schema || 'properties' in schema); | ||
// 8.2.1. The presence of "$id" in a subschema indicates that the subschema constitutes a distinct schema resource within a single schema document. | ||
return '$id' in schema && ('patternProperties' in schema || 'properties' in schema); | ||
}, | ||
@@ -82,3 +83,3 @@ NULL: function (schema) { | ||
} | ||
if (!JSONSchema_1.isCompound(schema) && typeof schema.default === 'number') { | ||
if (!(0, JSONSchema_1.isCompound)(schema) && typeof schema.default === 'number') { | ||
return true; | ||
@@ -90,3 +91,3 @@ } | ||
return (schema.type === 'object' && | ||
!lodash_1.isPlainObject(schema.additionalProperties) && | ||
!(0, lodash_1.isPlainObject)(schema.additionalProperties) && | ||
!schema.allOf && | ||
@@ -112,3 +113,3 @@ !schema.anyOf && | ||
} | ||
if (!JSONSchema_1.isCompound(schema) && typeof schema.default === 'string') { | ||
if (!(0, JSONSchema_1.isCompound)(schema) && typeof schema.default === 'string') { | ||
return true; | ||
@@ -115,0 +116,0 @@ } |
import { JSONSchema, LinkedJSONSchema } from './types/JSONSchema'; | ||
export declare function Try<T>(fn: () => T, err: (e: Error) => any): T; | ||
export declare function mapDeep(object: object, fn: (value: object, key?: string) => object, key?: string): object; | ||
export declare function traverse(schema: LinkedJSONSchema, callback: (schema: LinkedJSONSchema) => void, processed?: Set<LinkedJSONSchema>): void; | ||
export declare function traverse(schema: LinkedJSONSchema, callback: (schema: LinkedJSONSchema, key: string | null) => void, processed?: Set<LinkedJSONSchema>, key?: string): void; | ||
/** | ||
@@ -35,3 +34,3 @@ * Eg. `foo/bar/baz.json` => `baz` | ||
/** | ||
* Removes the schema's `id`, `name`, and `description` properties | ||
* Removes the schema's `$id`, `name`, and `description` properties | ||
* if they exist. | ||
@@ -43,2 +42,4 @@ * Useful when parsing intersections. | ||
export declare function maybeStripNameHints(schema: JSONSchema): JSONSchema; | ||
export declare function appendToDescription(existingDescription: string | undefined, ...values: string[]): string; | ||
export declare function isSchemaLike(schema: LinkedJSONSchema): boolean; | ||
export {}; |
"use strict"; | ||
var __spreadArrays = (this && this.__spreadArrays) || function () { | ||
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; | ||
for (var r = Array(s), k = 0, i = 0; i < il; i++) | ||
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) | ||
r[k] = a[j]; | ||
return r; | ||
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { | ||
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { | ||
if (ar || !(i in from)) { | ||
if (!ar) ar = Array.prototype.slice.call(from, 0, i); | ||
ar[i] = from[i]; | ||
} | ||
} | ||
return to.concat(ar || Array.prototype.slice.call(from)); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.maybeStripNameHints = exports.maybeStripDefault = exports.pathTransform = exports.escapeBlockComment = exports.log = exports.error = exports.generateName = exports.toSafeString = exports.stripExtension = exports.justName = exports.traverse = exports.mapDeep = exports.Try = void 0; | ||
exports.isSchemaLike = exports.appendToDescription = exports.maybeStripNameHints = exports.maybeStripDefault = exports.pathTransform = exports.escapeBlockComment = exports.log = exports.error = exports.generateName = exports.toSafeString = exports.stripExtension = exports.justName = exports.traverse = exports.Try = void 0; | ||
var lodash_1 = require("lodash"); | ||
var path_1 = require("path"); | ||
var JSONSchema_1 = require("./types/JSONSchema"); | ||
// TODO: pull out into a separate package | ||
// eslint-disable-next-line | ||
function Try(fn, err) { | ||
@@ -24,19 +26,2 @@ try { | ||
exports.Try = Try; | ||
function mapDeep(object, fn, key) { | ||
return fn(lodash_1.mapValues(object, function (_, key) { | ||
if (lodash_1.isPlainObject(_)) { | ||
return mapDeep(_, fn, key); | ||
} | ||
else if (Array.isArray(_)) { | ||
return _.map(function (item) { | ||
if (lodash_1.isPlainObject(item)) { | ||
return mapDeep(item, fn, key); | ||
} | ||
return item; | ||
}); | ||
} | ||
return _; | ||
}), key); | ||
} | ||
exports.mapDeep = mapDeep; | ||
// keys that shouldn't be traversed by the catchall step | ||
@@ -81,3 +66,3 @@ var BLACKLISTED_KEYS = new Set([ | ||
if (obj[k] && typeof obj[k] === 'object' && !Array.isArray(obj[k])) { | ||
traverse(obj[k], callback, processed); | ||
traverse(obj[k], callback, processed, k); | ||
} | ||
@@ -87,5 +72,5 @@ }); | ||
function traverseArray(arr, callback, processed) { | ||
arr.forEach(function (i) { return traverse(i, callback, processed); }); | ||
arr.forEach(function (s, k) { return traverse(s, callback, processed, k.toString()); }); | ||
} | ||
function traverse(schema, callback, processed) { | ||
function traverse(schema, callback, processed, key) { | ||
if (processed === void 0) { processed = new Set(); } | ||
@@ -97,3 +82,3 @@ // Handle recursive schemas | ||
processed.add(schema); | ||
callback(schema); | ||
callback(schema, key !== null && key !== void 0 ? key : null); | ||
if (schema.anyOf) { | ||
@@ -159,3 +144,3 @@ traverseArray(schema.anyOf, callback, processed); | ||
if (filename === void 0) { filename = ''; } | ||
return stripExtension(path_1.basename(filename)); | ||
return stripExtension((0, path_1.basename)(filename)); | ||
} | ||
@@ -167,3 +152,3 @@ exports.justName = justName; | ||
function stripExtension(filename) { | ||
return filename.replace(path_1.extname(filename), ''); | ||
return filename.replace((0, path_1.extname)(filename), ''); | ||
} | ||
@@ -179,5 +164,5 @@ exports.stripExtension = stripExtension; | ||
// Rest: a-zA-Z | _ | $ | 0-9 | ||
return lodash_1.upperFirst( | ||
return (0, lodash_1.upperFirst)( | ||
// remove accents, umlauts, ... by their basic latin letters | ||
lodash_1.deburr(string) | ||
(0, lodash_1.deburr)(string) | ||
// replace chars which are not valid for typescript identifiers with whitespace | ||
@@ -192,3 +177,3 @@ .replace(/(^\s*[^a-zA-Z_$])|([^a-zA-Z_$\d])/g, ' ') | ||
// uppercase first letter after whitespace | ||
.replace(/\s+([a-zA-Z])/g, function (match) { return lodash_1.trim(match.toUpperCase()); }) | ||
.replace(/\s+([a-zA-Z])/g, function (match) { return (0, lodash_1.trim)(match.toUpperCase()); }) | ||
// remove remaining whitespace | ||
@@ -206,5 +191,5 @@ .replace(/\s/g, '')); | ||
var counter = 1; | ||
var nameWithCounter = "" + name + counter; | ||
var nameWithCounter = "".concat(name).concat(counter); | ||
while (usedNames.has(nameWithCounter)) { | ||
nameWithCounter = "" + name + counter; | ||
nameWithCounter = "".concat(name).concat(counter); | ||
counter++; | ||
@@ -227,3 +212,3 @@ } | ||
} | ||
console.error.apply(console, __spreadArrays([(_a = getStyledTextForLogging('red')) === null || _a === void 0 ? void 0 : _a('error')], messages)); | ||
console.error.apply(console, __spreadArray([(_a = getStyledTextForLogging('red')) === null || _a === void 0 ? void 0 : _a('error')], messages, false)); | ||
} | ||
@@ -244,3 +229,3 @@ exports.error = error; | ||
} | ||
console.info.apply(console, __spreadArrays([require('cli-color').whiteBright.bgCyan('debug'), (_a = getStyledTextForLogging(style)) === null || _a === void 0 ? void 0 : _a(title)], messages)); | ||
console.info.apply(console, __spreadArray([require('cli-color').whiteBright.bgCyan('debug'), (_a = getStyledTextForLogging(style)) === null || _a === void 0 ? void 0 : _a(title)], messages, false)); | ||
if (lastMessage) { | ||
@@ -300,6 +285,6 @@ console.dir(lastMessage, { depth: 6, maxArrayLength: 6 }); | ||
function pathTransform(outputPath, inputPath, filePath) { | ||
var inPathList = path_1.normalize(inputPath).split(path_1.sep); | ||
var filePathList = path_1.dirname(path_1.normalize(filePath)).split(path_1.sep); | ||
var inPathList = (0, path_1.normalize)(inputPath).split(path_1.sep); | ||
var filePathList = (0, path_1.dirname)((0, path_1.normalize)(filePath)).split(path_1.sep); | ||
var filePathRel = filePathList.filter(function (f, i) { return f !== inPathList[i]; }); | ||
return path_1.join.apply(void 0, __spreadArrays([path_1.normalize(outputPath)], filePathRel)); | ||
return path_1.posix.join.apply(path_1.posix, __spreadArray([path_1.posix.normalize(outputPath)], filePathRel, false)); | ||
} | ||
@@ -345,3 +330,3 @@ exports.pathTransform = pathTransform; | ||
case 'object': | ||
if (lodash_1.isPlainObject(schema.default)) { | ||
if ((0, lodash_1.isPlainObject)(schema.default)) { | ||
return schema; | ||
@@ -356,3 +341,3 @@ } | ||
/** | ||
* Removes the schema's `id`, `name`, and `description` properties | ||
* Removes the schema's `$id`, `name`, and `description` properties | ||
* if they exist. | ||
@@ -364,8 +349,8 @@ * Useful when parsing intersections. | ||
function maybeStripNameHints(schema) { | ||
if ('$id' in schema) { | ||
delete schema.$id; | ||
} | ||
if ('description' in schema) { | ||
delete schema.description; | ||
} | ||
if ('id' in schema) { | ||
delete schema.id; | ||
} | ||
if ('name' in schema) { | ||
@@ -377,2 +362,39 @@ delete schema.name; | ||
exports.maybeStripNameHints = maybeStripNameHints; | ||
function appendToDescription(existingDescription) { | ||
var values = []; | ||
for (var _i = 1; _i < arguments.length; _i++) { | ||
values[_i - 1] = arguments[_i]; | ||
} | ||
if (existingDescription) { | ||
return "".concat(existingDescription, "\n\n").concat(values.join('\n')); | ||
} | ||
return values.join('\n'); | ||
} | ||
exports.appendToDescription = appendToDescription; | ||
function isSchemaLike(schema) { | ||
if (!(0, lodash_1.isPlainObject)(schema)) { | ||
return false; | ||
} | ||
var parent = schema[JSONSchema_1.Parent]; | ||
if (parent === null) { | ||
return true; | ||
} | ||
var JSON_SCHEMA_KEYWORDS = [ | ||
'allOf', | ||
'anyOf', | ||
'dependencies', | ||
'enum', | ||
'oneOf', | ||
'definitions', | ||
'not', | ||
'patternProperties', | ||
'properties', | ||
'required' | ||
]; | ||
if (JSON_SCHEMA_KEYWORDS.some(function (_) { return parent[_] === schema; })) { | ||
return false; | ||
} | ||
return true; | ||
} | ||
exports.isSchemaLike = isSchemaLike; | ||
//# sourceMappingURL=utils.js.map |
@@ -1,2 +0,2 @@ | ||
import { JSONSchema } from './types/JSONSchema'; | ||
export declare function validate(schema: JSONSchema, filename: string): string[]; | ||
import { LinkedJSONSchema } from './types/JSONSchema'; | ||
export declare function validate(schema: LinkedJSONSchema, filename: string): string[]; |
@@ -37,5 +37,5 @@ "use strict"; | ||
rules.forEach(function (rule, ruleName) { | ||
utils_1.mapDeep(schema, function (schema, key) { | ||
(0, utils_1.traverse)(schema, function (schema, key) { | ||
if (rule(schema) === false) { | ||
errors.push("Error at key \"" + key + "\" in file \"" + filename + "\": " + ruleName); | ||
errors.push("Error at key \"".concat(key, "\" in file \"").concat(filename, "\": ").concat(ruleName)); | ||
} | ||
@@ -42,0 +42,0 @@ return schema; |
{ | ||
"name": "json-schema-to-typescript", | ||
"version": "10.1.5", | ||
"version": "11.0.0", | ||
"description": "compile json schema to typescript typings", | ||
@@ -11,3 +11,3 @@ "main": "dist/src/index.js", | ||
"engines": { | ||
"node": ">=10.0.0" | ||
"node": ">=12.0.0" | ||
}, | ||
@@ -50,40 +50,39 @@ "scripts": { | ||
"dependencies": { | ||
"@types/json-schema": "^7.0.6", | ||
"@types/lodash": "^4.14.168", | ||
"@types/prettier": "^2.1.5", | ||
"cli-color": "^2.0.0", | ||
"@apidevtools/json-schema-ref-parser": "https://github.com/bcherny/json-schema-ref-parser.git#984282d3", | ||
"@types/json-schema": "^7.0.11", | ||
"@types/lodash": "^4.14.182", | ||
"@types/prettier": "^2.6.1", | ||
"cli-color": "^2.0.2", | ||
"get-stdin": "^8.0.0", | ||
"glob": "^7.1.6", | ||
"glob-promise": "^3.4.0", | ||
"is-glob": "^4.0.1", | ||
"json-schema-ref-parser": "^9.0.6", | ||
"json-stringify-safe": "^5.0.1", | ||
"lodash": "^4.17.20", | ||
"minimist": "^1.2.5", | ||
"glob-promise": "^4.2.2", | ||
"is-glob": "^4.0.3", | ||
"lodash": "^4.17.21", | ||
"minimist": "^1.2.6", | ||
"mkdirp": "^1.0.4", | ||
"mz": "^2.7.0", | ||
"prettier": "^2.2.0" | ||
"prettier": "^2.6.2" | ||
}, | ||
"devDependencies": { | ||
"@types/cli-color": "^2.0.0", | ||
"@types/glob": "^7.1.3", | ||
"@types/is-glob": "^4.0.1", | ||
"@types/minimist": "^1.2.1", | ||
"@types/mkdirp": "^1.0.1", | ||
"@types/mz": "^2.7.2", | ||
"@types/node": "^14.14.10", | ||
"@types/rimraf": "^3.0.0", | ||
"@typescript-eslint/eslint-plugin": "^4.8.2", | ||
"@typescript-eslint/parser": "^4.8.2", | ||
"ava": "^3.13.0", | ||
"@types/cli-color": "^2.0.2", | ||
"@types/glob": "^7.2.0", | ||
"@types/is-glob": "^4.0.2", | ||
"@types/minimist": "^1.2.2", | ||
"@types/mkdirp": "^1.0.2", | ||
"@types/mz": "^2.7.4", | ||
"@types/node": "^17.0.33", | ||
"@types/rimraf": "^3.0.2", | ||
"@typescript-eslint/eslint-plugin": "^5.23.0", | ||
"@typescript-eslint/parser": "^5.23.0", | ||
"ava": "^4.2.0", | ||
"browserify": "^17.0.0", | ||
"browserify-shim": "^3.8.14", | ||
"concurrently": "^5.3.0", | ||
"eslint": "^7.14.0", | ||
"eslint-config-prettier": "^6.15.0", | ||
"eslint-plugin-prettier": "^3.1.4", | ||
"concurrently": "^7.2.0", | ||
"eslint": "^8.15.0", | ||
"eslint-config-prettier": "^8.5.0", | ||
"eslint-plugin-prettier": "^4.0.0", | ||
"rimraf": "^3.0.2", | ||
"shx": "^0.3.3", | ||
"tsify": "^5.0.2", | ||
"typescript": "^4.1.2" | ||
"shx": "^0.3.4", | ||
"tsify": "^5.0.4", | ||
"typescript": "^4.6.4" | ||
}, | ||
@@ -97,4 +96,3 @@ "ava": { | ||
], | ||
"snapshotDir": "./test/__snapshots__", | ||
"vebose": true | ||
"snapshotDir": "./test/__snapshots__" | ||
}, | ||
@@ -101,0 +99,0 @@ "browserify": { |
@@ -86,2 +86,3 @@ # json-schema-to-typescript [![Build Status][build]](https://github.com/bcherny/json-schema-to-typescript/actions?query=branch%3Amaster+workflow%3ACI) [![npm]](https://www.npmjs.com/package/json-schema-to-typescript) [![mit]](https://opensource.org/licenses/MIT) | ||
|-|-|-|-| | ||
| additionalProperties | boolean | `true` | Default value for `additionalProperties`, when it is not explicitly set | | ||
| bannerComment | string | `"/* tslint:disable */\n/**\n* This file was automatically generated by json-schema-to-typescript.\n* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,\n* and run json-schema-to-typescript to regenerate this file.\n*/"` | Disclaimer comment prepended to the top of each generated file | | ||
@@ -93,2 +94,3 @@ | cwd | string | `process.cwd()` | Root directory for resolving [`$ref`](https://tools.ietf.org/id/draft-pbryan-zyp-json-ref-03.html)s | | ||
| ignoreMinAndMaxItems | boolean | `false` | Ignore maxItems and minItems for `array` types, preventing tuples being generated. | | ||
| maxItems | number | `20` | Maximum number of unioned tuples to emit when representing bounded-size array types, before falling back to emitting unbounded arrays. Increase this to improve precision of emitted types, decrease it to improve performance, or set it to `-1` to ignore `maxItems`. | ||
| style | object | `{ bracketSpacing: false, printWidth: 120, semi: true, singleQuote: false, tabWidth: 2, trailingComma: 'none', useTabs: false }` | A [Prettier](https://prettier.io/docs/en/options.html) configuration | | ||
@@ -95,0 +97,0 @@ | unknownAny | boolean | `true` | Use `unknown` instead of `any` where possible | |
@@ -154,2 +154,4 @@ #!/usr/bin/env node | ||
--additionalProperties | ||
Default value for additionalProperties, when it is not explicitly set | ||
--cwd=XXX | ||
@@ -163,2 +165,7 @@ Root directory for resolving $ref | ||
Format code? Set this to false to improve performance. | ||
--maxItems | ||
Maximum number of unioned tuples to emit when representing bounded-size | ||
array types, before falling back to emitting unbounded arrays. Increase | ||
this to improve precision of emitted types, decrease it to improve | ||
performance, or set it to -1 to ignore minItems and maxItems. | ||
--style.XXX=YYY | ||
@@ -165,0 +172,0 @@ Prettier configuration |
@@ -1,2 +0,2 @@ | ||
import {omit} from 'lodash' | ||
import {memoize, omit} from 'lodash' | ||
import {DEFAULT_OPTIONS, Options} from './index' | ||
@@ -110,7 +110,6 @@ import { | ||
processed.add(ast) | ||
let type = '' | ||
switch (ast.type) { | ||
case 'ARRAY': | ||
type = [ | ||
return [ | ||
declareNamedTypes(ast.params, options, rootASTName, processed), | ||
@@ -121,8 +120,6 @@ hasStandaloneName(ast) ? generateStandaloneType(ast, options) : undefined | ||
.join('\n') | ||
break | ||
case 'ENUM': | ||
type = '' | ||
break | ||
return '' | ||
case 'INTERFACE': | ||
type = getSuperTypesAndParams(ast) | ||
return getSuperTypesAndParams(ast) | ||
.map( | ||
@@ -135,7 +132,6 @@ ast => | ||
.join('\n') | ||
break | ||
case 'INTERSECTION': | ||
case 'TUPLE': | ||
case 'UNION': | ||
type = [ | ||
return [ | ||
hasStandaloneName(ast) ? generateStandaloneType(ast, options) : undefined, | ||
@@ -152,13 +148,11 @@ ast.params | ||
.join('\n') | ||
break | ||
default: | ||
if (hasStandaloneName(ast)) { | ||
type = generateStandaloneType(ast, options) | ||
return generateStandaloneType(ast, options) | ||
} | ||
return '' | ||
} | ||
return type | ||
} | ||
function generateType(ast: AST, options: Options): string { | ||
function generateTypeUnmemoized(ast: AST, options: Options): string { | ||
const type = generateRawType(ast, options) | ||
@@ -172,2 +166,3 @@ | ||
} | ||
export const generateType = memoize(generateTypeUnmemoized) | ||
@@ -174,0 +169,0 @@ function generateRawType(ast: AST, options: Options): string { |
import {readFileSync} from 'fs' | ||
import {JSONSchema4} from 'json-schema' | ||
import {Options as $RefOptions} from 'json-schema-ref-parser' | ||
import {endsWith, merge} from 'lodash' | ||
import {Options as $RefOptions} from '@apidevtools/json-schema-ref-parser' | ||
import {cloneDeep, endsWith, merge} from 'lodash' | ||
import {dirname} from 'path' | ||
@@ -17,2 +17,3 @@ import {Options as PrettierOptions} from 'prettier' | ||
import {link} from './linker' | ||
import {validateOptions} from './optionValidator' | ||
@@ -23,2 +24,10 @@ export {EnumJSONSchema, JSONSchema, NamedEnumJSONSchema, CustomTypeJSONSchema} from './types/JSONSchema' | ||
/** | ||
* [$RefParser](https://github.com/BigstickCarpet/json-schema-ref-parser) Options, used when resolving `$ref`s | ||
*/ | ||
$refOptions: $RefOptions | ||
/** | ||
* Default value for additionalProperties, when it is not explicitly set. | ||
*/ | ||
additionalProperties: boolean | ||
/** | ||
* Disclaimer comment prepended to the top of each generated file. | ||
@@ -48,2 +57,9 @@ */ | ||
/** | ||
* Maximum number of unioned tuples to emit when representing bounded-size array types, | ||
* before falling back to emitting unbounded arrays. Increase this to improve precision | ||
* of emitted types, decrease it to improve performance, or set it to `-1` to ignore | ||
* `minItems` and `maxItems`. | ||
*/ | ||
maxItems: number | ||
/** | ||
* Append all index signatures with `| undefined` so that they are strictly typed. | ||
@@ -66,6 +82,2 @@ * | ||
unknownAny: boolean | ||
/** | ||
* [$RefParser](https://github.com/BigstickCarpet/json-schema-ref-parser) Options, used when resolving `$ref`s | ||
*/ | ||
$refOptions: $RefOptions | ||
} | ||
@@ -75,2 +87,3 @@ | ||
$refOptions: {}, | ||
additionalProperties: true, // TODO: default to empty schema (as per spec) instead | ||
bannerComment: `/* tslint:disable */ | ||
@@ -87,2 +100,3 @@ /** | ||
ignoreMinAndMaxItems: false, | ||
maxItems: 20, | ||
strictIndexSignatures: false, | ||
@@ -119,2 +133,4 @@ style: { | ||
export async function compile(schema: JSONSchema4, name: string, options: Partial<Options> = {}): Promise<string> { | ||
validateOptions(options) | ||
const _options = merge({}, DEFAULT_OPTIONS, options) | ||
@@ -127,11 +143,2 @@ | ||
const errors = validate(schema, name) | ||
if (errors.length) { | ||
errors.forEach(_ => error(_)) | ||
throw new ValidationError() | ||
} | ||
if (process.env.VERBOSE) { | ||
log('green', 'validator', time(), '✅ No change') | ||
} | ||
// normalize options | ||
@@ -142,12 +149,15 @@ if (!endsWith(_options.cwd, '/')) { | ||
const dereferenced = await dereference(schema, _options) | ||
// Initial clone to avoid mutating the input | ||
const _schema = cloneDeep(schema) | ||
const {dereferencedPaths, dereferencedSchema} = await dereference(_schema, _options) | ||
if (process.env.VERBOSE) { | ||
if (isDeepStrictEqual(schema, dereferenced)) { | ||
if (isDeepStrictEqual(_schema, dereferencedSchema)) { | ||
log('green', 'dereferencer', time(), '✅ No change') | ||
} else { | ||
log('green', 'dereferencer', time(), '✅ Result:', dereferenced) | ||
log('green', 'dereferencer', time(), '✅ Result:', dereferencedSchema) | ||
} | ||
} | ||
const linked = link(dereferenced) | ||
const linked = link(dereferencedSchema) | ||
if (process.env.VERBOSE) { | ||
@@ -157,22 +167,19 @@ log('green', 'linker', time(), '✅ No change') | ||
const normalized = normalize(linked, name, _options) | ||
const errors = validate(linked, name) | ||
if (errors.length) { | ||
errors.forEach(_ => error(_)) | ||
throw new ValidationError() | ||
} | ||
if (process.env.VERBOSE) { | ||
if (isDeepStrictEqual(linked, normalized)) { | ||
log('yellow', 'normalizer', time(), '✅ No change') | ||
} else { | ||
log('yellow', 'normalizer', time(), '✅ Result:', normalized) | ||
} | ||
log('green', 'validator', time(), '✅ No change') | ||
} | ||
const normalized = normalize(linked, dereferencedPaths, name, _options) | ||
log('yellow', 'normalizer', time(), '✅ Result:', normalized) | ||
const parsed = parse(normalized, _options) | ||
log('blue', 'parser', time(), '✅ Result:', parsed) | ||
const optimized = optimize(parsed) | ||
if (process.env.VERBOSE) { | ||
if (isDeepStrictEqual(parsed, optimized)) { | ||
log('cyan', 'optimizer', time(), '✅ No change') | ||
} else { | ||
log('cyan', 'optimizer', time(), '✅ Result:', optimized) | ||
} | ||
} | ||
const optimized = optimize(parsed, _options) | ||
log('cyan', 'optimizer', time(), '✅ Result:', optimized) | ||
@@ -179,0 +186,0 @@ const generated = generate(optimized, _options) |
import {JSONSchemaTypeName, LinkedJSONSchema, NormalizedJSONSchema, Parent} from './types/JSONSchema' | ||
import {escapeBlockComment, justName, toSafeString, traverse} from './utils' | ||
import {appendToDescription, escapeBlockComment, isSchemaLike, justName, toSafeString, traverse} from './utils' | ||
import {Options} from './' | ||
import {DereferencedPaths} from './resolver' | ||
type Rule = (schema: LinkedJSONSchema, fileName: string, options: Options) => void | ||
type Rule = ( | ||
schema: LinkedJSONSchema, | ||
fileName: string, | ||
options: Options, | ||
key: string | null, | ||
dereferencedPaths: DereferencedPaths | ||
) => void | ||
const rules = new Map<string, Rule>() | ||
@@ -47,29 +54,78 @@ | ||
// TODO: default to empty schema (as per spec) instead | ||
rules.set('Default additionalProperties to true', schema => { | ||
rules.set('Default additionalProperties', (schema, _, options) => { | ||
if (isObjectType(schema) && !('additionalProperties' in schema) && schema.patternProperties === undefined) { | ||
schema.additionalProperties = true | ||
schema.additionalProperties = options.additionalProperties | ||
} | ||
}) | ||
rules.set('Default top level `id`', (schema, fileName) => { | ||
const isRoot = schema[Parent] === null | ||
if (isRoot && !schema.id) { | ||
schema.id = toSafeString(justName(fileName)) | ||
rules.set('Transform id to $id', (schema, fileName) => { | ||
if (!isSchemaLike(schema)) { | ||
return | ||
} | ||
if (schema.id && schema.$id && schema.id !== schema.$id) { | ||
throw ReferenceError( | ||
`Schema must define either id or $id, not both. Given id=${schema.id}, $id=${schema.$id} in ${fileName}` | ||
) | ||
} | ||
if (schema.id) { | ||
schema.$id = schema.id | ||
delete schema.id | ||
} | ||
}) | ||
rules.set('Escape closing JSDoc Comment', schema => { | ||
rules.set('Add an $id to anything that needs it', (schema, fileName, _options, _key, dereferencedPaths) => { | ||
if (!isSchemaLike(schema)) { | ||
return | ||
} | ||
// Top-level schema | ||
if (!schema.$id && !schema[Parent]) { | ||
schema.$id = toSafeString(justName(fileName)) | ||
return | ||
} | ||
// Sub-schemas with references | ||
if (!isArrayType(schema) && !isObjectType(schema)) { | ||
return | ||
} | ||
// We'll infer from $id and title downstream | ||
// TODO: Normalize upstream | ||
const dereferencedName = dereferencedPaths.get(schema) | ||
if (!schema.$id && !schema.title && dereferencedName) { | ||
schema.$id = toSafeString(justName(dereferencedName)) | ||
} | ||
if (dereferencedName) { | ||
dereferencedPaths.delete(schema) | ||
} | ||
}) | ||
rules.set('Escape closing JSDoc comment', schema => { | ||
escapeBlockComment(schema) | ||
}) | ||
rules.set('Add JSDoc comments for minItems and maxItems', schema => { | ||
if (!isArrayType(schema)) { | ||
return | ||
} | ||
const commentsToAppend = [ | ||
'minItems' in schema ? `@minItems ${schema.minItems}` : '', | ||
'maxItems' in schema ? `@maxItems ${schema.maxItems}` : '' | ||
].filter(Boolean) | ||
if (commentsToAppend.length) { | ||
schema.description = appendToDescription(schema.description, ...commentsToAppend) | ||
} | ||
}) | ||
rules.set('Optionally remove maxItems and minItems', (schema, _fileName, options) => { | ||
if (options.ignoreMinAndMaxItems) { | ||
if ('maxItems' in schema) { | ||
delete schema.maxItems | ||
} | ||
if ('minItems' in schema) { | ||
delete schema.minItems | ||
} | ||
if (!isArrayType(schema)) { | ||
return | ||
} | ||
if ('minItems' in schema && options.ignoreMinAndMaxItems) { | ||
delete schema.minItems | ||
} | ||
if ('maxItems' in schema && (options.ignoreMinAndMaxItems || options.maxItems === -1)) { | ||
delete schema.maxItems | ||
} | ||
}) | ||
@@ -82,9 +138,24 @@ | ||
// make sure we only add the props onto array types | ||
if (isArrayType(schema)) { | ||
const {minItems} = schema | ||
schema.minItems = typeof minItems === 'number' ? minItems : 0 | ||
if (!isArrayType(schema)) { | ||
return | ||
} | ||
const {minItems} = schema | ||
schema.minItems = typeof minItems === 'number' ? minItems : 0 | ||
// cannot normalize maxItems because maxItems = 0 has an actual meaning | ||
}) | ||
rules.set('Remove maxItems if it is big enough to likely cause OOMs', (schema, _fileName, options) => { | ||
if (options.ignoreMinAndMaxItems || options.maxItems === -1) { | ||
return | ||
} | ||
if (!isArrayType(schema)) { | ||
return | ||
} | ||
const {maxItems, minItems} = schema | ||
// minItems is guaranteed to be a number after the previous rule runs | ||
if (maxItems !== undefined && maxItems - (minItems as number) > options.maxItems) { | ||
delete schema.maxItems | ||
} | ||
}) | ||
rules.set('Normalize schema.items', (schema, _fileName, options) => { | ||
@@ -150,5 +221,10 @@ if (options.ignoreMinAndMaxItems) { | ||
export function normalize(rootSchema: LinkedJSONSchema, filename: string, options: Options): NormalizedJSONSchema { | ||
rules.forEach(rule => traverse(rootSchema, schema => rule(schema, filename, options))) | ||
export function normalize( | ||
rootSchema: LinkedJSONSchema, | ||
dereferencedPaths: DereferencedPaths, | ||
filename: string, | ||
options: Options | ||
): NormalizedJSONSchema { | ||
rules.forEach(rule => traverse(rootSchema, (schema, key) => rule(schema, filename, options, key, dereferencedPaths))) | ||
return rootSchema as NormalizedJSONSchema | ||
} |
@@ -1,9 +0,8 @@ | ||
import stringify = require('json-stringify-safe') | ||
import {uniqBy} from 'lodash' | ||
import {Options} from '.' | ||
import {generateType} from './generator' | ||
import {AST, T_ANY, T_UNKNOWN} from './types/AST' | ||
import {log} from './utils' | ||
export function optimize(ast: AST, processed = new Set<AST>()): AST { | ||
log('cyan', 'optimizer', ast, processed.has(ast) ? '(FROM CACHE)' : '') | ||
export function optimize(ast: AST, options: Options, processed = new Set<AST>()): AST { | ||
if (processed.has(ast)) { | ||
@@ -18,9 +17,14 @@ return ast | ||
return Object.assign(ast, { | ||
params: ast.params.map(_ => Object.assign(_, {ast: optimize(_.ast, processed)})) | ||
params: ast.params.map(_ => Object.assign(_, {ast: optimize(_.ast, options, processed)})) | ||
}) | ||
case 'INTERSECTION': | ||
case 'UNION': | ||
// Start with the leaves... | ||
const optimizedAST = Object.assign(ast, { | ||
params: ast.params.map(_ => optimize(_, options, processed)) | ||
}) | ||
// [A, B, C, Any] -> Any | ||
if (ast.params.some(_ => _.type === 'ANY')) { | ||
log('cyan', 'optimizer', '[A, B, C, Any] -> Any', ast) | ||
if (optimizedAST.params.some(_ => _.type === 'ANY')) { | ||
log('cyan', 'optimizer', '[A, B, C, Any] -> Any', optimizedAST) | ||
return T_ANY | ||
@@ -30,24 +34,29 @@ } | ||
// [A, B, C, Unknown] -> Unknown | ||
if (ast.params.some(_ => _.type === 'UNKNOWN')) { | ||
log('cyan', 'optimizer', '[A, B, C, Unknown] -> Unknown', ast) | ||
if (optimizedAST.params.some(_ => _.type === 'UNKNOWN')) { | ||
log('cyan', 'optimizer', '[A, B, C, Unknown] -> Unknown', optimizedAST) | ||
return T_UNKNOWN | ||
} | ||
// [A (named), A] -> [A (named)] | ||
if ( | ||
optimizedAST.params.every(_ => { | ||
const a = generateType(omitStandaloneName(_), options) | ||
const b = generateType(omitStandaloneName(optimizedAST.params[0]), options) | ||
return a === b | ||
}) && | ||
optimizedAST.params.some(_ => _.standaloneName !== undefined) | ||
) { | ||
log('cyan', 'optimizer', '[A (named), A] -> [A (named)]', optimizedAST) | ||
optimizedAST.params = optimizedAST.params.filter(_ => _.standaloneName !== undefined) | ||
} | ||
// [A, B, B] -> [A, B] | ||
const shouldTakeStandaloneNameIntoAccount = ast.params.filter(_ => _.standaloneName).length > 1 | ||
const params = uniqBy( | ||
ast.params, | ||
_ => ` | ||
${_.type}- | ||
${shouldTakeStandaloneNameIntoAccount ? _.standaloneName : ''}- | ||
${stringify((_ as any).params)} | ||
` | ||
) | ||
if (params.length !== ast.params.length) { | ||
log('cyan', 'optimizer', '[A, B, B] -> [A, B]', ast) | ||
ast.params = params | ||
const params = uniqBy(optimizedAST.params, _ => generateType(_, options)) | ||
if (params.length !== optimizedAST.params.length) { | ||
log('cyan', 'optimizer', '[A, B, B] -> [A, B]', optimizedAST) | ||
optimizedAST.params = params | ||
} | ||
return Object.assign(ast, { | ||
params: ast.params.map(_ => optimize(_, processed)) | ||
return Object.assign(optimizedAST, { | ||
params: optimizedAST.params.map(_ => optimize(_, options, processed)) | ||
}) | ||
@@ -58,1 +67,11 @@ default: | ||
} | ||
// TODO: More clearly disambiguate standalone names vs. aliased names instead. | ||
function omitStandaloneName<A extends AST>(ast: A): A { | ||
switch (ast.type) { | ||
case 'ENUM': | ||
return ast | ||
default: | ||
return {...ast, standaloneName: undefined} | ||
} | ||
} |
@@ -54,5 +54,5 @@ import {JSONSchema4Type, JSONSchema4TypeName} from 'json-schema' | ||
{ | ||
$id: schema.$id, | ||
allOf: [], | ||
description: schema.description, | ||
id: schema.id, | ||
title: schema.title | ||
@@ -251,3 +251,3 @@ }, | ||
params: (schema.type as JSONSchema4TypeName[]).map(type => { | ||
const member: LinkedJSONSchema = {...omit(schema, 'description', 'id', 'title'), type} | ||
const member: LinkedJSONSchema = {...omit(schema, '$id', 'description', 'title'), type} | ||
return parse(maybeStripDefault(member as any), options, undefined, processed, usedNames) | ||
@@ -305,3 +305,3 @@ }), | ||
): string | undefined { | ||
const name = schema.title || schema.id || keyNameFromDefinition | ||
const name = schema.title || schema.$id || keyNameFromDefinition | ||
if (name) { | ||
@@ -308,0 +308,0 @@ return generateName(name, usedNames) |
@@ -1,12 +0,24 @@ | ||
import $RefParser = require('json-schema-ref-parser') | ||
import $RefParser = require('@apidevtools/json-schema-ref-parser') | ||
import {JSONSchema} from './types/JSONSchema' | ||
import {log} from './utils' | ||
export type DereferencedPaths = WeakMap<$RefParser.JSONSchemaObject, string> | ||
export async function dereference( | ||
schema: JSONSchema, | ||
{cwd, $refOptions}: {cwd: string; $refOptions: $RefParser.Options} | ||
): Promise<JSONSchema> { | ||
): Promise<{dereferencedPaths: DereferencedPaths; dereferencedSchema: JSONSchema}> { | ||
log('green', 'dereferencer', 'Dereferencing input schema:', cwd, schema) | ||
const parser = new $RefParser() | ||
return parser.dereference(cwd, schema, $refOptions) | ||
const dereferencedPaths: DereferencedPaths = new WeakMap() | ||
const dereferencedSchema = await parser.dereference(cwd, schema as any, { | ||
...$refOptions, | ||
dereference: { | ||
...$refOptions.dereference, | ||
onDereference($ref, schema) { | ||
dereferencedPaths.set(schema, $ref) | ||
} | ||
} | ||
}) as any // TODO: fix types | ||
return {dereferencedPaths, dereferencedSchema} | ||
} |
@@ -90,2 +90,5 @@ import {JSONSchema4, JSONSchema4Type, JSONSchema4TypeName} from 'json-schema' | ||
required: string[] | ||
// Removed by normalizer | ||
id: never | ||
} | ||
@@ -118,11 +121,9 @@ | ||
export const getRootSchema = memoize( | ||
(schema: LinkedJSONSchema): LinkedJSONSchema => { | ||
const parent = schema[Parent] | ||
if (!parent) { | ||
return schema | ||
} | ||
return getRootSchema(parent) | ||
export const getRootSchema = memoize((schema: LinkedJSONSchema): LinkedJSONSchema => { | ||
const parent = schema[Parent] | ||
if (!parent) { | ||
return schema | ||
} | ||
) | ||
return getRootSchema(parent) | ||
}) | ||
@@ -129,0 +130,0 @@ export function isPrimitive(schema: LinkedJSONSchema | JSONSchemaType): schema is JSONSchemaType { |
@@ -68,3 +68,4 @@ import {isPlainObject} from 'lodash' | ||
NAMED_SCHEMA(schema) { | ||
return 'id' in schema && ('patternProperties' in schema || 'properties' in schema) | ||
// 8.2.1. The presence of "$id" in a subschema indicates that the subschema constitutes a distinct schema resource within a single schema document. | ||
return '$id' in schema && ('patternProperties' in schema || 'properties' in schema) | ||
}, | ||
@@ -71,0 +72,0 @@ NULL(schema) { |
@@ -1,7 +0,6 @@ | ||
import {deburr, isPlainObject, mapValues, trim, upperFirst} from 'lodash' | ||
import {basename, dirname, extname, join, normalize, sep} from 'path' | ||
import {JSONSchema, LinkedJSONSchema} from './types/JSONSchema' | ||
import {deburr, isPlainObject, trim, upperFirst} from 'lodash' | ||
import {basename, dirname, extname, normalize, sep, posix} from 'path' | ||
import {JSONSchema, LinkedJSONSchema, Parent} from './types/JSONSchema' | ||
// TODO: pull out into a separate package | ||
// eslint-disable-next-line | ||
export function Try<T>(fn: () => T, err: (e: Error) => any): T { | ||
@@ -15,21 +14,2 @@ try { | ||
export function mapDeep(object: object, fn: (value: object, key?: string) => object, key?: string): object { | ||
return fn( | ||
mapValues(object, (_: unknown, key) => { | ||
if (isPlainObject(_)) { | ||
return mapDeep(_ as object, fn, key) | ||
} else if (Array.isArray(_)) { | ||
return _.map(item => { | ||
if (isPlainObject(item)) { | ||
return mapDeep(item as object, fn, key) | ||
} | ||
return item | ||
}) | ||
} | ||
return _ | ||
}), | ||
key | ||
) | ||
} | ||
// keys that shouldn't be traversed by the catchall step | ||
@@ -74,3 +54,3 @@ const BLACKLISTED_KEYS = new Set([ | ||
obj: Record<string, LinkedJSONSchema>, | ||
callback: (schema: LinkedJSONSchema) => void, | ||
callback: (schema: LinkedJSONSchema, key: string | null) => void, | ||
processed: Set<LinkedJSONSchema> | ||
@@ -80,17 +60,20 @@ ) { | ||
if (obj[k] && typeof obj[k] === 'object' && !Array.isArray(obj[k])) { | ||
traverse(obj[k], callback, processed) | ||
traverse(obj[k], callback, processed, k) | ||
} | ||
}) | ||
} | ||
function traverseArray( | ||
arr: LinkedJSONSchema[], | ||
callback: (schema: LinkedJSONSchema) => void, | ||
callback: (schema: LinkedJSONSchema, key: string | null) => void, | ||
processed: Set<LinkedJSONSchema> | ||
) { | ||
arr.forEach(i => traverse(i, callback, processed)) | ||
arr.forEach((s, k) => traverse(s, callback, processed, k.toString())) | ||
} | ||
export function traverse( | ||
schema: LinkedJSONSchema, | ||
callback: (schema: LinkedJSONSchema) => void, | ||
processed = new Set<LinkedJSONSchema>() | ||
callback: (schema: LinkedJSONSchema, key: string | null) => void, | ||
processed = new Set<LinkedJSONSchema>(), | ||
key?: string | ||
): void { | ||
@@ -103,3 +86,3 @@ // Handle recursive schemas | ||
processed.add(schema) | ||
callback(schema) | ||
callback(schema, key ?? null) | ||
@@ -298,3 +281,3 @@ if (schema.anyOf) { | ||
return join(normalize(outputPath), ...filePathRel) | ||
return posix.join(posix.normalize(outputPath), ...filePathRel) | ||
} | ||
@@ -351,3 +334,3 @@ | ||
/** | ||
* Removes the schema's `id`, `name`, and `description` properties | ||
* Removes the schema's `$id`, `name`, and `description` properties | ||
* if they exist. | ||
@@ -359,8 +342,8 @@ * Useful when parsing intersections. | ||
export function maybeStripNameHints(schema: JSONSchema): JSONSchema { | ||
if ('$id' in schema) { | ||
delete schema.$id | ||
} | ||
if ('description' in schema) { | ||
delete schema.description | ||
} | ||
if ('id' in schema) { | ||
delete schema.id | ||
} | ||
if ('name' in schema) { | ||
@@ -371,1 +354,36 @@ delete schema.name | ||
} | ||
export function appendToDescription(existingDescription: string | undefined, ...values: string[]): string { | ||
if (existingDescription) { | ||
return `${existingDescription}\n\n${values.join('\n')}` | ||
} | ||
return values.join('\n') | ||
} | ||
export function isSchemaLike(schema: LinkedJSONSchema) { | ||
if (!isPlainObject(schema)) { | ||
return false | ||
} | ||
const parent = schema[Parent] | ||
if (parent === null) { | ||
return true | ||
} | ||
const JSON_SCHEMA_KEYWORDS = [ | ||
'allOf', | ||
'anyOf', | ||
'dependencies', | ||
'enum', | ||
'oneOf', | ||
'definitions', | ||
'not', | ||
'patternProperties', | ||
'properties', | ||
'required' | ||
] | ||
if (JSON_SCHEMA_KEYWORDS.some(_ => parent[_] === schema)) { | ||
return false | ||
} | ||
return true | ||
} |
@@ -1,3 +0,3 @@ | ||
import {JSONSchema} from './types/JSONSchema' | ||
import {mapDeep} from './utils' | ||
import {JSONSchema, LinkedJSONSchema} from './types/JSONSchema' | ||
import {traverse} from './utils' | ||
@@ -40,6 +40,6 @@ type Rule = (schema: JSONSchema) => boolean | void | ||
export function validate(schema: JSONSchema, filename: string): string[] { | ||
export function validate(schema: LinkedJSONSchema, filename: string): string[] { | ||
const errors: string[] = [] | ||
rules.forEach((rule, ruleName) => { | ||
mapDeep(schema, (schema, key) => { | ||
traverse(schema, (schema, key) => { | ||
if (rule(schema) === false) { | ||
@@ -46,0 +46,0 @@ errors.push(`Error at key "${key}" in file "${filename}": ${ruleName}`) |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
HTTP dependency
Supply chain riskContains a dependency which resolves to a remote HTTP URL which could be used to inject untrusted code and reduce overall package reliability.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
14
212
8
196839
4803
1
+ Added@apidevtools/json-schema-ref-parser@https://github.com/bcherny/json-schema-ref-parser.git#984282d3
+ Added@types/glob@7.2.0(transitive)
+ Addedglob-promise@4.2.2(transitive)
- Removedjson-schema-ref-parser@^9.0.6
- Removedjson-stringify-safe@^5.0.1
- Removed@apidevtools/json-schema-ref-parser@9.0.9(transitive)
- Removed@jsdevtools/ono@7.1.3(transitive)
- Removed@types/glob@8.1.0(transitive)
- Removedargparse@2.0.1(transitive)
- Removedcall-me-maybe@1.0.2(transitive)
- Removedglob-promise@3.4.0(transitive)
- Removedjs-yaml@4.1.0(transitive)
- Removedjson-schema-ref-parser@9.0.9(transitive)
- Removedjson-stringify-safe@5.0.1(transitive)
Updated@types/json-schema@^7.0.11
Updated@types/lodash@^4.14.182
Updated@types/prettier@^2.6.1
Updatedcli-color@^2.0.2
Updatedglob-promise@^4.2.2
Updatedis-glob@^4.0.3
Updatedlodash@^4.17.21
Updatedminimist@^1.2.6
Updatedprettier@^2.6.2