@vkontakte/api-schema-typescript-generator 0.13.2 → 0.15.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 -0
- package/.github/CODEOWNERS +1 -2
- package/.github/dependabot.yml +17 -0
- package/.github/workflows/publish.yml +5 -3
- package/.github/workflows/pull_request.yml +4 -3
- package/.prettierrc.js +10 -0
- package/dist/generators/APITypingsGenerator.js +62 -57
- package/dist/generators/CommentCodeBlock.js +2 -9
- package/dist/generators/SchemaObject.js +5 -1
- package/dist/generators/TypeCodeBlock.js +22 -18
- package/dist/generators/enums.js +2 -5
- package/dist/generators/methods.js +3 -3
- package/dist/helpers.js +32 -20
- package/dist/index.js +4 -3
- package/package.json +6 -4
- package/src/generator.ts +5 -1
- package/src/generators/APITypingsGenerator.ts +104 -81
- 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 +3 -3
- package/src/generators/typeString.ts +4 -1
- package/src/helpers.ts +36 -23
- package/src/index.ts +15 -5
- package/src/types/schema.ts +7 -0
package/.eslintrc.json
CHANGED
package/.github/CODEOWNERS
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
.yarnrc @VKCOM/vk-sec
|
|
1
|
+
.github/dependabot.yml @VKCOM/vk-sec
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: 'npm'
|
|
4
|
+
directory: '/'
|
|
5
|
+
schedule:
|
|
6
|
+
interval: 'daily'
|
|
7
|
+
allow:
|
|
8
|
+
- dependency-type: 'direct'
|
|
9
|
+
reviewers:
|
|
10
|
+
- 'VKCOM/vk-sec'
|
|
11
|
+
|
|
12
|
+
- package-ecosystem: 'github-actions'
|
|
13
|
+
directory: '/'
|
|
14
|
+
schedule:
|
|
15
|
+
interval: 'daily'
|
|
16
|
+
reviewers:
|
|
17
|
+
- 'VKCOM/vk-sec'
|
|
@@ -11,13 +11,15 @@ jobs:
|
|
|
11
11
|
publish:
|
|
12
12
|
runs-on: ubuntu-latest
|
|
13
13
|
steps:
|
|
14
|
-
- uses: actions/checkout@
|
|
14
|
+
- uses: actions/checkout@v3
|
|
15
15
|
with:
|
|
16
16
|
token: ${{ secrets.DEVTOOLS_GITHUB_TOKEN }}
|
|
17
17
|
|
|
18
|
-
- uses: actions/setup-node@
|
|
18
|
+
- uses: actions/setup-node@v3
|
|
19
19
|
with:
|
|
20
|
-
node-version:
|
|
20
|
+
node-version: 18
|
|
21
|
+
cache: 'yarn'
|
|
22
|
+
always-auth: true
|
|
21
23
|
registry-url: 'https://registry.npmjs.org'
|
|
22
24
|
|
|
23
25
|
- run: yarn install --frozen-lockfile
|
|
@@ -6,11 +6,12 @@ jobs:
|
|
|
6
6
|
test:
|
|
7
7
|
runs-on: ubuntu-latest
|
|
8
8
|
steps:
|
|
9
|
-
- uses: actions/checkout@
|
|
9
|
+
- uses: actions/checkout@v3
|
|
10
10
|
|
|
11
|
-
- uses: actions/setup-node@
|
|
11
|
+
- uses: actions/setup-node@v3
|
|
12
12
|
with:
|
|
13
|
-
node-version:
|
|
13
|
+
node-version: 18
|
|
14
|
+
cache: 'yarn'
|
|
14
15
|
|
|
15
16
|
- run: yarn install --frozen-lockfile
|
|
16
17
|
|
package/.prettierrc.js
ADDED
|
@@ -26,13 +26,14 @@ 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 = {};
|
|
@@ -44,6 +45,7 @@ class APITypingsGenerator {
|
|
|
44
45
|
methodsList;
|
|
45
46
|
objects;
|
|
46
47
|
responses;
|
|
48
|
+
errors;
|
|
47
49
|
visitedRefs;
|
|
48
50
|
generatedObjects;
|
|
49
51
|
methodFilesMap;
|
|
@@ -80,10 +82,7 @@ class APITypingsGenerator {
|
|
|
80
82
|
...methodFile.imports,
|
|
81
83
|
...imports,
|
|
82
84
|
},
|
|
83
|
-
codeBlocks: [
|
|
84
|
-
...methodFile.codeBlocks,
|
|
85
|
-
...codeBlocks,
|
|
86
|
-
],
|
|
85
|
+
codeBlocks: [...methodFile.codeBlocks, ...codeBlocks],
|
|
87
86
|
};
|
|
88
87
|
}
|
|
89
88
|
collectAllOf(object, deep = 0) {
|
|
@@ -133,10 +132,7 @@ class APITypingsGenerator {
|
|
|
133
132
|
additionalProperties = this.getObjectProperties(refObject, deep + 1);
|
|
134
133
|
}
|
|
135
134
|
if (additionalProperties.length) {
|
|
136
|
-
properties = [
|
|
137
|
-
...properties,
|
|
138
|
-
...additionalProperties,
|
|
139
|
-
];
|
|
135
|
+
properties = [...properties, ...additionalProperties];
|
|
140
136
|
}
|
|
141
137
|
});
|
|
142
138
|
}
|
|
@@ -192,10 +188,7 @@ class APITypingsGenerator {
|
|
|
192
188
|
});
|
|
193
189
|
});
|
|
194
190
|
return {
|
|
195
|
-
codeBlocks: [
|
|
196
|
-
...codeBlocks,
|
|
197
|
-
codeBlock,
|
|
198
|
-
],
|
|
191
|
+
codeBlocks: [...codeBlocks, codeBlock],
|
|
199
192
|
imports,
|
|
200
193
|
value: '',
|
|
201
194
|
};
|
|
@@ -222,24 +215,26 @@ class APITypingsGenerator {
|
|
|
222
215
|
}
|
|
223
216
|
this.generatedObjects[object.name] = true;
|
|
224
217
|
let result = false;
|
|
225
|
-
if (
|
|
218
|
+
if (object.ref) {
|
|
226
219
|
result = this.getPrimitiveInterfaceCode(object);
|
|
227
220
|
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
221
|
+
else {
|
|
222
|
+
switch (object.type) {
|
|
223
|
+
case 'object':
|
|
224
|
+
result = this.getObjectInterfaceCode(object);
|
|
225
|
+
break;
|
|
226
|
+
case 'string':
|
|
227
|
+
case 'number':
|
|
228
|
+
case 'integer':
|
|
229
|
+
case 'array':
|
|
230
|
+
case 'boolean':
|
|
231
|
+
result = this.getPrimitiveInterfaceCode(object);
|
|
232
|
+
break;
|
|
233
|
+
default:
|
|
234
|
+
if (!result) {
|
|
235
|
+
log_1.consoleLogErrorAndExit(helpers_1.getInterfaceName(object.name), 'Unknown type of object', object);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
243
238
|
}
|
|
244
239
|
if (!result) {
|
|
245
240
|
log_1.consoleLogErrorAndExit('empty object result', object);
|
|
@@ -298,7 +293,9 @@ class APITypingsGenerator {
|
|
|
298
293
|
properties: [],
|
|
299
294
|
});
|
|
300
295
|
methodInfo.parameters.forEach((property) => {
|
|
301
|
-
const { imports: newImports, value, codeBlocks: newCodeBlocks, } = typeString_1.generateTypeString(property, this.objects, {
|
|
296
|
+
const { imports: newImports, value, codeBlocks: newCodeBlocks, } = typeString_1.generateTypeString(property, this.objects, {
|
|
297
|
+
needEnumNamesConstant: false,
|
|
298
|
+
});
|
|
302
299
|
imports = { ...imports, ...newImports };
|
|
303
300
|
codeBlocks = [...codeBlocks, ...newCodeBlocks];
|
|
304
301
|
codeBlock.addProperty({
|
|
@@ -323,12 +320,10 @@ class APITypingsGenerator {
|
|
|
323
320
|
let imports = {};
|
|
324
321
|
if (object.enum) {
|
|
325
322
|
const { codeBlocks: newCodeBlocks } = enums_1.generateEnumAsUnionType(object);
|
|
326
|
-
codeBlocks = [
|
|
327
|
-
...newCodeBlocks,
|
|
328
|
-
];
|
|
323
|
+
codeBlocks = [...newCodeBlocks];
|
|
329
324
|
}
|
|
330
325
|
else {
|
|
331
|
-
const { imports: newImports, value, codeBlocks: newCodeBlocks } = typeString_1.generateTypeString(object, this.objects);
|
|
326
|
+
const { imports: newImports, value, codeBlocks: newCodeBlocks, } = typeString_1.generateTypeString(object, this.objects);
|
|
332
327
|
const codeBlock = new TypeCodeBlock_1.TypeCodeBlock({
|
|
333
328
|
type: TypeCodeBlock_1.TypeScriptCodeTypes.Type,
|
|
334
329
|
refName: object.name,
|
|
@@ -339,11 +334,7 @@ class APITypingsGenerator {
|
|
|
339
334
|
value,
|
|
340
335
|
});
|
|
341
336
|
imports = newImports;
|
|
342
|
-
codeBlocks = [
|
|
343
|
-
...codeBlocks,
|
|
344
|
-
...newCodeBlocks,
|
|
345
|
-
codeBlock,
|
|
346
|
-
];
|
|
337
|
+
codeBlocks = [...codeBlocks, ...newCodeBlocks, codeBlock];
|
|
347
338
|
}
|
|
348
339
|
return {
|
|
349
340
|
codeBlocks,
|
|
@@ -352,26 +343,20 @@ class APITypingsGenerator {
|
|
|
352
343
|
};
|
|
353
344
|
}
|
|
354
345
|
getResponseCodeBlockAsType(object, response) {
|
|
355
|
-
const { imports, value, codeBlocks, description
|
|
346
|
+
const { imports, value, codeBlocks, description } = typeString_1.generateTypeString(response, this.objects, {
|
|
356
347
|
objectParentName: ' ', // TODO: Refactor
|
|
357
348
|
});
|
|
358
349
|
const codeBlock = new TypeCodeBlock_1.TypeCodeBlock({
|
|
359
350
|
type: TypeCodeBlock_1.TypeScriptCodeTypes.Type,
|
|
360
351
|
refName: object.name,
|
|
361
352
|
interfaceName: helpers_1.getInterfaceName(object.name),
|
|
362
|
-
description: [
|
|
363
|
-
object.description,
|
|
364
|
-
description || '',
|
|
365
|
-
].join(constants_1.newLineChar),
|
|
353
|
+
description: [object.description, description || ''].join(constants_1.newLineChar),
|
|
366
354
|
needExport: true,
|
|
367
355
|
properties: [],
|
|
368
356
|
value,
|
|
369
357
|
});
|
|
370
358
|
return {
|
|
371
|
-
codeBlocks: [
|
|
372
|
-
...codeBlocks,
|
|
373
|
-
codeBlock,
|
|
374
|
-
],
|
|
359
|
+
codeBlocks: [...codeBlocks, codeBlock],
|
|
375
360
|
imports,
|
|
376
361
|
value: '',
|
|
377
362
|
description,
|
|
@@ -441,13 +426,10 @@ class APITypingsGenerator {
|
|
|
441
426
|
// Comment with method name for visual sections in file
|
|
442
427
|
const methodNameComment = new CommentCodeBlock_1.CommentCodeBlock([methodName]);
|
|
443
428
|
if (method.description) {
|
|
444
|
-
methodNameComment.appendLines([
|
|
445
|
-
'',
|
|
446
|
-
method.description,
|
|
447
|
-
]);
|
|
429
|
+
methodNameComment.appendLines(['', method.description]);
|
|
448
430
|
}
|
|
449
431
|
this.appendToFileMap(section, {}, [methodNameComment]);
|
|
450
|
-
const { method: normalizedMethod, parameterRefs
|
|
432
|
+
const { method: normalizedMethod, parameterRefs } = methods_1.normalizeMethodInfo(method);
|
|
451
433
|
method = normalizedMethod;
|
|
452
434
|
this.generateObjectsFromRefs(parameterRefs);
|
|
453
435
|
this.generateMethodParams(new SchemaObject_1.SchemaObject(method.name, method));
|
|
@@ -473,13 +455,35 @@ class APITypingsGenerator {
|
|
|
473
455
|
this.registerExport(`./methods/${section}`, codeBlock.interfaceName);
|
|
474
456
|
}
|
|
475
457
|
});
|
|
476
|
-
const code = [
|
|
477
|
-
generator_1.generateImportsBlock(imports, null),
|
|
478
|
-
...codeBlocks,
|
|
479
|
-
];
|
|
458
|
+
const code = [generator_1.generateImportsBlock(imports, null), ...codeBlocks];
|
|
480
459
|
this.registerResultFile(path_1.default.join('methods', `${section}.ts`), code.join(constants_1.newLineChar.repeat(2)));
|
|
481
460
|
});
|
|
482
461
|
}
|
|
462
|
+
generateErrors() {
|
|
463
|
+
log_1.consoleLogInfo('creating errors...');
|
|
464
|
+
const code = [];
|
|
465
|
+
Object.entries(this.errors)
|
|
466
|
+
.reduce((acc, [name, error]) => {
|
|
467
|
+
acc.push({ name, ...error });
|
|
468
|
+
return acc;
|
|
469
|
+
}, [])
|
|
470
|
+
.sort((errorA, errorB) => {
|
|
471
|
+
return errorA.code - errorB.code;
|
|
472
|
+
})
|
|
473
|
+
.forEach((error) => {
|
|
474
|
+
const errorConstantName = error.name.toUpperCase();
|
|
475
|
+
code.push(new TypeCodeBlock_1.TypeCodeBlock({
|
|
476
|
+
type: TypeCodeBlock_1.TypeScriptCodeTypes.Const,
|
|
477
|
+
interfaceName: errorConstantName,
|
|
478
|
+
needExport: true,
|
|
479
|
+
value: String(error.code),
|
|
480
|
+
properties: [],
|
|
481
|
+
description: [error.description, error.$comment || ''].join(constants_1.newLineChar.repeat(2)),
|
|
482
|
+
}).toString());
|
|
483
|
+
this.registerExport('./common/errors', errorConstantName);
|
|
484
|
+
});
|
|
485
|
+
this.registerResultFile(path_1.default.join('common', 'errors.ts'), code.join(constants_1.newLineChar.repeat(2)));
|
|
486
|
+
}
|
|
483
487
|
createCommonTypes() {
|
|
484
488
|
log_1.consoleLogInfo('creating common types...');
|
|
485
489
|
const code = [];
|
|
@@ -545,6 +549,7 @@ class APITypingsGenerator {
|
|
|
545
549
|
generate() {
|
|
546
550
|
log_1.consoleLogInfo('generate');
|
|
547
551
|
this.generateMethods();
|
|
552
|
+
this.generateErrors();
|
|
548
553
|
if (this.needEmit) {
|
|
549
554
|
this.createCommonTypes();
|
|
550
555
|
this.createIndexExports();
|
|
@@ -10,18 +10,11 @@ class CommentCodeBlock extends BaseCodeBlock_1.BaseCodeBlock {
|
|
|
10
10
|
}
|
|
11
11
|
lines;
|
|
12
12
|
appendLines(lines) {
|
|
13
|
-
this.lines = [
|
|
14
|
-
...this.lines,
|
|
15
|
-
...lines,
|
|
16
|
-
];
|
|
13
|
+
this.lines = [...this.lines, ...lines];
|
|
17
14
|
}
|
|
18
15
|
toString() {
|
|
19
16
|
const inner = this.lines.map((line) => constants_1.spaceChar + `* ${line}`.trim());
|
|
20
|
-
return [
|
|
21
|
-
'/**',
|
|
22
|
-
...inner,
|
|
23
|
-
' */',
|
|
24
|
-
].join(constants_1.newLineChar);
|
|
17
|
+
return ['/**', ...inner, ' */'].join(constants_1.newLineChar);
|
|
25
18
|
}
|
|
26
19
|
}
|
|
27
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;
|
|
@@ -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) {
|
|
@@ -39,8 +40,11 @@ class TypeCodeBlock extends BaseCodeBlock_1.BaseCodeBlock {
|
|
|
39
40
|
this.properties.push(property);
|
|
40
41
|
}
|
|
41
42
|
getPropertiesCode() {
|
|
42
|
-
const quoteChar = this.properties.some((property) => helpers_1.areQuotesNeededForProperty(property.name))
|
|
43
|
-
|
|
43
|
+
const quoteChar = this.properties.some((property) => helpers_1.areQuotesNeededForProperty(property.name))
|
|
44
|
+
? "'"
|
|
45
|
+
: '';
|
|
46
|
+
return this.properties
|
|
47
|
+
.map((property) => {
|
|
44
48
|
let divider = '';
|
|
45
49
|
let lineEnd = '';
|
|
46
50
|
switch (this.type) {
|
|
@@ -68,7 +72,8 @@ class TypeCodeBlock extends BaseCodeBlock_1.BaseCodeBlock {
|
|
|
68
72
|
}
|
|
69
73
|
}
|
|
70
74
|
return propertyCode.join(constants_1.newLineChar);
|
|
71
|
-
})
|
|
75
|
+
})
|
|
76
|
+
.join(constants_1.newLineChar);
|
|
72
77
|
}
|
|
73
78
|
toString() {
|
|
74
79
|
const hasProperties = this.properties.length > 0;
|
|
@@ -80,10 +85,7 @@ class TypeCodeBlock extends BaseCodeBlock_1.BaseCodeBlock {
|
|
|
80
85
|
before.push(`// ${this.refName}`);
|
|
81
86
|
}
|
|
82
87
|
if (this.description) {
|
|
83
|
-
before = [
|
|
84
|
-
...before,
|
|
85
|
-
...helpers_1.joinCommentLines(0, this.description),
|
|
86
|
-
];
|
|
88
|
+
before = [...before, ...helpers_1.joinCommentLines(0, this.description)];
|
|
87
89
|
}
|
|
88
90
|
switch (this.type) {
|
|
89
91
|
case TypeScriptCodeTypes.Interface: {
|
|
@@ -92,15 +94,12 @@ class TypeCodeBlock extends BaseCodeBlock_1.BaseCodeBlock {
|
|
|
92
94
|
propertiesCode = '';
|
|
93
95
|
}
|
|
94
96
|
else {
|
|
95
|
-
propertiesCode = [
|
|
96
|
-
' // empty interface',
|
|
97
|
-
' [key: string]: any;',
|
|
98
|
-
].join(constants_1.newLineChar);
|
|
97
|
+
propertiesCode = [' // empty interface', ' [key: string]: any;'].join(constants_1.newLineChar);
|
|
99
98
|
}
|
|
100
99
|
}
|
|
101
|
-
const extendsInterfaces = Array.isArray(this.extendsInterfaces) && this.extendsInterfaces.length
|
|
102
|
-
this.extendsInterfaces.join(', ')
|
|
103
|
-
'';
|
|
100
|
+
const extendsInterfaces = Array.isArray(this.extendsInterfaces) && this.extendsInterfaces.length
|
|
101
|
+
? this.extendsInterfaces.join(', ')
|
|
102
|
+
: '';
|
|
104
103
|
code = [
|
|
105
104
|
utils_1.trimStringDoubleSpaces(`${exportKeyword} interface ${this.interfaceName} ${extendsInterfaces} {`),
|
|
106
105
|
propertiesCode,
|
|
@@ -130,11 +129,16 @@ class TypeCodeBlock extends BaseCodeBlock_1.BaseCodeBlock {
|
|
|
130
129
|
utils_1.trimStringDoubleSpaces(`${exportKeyword} type ${this.interfaceName} = ${this.value};`),
|
|
131
130
|
].join(constants_1.newLineChar);
|
|
132
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;
|
|
133
140
|
}
|
|
134
|
-
return [
|
|
135
|
-
before.join(constants_1.newLineChar),
|
|
136
|
-
code,
|
|
137
|
-
].join(constants_1.newLineChar).trim();
|
|
141
|
+
return [before.join(constants_1.newLineChar), code].join(constants_1.newLineChar).trim();
|
|
138
142
|
}
|
|
139
143
|
}
|
|
140
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,
|
|
@@ -28,9 +28,9 @@ function normalizeMethodInfo(method) {
|
|
|
28
28
|
if (parameter.items && parameter.items.$ref) {
|
|
29
29
|
const ref = parameter.items?.$ref;
|
|
30
30
|
parameterRefs[ref] = types_1.RefsDictionaryType.Generate;
|
|
31
|
-
parameter.description +=
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
parameter.description +=
|
|
32
|
+
constants_1.newLineChar.repeat(2) +
|
|
33
|
+
[`@see ${helpers_1.getInterfaceName(helpers_1.getObjectNameByRef(ref))} (${ref})`].join(constants_1.newLineChar);
|
|
34
34
|
}
|
|
35
35
|
});
|
|
36
36
|
return {
|
package/dist/helpers.js
CHANGED
|
@@ -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,15 +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
|
-
|
|
62
|
-
|
|
63
|
-
|
|
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();
|
|
64
68
|
}
|
|
65
|
-
|
|
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
|
+
});
|
|
66
79
|
fs_1.default.writeFileSync(filePath, code.trim() + constants_1.newLineChar);
|
|
67
80
|
}
|
|
68
81
|
exports.writeFile = writeFile;
|
|
@@ -70,7 +83,10 @@ function prepareMethodsPattern(methodsPattern) {
|
|
|
70
83
|
if (!methodsPattern) {
|
|
71
84
|
log_1.consoleLogErrorAndExit('methodsPattern is empty. Pass "*" to generate all methods');
|
|
72
85
|
}
|
|
73
|
-
return methodsPattern
|
|
86
|
+
return methodsPattern
|
|
87
|
+
.replace(/\s+/g, '')
|
|
88
|
+
.split(',')
|
|
89
|
+
.reduce((acc, pattern) => {
|
|
74
90
|
acc[pattern] = true;
|
|
75
91
|
return acc;
|
|
76
92
|
}, {});
|
|
@@ -95,17 +111,16 @@ function getMethodSection(methodName) {
|
|
|
95
111
|
}
|
|
96
112
|
exports.getMethodSection = getMethodSection;
|
|
97
113
|
function getInterfaceName(name) {
|
|
98
|
-
name = name
|
|
114
|
+
name = name
|
|
115
|
+
.replace(/\.|(\s+)|_/g, ' ')
|
|
99
116
|
.split(' ')
|
|
100
|
-
.map((v) => utils_1.capitalizeFirstLetter(v))
|
|
117
|
+
.map((v) => utils_1.capitalizeFirstLetter(v))
|
|
118
|
+
.join('');
|
|
101
119
|
return utils_1.capitalizeFirstLetter(name);
|
|
102
120
|
}
|
|
103
121
|
exports.getInterfaceName = getInterfaceName;
|
|
104
122
|
function getEnumPropertyName(name) {
|
|
105
|
-
return name.toUpperCase()
|
|
106
|
-
.replace(/\s+/g, '_')
|
|
107
|
-
.replace(/-/g, '_')
|
|
108
|
-
.replace(/\./g, '_');
|
|
123
|
+
return name.toUpperCase().replace(/\s+/g, '_').replace(/-/g, '_').replace(/\./g, '_');
|
|
109
124
|
}
|
|
110
125
|
exports.getEnumPropertyName = getEnumPropertyName;
|
|
111
126
|
function getObjectNameByRef(ref) {
|
|
@@ -149,10 +164,7 @@ function joinCommentLines(indent = 2, ...description) {
|
|
|
149
164
|
];
|
|
150
165
|
}
|
|
151
166
|
else if (Array.isArray(entry)) {
|
|
152
|
-
descriptionLines = [
|
|
153
|
-
...descriptionLines,
|
|
154
|
-
...entry,
|
|
155
|
-
];
|
|
167
|
+
descriptionLines = [...descriptionLines, ...entry];
|
|
156
168
|
}
|
|
157
169
|
});
|
|
158
170
|
descriptionLines = utils_1.trimArray(descriptionLines);
|
|
@@ -181,7 +193,7 @@ function joinOneOfValues(values, primitive) {
|
|
|
181
193
|
}
|
|
182
194
|
exports.joinOneOfValues = joinOneOfValues;
|
|
183
195
|
function formatArrayDepth(value, depth) {
|
|
184
|
-
if (value.endsWith('
|
|
196
|
+
if (value.endsWith("'") || value.includes('|')) {
|
|
185
197
|
return `Array<${value}>` + '[]'.repeat(depth - 1); // Need decrement depth value because of Array<T> has its own depth
|
|
186
198
|
}
|
|
187
199
|
else {
|
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vkontakte/api-schema-typescript-generator",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "VK API TypeScript generator",
|
|
6
6
|
"author": {
|
|
@@ -33,20 +33,22 @@
|
|
|
33
33
|
"clear": "rimraf dist/*",
|
|
34
34
|
"build": "yarn clear && tsc",
|
|
35
35
|
"watch": "yarn clear && tsc --watch",
|
|
36
|
-
"
|
|
36
|
+
"prettier": "prettier --write \"src/**/*.ts\"",
|
|
37
|
+
"test": "jest && tsc --noEmit && eslint src --ext .ts && yarn prettier"
|
|
37
38
|
},
|
|
38
39
|
"pre-commit": [
|
|
39
40
|
"test"
|
|
40
41
|
],
|
|
41
42
|
"dependencies": {
|
|
42
43
|
"arg": "^4.1.3",
|
|
43
|
-
"chalk": "4.1.0"
|
|
44
|
+
"chalk": "4.1.0",
|
|
45
|
+
"prettier": "^2.7.1"
|
|
44
46
|
},
|
|
45
47
|
"devDependencies": {
|
|
46
48
|
"@types/jest": "^28.1.5",
|
|
47
49
|
"@types/node": "^14.0.13",
|
|
48
50
|
"@typescript-eslint/eslint-plugin": "5.30.6",
|
|
49
|
-
"@typescript-eslint/parser": "5.
|
|
51
|
+
"@typescript-eslint/parser": "5.62.0",
|
|
50
52
|
"@vkontakte/eslint-config": "3.1.0",
|
|
51
53
|
"eslint": "8.19.0",
|
|
52
54
|
"eslint-plugin-react": "7.30.1",
|
package/src/generator.ts
CHANGED
|
@@ -3,7 +3,11 @@ import { getInterfaceName, getSectionFromObjectName } from './helpers';
|
|
|
3
3
|
import { Dictionary, ObjectType, RefsDictionary, RefsDictionaryType } from './types';
|
|
4
4
|
import { sortArrayAlphabetically, uniqueArray } from './utils';
|
|
5
5
|
|
|
6
|
-
export function generateImportsBlock(
|
|
6
|
+
export function generateImportsBlock(
|
|
7
|
+
refs: RefsDictionary,
|
|
8
|
+
section: string | null,
|
|
9
|
+
type?: ObjectType,
|
|
10
|
+
): string {
|
|
7
11
|
let importRefs = Object.entries(refs)
|
|
8
12
|
.filter(([, type]) => type === RefsDictionaryType.GenerateAndImport)
|
|
9
13
|
.map(([key]) => key);
|