dtsgenerator 3.12.1 → 3.14.0
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.
- package/.eslintrc.json +3 -37
- package/.husky/pre-commit +4 -0
- package/.nycrc +4 -17
- package/.prettierignore +1 -0
- package/README.md +24 -2
- package/config_sample/dtsgen.json +10 -0
- package/config_sample/plugins.json +25 -0
- package/dist/cli.js +14 -84
- package/dist/commandOptions.js +1 -1
- package/dist/core/astBuilder.d.ts +1 -0
- package/dist/core/astBuilder.js +13 -8
- package/dist/core/config.js +4 -2
- package/dist/core/dtsGenerator.d.ts +4 -2
- package/dist/core/dtsGenerator.js +82 -76
- package/dist/core/index.js +4 -4
- package/dist/core/jsonSchema.js +19 -7
- package/dist/core/referenceResolver.d.ts +1 -1
- package/dist/core/referenceResolver.js +6 -6
- package/dist/core/schemaId.js +1 -1
- package/dist/core/type.d.ts +2 -2
- package/dist/core/type.js +12 -12
- package/dist/core/typeTree.d.ts +6 -0
- package/dist/core/typeTree.js +34 -0
- package/dist/core/utils.d.ts +1 -1
- package/dist/core/utils.js +9 -10
- package/dist/utils.d.ts +5 -1
- package/dist/utils.js +83 -5
- package/package.json +35 -44
- package/src/cli.ts +3 -78
- package/src/commandOptions.ts +1 -1
- package/src/core/astBuilder.ts +12 -4
- package/src/core/config.ts +3 -1
- package/src/core/dtsGenerator.ts +123 -101
- package/src/core/jsonSchema.ts +26 -12
- package/src/core/referenceResolver.ts +1 -1
- package/src/core/type.ts +7 -2
- package/src/core/typeTree.ts +39 -0
- package/src/core/utils.ts +7 -9
- package/src/utils.ts +79 -2
- package/tsconfig.json +1 -1
- package/.github/FUNDING.yml +0 -3
package/src/core/dtsGenerator.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import Debug from 'debug';
|
|
2
2
|
import * as ts from 'typescript';
|
|
3
|
-
import {
|
|
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
|
-
|
|
46
|
-
const
|
|
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(
|
|
144
|
+
private walk(tree: TypeTree, root = true): ts.Statement[] {
|
|
173
145
|
const result: ts.Statement[] = [];
|
|
174
|
-
const keys =
|
|
146
|
+
const keys = [...tree.children.keys()].sort();
|
|
175
147
|
for (const key of keys) {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
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 (
|
|
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(
|
|
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
|
|
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
|
-
|
|
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: ${
|
|
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.
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
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.
|
|
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.
|
|
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
|
|
487
|
+
private generateUnionType(
|
|
482
488
|
baseSchema: NormalizedSchema,
|
|
483
489
|
contents: JsonSchema[],
|
|
484
|
-
mergeContent:
|
|
490
|
+
mergeContent: JsonSchemaObject,
|
|
485
491
|
path: string,
|
|
486
492
|
terminate: boolean
|
|
487
493
|
): ts.TypeNode {
|
|
488
|
-
|
|
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
|
-
|
|
492
|
-
(
|
|
493
|
-
const
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
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(
|
package/src/core/jsonSchema.ts
CHANGED
|
@@ -234,13 +234,15 @@ export function searchAllSubSchema(
|
|
|
234
234
|
return;
|
|
235
235
|
}
|
|
236
236
|
addParameterSchema(
|
|
237
|
-
array.map(
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
237
|
+
array.map(
|
|
238
|
+
(
|
|
239
|
+
item: ParameterOrReference,
|
|
240
|
+
index: number
|
|
241
|
+
): [string, ParameterOrReference] => {
|
|
242
|
+
const key = 'name' in item ? item.name : `${index}`;
|
|
243
|
+
return [key, item];
|
|
244
|
+
}
|
|
245
|
+
),
|
|
244
246
|
keys
|
|
245
247
|
);
|
|
246
248
|
}
|
|
@@ -552,12 +554,24 @@ export function selectSchemaType(content: JsonSchema | OpenApiSchema): {
|
|
|
552
554
|
);
|
|
553
555
|
}
|
|
554
556
|
if ('$schema' in content) {
|
|
555
|
-
const
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
557
|
+
const schema = content['$schema'] ?? '';
|
|
558
|
+
if (/^https?:\/\/json-schema.org\/schema#?$/.test(schema)) {
|
|
559
|
+
return { type: 'Latest' };
|
|
560
|
+
}
|
|
561
|
+
const match =
|
|
562
|
+
/^https?:\/\/json-schema\.org\/(?:draft\/(\d{4}-\d{2})|draft-(\d+))\/schema#?$/.exec(
|
|
563
|
+
schema
|
|
564
|
+
);
|
|
559
565
|
if (match) {
|
|
560
|
-
|
|
566
|
+
if (match[1] != null) {
|
|
567
|
+
switch (match[1]) {
|
|
568
|
+
case '2019-09':
|
|
569
|
+
return { type: '2019-09' };
|
|
570
|
+
case '2020-12':
|
|
571
|
+
return { type: '2020-12' };
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
const version = Number(match[2]);
|
|
561
575
|
if (version <= 4) {
|
|
562
576
|
return { type: 'Draft04' };
|
|
563
577
|
} else {
|
|
@@ -21,7 +21,7 @@ export default class ReferenceResolver {
|
|
|
21
21
|
public getAllRegisteredSchema(): IterableIterator<Schema> {
|
|
22
22
|
return this.schemaCache.values();
|
|
23
23
|
}
|
|
24
|
-
public getAllRegisteredIdAndSchema():
|
|
24
|
+
public getAllRegisteredIdAndSchema(): IterableIterator<[string, Schema]> {
|
|
25
25
|
return this.schemaCache.entries();
|
|
26
26
|
}
|
|
27
27
|
|
package/src/core/type.ts
CHANGED
|
@@ -21,7 +21,12 @@ export type JsonSchema = JsonSchemaDraft04.Schema | JsonSchemaDraft07.Schema;
|
|
|
21
21
|
export type JsonSchemaObject =
|
|
22
22
|
| JsonSchemaDraft04.Schema
|
|
23
23
|
| JsonSchemaDraft07.SchemaObject;
|
|
24
|
-
export type SchemaType =
|
|
24
|
+
export type SchemaType =
|
|
25
|
+
| 'Draft04'
|
|
26
|
+
| 'Draft07'
|
|
27
|
+
| '2019-09'
|
|
28
|
+
| '2020-12'
|
|
29
|
+
| 'Latest';
|
|
25
30
|
export function isJsonSchemaDraft04(
|
|
26
31
|
_content: JsonSchemaObject,
|
|
27
32
|
type: SchemaType
|
|
@@ -109,7 +114,7 @@ function deepCopy(obj: any): any {
|
|
|
109
114
|
|
|
110
115
|
export interface PluginContext {
|
|
111
116
|
option: boolean | Record<string, unknown>;
|
|
112
|
-
inputSchemas:
|
|
117
|
+
inputSchemas: IterableIterator<[string, Schema]>;
|
|
113
118
|
}
|
|
114
119
|
|
|
115
120
|
export type PreProcessHandler = (contents: Schema[]) => Schema[];
|
|
@@ -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):
|
|
59
|
+
export function mergeSchema(a: any, b: any): boolean {
|
|
63
60
|
if ('$ref' in a || '$ref' in b) {
|
|
64
|
-
|
|
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]
|
|
73
|
+
a[key] ??= {};
|
|
74
|
+
mergeSchema(a[key], value);
|
|
76
75
|
} else {
|
|
77
76
|
a[key] = value;
|
|
78
77
|
}
|
|
79
78
|
});
|
|
80
|
-
|
|
81
|
-
return a;
|
|
79
|
+
return true;
|
|
82
80
|
}
|
package/src/utils.ts
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
1
2
|
import { URL } from 'url';
|
|
2
3
|
import glob from 'glob';
|
|
3
4
|
import proxy from 'https-proxy-agent';
|
|
5
|
+
import { ScriptTarget } from 'typescript';
|
|
6
|
+
import { CommandOptions, defaultConfigFile } from './commandOptions';
|
|
7
|
+
import { Config } from './core/config';
|
|
4
8
|
|
|
5
9
|
export function readStream(
|
|
6
|
-
stream: NodeJS.
|
|
10
|
+
stream: NodeJS.ReadableStream,
|
|
7
11
|
encoding: BufferEncoding = 'utf8'
|
|
8
12
|
): Promise<string> {
|
|
9
13
|
stream.setEncoding(encoding);
|
|
@@ -36,7 +40,7 @@ function noProxy(url: URL): boolean {
|
|
|
36
40
|
}
|
|
37
41
|
return false;
|
|
38
42
|
}
|
|
39
|
-
function buildProxyOptions(url: string): RequestInit | undefined {
|
|
43
|
+
export function buildProxyOptions(url: string): RequestInit | undefined {
|
|
40
44
|
const parsedUrl = new URL(url);
|
|
41
45
|
let proxyUrl;
|
|
42
46
|
if (!noProxy(parsedUrl)) {
|
|
@@ -73,3 +77,76 @@ export function globFiles(
|
|
|
73
77
|
});
|
|
74
78
|
});
|
|
75
79
|
}
|
|
80
|
+
|
|
81
|
+
export function readConfig(options: CommandOptions): Partial<Config> {
|
|
82
|
+
let pc: Partial<Config> = {};
|
|
83
|
+
const configFile = options.configFile ?? defaultConfigFile;
|
|
84
|
+
try {
|
|
85
|
+
pc = loadJSON(configFile);
|
|
86
|
+
pc.configFile = configFile;
|
|
87
|
+
} catch (err) {
|
|
88
|
+
if (options.configFile != null) {
|
|
89
|
+
console.error(
|
|
90
|
+
'Error to load config file from ' + options.configFile
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (pc.input == null) {
|
|
96
|
+
pc.input = {
|
|
97
|
+
files: [],
|
|
98
|
+
urls: [],
|
|
99
|
+
stdin: false,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
if (options.files.length > 0) {
|
|
103
|
+
pc.input.files = options.files;
|
|
104
|
+
} else if (pc.input.files == null) {
|
|
105
|
+
pc.input.files = [];
|
|
106
|
+
}
|
|
107
|
+
if (options.urls.length > 0) {
|
|
108
|
+
pc.input.urls = options.urls;
|
|
109
|
+
} else if (pc.input.urls == null) {
|
|
110
|
+
pc.input.urls = [];
|
|
111
|
+
}
|
|
112
|
+
pc.input.stdin = options.isReadFromStdin();
|
|
113
|
+
|
|
114
|
+
if (options.out != null) {
|
|
115
|
+
pc.outputFile = options.out;
|
|
116
|
+
}
|
|
117
|
+
if (options.target != null) {
|
|
118
|
+
pc.target = convertToScriptTarget(options.target);
|
|
119
|
+
} else if (pc.target != null) {
|
|
120
|
+
pc.target = convertToScriptTarget(pc.target as unknown as string);
|
|
121
|
+
}
|
|
122
|
+
pc.outputAST = !!options.outputAST;
|
|
123
|
+
return pc;
|
|
124
|
+
}
|
|
125
|
+
function loadJSON(file: string): Partial<Config> {
|
|
126
|
+
const content = fs.readFileSync(file, 'utf-8');
|
|
127
|
+
return JSON.parse(content) as Partial<Config>;
|
|
128
|
+
}
|
|
129
|
+
function convertToScriptTarget(target: string): ScriptTarget {
|
|
130
|
+
switch (target.trim().toLowerCase()) {
|
|
131
|
+
case 'es3':
|
|
132
|
+
return ScriptTarget.ES3;
|
|
133
|
+
case 'es5':
|
|
134
|
+
return ScriptTarget.ES5;
|
|
135
|
+
case 'es2015':
|
|
136
|
+
return ScriptTarget.ES2015;
|
|
137
|
+
case 'es2016':
|
|
138
|
+
return ScriptTarget.ES2016;
|
|
139
|
+
case 'es2017':
|
|
140
|
+
return ScriptTarget.ES2017;
|
|
141
|
+
case 'es2018':
|
|
142
|
+
return ScriptTarget.ES2018;
|
|
143
|
+
case 'es2019':
|
|
144
|
+
return ScriptTarget.ES2019;
|
|
145
|
+
case 'es2020':
|
|
146
|
+
return ScriptTarget.ES2020;
|
|
147
|
+
case 'esnext':
|
|
148
|
+
return ScriptTarget.ESNext;
|
|
149
|
+
default:
|
|
150
|
+
return ScriptTarget.Latest;
|
|
151
|
+
}
|
|
152
|
+
}
|
package/tsconfig.json
CHANGED
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"noUnusedLocals": true, /* Report errors on unused locals. */
|
|
37
37
|
"noUnusedParameters": true, /* Report errors on unused parameters. */
|
|
38
38
|
"noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
|
39
|
-
|
|
39
|
+
"noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
|
40
40
|
|
|
41
41
|
/* Module Resolution Options */
|
|
42
42
|
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
package/.github/FUNDING.yml
DELETED