swagger-typescript-api 13.0.0-experimental-1 → 13.0.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.
Files changed (81) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +22 -12
  3. package/cli/constants.js +3 -3
  4. package/cli/execute.js +52 -31
  5. package/cli/index.d.ts +1 -2
  6. package/cli/index.js +18 -17
  7. package/cli/operations/display-help.js +51 -29
  8. package/cli/parse-args.js +3 -3
  9. package/cli/process-option.js +28 -20
  10. package/index.d.ts +113 -8
  11. package/index.js +158 -135
  12. package/package.json +35 -30
  13. package/src/code-formatter.js +28 -13
  14. package/src/code-gen-process.js +357 -259
  15. package/src/commands/generate-templates/configuration.js +2 -2
  16. package/src/commands/generate-templates/index.js +1 -2
  17. package/src/commands/generate-templates/templates-gen-process.js +62 -35
  18. package/src/component-type-name-resolver.js +44 -0
  19. package/src/configuration.js +167 -95
  20. package/src/constants.js +28 -22
  21. package/src/index.js +3 -4
  22. package/src/schema-components-map.js +39 -23
  23. package/src/schema-parser/base-schema-parsers/array.js +43 -0
  24. package/src/schema-parser/base-schema-parsers/complex.js +51 -0
  25. package/src/schema-parser/base-schema-parsers/discriminator.js +301 -0
  26. package/src/schema-parser/base-schema-parsers/enum.js +158 -0
  27. package/src/schema-parser/base-schema-parsers/object.js +105 -0
  28. package/src/schema-parser/base-schema-parsers/primitive.js +63 -0
  29. package/src/schema-parser/complex-schema-parsers/all-of.js +26 -0
  30. package/src/schema-parser/complex-schema-parsers/any-of.js +34 -0
  31. package/src/schema-parser/complex-schema-parsers/not.js +9 -0
  32. package/src/schema-parser/complex-schema-parsers/one-of.js +27 -0
  33. package/src/schema-parser/mono-schema-parser.js +48 -0
  34. package/src/schema-parser/schema-formatters.js +69 -60
  35. package/src/schema-parser/schema-parser-fabric.js +131 -0
  36. package/src/schema-parser/schema-parser.js +208 -427
  37. package/src/schema-parser/schema-utils.js +123 -58
  38. package/src/schema-parser/util/enum-key-resolver.js +26 -0
  39. package/src/schema-routes/schema-routes.js +1225 -0
  40. package/src/schema-routes/util/specific-arg-name-resolver.js +26 -0
  41. package/src/schema-walker.js +93 -0
  42. package/src/swagger-schema-resolver.js +61 -28
  43. package/src/templates-worker.js +240 -0
  44. package/src/translators/javascript.js +83 -0
  45. package/src/translators/translator.js +35 -0
  46. package/src/type-name-formatter.js +33 -18
  47. package/src/util/file-system.js +30 -14
  48. package/src/util/id.js +2 -2
  49. package/src/util/internal-case.js +1 -1
  50. package/src/util/logger.js +46 -20
  51. package/src/util/name-resolver.js +52 -60
  52. package/src/util/object-assign.js +7 -3
  53. package/src/util/pascal-case.js +1 -1
  54. package/src/util/request.js +5 -5
  55. package/src/util/sort-by-property.js +17 -0
  56. package/templates/README.md +17 -17
  57. package/templates/base/README.md +7 -7
  58. package/templates/base/data-contract-jsdoc.ejs +37 -37
  59. package/templates/base/data-contracts.ejs +40 -27
  60. package/templates/base/enum-data-contract.ejs +12 -12
  61. package/templates/base/http-client.ejs +3 -3
  62. package/templates/base/http-clients/axios-http-client.ejs +139 -138
  63. package/templates/base/http-clients/fetch-http-client.ejs +224 -224
  64. package/templates/base/interface-data-contract.ejs +10 -10
  65. package/templates/base/object-field-jsdoc.ejs +28 -28
  66. package/templates/base/route-docs.ejs +30 -30
  67. package/templates/base/route-name.ejs +42 -42
  68. package/templates/base/route-type.ejs +22 -21
  69. package/templates/base/type-data-contract.ejs +15 -15
  70. package/templates/default/README.md +6 -6
  71. package/templates/default/api.ejs +69 -68
  72. package/templates/default/procedure-call.ejs +100 -100
  73. package/templates/default/route-types.ejs +32 -32
  74. package/templates/modular/README.md +6 -6
  75. package/templates/modular/api.ejs +28 -28
  76. package/templates/modular/procedure-call.ejs +100 -100
  77. package/templates/modular/route-types.ejs +18 -18
  78. package/src/schema-parser/schema-processor.js +0 -79
  79. package/src/schema-parser/schema-routes.js +0 -950
  80. package/src/templates.js +0 -182
  81. package/src/translators/JavaScript.js +0 -60
