swagger-typescript-api 10.0.3 → 11.0.0--alpha-1
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 +218 -0
- package/index.d.ts +93 -0
- package/index.js +230 -103
- package/package.json +121 -119
- package/src/code-formatter.js +101 -0
- package/src/code-gen-process.js +456 -0
- package/src/configuration.js +425 -0
- package/src/constants.js +14 -31
- package/src/index.js +6 -257
- package/src/schema-components-map.js +60 -0
- package/src/schema-parser/schema-formatters.js +145 -0
- package/src/schema-parser/schema-parser.js +497 -0
- package/src/schema-parser/schema-routes.js +902 -0
- package/src/swagger-schema-resolver.js +187 -0
- package/src/templates.js +141 -122
- package/src/translators/JavaScript.js +49 -49
- package/src/type-name.js +79 -0
- package/src/util/file-system.js +76 -0
- package/src/{utils → util}/id.js +0 -0
- package/src/util/internal-case.js +5 -0
- package/src/util/logger.js +100 -0
- package/src/{utils/resolveName.js → util/name-resolver.js} +1 -1
- package/src/util/object-assign.js +11 -0
- package/src/util/pascal-case.js +5 -0
- package/src/{utils → util}/random.js +1 -1
- package/templates/base/data-contract-jsdoc.ejs +29 -24
- package/templates/base/data-contracts.ejs +3 -3
- package/templates/base/interface-data-contract.ejs +1 -0
- package/templates/base/route-docs.ejs +2 -2
- package/templates/base/route-type.ejs +2 -2
- package/templates/default/route-types.ejs +2 -2
- package/templates/modular/api.ejs +2 -2
- package/templates/modular/route-types.ejs +2 -2
- package/src/apiConfig.js +0 -30
- package/src/common.js +0 -28
- package/src/components.js +0 -91
- package/src/config.js +0 -108
- package/src/filePrefix.js +0 -14
- package/src/files.js +0 -56
- package/src/formatFileContent.js +0 -81
- package/src/logger.js +0 -68
- package/src/modelNames.js +0 -74
- package/src/modelTypes.js +0 -31
- package/src/output.js +0 -165
- package/src/prettierOptions.js +0 -23
- package/src/render/utils/fmtToJSDocLine.js +0 -10
- package/src/render/utils/index.js +0 -31
- package/src/render/utils/templateRequire.js +0 -17
- package/src/routeNames.js +0 -46
- package/src/routes.js +0 -809
- package/src/schema.js +0 -474
- package/src/swagger.js +0 -152
- package/src/typeFormatters.js +0 -121
package/README.md
CHANGED
|
@@ -71,6 +71,8 @@ Options:
|
|
|
71
71
|
--clean-output clean output folder before generate api. WARNING: May cause data loss (default: false)
|
|
72
72
|
--api-class-name <string> name of the api class
|
|
73
73
|
--patch fix up small errors in the swagger source definition (default: false)
|
|
74
|
+
--debug additional information about processes inside this tool (default: false)
|
|
75
|
+
--another-array-type generate array types as Array<Type> (by default Type[]) (default: false)
|
|
74
76
|
-h, --help display help for command
|
|
75
77
|
```
|
|
76
78
|
|
|
@@ -122,6 +124,17 @@ generateApi({
|
|
|
122
124
|
generateUnionEnums: false,
|
|
123
125
|
addReadonly: false,
|
|
124
126
|
extraTemplates: [],
|
|
127
|
+
anotherArrayType: false,
|
|
128
|
+
codeGenConstructs: (constructs) => ({
|
|
129
|
+
...constructs,
|
|
130
|
+
RecordType: (key, value) => `MyRecord<key, value>`
|
|
131
|
+
}),
|
|
132
|
+
primitiveTypeConstructs: (constructs) => ({
|
|
133
|
+
...constructs,
|
|
134
|
+
string: {
|
|
135
|
+
'date-time': 'Date'
|
|
136
|
+
}
|
|
137
|
+
}),
|
|
125
138
|
hooks: {
|
|
126
139
|
onCreateComponent: (component) => {},
|
|
127
140
|
onCreateRequestParams: (rawType) => {},
|
|
@@ -203,8 +216,213 @@ When we change it to `--module-name-index 1` then Api class have two properties
|
|
|
203
216
|
This option will group your API operations based on their first tag - mirroring how the Swagger UI groups displayed operations
|
|
204
217
|
|
|
205
218
|
|
|
219
|
+
## Modification internal codegen structs with NodeJS API:
|
|
220
|
+
|
|
221
|
+
You are able to modify TypeScript internal structs using for generating output with using `generateApi` options `codeGenConstructs` and `primitiveTypeConstructs`.
|
|
222
|
+
|
|
223
|
+
### `codeGenConstructs`
|
|
224
|
+
|
|
225
|
+
This option has type `(struct: CodeGenConstruct) => Partial<CodeGenConstruct>`.
|
|
226
|
+
|
|
227
|
+
```ts
|
|
228
|
+
generateApi({
|
|
229
|
+
// ...
|
|
230
|
+
codeGenConstructs: (struct) => ({
|
|
231
|
+
Keyword: {
|
|
232
|
+
Number: "number",
|
|
233
|
+
String: "string",
|
|
234
|
+
Boolean: "boolean",
|
|
235
|
+
Any: "any",
|
|
236
|
+
Void: "void",
|
|
237
|
+
Unknown: "unknown",
|
|
238
|
+
Null: "null",
|
|
239
|
+
Undefined: "undefined",
|
|
240
|
+
Object: "object",
|
|
241
|
+
File: "File",
|
|
242
|
+
Date: "Date",
|
|
243
|
+
Type: "type",
|
|
244
|
+
Enum: "enum",
|
|
245
|
+
Interface: "interface",
|
|
246
|
+
Array: "Array",
|
|
247
|
+
Record: "Record",
|
|
248
|
+
Intersection: "&",
|
|
249
|
+
Union: "|",
|
|
250
|
+
},
|
|
251
|
+
CodeGenKeyword: {
|
|
252
|
+
UtilRequiredKeys: "UtilRequiredKeys",
|
|
253
|
+
},
|
|
254
|
+
/**
|
|
255
|
+
* $A[] or Array<$A>
|
|
256
|
+
*/
|
|
257
|
+
ArrayType: (content) => {
|
|
258
|
+
if (this.anotherArrayType) {
|
|
259
|
+
return `Array<${content}>`;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
return `(${content})[]`;
|
|
263
|
+
},
|
|
264
|
+
/**
|
|
265
|
+
* "$A"
|
|
266
|
+
*/
|
|
267
|
+
StringValue: (content) => `"${content}"`,
|
|
268
|
+
/**
|
|
269
|
+
* $A
|
|
270
|
+
*/
|
|
271
|
+
BooleanValue: (content) => `${content}`,
|
|
272
|
+
/**
|
|
273
|
+
* $A
|
|
274
|
+
*/
|
|
275
|
+
NumberValue: (content) => `${content}`,
|
|
276
|
+
/**
|
|
277
|
+
* $A
|
|
278
|
+
*/
|
|
279
|
+
NullValue: (content) => content,
|
|
280
|
+
/**
|
|
281
|
+
* $A1 | $A2
|
|
282
|
+
*/
|
|
283
|
+
UnionType: (contents) => _.join(_.uniq(contents), ` | `),
|
|
284
|
+
/**
|
|
285
|
+
* ($A1)
|
|
286
|
+
*/
|
|
287
|
+
ExpressionGroup: (content) => (content ? `(${content})` : ""),
|
|
288
|
+
/**
|
|
289
|
+
* $A1 & $A2
|
|
290
|
+
*/
|
|
291
|
+
IntersectionType: (contents) => _.join(_.uniq(contents), ` & `),
|
|
292
|
+
/**
|
|
293
|
+
* Record<$A1, $A2>
|
|
294
|
+
*/
|
|
295
|
+
RecordType: (key, value) => `Record<${key}, ${value}>`,
|
|
296
|
+
/**
|
|
297
|
+
* readonly $key?:$value
|
|
298
|
+
*/
|
|
299
|
+
TypeField: ({ readonly, key, optional, value }) =>
|
|
300
|
+
_.compact([readonly && "readonly ", key, optional && "?", ": ", value]).join(""),
|
|
301
|
+
/**
|
|
302
|
+
* [key: $A1]: $A2
|
|
303
|
+
*/
|
|
304
|
+
InterfaceDynamicField: (key, value) => `[key: ${key}]: ${value}`,
|
|
305
|
+
/**
|
|
306
|
+
* $A1 = $A2
|
|
307
|
+
*/
|
|
308
|
+
EnumField: (key, value) => `${key} = ${value}`,
|
|
309
|
+
/**
|
|
310
|
+
* $A0.key = $A0.value,
|
|
311
|
+
* $A1.key = $A1.value,
|
|
312
|
+
* $AN.key = $AN.value,
|
|
313
|
+
*/
|
|
314
|
+
EnumFieldsWrapper: (contents) =>
|
|
315
|
+
_.map(contents, ({ key, value }) => ` ${key} = ${value}`).join(",\n"),
|
|
316
|
+
/**
|
|
317
|
+
* {\n $A \n}
|
|
318
|
+
*/
|
|
319
|
+
ObjectWrapper: (content) => `{\n${content}\n}`,
|
|
320
|
+
/**
|
|
321
|
+
* /** $A *\/
|
|
322
|
+
*/
|
|
323
|
+
MultilineComment: (contents, formatFn) =>
|
|
324
|
+
[
|
|
325
|
+
...(contents.length === 1
|
|
326
|
+
? [`/** ${contents[0]} */`]
|
|
327
|
+
: ["/**", ...contents.map((content) => ` * ${content}`), " */"]),
|
|
328
|
+
].map((part) => `${formatFn ? formatFn(part) : part}\n`),
|
|
329
|
+
/**
|
|
330
|
+
* $A1<...$A2.join(,)>
|
|
331
|
+
*/
|
|
332
|
+
TypeWithGeneric: (typeName, genericArgs) => {
|
|
333
|
+
return `${typeName}${genericArgs.length ? `<${genericArgs.join(",")}>` : ""}`;
|
|
334
|
+
},
|
|
335
|
+
})
|
|
336
|
+
})
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
For example, if you need to generate output `Record<string, any>` instead of `object` you can do it with using following code:
|
|
340
|
+
|
|
341
|
+
```ts
|
|
342
|
+
generateApi({
|
|
343
|
+
// ...
|
|
344
|
+
codeGenConstructs: (struct) => ({
|
|
345
|
+
Keyword: {
|
|
346
|
+
Object: "Record<string, any>",
|
|
347
|
+
}
|
|
348
|
+
})
|
|
349
|
+
})
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
### `primitiveTypeConstructs`
|
|
353
|
+
|
|
354
|
+
It is type mapper or translator swagger schema objects. `primitiveTypeConstructs` translates `type`/`format` schema fields to typescript structs.
|
|
355
|
+
This option has type
|
|
356
|
+
```ts
|
|
357
|
+
type PrimitiveTypeStructValue =
|
|
358
|
+
| string
|
|
359
|
+
| ((schema: Record<string, any>, parser: import("./src/schema-parser/schema-parser").SchemaParser) => string);
|
|
360
|
+
|
|
361
|
+
type PrimitiveTypeStruct = Record<
|
|
362
|
+
"integer" | "number" | "boolean" | "object" | "file" | "string" | "array",
|
|
363
|
+
string | ({ $default: PrimitiveTypeStructValue } & Record<string, PrimitiveTypeStructValue>)
|
|
364
|
+
>
|
|
365
|
+
|
|
366
|
+
declare const primitiveTypeConstructs: (struct: PrimitiveTypeStruct) => Partial<PrimitiveTypeStruct>
|
|
367
|
+
|
|
368
|
+
generateApi({
|
|
369
|
+
// ...
|
|
370
|
+
primitiveTypeConstructs: (struct) => ({
|
|
371
|
+
integer: () => "number",
|
|
372
|
+
number: () => "number",
|
|
373
|
+
boolean: () => "boolean",
|
|
374
|
+
object: () => "object",
|
|
375
|
+
file: () => "File",
|
|
376
|
+
string: {
|
|
377
|
+
$default: () => "string",
|
|
378
|
+
|
|
379
|
+
/** formats */
|
|
380
|
+
binary: () => "File",
|
|
381
|
+
file: () => "File",
|
|
382
|
+
"date-time": () => "string",
|
|
383
|
+
time: () => "string",
|
|
384
|
+
date: () => "string",
|
|
385
|
+
duration: () => "string",
|
|
386
|
+
email: () => "string",
|
|
387
|
+
"idn-email": () => "string",
|
|
388
|
+
"idn-hostname": () => "string",
|
|
389
|
+
ipv4: () => "string",
|
|
390
|
+
ipv6: () => "string",
|
|
391
|
+
uuid: () => "string",
|
|
392
|
+
uri: () => "string",
|
|
393
|
+
"uri-reference": () => "string",
|
|
394
|
+
"uri-template": () => "string",
|
|
395
|
+
"json-pointer": () => "string",
|
|
396
|
+
"relative-json-pointer": () => "string",
|
|
397
|
+
regex: () => "string",
|
|
398
|
+
},
|
|
399
|
+
array: (schema, parser) => {
|
|
400
|
+
const content = parser.getInlineParseContent(schema.items);
|
|
401
|
+
return parser.checkAndAddNull(schema, `(${content})[]`);
|
|
402
|
+
},
|
|
403
|
+
})
|
|
404
|
+
})
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
For example, if you need to change `"string"/"date-time"` default output as `string` to `Date` you can do it with using following code:
|
|
408
|
+
|
|
409
|
+
```ts
|
|
410
|
+
|
|
411
|
+
generateApi({
|
|
412
|
+
primitiveTypeConstructs: (struct) => ({
|
|
413
|
+
string: {
|
|
414
|
+
"date-time": "Date",
|
|
415
|
+
},
|
|
416
|
+
})
|
|
417
|
+
})
|
|
418
|
+
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
See more about [swagger schema type/format data here](https://json-schema.org/understanding-json-schema/reference/string.html#dates-and-times)
|
|
422
|
+
|
|
206
423
|
## 📄 Mass media
|
|
207
424
|
|
|
425
|
+
- [5 Lessons learned about swagger-typescript-api](https://christo8989.medium.com/5-lessons-learned-about-swagger-typescript-api-511240b34c1)
|
|
208
426
|
- [Why Swagger schemes are needed in frontend development ?](https://dev.to/js2me/why-swagger-schemes-are-needed-in-frontend-development-2cb4)
|
|
209
427
|
- [Migration en douceur vers TypeScript (French)](https://www.premieroctet.com/blog/migration-typescript/)
|
|
210
428
|
- [swagger-typescript-api usage (Japanese)](https://zenn.dev/watahaya/articles/2f4a716c47903b)
|
package/index.d.ts
CHANGED
|
@@ -127,8 +127,63 @@ interface GenerateApiParamsBase {
|
|
|
127
127
|
* generate readonly properties (default: false)
|
|
128
128
|
*/
|
|
129
129
|
addReadonly?: boolean;
|
|
130
|
+
|
|
131
|
+
primitiveTypeConstructs?: (struct: PrimitiveTypeStruct) => Partial<PrimitiveTypeStruct>;
|
|
132
|
+
|
|
133
|
+
codeGenConstructs?: (struct: CodeGenConstruct) => Partial<CodeGenConstruct>;
|
|
130
134
|
}
|
|
131
135
|
|
|
136
|
+
type CodeGenConstruct = {
|
|
137
|
+
Keyword: {
|
|
138
|
+
Number: string;
|
|
139
|
+
String: string;
|
|
140
|
+
Boolean: string;
|
|
141
|
+
Any: string;
|
|
142
|
+
Void: string;
|
|
143
|
+
Unknown: string;
|
|
144
|
+
Null: string;
|
|
145
|
+
Undefined: string;
|
|
146
|
+
Object: string;
|
|
147
|
+
File: string;
|
|
148
|
+
Date: string;
|
|
149
|
+
Type: string;
|
|
150
|
+
Enum: string;
|
|
151
|
+
Interface: string;
|
|
152
|
+
Array: string;
|
|
153
|
+
Record: string;
|
|
154
|
+
Intersection: string;
|
|
155
|
+
Union: string;
|
|
156
|
+
};
|
|
157
|
+
CodeGenKeyword: {
|
|
158
|
+
UtilRequiredKeys: string;
|
|
159
|
+
};
|
|
160
|
+
ArrayType: (content: any) => string;
|
|
161
|
+
StringValue: (content: any) => string;
|
|
162
|
+
BooleanValue: (content: any) => string;
|
|
163
|
+
NumberValue: (content: any) => string;
|
|
164
|
+
NullValue: (content: any) => string;
|
|
165
|
+
UnionType: (content: any) => string;
|
|
166
|
+
ExpressionGroup: (content: any) => string;
|
|
167
|
+
IntersectionType: (content: any) => string;
|
|
168
|
+
RecordType: (content: any) => string;
|
|
169
|
+
TypeField: (content: any) => string;
|
|
170
|
+
InterfaceDynamicField: (content: any) => string;
|
|
171
|
+
EnumField: (content: any) => string;
|
|
172
|
+
EnumFieldsWrapper: (content: any) => string;
|
|
173
|
+
ObjectWrapper: (content: any) => string;
|
|
174
|
+
MultilineComment: (content: any) => string;
|
|
175
|
+
TypeWithGeneric: (content: any) => string;
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
type PrimitiveTypeStructValue =
|
|
179
|
+
| string
|
|
180
|
+
| ((schema: Record<string, any>, parser: import("./src/schema-parser/schema-parser").SchemaParser) => string);
|
|
181
|
+
|
|
182
|
+
type PrimitiveTypeStruct = Record<
|
|
183
|
+
"integer" | "number" | "boolean" | "object" | "file" | "string" | "array",
|
|
184
|
+
string | ({ $default: PrimitiveTypeStructValue } & Record<string, PrimitiveTypeStructValue>)
|
|
185
|
+
>;
|
|
186
|
+
|
|
132
187
|
interface GenerateApiParamsFromPath extends GenerateApiParamsBase {
|
|
133
188
|
/**
|
|
134
189
|
* path to swagger schema
|
|
@@ -324,6 +379,12 @@ export interface GenerateApiConfiguration {
|
|
|
324
379
|
hasDescription: boolean;
|
|
325
380
|
};
|
|
326
381
|
config: {
|
|
382
|
+
input: string;
|
|
383
|
+
output: string;
|
|
384
|
+
url: string;
|
|
385
|
+
spec: any;
|
|
386
|
+
fileName: string;
|
|
387
|
+
authorizationToken?: string;
|
|
327
388
|
generateResponses: boolean;
|
|
328
389
|
defaultResponseAsSuccess: boolean;
|
|
329
390
|
generateRouteTypes: boolean;
|
|
@@ -335,10 +396,35 @@ export interface GenerateApiConfiguration {
|
|
|
335
396
|
convertedFromSwagger2: boolean;
|
|
336
397
|
moduleNameIndex: number;
|
|
337
398
|
moduleNameFirstTag: boolean;
|
|
399
|
+
extraTemplates: { name: string; path: string }[];
|
|
338
400
|
disableStrictSSL: boolean;
|
|
339
401
|
disableProxy: boolean;
|
|
340
402
|
extractRequestParams: boolean;
|
|
341
403
|
unwrapResponseData: boolean;
|
|
404
|
+
sortTypes: boolean;
|
|
405
|
+
singleHttpClient: boolean;
|
|
406
|
+
typePrefix: string;
|
|
407
|
+
typeSuffix: string;
|
|
408
|
+
patch: boolean;
|
|
409
|
+
cleanOutput: boolean;
|
|
410
|
+
debug: boolean;
|
|
411
|
+
anotherArrayType: boolean;
|
|
412
|
+
extractRequestBody: boolean;
|
|
413
|
+
httpClientType: "axios" | "fetch";
|
|
414
|
+
addReadonly: boolean;
|
|
415
|
+
extractResponseBody: boolean;
|
|
416
|
+
extractResponseError: boolean;
|
|
417
|
+
defaultResponseType: boolean;
|
|
418
|
+
toJS: boolean;
|
|
419
|
+
disableThrowOnError: boolean;
|
|
420
|
+
silent: boolean;
|
|
421
|
+
hooks: Hooks;
|
|
422
|
+
enumNamesAsValues: boolean;
|
|
423
|
+
version: string;
|
|
424
|
+
internalTemplateOptions: {
|
|
425
|
+
addUtilRequiredKeysType: boolean;
|
|
426
|
+
};
|
|
427
|
+
componentTypeNameResolver: typeof import("./src/util/name-resolver").ComponentTypeNameResolver;
|
|
342
428
|
fileNames: {
|
|
343
429
|
dataContracts: string;
|
|
344
430
|
routeTypes: string;
|
|
@@ -351,6 +437,11 @@ export interface GenerateApiConfiguration {
|
|
|
351
437
|
httpClient: string;
|
|
352
438
|
routeTypes: string;
|
|
353
439
|
routeName: string;
|
|
440
|
+
dataContractJsDoc: string;
|
|
441
|
+
interfaceDataContract: string;
|
|
442
|
+
typeDataContract: string;
|
|
443
|
+
enumDataContract: string;
|
|
444
|
+
objectFieldJsDoc: string;
|
|
354
445
|
};
|
|
355
446
|
routeNameDuplicatesMap: Map<string, string>;
|
|
356
447
|
apiClassName: string;
|
|
@@ -371,7 +462,9 @@ export interface GenerateApiConfiguration {
|
|
|
371
462
|
utils: {
|
|
372
463
|
formatDescription: (description: string, inline?: boolean) => string;
|
|
373
464
|
internalCase: (value: string) => string;
|
|
465
|
+
/** @deprecated */
|
|
374
466
|
classNameCase: (value: string) => string;
|
|
467
|
+
pascalCase: (value: string) => string;
|
|
375
468
|
getInlineParseContent: (rawTypeData: SchemaComponent["rawTypeData"], typeName?: string) => string;
|
|
376
469
|
getParseContent: (rawTypeData: SchemaComponent["rawTypeData"], typeName?: string) => ModelType;
|
|
377
470
|
getComponentByRef: (ref: string) => SchemaComponent;
|