dtsgenerator 3.15.1 → 3.16.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/README.md +16 -11
- package/SupportedFeatures.md +1 -0
- package/dist/core/astBuilder.js +27 -26
- package/dist/core/config.d.ts +10 -6
- package/dist/core/dtsGenerator.js +2 -4
- package/dist/core/jsonSchema.js +7 -3
- package/dist/core/schemaId.js +7 -8
- package/dist/core/type.js +1 -1
- package/dist/jsonPointer.js +1 -1
- package/dist/utils.d.ts +3 -2
- package/package.json +83 -83
- package/src/commandOptions.ts +2 -2
- package/src/core/astBuilder.ts +26 -27
- package/src/core/config.ts +12 -6
- package/src/core/dtsGenerator.ts +3 -7
- package/src/core/jsonSchema.ts +13 -5
- package/src/core/schemaId.ts +7 -7
- package/src/core/type.ts +1 -1
- package/src/core/validateIdentifier.ts +4 -3
- package/src/jsonPointer.ts +6 -6
- package/src/utils.ts +5 -5
- package/tsconfig.json +1 -0
package/README.md
CHANGED
|
@@ -29,6 +29,7 @@ TypeScript d.ts file generator from JSON Schema file or OpenAPI(Swagger) spec fi
|
|
|
29
29
|
## Usage
|
|
30
30
|
|
|
31
31
|
### CLI
|
|
32
|
+
|
|
32
33
|
```sh
|
|
33
34
|
$ dtsgen --help
|
|
34
35
|
Usage: dtsgenerator [options] <file ... | file patterns using node-glob>
|
|
@@ -58,6 +59,7 @@ Examples:
|
|
|
58
59
|
For the configuration file, please refer to the file in the [config_sample](https://github.com/horiuchi/dtsgenerator/tree/master/config_sample/) directory.
|
|
59
60
|
|
|
60
61
|
### NodeJS API
|
|
62
|
+
|
|
61
63
|
```js
|
|
62
64
|
const { default: dtsgenerator, parseSchema } = require('dtsgenerator');
|
|
63
65
|
|
|
@@ -88,21 +90,20 @@ The dtsgenerator v3 has made the following braking changes from v2.
|
|
|
88
90
|
|
|
89
91
|
- Support Plug-in feature. See the Plug-in section for more information.
|
|
90
92
|
- Change the command line options.
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
93
|
+
- Remove the `--namespace` option. Use the `@dtsgenerator/replace-namespace` plug-in instead.
|
|
94
|
+
- Add the `--config` option. Mainly for setting up the Plug-in.
|
|
95
|
+
- And add more options.
|
|
94
96
|
- TypeScript AST is now used internally to generate type definitions.
|
|
95
97
|
|
|
96
|
-
|
|
97
98
|
## Plug-in
|
|
98
99
|
|
|
99
100
|
### How to find plug-in
|
|
100
101
|
|
|
101
|
-
- Search by npm: https://www.npmjs.com/search?q=dtsgenerator%20plugin
|
|
102
|
-
- Find by the @dtsgenerator repositories: https://github.com/dtsgenerator
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
102
|
+
- Search by npm: <https://www.npmjs.com/search?q=dtsgenerator%20plugin>
|
|
103
|
+
- Find by the @dtsgenerator repositories: <https://github.com/dtsgenerator>
|
|
104
|
+
- `@dtsgenerator/replace-namespace` : This plug-in is instead the `--namespace` option on old version.
|
|
105
|
+
- `@dtsgenerator/decorate-typename` : This plug-in can decorate the output type name.
|
|
106
|
+
- `@dtsgenerator/single-quote` : This plug-in replace the quote mark to single.
|
|
106
107
|
|
|
107
108
|
### How to create plug-in
|
|
108
109
|
|
|
@@ -122,8 +123,7 @@ The dtsgenerator v3 has made the following braking changes from v2.
|
|
|
122
123
|
|
|
123
124
|
Output debug message by [debug](https://www.npmjs.com/package/debug) library.
|
|
124
125
|
|
|
125
|
-
|
|
126
|
-
|
|
126
|
+
DEBUG=dtsgen dtsgen schema/news.json
|
|
127
127
|
|
|
128
128
|
### Links about JSON Schema and Swagger
|
|
129
129
|
|
|
@@ -143,6 +143,11 @@ Output debug message by [debug](https://www.npmjs.com/package/debug) library.
|
|
|
143
143
|
|
|
144
144
|
## ChangeLog
|
|
145
145
|
|
|
146
|
+
### [v3.16.0](https://github.com/horiuchi/dtsgenerator/releases/tag/v3.16.0) (2022-06-10)
|
|
147
|
+
|
|
148
|
+
- features:
|
|
149
|
+
- Support 'image/*' media types for #539. Thank you @Geloosa :+1:
|
|
150
|
+
|
|
146
151
|
### [v3.15.1](https://github.com/horiuchi/dtsgenerator/releases/tag/v3.15.1) (2022-03-10)
|
|
147
152
|
|
|
148
153
|
- fixed:
|
package/SupportedFeatures.md
CHANGED
package/dist/core/astBuilder.js
CHANGED
|
@@ -87,7 +87,7 @@ function buildTypeAliasNode(id, type, root) {
|
|
|
87
87
|
exports.buildTypeAliasNode = buildTypeAliasNode;
|
|
88
88
|
function buildPropertySignature(_schema, propertyName, valueType, required, isPattern) {
|
|
89
89
|
const modifiers = undefined;
|
|
90
|
-
const questionToken = required == null || required.
|
|
90
|
+
const questionToken = required == null || !required.includes(propertyName)
|
|
91
91
|
? ts.factory.createToken(ts.SyntaxKind.QuestionToken)
|
|
92
92
|
: undefined;
|
|
93
93
|
if (isPattern) {
|
|
@@ -147,7 +147,8 @@ function buildTupleTypeNode(types, minItems, maxItems, additionalItems) {
|
|
|
147
147
|
for (let i = 0; i < itemCount; i++) {
|
|
148
148
|
let node = typesIsArray(types)
|
|
149
149
|
? i < types.length
|
|
150
|
-
?
|
|
150
|
+
?
|
|
151
|
+
types[i]
|
|
151
152
|
: additionalItems !== undefined
|
|
152
153
|
? additionalItems === false
|
|
153
154
|
? buildNeverKeyword()
|
|
@@ -172,12 +173,17 @@ function buildTupleTypeNode(types, minItems, maxItems, additionalItems) {
|
|
|
172
173
|
exports.buildTupleTypeNode = buildTupleTypeNode;
|
|
173
174
|
function buildTypeReferenceNode(schema, currentSchema) {
|
|
174
175
|
const typeName = getTypename(schema.id, currentSchema);
|
|
175
|
-
|
|
176
|
-
|
|
176
|
+
let node;
|
|
177
|
+
for (const name of typeName) {
|
|
178
|
+
if (node == null) {
|
|
179
|
+
node = buildTypeNameIdentifier(name);
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
node = ts.factory.createQualifiedName(node, buildTypeNameIdentifier(name));
|
|
183
|
+
}
|
|
177
184
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
node = ts.factory.createQualifiedName(node, buildTypeNameIdentifier(typeName[i]));
|
|
185
|
+
if (node == null) {
|
|
186
|
+
throw new Error('TypeName array must not be empty.');
|
|
181
187
|
}
|
|
182
188
|
return ts.factory.createTypeReferenceNode(node, undefined);
|
|
183
189
|
}
|
|
@@ -185,29 +191,28 @@ exports.buildTypeReferenceNode = buildTypeReferenceNode;
|
|
|
185
191
|
function getTypename(id, baseSchema) {
|
|
186
192
|
const result = id.toNames();
|
|
187
193
|
const baseId = baseSchema.id;
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
break;
|
|
199
|
-
}
|
|
194
|
+
const baseTypes = baseId.toNames().slice(0, -1);
|
|
195
|
+
for (const type of baseTypes) {
|
|
196
|
+
if (result.length === 1) {
|
|
197
|
+
break;
|
|
198
|
+
}
|
|
199
|
+
if (result[0] === type) {
|
|
200
|
+
result.shift();
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
break;
|
|
200
204
|
}
|
|
201
205
|
}
|
|
202
206
|
return result;
|
|
203
207
|
}
|
|
204
208
|
function addComment(node, schema, terminate) {
|
|
209
|
+
var _a;
|
|
205
210
|
const comments = getComment(schema);
|
|
206
211
|
if (comments.length === 0) {
|
|
207
212
|
return node;
|
|
208
213
|
}
|
|
209
214
|
else if (!terminate && comments.length === 1) {
|
|
210
|
-
return ts.addSyntheticLeadingComment(node, ts.SyntaxKind.MultiLineCommentTrivia, ` ${comments[0]} `, false);
|
|
215
|
+
return ts.addSyntheticLeadingComment(node, ts.SyntaxKind.MultiLineCommentTrivia, ` ${(_a = comments[0]) !== null && _a !== void 0 ? _a : ''} `, false);
|
|
211
216
|
}
|
|
212
217
|
else {
|
|
213
218
|
let result = '*\n';
|
|
@@ -276,11 +281,7 @@ function addOptionalInformation(node, schema, terminate) {
|
|
|
276
281
|
}
|
|
277
282
|
exports.addOptionalInformation = addOptionalInformation;
|
|
278
283
|
function getLastTypeName(id) {
|
|
284
|
+
var _a;
|
|
279
285
|
const names = id.toNames();
|
|
280
|
-
|
|
281
|
-
return names[names.length - 1];
|
|
282
|
-
}
|
|
283
|
-
else {
|
|
284
|
-
return '';
|
|
285
|
-
}
|
|
286
|
+
return (_a = names[names.length - 1]) !== null && _a !== void 0 ? _a : '';
|
|
286
287
|
}
|
package/dist/core/config.d.ts
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import { ScriptTarget } from 'typescript';
|
|
2
2
|
export interface Config {
|
|
3
3
|
configFile?: string;
|
|
4
|
-
input:
|
|
5
|
-
files: string[];
|
|
6
|
-
urls: string[];
|
|
7
|
-
stdin: boolean;
|
|
8
|
-
};
|
|
4
|
+
input: InputConfig;
|
|
9
5
|
outputFile?: string;
|
|
10
6
|
target: ScriptTarget;
|
|
11
7
|
outputAST: boolean;
|
|
@@ -13,8 +9,16 @@ export interface Config {
|
|
|
13
9
|
[pluginName: string]: boolean | Record<string, unknown>;
|
|
14
10
|
};
|
|
15
11
|
}
|
|
12
|
+
interface InputConfig {
|
|
13
|
+
files: string[];
|
|
14
|
+
urls: string[];
|
|
15
|
+
stdin: boolean;
|
|
16
|
+
}
|
|
17
|
+
export declare type PartialConfig = Omit<Partial<Config>, 'input'> & {
|
|
18
|
+
input?: Partial<InputConfig>;
|
|
19
|
+
};
|
|
16
20
|
declare let config: Config;
|
|
17
|
-
export declare function setConfig(input:
|
|
21
|
+
export declare function setConfig(input: PartialConfig): void;
|
|
18
22
|
export declare function clearToDefault(): void;
|
|
19
23
|
export declare function showConfig(version: string, c: Config): Promise<void>;
|
|
20
24
|
export default config;
|
|
@@ -243,9 +243,6 @@ class DtsGenerator {
|
|
|
243
243
|
const content = schema.content;
|
|
244
244
|
if (content.$ref) {
|
|
245
245
|
const ref = this.resolver.dereference(content.$ref);
|
|
246
|
-
if (ref.id == null) {
|
|
247
|
-
throw new Error('target referenced id is nothing: ' + content.$ref);
|
|
248
|
-
}
|
|
249
246
|
const refSchema = this.normalizeContent(ref);
|
|
250
247
|
const node = ast.addOptionalInformation(ast.addComment(ast.buildTypeReferenceNode(refSchema, this.currentSchema), refSchema, false), refSchema, false);
|
|
251
248
|
return node;
|
|
@@ -280,6 +277,7 @@ class DtsGenerator {
|
|
|
280
277
|
}
|
|
281
278
|
}
|
|
282
279
|
checkExistOtherType(content, base) {
|
|
280
|
+
var _a;
|
|
283
281
|
const schema = Object.assign({}, base, { content });
|
|
284
282
|
const result = this.generateLiteralTypeProperty(schema, false);
|
|
285
283
|
if (result.kind === ts.SyntaxKind.AnyKeyword) {
|
|
@@ -288,7 +286,7 @@ class DtsGenerator {
|
|
|
288
286
|
else if (result.kind === ts.SyntaxKind.TypeLiteral) {
|
|
289
287
|
const node = result;
|
|
290
288
|
if (node.members.length === 1 &&
|
|
291
|
-
node.members[0].kind === ts.SyntaxKind.IndexSignature) {
|
|
289
|
+
((_a = node.members[0]) === null || _a === void 0 ? void 0 : _a.kind) === ts.SyntaxKind.IndexSignature) {
|
|
292
290
|
return undefined;
|
|
293
291
|
}
|
|
294
292
|
}
|
package/dist/core/jsonSchema.js
CHANGED
|
@@ -144,7 +144,9 @@ function searchAllSubSchema(schema, onFoundSchema, onFoundReference) {
|
|
|
144
144
|
}
|
|
145
145
|
Object.keys(obj).forEach((key) => {
|
|
146
146
|
const item = obj[key];
|
|
147
|
-
|
|
147
|
+
if (item != null) {
|
|
148
|
+
f(item, keys.concat(convertKeyToTypeName(key)));
|
|
149
|
+
}
|
|
148
150
|
});
|
|
149
151
|
}
|
|
150
152
|
function setSubIdToParameterObject(obj, keys) {
|
|
@@ -256,9 +258,11 @@ function searchAllSubSchema(schema, onFoundSchema, onFoundReference) {
|
|
|
256
258
|
return;
|
|
257
259
|
}
|
|
258
260
|
for (const mime of Object.keys(types)) {
|
|
259
|
-
if (/^text\/|^(?:application\/x-www-form-urlencoded$|^application\/([a-z0-9-_.]+\+)?json)$|^application\/octet-stream$|^application\/jwt$|^application\/vnd.apple.pkpass$|^multipart\/form-data
|
|
261
|
+
if (/^text\/|^(?:application\/x-www-form-urlencoded$|^application\/([a-z0-9-_.]+\+)?json)$|^application\/octet-stream$|^application\/jwt$|^application\/vnd.apple.pkpass$|^multipart\/form-data$|^image\//.test(mime)) {
|
|
260
262
|
const mt = types[mime];
|
|
261
|
-
|
|
263
|
+
if (mt != null) {
|
|
264
|
+
setSubId(mt.schema, keys);
|
|
265
|
+
}
|
|
262
266
|
}
|
|
263
267
|
}
|
|
264
268
|
}
|
package/dist/core/schemaId.js
CHANGED
|
@@ -5,7 +5,6 @@ const url = tslib_1.__importStar(require("url"));
|
|
|
5
5
|
const validateIdentifier_1 = require("./validateIdentifier");
|
|
6
6
|
class SchemaId {
|
|
7
7
|
constructor(inputId, parentIds) {
|
|
8
|
-
var _a;
|
|
9
8
|
this.inputId = inputId;
|
|
10
9
|
let absoluteId = url.resolve('', inputId);
|
|
11
10
|
if (parentIds) {
|
|
@@ -15,16 +14,16 @@ class SchemaId {
|
|
|
15
14
|
}
|
|
16
15
|
});
|
|
17
16
|
}
|
|
18
|
-
if (absoluteId.
|
|
17
|
+
if (!absoluteId.includes('#')) {
|
|
19
18
|
absoluteId += '#';
|
|
20
19
|
}
|
|
21
|
-
if (absoluteId.
|
|
22
|
-
absoluteId
|
|
23
|
-
absoluteId
|
|
20
|
+
if (!absoluteId.includes('://') &&
|
|
21
|
+
!absoluteId.startsWith('/') &&
|
|
22
|
+
!absoluteId.startsWith('#')) {
|
|
24
23
|
absoluteId = '/' + absoluteId;
|
|
25
24
|
}
|
|
26
25
|
this.id = url.parse(absoluteId);
|
|
27
|
-
this.absoluteId =
|
|
26
|
+
this.absoluteId = this.id.href;
|
|
28
27
|
}
|
|
29
28
|
getAbsoluteId() {
|
|
30
29
|
return this.absoluteId;
|
|
@@ -39,11 +38,11 @@ class SchemaId {
|
|
|
39
38
|
return this.absoluteId.replace(/#.*$/, '#');
|
|
40
39
|
}
|
|
41
40
|
existsJsonPointerHash() {
|
|
42
|
-
return this.absoluteId === '#' ||
|
|
41
|
+
return this.absoluteId === '#' || this.absoluteId.includes('#/');
|
|
43
42
|
}
|
|
44
43
|
getJsonPointerHash() {
|
|
45
44
|
const m = /(#\/.*)$/.exec(this.absoluteId);
|
|
46
|
-
if (m == null) {
|
|
45
|
+
if ((m === null || m === void 0 ? void 0 : m[1]) == null) {
|
|
47
46
|
return '#';
|
|
48
47
|
}
|
|
49
48
|
return decodeURIComponent(m[1]);
|
package/dist/core/type.js
CHANGED
|
@@ -82,7 +82,7 @@ async function loadPlugin(name, option) {
|
|
|
82
82
|
return undefined;
|
|
83
83
|
}
|
|
84
84
|
const mod = (await Promise.resolve().then(() => tslib_1.__importStar(require(name))));
|
|
85
|
-
if (!
|
|
85
|
+
if (!mod.default) {
|
|
86
86
|
console.warn(`The plugin (${name}) is invalid module. That is not default export format.`);
|
|
87
87
|
return undefined;
|
|
88
88
|
}
|
package/dist/jsonPointer.js
CHANGED
package/dist/utils.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
2
3
|
import glob from 'glob';
|
|
3
4
|
import { CommandOptions } from './commandOptions';
|
|
4
|
-
import {
|
|
5
|
+
import { PartialConfig } from './core/config';
|
|
5
6
|
export declare function readStream(stream: NodeJS.ReadableStream, encoding?: BufferEncoding): Promise<string>;
|
|
6
7
|
export declare function readUrl(url: string): Promise<string>;
|
|
7
8
|
export declare function buildProxyOptions(url: string): RequestInit | undefined;
|
|
8
9
|
export declare function globFiles(pattern: string, options?: glob.IOptions): Promise<string[]>;
|
|
9
|
-
export declare function readConfig(options: CommandOptions):
|
|
10
|
+
export declare function readConfig(options: CommandOptions): PartialConfig;
|
package/package.json
CHANGED
|
@@ -1,85 +1,85 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
2
|
+
"name": "dtsgenerator",
|
|
3
|
+
"version": "3.16.0",
|
|
4
|
+
"description": "TypeScript d.ts file generator for JSON Schema file",
|
|
5
|
+
"bin": {
|
|
6
|
+
"dtsgen": "bin/dtsgen"
|
|
7
|
+
},
|
|
8
|
+
"main": "dist/core/",
|
|
9
|
+
"typings": "dist/core/index.d.ts",
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc -p ./tsconfig-build.json",
|
|
12
|
+
"clean": "rimraf dist/ build/ {src,test}/**/*.{js,js.map} *.tsbuildinfo",
|
|
13
|
+
"compile": "tsc -p .",
|
|
14
|
+
"lint": "eslint --fix --ext ts src/ test/",
|
|
15
|
+
"format": "prettier --write 'src/**/*.ts' 'test/*.ts' 'test/core/*.ts'",
|
|
16
|
+
"precompile": "npm run lint && npm run format",
|
|
17
|
+
"prepublishOnly": "npm run build",
|
|
18
|
+
"pretest": "npm run compile",
|
|
19
|
+
"do-test": "cross-env TS_NODE_FILES=true mocha --exit --require ts-node/register --require source-map-support/register --colors test/*_test.ts test/**/*_test.ts",
|
|
20
|
+
"test": "nyc npm run do-test",
|
|
21
|
+
"test:update-snapshot": "UPDATE_SNAPSHOT=1 npm run test",
|
|
22
|
+
"coverage": "nyc report --reporter=lcov",
|
|
23
|
+
"prepare": "husky install"
|
|
24
|
+
},
|
|
25
|
+
"directories": {
|
|
26
|
+
"test": "test/"
|
|
27
|
+
},
|
|
28
|
+
"keywords": [
|
|
29
|
+
"TypeScript",
|
|
30
|
+
"JSON Schema",
|
|
31
|
+
"OpenAPI"
|
|
32
|
+
],
|
|
33
|
+
"author": "horiuchi",
|
|
34
|
+
"license": "MIT",
|
|
35
|
+
"homepage": "https://github.com/horiuchi/dtsgenerator",
|
|
36
|
+
"repository": {
|
|
37
|
+
"type": "git",
|
|
38
|
+
"url": "git@github.com:horiuchi/dtsgenerator.git"
|
|
39
|
+
},
|
|
40
|
+
"bugs": {
|
|
41
|
+
"url": "https://github.com/horiuchi/dtsgenerator/issues"
|
|
42
|
+
},
|
|
43
|
+
"engines": {
|
|
44
|
+
"node": ">= 10.0"
|
|
45
|
+
},
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"commander": "^9.3.0",
|
|
48
|
+
"cross-fetch": "^3.1.5",
|
|
49
|
+
"debug": "^4.3.4",
|
|
50
|
+
"glob": "^8.0.3",
|
|
51
|
+
"https-proxy-agent": "^5.0.1",
|
|
52
|
+
"js-yaml": "^4.1.0",
|
|
53
|
+
"tslib": "^2.4.0",
|
|
54
|
+
"typescript": "^4.7.3"
|
|
55
|
+
},
|
|
56
|
+
"devDependencies": {
|
|
57
|
+
"@dtsgenerator/do-nothing": "^2.5.2",
|
|
58
|
+
"@dtsgenerator/eslint-config": "^0.6.1",
|
|
59
|
+
"@dtsgenerator/replace-namespace": "^1.5.2",
|
|
60
|
+
"@dtsgenerator/single-quote": "^1.6.2",
|
|
61
|
+
"@istanbuljs/nyc-config-typescript": "^1.0.2",
|
|
62
|
+
"@types/debug": "^4.1.7",
|
|
63
|
+
"@types/glob": "^7.2.0",
|
|
64
|
+
"@types/js-yaml": "^4.0.5",
|
|
65
|
+
"@types/mkdirp": "^1.0.2",
|
|
66
|
+
"@types/mocha": "^9.1.1",
|
|
67
|
+
"@types/node": "^16.11.39",
|
|
68
|
+
"cross-env": "^7.0.3",
|
|
69
|
+
"eslint": "^8.17.0",
|
|
70
|
+
"husky": "^8.0.1",
|
|
71
|
+
"lint-staged": "^13.0.1",
|
|
72
|
+
"mocha": "^10.0.0",
|
|
73
|
+
"nyc": "^15.1.0",
|
|
74
|
+
"prettier": "^2.6.2",
|
|
75
|
+
"rimraf": "^3.0.2",
|
|
76
|
+
"source-map-support": "^0.5.21",
|
|
77
|
+
"ts-node": "^10.8.1"
|
|
78
|
+
},
|
|
79
|
+
"lint-staged": {
|
|
80
|
+
"**/*.ts": [
|
|
81
|
+
"prettier --write",
|
|
82
|
+
"eslint --fix"
|
|
83
|
+
]
|
|
84
|
+
}
|
|
85
85
|
}
|
package/src/commandOptions.ts
CHANGED
|
@@ -40,8 +40,8 @@ function parse(options: CommandOptions, argv: string[]): commander.Command {
|
|
|
40
40
|
return memo;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
44
|
-
const pkg:
|
|
43
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-unsafe-assignment
|
|
44
|
+
const pkg: { name: string; version: string } = require('../package.json');
|
|
45
45
|
|
|
46
46
|
// <hoge> is required, [hoge] is optional
|
|
47
47
|
program
|
package/src/core/astBuilder.ts
CHANGED
|
@@ -121,7 +121,7 @@ export function buildPropertySignature(
|
|
|
121
121
|
): ts.PropertySignature | ts.IndexSignatureDeclaration {
|
|
122
122
|
const modifiers = undefined;
|
|
123
123
|
const questionToken =
|
|
124
|
-
required == null || required.
|
|
124
|
+
required == null || !required.includes(propertyName)
|
|
125
125
|
? ts.factory.createToken(ts.SyntaxKind.QuestionToken)
|
|
126
126
|
: undefined;
|
|
127
127
|
if (isPattern) {
|
|
@@ -230,7 +230,8 @@ export function buildTupleTypeNode(
|
|
|
230
230
|
for (let i = 0; i < itemCount; i++) {
|
|
231
231
|
let node = typesIsArray(types)
|
|
232
232
|
? i < types.length
|
|
233
|
-
?
|
|
233
|
+
? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
234
|
+
types[i]!
|
|
234
235
|
: additionalItems !== undefined
|
|
235
236
|
? additionalItems === false
|
|
236
237
|
? buildNeverKeyword()
|
|
@@ -266,32 +267,34 @@ export function buildTypeReferenceNode(
|
|
|
266
267
|
currentSchema: Schema
|
|
267
268
|
): ts.TypeReferenceNode {
|
|
268
269
|
const typeName = getTypename(schema.id, currentSchema);
|
|
269
|
-
|
|
270
|
-
|
|
270
|
+
let node: ts.EntityName | undefined;
|
|
271
|
+
for (const name of typeName) {
|
|
272
|
+
if (node == null) {
|
|
273
|
+
node = buildTypeNameIdentifier(name);
|
|
274
|
+
} else {
|
|
275
|
+
node = ts.factory.createQualifiedName(
|
|
276
|
+
node,
|
|
277
|
+
buildTypeNameIdentifier(name)
|
|
278
|
+
);
|
|
279
|
+
}
|
|
271
280
|
}
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
node = ts.factory.createQualifiedName(
|
|
275
|
-
node,
|
|
276
|
-
buildTypeNameIdentifier(typeName[i])
|
|
277
|
-
);
|
|
281
|
+
if (node == null) {
|
|
282
|
+
throw new Error('TypeName array must not be empty.');
|
|
278
283
|
}
|
|
279
284
|
return ts.factory.createTypeReferenceNode(node, undefined);
|
|
280
285
|
}
|
|
281
286
|
function getTypename(id: SchemaId, baseSchema: Schema): string[] {
|
|
282
287
|
const result = id.toNames();
|
|
283
288
|
const baseId = baseSchema.id;
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
break;
|
|
294
|
-
}
|
|
289
|
+
const baseTypes = baseId.toNames().slice(0, -1);
|
|
290
|
+
for (const type of baseTypes) {
|
|
291
|
+
if (result.length === 1) {
|
|
292
|
+
break;
|
|
293
|
+
}
|
|
294
|
+
if (result[0] === type) {
|
|
295
|
+
result.shift();
|
|
296
|
+
} else {
|
|
297
|
+
break;
|
|
295
298
|
}
|
|
296
299
|
}
|
|
297
300
|
return result;
|
|
@@ -309,7 +312,7 @@ export function addComment<T extends ts.Node>(
|
|
|
309
312
|
return ts.addSyntheticLeadingComment(
|
|
310
313
|
node,
|
|
311
314
|
ts.SyntaxKind.MultiLineCommentTrivia,
|
|
312
|
-
` ${comments[0]} `,
|
|
315
|
+
` ${comments[0] ?? ''} `,
|
|
313
316
|
false
|
|
314
317
|
);
|
|
315
318
|
} else {
|
|
@@ -394,9 +397,5 @@ export function addOptionalInformation<T extends ts.Node>(
|
|
|
394
397
|
|
|
395
398
|
function getLastTypeName(id: SchemaId): string {
|
|
396
399
|
const names = id.toNames();
|
|
397
|
-
|
|
398
|
-
return names[names.length - 1];
|
|
399
|
-
} else {
|
|
400
|
-
return '';
|
|
401
|
-
}
|
|
400
|
+
return names[names.length - 1] ?? '';
|
|
402
401
|
}
|
package/src/core/config.ts
CHANGED
|
@@ -3,11 +3,7 @@ import { Plugin, loadPlugin } from './type';
|
|
|
3
3
|
|
|
4
4
|
export interface Config {
|
|
5
5
|
configFile?: string;
|
|
6
|
-
input:
|
|
7
|
-
files: string[];
|
|
8
|
-
urls: string[];
|
|
9
|
-
stdin: boolean;
|
|
10
|
-
};
|
|
6
|
+
input: InputConfig;
|
|
11
7
|
outputFile?: string;
|
|
12
8
|
target: ScriptTarget;
|
|
13
9
|
outputAST: boolean;
|
|
@@ -17,6 +13,16 @@ export interface Config {
|
|
|
17
13
|
};
|
|
18
14
|
}
|
|
19
15
|
|
|
16
|
+
interface InputConfig {
|
|
17
|
+
files: string[];
|
|
18
|
+
urls: string[];
|
|
19
|
+
stdin: boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export type PartialConfig = Omit<Partial<Config>, 'input'> & {
|
|
23
|
+
input?: Partial<InputConfig>;
|
|
24
|
+
};
|
|
25
|
+
|
|
20
26
|
const defaultConfig: Config = {
|
|
21
27
|
configFile: undefined,
|
|
22
28
|
input: {
|
|
@@ -32,7 +38,7 @@ const defaultConfig: Config = {
|
|
|
32
38
|
|
|
33
39
|
let config: Config = Object.assign({}, defaultConfig);
|
|
34
40
|
|
|
35
|
-
export function setConfig(input:
|
|
41
|
+
export function setConfig(input: PartialConfig): void {
|
|
36
42
|
config = Object.assign(config, input);
|
|
37
43
|
}
|
|
38
44
|
|
package/src/core/dtsGenerator.ts
CHANGED
|
@@ -57,7 +57,8 @@ export default class DtsGenerator {
|
|
|
57
57
|
|
|
58
58
|
const postProcess = await this.getPostProcess(plugins.post);
|
|
59
59
|
const result = ts.transform(file, postProcess);
|
|
60
|
-
|
|
60
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
61
|
+
const transformedNodes = result.transformed[0]!;
|
|
61
62
|
|
|
62
63
|
const transformedContent = config.outputAST
|
|
63
64
|
? JSON.stringify(transformedNodes, null, 2)
|
|
@@ -374,11 +375,6 @@ export default class DtsGenerator {
|
|
|
374
375
|
const content = schema.content;
|
|
375
376
|
if (content.$ref) {
|
|
376
377
|
const ref = this.resolver.dereference(content.$ref);
|
|
377
|
-
if (ref.id == null) {
|
|
378
|
-
throw new Error(
|
|
379
|
-
'target referenced id is nothing: ' + content.$ref
|
|
380
|
-
);
|
|
381
|
-
}
|
|
382
378
|
const refSchema = this.normalizeContent(ref);
|
|
383
379
|
const node = ast.addOptionalInformation(
|
|
384
380
|
ast.addComment(
|
|
@@ -448,7 +444,7 @@ export default class DtsGenerator {
|
|
|
448
444
|
const node = result as ts.TypeLiteralNode;
|
|
449
445
|
if (
|
|
450
446
|
node.members.length === 1 &&
|
|
451
|
-
node.members[0]
|
|
447
|
+
node.members[0]?.kind === ts.SyntaxKind.IndexSignature
|
|
452
448
|
) {
|
|
453
449
|
return undefined;
|
|
454
450
|
}
|
package/src/core/jsonSchema.ts
CHANGED
|
@@ -209,7 +209,9 @@ export function searchAllSubSchema(
|
|
|
209
209
|
}
|
|
210
210
|
Object.keys(obj).forEach((key) => {
|
|
211
211
|
const item = obj[key];
|
|
212
|
-
|
|
212
|
+
if (item != null) {
|
|
213
|
+
f(item, keys.concat(convertKeyToTypeName(key)));
|
|
214
|
+
}
|
|
213
215
|
});
|
|
214
216
|
}
|
|
215
217
|
|
|
@@ -272,6 +274,7 @@ export function searchAllSubSchema(
|
|
|
272
274
|
if ('$ref' in item) {
|
|
273
275
|
setSubId(item, keys.concat(key));
|
|
274
276
|
}
|
|
277
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
275
278
|
if ('type' in item && item.in !== undefined) {
|
|
276
279
|
setSubId(
|
|
277
280
|
item as JsonSchemaDraft04.Schema,
|
|
@@ -343,7 +346,8 @@ export function searchAllSubSchema(
|
|
|
343
346
|
}
|
|
344
347
|
const operationId = ops.operationId;
|
|
345
348
|
if (operationId) {
|
|
346
|
-
|
|
349
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
350
|
+
keys = [keys[0]!, convertKeyToTypeName(operationId)];
|
|
347
351
|
}
|
|
348
352
|
setSubIdToParameters(ops.parameters, keys.concat('parameters'));
|
|
349
353
|
setSubIdToResponsesV2(ops.responses, keys.concat('responses'));
|
|
@@ -379,12 +383,14 @@ export function searchAllSubSchema(
|
|
|
379
383
|
}
|
|
380
384
|
for (const mime of Object.keys(types)) {
|
|
381
385
|
if (
|
|
382
|
-
/^text\/|^(?:application\/x-www-form-urlencoded$|^application\/([a-z0-9-_.]+\+)?json)$|^application\/octet-stream$|^application\/jwt$|^application\/vnd.apple.pkpass$|^multipart\/form-data
|
|
386
|
+
/^text\/|^(?:application\/x-www-form-urlencoded$|^application\/([a-z0-9-_.]+\+)?json)$|^application\/octet-stream$|^application\/jwt$|^application\/vnd.apple.pkpass$|^multipart\/form-data$|^image\//.test(
|
|
383
387
|
mime
|
|
384
388
|
)
|
|
385
389
|
) {
|
|
386
390
|
const mt = types[mime];
|
|
387
|
-
|
|
391
|
+
if (mt != null) {
|
|
392
|
+
setSubId(mt.schema, keys);
|
|
393
|
+
}
|
|
388
394
|
}
|
|
389
395
|
}
|
|
390
396
|
}
|
|
@@ -443,7 +449,8 @@ export function searchAllSubSchema(
|
|
|
443
449
|
}
|
|
444
450
|
const operationId = ops.operationId;
|
|
445
451
|
if (operationId) {
|
|
446
|
-
|
|
452
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
453
|
+
keys = [keys[0]!, convertKeyToTypeName(operationId)];
|
|
447
454
|
}
|
|
448
455
|
setSubIdToParameters(ops.parameters, keys.concat('parameters'));
|
|
449
456
|
setSubIdToRequestBody(ops.requestBody, keys.concat('requestBody'));
|
|
@@ -579,6 +586,7 @@ export function selectSchemaType(content: JsonSchema | OpenApiSchema): {
|
|
|
579
586
|
}
|
|
580
587
|
}
|
|
581
588
|
}
|
|
589
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
582
590
|
if ('swagger' in content && content.swagger === '2.0') {
|
|
583
591
|
return {
|
|
584
592
|
type: 'Draft04',
|
package/src/core/schemaId.ts
CHANGED
|
@@ -15,18 +15,18 @@ export default class SchemaId {
|
|
|
15
15
|
}
|
|
16
16
|
});
|
|
17
17
|
}
|
|
18
|
-
if (absoluteId.
|
|
18
|
+
if (!absoluteId.includes('#')) {
|
|
19
19
|
absoluteId += '#';
|
|
20
20
|
}
|
|
21
21
|
if (
|
|
22
|
-
absoluteId.
|
|
23
|
-
absoluteId
|
|
24
|
-
absoluteId
|
|
22
|
+
!absoluteId.includes('://') &&
|
|
23
|
+
!absoluteId.startsWith('/') &&
|
|
24
|
+
!absoluteId.startsWith('#')
|
|
25
25
|
) {
|
|
26
26
|
absoluteId = '/' + absoluteId;
|
|
27
27
|
}
|
|
28
28
|
this.id = url.parse(absoluteId);
|
|
29
|
-
this.absoluteId = this.id.href
|
|
29
|
+
this.absoluteId = this.id.href;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
public getAbsoluteId(): string {
|
|
@@ -42,11 +42,11 @@ export default class SchemaId {
|
|
|
42
42
|
return this.absoluteId.replace(/#.*$/, '#');
|
|
43
43
|
}
|
|
44
44
|
public existsJsonPointerHash(): boolean {
|
|
45
|
-
return this.absoluteId === '#' ||
|
|
45
|
+
return this.absoluteId === '#' || this.absoluteId.includes('#/');
|
|
46
46
|
}
|
|
47
47
|
public getJsonPointerHash(): string {
|
|
48
48
|
const m = /(#\/.*)$/.exec(this.absoluteId);
|
|
49
|
-
if (m == null) {
|
|
49
|
+
if (m?.[1] == null) {
|
|
50
50
|
return '#';
|
|
51
51
|
}
|
|
52
52
|
return decodeURIComponent(m[1]);
|
package/src/core/type.ts
CHANGED
|
@@ -142,7 +142,7 @@ export async function loadPlugin(
|
|
|
142
142
|
}
|
|
143
143
|
|
|
144
144
|
const mod = (await import(name)) as { default?: Plugin };
|
|
145
|
-
if (!mod
|
|
145
|
+
if (!mod.default) {
|
|
146
146
|
console.warn(
|
|
147
147
|
`The plugin (${name}) is invalid module. That is not default export format.`
|
|
148
148
|
);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
1
2
|
import { ScriptTarget } from 'typescript';
|
|
2
3
|
|
|
3
4
|
// via. https://github.com/microsoft/TypeScript/blob/v3.7.5/src/services/codefixes/importFixes.ts#L689
|
|
@@ -752,7 +753,7 @@ const unicodeESNextIdentifierPart = [
|
|
|
752
753
|
|
|
753
754
|
function lookupInUnicodeMap(code: number, map: readonly number[]): boolean {
|
|
754
755
|
// Bail out quickly if it couldn't possibly be in the map.
|
|
755
|
-
if (code < map[0]) {
|
|
756
|
+
if (code < map[0]!) {
|
|
756
757
|
return false;
|
|
757
758
|
}
|
|
758
759
|
|
|
@@ -765,11 +766,11 @@ function lookupInUnicodeMap(code: number, map: readonly number[]): boolean {
|
|
|
765
766
|
mid = lo + (hi - lo) / 2;
|
|
766
767
|
// mid has to be even to catch a range's beginning
|
|
767
768
|
mid -= mid % 2;
|
|
768
|
-
if (map[mid] <= code && code <= map[mid + 1]) {
|
|
769
|
+
if (map[mid]! <= code && code <= map[mid + 1]!) {
|
|
769
770
|
return true;
|
|
770
771
|
}
|
|
771
772
|
|
|
772
|
-
if (code < map[mid]) {
|
|
773
|
+
if (code < map[mid]!) {
|
|
773
774
|
hi = mid;
|
|
774
775
|
} else {
|
|
775
776
|
lo = mid + 2;
|
package/src/jsonPointer.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
3
3
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
4
4
|
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
|
@@ -12,9 +12,9 @@ export function get(
|
|
|
12
12
|
return obj;
|
|
13
13
|
}
|
|
14
14
|
let o = obj;
|
|
15
|
-
const lastKey = path[path.length - 1]
|
|
15
|
+
const lastKey = path[path.length - 1]!;
|
|
16
16
|
for (let i = 0; i < path.length - 1; i++) {
|
|
17
|
-
const key = path[i]
|
|
17
|
+
const key = path[i]!;
|
|
18
18
|
let next = o[key];
|
|
19
19
|
if (next == null) {
|
|
20
20
|
if (isCreateOnNotExists) {
|
|
@@ -34,9 +34,9 @@ export function set(obj: any, path: string[], value: any): void {
|
|
|
34
34
|
return;
|
|
35
35
|
}
|
|
36
36
|
let o = obj;
|
|
37
|
-
const lastKey = path[path.length - 1]
|
|
37
|
+
const lastKey = path[path.length - 1]!;
|
|
38
38
|
for (let i = 0; i < path.length - 1; i++) {
|
|
39
|
-
const key = path[i]
|
|
39
|
+
const key = path[i]!;
|
|
40
40
|
let next = o[key];
|
|
41
41
|
if (next == null) {
|
|
42
42
|
next = {};
|
|
@@ -48,7 +48,7 @@ export function set(obj: any, path: string[], value: any): void {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
export function parse(s: string): string[] {
|
|
51
|
-
if (
|
|
51
|
+
if (s.startsWith('#')) {
|
|
52
52
|
s = s.substring(1);
|
|
53
53
|
}
|
|
54
54
|
const path = s.split('/');
|
package/src/utils.ts
CHANGED
|
@@ -4,7 +4,7 @@ import glob from 'glob';
|
|
|
4
4
|
import proxy from 'https-proxy-agent';
|
|
5
5
|
import { ScriptTarget } from 'typescript';
|
|
6
6
|
import { CommandOptions, defaultConfigFile } from './commandOptions';
|
|
7
|
-
import {
|
|
7
|
+
import { PartialConfig } from './core/config';
|
|
8
8
|
|
|
9
9
|
export function readStream(
|
|
10
10
|
stream: NodeJS.ReadableStream,
|
|
@@ -78,8 +78,8 @@ export function globFiles(
|
|
|
78
78
|
});
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
export function readConfig(options: CommandOptions):
|
|
82
|
-
let pc:
|
|
81
|
+
export function readConfig(options: CommandOptions): PartialConfig {
|
|
82
|
+
let pc: PartialConfig = {};
|
|
83
83
|
const configFile = options.configFile ?? defaultConfigFile;
|
|
84
84
|
try {
|
|
85
85
|
pc = loadJSON(configFile);
|
|
@@ -128,9 +128,9 @@ export function readConfig(options: CommandOptions): Partial<Config> {
|
|
|
128
128
|
pc.outputAST = !!options.outputAST;
|
|
129
129
|
return pc;
|
|
130
130
|
}
|
|
131
|
-
function loadJSON(file: string):
|
|
131
|
+
function loadJSON(file: string): PartialConfig {
|
|
132
132
|
const content = fs.readFileSync(file, 'utf-8');
|
|
133
|
-
return JSON.parse(content) as
|
|
133
|
+
return JSON.parse(content) as PartialConfig;
|
|
134
134
|
}
|
|
135
135
|
function convertToScriptTarget(target: string): ScriptTarget {
|
|
136
136
|
switch (target.trim().toLowerCase()) {
|
package/tsconfig.json
CHANGED
|
@@ -37,6 +37,7 @@
|
|
|
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
|
+
"noUncheckedIndexedAccess": true,
|
|
40
41
|
|
|
41
42
|
/* Module Resolution Options */
|
|
42
43
|
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|