@vkontakte/api-schema-typescript-generator 0.9.0 → 0.13.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/dist/generator.js +9 -99
- package/dist/generators/APITypingsGenerator.js +78 -138
- package/dist/generators/SchemaObject.js +15 -6
- package/dist/generators/TypeCodeBlock.js +10 -15
- package/dist/generators/enums.js +118 -0
- package/dist/generators/methods.js +40 -0
- package/dist/generators/typeString.js +18 -18
- package/dist/helpers.js +40 -1
- package/dist/log.js +1 -1
- package/dist/types/schema.js +2 -0
- package/dist/types.js +6 -1
- package/package.json +2 -1
- package/src/generator.ts +11 -134
- package/src/generators/APITypingsGenerator.ts +101 -163
- package/src/generators/BaseCodeBlock.ts +2 -2
- package/src/generators/SchemaObject.ts +26 -12
- package/src/generators/TypeCodeBlock.ts +13 -18
- package/src/generators/enums.ts +150 -0
- package/src/generators/methods.ts +49 -0
- package/src/generators/typeString.ts +35 -30
- package/src/helpers.ts +42 -1
- package/src/log.ts +1 -1
- package/src/types/schema.ts +152 -0
- package/src/types.ts +8 -40
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import * as Schema from '../types/schema';
|
|
1
2
|
import {
|
|
2
3
|
Dictionary,
|
|
3
|
-
JSONSchemaMethodInfoInterface,
|
|
4
|
-
JSONSchemaMethodsDefinitionsInterface,
|
|
5
4
|
ObjectType,
|
|
6
5
|
RefsDictionary,
|
|
7
6
|
} from '../types';
|
|
7
|
+
import { generateEnumAsUnionType } from './enums';
|
|
8
|
+
import { normalizeMethodInfo } from './methods';
|
|
8
9
|
import { SchemaObject } from './SchemaObject';
|
|
9
10
|
import {
|
|
10
11
|
getInterfaceName, getMethodSection, getObjectNameByRef,
|
|
@@ -14,7 +15,7 @@ import {
|
|
|
14
15
|
} from '../helpers';
|
|
15
16
|
import { CodeBlocksArray, GeneratorResultInterface } from './BaseCodeBlock';
|
|
16
17
|
import { TypeCodeBlock, TypeScriptCodeTypes } from './TypeCodeBlock';
|
|
17
|
-
import {
|
|
18
|
+
import { isObject, sortArrayAlphabetically, uniqueArray } from '../utils';
|
|
18
19
|
import {
|
|
19
20
|
baseAPIParamsInterfaceName,
|
|
20
21
|
baseBoolIntRef,
|
|
@@ -25,7 +26,7 @@ import {
|
|
|
25
26
|
import path from 'path';
|
|
26
27
|
import { CommentCodeBlock } from './CommentCodeBlock';
|
|
27
28
|
import { consoleLogError, consoleLogErrorAndExit, consoleLogInfo } from '../log';
|
|
28
|
-
import { generateImportsBlock
|
|
29
|
+
import { generateImportsBlock } from '../generator';
|
|
29
30
|
import { generateTypeString } from './typeString';
|
|
30
31
|
|
|
31
32
|
interface APITypingsGeneratorOptions {
|
|
@@ -43,7 +44,7 @@ interface APITypingsGeneratorOptions {
|
|
|
43
44
|
*/
|
|
44
45
|
methodsPattern: string;
|
|
45
46
|
|
|
46
|
-
methodsDefinitions:
|
|
47
|
+
methodsDefinitions: Schema.API;
|
|
47
48
|
objects: Dictionary<SchemaObject>;
|
|
48
49
|
responses: Dictionary<SchemaObject>;
|
|
49
50
|
}
|
|
@@ -55,7 +56,7 @@ export class APITypingsGenerator {
|
|
|
55
56
|
this.methodsPattern = prepareMethodsPattern(options.methodsPattern);
|
|
56
57
|
|
|
57
58
|
this.methodsDefinitions = options.methodsDefinitions;
|
|
58
|
-
this.methodsList = options.methodsDefinitions.methods;
|
|
59
|
+
this.methodsList = options.methodsDefinitions.methods || [];
|
|
59
60
|
this.objects = this.convertJSONSchemaDictionary(options.objects);
|
|
60
61
|
this.responses = this.convertJSONSchemaDictionary(options.responses);
|
|
61
62
|
|
|
@@ -78,8 +79,8 @@ export class APITypingsGenerator {
|
|
|
78
79
|
outDirPath!: APITypingsGeneratorOptions['outDirPath'];
|
|
79
80
|
methodsPattern!: Dictionary<boolean>;
|
|
80
81
|
|
|
81
|
-
methodsDefinitions!:
|
|
82
|
-
methodsList!:
|
|
82
|
+
methodsDefinitions!: Schema.API;
|
|
83
|
+
methodsList!: NonNullable<Schema.API['methods']>;
|
|
83
84
|
objects!: Dictionary<SchemaObject>;
|
|
84
85
|
responses!: Dictionary<SchemaObject>;
|
|
85
86
|
|
|
@@ -117,7 +118,7 @@ export class APITypingsGenerator {
|
|
|
117
118
|
this.resultFiles[path] = content;
|
|
118
119
|
}
|
|
119
120
|
|
|
120
|
-
private appendToFileMap(section: string, imports:
|
|
121
|
+
private appendToFileMap(section: string, imports: RefsDictionary, codeBlocks: CodeBlocksArray) {
|
|
121
122
|
const methodFile = this.methodFilesMap[section] || {
|
|
122
123
|
imports: {},
|
|
123
124
|
codeBlocks: [],
|
|
@@ -150,10 +151,11 @@ export class APITypingsGenerator {
|
|
|
150
151
|
if (allOfItem.ref && !this.visitedRefs[allOfItem.ref]) {
|
|
151
152
|
this.visitedRefs[allOfItem.ref] = true;
|
|
152
153
|
const refName = allOfItem.ref;
|
|
153
|
-
const objectName = getObjectNameByRef(refName);
|
|
154
|
-
allOfItem = this.objects[objectName];
|
|
155
154
|
|
|
156
|
-
|
|
155
|
+
const tempAllOfItem = this.getObjectByRef(refName);
|
|
156
|
+
if (tempAllOfItem) {
|
|
157
|
+
allOfItem = tempAllOfItem;
|
|
158
|
+
} else {
|
|
157
159
|
consoleLogErrorAndExit(`${refName} ref not found`);
|
|
158
160
|
}
|
|
159
161
|
}
|
|
@@ -180,11 +182,10 @@ export class APITypingsGenerator {
|
|
|
180
182
|
if (allOfItem.properties) {
|
|
181
183
|
additionalProperties = allOfItem.properties;
|
|
182
184
|
} else if (allOfItem.ref) {
|
|
183
|
-
const
|
|
184
|
-
const refObject = this.objects[objectName];
|
|
185
|
-
|
|
185
|
+
const refObject = this.getObjectByRef(allOfItem.ref);
|
|
186
186
|
if (!refObject) {
|
|
187
187
|
consoleLogErrorAndExit(`${object.name} ref object in allOf is not found`);
|
|
188
|
+
return;
|
|
188
189
|
}
|
|
189
190
|
|
|
190
191
|
additionalProperties = this.getObjectProperties(refObject, deep + 1);
|
|
@@ -206,7 +207,7 @@ export class APITypingsGenerator {
|
|
|
206
207
|
}
|
|
207
208
|
}
|
|
208
209
|
|
|
209
|
-
|
|
210
|
+
/**
|
|
210
211
|
* Filter properties with same name
|
|
211
212
|
* If an object uses allOf, some nested objects may have the same properties
|
|
212
213
|
*/
|
|
@@ -224,11 +225,10 @@ export class APITypingsGenerator {
|
|
|
224
225
|
}
|
|
225
226
|
|
|
226
227
|
private getObjectInterfaceCode(object: SchemaObject): GeneratorResultInterface | false {
|
|
227
|
-
let imports:
|
|
228
|
+
let imports: RefsDictionary = {};
|
|
228
229
|
let codeBlocks: CodeBlocksArray = [];
|
|
229
230
|
|
|
230
231
|
const properties = this.getObjectProperties(object);
|
|
231
|
-
const requiredProperties = arrayToMap(object.required);
|
|
232
232
|
|
|
233
233
|
const codeBlock = new TypeCodeBlock({
|
|
234
234
|
type: TypeScriptCodeTypes.Interface,
|
|
@@ -249,7 +249,9 @@ export class APITypingsGenerator {
|
|
|
249
249
|
value,
|
|
250
250
|
codeBlocks: newCodeBlocks,
|
|
251
251
|
description,
|
|
252
|
-
} = generateTypeString(property, this.objects
|
|
252
|
+
} = generateTypeString(property, this.objects, {
|
|
253
|
+
objectParentName: object.name,
|
|
254
|
+
});
|
|
253
255
|
|
|
254
256
|
imports = { ...imports, ...newImports };
|
|
255
257
|
codeBlocks = [...codeBlocks, ...newCodeBlocks];
|
|
@@ -258,7 +260,7 @@ export class APITypingsGenerator {
|
|
|
258
260
|
name: property.name,
|
|
259
261
|
description: [property.description, description].join(newLineChar),
|
|
260
262
|
value,
|
|
261
|
-
isRequired: isPatternProperty(property.name) ||
|
|
263
|
+
isRequired: isPatternProperty(property.name) || property.isRequired,
|
|
262
264
|
});
|
|
263
265
|
});
|
|
264
266
|
|
|
@@ -278,7 +280,7 @@ export class APITypingsGenerator {
|
|
|
278
280
|
}
|
|
279
281
|
|
|
280
282
|
if (object.enum) {
|
|
281
|
-
const { codeBlocks } =
|
|
283
|
+
const { codeBlocks } = generateEnumAsUnionType(object);
|
|
282
284
|
|
|
283
285
|
return {
|
|
284
286
|
codeBlocks: codeBlocks,
|
|
@@ -348,10 +350,14 @@ export class APITypingsGenerator {
|
|
|
348
350
|
this.generateObjectsFromImports(imports);
|
|
349
351
|
}
|
|
350
352
|
|
|
353
|
+
private getObjectByRef(ref: string): SchemaObject | undefined {
|
|
354
|
+
const refName = getObjectNameByRef(ref);
|
|
355
|
+
return this.objects[refName];
|
|
356
|
+
}
|
|
357
|
+
|
|
351
358
|
private generateObjectsFromRefs(refs: RefsDictionary): void {
|
|
352
359
|
Object.keys(refs).forEach((ref) => {
|
|
353
|
-
const
|
|
354
|
-
const refObject = this.objects[refName];
|
|
360
|
+
const refObject = this.getObjectByRef(ref);
|
|
355
361
|
if (!refObject) {
|
|
356
362
|
consoleLogInfo(`"${ref}" ref is not found`);
|
|
357
363
|
return;
|
|
@@ -361,10 +367,9 @@ export class APITypingsGenerator {
|
|
|
361
367
|
});
|
|
362
368
|
}
|
|
363
369
|
|
|
364
|
-
private generateObjectsFromImports(imports:
|
|
370
|
+
private generateObjectsFromImports(imports: RefsDictionary) {
|
|
365
371
|
Object.keys(imports).forEach((ref) => {
|
|
366
|
-
const
|
|
367
|
-
const refObject = this.objects[refName];
|
|
372
|
+
const refObject = this.getObjectByRef(ref);
|
|
368
373
|
if (!refObject) {
|
|
369
374
|
consoleLogInfo(`"${ref}" ref is not found`);
|
|
370
375
|
return;
|
|
@@ -374,52 +379,11 @@ export class APITypingsGenerator {
|
|
|
374
379
|
});
|
|
375
380
|
}
|
|
376
381
|
|
|
377
|
-
private generateMethodParams(methodInfo:
|
|
382
|
+
private generateMethodParams(methodInfo: SchemaObject) {
|
|
378
383
|
const section = getMethodSection(methodInfo.name);
|
|
379
384
|
const interfaceName = `${methodInfo.name} params`;
|
|
380
385
|
|
|
381
|
-
|
|
382
|
-
const requiredParams = parametersRaw.reduce<Dictionary<boolean>>((acc, param) => {
|
|
383
|
-
if (param.required) {
|
|
384
|
-
acc[param.name] = true;
|
|
385
|
-
}
|
|
386
|
-
return acc;
|
|
387
|
-
}, {});
|
|
388
|
-
|
|
389
|
-
const properties = parametersRaw.map((paramRaw) => {
|
|
390
|
-
paramRaw = { ...paramRaw };
|
|
391
|
-
|
|
392
|
-
// For method params "boolean" type means 1 or 0
|
|
393
|
-
// Real "false" boolean value will be detected by API as true
|
|
394
|
-
if (paramRaw.type === 'boolean') {
|
|
395
|
-
delete paramRaw.type;
|
|
396
|
-
paramRaw.$ref = baseBoolIntRef;
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
// For parameters of the "array" type, VK API still accepts only a comma-separated string
|
|
400
|
-
// This may change in the future when the VK API starts accepting a json body
|
|
401
|
-
if (paramRaw.type === 'array') {
|
|
402
|
-
paramRaw.type = 'string';
|
|
403
|
-
|
|
404
|
-
if (!paramRaw.description) {
|
|
405
|
-
paramRaw.description = '';
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
if (paramRaw.items) {
|
|
409
|
-
if (paramRaw.items.$ref) {
|
|
410
|
-
this.generateObjectsFromRefs({
|
|
411
|
-
[paramRaw.items.$ref]: true,
|
|
412
|
-
});
|
|
413
|
-
|
|
414
|
-
paramRaw.description += newLineChar.repeat(2) + paramRaw.items.$ref;
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
return new SchemaObject(paramRaw.name, paramRaw, interfaceName);
|
|
420
|
-
});
|
|
421
|
-
|
|
422
|
-
let imports: Dictionary<boolean> = {};
|
|
386
|
+
let imports: RefsDictionary = {};
|
|
423
387
|
let codeBlocks: CodeBlocksArray = [];
|
|
424
388
|
|
|
425
389
|
const codeBlock = new TypeCodeBlock({
|
|
@@ -430,12 +394,12 @@ export class APITypingsGenerator {
|
|
|
430
394
|
properties: [],
|
|
431
395
|
});
|
|
432
396
|
|
|
433
|
-
|
|
397
|
+
methodInfo.parameters.forEach((property) => {
|
|
434
398
|
const {
|
|
435
399
|
imports: newImports,
|
|
436
400
|
value,
|
|
437
401
|
codeBlocks: newCodeBlocks,
|
|
438
|
-
} = generateTypeString(property, this.objects, {
|
|
402
|
+
} = generateTypeString(property, this.objects, { needEnumNamesConstant: false });
|
|
439
403
|
|
|
440
404
|
imports = { ...imports, ...newImports };
|
|
441
405
|
codeBlocks = [...codeBlocks, ...newCodeBlocks];
|
|
@@ -444,7 +408,7 @@ export class APITypingsGenerator {
|
|
|
444
408
|
name: property.name,
|
|
445
409
|
description: property.description,
|
|
446
410
|
value,
|
|
447
|
-
isRequired:
|
|
411
|
+
isRequired: property.isRequired,
|
|
448
412
|
});
|
|
449
413
|
});
|
|
450
414
|
|
|
@@ -452,24 +416,22 @@ export class APITypingsGenerator {
|
|
|
452
416
|
this.generateObjectsFromImports(imports);
|
|
453
417
|
}
|
|
454
418
|
|
|
455
|
-
private getResponseObjectRef(
|
|
456
|
-
const objectName = getObjectNameByRef(
|
|
419
|
+
private getResponseObjectRef(ref: string): SchemaObject | undefined {
|
|
420
|
+
const objectName = getObjectNameByRef(ref);
|
|
457
421
|
|
|
458
422
|
if (this.responses[objectName]) {
|
|
459
423
|
return this.responses[objectName];
|
|
460
|
-
} else if (this.objects[objectName]) {
|
|
461
|
-
return this.objects[objectName];
|
|
462
424
|
}
|
|
463
425
|
|
|
464
|
-
return
|
|
426
|
+
return this.getObjectByRef(ref);
|
|
465
427
|
}
|
|
466
428
|
|
|
467
429
|
private getObjectCodeBlockAsType(object: SchemaObject): GeneratorResultInterface | false {
|
|
468
430
|
let codeBlocks: CodeBlocksArray = [];
|
|
469
|
-
let imports:
|
|
431
|
+
let imports: RefsDictionary = {};
|
|
470
432
|
|
|
471
433
|
if (object.enum) {
|
|
472
|
-
const { codeBlocks: newCodeBlocks } =
|
|
434
|
+
const { codeBlocks: newCodeBlocks } = generateEnumAsUnionType(object);
|
|
473
435
|
codeBlocks = [
|
|
474
436
|
...newCodeBlocks,
|
|
475
437
|
];
|
|
@@ -501,38 +463,36 @@ export class APITypingsGenerator {
|
|
|
501
463
|
}
|
|
502
464
|
|
|
503
465
|
private getResponseCodeBlockAsType(object: SchemaObject, response: SchemaObject): GeneratorResultInterface | false {
|
|
504
|
-
|
|
505
|
-
|
|
466
|
+
const {
|
|
467
|
+
imports,
|
|
468
|
+
value,
|
|
469
|
+
codeBlocks,
|
|
470
|
+
description,
|
|
471
|
+
} = generateTypeString(response, this.objects, {
|
|
472
|
+
objectParentName: ' ', // TODO: Refactor
|
|
473
|
+
});
|
|
506
474
|
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
needExport: true,
|
|
520
|
-
properties: [],
|
|
521
|
-
value,
|
|
522
|
-
});
|
|
475
|
+
const codeBlock = new TypeCodeBlock({
|
|
476
|
+
type: TypeScriptCodeTypes.Type,
|
|
477
|
+
refName: object.name,
|
|
478
|
+
interfaceName: getInterfaceName(object.name),
|
|
479
|
+
description: [
|
|
480
|
+
object.description,
|
|
481
|
+
description || '',
|
|
482
|
+
].join(newLineChar),
|
|
483
|
+
needExport: true,
|
|
484
|
+
properties: [],
|
|
485
|
+
value,
|
|
486
|
+
});
|
|
523
487
|
|
|
524
|
-
|
|
525
|
-
codeBlocks
|
|
488
|
+
return {
|
|
489
|
+
codeBlocks: [
|
|
526
490
|
...codeBlocks,
|
|
527
|
-
...newCodeBlocks,
|
|
528
491
|
codeBlock,
|
|
529
|
-
]
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
return {
|
|
533
|
-
codeBlocks,
|
|
492
|
+
],
|
|
534
493
|
imports,
|
|
535
494
|
value: '',
|
|
495
|
+
description,
|
|
536
496
|
};
|
|
537
497
|
}
|
|
538
498
|
|
|
@@ -549,59 +509,31 @@ export class APITypingsGenerator {
|
|
|
549
509
|
};
|
|
550
510
|
|
|
551
511
|
const objectName = getObjectNameByRef(object.ref);
|
|
552
|
-
let response: SchemaObject | undefined;
|
|
553
|
-
|
|
554
512
|
if (nonBuildableRefs[objectName]) {
|
|
555
513
|
return this.getObjectCodeBlockAsType(object);
|
|
556
|
-
}
|
|
557
|
-
response = this.responses[objectName];
|
|
558
|
-
|
|
559
|
-
const { properties = [] } = response;
|
|
560
|
-
const responseProperty = properties.find((property) => property.name === 'response');
|
|
561
|
-
|
|
562
|
-
if (responseProperty) {
|
|
563
|
-
response = responseProperty;
|
|
564
|
-
if (response.ref) {
|
|
565
|
-
return this.getResponseCodeBlockAsType(object, response);
|
|
566
|
-
}
|
|
567
|
-
} else {
|
|
568
|
-
// Maybe this is a crutch?
|
|
569
|
-
response.properties.forEach((property) => {
|
|
570
|
-
if (response && property.parentObjectName === response.name) {
|
|
571
|
-
response = property;
|
|
572
|
-
return true;
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
return false;
|
|
576
|
-
});
|
|
577
|
-
}
|
|
578
|
-
} else if (this.objects[objectName]) {
|
|
579
|
-
response = this.objects[objectName];
|
|
514
|
+
}
|
|
580
515
|
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
}
|
|
516
|
+
let response = this.getResponseObjectRef(object.ref);
|
|
517
|
+
if (!response) {
|
|
518
|
+
consoleLogError(`response schema object "${object.name}" has no response`, object);
|
|
519
|
+
return false;
|
|
584
520
|
}
|
|
585
521
|
|
|
586
|
-
//
|
|
587
|
-
|
|
588
|
-
response =
|
|
522
|
+
// VK API JSON Schema specific heuristic
|
|
523
|
+
if (response.properties.length === 1 && response.properties[0].name === 'response') {
|
|
524
|
+
response = response.properties[0];
|
|
589
525
|
}
|
|
590
526
|
|
|
591
|
-
if (
|
|
592
|
-
|
|
593
|
-
return false;
|
|
527
|
+
if (response.ref) {
|
|
528
|
+
return this.getResponseCodeBlockAsType(object, response);
|
|
594
529
|
}
|
|
595
530
|
|
|
596
|
-
response
|
|
531
|
+
response = response.clone();
|
|
597
532
|
response.setName(object.name);
|
|
598
533
|
|
|
599
|
-
let result: GeneratorResultInterface | false;
|
|
600
|
-
|
|
601
534
|
switch (response.type) {
|
|
602
535
|
case 'object':
|
|
603
|
-
|
|
604
|
-
break;
|
|
536
|
+
return this.getObjectInterfaceCode(response);
|
|
605
537
|
|
|
606
538
|
case 'integer':
|
|
607
539
|
case 'string':
|
|
@@ -610,11 +542,9 @@ export class APITypingsGenerator {
|
|
|
610
542
|
return this.getResponseCodeBlockAsType(object, response);
|
|
611
543
|
|
|
612
544
|
default:
|
|
613
|
-
consoleLogErrorAndExit(response.name, 'unknown type');
|
|
545
|
+
consoleLogErrorAndExit(response.name, 'unknown type', response.type);
|
|
614
546
|
return false;
|
|
615
547
|
}
|
|
616
|
-
|
|
617
|
-
return result;
|
|
618
548
|
}
|
|
619
549
|
|
|
620
550
|
public generateResponse(section: string, response: SchemaObject) {
|
|
@@ -629,39 +559,47 @@ export class APITypingsGenerator {
|
|
|
629
559
|
this.generateObjectsFromImports(imports);
|
|
630
560
|
}
|
|
631
561
|
|
|
632
|
-
private generateMethodParamsAndResponses(
|
|
633
|
-
const { name } =
|
|
634
|
-
const section = getMethodSection(
|
|
562
|
+
private generateMethodParamsAndResponses(method: Schema.Method) {
|
|
563
|
+
const { name: methodName } = method;
|
|
564
|
+
const section = getMethodSection(methodName);
|
|
635
565
|
|
|
636
|
-
if (!isObject(
|
|
637
|
-
consoleLogErrorAndExit(`"${
|
|
566
|
+
if (!isObject(method.responses)) {
|
|
567
|
+
consoleLogErrorAndExit(`"${methodName}" "responses" field is not an object.`);
|
|
638
568
|
return;
|
|
639
569
|
}
|
|
640
570
|
|
|
641
|
-
if (Object.keys(
|
|
642
|
-
consoleLogErrorAndExit(`"${
|
|
571
|
+
if (Object.keys(method.responses).length === 0) {
|
|
572
|
+
consoleLogErrorAndExit(`"${methodName}" "responses" field is empty.`);
|
|
643
573
|
return;
|
|
644
574
|
}
|
|
645
575
|
|
|
646
576
|
// Comment with method name for visual sections in file
|
|
647
|
-
const methodNameComment = new CommentCodeBlock([
|
|
648
|
-
if (
|
|
577
|
+
const methodNameComment = new CommentCodeBlock([methodName]);
|
|
578
|
+
if (method.description) {
|
|
649
579
|
methodNameComment.appendLines([
|
|
650
580
|
'',
|
|
651
|
-
|
|
581
|
+
method.description,
|
|
652
582
|
]);
|
|
653
583
|
}
|
|
654
584
|
this.appendToFileMap(section, {}, [methodNameComment]);
|
|
655
585
|
|
|
656
|
-
|
|
586
|
+
const {
|
|
587
|
+
method: normalizedMethod,
|
|
588
|
+
parameterRefs,
|
|
589
|
+
} = normalizeMethodInfo(method);
|
|
590
|
+
|
|
591
|
+
method = normalizedMethod;
|
|
592
|
+
this.generateObjectsFromRefs(parameterRefs);
|
|
593
|
+
|
|
594
|
+
this.generateMethodParams(new SchemaObject(method.name, method));
|
|
657
595
|
|
|
658
|
-
Object.entries(
|
|
659
|
-
if (this.ignoredResponses[
|
|
596
|
+
Object.entries(method.responses).forEach(([responseName, responseObject]) => {
|
|
597
|
+
if (this.ignoredResponses[methodName] && this.ignoredResponses[methodName][responseName]) {
|
|
660
598
|
return;
|
|
661
599
|
}
|
|
662
600
|
|
|
663
|
-
|
|
664
|
-
this.generateResponse(section, new SchemaObject(
|
|
601
|
+
const name = `${methodName}_${responseName}`;
|
|
602
|
+
this.generateResponse(section, new SchemaObject(name, responseObject));
|
|
665
603
|
});
|
|
666
604
|
}
|
|
667
605
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { RefsDictionary } from '../types';
|
|
2
2
|
|
|
3
3
|
export abstract class BaseCodeBlock {
|
|
4
4
|
toString(): string {
|
|
@@ -10,7 +10,7 @@ export type CodeBlocksArray = BaseCodeBlock[];
|
|
|
10
10
|
|
|
11
11
|
export interface GeneratorResultInterface {
|
|
12
12
|
codeBlocks: CodeBlocksArray;
|
|
13
|
-
imports:
|
|
13
|
+
imports: RefsDictionary;
|
|
14
14
|
value: string;
|
|
15
15
|
description?: string;
|
|
16
16
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { EnumLikeArray } from '../types';
|
|
1
2
|
import { isObject, isString } from '../utils';
|
|
2
3
|
import {
|
|
3
4
|
transformPatternPropertyName,
|
|
@@ -45,6 +46,10 @@ export class SchemaObject {
|
|
|
45
46
|
this.required = [];
|
|
46
47
|
}
|
|
47
48
|
|
|
49
|
+
if (typeof object.required === 'boolean') {
|
|
50
|
+
this.isRequired = object.required;
|
|
51
|
+
}
|
|
52
|
+
|
|
48
53
|
this.properties = [];
|
|
49
54
|
|
|
50
55
|
if (object.properties) {
|
|
@@ -53,6 +58,14 @@ export class SchemaObject {
|
|
|
53
58
|
});
|
|
54
59
|
}
|
|
55
60
|
|
|
61
|
+
this.parameters = [];
|
|
62
|
+
|
|
63
|
+
if (Array.isArray(object.parameters)) {
|
|
64
|
+
object.parameters.forEach((parameter: any) => {
|
|
65
|
+
this.parameters.push(new SchemaObject(parameter.name, parameter, `${name} param`));
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
56
69
|
if (object.patternProperties) {
|
|
57
70
|
Object.entries(object.patternProperties).forEach(([propertyName, property]: [string, any]) => {
|
|
58
71
|
this.properties.push(new SchemaObject(transformPatternPropertyName(propertyName), property, name));
|
|
@@ -70,25 +83,20 @@ export class SchemaObject {
|
|
|
70
83
|
if (Array.isArray(object.allOf) && object.allOf.length > 0) {
|
|
71
84
|
this.allOf = object.allOf.map((item: any) => new SchemaObject(name, item));
|
|
72
85
|
}
|
|
73
|
-
|
|
74
|
-
// Crutch
|
|
75
|
-
// if (this.oneOf && this.oneOf.length === 1) {
|
|
76
|
-
// this.allOf = [this.oneOf[0]];
|
|
77
|
-
// this.oneOf = undefined;
|
|
78
|
-
// }
|
|
79
86
|
}
|
|
80
87
|
|
|
81
88
|
name!: string;
|
|
82
|
-
originalName!: string;
|
|
83
89
|
parentObjectName!: string;
|
|
84
90
|
|
|
85
91
|
type!: string | string[];
|
|
86
|
-
|
|
87
|
-
|
|
92
|
+
description!: string;
|
|
93
|
+
ref!: string;
|
|
88
94
|
required!: string[];
|
|
89
|
-
|
|
90
|
-
readonly
|
|
95
|
+
isRequired!: boolean;
|
|
96
|
+
readonly enum!: EnumLikeArray;
|
|
97
|
+
readonly enumNames!: EnumLikeArray;
|
|
91
98
|
properties!: SchemaObject[];
|
|
99
|
+
parameters!: SchemaObject[];
|
|
92
100
|
readonly items!: SchemaObject;
|
|
93
101
|
readonly oneOf!: SchemaObject[];
|
|
94
102
|
readonly allOf!: SchemaObject[];
|
|
@@ -97,7 +105,13 @@ export class SchemaObject {
|
|
|
97
105
|
this.name = name;
|
|
98
106
|
|
|
99
107
|
if (Array.isArray(this.properties)) {
|
|
100
|
-
this.properties.forEach((property) =>
|
|
108
|
+
this.properties.forEach((property) => {
|
|
109
|
+
property.parentObjectName = name;
|
|
110
|
+
});
|
|
101
111
|
}
|
|
102
112
|
}
|
|
113
|
+
|
|
114
|
+
public clone() {
|
|
115
|
+
return Object.assign(Object.create(Object.getPrototypeOf(this)), this) as NonNullable<SchemaObject>;
|
|
116
|
+
}
|
|
103
117
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { BaseCodeBlock } from './BaseCodeBlock';
|
|
2
2
|
import { newLineChar } from '../constants';
|
|
3
|
-
import { areQuotesNeededForProperty } from '../helpers';
|
|
3
|
+
import { areQuotesNeededForProperty, joinCommentLines } from '../helpers';
|
|
4
4
|
import { consoleLogErrorAndExit } from '../log';
|
|
5
|
-
import { quoteJavaScriptValue,
|
|
5
|
+
import { quoteJavaScriptValue, trimStringDoubleSpaces } from '../utils';
|
|
6
6
|
|
|
7
7
|
export enum TypeScriptCodeTypes {
|
|
8
8
|
Interface = 'interface',
|
|
@@ -89,15 +89,11 @@ export class TypeCodeBlock extends BaseCodeBlock {
|
|
|
89
89
|
` ${quoteChar}${property.name}${quoteChar}${divider} ${value}${lineEnd}`,
|
|
90
90
|
];
|
|
91
91
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
return ' ' + `* ${line}`.trim();
|
|
98
|
-
}),
|
|
99
|
-
' */',
|
|
100
|
-
].join(newLineChar));
|
|
92
|
+
if (property.description) {
|
|
93
|
+
const commentLines = joinCommentLines(2, property.description);
|
|
94
|
+
if (commentLines.length) {
|
|
95
|
+
propertyCode.unshift(commentLines.join(newLineChar));
|
|
96
|
+
}
|
|
101
97
|
}
|
|
102
98
|
|
|
103
99
|
return propertyCode.join(newLineChar);
|
|
@@ -112,18 +108,17 @@ export class TypeCodeBlock extends BaseCodeBlock {
|
|
|
112
108
|
let before: string[] = [];
|
|
113
109
|
let code = '';
|
|
114
110
|
|
|
111
|
+
if (this.refName) {
|
|
112
|
+
before.push(`// ${this.refName}`);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
115
|
if (this.description) {
|
|
116
116
|
before = [
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
' */',
|
|
117
|
+
...before,
|
|
118
|
+
...joinCommentLines(0, this.description),
|
|
120
119
|
];
|
|
121
120
|
}
|
|
122
121
|
|
|
123
|
-
if (this.refName) {
|
|
124
|
-
before.push(`// ${this.refName}`);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
122
|
switch (this.type) {
|
|
128
123
|
case TypeScriptCodeTypes.Interface: {
|
|
129
124
|
if (!hasProperties) {
|