swagger-typescript-api 10.0.3 → 11.0.0--alpha

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.
Files changed (53) hide show
  1. package/README.md +218 -0
  2. package/index.d.ts +93 -0
  3. package/index.js +230 -103
  4. package/package.json +121 -119
  5. package/src/code-formatter.js +101 -0
  6. package/src/code-gen-process.js +456 -0
  7. package/src/configuration.js +425 -0
  8. package/src/constants.js +14 -31
  9. package/src/index.js +6 -257
  10. package/src/schema-components-map.js +60 -0
  11. package/src/schema-parser/schema-formatters.js +145 -0
  12. package/src/schema-parser/schema-parser.js +497 -0
  13. package/src/schema-parser/schema-routes.js +902 -0
  14. package/src/swagger-schema-resolver.js +187 -0
  15. package/src/templates.js +141 -122
  16. package/src/translators/JavaScript.js +49 -49
  17. package/src/type-name.js +79 -0
  18. package/src/util/file-system.js +76 -0
  19. package/src/{utils → util}/id.js +0 -0
  20. package/src/util/internal-case.js +5 -0
  21. package/src/util/logger.js +100 -0
  22. package/src/{utils/resolveName.js → util/name-resolver.js} +1 -1
  23. package/src/util/object-assign.js +11 -0
  24. package/src/util/pascal-case.js +5 -0
  25. package/src/{utils → util}/random.js +1 -1
  26. package/templates/base/data-contract-jsdoc.ejs +29 -24
  27. package/templates/base/data-contracts.ejs +3 -3
  28. package/templates/base/interface-data-contract.ejs +1 -0
  29. package/templates/base/route-docs.ejs +2 -2
  30. package/templates/base/route-type.ejs +2 -2
  31. package/templates/default/route-types.ejs +2 -2
  32. package/templates/modular/api.ejs +2 -2
  33. package/templates/modular/route-types.ejs +2 -2
  34. package/src/apiConfig.js +0 -30
  35. package/src/common.js +0 -28
  36. package/src/components.js +0 -91
  37. package/src/config.js +0 -108
  38. package/src/filePrefix.js +0 -14
  39. package/src/files.js +0 -56
  40. package/src/formatFileContent.js +0 -81
  41. package/src/logger.js +0 -68
  42. package/src/modelNames.js +0 -74
  43. package/src/modelTypes.js +0 -31
  44. package/src/output.js +0 -165
  45. package/src/prettierOptions.js +0 -23
  46. package/src/render/utils/fmtToJSDocLine.js +0 -10
  47. package/src/render/utils/index.js +0 -31
  48. package/src/render/utils/templateRequire.js +0 -17
  49. package/src/routeNames.js +0 -46
  50. package/src/routes.js +0 -809
  51. package/src/schema.js +0 -474
  52. package/src/swagger.js +0 -152
  53. package/src/typeFormatters.js +0 -121
