@vkontakte/api-schema-typescript-generator 0.13.0 → 0.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 +15 -2
- package/.github/CODEOWNERS +2 -0
- package/.prettierrc.js +10 -0
- package/dist/constants.js +1 -1
- package/dist/generators/APITypingsGenerator.js +58 -42
- package/dist/generators/CommentCodeBlock.js +3 -9
- package/dist/generators/SchemaObject.js +19 -1
- package/dist/generators/TypeCodeBlock.js +31 -18
- package/dist/generators/enums.js +2 -5
- package/dist/generators/methods.js +4 -3
- package/dist/helpers.js +34 -20
- package/dist/helpers.test.js +12 -0
- package/dist/index.js +4 -3
- package/jest.config.js +5 -0
- package/package.json +17 -11
- package/src/constants.ts +1 -1
- package/src/generator.ts +5 -1
- package/src/generators/APITypingsGenerator.ts +84 -61
- package/src/generators/CommentCodeBlock.ts +2 -9
- package/src/generators/SchemaObject.ts +17 -8
- package/src/generators/TypeCodeBlock.ts +56 -47
- package/src/generators/enums.ts +11 -11
- package/src/generators/methods.ts +4 -3
- package/src/generators/typeString.ts +4 -1
- package/src/helpers.test.ts +12 -0
- package/src/helpers.ts +38 -24
- package/src/index.ts +15 -5
- package/src/types/schema.ts +7 -0
package/.eslintrc.json
CHANGED
|
@@ -22,6 +22,19 @@
|
|
|
22
22
|
"@typescript-eslint/explicit-member-accessibility": "off",
|
|
23
23
|
"@typescript-eslint/no-unnecessary-condition": "off",
|
|
24
24
|
"@typescript-eslint/no-magic-numbers": "off",
|
|
25
|
-
"@typescript-eslint/no-extra-parens": "off"
|
|
26
|
-
|
|
25
|
+
"@typescript-eslint/no-extra-parens": "off",
|
|
26
|
+
|
|
27
|
+
"@typescript-eslint/quotes": "off",
|
|
28
|
+
"@typescript-eslint/indent": "off",
|
|
29
|
+
|
|
30
|
+
"no-shadow": "off"
|
|
31
|
+
},
|
|
32
|
+
"overrides": [
|
|
33
|
+
{
|
|
34
|
+
"files": ["**/*.ts"],
|
|
35
|
+
"rules": {
|
|
36
|
+
"no-undef": "off"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
]
|
|
27
40
|
}
|
package/.prettierrc.js
ADDED
package/dist/constants.js
CHANGED
|
@@ -26,17 +26,32 @@ class APITypingsGenerator {
|
|
|
26
26
|
this.methodsList = options.methodsDefinitions.methods || [];
|
|
27
27
|
this.objects = this.convertJSONSchemaDictionary(options.objects);
|
|
28
28
|
this.responses = this.convertJSONSchemaDictionary(options.responses);
|
|
29
|
+
this.errors = options.errors;
|
|
29
30
|
this.visitedRefs = {};
|
|
30
31
|
this.generatedObjects = {};
|
|
31
32
|
this.methodFilesMap = {};
|
|
32
33
|
this.exports = {};
|
|
33
34
|
this.ignoredResponses = {
|
|
34
35
|
'storage.get': {
|
|
35
|
-
|
|
36
|
+
keysResponse: true,
|
|
36
37
|
},
|
|
37
38
|
};
|
|
38
39
|
this.resultFiles = {};
|
|
39
40
|
}
|
|
41
|
+
needEmit;
|
|
42
|
+
outDirPath;
|
|
43
|
+
methodsPattern;
|
|
44
|
+
methodsDefinitions;
|
|
45
|
+
methodsList;
|
|
46
|
+
objects;
|
|
47
|
+
responses;
|
|
48
|
+
errors;
|
|
49
|
+
visitedRefs;
|
|
50
|
+
generatedObjects;
|
|
51
|
+
methodFilesMap;
|
|
52
|
+
exports;
|
|
53
|
+
ignoredResponses;
|
|
54
|
+
resultFiles;
|
|
40
55
|
convertJSONSchemaDictionary(objects) {
|
|
41
56
|
const dictionary = {};
|
|
42
57
|
Object.keys(objects).forEach((name) => {
|
|
@@ -67,10 +82,7 @@ class APITypingsGenerator {
|
|
|
67
82
|
...methodFile.imports,
|
|
68
83
|
...imports,
|
|
69
84
|
},
|
|
70
|
-
codeBlocks: [
|
|
71
|
-
...methodFile.codeBlocks,
|
|
72
|
-
...codeBlocks,
|
|
73
|
-
],
|
|
85
|
+
codeBlocks: [...methodFile.codeBlocks, ...codeBlocks],
|
|
74
86
|
};
|
|
75
87
|
}
|
|
76
88
|
collectAllOf(object, deep = 0) {
|
|
@@ -120,10 +132,7 @@ class APITypingsGenerator {
|
|
|
120
132
|
additionalProperties = this.getObjectProperties(refObject, deep + 1);
|
|
121
133
|
}
|
|
122
134
|
if (additionalProperties.length) {
|
|
123
|
-
properties = [
|
|
124
|
-
...properties,
|
|
125
|
-
...additionalProperties,
|
|
126
|
-
];
|
|
135
|
+
properties = [...properties, ...additionalProperties];
|
|
127
136
|
}
|
|
128
137
|
});
|
|
129
138
|
}
|
|
@@ -179,10 +188,7 @@ class APITypingsGenerator {
|
|
|
179
188
|
});
|
|
180
189
|
});
|
|
181
190
|
return {
|
|
182
|
-
codeBlocks: [
|
|
183
|
-
...codeBlocks,
|
|
184
|
-
codeBlock,
|
|
185
|
-
],
|
|
191
|
+
codeBlocks: [...codeBlocks, codeBlock],
|
|
186
192
|
imports,
|
|
187
193
|
value: '',
|
|
188
194
|
};
|
|
@@ -285,7 +291,9 @@ class APITypingsGenerator {
|
|
|
285
291
|
properties: [],
|
|
286
292
|
});
|
|
287
293
|
methodInfo.parameters.forEach((property) => {
|
|
288
|
-
const { imports: newImports, value, codeBlocks: newCodeBlocks, } = typeString_1.generateTypeString(property, this.objects, {
|
|
294
|
+
const { imports: newImports, value, codeBlocks: newCodeBlocks, } = typeString_1.generateTypeString(property, this.objects, {
|
|
295
|
+
needEnumNamesConstant: false,
|
|
296
|
+
});
|
|
289
297
|
imports = { ...imports, ...newImports };
|
|
290
298
|
codeBlocks = [...codeBlocks, ...newCodeBlocks];
|
|
291
299
|
codeBlock.addProperty({
|
|
@@ -310,12 +318,10 @@ class APITypingsGenerator {
|
|
|
310
318
|
let imports = {};
|
|
311
319
|
if (object.enum) {
|
|
312
320
|
const { codeBlocks: newCodeBlocks } = enums_1.generateEnumAsUnionType(object);
|
|
313
|
-
codeBlocks = [
|
|
314
|
-
...newCodeBlocks,
|
|
315
|
-
];
|
|
321
|
+
codeBlocks = [...newCodeBlocks];
|
|
316
322
|
}
|
|
317
323
|
else {
|
|
318
|
-
const { imports: newImports, value, codeBlocks: newCodeBlocks } = typeString_1.generateTypeString(object, this.objects);
|
|
324
|
+
const { imports: newImports, value, codeBlocks: newCodeBlocks, } = typeString_1.generateTypeString(object, this.objects);
|
|
319
325
|
const codeBlock = new TypeCodeBlock_1.TypeCodeBlock({
|
|
320
326
|
type: TypeCodeBlock_1.TypeScriptCodeTypes.Type,
|
|
321
327
|
refName: object.name,
|
|
@@ -326,11 +332,7 @@ class APITypingsGenerator {
|
|
|
326
332
|
value,
|
|
327
333
|
});
|
|
328
334
|
imports = newImports;
|
|
329
|
-
codeBlocks = [
|
|
330
|
-
...codeBlocks,
|
|
331
|
-
...newCodeBlocks,
|
|
332
|
-
codeBlock,
|
|
333
|
-
];
|
|
335
|
+
codeBlocks = [...codeBlocks, ...newCodeBlocks, codeBlock];
|
|
334
336
|
}
|
|
335
337
|
return {
|
|
336
338
|
codeBlocks,
|
|
@@ -339,26 +341,20 @@ class APITypingsGenerator {
|
|
|
339
341
|
};
|
|
340
342
|
}
|
|
341
343
|
getResponseCodeBlockAsType(object, response) {
|
|
342
|
-
const { imports, value, codeBlocks, description
|
|
343
|
-
objectParentName: ' ',
|
|
344
|
+
const { imports, value, codeBlocks, description } = typeString_1.generateTypeString(response, this.objects, {
|
|
345
|
+
objectParentName: ' ', // TODO: Refactor
|
|
344
346
|
});
|
|
345
347
|
const codeBlock = new TypeCodeBlock_1.TypeCodeBlock({
|
|
346
348
|
type: TypeCodeBlock_1.TypeScriptCodeTypes.Type,
|
|
347
349
|
refName: object.name,
|
|
348
350
|
interfaceName: helpers_1.getInterfaceName(object.name),
|
|
349
|
-
description: [
|
|
350
|
-
object.description,
|
|
351
|
-
description || '',
|
|
352
|
-
].join(constants_1.newLineChar),
|
|
351
|
+
description: [object.description, description || ''].join(constants_1.newLineChar),
|
|
353
352
|
needExport: true,
|
|
354
353
|
properties: [],
|
|
355
354
|
value,
|
|
356
355
|
});
|
|
357
356
|
return {
|
|
358
|
-
codeBlocks: [
|
|
359
|
-
...codeBlocks,
|
|
360
|
-
codeBlock,
|
|
361
|
-
],
|
|
357
|
+
codeBlocks: [...codeBlocks, codeBlock],
|
|
362
358
|
imports,
|
|
363
359
|
value: '',
|
|
364
360
|
description,
|
|
@@ -428,13 +424,10 @@ class APITypingsGenerator {
|
|
|
428
424
|
// Comment with method name for visual sections in file
|
|
429
425
|
const methodNameComment = new CommentCodeBlock_1.CommentCodeBlock([methodName]);
|
|
430
426
|
if (method.description) {
|
|
431
|
-
methodNameComment.appendLines([
|
|
432
|
-
'',
|
|
433
|
-
method.description,
|
|
434
|
-
]);
|
|
427
|
+
methodNameComment.appendLines(['', method.description]);
|
|
435
428
|
}
|
|
436
429
|
this.appendToFileMap(section, {}, [methodNameComment]);
|
|
437
|
-
const { method: normalizedMethod, parameterRefs
|
|
430
|
+
const { method: normalizedMethod, parameterRefs } = methods_1.normalizeMethodInfo(method);
|
|
438
431
|
method = normalizedMethod;
|
|
439
432
|
this.generateObjectsFromRefs(parameterRefs);
|
|
440
433
|
this.generateMethodParams(new SchemaObject_1.SchemaObject(method.name, method));
|
|
@@ -460,13 +453,35 @@ class APITypingsGenerator {
|
|
|
460
453
|
this.registerExport(`./methods/${section}`, codeBlock.interfaceName);
|
|
461
454
|
}
|
|
462
455
|
});
|
|
463
|
-
const code = [
|
|
464
|
-
generator_1.generateImportsBlock(imports, null),
|
|
465
|
-
...codeBlocks,
|
|
466
|
-
];
|
|
456
|
+
const code = [generator_1.generateImportsBlock(imports, null), ...codeBlocks];
|
|
467
457
|
this.registerResultFile(path_1.default.join('methods', `${section}.ts`), code.join(constants_1.newLineChar.repeat(2)));
|
|
468
458
|
});
|
|
469
459
|
}
|
|
460
|
+
generateErrors() {
|
|
461
|
+
log_1.consoleLogInfo('creating errors...');
|
|
462
|
+
const code = [];
|
|
463
|
+
Object.entries(this.errors)
|
|
464
|
+
.reduce((acc, [name, error]) => {
|
|
465
|
+
acc.push({ name, ...error });
|
|
466
|
+
return acc;
|
|
467
|
+
}, [])
|
|
468
|
+
.sort((errorA, errorB) => {
|
|
469
|
+
return errorA.code - errorB.code;
|
|
470
|
+
})
|
|
471
|
+
.forEach((error) => {
|
|
472
|
+
const errorConstantName = error.name.toUpperCase();
|
|
473
|
+
code.push(new TypeCodeBlock_1.TypeCodeBlock({
|
|
474
|
+
type: TypeCodeBlock_1.TypeScriptCodeTypes.Const,
|
|
475
|
+
interfaceName: errorConstantName,
|
|
476
|
+
needExport: true,
|
|
477
|
+
value: String(error.code),
|
|
478
|
+
properties: [],
|
|
479
|
+
description: [error.description, error.$comment || ''].join(constants_1.newLineChar.repeat(2)),
|
|
480
|
+
}).toString());
|
|
481
|
+
this.registerExport('./common/errors', errorConstantName);
|
|
482
|
+
});
|
|
483
|
+
this.registerResultFile(path_1.default.join('common', 'errors.ts'), code.join(constants_1.newLineChar.repeat(2)));
|
|
484
|
+
}
|
|
470
485
|
createCommonTypes() {
|
|
471
486
|
log_1.consoleLogInfo('creating common types...');
|
|
472
487
|
const code = [];
|
|
@@ -532,6 +547,7 @@ class APITypingsGenerator {
|
|
|
532
547
|
generate() {
|
|
533
548
|
log_1.consoleLogInfo('generate');
|
|
534
549
|
this.generateMethods();
|
|
550
|
+
this.generateErrors();
|
|
535
551
|
if (this.needEmit) {
|
|
536
552
|
this.createCommonTypes();
|
|
537
553
|
this.createIndexExports();
|
|
@@ -8,19 +8,13 @@ class CommentCodeBlock extends BaseCodeBlock_1.BaseCodeBlock {
|
|
|
8
8
|
super();
|
|
9
9
|
this.lines = lines;
|
|
10
10
|
}
|
|
11
|
+
lines;
|
|
11
12
|
appendLines(lines) {
|
|
12
|
-
this.lines = [
|
|
13
|
-
...this.lines,
|
|
14
|
-
...lines,
|
|
15
|
-
];
|
|
13
|
+
this.lines = [...this.lines, ...lines];
|
|
16
14
|
}
|
|
17
15
|
toString() {
|
|
18
16
|
const inner = this.lines.map((line) => constants_1.spaceChar + `* ${line}`.trim());
|
|
19
|
-
return [
|
|
20
|
-
'/**',
|
|
21
|
-
...inner,
|
|
22
|
-
' */',
|
|
23
|
-
].join(constants_1.newLineChar);
|
|
17
|
+
return ['/**', ...inner, ' */'].join(constants_1.newLineChar);
|
|
24
18
|
}
|
|
25
19
|
}
|
|
26
20
|
exports.CommentCodeBlock = CommentCodeBlock;
|
|
@@ -7,7 +7,11 @@ const log_1 = require("../log");
|
|
|
7
7
|
class SchemaObject {
|
|
8
8
|
constructor(name, object, parentName) {
|
|
9
9
|
if (!utils_1.isObject(object)) {
|
|
10
|
-
log_1.consoleLogErrorAndExit(`[SchemaObject] "${name}" is not an object.`, {
|
|
10
|
+
log_1.consoleLogErrorAndExit(`[SchemaObject] "${name}" is not an object.`, {
|
|
11
|
+
name,
|
|
12
|
+
object,
|
|
13
|
+
parentName,
|
|
14
|
+
});
|
|
11
15
|
return;
|
|
12
16
|
}
|
|
13
17
|
this.name = name;
|
|
@@ -68,6 +72,20 @@ class SchemaObject {
|
|
|
68
72
|
this.allOf = object.allOf.map((item) => new SchemaObject(name, item));
|
|
69
73
|
}
|
|
70
74
|
}
|
|
75
|
+
name;
|
|
76
|
+
parentObjectName;
|
|
77
|
+
type;
|
|
78
|
+
description;
|
|
79
|
+
ref;
|
|
80
|
+
required;
|
|
81
|
+
isRequired;
|
|
82
|
+
enum;
|
|
83
|
+
enumNames;
|
|
84
|
+
properties;
|
|
85
|
+
parameters;
|
|
86
|
+
items;
|
|
87
|
+
oneOf;
|
|
88
|
+
allOf;
|
|
71
89
|
setName(name) {
|
|
72
90
|
this.name = name;
|
|
73
91
|
if (Array.isArray(this.properties)) {
|
|
@@ -12,6 +12,7 @@ var TypeScriptCodeTypes;
|
|
|
12
12
|
TypeScriptCodeTypes["Enum"] = "enum";
|
|
13
13
|
TypeScriptCodeTypes["ConstantObject"] = "constant_object";
|
|
14
14
|
TypeScriptCodeTypes["Type"] = "type";
|
|
15
|
+
TypeScriptCodeTypes["Const"] = "const";
|
|
15
16
|
})(TypeScriptCodeTypes = exports.TypeScriptCodeTypes || (exports.TypeScriptCodeTypes = {}));
|
|
16
17
|
class TypeCodeBlock extends BaseCodeBlock_1.BaseCodeBlock {
|
|
17
18
|
constructor(options) {
|
|
@@ -26,12 +27,24 @@ class TypeCodeBlock extends BaseCodeBlock_1.BaseCodeBlock {
|
|
|
26
27
|
this.value = options.value;
|
|
27
28
|
this.needExport = options.needExport;
|
|
28
29
|
}
|
|
30
|
+
options;
|
|
31
|
+
type;
|
|
32
|
+
refName;
|
|
33
|
+
interfaceName;
|
|
34
|
+
extendsInterfaces;
|
|
35
|
+
description;
|
|
36
|
+
properties;
|
|
37
|
+
value;
|
|
38
|
+
needExport;
|
|
29
39
|
addProperty(property) {
|
|
30
40
|
this.properties.push(property);
|
|
31
41
|
}
|
|
32
42
|
getPropertiesCode() {
|
|
33
|
-
const quoteChar = this.properties.some((property) => helpers_1.areQuotesNeededForProperty(property.name))
|
|
34
|
-
|
|
43
|
+
const quoteChar = this.properties.some((property) => helpers_1.areQuotesNeededForProperty(property.name))
|
|
44
|
+
? "'"
|
|
45
|
+
: '';
|
|
46
|
+
return this.properties
|
|
47
|
+
.map((property) => {
|
|
35
48
|
let divider = '';
|
|
36
49
|
let lineEnd = '';
|
|
37
50
|
switch (this.type) {
|
|
@@ -59,7 +72,8 @@ class TypeCodeBlock extends BaseCodeBlock_1.BaseCodeBlock {
|
|
|
59
72
|
}
|
|
60
73
|
}
|
|
61
74
|
return propertyCode.join(constants_1.newLineChar);
|
|
62
|
-
})
|
|
75
|
+
})
|
|
76
|
+
.join(constants_1.newLineChar);
|
|
63
77
|
}
|
|
64
78
|
toString() {
|
|
65
79
|
const hasProperties = this.properties.length > 0;
|
|
@@ -71,10 +85,7 @@ class TypeCodeBlock extends BaseCodeBlock_1.BaseCodeBlock {
|
|
|
71
85
|
before.push(`// ${this.refName}`);
|
|
72
86
|
}
|
|
73
87
|
if (this.description) {
|
|
74
|
-
before = [
|
|
75
|
-
...before,
|
|
76
|
-
...helpers_1.joinCommentLines(0, this.description),
|
|
77
|
-
];
|
|
88
|
+
before = [...before, ...helpers_1.joinCommentLines(0, this.description)];
|
|
78
89
|
}
|
|
79
90
|
switch (this.type) {
|
|
80
91
|
case TypeScriptCodeTypes.Interface: {
|
|
@@ -83,15 +94,12 @@ class TypeCodeBlock extends BaseCodeBlock_1.BaseCodeBlock {
|
|
|
83
94
|
propertiesCode = '';
|
|
84
95
|
}
|
|
85
96
|
else {
|
|
86
|
-
propertiesCode = [
|
|
87
|
-
' // empty interface',
|
|
88
|
-
' [key: string]: any;',
|
|
89
|
-
].join(constants_1.newLineChar);
|
|
97
|
+
propertiesCode = [' // empty interface', ' [key: string]: any;'].join(constants_1.newLineChar);
|
|
90
98
|
}
|
|
91
99
|
}
|
|
92
|
-
const extendsInterfaces = Array.isArray(this.extendsInterfaces) && this.extendsInterfaces.length
|
|
93
|
-
this.extendsInterfaces.join(', ')
|
|
94
|
-
'';
|
|
100
|
+
const extendsInterfaces = Array.isArray(this.extendsInterfaces) && this.extendsInterfaces.length
|
|
101
|
+
? this.extendsInterfaces.join(', ')
|
|
102
|
+
: '';
|
|
95
103
|
code = [
|
|
96
104
|
utils_1.trimStringDoubleSpaces(`${exportKeyword} interface ${this.interfaceName} ${extendsInterfaces} {`),
|
|
97
105
|
propertiesCode,
|
|
@@ -121,11 +129,16 @@ class TypeCodeBlock extends BaseCodeBlock_1.BaseCodeBlock {
|
|
|
121
129
|
utils_1.trimStringDoubleSpaces(`${exportKeyword} type ${this.interfaceName} = ${this.value};`),
|
|
122
130
|
].join(constants_1.newLineChar);
|
|
123
131
|
break;
|
|
132
|
+
case TypeScriptCodeTypes.Const:
|
|
133
|
+
if (!this.value) {
|
|
134
|
+
log_1.consoleLogErrorAndExit(`"${this.interfaceName}" type has empty value`);
|
|
135
|
+
}
|
|
136
|
+
code = [
|
|
137
|
+
utils_1.trimStringDoubleSpaces(`${exportKeyword} const ${this.interfaceName} = ${this.value};`),
|
|
138
|
+
].join(constants_1.newLineChar);
|
|
139
|
+
break;
|
|
124
140
|
}
|
|
125
|
-
return [
|
|
126
|
-
before.join(constants_1.newLineChar),
|
|
127
|
-
code,
|
|
128
|
-
].join(constants_1.newLineChar).trim();
|
|
141
|
+
return [before.join(constants_1.newLineChar), code].join(constants_1.newLineChar).trim();
|
|
129
142
|
}
|
|
130
143
|
}
|
|
131
144
|
exports.TypeCodeBlock = TypeCodeBlock;
|
package/dist/generators/enums.js
CHANGED
|
@@ -46,10 +46,7 @@ function generateEnumAsUnionType(object) {
|
|
|
46
46
|
type: TypeCodeBlock_1.TypeScriptCodeTypes.Type,
|
|
47
47
|
refName: object.name,
|
|
48
48
|
interfaceName: helpers_1.getInterfaceName(object.name),
|
|
49
|
-
description: [
|
|
50
|
-
object.description,
|
|
51
|
-
description,
|
|
52
|
-
].join(constants_1.newLineChar),
|
|
49
|
+
description: [object.description, description].join(constants_1.newLineChar),
|
|
53
50
|
needExport: true,
|
|
54
51
|
properties: [],
|
|
55
52
|
value,
|
|
@@ -79,7 +76,7 @@ function getEnumNames(object) {
|
|
|
79
76
|
};
|
|
80
77
|
}
|
|
81
78
|
function generateInlineEnum(object, options = {}) {
|
|
82
|
-
const { isNumericEnum, enumNames, needEnumNamesDescription
|
|
79
|
+
const { isNumericEnum, enumNames, needEnumNamesDescription } = getEnumNames(object);
|
|
83
80
|
options = {
|
|
84
81
|
needEnumNamesConstant: isNumericEnum,
|
|
85
82
|
...options,
|
|
@@ -13,6 +13,7 @@ function normalizeMethodInfo(method) {
|
|
|
13
13
|
// For method params "boolean" type means 1 or 0
|
|
14
14
|
// Real "false" boolean value will be detected by API as true
|
|
15
15
|
if (parameter.type === 'boolean') {
|
|
16
|
+
// @ts-expect-error
|
|
16
17
|
delete parameter.type;
|
|
17
18
|
parameter.$ref = constants_1.baseBoolIntRef;
|
|
18
19
|
}
|
|
@@ -27,9 +28,9 @@ function normalizeMethodInfo(method) {
|
|
|
27
28
|
if (parameter.items && parameter.items.$ref) {
|
|
28
29
|
const ref = parameter.items?.$ref;
|
|
29
30
|
parameterRefs[ref] = types_1.RefsDictionaryType.Generate;
|
|
30
|
-
parameter.description +=
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
parameter.description +=
|
|
32
|
+
constants_1.newLineChar.repeat(2) +
|
|
33
|
+
[`@see ${helpers_1.getInterfaceName(helpers_1.getObjectNameByRef(ref))} (${ref})`].join(constants_1.newLineChar);
|
|
33
34
|
}
|
|
34
35
|
});
|
|
35
36
|
return {
|
package/dist/helpers.js
CHANGED
|
@@ -14,7 +14,7 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
14
14
|
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
15
|
if (mod && mod.__esModule) return mod;
|
|
16
16
|
var result = {};
|
|
17
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
18
|
__setModuleDefault(result, mod);
|
|
19
19
|
return result;
|
|
20
20
|
};
|
|
@@ -28,6 +28,7 @@ const path_1 = __importDefault(require("path"));
|
|
|
28
28
|
const utils_1 = require("./utils");
|
|
29
29
|
const constants_1 = require("./constants");
|
|
30
30
|
const log_1 = require("./log");
|
|
31
|
+
const prettier_1 = __importDefault(require("prettier"));
|
|
31
32
|
async function readJSONFile(path) {
|
|
32
33
|
const content = await fs_1.promises.readFile(path, 'utf-8');
|
|
33
34
|
return JSON.parse(content);
|
|
@@ -54,13 +55,27 @@ function prepareBuildDirectory(directoryPath) {
|
|
|
54
55
|
exports.prepareBuildDirectory = prepareBuildDirectory;
|
|
55
56
|
function writeFile(filePath, code, insertAutoGeneratedNote = true) {
|
|
56
57
|
if (insertAutoGeneratedNote) {
|
|
57
|
-
code =
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
58
|
+
code =
|
|
59
|
+
[
|
|
60
|
+
'/**',
|
|
61
|
+
" * This is auto-generated file, don't modify this file manually",
|
|
62
|
+
' */',
|
|
63
|
+
// '/* eslint-disable max-len */',
|
|
64
|
+
// '/* eslint-disable @typescript-eslint/no-empty-interface */',
|
|
65
|
+
].join(constants_1.newLineChar) +
|
|
66
|
+
constants_1.newLineChar.repeat(2) +
|
|
67
|
+
code.trim();
|
|
62
68
|
}
|
|
63
|
-
|
|
69
|
+
code = prettier_1.default.format(code, {
|
|
70
|
+
semi: true,
|
|
71
|
+
singleQuote: true,
|
|
72
|
+
trailingComma: 'all',
|
|
73
|
+
quoteProps: 'consistent',
|
|
74
|
+
parser: 'typescript',
|
|
75
|
+
});
|
|
76
|
+
fs_1.default.mkdirSync(filePath.replace(path_1.default.basename(filePath), ''), {
|
|
77
|
+
recursive: true,
|
|
78
|
+
});
|
|
64
79
|
fs_1.default.writeFileSync(filePath, code.trim() + constants_1.newLineChar);
|
|
65
80
|
}
|
|
66
81
|
exports.writeFile = writeFile;
|
|
@@ -68,7 +83,10 @@ function prepareMethodsPattern(methodsPattern) {
|
|
|
68
83
|
if (!methodsPattern) {
|
|
69
84
|
log_1.consoleLogErrorAndExit('methodsPattern is empty. Pass "*" to generate all methods');
|
|
70
85
|
}
|
|
71
|
-
return methodsPattern
|
|
86
|
+
return methodsPattern
|
|
87
|
+
.replace(/\s+/g, '')
|
|
88
|
+
.split(',')
|
|
89
|
+
.reduce((acc, pattern) => {
|
|
72
90
|
acc[pattern] = true;
|
|
73
91
|
return acc;
|
|
74
92
|
}, {});
|
|
@@ -93,17 +111,16 @@ function getMethodSection(methodName) {
|
|
|
93
111
|
}
|
|
94
112
|
exports.getMethodSection = getMethodSection;
|
|
95
113
|
function getInterfaceName(name) {
|
|
96
|
-
name = name
|
|
114
|
+
name = name
|
|
115
|
+
.replace(/\.|(\s+)|_/g, ' ')
|
|
97
116
|
.split(' ')
|
|
98
|
-
.map((v) => utils_1.capitalizeFirstLetter(v))
|
|
117
|
+
.map((v) => utils_1.capitalizeFirstLetter(v))
|
|
118
|
+
.join('');
|
|
99
119
|
return utils_1.capitalizeFirstLetter(name);
|
|
100
120
|
}
|
|
101
121
|
exports.getInterfaceName = getInterfaceName;
|
|
102
122
|
function getEnumPropertyName(name) {
|
|
103
|
-
return name.toUpperCase()
|
|
104
|
-
.replace(/\s+/g, '_')
|
|
105
|
-
.replace(/-/g, '_')
|
|
106
|
-
.replace(/\./g, '_');
|
|
123
|
+
return name.toUpperCase().replace(/\s+/g, '_').replace(/-/g, '_').replace(/\./g, '_');
|
|
107
124
|
}
|
|
108
125
|
exports.getEnumPropertyName = getEnumPropertyName;
|
|
109
126
|
function getObjectNameByRef(ref) {
|
|
@@ -124,7 +141,7 @@ function areQuotesNeededForProperty(name) {
|
|
|
124
141
|
if (isPatternProperty(name)) {
|
|
125
142
|
return false;
|
|
126
143
|
}
|
|
127
|
-
if (/[
|
|
144
|
+
if (/[&-]/.test(name)) {
|
|
128
145
|
return true;
|
|
129
146
|
}
|
|
130
147
|
return !(/^[a-z_]([a-z0-9_])+$/i.test(name) || /^[a-z_]/i.test(name));
|
|
@@ -147,10 +164,7 @@ function joinCommentLines(indent = 2, ...description) {
|
|
|
147
164
|
];
|
|
148
165
|
}
|
|
149
166
|
else if (Array.isArray(entry)) {
|
|
150
|
-
descriptionLines = [
|
|
151
|
-
...descriptionLines,
|
|
152
|
-
...entry,
|
|
153
|
-
];
|
|
167
|
+
descriptionLines = [...descriptionLines, ...entry];
|
|
154
168
|
}
|
|
155
169
|
});
|
|
156
170
|
descriptionLines = utils_1.trimArray(descriptionLines);
|
|
@@ -179,7 +193,7 @@ function joinOneOfValues(values, primitive) {
|
|
|
179
193
|
}
|
|
180
194
|
exports.joinOneOfValues = joinOneOfValues;
|
|
181
195
|
function formatArrayDepth(value, depth) {
|
|
182
|
-
if (value.endsWith('
|
|
196
|
+
if (value.endsWith("'") || value.includes('|')) {
|
|
183
197
|
return `Array<${value}>` + '[]'.repeat(depth - 1); // Need decrement depth value because of Array<T> has its own depth
|
|
184
198
|
}
|
|
185
199
|
else {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const helpers_1 = require("./helpers");
|
|
4
|
+
test('areQuotesNeededForProperty', () => {
|
|
5
|
+
expect(helpers_1.areQuotesNeededForProperty('user_id')).toBe(false);
|
|
6
|
+
expect(helpers_1.areQuotesNeededForProperty('uuid4')).toBe(false);
|
|
7
|
+
expect(helpers_1.areQuotesNeededForProperty('_foo')).toBe(false);
|
|
8
|
+
expect(helpers_1.areQuotesNeededForProperty('4uuid')).toBe(true);
|
|
9
|
+
expect(helpers_1.areQuotesNeededForProperty('user-id')).toBe(true);
|
|
10
|
+
expect(helpers_1.areQuotesNeededForProperty('user&id')).toBe(true);
|
|
11
|
+
expect(helpers_1.areQuotesNeededForProperty('идентификатор')).toBe(true);
|
|
12
|
+
});
|
package/dist/index.js
CHANGED
|
@@ -24,8 +24,8 @@ const helpMessage = `
|
|
|
24
24
|
|
|
25
25
|
${chalk_1.default.greenBright('--methods')} List of methods to generate responses and all needed objects.
|
|
26
26
|
Example:
|
|
27
|
-
- ${chalk_1.default.bold('
|
|
28
|
-
- ${chalk_1.default.bold('
|
|
27
|
+
- ${chalk_1.default.bold("'*'")} - to generate all responses and objects.
|
|
28
|
+
- ${chalk_1.default.bold("'messages.*, users.get, groups.isMember'")} - to generate all methods from messages section, users.get and groups.isMember.
|
|
29
29
|
`;
|
|
30
30
|
async function main() {
|
|
31
31
|
console.log(chalk_1.default.bold('VK API Schema TypeScript generator'));
|
|
@@ -52,7 +52,7 @@ async function main() {
|
|
|
52
52
|
schemaDir = path_1.default.resolve(schemaDir);
|
|
53
53
|
outDir = outDir ? path_1.default.resolve(outDir) : '';
|
|
54
54
|
// Read and check required schema files
|
|
55
|
-
const [methodsDefinitions, { definitions: responsesDefinitions }, { definitions: objectsDefinitions },] = await Promise.all([
|
|
55
|
+
const [methodsDefinitions, { definitions: responsesDefinitions }, { definitions: objectsDefinitions }, { errors: errorsDefinitions },] = await Promise.all([
|
|
56
56
|
helpers_1.readJSONFile(path_1.default.resolve(schemaDir, 'methods.json')),
|
|
57
57
|
helpers_1.readJSONFile(path_1.default.resolve(schemaDir, 'responses.json')),
|
|
58
58
|
helpers_1.readJSONFile(path_1.default.resolve(schemaDir, 'objects.json')),
|
|
@@ -77,6 +77,7 @@ async function main() {
|
|
|
77
77
|
methodsDefinitions,
|
|
78
78
|
objects: objectsDefinitions,
|
|
79
79
|
responses: responsesDefinitions,
|
|
80
|
+
errors: errorsDefinitions,
|
|
80
81
|
methodsPattern: methods.join(','),
|
|
81
82
|
});
|
|
82
83
|
generator.generate();
|
package/jest.config.js
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vkontakte/api-schema-typescript-generator",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "VK API TypeScript generator",
|
|
6
6
|
"author": {
|
|
@@ -23,7 +23,8 @@
|
|
|
23
23
|
],
|
|
24
24
|
"repository": "https://github.com/VKCOM/api-schema-typescript-generator",
|
|
25
25
|
"engines": {
|
|
26
|
-
"node": ">=12.0.0"
|
|
26
|
+
"node": ">=12.0.0",
|
|
27
|
+
"yarn": "^1.21.1"
|
|
27
28
|
},
|
|
28
29
|
"bin": {
|
|
29
30
|
"vk-api-schema-typescript-generator": "./bin/vk-api-schema-typescript-generator.js"
|
|
@@ -32,25 +33,30 @@
|
|
|
32
33
|
"clear": "rimraf dist/*",
|
|
33
34
|
"build": "yarn clear && tsc",
|
|
34
35
|
"watch": "yarn clear && tsc --watch",
|
|
35
|
-
"
|
|
36
|
+
"prettier": "prettier --write \"src/**/*.ts\"",
|
|
37
|
+
"test": "jest && tsc --noEmit && eslint src --ext .ts && yarn prettier"
|
|
36
38
|
},
|
|
37
39
|
"pre-commit": [
|
|
38
40
|
"test"
|
|
39
41
|
],
|
|
40
42
|
"dependencies": {
|
|
41
43
|
"arg": "^4.1.3",
|
|
42
|
-
"chalk": "4.1.0"
|
|
44
|
+
"chalk": "4.1.0",
|
|
45
|
+
"prettier": "^2.7.1"
|
|
43
46
|
},
|
|
44
47
|
"devDependencies": {
|
|
48
|
+
"@types/jest": "^28.1.5",
|
|
45
49
|
"@types/node": "^14.0.13",
|
|
46
|
-
"@typescript-eslint/eslint-plugin": "
|
|
47
|
-
"@typescript-eslint/parser": "
|
|
48
|
-
"@vkontakte/eslint-config": "
|
|
49
|
-
"eslint": "
|
|
50
|
-
"eslint-plugin-react": "7.
|
|
51
|
-
"eslint-plugin-react-hooks": "
|
|
50
|
+
"@typescript-eslint/eslint-plugin": "5.30.6",
|
|
51
|
+
"@typescript-eslint/parser": "5.30.6",
|
|
52
|
+
"@vkontakte/eslint-config": "3.1.0",
|
|
53
|
+
"eslint": "8.19.0",
|
|
54
|
+
"eslint-plugin-react": "7.30.1",
|
|
55
|
+
"eslint-plugin-react-hooks": "4.6.0",
|
|
56
|
+
"jest": "28.1.3",
|
|
52
57
|
"pre-commit": "1.2.2",
|
|
53
58
|
"rimraf": "^3.0.2",
|
|
54
|
-
"
|
|
59
|
+
"ts-jest": "^28.0.6",
|
|
60
|
+
"typescript": "4.3.5"
|
|
55
61
|
}
|
|
56
62
|
}
|