dtsgenerator 3.13.2 → 3.15.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ /test/snapshots
package/README.md CHANGED
@@ -143,6 +143,21 @@ Output debug message by [debug](https://www.npmjs.com/package/debug) library.
143
143
 
144
144
  ## ChangeLog
145
145
 
146
+ ### [v3.15.1](https://github.com/horiuchi/dtsgenerator/releases/tag/v3.15.1) (2022-03-10)
147
+
148
+ - fixed:
149
+ - Fix handling of stdin option with config file for #534. Thank you @arnestaphorsius :+1:
150
+
151
+ ### [v3.15.0](https://github.com/horiuchi/dtsgenerator/releases/tag/v3.15.0) (2022-02-06)
152
+
153
+ - features:
154
+ - Support mobile wallet media types(`application/jwt` and `application/vnd.apple.pkpass`) for #530. Thank you @eostrom :+1:
155
+
156
+ ### [v3.14.0](https://github.com/horiuchi/dtsgenerator/releases/tag/v3.14.0) (2022-01-27)
157
+
158
+ - features:
159
+ - Support the nested `allOf` and `oneOf` schema for #513. Thank you for your report @Cry0nicS :+1:
160
+
146
161
  ### [v3.13.2](https://github.com/horiuchi/dtsgenerator/releases/tag/v3.13.2) (2021-10-08)
147
162
 
148
163
  - features:
@@ -112,5 +112,7 @@ The base JSON Schema version is Draft-07
112
112
  - `application/x-www-form-urlencoded`
113
113
  - `application/*+json`
114
114
  - `application/octet-stream`
115
+ - `application/jwt`
116
+ - `application/vnd.apple.pkpass`
115
117
  - `multipart/form-data`
116
118
  - `text/*`
package/dist/cli.js CHANGED
@@ -1,11 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
- const fs = (0, tslib_1.__importStar)(require("fs"));
4
+ const fs = tslib_1.__importStar(require("fs"));
5
5
  const path_1 = require("path");
6
- const commandOptions_1 = (0, tslib_1.__importStar)(require("./commandOptions"));
7
- const core_1 = (0, tslib_1.__importStar)(require("./core"));
8
- const config_1 = (0, tslib_1.__importStar)(require("./core/config"));
6
+ const commandOptions_1 = tslib_1.__importStar(require("./commandOptions"));
7
+ const core_1 = tslib_1.__importStar(require("./core"));
8
+ const config_1 = tslib_1.__importStar(require("./core/config"));
9
9
  const utils_1 = require("./utils");
10
10
  async function loadContents() {
11
11
  let contents = [];
@@ -9,7 +9,6 @@ export declare class CommandOptions {
9
9
  target?: string;
10
10
  info?: boolean;
11
11
  outputAST?: boolean;
12
- isReadFromStdin(): boolean;
13
12
  }
14
13
  declare const opts: CommandOptions;
15
14
  export default opts;
@@ -2,16 +2,13 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.clear = exports.initialize = exports.CommandOptions = exports.defaultConfigFile = void 0;
4
4
  const tslib_1 = require("tslib");
5
- const commander = (0, tslib_1.__importStar)(require("commander"));
5
+ const commander = tslib_1.__importStar(require("commander"));
6
6
  exports.defaultConfigFile = 'dtsgen.json';
7
7
  class CommandOptions {
8
8
  constructor() {
9
9
  this.files = [];
10
10
  this.urls = [];
11
11
  }
12
- isReadFromStdin() {
13
- return (this.stdin || (this.files.length === 0 && this.urls.length === 0));
14
- }
15
12
  }
16
13
  exports.CommandOptions = CommandOptions;
17
14
  const opts = new CommandOptions();
@@ -21,6 +21,7 @@ export declare function buildIndexSignatureNode(name: string, indexType: ts.Type
21
21
  export declare function buildTypeLiteralNode(elements: ts.TypeElement[]): ts.TypeNode;
22
22
  export declare function buildFreeFormObjectTypeLiteralNode(): ts.TypeNode;
23
23
  export declare function buildUnionTypeNode<T>(types: T[], builder: (t: T, index: number) => ts.TypeNode, terminate: boolean): ts.TypeNode;
24
+ export declare function buildIntersectionTypeNode(types: readonly ts.TypeNode[], terminate: boolean): ts.TypeNode;
24
25
  export declare function buildTupleTypeNode(types: ts.TypeNode | ts.TypeNode[], minItems?: number, maxItems?: number, additionalItems?: ts.TypeNode | false): ts.TypeNode;
25
26
  export declare function buildTypeReferenceNode(schema: NormalizedSchema, currentSchema: Schema): ts.TypeReferenceNode;
26
27
  export declare function addComment<T extends ts.Node>(node: T, schema: NormalizedSchema, terminate: boolean): T;
@@ -1,9 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.addOptionalInformation = exports.addComment = exports.buildTypeReferenceNode = exports.buildTupleTypeNode = exports.buildUnionTypeNode = exports.buildFreeFormObjectTypeLiteralNode = exports.buildTypeLiteralNode = exports.buildIndexSignatureNode = exports.buildPropertySignature = exports.buildTypeAliasNode = exports.buildInterfaceNode = exports.buildNamespaceNode = exports.buildBooleanLiteralTypeNode = exports.buildNumericLiteralTypeNode = exports.buildStringLiteralTypeNode = exports.buildNullKeyword = exports.buildSimpleArrayNode = exports.buildStringKeyword = exports.buildVoidKeyword = exports.buildUnknownKeyword = exports.buildNeverKeyword = exports.buildAnyKeyword = exports.buildKeyword = void 0;
3
+ exports.addOptionalInformation = exports.addComment = exports.buildTypeReferenceNode = exports.buildTupleTypeNode = exports.buildIntersectionTypeNode = exports.buildUnionTypeNode = exports.buildFreeFormObjectTypeLiteralNode = exports.buildTypeLiteralNode = exports.buildIndexSignatureNode = exports.buildPropertySignature = exports.buildTypeAliasNode = exports.buildInterfaceNode = exports.buildNamespaceNode = exports.buildBooleanLiteralTypeNode = exports.buildNumericLiteralTypeNode = exports.buildStringLiteralTypeNode = exports.buildNullKeyword = exports.buildSimpleArrayNode = exports.buildStringKeyword = exports.buildVoidKeyword = exports.buildUnknownKeyword = exports.buildNeverKeyword = exports.buildAnyKeyword = exports.buildKeyword = void 0;
4
4
  const tslib_1 = require("tslib");
5
- const ts = (0, tslib_1.__importStar)(require("typescript"));
6
- const config_1 = (0, tslib_1.__importDefault)(require("./config"));
5
+ const ts = tslib_1.__importStar(require("typescript"));
6
+ const config_1 = tslib_1.__importDefault(require("./config"));
7
7
  const validateIdentifier_1 = require("./validateIdentifier");
8
8
  function buildTypeNameIdentifier(name) {
9
9
  return ts.factory.createIdentifier((0, validateIdentifier_1.toValidIdentifier)(name, config_1.default.target));
@@ -122,6 +122,14 @@ function buildUnionTypeNode(types, builder, terminate) {
122
122
  return ts.factory.createParenthesizedType(node);
123
123
  }
124
124
  exports.buildUnionTypeNode = buildUnionTypeNode;
125
+ function buildIntersectionTypeNode(types, terminate) {
126
+ const node = ts.factory.createIntersectionTypeNode(types);
127
+ if (terminate) {
128
+ return node;
129
+ }
130
+ return ts.factory.createParenthesizedType(node);
131
+ }
132
+ exports.buildIntersectionTypeNode = buildIntersectionTypeNode;
125
133
  function buildTupleTypeNode(types, minItems, maxItems, additionalItems) {
126
134
  function typesIsArray(types) {
127
135
  return Array.isArray(types);
@@ -5,12 +5,12 @@ export default class DtsGenerator {
5
5
  private contents;
6
6
  constructor(contents: Schema[]);
7
7
  generate(): Promise<string>;
8
- private buildSchemaMergedMap;
9
8
  private getPlugins;
10
9
  private getPreProcess;
11
10
  private getPostProcess;
12
11
  private walk;
13
12
  private walkSchema;
13
+ private parseSchema;
14
14
  private normalizeContent;
15
15
  private normalizeSchemaContent;
16
16
  private generateDeclareType;
@@ -18,8 +18,10 @@ export default class DtsGenerator {
18
18
  private generateTypeCollection;
19
19
  private generateProperties;
20
20
  private generateTypeProperty;
21
+ private generateLiteralTypeProperty;
22
+ private checkExistOtherType;
21
23
  private generateLiteralTypeNode;
22
- private generateArrayedType;
24
+ private generateUnionType;
23
25
  private generateArrayTypeProperty;
24
26
  private generateType;
25
27
  private generateTypeName;
@@ -1,17 +1,17 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
- const debug_1 = (0, tslib_1.__importDefault)(require("debug"));
5
- const ts = (0, tslib_1.__importStar)(require("typescript"));
4
+ const debug_1 = tslib_1.__importDefault(require("debug"));
5
+ const ts = tslib_1.__importStar(require("typescript"));
6
6
  const jsonPointer_1 = require("../jsonPointer");
7
- const ast = (0, tslib_1.__importStar)(require("./astBuilder"));
8
- const config_1 = (0, tslib_1.__importDefault)(require("./config"));
7
+ const ast = tslib_1.__importStar(require("./astBuilder"));
8
+ const config_1 = tslib_1.__importDefault(require("./config"));
9
9
  const jsonSchema_1 = require("./jsonSchema");
10
- const referenceResolver_1 = (0, tslib_1.__importDefault)(require("./referenceResolver"));
10
+ const referenceResolver_1 = tslib_1.__importDefault(require("./referenceResolver"));
11
11
  const type_1 = require("./type");
12
- const utils = (0, tslib_1.__importStar)(require("./utils"));
12
+ const typeTree_1 = require("./typeTree");
13
+ const utils = tslib_1.__importStar(require("./utils"));
13
14
  const debug = (0, debug_1.default)('dtsgen');
14
- const typeMarker = Symbol();
15
15
  class DtsGenerator {
16
16
  constructor(contents) {
17
17
  this.resolver = new referenceResolver_1.default();
@@ -26,8 +26,8 @@ class DtsGenerator {
26
26
  debug('generate type definition files.');
27
27
  this.contents.forEach((schema) => this.resolver.registerSchema(schema));
28
28
  await this.resolver.resolve();
29
- const map = this.buildSchemaMergedMap(this.resolver.getAllRegisteredSchema());
30
- const root = this.walk(map, true);
29
+ const tree = (0, typeTree_1.buildTypeTree)(this.resolver.getAllRegisteredSchema());
30
+ const root = this.walk(tree);
31
31
  const file = ts.createSourceFile('_.d.ts', '', config_1.default.target, false, ts.ScriptKind.TS);
32
32
  Object.assign(file, {
33
33
  statements: ts.factory.createNodeArray(root),
@@ -44,28 +44,6 @@ class DtsGenerator {
44
44
  result.dispose();
45
45
  return transformedContent;
46
46
  }
47
- buildSchemaMergedMap(schemas) {
48
- const map = {};
49
- const paths = [];
50
- for (const type of schemas) {
51
- const path = type.id.toNames();
52
- paths.push({ path, type });
53
- }
54
- for (const item of paths) {
55
- const path = item.path;
56
- const parent = (0, jsonPointer_1.get)(map, path, true);
57
- if (parent == null) {
58
- (0, jsonPointer_1.set)(map, path, { [typeMarker]: item.type });
59
- }
60
- else {
61
- Object.assign(parent, { [typeMarker]: item.type });
62
- }
63
- }
64
- if (Object.keys(map).length === 0) {
65
- throw new Error('There is no schema in the input contents.');
66
- }
67
- return map;
68
- }
69
47
  async getPlugins() {
70
48
  const pre = [];
71
49
  const post = [];
@@ -117,18 +95,20 @@ class DtsGenerator {
117
95
  }
118
96
  return result;
119
97
  }
120
- walk(map, root) {
98
+ walk(tree, root = true) {
121
99
  const result = [];
122
- const keys = Object.keys(map).sort();
100
+ const keys = [...tree.children.keys()].sort();
123
101
  for (const key of keys) {
124
- const value = map[key];
125
- if (typeof value === 'object' &&
126
- Object.prototype.hasOwnProperty.call(value, typeMarker)) {
127
- const schema = value[typeMarker];
102
+ const value = tree.children.get(key);
103
+ if (value === undefined) {
104
+ continue;
105
+ }
106
+ if (value.schema !== undefined) {
107
+ const schema = value.schema;
128
108
  debug(` walk doProcess: key=${key} schemaId=${schema.id.getAbsoluteId()}`);
129
109
  result.push(this.walkSchema(schema, root));
130
110
  }
131
- if (typeof value === 'object' && Object.keys(value).length > 0) {
111
+ if (value.children.size > 0) {
132
112
  result.push(ast.buildNamespaceNode(key, this.walk(value, false), root));
133
113
  }
134
114
  }
@@ -137,19 +117,19 @@ class DtsGenerator {
137
117
  walkSchema(schema, root) {
138
118
  const normalized = this.normalizeContent(schema);
139
119
  this.currentSchema = normalized;
140
- const getNode = () => {
141
- const type = normalized.content.type;
142
- switch (type) {
143
- case 'any':
144
- return this.generateAnyTypeModel(normalized, root);
145
- case 'array':
146
- return this.generateTypeCollection(normalized, root);
147
- case 'object':
148
- default:
149
- return this.generateDeclareType(normalized, root);
150
- }
151
- };
152
- return ast.addOptionalInformation(ast.addComment(getNode(), normalized, true), normalized, true);
120
+ return ast.addOptionalInformation(ast.addComment(this.parseSchema(normalized, root), normalized, true), normalized, true);
121
+ }
122
+ parseSchema(schema, root = false) {
123
+ const type = schema.content.type;
124
+ switch (type) {
125
+ case 'any':
126
+ return this.generateAnyTypeModel(schema, root);
127
+ case 'array':
128
+ return this.generateTypeCollection(schema, root);
129
+ case 'object':
130
+ default:
131
+ return this.generateDeclareType(schema, root);
132
+ }
153
133
  }
154
134
  normalizeContent(schema, pointer) {
155
135
  if (pointer != null) {
@@ -253,13 +233,9 @@ class DtsGenerator {
253
233
  }
254
234
  }
255
235
  if (content.patternProperties) {
256
- const schemasTypes = [];
257
- for (const propertyName of Object.keys(content.patternProperties)) {
258
- const schema = this.normalizeContent(baseSchema, '/patternProperties/' + (0, jsonPointer_1.tilde)(propertyName));
259
- schemasTypes.push(this.generateTypeProperty(schema));
260
- }
261
- const node = ast.buildPropertySignature({ content: { readOnly: false } }, 'pattern', ts.createUnionTypeNode(schemasTypes), baseSchema.content.required, true);
262
- result.push(ts.addSyntheticTrailingComment(node, ts.SyntaxKind.MultiLineCommentTrivia, ` Patterns: ${Object.keys(content.patternProperties).join(' | ')} `));
236
+ const properties = Object.keys(content.patternProperties);
237
+ const node = ast.buildPropertySignature({ content: { readOnly: false } }, 'pattern', ast.buildUnionTypeNode(properties, (propertyName) => this.generateTypeProperty(this.normalizeContent(baseSchema, '/patternProperties/' + (0, jsonPointer_1.tilde)(propertyName))), true), baseSchema.content.required, true);
238
+ result.push(ts.addSyntheticTrailingComment(node, ts.SyntaxKind.MultiLineCommentTrivia, ` Patterns: ${properties.join(' | ')} `));
263
239
  }
264
240
  return result;
265
241
  }
@@ -271,19 +247,23 @@ class DtsGenerator {
271
247
  throw new Error('target referenced id is nothing: ' + content.$ref);
272
248
  }
273
249
  const refSchema = this.normalizeContent(ref);
274
- const node = ast.buildTypeReferenceNode(refSchema, this.currentSchema);
275
- return ast.addOptionalInformation(ast.addComment(node, refSchema, false), refSchema, false);
250
+ const node = ast.addOptionalInformation(ast.addComment(ast.buildTypeReferenceNode(refSchema, this.currentSchema), refSchema, false), refSchema, false);
251
+ return node;
276
252
  }
277
253
  if (content.anyOf) {
278
254
  const mergeContent = Object.assign({}, content);
279
255
  delete mergeContent.anyOf;
280
- return this.generateArrayedType(schema, content.anyOf, mergeContent, '/anyOf/', terminate);
256
+ return this.generateUnionType(schema, content.anyOf, mergeContent, '/anyOf/', terminate);
281
257
  }
282
258
  if (content.oneOf) {
283
259
  const mergeContent = Object.assign({}, content);
284
260
  delete mergeContent.oneOf;
285
- return this.generateArrayedType(schema, content.oneOf, mergeContent, '/oneOf/', terminate);
261
+ return this.generateUnionType(schema, content.oneOf, mergeContent, '/oneOf/', terminate);
286
262
  }
263
+ return this.generateLiteralTypeProperty(schema, terminate);
264
+ }
265
+ generateLiteralTypeProperty(schema, terminate = true) {
266
+ const content = schema.content;
287
267
  if (content.enum) {
288
268
  return ast.buildUnionTypeNode(content.enum, (value) => {
289
269
  return this.generateLiteralTypeNode(content, value);
@@ -299,17 +279,32 @@ class DtsGenerator {
299
279
  return this.generateType(schema, terminate);
300
280
  }
301
281
  }
282
+ checkExistOtherType(content, base) {
283
+ const schema = Object.assign({}, base, { content });
284
+ const result = this.generateLiteralTypeProperty(schema, false);
285
+ if (result.kind === ts.SyntaxKind.AnyKeyword) {
286
+ return undefined;
287
+ }
288
+ else if (result.kind === ts.SyntaxKind.TypeLiteral) {
289
+ const node = result;
290
+ if (node.members.length === 1 &&
291
+ node.members[0].kind === ts.SyntaxKind.IndexSignature) {
292
+ return undefined;
293
+ }
294
+ }
295
+ return result;
296
+ }
302
297
  generateLiteralTypeNode(content, value) {
303
298
  switch (content.type) {
304
299
  case 'integer':
305
300
  case 'number':
306
301
  return ast.buildNumericLiteralTypeNode(String(value));
307
302
  case 'boolean':
308
- return ast.buildBooleanLiteralTypeNode(value);
303
+ return ast.buildBooleanLiteralTypeNode(Boolean(value));
309
304
  case 'null':
310
305
  return ast.buildNullKeyword();
311
306
  case 'string':
312
- return ast.buildStringLiteralTypeNode(value);
307
+ return ast.buildStringLiteralTypeNode(String(value));
313
308
  }
314
309
  if (value === null) {
315
310
  return ast.buildNullKeyword();
@@ -324,17 +319,28 @@ class DtsGenerator {
324
319
  }
325
320
  return ast.buildStringLiteralTypeNode(String(value));
326
321
  }
327
- generateArrayedType(baseSchema, contents, mergeContent, path, terminate) {
328
- return ast.addOptionalInformation(ast.addComment(ast.buildUnionTypeNode(contents, (_, index) => {
322
+ generateUnionType(baseSchema, contents, mergeContent, path, terminate) {
323
+ const merged = [];
324
+ const children = contents.map((_, index) => {
329
325
  const schema = this.normalizeContent(baseSchema, path + index.toString());
330
- utils.mergeSchema(schema.content, mergeContent);
331
- if (schema.id.isEmpty()) {
332
- return ast.addOptionalInformation(this.generateTypeProperty(schema, false), schema, false);
333
- }
334
- else {
335
- return ast.addOptionalInformation(ast.buildTypeReferenceNode(schema, this.currentSchema), schema, false);
326
+ merged.push(utils.mergeSchema(schema.content, mergeContent));
327
+ return schema;
328
+ });
329
+ const allRef = merged.every((b) => !b);
330
+ const baseType = this.checkExistOtherType(mergeContent, baseSchema);
331
+ const result = ast.addOptionalInformation(ast.addComment(ast.buildUnionTypeNode(children, (schema, index) => {
332
+ const node = schema.id.isEmpty()
333
+ ? ast.addOptionalInformation(this.generateTypeProperty(schema, false), schema, false)
334
+ : ast.addOptionalInformation(ast.buildTypeReferenceNode(schema, this.currentSchema), schema, false);
335
+ if (baseType != null && !allRef && !merged[index]) {
336
+ return ast.buildIntersectionTypeNode([baseType, node], false);
336
337
  }
338
+ return node;
337
339
  }, terminate), baseSchema, false), baseSchema, terminate);
340
+ if (baseType != null && allRef) {
341
+ return ast.buildIntersectionTypeNode([baseType, result], terminate);
342
+ }
343
+ return result;
338
344
  }
339
345
  generateArrayTypeProperty(schema, terminate = true) {
340
346
  const items = schema.content.items;
@@ -3,10 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SchemaId = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const config_1 = require("./config");
6
- const dtsGenerator_1 = (0, tslib_1.__importDefault)(require("./dtsGenerator"));
6
+ const dtsGenerator_1 = tslib_1.__importDefault(require("./dtsGenerator"));
7
7
  var schemaId_1 = require("./schemaId");
8
- Object.defineProperty(exports, "SchemaId", { enumerable: true, get: function () { return (0, tslib_1.__importDefault)(schemaId_1).default; } });
9
- (0, tslib_1.__exportStar)(require("./type"), exports);
8
+ Object.defineProperty(exports, "SchemaId", { enumerable: true, get: function () { return tslib_1.__importDefault(schemaId_1).default; } });
9
+ tslib_1.__exportStar(require("./type"), exports);
10
10
  async function dtsGenerator(options) {
11
11
  if (options.config) {
12
12
  (0, config_1.setConfig)(options.config);
@@ -2,8 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.selectSchemaType = exports.searchAllSubSchema = exports.setId = exports.getId = exports.getSubSchema = void 0;
4
4
  const tslib_1 = require("tslib");
5
- const JsonPointer = (0, tslib_1.__importStar)(require("../jsonPointer"));
6
- const schemaId_1 = (0, tslib_1.__importDefault)(require("./schemaId"));
5
+ const JsonPointer = tslib_1.__importStar(require("../jsonPointer"));
6
+ const schemaId_1 = tslib_1.__importDefault(require("./schemaId"));
7
7
  const type_1 = require("./type");
8
8
  function getSubSchema(rootSchema, pointer, id) {
9
9
  const content = JsonPointer.get(rootSchema.content, JsonPointer.parse(pointer));
@@ -256,7 +256,7 @@ function searchAllSubSchema(schema, onFoundSchema, onFoundReference) {
256
256
  return;
257
257
  }
258
258
  for (const mime of Object.keys(types)) {
259
- if (/^text\/|^(?:application\/x-www-form-urlencoded$|^application\/([a-z0-9-_.]+\+)?json)$|^application\/octet-stream$|^multipart\/form-data$/.test(mime)) {
259
+ if (/^text\/|^(?:application\/x-www-form-urlencoded$|^application\/([a-z0-9-_.]+\+)?json)$|^application\/octet-stream$|^application\/jwt$|^application\/vnd.apple.pkpass$|^multipart\/form-data$/.test(mime)) {
260
260
  const mt = types[mime];
261
261
  setSubId(mt.schema, keys);
262
262
  }
@@ -2,9 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
4
  require("cross-fetch/polyfill");
5
- const debug_1 = (0, tslib_1.__importDefault)(require("debug"));
5
+ const debug_1 = tslib_1.__importDefault(require("debug"));
6
6
  const jsonSchema_1 = require("./jsonSchema");
7
- const schemaId_1 = (0, tslib_1.__importDefault)(require("./schemaId"));
7
+ const schemaId_1 = tslib_1.__importDefault(require("./schemaId"));
8
8
  const type_1 = require("./type");
9
9
  const debug = (0, debug_1.default)('dtsgen');
10
10
  class ReferenceResolver {
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
- const url = (0, tslib_1.__importStar)(require("url"));
4
+ const url = tslib_1.__importStar(require("url"));
5
5
  const validateIdentifier_1 = require("./validateIdentifier");
6
6
  class SchemaId {
7
7
  constructor(inputId, parentIds) {
package/dist/core/type.js CHANGED
@@ -2,12 +2,12 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.loadPlugin = exports.parseFileContent = exports.readSchemaFromUrl = exports.readSchemasFromFile = exports.readSchemaFromStdin = exports.parseSchema = exports.isJsonSchemaDraft04 = void 0;
4
4
  const tslib_1 = require("tslib");
5
- const fs = (0, tslib_1.__importStar)(require("fs"));
5
+ const fs = tslib_1.__importStar(require("fs"));
6
6
  const path_1 = require("path");
7
7
  const js_yaml_1 = require("js-yaml");
8
8
  const utils_1 = require("../utils");
9
9
  const jsonSchema_1 = require("./jsonSchema");
10
- const schemaId_1 = (0, tslib_1.__importDefault)(require("./schemaId"));
10
+ const schemaId_1 = tslib_1.__importDefault(require("./schemaId"));
11
11
  exports.ts = require("typescript");
12
12
  function isJsonSchemaDraft04(_content, type) {
13
13
  return type === 'Draft04';
@@ -81,7 +81,7 @@ async function loadPlugin(name, option) {
81
81
  if (!option) {
82
82
  return undefined;
83
83
  }
84
- const mod = (await Promise.resolve().then(() => (0, tslib_1.__importStar)(require(name))));
84
+ const mod = (await Promise.resolve().then(() => tslib_1.__importStar(require(name))));
85
85
  if (!(mod === null || mod === void 0 ? void 0 : mod.default)) {
86
86
  console.warn(`The plugin (${name}) is invalid module. That is not default export format.`);
87
87
  return undefined;
@@ -0,0 +1,6 @@
1
+ import { Schema } from './type';
2
+ export interface TypeTree {
3
+ children: Map<string, TypeTree>;
4
+ schema?: Schema;
5
+ }
6
+ export declare function buildTypeTree(schemas: IterableIterator<Schema>): TypeTree;
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildTypeTree = void 0;
4
+ function buildTypeTree(schemas) {
5
+ const tree = buildTree();
6
+ for (const type of schemas) {
7
+ setTypeToTree(tree, type.id.toNames(), type);
8
+ }
9
+ if (tree.children.size === 0) {
10
+ throw new Error('There is no schema in the input contents.');
11
+ }
12
+ return tree;
13
+ }
14
+ exports.buildTypeTree = buildTypeTree;
15
+ function setTypeToTree(tree, paths, type) {
16
+ if (paths.length === 0) {
17
+ throw new Error('The paths is nothing for set the type to TypeTree.');
18
+ }
19
+ let t = tree;
20
+ for (const key of paths) {
21
+ let next = t.children.get(key);
22
+ if (next === undefined) {
23
+ next = buildTree();
24
+ t.children.set(key, next);
25
+ }
26
+ t = next;
27
+ }
28
+ t.schema = type;
29
+ }
30
+ function buildTree() {
31
+ return {
32
+ children: new Map(),
33
+ };
34
+ }
@@ -4,4 +4,4 @@ import { JsonSchemaObject } from './type';
4
4
  import SimpleTypes = JsonSchemaDraft04.Schema.Definitions.SimpleTypes;
5
5
  export declare function toTSType(type: string, debugSource?: JsonSchemaObject): ts.KeywordTypeSyntaxKind | ts.SyntaxKind.NullKeyword | undefined;
6
6
  export declare function reduceTypes(types: SimpleTypes[]): SimpleTypes[];
7
- export declare function mergeSchema(a: any, b: any): any;
7
+ export declare function mergeSchema(a: any, b: any): boolean;
@@ -2,8 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.mergeSchema = exports.reduceTypes = exports.toTSType = void 0;
4
4
  const tslib_1 = require("tslib");
5
- const debug_1 = (0, tslib_1.__importDefault)(require("debug"));
6
- const ts = (0, tslib_1.__importStar)(require("typescript"));
5
+ const debug_1 = tslib_1.__importDefault(require("debug"));
6
+ const ts = tslib_1.__importStar(require("typescript"));
7
7
  const debug = (0, debug_1.default)('dtsgen');
8
8
  function toTSType(type, debugSource) {
9
9
  switch (type) {
@@ -39,18 +39,16 @@ function reduceTypes(types) {
39
39
  return types;
40
40
  }
41
41
  const set = new Set(types);
42
- if (set.delete('integer')) {
43
- set.add('number');
44
- }
45
42
  return Array.from(set.values());
46
43
  }
47
44
  exports.reduceTypes = reduceTypes;
48
45
  function mergeSchema(a, b) {
49
46
  if ('$ref' in a || '$ref' in b) {
50
- return { $ref: b['$ref'] || a['$ref'] };
47
+ a.$ref = b.$ref || a.$ref;
48
+ return false;
51
49
  }
52
50
  Object.keys(b).forEach((key) => {
53
- var _a;
51
+ var _a, _b;
54
52
  const value = b[key];
55
53
  if (a[key] != null && typeof value !== typeof a[key]) {
56
54
  debug(`mergeSchema warning: type is mismatched, key=${key}`);
@@ -59,12 +57,13 @@ function mergeSchema(a, b) {
59
57
  a[key] = ((_a = a[key]) !== null && _a !== void 0 ? _a : []).concat(value);
60
58
  }
61
59
  else if (value != null && typeof value === 'object') {
62
- a[key] = mergeSchema(a[key] || {}, value);
60
+ (_b = a[key]) !== null && _b !== void 0 ? _b : (a[key] = {});
61
+ mergeSchema(a[key], value);
63
62
  }
64
63
  else {
65
64
  a[key] = value;
66
65
  }
67
66
  });
68
- return a;
67
+ return true;
69
68
  }
70
69
  exports.mergeSchema = mergeSchema;
package/dist/utils.js CHANGED
@@ -2,10 +2,10 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.readConfig = exports.globFiles = exports.buildProxyOptions = exports.readUrl = exports.readStream = void 0;
4
4
  const tslib_1 = require("tslib");
5
- const fs = (0, tslib_1.__importStar)(require("fs"));
5
+ const fs = tslib_1.__importStar(require("fs"));
6
6
  const url_1 = require("url");
7
- const glob_1 = (0, tslib_1.__importDefault)(require("glob"));
8
- const https_proxy_agent_1 = (0, tslib_1.__importDefault)(require("https-proxy-agent"));
7
+ const glob_1 = tslib_1.__importDefault(require("glob"));
8
+ const https_proxy_agent_1 = tslib_1.__importDefault(require("https-proxy-agent"));
9
9
  const typescript_1 = require("typescript");
10
10
  const commandOptions_1 = require("./commandOptions");
11
11
  function readStream(stream, encoding = 'utf8') {
@@ -107,7 +107,14 @@ function readConfig(options) {
107
107
  else if (pc.input.urls == null) {
108
108
  pc.input.urls = [];
109
109
  }
110
- pc.input.stdin = options.isReadFromStdin();
110
+ if (options.stdin != null) {
111
+ pc.input.stdin = options.stdin;
112
+ }
113
+ else {
114
+ pc.input.stdin =
115
+ pc.input.stdin ||
116
+ (pc.input.files.length === 0 && pc.input.urls.length === 0);
117
+ }
111
118
  if (options.out != null) {
112
119
  pc.outputFile = options.out;
113
120
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dtsgenerator",
3
- "version": "3.13.2",
3
+ "version": "3.15.1",
4
4
  "description": "TypeScript d.ts file generator for JSON Schema file",
5
5
  "bin": {
6
6
  "dtsgen": "bin/dtsgen"
@@ -44,37 +44,37 @@
44
44
  "node": ">= 10.0"
45
45
  },
46
46
  "dependencies": {
47
- "commander": "^8.2.0",
48
- "cross-fetch": "^3.1.4",
49
- "debug": "^4.3.2",
47
+ "commander": "^9.0.0",
48
+ "cross-fetch": "^3.1.5",
49
+ "debug": "^4.3.3",
50
50
  "glob": "^7.2.0",
51
51
  "https-proxy-agent": "^5.0.0",
52
52
  "js-yaml": "^4.1.0",
53
53
  "tslib": "^2.3.1",
54
- "typescript": "^4.4.3"
54
+ "typescript": "^4.6.2"
55
55
  },
56
56
  "devDependencies": {
57
57
  "@dtsgenerator/do-nothing": "^2.5.1",
58
- "@dtsgenerator/eslint-config": "^0.4.0",
58
+ "@dtsgenerator/eslint-config": "^0.5.0",
59
59
  "@dtsgenerator/replace-namespace": "^1.5.1",
60
60
  "@dtsgenerator/single-quote": "^1.6.1",
61
- "@istanbuljs/nyc-config-typescript": "^1.0.1",
61
+ "@istanbuljs/nyc-config-typescript": "^1.0.2",
62
62
  "@types/debug": "^4.1.7",
63
- "@types/glob": "^7.1.4",
64
- "@types/js-yaml": "^4.0.3",
63
+ "@types/glob": "^7.2.0",
64
+ "@types/js-yaml": "^4.0.5",
65
65
  "@types/mkdirp": "^1.0.2",
66
- "@types/mocha": "^9.0.0",
67
- "@types/node": "^16.10.3",
66
+ "@types/mocha": "^9.1.0",
67
+ "@types/node": "^16.11.26",
68
68
  "cross-env": "^7.0.3",
69
- "eslint": "^7.32.0",
70
- "husky": "^7.0.2",
71
- "lint-staged": "^11.2.0",
72
- "mocha": "^9.1.2",
69
+ "eslint": "^8.10.0",
70
+ "husky": "^7.0.4",
71
+ "lint-staged": "^12.3.5",
72
+ "mocha": "^9.2.1",
73
73
  "nyc": "^15.1.0",
74
- "prettier": "^2.4.1",
74
+ "prettier": "^2.5.1",
75
75
  "rimraf": "^3.0.2",
76
- "source-map-support": "^0.5.20",
77
- "ts-node": "^10.2.1"
76
+ "source-map-support": "^0.5.21",
77
+ "ts-node": "^10.7.0"
78
78
  },
79
79
  "lint-staged": {
80
80
  "**/*.ts": [
@@ -11,12 +11,6 @@ export class CommandOptions {
11
11
  public target?: string;
12
12
  public info?: boolean;
13
13
  public outputAST?: boolean;
14
-
15
- public isReadFromStdin(): boolean {
16
- return (
17
- this.stdin || (this.files.length === 0 && this.urls.length === 0)
18
- );
19
- }
20
14
  }
21
15
 
22
16
  const opts = new CommandOptions();
@@ -47,7 +41,7 @@ function parse(options: CommandOptions, argv: string[]): commander.Command {
47
41
  }
48
42
 
49
43
  // eslint-disable-next-line @typescript-eslint/no-var-requires,@typescript-eslint/no-unsafe-assignment
50
- const pkg: Record<string, any> = require('../package.json');
44
+ const pkg: Record<string, string> = require('../package.json');
51
45
 
52
46
  // <hoge> is required, [hoge] is optional
53
47
  program
@@ -195,6 +195,17 @@ export function buildUnionTypeNode<T>(
195
195
  return ts.factory.createParenthesizedType(node);
196
196
  }
197
197
 
198
+ export function buildIntersectionTypeNode(
199
+ types: readonly ts.TypeNode[],
200
+ terminate: boolean
201
+ ): ts.TypeNode {
202
+ const node = ts.factory.createIntersectionTypeNode(types);
203
+ if (terminate) {
204
+ return node;
205
+ }
206
+ return ts.factory.createParenthesizedType(node);
207
+ }
208
+
198
209
  export function buildTupleTypeNode(
199
210
  types: ts.TypeNode | ts.TypeNode[],
200
211
  minItems?: number,
@@ -322,7 +333,7 @@ function getComment(schema: NormalizedSchema): string[] {
322
333
  function protectComment(str: string): string {
323
334
  return str.replace(/\*\//g, '*\u200B/'); // Unicode [ZERO WIDTH SPACE]
324
335
  }
325
- function appendComment(value?: string): void {
336
+ function appendComment(value?: any): void {
326
337
  if (value == null) {
327
338
  return;
328
339
  }
@@ -1,6 +1,6 @@
1
1
  import Debug from 'debug';
2
2
  import * as ts from 'typescript';
3
- import { get, set, tilde } from '../jsonPointer';
3
+ import { tilde } from '../jsonPointer';
4
4
  import * as ast from './astBuilder';
5
5
  import config from './config';
6
6
  import { getSubSchema, NormalizedSchema } from './jsonSchema';
@@ -13,10 +13,10 @@ import {
13
13
  PreProcessHandler,
14
14
  loadPlugin,
15
15
  } from './type';
16
+ import { buildTypeTree, TypeTree } from './typeTree';
16
17
  import * as utils from './utils';
17
18
 
18
19
  const debug = Debug('dtsgen');
19
- const typeMarker = Symbol();
20
20
 
21
21
  interface PluginConfig {
22
22
  plugin: Plugin;
@@ -42,11 +42,8 @@ export default class DtsGenerator {
42
42
  this.contents.forEach((schema) => this.resolver.registerSchema(schema));
43
43
  await this.resolver.resolve();
44
44
 
45
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
46
- const map = this.buildSchemaMergedMap(
47
- this.resolver.getAllRegisteredSchema()
48
- );
49
- const root = this.walk(map, true);
45
+ const tree = buildTypeTree(this.resolver.getAllRegisteredSchema());
46
+ const root = this.walk(tree);
50
47
  const file = ts.createSourceFile(
51
48
  '_.d.ts',
52
49
  '',
@@ -77,31 +74,6 @@ export default class DtsGenerator {
77
74
  return transformedContent;
78
75
  }
79
76
 
80
- private buildSchemaMergedMap(schemas: IterableIterator<Schema>): any {
81
- const map: any = {};
82
- const paths: { path: string[]; type: Schema }[] = [];
83
- for (const type of schemas) {
84
- const path = type.id.toNames();
85
- paths.push({ path, type });
86
- }
87
-
88
- for (const item of paths) {
89
- const path = item.path;
90
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
91
- const parent = get(map, path, true);
92
- if (parent == null) {
93
- set(map, path, { [typeMarker]: item.type });
94
- } else {
95
- Object.assign(parent, { [typeMarker]: item.type });
96
- }
97
- }
98
- if (Object.keys(map).length === 0) {
99
- throw new Error('There is no schema in the input contents.');
100
- }
101
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
102
- return map;
103
- }
104
-
105
77
  private async getPlugins(): Promise<{
106
78
  pre: PluginConfig[];
107
79
  post: PluginConfig[];
@@ -169,24 +141,22 @@ export default class DtsGenerator {
169
141
  return result;
170
142
  }
171
143
 
172
- private walk(map: any, root: boolean): ts.Statement[] {
144
+ private walk(tree: TypeTree, root = true): ts.Statement[] {
173
145
  const result: ts.Statement[] = [];
174
- const keys = Object.keys(map).sort();
146
+ const keys = [...tree.children.keys()].sort();
175
147
  for (const key of keys) {
176
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access
177
- const value = map[key];
178
- if (
179
- typeof value === 'object' &&
180
- Object.prototype.hasOwnProperty.call(value, typeMarker)
181
- ) {
182
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
183
- const schema = value[typeMarker] as Schema;
148
+ const value = tree.children.get(key);
149
+ if (value === undefined) {
150
+ continue;
151
+ }
152
+ if (value.schema !== undefined) {
153
+ const schema = value.schema;
184
154
  debug(
185
155
  ` walk doProcess: key=${key} schemaId=${schema.id.getAbsoluteId()}`
186
156
  );
187
157
  result.push(this.walkSchema(schema, root));
188
158
  }
189
- if (typeof value === 'object' && Object.keys(value).length > 0) {
159
+ if (value.children.size > 0) {
190
160
  result.push(
191
161
  ast.buildNamespaceNode(key, this.walk(value, false), root)
192
162
  );
@@ -199,25 +169,33 @@ export default class DtsGenerator {
199
169
  const normalized = this.normalizeContent(schema);
200
170
  this.currentSchema = normalized;
201
171
 
202
- const getNode = () => {
203
- const type = normalized.content.type;
204
- switch (type) {
205
- case 'any':
206
- return this.generateAnyTypeModel(normalized, root);
207
- case 'array':
208
- return this.generateTypeCollection(normalized, root);
209
- case 'object':
210
- default:
211
- return this.generateDeclareType(normalized, root);
212
- }
213
- };
214
172
  return ast.addOptionalInformation(
215
- ast.addComment(getNode(), normalized, true),
173
+ ast.addComment(
174
+ this.parseSchema(normalized, root),
175
+ normalized,
176
+ true
177
+ ),
216
178
  normalized,
217
179
  true
218
180
  );
219
181
  }
220
182
 
183
+ private parseSchema(
184
+ schema: NormalizedSchema,
185
+ root = false
186
+ ): ts.DeclarationStatement {
187
+ const type = schema.content.type;
188
+ switch (type) {
189
+ case 'any':
190
+ return this.generateAnyTypeModel(schema, root);
191
+ case 'array':
192
+ return this.generateTypeCollection(schema, root);
193
+ case 'object':
194
+ default:
195
+ return this.generateDeclareType(schema, root);
196
+ }
197
+ }
198
+
221
199
  private normalizeContent(
222
200
  schema: Schema,
223
201
  pointer?: string
@@ -361,18 +339,21 @@ export default class DtsGenerator {
361
339
  }
362
340
  }
363
341
  if (content.patternProperties) {
364
- const schemasTypes = [];
365
- for (const propertyName of Object.keys(content.patternProperties)) {
366
- const schema = this.normalizeContent(
367
- baseSchema,
368
- '/patternProperties/' + tilde(propertyName)
369
- );
370
- schemasTypes.push(this.generateTypeProperty(schema));
371
- }
342
+ const properties = Object.keys(content.patternProperties);
372
343
  const node = ast.buildPropertySignature(
373
344
  { content: { readOnly: false } } as NormalizedSchema,
374
345
  'pattern',
375
- ts.createUnionTypeNode(schemasTypes),
346
+ ast.buildUnionTypeNode(
347
+ properties,
348
+ (propertyName) =>
349
+ this.generateTypeProperty(
350
+ this.normalizeContent(
351
+ baseSchema,
352
+ '/patternProperties/' + tilde(propertyName)
353
+ )
354
+ ),
355
+ true
356
+ ),
376
357
  baseSchema.content.required,
377
358
  true
378
359
  );
@@ -380,9 +361,7 @@ export default class DtsGenerator {
380
361
  ts.addSyntheticTrailingComment(
381
362
  node,
382
363
  ts.SyntaxKind.MultiLineCommentTrivia,
383
- ` Patterns: ${Object.keys(content.patternProperties).join(
384
- ' | '
385
- )} `
364
+ ` Patterns: ${properties.join(' | ')} `
386
365
  )
387
366
  );
388
367
  }
@@ -401,20 +380,21 @@ export default class DtsGenerator {
401
380
  );
402
381
  }
403
382
  const refSchema = this.normalizeContent(ref);
404
- const node = ast.buildTypeReferenceNode(
405
- refSchema,
406
- this.currentSchema
407
- );
408
- return ast.addOptionalInformation(
409
- ast.addComment(node, refSchema, false),
383
+ const node = ast.addOptionalInformation(
384
+ ast.addComment(
385
+ ast.buildTypeReferenceNode(refSchema, this.currentSchema),
386
+ refSchema,
387
+ false
388
+ ),
410
389
  refSchema,
411
390
  false
412
391
  );
392
+ return node;
413
393
  }
414
394
  if (content.anyOf) {
415
395
  const mergeContent = Object.assign({}, content);
416
396
  delete mergeContent.anyOf;
417
- return this.generateArrayedType(
397
+ return this.generateUnionType(
418
398
  schema,
419
399
  content.anyOf,
420
400
  mergeContent,
@@ -425,7 +405,7 @@ export default class DtsGenerator {
425
405
  if (content.oneOf) {
426
406
  const mergeContent = Object.assign({}, content);
427
407
  delete mergeContent.oneOf;
428
- return this.generateArrayedType(
408
+ return this.generateUnionType(
429
409
  schema,
430
410
  content.oneOf,
431
411
  mergeContent,
@@ -433,6 +413,13 @@ export default class DtsGenerator {
433
413
  terminate
434
414
  );
435
415
  }
416
+ return this.generateLiteralTypeProperty(schema, terminate);
417
+ }
418
+ private generateLiteralTypeProperty(
419
+ schema: NormalizedSchema,
420
+ terminate = true
421
+ ): ts.TypeNode {
422
+ const content = schema.content;
436
423
  if (content.enum) {
437
424
  return ast.buildUnionTypeNode(
438
425
  content.enum,
@@ -449,6 +436,25 @@ export default class DtsGenerator {
449
436
  return this.generateType(schema, terminate);
450
437
  }
451
438
  }
439
+ private checkExistOtherType(
440
+ content: JsonSchemaObject,
441
+ base: NormalizedSchema
442
+ ): ts.TypeNode | undefined {
443
+ const schema = Object.assign({}, base, { content });
444
+ const result = this.generateLiteralTypeProperty(schema, false);
445
+ if (result.kind === ts.SyntaxKind.AnyKeyword) {
446
+ return undefined;
447
+ } else if (result.kind === ts.SyntaxKind.TypeLiteral) {
448
+ const node = result as ts.TypeLiteralNode;
449
+ if (
450
+ node.members.length === 1 &&
451
+ node.members[0].kind === ts.SyntaxKind.IndexSignature
452
+ ) {
453
+ return undefined;
454
+ }
455
+ }
456
+ return result;
457
+ }
452
458
  private generateLiteralTypeNode(
453
459
  content: JsonSchemaObject,
454
460
  value: any
@@ -458,11 +464,11 @@ export default class DtsGenerator {
458
464
  case 'number':
459
465
  return ast.buildNumericLiteralTypeNode(String(value));
460
466
  case 'boolean':
461
- return ast.buildBooleanLiteralTypeNode(value);
467
+ return ast.buildBooleanLiteralTypeNode(Boolean(value));
462
468
  case 'null':
463
469
  return ast.buildNullKeyword();
464
470
  case 'string':
465
- return ast.buildStringLiteralTypeNode(value);
471
+ return ast.buildStringLiteralTypeNode(String(value));
466
472
  }
467
473
  if (value === null) {
468
474
  return ast.buildNullKeyword();
@@ -478,39 +484,51 @@ export default class DtsGenerator {
478
484
  return ast.buildStringLiteralTypeNode(String(value));
479
485
  }
480
486
 
481
- private generateArrayedType(
487
+ private generateUnionType(
482
488
  baseSchema: NormalizedSchema,
483
489
  contents: JsonSchema[],
484
- mergeContent: JsonSchema,
490
+ mergeContent: JsonSchemaObject,
485
491
  path: string,
486
492
  terminate: boolean
487
493
  ): ts.TypeNode {
488
- return ast.addOptionalInformation(
494
+ const merged: boolean[] = [];
495
+ const children = contents.map((_, index) => {
496
+ const schema = this.normalizeContent(
497
+ baseSchema,
498
+ path + index.toString()
499
+ );
500
+ merged.push(utils.mergeSchema(schema.content, mergeContent));
501
+ return schema;
502
+ });
503
+ const allRef = merged.every((b) => !b);
504
+ const baseType = this.checkExistOtherType(mergeContent, baseSchema);
505
+
506
+ const result = ast.addOptionalInformation(
489
507
  ast.addComment(
490
508
  ast.buildUnionTypeNode(
491
- contents,
492
- (_, index) => {
493
- const schema = this.normalizeContent(
494
- baseSchema,
495
- path + index.toString()
496
- );
497
- utils.mergeSchema(schema.content, mergeContent);
498
- if (schema.id.isEmpty()) {
499
- return ast.addOptionalInformation(
500
- this.generateTypeProperty(schema, false),
501
- schema,
502
- false
503
- );
504
- } else {
505
- return ast.addOptionalInformation(
506
- ast.buildTypeReferenceNode(
507
- schema,
508
- this.currentSchema
509
- ),
510
- schema,
509
+ children,
510
+ (schema, index) => {
511
+ const node = schema.id.isEmpty()
512
+ ? ast.addOptionalInformation(
513
+ this.generateTypeProperty(schema, false),
514
+ schema,
515
+ false
516
+ )
517
+ : ast.addOptionalInformation(
518
+ ast.buildTypeReferenceNode(
519
+ schema,
520
+ this.currentSchema
521
+ ),
522
+ schema,
523
+ false
524
+ );
525
+ if (baseType != null && !allRef && !merged[index]) {
526
+ return ast.buildIntersectionTypeNode(
527
+ [baseType, node],
511
528
  false
512
529
  );
513
530
  }
531
+ return node;
514
532
  },
515
533
  terminate
516
534
  ),
@@ -520,6 +538,10 @@ export default class DtsGenerator {
520
538
  baseSchema,
521
539
  terminate
522
540
  );
541
+ if (baseType != null && allRef) {
542
+ return ast.buildIntersectionTypeNode([baseType, result], terminate);
543
+ }
544
+ return result;
523
545
  }
524
546
 
525
547
  private generateArrayTypeProperty(
@@ -379,7 +379,7 @@ export function searchAllSubSchema(
379
379
  }
380
380
  for (const mime of Object.keys(types)) {
381
381
  if (
382
- /^text\/|^(?:application\/x-www-form-urlencoded$|^application\/([a-z0-9-_.]+\+)?json)$|^application\/octet-stream$|^multipart\/form-data$/.test(
382
+ /^text\/|^(?:application\/x-www-form-urlencoded$|^application\/([a-z0-9-_.]+\+)?json)$|^application\/octet-stream$|^application\/jwt$|^application\/vnd.apple.pkpass$|^multipart\/form-data$/.test(
383
383
  mime
384
384
  )
385
385
  ) {
@@ -0,0 +1,39 @@
1
+ import { Schema } from './type';
2
+
3
+ export interface TypeTree {
4
+ children: Map<string, TypeTree>;
5
+ schema?: Schema;
6
+ }
7
+
8
+ export function buildTypeTree(schemas: IterableIterator<Schema>): TypeTree {
9
+ const tree: TypeTree = buildTree();
10
+ for (const type of schemas) {
11
+ setTypeToTree(tree, type.id.toNames(), type);
12
+ }
13
+ if (tree.children.size === 0) {
14
+ throw new Error('There is no schema in the input contents.');
15
+ }
16
+ return tree;
17
+ }
18
+
19
+ function setTypeToTree(tree: TypeTree, paths: string[], type: Schema): void {
20
+ if (paths.length === 0) {
21
+ throw new Error('The paths is nothing for set the type to TypeTree.');
22
+ }
23
+ let t: TypeTree = tree;
24
+ for (const key of paths) {
25
+ let next = t.children.get(key);
26
+ if (next === undefined) {
27
+ next = buildTree();
28
+ t.children.set(key, next);
29
+ }
30
+ t = next;
31
+ }
32
+ t.schema = type;
33
+ }
34
+
35
+ function buildTree(): TypeTree {
36
+ return {
37
+ children: new Map(),
38
+ };
39
+ }
package/src/core/utils.ts CHANGED
@@ -52,18 +52,16 @@ export function reduceTypes(types: SimpleTypes[]): SimpleTypes[] {
52
52
  return types;
53
53
  }
54
54
  const set = new Set<SimpleTypes>(types);
55
- if (set.delete('integer')) {
56
- set.add('number');
57
- }
58
55
  return Array.from(set.values());
59
56
  }
60
57
 
61
58
  // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
62
- export function mergeSchema(a: any, b: any): any {
59
+ export function mergeSchema(a: any, b: any): boolean {
63
60
  if ('$ref' in a || '$ref' in b) {
64
- return { $ref: b['$ref'] || a['$ref'] };
61
+ a.$ref = b.$ref || a.$ref;
62
+ return false;
65
63
  }
66
- Object.keys(b).forEach((key: string) => {
64
+ Object.keys(b as object).forEach((key: string) => {
67
65
  const value = b[key];
68
66
  if (a[key] != null && typeof value !== typeof a[key]) {
69
67
  debug(`mergeSchema warning: type is mismatched, key=${key}`);
@@ -72,11 +70,11 @@ export function mergeSchema(a: any, b: any): any {
72
70
  // eslint-disable-next-line @typescript-eslint/no-unsafe-call
73
71
  a[key] = (a[key] ?? []).concat(value);
74
72
  } else if (value != null && typeof value === 'object') {
75
- a[key] = mergeSchema(a[key] || {}, value);
73
+ a[key] ??= {};
74
+ mergeSchema(a[key], value);
76
75
  } else {
77
76
  a[key] = value;
78
77
  }
79
78
  });
80
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
81
- return a;
79
+ return true;
82
80
  }
package/src/utils.ts CHANGED
@@ -109,7 +109,13 @@ export function readConfig(options: CommandOptions): Partial<Config> {
109
109
  } else if (pc.input.urls == null) {
110
110
  pc.input.urls = [];
111
111
  }
112
- pc.input.stdin = options.isReadFromStdin();
112
+ if (options.stdin != null) {
113
+ pc.input.stdin = options.stdin;
114
+ } else {
115
+ pc.input.stdin =
116
+ pc.input.stdin ||
117
+ (pc.input.files.length === 0 && pc.input.urls.length === 0);
118
+ }
113
119
 
114
120
  if (options.out != null) {
115
121
  pc.outputFile = options.out;