@@ -0,0 +1,425 @@
1
+ const { objectAssign } = require("./util/object-assign");
2
+ const _ = require("lodash");
3
+ const constantsBase = require("./constants.js");
4
+ const packageJson = require("../package.json");
5
+ const { NameResolver, ComponentTypeNameResolver } = require("./util/name-resolver");
6
+ const { cosmiconfigSync } = require("cosmiconfig");
7
+ const CONSTANTS = require("./constants");
8
+
9
+ const TsKeyword = {
10
+ Number: "number",
11
+ String: "string",
12
+ Boolean: "boolean",
13
+ Any: "any",
14
+ Void: "void",
15
+ Unknown: "unknown",
16
+ Null: "null",
17
+ Undefined: "undefined",
18
+ Object: "object",
19
+ File: "File",
20
+ Date: "Date",
21
+ Type: "type",
22
+ Enum: "enum",
23
+ Interface: "interface",
24
+ Array: "Array",
25
+ Record: "Record",
26
+ Intersection: "&",
27
+ Union: "|",
28
+ };
29
+
30
+ const TsCodeGenKeyword = {
31
+ UtilRequiredKeys: "UtilRequiredKeys",
32
+ };
33
+
34
+ /**
35
+ * @type {GenerateApiConfiguration["config"]}}
36
+ */
37
+ class Configuration {
38
+ version = packageJson.version;
39
+ /** CLI flag */
40
+ templates = "../templates/default";
41
+ /** CLI flag */
42
+ generateResponses = false;
43
+ /** CLI flag */
44
+ defaultResponseAsSuccess = false;
45
+ /** CLI flag */
46
+ generateRouteTypes = false;
47
+ /** CLI flag */
48
+ generateClient = true;
49
+ /** CLI flag */
50
+ generateUnionEnums = false;
51
+ /** CLI flag */
52
+ addReadonly = false;
53
+ enumNamesAsValues = false;
54
+ /** parsed swagger schema from getSwaggerObject() */
55
+
56
+ /** parsed swagger schema ref */
57
+ swaggerSchema = null;
58
+ /** original (converted to json) swagger schema ref */
59
+ originalSchema = null;
60
+
61
+ /** { "#/components/schemas/Foo": @TypeInfo, ... } */
62
+ componentsMap = {};
63
+ /** flag for catching convertion from swagger 2.0 */
64
+ convertedFromSwagger2 = false;
65
+
66
+ /** url index from paths used for merging into modules */
67
+ moduleNameIndex = 0;
68
+
69
+ /** use the first tag for the module name */
70
+ moduleNameFirstTag = false;
71
+ disableStrictSSL = false;
72
+ disableProxy = false;
73
+ extractRequestParams = false;
74
+ extractRequestBody = false;
75
+ extractResponseBody = false;
76
+ extractResponseError = false;
77
+ fileNames = {
78
+ dataContracts: "data-contracts",
79
+ routeTypes: "route-types",
80
+ httpClient: "http-client",
81
+ outOfModuleApi: "Common",
82
+ };
83
+ routeNameDuplicatesMap = new Map();
84
+ prettierOptions = { ...CONSTANTS.PRETTIER_OPTIONS };
85
+ hooks = {
86
+ onCreateComponent: (schema) => schema,
87
+ onParseSchema: (originalSchema, parsedSchema) => parsedSchema,
88
+ onCreateRoute: (routeData) => routeData,
89
+ onInit: (config) => config,
90
+ onPrepareConfig: (apiConfig) => apiConfig,
91
+ onCreateRequestParams: (rawType) => {},
92
+ onCreateRouteName: () => {},
93
+ onFormatTypeName: (typeName, rawTypeName) => {},
94
+ onFormatRouteName: (routeInfo, templateRouteName) => {},
95
+ };
96
+ defaultResponseType;
97
+ singleHttpClient = false;
98
+ httpClientType = CONSTANTS.HTTP_CLIENT.FETCH;
99
+ unwrapResponseData = false;
100
+ disableThrowOnError = false;
101
+ sortTypes = false;
102
+ templatePaths = {
103
+ /** `templates/base` */
104
+ base: "",
105
+ /** `templates/default` */
106
+ default: "",
107
+ /** `templates/modular` */
108
+ modular: "",
109
+ /** usage path if `--templates` option is not set */
110
+ original: "",
111
+ /** custom path to templates (`--templates`) */
112
+ custom: "",
113
+ };
114
+ /** Record<templateName, templateContent> */
115
+ templatesToRender = {
116
+ api: "",
117
+ dataContracts: "",
118
+ dataContractJsDoc: "",
119
+ interfaceDataContract: "",
120
+ typeDataContract: "",
121
+ enumDataContract: "",
122
+ objectFieldJsDoc: "",
123
+ httpClient: "",
124
+ routeTypes: "",
125
+ routeName: "",
126
+ };
127
+ toJS = false;
128
+ silent = false;
129
+ typePrefix = "";
130
+ typeSuffix = "";
131
+ patch = false;
132
+ componentTypeNameResolver = new ComponentTypeNameResolver([]);
133
+ /** name of the main exported class */
134
+ apiClassName = "Api";
135
+ debug = false;
136
+ anotherArrayType = false;
137
+ internalTemplateOptions = {
138
+ addUtilRequiredKeysType: false,
139
+ };
140
+ extraTemplates = [];
141
+ input = "";
142
+ modular = false;
143
+ output = "";
144
+ url = "";
145
+ cleanOutput = false;
146
+ spec = null;
147
+ fileName = "";
148
+ authorizationToken = void 0;
149
+
150
+ jsPrimitiveTypes = [];
151
+ jsEmptyTypes = [];
152
+
153
+ successResponseStatusRange = [200, 299];
154
+
155
+ Ts = {
156
+ Keyword: _.cloneDeep(TsKeyword),
157
+ CodeGenKeyword: _.cloneDeep(TsCodeGenKeyword),
158
+ /**
159
+ * $A[] or Array<$A>
160
+ */
161
+ ArrayType: (content) => {
162
+ if (this.anotherArrayType) {
163
+ return this.Ts.TypeWithGeneric(this.Ts.Keyword.Array, [content]);
164
+ }
165
+
166
+ return `${this.Ts.ExpressionGroup(content)}[]`;
167
+ },
168
+ /**
169
+ * "$A"
170
+ */
171
+ StringValue: (content) => `"${content}"`,
172
+ /**
173
+ * $A
174
+ */
175
+ BooleanValue: (content) => `${content}`,
176
+ /**
177
+ * $A
178
+ */
179
+ NumberValue: (content) => `${content}`,
180
+ /**
181
+ * $A
182
+ */
183
+ NullValue: (content) => content,
184
+ /**
185
+ * $A1 | $A2
186
+ */
187
+ UnionType: (contents) => _.join(_.uniq(contents), ` ${this.Ts.Keyword.Union} `),
188
+ /**
189
+ * ($A1)
190
+ */
191
+ ExpressionGroup: (content) => (content ? `(${content})` : ""),
192
+ /**
193
+ * $A1 & $A2
194
+ */
195
+ IntersectionType: (contents) => _.join(_.uniq(contents), ` ${this.Ts.Keyword.Intersection} `),
196
+ /**
197
+ * Record<$A1, $A2>
198
+ */
199
+ RecordType: (key, value) => this.Ts.TypeWithGeneric(this.Ts.Keyword.Record, [key, value]),
200
+ /**
201
+ * readonly $key?:$value
202
+ */
203
+ TypeField: ({ readonly, key, optional, value }) =>
204
+ _.compact([readonly && "readonly ", key, optional && "?", ": ", value]).join(""),
205
+ /**
206
+ * [key: $A1]: $A2
207
+ */
208
+ InterfaceDynamicField: (key, value) => `[key: ${key}]: ${value}`,
209
+ /**
210
+ * $A1 = $A2
211
+ */
212
+ EnumField: (key, value) => `${key} = ${value}`,
213
+ /**
214
+ * $A0.key = $A0.value,
215
+ * $A1.key = $A1.value,
216
+ * $AN.key = $AN.value,
217
+ */
218
+ EnumFieldsWrapper: (contents) =>
219
+ _.map(contents, ({ key, value }) => ` ${this.Ts.EnumField(key, value)}`).join(",\n"),
220
+ /**
221
+ * {\n $A \n}
222
+ */
223
+ ObjectWrapper: (content) => `{\n${content}\n}`,
224
+ /**
225
+ * /** $A *\/
226
+ */
227
+ MultilineComment: (contents, formatFn) =>
228
+ [
229
+ ...(contents.length === 1
230
+ ? [`/** ${contents[0]} */`]
231
+ : ["/**", ...contents.map((content) => ` * ${content}`), " */"]),
232
+ ].map((part) => `${formatFn ? formatFn(part) : part}\n`),
233
+ /**
234
+ * $A1<...$A2.join(,)>
235
+ */
236
+ TypeWithGeneric: (typeName, genericArgs) => {
237
+ return `${typeName}${genericArgs.length ? `<${genericArgs.join(",")}>` : ""}`;
238
+ },
239
+ };
240
+
241
+ /**
242
+ * swagger schema type -> typescript type
243
+ * https://json-schema.org/understanding-json-schema/reference/string.html#dates-and-times
244
+ * @type {Record<string, string | ((schema: any, parser: SchemaParser) => string) | ({ $default: string } & Record<string, string | ((schema: any, parser: SchemaParser) => string)>)>}
245
+ */
246
+ primitiveTypes = {
247
+ integer: () => this.Ts.Keyword.Number,
248
+ number: () => this.Ts.Keyword.Number,
249
+ boolean: () => this.Ts.Keyword.Boolean,
250
+ object: () => this.Ts.Keyword.Object,
251
+ file: () => this.Ts.Keyword.File,
252
+ string: {
253
+ $default: () => this.Ts.Keyword.String,
254
+
255
+ /** formats */
256
+ binary: () => this.Ts.Keyword.File,
257
+ file: () => this.Ts.Keyword.File,
258
+ "date-time": () => this.Ts.Keyword.String,
259
+ time: () => this.Ts.Keyword.String,
260
+ date: () => this.Ts.Keyword.String,
261
+ duration: () => this.Ts.Keyword.String,
262
+ email: () => this.Ts.Keyword.String,
263
+ "idn-email": () => this.Ts.Keyword.String,
264
+ "idn-hostname": () => this.Ts.Keyword.String,
265
+ ipv4: () => this.Ts.Keyword.String,
266
+ ipv6: () => this.Ts.Keyword.String,
267
+ uuid: () => this.Ts.Keyword.String,
268
+ uri: () => this.Ts.Keyword.String,
269
+ "uri-reference": () => this.Ts.Keyword.String,
270
+ "uri-template": () => this.Ts.Keyword.String,
271
+ "json-pointer": () => this.Ts.Keyword.String,
272
+ "relative-json-pointer": () => this.Ts.Keyword.String,
273
+ regex: () => this.Ts.Keyword.String,
274
+ },
275
+ array: ({ items, ...schemaPart }, parser) => {
276
+ const content = parser.getInlineParseContent(items);
277
+ return parser.checkAndAddNull(schemaPart, this.Ts.ArrayType(content));
278
+ },
279
+ };
280
+
281
+ templateInfos = [
282
+ { name: "api", fileName: "api" },
283
+ { name: "dataContracts", fileName: "data-contracts" },
284
+ { name: "dataContractJsDoc", fileName: "data-contract-jsdoc" },
285
+ { name: "interfaceDataContract", fileName: "interface-data-contract" },
286
+ { name: "typeDataContract", fileName: "type-data-contract" },
287
+ { name: "enumDataContract", fileName: "enum-data-contract" },
288
+ { name: "objectFieldJsDoc", fileName: "object-field-jsdoc" },
289
+ { name: "httpClient", fileName: "http-client" },
290
+ { name: "routeTypes", fileName: "route-types" },
291
+ { name: "routeName", fileName: "route-name" },
292
+ ];
293
+
294
+ templateExtensions = [".eta", ".ejs"];
295
+
296
+ constructor({
297
+ input,
298
+ output,
299
+ url,
300
+ spec,
301
+ name: fileName,
302
+ toJS,
303
+ modular,
304
+ templates,
305
+ generateResponses,
306
+ defaultResponseAsSuccess,
307
+ generateRouteTypes,
308
+ generateClient,
309
+ httpClientType,
310
+ generateUnionEnums,
311
+ addReadonly,
312
+ moduleNameIndex,
313
+ moduleNameFirstTag,
314
+ extractRequestParams,
315
+ extractRequestBody,
316
+ extractResponseBody,
317
+ extractResponseError,
318
+ defaultResponseType,
319
+ unwrapResponseData,
320
+ disableThrowOnError,
321
+ sortTypes,
322
+ singleHttpClient,
323
+ prettier: prettierOptions = getDefaultPrettierOptions(),
324
+ hooks: rawHooks,
325
+ extraTemplates,
326
+ enumNamesAsValues,
327
+ disableStrictSSL,
328
+ disableProxy,
329
+ cleanOutput,
330
+ silent,
331
+ typePrefix,
332
+ typeSuffix,
333
+ patch,
334
+ authorizationToken,
335
+ apiClassName,
336
+ debug,
337
+ anotherArrayType,
338
+ codeGenConstructs,
339
+ primitiveTypeConstructs,
340
+ constants,
341
+ templateInfos,
342
+ }) {
343
+ objectAssign(this.Ts, codeGenConstructs);
344
+ objectAssign(this.primitiveTypes, primitiveTypeConstructs);
345
+
346
+ this.defaultResponseType = this.Ts.Keyword.Void;
347
+
348
+ this.update({
349
+ input,
350
+ output,
351
+ url,
352
+ spec,
353
+ fileName,
354
+ extraTemplates,
355
+ defaultResponseAsSuccess,
356
+ generateRouteTypes,
357
+ generateClient,
358
+ httpClientType,
359
+ generateResponses,
360
+ templates,
361
+ generateUnionEnums,
362
+ addReadonly,
363
+ moduleNameIndex,
364
+ moduleNameFirstTag,
365
+ prettierOptions,
366
+ modular,
367
+ extractRequestParams,
368
+ extractRequestBody,
369
+ extractResponseBody,
370
+ extractResponseError,
371
+ hooks: _.merge(this.hooks, rawHooks || {}),
372
+ enumNamesAsValues,
373
+ disableStrictSSL,
374
+ disableProxy,
375
+ cleanOutput,
376
+ defaultResponseType,
377
+ unwrapResponseData,
378
+ disableThrowOnError,
379
+ sortTypes,
380
+ singleHttpClient,
381
+ constants: {
382
+ ...constantsBase,
383
+ ...constants,
384
+ },
385
+ authorizationToken,
386
+ silent,
387
+ toJS,
388
+ typePrefix,
389
+ typeSuffix,
390
+ patch,
391
+ apiClassName,
392
+ debug,
393
+ anotherArrayType,
394
+ templateInfos,
395
+ });
396
+
397
+ this.jsPrimitiveTypes = [this.Ts.Keyword.Number, this.Ts.Keyword.String, this.Ts.Keyword.Boolean];
398
+ this.jsEmptyTypes = [this.Ts.Keyword.Null, this.Ts.Keyword.Undefined];
399
+ }
400
+
401
+ /**
402
+ *
403
+ * @param update {Partial<GenerateApiConfiguration["config"]>}
404
+ */
405
+ update = (update) => {
406
+ objectAssign(this, update);
407
+ };
408
+ }
409
+
410
+ const getDefaultPrettierOptions = () => {
411
+ const prettier = cosmiconfigSync("prettier").search();
412
+
413
+ if (prettier) {
414
+ return {
415
+ ...prettier.config,
416
+ parser: "typescript",
417
+ };
418
+ }
419
+
420
+ return { ...CONSTANTS.PRETTIER_OPTIONS };
421
+ };
422
+
423
+ module.exports = {
424
+ Configuration,
425
+ };
package/src/constants.js CHANGED
@@ -1,29 +1,3 @@
1
- const TS_KEYWORDS = {
2
- NUMBER: "number",
3
- STRING: "string",
4
- BOOLEAN: "boolean",
5
- ANY: "any",
6
- VOID: "void",
7
- UNKNOWN: "unknown",
8
- NULL: "null",
9
- UNDEFINED: "undefined",
10
- OBJECT: "object",
11
- FILE: "File",
12
- DATE: "Date",
13
- TYPE: "type",
14
- ENUM: "enum",
15
- INTERFACE: "interface",
16
- TYPE_AND_OPERATOR: " & ",
17
- TYPE_OR_OPERATOR: " | ",
18
- };
19
-
20
- const TS_EXTERNAL = {
21
- RECORD: "Record<string, any>",
22
- };
23
-
24
- const JS_PRIMITIVE_TYPES = [TS_KEYWORDS.NUMBER, TS_KEYWORDS.STRING, TS_KEYWORDS.BOOLEAN];
25
- const JS_EMPTY_TYPES = [TS_KEYWORDS.NULL, TS_KEYWORDS.UNDEFINED];
26
-
27
1
  const RESERVED_QUERY_ARG_NAMES = ["query", "queryParams", "queryArg"];