@@ -1,32 +1,34 @@
1
- const { objectAssign } = require("./util/object-assign");
2
- const _ = require("lodash");
3
- const CONSTANTS = require("./constants");
4
- const { ComponentTypeNameResolver } = require("./util/name-resolver");
5
- const { cosmiconfigSync } = require("cosmiconfig");
1
+ /* eslint-disable no-unused-vars */
2
+ const { objectAssign } = require('./util/object-assign');
3
+ const _ = require('lodash');
4
+ const CONSTANTS = require('./constants');
5
+ const { ComponentTypeNameResolver } = require('./component-type-name-resolver');
6
+ const { cosmiconfigSync } = require('cosmiconfig');
7
+ const ts = require('typescript');
6
8
 
7
9
  const TsKeyword = {
8
- Number: "number",
9
- String: "string",
10
- Boolean: "boolean",
11
- Any: "any",
12
- Void: "void",
13
- Unknown: "unknown",
14
- Null: "null",
15
- Undefined: "undefined",
16
- Object: "object",
17
- File: "File",
18
- Date: "Date",
19
- Type: "type",
20
- Enum: "enum",
21
- Interface: "interface",
22
- Array: "Array",
23
- Record: "Record",
24
- Intersection: "&",
25
- Union: "|",
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: '|',
26
28
  };
27
29
 
28
30
  const TsCodeGenKeyword = {
29
- UtilRequiredKeys: "UtilRequiredKeys",
31
+ UtilRequiredKeys: 'UtilRequiredKeys',
30
32
  };
31
33
 
32
34
  /**
@@ -35,7 +37,7 @@ const TsCodeGenKeyword = {
35
37
  class CodeGenConfig {
36
38
  version = CONSTANTS.PROJECT_VERSION;
37
39
  /** CLI flag */
38
- templates = "../templates/default";
40
+ templates = '';
39
41
  /** CLI flag */
40
42
  generateResponses = false;
41
43
  /** CLI flag */
@@ -74,10 +76,10 @@ class CodeGenConfig {
74
76
  extractResponseError = false;
75
77
  extractEnums = false;
76
78
  fileNames = {
77
- dataContracts: "data-contracts",
78
- routeTypes: "route-types",
79
- httpClient: "http-client",
80
- outOfModuleApi: "Common",
79
+ dataContracts: 'data-contracts',
80
+ routeTypes: 'route-types',
81
+ httpClient: 'http-client',
82
+ outOfModuleApi: 'Common',
81
83
  };
82
84
  routeNameDuplicatesMap = new Map();
83
85
  prettierOptions = { ...CONSTANTS.PRETTIER_OPTIONS };
@@ -89,7 +91,7 @@ class CodeGenConfig {
89
91
  onPreParseSchema: (originalSchema, typeName, schemaType) => void 0,
90
92
  onParseSchema: (originalSchema, parsedSchema) => parsedSchema,
91
93
  onCreateRoute: (routeData) => routeData,
92
- onInit: (config) => config,
94
+ onInit: (config, codeGenProcess) => config,
93
95
  onPrepareConfig: (apiConfig) => apiConfig,
94
96
  onCreateRequestParams: (rawType) => {},
95
97
  onCreateRouteName: () => {},
@@ -102,72 +104,114 @@ class CodeGenConfig {
102
104
  unwrapResponseData = false;
103
105
  disableThrowOnError = false;
104
106
  sortTypes = false;
107
+ sortRoutes = false;
105
108
  templatePaths = {
106
109
  /** `templates/base` */
107
- base: "",
110
+ base: '',
108
111
  /** `templates/default` */
109
- default: "",
112
+ default: '',
110
113
  /** `templates/modular` */
111
- modular: "",
114
+ modular: '',
112
115
  /** usage path if `--templates` option is not set */
113
- original: "",
116
+ original: '',
114
117
  /** custom path to templates (`--templates`) */
115
- custom: "",
118
+ custom: '',
116
119
  };
117
120
  /** Record<templateName, templateContent> */
118
121
  templatesToRender = {
119
- api: "",
120
- dataContracts: "",
121
- dataContractJsDoc: "",
122
- interfaceDataContract: "",
123
- typeDataContract: "",
124
- enumDataContract: "",
125
- objectFieldJsDoc: "",
126
- httpClient: "",
127
- routeTypes: "",
128
- routeName: "",
122
+ api: '',
123
+ dataContracts: '',
124
+ dataContractJsDoc: '',
125
+ interfaceDataContract: '',
126
+ typeDataContract: '',
127
+ enumDataContract: '',
128
+ objectFieldJsDoc: '',
129
+ httpClient: '',
130
+ routeTypes: '',
131
+ routeName: '',
129
132
  };
133
+ /**
134
+ * @type {Record<string, (...args: any[]) => MonoSchemaParser>}
135
+ */
136
+ schemaParsers = {};
130
137
  toJS = false;
131
138
  silent = false;
132
- typePrefix = "";
133
- typeSuffix = "";
134
- enumKeyPrefix = "";
135
- enumKeySuffix = "";
139
+ typePrefix = '';
140
+ typeSuffix = '';
141
+ enumKeyPrefix = '';
142
+ enumKeySuffix = '';
136
143
  patch = false;
137
- componentTypeNameResolver = new ComponentTypeNameResolver(null, []);
144
+ /** @type {ComponentTypeNameResolver} */
145
+ componentTypeNameResolver;
138
146
  /** name of the main exported class */
139
- apiClassName = "Api";
147
+ apiClassName = 'Api';
140
148
  debug = false;
141
149
  anotherArrayType = false;
142
150
  internalTemplateOptions = {
143
151
  addUtilRequiredKeysType: false,
144
152
  };
145
153
  extraTemplates = [];
146
- input = "";
154
+ input = '';
147
155
  modular = false;
148
- output = "";
149
- url = "";
156
+ output = '';
157
+ url = '';
150
158
  cleanOutput = false;
151
159
  spec = null;
152
- fileName = "Api.ts";
160
+ fileName = 'Api.ts';
153
161
  authorizationToken = void 0;
154
162
  requestOptions = null;
155
163
 
156
164
  jsPrimitiveTypes = [];
157
165
  jsEmptyTypes = [];
158
- fixInvalidTypeNamePrefix = "Type";
159
- fixInvalidEnumKeyPrefix = "Value";
166
+ fixInvalidTypeNamePrefix = 'Type';
167
+ fixInvalidEnumKeyPrefix = 'Value';
168
+
169
+ enumKeyResolverName = 'Value';
170
+ typeNameResolverName = 'ComponentType';
171
+ specificArgNameResolverName = 'arg';
160
172
 
161
173
  successResponseStatusRange = [200, 299];
162
174
 
163
175
  /** @type {ExtractingOptions} */
164
176
  extractingOptions = {
165
- requestBodySuffix: ["Payload", "Body", "Input"],
166
- requestParamsSuffix: ["Params"],
167
- responseBodySuffix: ["Data", "Result", "Output"],
168
- responseErrorSuffix: ["Error", "Fail", "Fails", "ErrorData", "HttpError", "BadResponse"],
177
+ requestBodySuffix: ['Payload', 'Body', 'Input'],
178
+ requestParamsSuffix: ['Params'],
179
+ responseBodySuffix: ['Data', 'Result', 'Output'],
180
+ responseErrorSuffix: [
181
+ 'Error',
182
+ 'Fail',
183
+ 'Fails',
184
+ 'ErrorData',
185
+ 'HttpError',
186
+ 'BadResponse',
187
+ ],
188
+ enumSuffix: ['Enum'],
189
+ discriminatorMappingSuffix: ['Mapping', 'Mapper', 'MapType'],
190
+ discriminatorAbstractPrefix: [
191
+ 'Base',
192
+ 'Abstract',
193
+ 'Discriminator',
194
+ 'Internal',
195
+ 'Polymorph',
196
+ ],
169
197
  };
170
198
 
199
+ compilerTsConfig = {
200
+ module: 'ESNext',
201
+ noImplicitReturns: true,
202
+ alwaysStrict: true,
203
+ target: ts.ScriptTarget.ESNext,
204
+ declaration: true,
205
+ noImplicitAny: false,
206
+ sourceMap: false,
207
+ removeComments: false,
208
+ disableSizeLimit: true,
209
+ esModuleInterop: true,
210
+ emitDecoratorMetadata: true,
211
+ skipLibCheck: true,
212
+ };
213
+ customTranslator;
214
+
171
215
  Ts = {
172
216
  Keyword: _.cloneDeep(TsKeyword),
173
217
  CodeGenKeyword: _.cloneDeep(TsCodeGenKeyword),
@@ -200,28 +244,39 @@ class CodeGenConfig {
200
244
  /**
201
245
  * $A1 | $A2
202
246
  */
203
- UnionType: (contents) => _.join(_.uniq(contents), ` ${this.Ts.Keyword.Union} `),
247
+ UnionType: (contents) =>
248
+ _.join(_.uniq(contents), ` ${this.Ts.Keyword.Union} `),
204
249
  /**
205
250
  * ($A1)
206
251
  */
207
- ExpressionGroup: (content) => (content ? `(${content})` : ""),
252
+ ExpressionGroup: (content) => (content ? `(${content})` : ''),
208
253
  /**
209
254
  * $A1 & $A2
210
255
  */
211
- IntersectionType: (contents) => _.join(_.uniq(contents), ` ${this.Ts.Keyword.Intersection} `),
256
+ IntersectionType: (contents) =>
257
+ _.join(_.uniq(contents), ` ${this.Ts.Keyword.Intersection} `),
212
258
  /**
213
259
  * Record<$A1, $A2>
214
260
  */
215
- RecordType: (key, value) => this.Ts.TypeWithGeneric(this.Ts.Keyword.Record, [key, value]),
261
+ RecordType: (key, value) =>
262
+ this.Ts.TypeWithGeneric(this.Ts.Keyword.Record, [key, value]),
216
263
  /**
217
264
  * readonly $key?:$value
218
265
  */
219
266
  TypeField: ({ readonly, key, optional, value }) =>
220
- _.compact([readonly && "readonly ", key, optional && "?", ": ", value]).join(""),
267
+ _.compact([
268
+ readonly && 'readonly ',
269
+ key,
270
+ optional && '?',
271
+ ': ',
272
+ value,
273
+ ]).join(''),
221
274
  /**
222
275
  * [key: $A1]: $A2
223
276
  */
224
277
  InterfaceDynamicField: (key, value) => `[key: ${key}]: ${value}`,
278
+
279
+ EnumUsageKey: (enumStruct, key) => `${enumStruct}.${key}`,
225
280
  /**
226
281
  * $A1 = $A2
227
282
  */
@@ -232,7 +287,10 @@ class CodeGenConfig {
232
287
  * $AN.key = $AN.value,
233
288
  */
234
289
  EnumFieldsWrapper: (contents) =>
235
- _.map(contents, ({ key, value }) => ` ${this.Ts.EnumField(key, value)}`).join(",\n"),
290
+ _.map(
291
+ contents,
292
+ ({ key, value }) => ` ${this.Ts.EnumField(key, value)}`,
293
+ ).join(',\n'),
236
294
  /**
237
295
  * {\n $A \n}
238
296
  */
@@ -244,26 +302,28 @@ class CodeGenConfig {
244
302
  [
245
303
  ...(contents.length === 1
246
304
  ? [`/** ${contents[0]} */`]
247
- : ["/**", ...contents.map((content) => ` * ${content}`), " */"]),
305
+ : ['/**', ...contents.map((content) => ` * ${content}`), ' */']),
248
306
  ].map((part) => `${formatFn ? formatFn(part) : part}\n`),
249
307
  /**
250
308
  * $A1<...$A2.join(,)>
251
309
  */
252
310
  TypeWithGeneric: (typeName, genericArgs) => {
253
- return `${typeName}${genericArgs.length ? `<${genericArgs.join(",")}>` : ""}`;
311
+ return `${typeName}${
312
+ genericArgs.length ? `<${genericArgs.join(',')}>` : ''
313
+ }`;
254
314
  },
255
315
  /**
256
316
  * [$A1, $A2, ...$AN]
257
317
  */
258
318
  Tuple: (values) => {
259
- return `[${values.join(", ")}]`;
319
+ return `[${values.join(', ')}]`;
260
320
  },
261
321
  };
262
322
 
263
323
  /**
264
324
  * swagger schema type -> typescript type
265
325
  * https://json-schema.org/understanding-json-schema/reference/string.html#dates-and-times
266
- * @type {Record<string, string | ((schema: any, parser: SchemaProcessor) => string) | ({ $default: string } & Record<string, string | ((schema: any, parser: SchemaParser) => string)>)>}
326
+ * @type {Record<string, string | ((schema: any, parser: SchemaParser) => string) | ({ $default: string } & Record<string, string | ((schema: any, parser: SchemaParser) => string)>)>}
267
327
  */
268
328
  primitiveTypes = {
269
329
  integer: () => this.Ts.Keyword.Number,
@@ -277,39 +337,39 @@ class CodeGenConfig {
277
337
  /** formats */
278
338
  binary: () => this.Ts.Keyword.File,
279
339
  file: () => this.Ts.Keyword.File,
280
- "date-time": () => this.Ts.Keyword.String,
340
+ 'date-time': () => this.Ts.Keyword.String,
281
341
  time: () => this.Ts.Keyword.String,
282
342
  date: () => this.Ts.Keyword.String,
283
343
  duration: () => this.Ts.Keyword.String,
284
344
  email: () => this.Ts.Keyword.String,
285
- "idn-email": () => this.Ts.Keyword.String,
286
- "idn-hostname": () => this.Ts.Keyword.String,
345
+ 'idn-email': () => this.Ts.Keyword.String,
346
+ 'idn-hostname': () => this.Ts.Keyword.String,
287
347
  ipv4: () => this.Ts.Keyword.String,
288
348
  ipv6: () => this.Ts.Keyword.String,
289
349
  uuid: () => this.Ts.Keyword.String,
290
350
  uri: () => this.Ts.Keyword.String,
291
- "uri-reference": () => this.Ts.Keyword.String,
292
- "uri-template": () => this.Ts.Keyword.String,
293
- "json-pointer": () => this.Ts.Keyword.String,
294
- "relative-json-pointer": () => this.Ts.Keyword.String,
351
+ 'uri-reference': () => this.Ts.Keyword.String,
352
+ 'uri-template': () => this.Ts.Keyword.String,
353
+ 'json-pointer': () => this.Ts.Keyword.String,
354
+ 'relative-json-pointer': () => this.Ts.Keyword.String,
295
355
  regex: () => this.Ts.Keyword.String,
296
356
  },
297
357
  };
298
358
 
299
359
  templateInfos = [
300
- { name: "api", fileName: "api" },
301
- { name: "dataContracts", fileName: "data-contracts" },
302
- { name: "dataContractJsDoc", fileName: "data-contract-jsdoc" },
303
- { name: "interfaceDataContract", fileName: "interface-data-contract" },
304
- { name: "typeDataContract", fileName: "type-data-contract" },
305
- { name: "enumDataContract", fileName: "enum-data-contract" },
306
- { name: "objectFieldJsDoc", fileName: "object-field-jsdoc" },
307
- { name: "httpClient", fileName: "http-client" },
308
- { name: "routeTypes", fileName: "route-types" },
309
- { name: "routeName", fileName: "route-name" },
360
+ { name: 'api', fileName: 'api' },
361
+ { name: 'dataContracts', fileName: 'data-contracts' },
362
+ { name: 'dataContractJsDoc', fileName: 'data-contract-jsdoc' },
363
+ { name: 'interfaceDataContract', fileName: 'interface-data-contract' },
364
+ { name: 'typeDataContract', fileName: 'type-data-contract' },
365
+ { name: 'enumDataContract', fileName: 'enum-data-contract' },
366
+ { name: 'objectFieldJsDoc', fileName: 'object-field-jsdoc' },
367
+ { name: 'httpClient', fileName: 'http-client' },
368
+ { name: 'routeTypes', fileName: 'route-types' },
369
+ { name: 'routeName', fileName: 'route-name' },
310
370
  ];
311
371
 
312
- templateExtensions = [".eta", ".ejs"];
372
+ templateExtensions = ['.eta', '.ejs'];
313
373
 
314
374
  /**
315
375
  * @param config {Partial<GenerateApiConfiguration['config']>}
@@ -321,7 +381,7 @@ class CodeGenConfig {
321
381
  constants,
322
382
  templateInfos,
323
383
  hooks,
324
- ...params
384
+ ...otherConfig
325
385
  }) {
326
386
  objectAssign(this.Ts, codeGenConstructs);
327
387
  objectAssign(this.primitiveTypes, primitiveTypeConstructs);
@@ -329,8 +389,11 @@ class CodeGenConfig {
329
389
  this.defaultResponseType = this.Ts.Keyword.Void;
330
390
 
331
391
  this.update({
332
- ...params,
333
- prettierOptions: prettierOptions === undefined ? getDefaultPrettierOptions() : prettierOptions,
392
+ ...otherConfig,
393
+ prettierOptions:
394
+ prettierOptions === undefined
395
+ ? getDefaultPrettierOptions()
396
+ : prettierOptions,
334
397
  hooks: _.merge(this.hooks, hooks || {}),
335
398
  constants: {
336
399
  ...CONSTANTS,
@@ -339,8 +402,17 @@ class CodeGenConfig {
339
402
  templateInfos: templateInfos || this.templateInfos,
340
403
  });
341
404
 
342
- this.jsPrimitiveTypes = [this.Ts.Keyword.Number, this.Ts.Keyword.String, this.Ts.Keyword.Boolean];
405
+ this.jsPrimitiveTypes = [
406
+ this.Ts.Keyword.Number,
407
+ this.Ts.Keyword.String,
408
+ this.Ts.Keyword.Boolean,
409
+ ];
343
410
  this.jsEmptyTypes = [this.Ts.Keyword.Null, this.Ts.Keyword.Undefined];
411
+ this.componentTypeNameResolver = new ComponentTypeNameResolver(
412
+ this,
413
+ null,
414
+ [],
415
+ );
344
416
  }
345
417
 
346
418
  /**
@@ -353,12 +425,12 @@ class CodeGenConfig {
353
425
  }
354
426
 
355
427
  const getDefaultPrettierOptions = () => {
356
- const prettier = cosmiconfigSync("prettier").search();
428
+ const prettier = cosmiconfigSync('prettier').search();
357
429
 
358
430
  if (prettier) {
359
431
  return {
360
432
  ...prettier.config,
361
- parser: "typescript",
433
+ parser: 'typescript',
362
434
  };
363
435
  }
364
436
 
package/src/constants.js CHANGED
@@ -1,27 +1,33 @@
1
- const packageJson = require("../package.json");
2
- const RESERVED_QUERY_ARG_NAMES = ["query", "queryParams", "queryArg"];
3
- const RESERVED_BODY_ARG_NAMES = ["data", "body", "reqBody"];
4
- const RESERVED_REQ_PARAMS_ARG_NAMES = ["params", "requestParams", "reqParams", "httpParams"];
5
- const RESERVED_PATH_ARG_NAMES = ["path", "pathParams"];
6
- const RESERVED_HEADER_ARG_NAMES = ["headers", "headersParams"];
1
+ const packageJson = require('../package.json');
2
+ const RESERVED_QUERY_ARG_NAMES = ['query', 'queryParams', 'queryArg'];
3
+ const RESERVED_BODY_ARG_NAMES = ['data', 'body', 'reqBody'];
4
+ const RESERVED_REQ_PARAMS_ARG_NAMES = [
5
+ 'params',
6
+ 'requestParams',
7
+ 'reqParams',
8
+ 'httpParams',
9
+ ];
10
+ const RESERVED_PATH_ARG_NAMES = ['path', 'pathParams'];
11
+ const RESERVED_HEADER_ARG_NAMES = ['headers', 'headersParams'];
7
12
 
8
13
  const SCHEMA_TYPES = {
9
- ARRAY: "array",
10
- OBJECT: "object",
11
- ENUM: "enum",
12
- REF: "$ref",
13
- PRIMITIVE: "primitive",
14
- COMPLEX: "complex",
15
- COMPLEX_ONE_OF: "oneOf",
16
- COMPLEX_ANY_OF: "anyOf",
17
- COMPLEX_ALL_OF: "allOf",
18
- COMPLEX_NOT: "not",
19
- COMPLEX_UNKNOWN: "__unknown",
14
+ ARRAY: 'array',
15
+ OBJECT: 'object',
16
+ ENUM: 'enum',
17
+ REF: '$ref',
18
+ PRIMITIVE: 'primitive',
19
+ COMPLEX: 'complex',
20
+ DISCRIMINATOR: 'discriminator',
21
+ COMPLEX_ONE_OF: 'oneOf',
22
+ COMPLEX_ANY_OF: 'anyOf',
23
+ COMPLEX_ALL_OF: 'allOf',
24
+ COMPLEX_NOT: 'not',
25
+ COMPLEX_UNKNOWN: '__unknown',
20
26
  };
21
27
 
22
28
  const HTTP_CLIENT = {
23
- FETCH: "fetch",
24
- AXIOS: "axios",
29
+ FETCH: 'fetch',
30
+ AXIOS: 'axios',
25
31
  };
26
32
 
27
33
  const PROJECT_VERSION = packageJson.version;
@@ -41,7 +47,7 @@ const FILE_PREFIX = `/* eslint-disable */
41
47
 
42
48
  module.exports = {
43
49
  FILE_PREFIX,
44
- DEFAULT_BODY_ARG_NAME: "data",
50
+ DEFAULT_BODY_ARG_NAME: 'data',
45
51
  PROJECT_VERSION,
46
52
  SCHEMA_TYPES,
47
53
  HTTP_CLIENT,
@@ -53,7 +59,7 @@ module.exports = {
53
59
  PRETTIER_OPTIONS: {
54
60
  printWidth: 120,
55
61
  tabWidth: 2,
56
- trailingComma: "all",
57
- parser: "typescript",
62
+ trailingComma: 'all',
63
+ parser: 'typescript',
58
64
  },
59
65
  };
package/src/index.js CHANGED
@@ -6,10 +6,9 @@
6
6
  // License text available at https://opensource.org/licenses/MIT
7
7
  // Repository https://github.com/acacode/swagger-typescript-api
8
8
 
9
- const _ = require("lodash");
10
- const constants = require("./constants");
11
- const { CodeGenProcess } = require("./code-gen-process.js");
12
- const { generateTemplates } = require("./commands/generate-templates");
9
+ const constants = require('./constants');
10
+ const { CodeGenProcess } = require('./code-gen-process.js');
11
+ const { generateTemplates } = require('./commands/generate-templates');
13
12
 
14
13
  module.exports = {
15
14
  constants: constants,
@@ -1,31 +1,31 @@
1
- const _ = require("lodash");
1
+ const _ = require('lodash');
2
2
 
3
3
  class SchemaComponentsMap {
4
- /**
5
- * @type {Record<string, SchemaComponent>}
6
- */
7
- data = {};
8
- /**
9
- * @type {CodeGenConfig}
10
- */
4
+ /** @type {SchemaComponent[]} */
5
+ _data = [];
6
+ /** @type {CodeGenConfig} */
11
7
  config;
12
8
 
13
- constructor(config, schema) {
9
+ constructor({ config }) {
14
10
  this.config = config;
15
- this.processSchema(schema);
16
11
  }
17
12
 
18
- processSchema(schema) {
19
- this.data = {};
20
- if (!schema) return;
21
- _.each(schema.components, (component, componentName) =>
22
- _.each(component, (rawTypeData, typeName) => this.createComponent(componentName, typeName, rawTypeData)),
23
- );
13
+ clear() {
14
+ this._data = [];
24
15
  }
25
16
 
26
- createComponent(componentName, typeName, rawTypeData) {
27
- const $ref = `#/components/${componentName}/${typeName}`;
17
+ createRef = (paths) => {
18
+ return ['#', ...paths].join('/');
19
+ };
20
+
21
+ parseRef = (ref) => {
22
+ return ref.split('/');
23
+ };
28
24
 
25
+ createComponent($ref, rawTypeData) {
26
+ const parsed = this.parseRef($ref);
27
+ const typeName = parsed[parsed.length - 1];
28
+ const componentName = parsed[parsed.length - 2];
29
29
  const componentSchema = {
30
30
  $ref,
31
31
  typeName,
@@ -35,23 +35,39 @@ class SchemaComponentsMap {
35
35
  typeData: null,
36
36
  };
37
37
 
38
- const usageComponent = this.config.hooks.onCreateComponent(componentSchema) || componentSchema;
38
+ const usageComponent =
39
+ this.config.hooks.onCreateComponent(componentSchema) || componentSchema;
40
+
41
+ const refIndex = this._data.findIndex((c) => c.$ref === $ref);
39
42
 
40
- this.data[$ref] = usageComponent;
43
+ if (refIndex === -1) {
44
+ this._data.push(usageComponent);
45
+ } else {
46
+ this._data[refIndex] = usageComponent;
47
+ }
41
48
 
42
49
  return usageComponent;
43
50
  }
44
51
 
52
+ /**
53
+ * @returns {SchemaComponent[]}
54
+ */
55
+ getComponents() {
56
+ return this._data;
57
+ }
58
+
45
59
  /**
46
60
  * @param componentName {string}
47
61
  * @returns {SchemaComponent[]}
48
62
  */
49
63
  filter(componentName) {
50
- return _.filter(this.data, (v, ref) => _.startsWith(ref, `#/components/${componentName}`));
64
+ return _.filter(this._data, (v) =>
65
+ _.startsWith(v.$ref, `#/components/${componentName}`),
66
+ );
51
67
  }
52
68
 
53
- get(ref) {
54
- return this.data[ref] || null;
69
+ get($ref) {
70
+ return this._data.find((c) => c.$ref === $ref) || null;
55
71
  }
56
72
  }
57
73
 
@@ -0,0 +1,43 @@
1
+ const { MonoSchemaParser } = require('../mono-schema-parser');
2
+ const _ = require('lodash');
3
+ const { SCHEMA_TYPES } = require('../../constants');
4
+
5
+ class ArraySchemaParser extends MonoSchemaParser {
6
+ parse() {
7
+ let contentType;
8
+ const { type, description, items } = this.schema || {};
9
+
10
+ if (_.isArray(items) && type === SCHEMA_TYPES.ARRAY) {
11
+ const tupleContent = [];
12
+ for (const item of items) {
13
+ tupleContent.push(
14
+ this.schemaParserFabric
15
+ .createSchemaParser({ schema: item, schemaPath: this.schemaPath })
16
+ .getInlineParseContent(),
17
+ );
18
+ }
19
+ contentType = this.config.Ts.Tuple(tupleContent);
20
+ } else {
21
+ const content = this.schemaParserFabric
22
+ .createSchemaParser({ schema: items, schemaPath: this.schemaPath })
23
+ .getInlineParseContent();
24
+ contentType = this.config.Ts.ArrayType(content);
25
+ }
26
+
27
+ return {
28
+ ...(_.isObject(this.schema) ? this.schema : {}),
29
+ $schemaPath: this.schemaPath.slice(),
30
+ $parsedSchema: true,
31
+ schemaType: SCHEMA_TYPES.PRIMITIVE,
32
+ type: SCHEMA_TYPES.PRIMITIVE,
33
+ typeIdentifier: this.config.Ts.Keyword.Type,
34
+ name: this.typeName,
35
+ description: this.schemaFormatters.formatDescription(description),
36
+ content: this.schemaUtils.safeAddNullToType(this.schema, contentType),
37
+ };
38
+ }
39
+ }
40
+
41
+ module.exports = {
42
+ ArraySchemaParser,
43
+ };