28
2
  const RESERVED_BODY_ARG_NAMES = ["data", "body", "reqBody"];
29
3
  const RESERVED_REQ_PARAMS_ARG_NAMES = ["params", "requestParams", "reqParams", "httpParams"];
@@ -49,13 +23,22 @@ const HTTP_CLIENT = {
49
23
  AXIOS: "axios",
50
24
  };
51
25
 
26
+ const FILE_PREFIX = `/* eslint-disable */
27
+ /* tslint:disable */
28
+ /*
29
+ * ---------------------------------------------------------------
30
+ * ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ##
31
+ * ## ##
32
+ * ## AUTHOR: acacode ##
33
+ * ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
34
+ * ---------------------------------------------------------------
35
+ */
36
+
37
+ `;
38
+
52
39
  module.exports = {
40
+ FILE_PREFIX,
53
41
  DEFAULT_BODY_ARG_NAME: "data",
54
- SUCCESS_RESPONSE_STATUS_RANGE: [200, 300],
55
- JS_PRIMITIVE_TYPES,
56
- JS_EMPTY_TYPES,
57
- TS_KEYWORDS,
58
- TS_EXTERNAL,
59
42
  SCHEMA_TYPES,
60
43
  HTTP_CLIENT,
61
44
  RESERVED_QUERY_ARG_NAMES,