swagger-typescript-api 12.0.4 → 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 (75) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +1 -1
  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 +99 -7
  11. package/index.js +158 -136
  12. package/package.json +35 -30
  13. package/src/code-formatter.js +28 -13
  14. package/src/code-gen-process.js +367 -264
  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 +166 -98
  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 +58 -44
  35. package/src/schema-parser/schema-parser-fabric.js +131 -0
  36. package/src/schema-parser/schema-parser.js +212 -361
  37. package/src/schema-parser/schema-utils.js +158 -33
  38. package/src/schema-parser/util/enum-key-resolver.js +26 -0
  39. package/src/{schema-parser → schema-routes}/schema-routes.js +472 -203
  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.js → type-name-formatter.js} +35 -20
  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 +50 -58
  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/base/data-contract-jsdoc.ejs +37 -37
  57. package/templates/base/data-contracts.ejs +40 -28
  58. package/templates/base/enum-data-contract.ejs +12 -12
  59. package/templates/base/http-client.ejs +2 -2
  60. package/templates/base/http-clients/axios-http-client.ejs +139 -138
  61. package/templates/base/http-clients/fetch-http-client.ejs +224 -224
  62. package/templates/base/interface-data-contract.ejs +10 -10
  63. package/templates/base/object-field-jsdoc.ejs +28 -28
  64. package/templates/base/route-docs.ejs +30 -30
  65. package/templates/base/route-name.ejs +42 -42
  66. package/templates/base/route-type.ejs +22 -21
  67. package/templates/base/type-data-contract.ejs +15 -15
  68. package/templates/default/api.ejs +69 -65
  69. package/templates/default/procedure-call.ejs +100 -100
  70. package/templates/default/route-types.ejs +32 -28
  71. package/templates/modular/api.ejs +28 -28
  72. package/templates/modular/procedure-call.ejs +100 -100
  73. package/templates/modular/route-types.ejs +18 -18
  74. package/src/templates.js +0 -177
  75. package/src/translators/JavaScript.js +0 -60
@@ -1,22 +1,24 @@
1
- const _ = require("lodash");
2
- const { generateId } = require("../util/id.js");
3
- const { SpecificArgNameResolver } = require("../util/name-resolver.js");
1
+ const _ = require('lodash');
2
+ const { generateId } = require('../util/id.js');
3
+ const {
4
+ SpecificArgNameResolver,
5
+ } = require('./util/specific-arg-name-resolver');
4
6
  const {
5
7
  DEFAULT_BODY_ARG_NAME,
6
8
  RESERVED_BODY_ARG_NAMES,
7
9
  RESERVED_HEADER_ARG_NAMES,
8
10
  RESERVED_PATH_ARG_NAMES,
9
11
  RESERVED_QUERY_ARG_NAMES,
10
- } = require("../constants.js");
11
- const { pascalCase } = require("../util/pascal-case");
12
+ } = require('../constants.js');
13
+ const { camelCase } = require('lodash');
12
14
 
13
15
  const CONTENT_KIND = {
14
- JSON: "JSON",
15
- URL_ENCODED: "URL_ENCODED",
16
- FORM_DATA: "FORM_DATA",
17
- IMAGE: "IMAGE",
18
- OTHER: "OTHER",
19
- TEXT: "TEXT",
16
+ JSON: 'JSON',
17
+ URL_ENCODED: 'URL_ENCODED',
18
+ FORM_DATA: 'FORM_DATA',
19
+ IMAGE: 'IMAGE',
20
+ OTHER: 'OTHER',
21
+ TEXT: 'TEXT',
20
22
  };
21
23
 
22
24
  class SchemaRoutes {
@@ -25,29 +27,29 @@ class SchemaRoutes {
25
27
  */
26
28
  config;
27
29
  /**
28
- * @type {SchemaParser}
30
+ * @type {SchemaParserFabric}
29
31
  */
30
- schemaParser;
32
+ schemaParserFabric;
31
33
  /**
32
34
  * @type {SchemaUtils}
33
35
  */
34
36
  schemaUtils;
35
37
  /**
36
- * @type {TypeName}
38
+ * @type {TypeNameFormatter}
37
39
  */
38
- typeName;
40
+ typeNameFormatter;
39
41
  /**
40
42
  * @type {SchemaComponentsMap}
41
43
  */
42
- schemaComponentMap;
44
+ schemaComponentsMap;
43
45
  /**
44
46
  * @type {Logger}
45
47
  */
46
48
  logger;
47
49
  /**
48
- * @type {Templates}
50
+ * @type {TemplatesWorker}
49
51
  */
50
- templates;
52
+ templatesWorker;
51
53
 
52
54
  FORM_DATA_TYPES = [];
53
55
 
@@ -56,28 +58,38 @@ class SchemaRoutes {
56
58
  hasQueryRoutes = false;
57
59
  hasFormDataRoutes = false;
58
60
 
59
- constructor(config, schemaParser, schemaComponentMap, logger, templates, typeName) {
61
+ constructor({
62
+ config,
63
+ schemaParserFabric,
64
+ schemaComponentsMap,
65
+ logger,
66
+ templatesWorker,
67
+ typeNameFormatter,
68
+ }) {
60
69
  this.config = config;
61
- this.schemaParser = schemaParser;
62
- this.schemaUtils = this.schemaParser.schemaUtils;
63
- this.typeName = typeName;
64
- this.schemaComponentMap = schemaComponentMap;
70
+ this.schemaParserFabric = schemaParserFabric;
71
+ this.schemaUtils = this.schemaParserFabric.schemaUtils;
72
+ this.typeNameFormatter = typeNameFormatter;
73
+ this.schemaComponentsMap = schemaComponentsMap;
65
74
  this.logger = logger;
66
- this.templates = templates;
75
+ this.templatesWorker = templatesWorker;
67
76
 
68
77
  this.FORM_DATA_TYPES = _.uniq([
69
- this.schemaParser.getSchemaType({ type: "string", format: "file" }),
70
- this.schemaParser.getSchemaType({ type: "string", format: "binary" }),
78
+ this.schemaUtils.getSchemaType({ type: 'string', format: 'file' }),
79
+ this.schemaUtils.getSchemaType({ type: 'string', format: 'binary' }),
71
80
  ]);
72
81
  }
73
82
 
74
83
  createRequestsMap = (routeInfoByMethodsMap) => {
75
- const parameters = _.get(routeInfoByMethodsMap, "parameters");
84
+ const parameters = _.get(routeInfoByMethodsMap, 'parameters');
76
85
 
77
86
  return _.reduce(
78
87
  routeInfoByMethodsMap,
79
88
  (acc, requestInfo, method) => {
80
- if (_.startsWith(method, "x-") || ["parameters", "$ref"].includes(method)) {
89
+ if (
90
+ _.startsWith(method, 'x-') ||
91
+ ['parameters', '$ref'].includes(method)
92
+ ) {
81
93
  return acc;
82
94
  }
83
95
 
@@ -93,34 +105,36 @@ class SchemaRoutes {
93
105
  };
94
106
 
95
107
  parseRouteName = (originalRouteName) => {
96
- const routeName = this.config.hooks.onPreBuildRoutePath(originalRouteName) || originalRouteName;
108
+ const routeName =
109
+ this.config.hooks.onPreBuildRoutePath(originalRouteName) ||
110
+ originalRouteName;
97
111
 
98
- const pathParamMatches = (routeName || "").match(
99
- /({(([a-zA-Z]-?_?\.?){1,})([0-9]{1,})?})|(:(([a-zA-Z]-?_?\.?){1,})([0-9]{1,})?:?)/g,
112
+ const pathParamMatches = (routeName || '').match(
113
+ /({(([A-z]){1}([a-zA-Z0-9]-?_?\.?)+)([0-9]+)?})|(:(([A-z]){1}([a-zA-Z0-9]-?_?\.?)+)([0-9]+)?:?)/g,
100
114
  );
101
115
 
102
116
  // used in case when path parameters is not declared in requestInfo.parameters ("in": "path")
103
117
  const pathParams = _.reduce(
104
118
  pathParamMatches,
105
119
  (pathParams, match) => {
106
- const paramName = _.replace(match, /\{|\}|\:/g, "");
120
+ const paramName = _.replace(match, /\{|\}|:/g, '');
107
121
 
108
122
  if (!paramName) return pathParams;
109
123
 
110
- if (_.includes(paramName, "-")) {
111
- this.logger.warn("wrong path param name", paramName);
124
+ if (_.includes(paramName, '-')) {
125
+ this.logger.warn('wrong path param name', paramName);
112
126
  }
113
127
 
114
128
  pathParams.push({
115
129
  $match: match,
116
130
  name: _.camelCase(paramName),
117
131
  required: true,
118
- type: "string",
119
- description: "",
132
+ type: 'string',
133
+ description: '',
120
134
  schema: {
121
- type: "string",
135
+ type: 'string',
122
136
  },
123
- in: "path",
137
+ in: 'path',
124
138
  });
125
139
 
126
140
  return pathParams;
@@ -131,10 +145,16 @@ class SchemaRoutes {
131
145
  let fixedRoute = _.reduce(
132
146
  pathParams,
133
147
  (fixedRoute, pathParam, i, arr) => {
134
- const insertion = this.config.hooks.onInsertPathParam(pathParam.name, i, arr, fixedRoute) || pathParam.name;
148
+ const insertion =
149
+ this.config.hooks.onInsertPathParam(
150
+ pathParam.name,
151
+ i,
152
+ arr,
153
+ fixedRoute,
154
+ ) || pathParam.name;
135
155
  return _.replace(fixedRoute, pathParam.$match, `\${${insertion}}`);
136
156
  },
137
- routeName || "",
157
+ routeName || '',
138
158
  );
139
159
 
140
160
  const queryParamMatches = fixedRoute.match(/(\{\?.*\})/g);
@@ -142,35 +162,35 @@ class SchemaRoutes {
142
162
 
143
163
  if (queryParamMatches && queryParamMatches.length) {
144
164
  queryParamMatches.forEach((match) => {
145
- fixedRoute = fixedRoute.replace(match, "");
165
+ fixedRoute = fixedRoute.replace(match, '');
146
166
  });
147
167
 
148
168
  _.uniq(
149
169
  queryParamMatches
150
- .join(",")
151
- .replace(/(\{\?)|(\})|\s/g, "")
152
- .split(","),
170
+ .join(',')
171
+ .replace(/(\{\?)|(\})|\s/g, '')
172
+ .split(','),
153
173
  ).forEach((paramName) => {
154
- if (_.includes(paramName, "-")) {
155
- this.logger.warn("wrong query param name", paramName);
174
+ if (_.includes(paramName, '-')) {
175
+ this.logger.warn('wrong query param name', paramName);
156
176
  }
157
177
 
158
178
  queryParams.push({
159
179
  $match: paramName,
160
180
  name: _.camelCase(paramName),
161
181
  required: true,
162
- type: "string",
163
- description: "",
182
+ type: 'string',
183
+ description: '',
164
184
  schema: {
165
- type: "string",
185
+ type: 'string',
166
186
  },
167
- in: "query",
187
+ in: 'query',
168
188
  });
169
189
  });
170
190
  }
171
191
 
172
192
  const result = {
173
- originalRoute: originalRouteName || "",
193
+ originalRoute: originalRouteName || '',
174
194
  route: fixedRoute,
175
195
  pathParams,
176
196
  queryParams,
@@ -179,7 +199,11 @@ class SchemaRoutes {
179
199
  return this.config.hooks.onBuildRoutePath(result) || result;
180
200
  };
181
201
 
182
- getRouteParams = (routeInfo, pathParamsFromRouteName, queryParamsFromRouteName) => {
202
+ getRouteParams = (
203
+ routeInfo,
204
+ pathParamsFromRouteName,
205
+ queryParamsFromRouteName,
206
+ ) => {
183
207
  const { parameters } = routeInfo;
184
208
 
185
209
  const routeParams = {
@@ -192,10 +216,15 @@ class SchemaRoutes {
192
216
  };
193
217
 
194
218
  _.each(parameters, (parameter) => {
195
- const refTypeInfo = this.schemaParser.schemaUtils.getSchemaRefType(parameter);
219
+ const refTypeInfo =
220
+ this.schemaParserFabric.schemaUtils.getSchemaRefType(parameter);
196
221
  let routeParam = null;
197
222
 
198
- if (refTypeInfo && refTypeInfo.rawTypeData.in && refTypeInfo.rawTypeData) {
223
+ if (
224
+ refTypeInfo &&
225
+ refTypeInfo.rawTypeData.in &&
226
+ refTypeInfo.rawTypeData
227
+ ) {
199
228
  if (!routeParams[refTypeInfo.rawTypeData.in]) {
200
229
  routeParams[refTypeInfo.rawTypeData.in] = [];
201
230
  }
@@ -217,7 +246,7 @@ class SchemaRoutes {
217
246
  };
218
247
  }
219
248
 
220
- if (routeParam.in === "path") {
249
+ if (routeParam.in === 'path') {
221
250
  if (!routeParam.name) return;
222
251
 
223
252
  routeParam.name = _.camelCase(routeParam.name);
@@ -230,7 +259,10 @@ class SchemaRoutes {
230
259
 
231
260
  // used in case when path parameters is not declared in requestInfo.parameters ("in": "path")
232
261
  _.each(pathParamsFromRouteName, (pathParam) => {
233
- const alreadyExist = _.some(routeParams.path, (parameter) => parameter.name === pathParam.name);
262
+ const alreadyExist = _.some(
263
+ routeParams.path,
264
+ (parameter) => parameter.name === pathParam.name,
265
+ );
234
266
 
235
267
  if (!alreadyExist) {
236
268
  routeParams.path.push(pathParam);
@@ -238,7 +270,10 @@ class SchemaRoutes {
238
270
  });
239
271
  // used in case when path parameters is not declared in requestInfo.parameters ("in": "path")
240
272
  _.each(queryParamsFromRouteName, (queryParam) => {
241
- const alreadyExist = _.some(routeParams.query, (parameter) => parameter.name === queryParam.name);
273
+ const alreadyExist = _.some(
274
+ routeParams.query,
275
+ (parameter) => parameter.name === queryParam.name,
276
+ );
242
277
 
243
278
  if (!alreadyExist) {
244
279
  routeParams.query.push(queryParam);
@@ -252,31 +287,43 @@ class SchemaRoutes {
252
287
  _.uniq(
253
288
  _.compact([
254
289
  ...(extraContentTypes || []),
255
- ..._.flatten(_.map(requestInfo, (requestInfoData) => requestInfoData && _.keys(requestInfoData.content))),
290
+ ..._.flatten(
291
+ _.map(
292
+ requestInfo,
293
+ (requestInfoData) =>
294
+ requestInfoData && _.keys(requestInfoData.content),
295
+ ),
296
+ ),
256
297
  ]),
257
298
  );
258
299
 
259
300
  getContentKind = (contentTypes) => {
260
301
  if (
261
- _.some(contentTypes, (contentType) => _.startsWith(contentType, "application/json")) ||
262
- _.some(contentTypes, (contentType) => _.endsWith(contentType, "+json"))
302
+ _.some(contentTypes, (contentType) =>
303
+ _.startsWith(contentType, 'application/json'),
304
+ ) ||
305
+ _.some(contentTypes, (contentType) => _.endsWith(contentType, '+json'))
263
306
  ) {
264
307
  return CONTENT_KIND.JSON;
265
308
  }
266
309
 
267
- if (contentTypes.includes("application/x-www-form-urlencoded")) {
310
+ if (contentTypes.includes('application/x-www-form-urlencoded')) {
268
311
  return CONTENT_KIND.URL_ENCODED;
269
312
  }
270
313
 
271
- if (contentTypes.includes("multipart/form-data")) {
314
+ if (contentTypes.includes('multipart/form-data')) {
272
315
  return CONTENT_KIND.FORM_DATA;
273
316
  }
274
317
 
275
- if (_.some(contentTypes, (contentType) => _.includes(contentType, "image/"))) {
318
+ if (
319
+ _.some(contentTypes, (contentType) => _.includes(contentType, 'image/'))
320
+ ) {
276
321
  return CONTENT_KIND.IMAGE;
277
322
  }
278
323
 
279
- if (_.some(contentTypes, (contentType) => _.startsWith(contentType, "text/"))) {
324
+ if (
325
+ _.some(contentTypes, (contentType) => _.startsWith(contentType, 'text/'))
326
+ ) {
280
327
  return CONTENT_KIND.TEXT;
281
328
  }
282
329
 
@@ -284,12 +331,13 @@ class SchemaRoutes {
284
331
  };
285
332
 
286
333
  isSuccessStatus = (status) =>
287
- (this.config.defaultResponseAsSuccess && status === "default") ||
288
- (+status >= this.config.successResponseStatusRange[0] && +status <= this.config.successResponseStatusRange[1]) ||
289
- status === "2xx";
334
+ (this.config.defaultResponseAsSuccess && status === 'default') ||
335
+ (+status >= this.config.successResponseStatusRange[0] &&
336
+ +status <= this.config.successResponseStatusRange[1]) ||
337
+ status === '2xx';
290
338
 
291
339
  getSchemaFromRequestType = (requestInfo) => {
292
- const content = _.get(requestInfo, "content");
340
+ const content = _.get(requestInfo, 'content');
293
341
 
294
342
  if (!content) return null;
295
343
 
@@ -308,22 +356,38 @@ class SchemaRoutes {
308
356
  return null;
309
357
  };
310
358
 
311
- getTypeFromRequestInfo = ({ requestInfo, parsedSchemas, operationId, defaultType, typeName }) => {
359
+ getTypeFromRequestInfo = ({
360
+ requestInfo,
361
+ parsedSchemas,
362
+ operationId,
363
+ defaultType,
364
+ typeName,
365
+ }) => {
312
366
  // TODO: make more flexible pick schema without content type
313
367
  const schema = this.getSchemaFromRequestType(requestInfo);
314
- const refTypeInfo = this.schemaParser.schemaUtils.getSchemaRefType(requestInfo);
368
+ const refTypeInfo =
369
+ this.schemaParserFabric.schemaUtils.getSchemaRefType(requestInfo);
315
370
 
316
371
  if (schema) {
317
- const content = this.schemaParser.getInlineParseContent(schema, typeName);
372
+ const content = this.schemaParserFabric.getInlineParseContent(
373
+ schema,
374
+ typeName,
375
+ [operationId],
376
+ );
318
377
  const foundedSchemaByName = _.find(
319
378
  parsedSchemas,
320
- (parsedSchema) => this.typeName.format(parsedSchema.name) === content,
379
+ (parsedSchema) =>
380
+ this.typeNameFormatter.format(parsedSchema.name) === content,
381
+ );
382
+ const foundSchemaByContent = _.find(parsedSchemas, (parsedSchema) =>
383
+ _.isEqual(parsedSchema.content, content),
321
384
  );
322
- const foundSchemaByContent = _.find(parsedSchemas, (parsedSchema) => _.isEqual(parsedSchema.content, content));
323
385
 
324
386
  const foundSchema = foundedSchemaByName || foundSchemaByContent;
325
387
 
326
- return foundSchema ? this.typeName.format(foundSchema.name) : content;
388
+ return foundSchema
389
+ ? this.typeNameFormatter.format(foundSchema.name)
390
+ : content;
327
391
  }
328
392
 
329
393
  if (refTypeInfo) {
@@ -331,29 +395,45 @@ class SchemaRoutes {
331
395
  // const foundedSchemaByName = _.find(parsedSchemas, ({ name }) => name === refType || name === refTypeWithoutOpId)
332
396
 
333
397
  // TODO:HACK fix problem of swagger2opeanpi
334
- const typeNameWithoutOpId = _.replace(refTypeInfo.typeName, operationId, "");
335
- if (_.find(parsedSchemas, (schema) => schema.name === typeNameWithoutOpId)) {
336
- return this.typeName.format(typeNameWithoutOpId);
398
+ const typeNameWithoutOpId = _.replace(
399
+ refTypeInfo.typeName,
400
+ operationId,
401
+ '',
402
+ );
403
+ if (
404
+ _.find(parsedSchemas, (schema) => schema.name === typeNameWithoutOpId)
405
+ ) {
406
+ return this.typeNameFormatter.format(typeNameWithoutOpId);
337
407
  }
338
408
 
339
409
  switch (refTypeInfo.componentName) {
340
- case "schemas":
341
- return this.typeName.format(refTypeInfo.typeName);
342
- case "responses":
343
- case "requestBodies":
344
- return this.schemaParser.getInlineParseContent(
410
+ case 'schemas':
411
+ return this.typeNameFormatter.format(refTypeInfo.typeName);
412
+ case 'responses':
413
+ case 'requestBodies':
414
+ return this.schemaParserFabric.getInlineParseContent(
345
415
  this.getSchemaFromRequestType(refTypeInfo.rawTypeData),
346
416
  refTypeInfo.typeName || null,
417
+ [operationId],
347
418
  );
348
419
  default:
349
- return this.schemaParser.getInlineParseContent(refTypeInfo.rawTypeData, refTypeInfo.typeName || null);
420
+ return this.schemaParserFabric.getInlineParseContent(
421
+ refTypeInfo.rawTypeData,
422
+ refTypeInfo.typeName || null,
423
+ [operationId],
424
+ );
350
425
  }
351
426
  }
352
427
 
353
428
  return defaultType || this.config.Ts.Keyword.Any;
354
429
  };
355
430
 
356
- getRequestInfoTypes = ({ requestInfos, parsedSchemas, operationId, defaultType }) =>
431
+ getRequestInfoTypes = ({
432
+ requestInfos,
433
+ parsedSchemas,
434
+ operationId,
435
+ defaultType,
436
+ }) =>
357
437
  _.reduce(
358
438
  requestInfos,
359
439
  (acc, requestInfo, status) => {
@@ -365,7 +445,7 @@ class SchemaRoutes {
365
445
  ...(requestInfo || {}),
366
446
  contentTypes: contentTypes,
367
447
  contentKind: this.getContentKind(contentTypes),
368
- type: this.schemaParser.schemaUtils.safeAddNullToType(
448
+ type: this.schemaParserFabric.schemaUtils.safeAddNullToType(
369
449
  requestInfo,
370
450
  this.getTypeFromRequestInfo({
371
451
  requestInfo,
@@ -374,7 +454,11 @@ class SchemaRoutes {
374
454
  defaultType,
375
455
  }),
376
456
  ),
377
- description: this.schemaParser.schemaFormatters.formatDescription(requestInfo.description || "", true),
457
+ description:
458
+ this.schemaParserFabric.schemaFormatters.formatDescription(
459
+ requestInfo.description || '',
460
+ true,
461
+ ),
378
462
  status: _.isNaN(+status) ? status : +status,
379
463
  isSuccess: this.isSuccessStatus(status),
380
464
  },
@@ -386,7 +470,10 @@ class SchemaRoutes {
386
470
  getResponseBodyInfo = (routeInfo, parsedSchemas) => {
387
471
  const { produces, operationId, responses } = routeInfo;
388
472
 
389
- const contentTypes = this.getContentTypes(responses, [...(produces || []), routeInfo["x-accepts"]]);
473
+ const contentTypes = this.getContentTypes(responses, [
474
+ ...(produces || []),
475
+ routeInfo['x-accepts'],
476
+ ]);
390
477
 
391
478
  const responseInfos = this.getRequestInfoTypes({
392
479
  requestInfos: responses,
@@ -395,23 +482,26 @@ class SchemaRoutes {
395
482
  defaultType: this.config.defaultResponseType,
396
483
  });
397
484
 
398
- const successResponse = responseInfos.find((response) => response.isSuccess);
485
+ const successResponse = responseInfos.find(
486
+ (response) => response.isSuccess,
487
+ );
399
488
  const errorResponses = responseInfos.filter(
400
- (response) => !response.isSuccess && response.type !== this.config.Ts.Keyword.Any,
489
+ (response) =>
490
+ !response.isSuccess && response.type !== this.config.Ts.Keyword.Any,
401
491
  );
402
492
 
403
493
  const handleResponseHeaders = (src) => {
404
494
  if (!src) {
405
- return "headers: {},";
495
+ return 'headers: {},';
406
496
  }
407
497
  const headerTypes = Object.fromEntries(
408
498
  Object.entries(src).map(([k, v]) => {
409
- return [k, this.schemaParser.getSchemaType(v)];
499
+ return [k, this.schemaUtils.getSchemaType(v)];
410
500
  }),
411
501
  );
412
502
  const r = `headers: { ${Object.entries(headerTypes)
413
503
  .map(([k, v]) => `"${k}": ${v}`)
414
- .join(",")} },`;
504
+ .join(',')} },`;
415
505
  return r;
416
506
  };
417
507
 
@@ -420,20 +510,27 @@ class SchemaRoutes {
420
510
  responses: responseInfos,
421
511
  success: {
422
512
  schema: successResponse,
423
- type: (successResponse && successResponse.type) || this.config.Ts.Keyword.Any,
513
+ type:
514
+ (successResponse && successResponse.type) ||
515
+ this.config.Ts.Keyword.Any,
424
516
  },
425
517
  error: {
426
518
  schemas: errorResponses,
427
- type: this.config.Ts.UnionType(errorResponses.map((response) => response.type)) || this.config.Ts.Keyword.Any,
519
+ type:
520
+ this.config.Ts.UnionType(
521
+ errorResponses.map((response) => response.type),
522
+ ) || this.config.Ts.Keyword.Any,
428
523
  },
429
524
  full: {
430
525
  types:
431
526
  this.config.Ts.UnionType(
432
527
  responseInfos.map(
433
528
  (response) => `{
434
- data: ${response.type}, status: ${response.status}, statusCode: ${response.status}, statusText: "${
435
- response.description
436
- }", ${handleResponseHeaders(response.headers)} config: {} }`,
529
+ data: ${response.type}, status: ${response.status}, statusCode: ${
530
+ response.status
531
+ }, statusText: "${response.description}", ${handleResponseHeaders(
532
+ response.headers,
533
+ )} config: {} }`,
437
534
  ),
438
535
  ) || this.config.Ts.Keyword.Any,
439
536
  },
@@ -446,20 +543,28 @@ class SchemaRoutes {
446
543
  (objectSchema, schemaPart) => {
447
544
  if (!schemaPart || !schemaPart.name) return objectSchema;
448
545
 
546
+ let usageName = `${schemaPart.name}`;
547
+
548
+ if (usageName.includes('.')) {
549
+ usageName = camelCase(usageName);
550
+ }
551
+
449
552
  return {
450
553
  ...objectSchema,
451
554
  properties: {
452
555
  ...objectSchema.properties,
453
- [schemaPart.name]: {
556
+ [usageName]: {
454
557
  ...schemaPart,
455
558
  ...(schemaPart.schema || {}),
559
+ $origName: schemaPart.name,
560
+ name: usageName,
456
561
  },
457
562
  },
458
563
  };
459
564
  },
460
565
  {
461
566
  properties: {},
462
- type: "object",
567
+ type: 'object',
463
568
  },
464
569
  );
465
570
  };
@@ -467,31 +572,41 @@ class SchemaRoutes {
467
572
  getRequestBodyInfo = (routeInfo, routeParams, parsedSchemas, routeName) => {
468
573
  const { requestBody, consumes, requestBodyName, operationId } = routeInfo;
469
574
  let schema = null;
470
- let type = null;
575
+ let content = null;
471
576
 
472
- const contentTypes = this.getContentTypes([requestBody], [...(consumes || []), routeInfo["x-contentType"]]);
577
+ const contentTypes = this.getContentTypes(
578
+ [requestBody],
579
+ [...(consumes || []), routeInfo['x-contentType']],
580
+ );
473
581
  let contentKind = this.getContentKind(contentTypes);
474
582
 
475
583
  let typeName = null;
476
584
 
477
585
  if (this.config.extractRequestBody) {
478
- typeName = this.schemaUtils.resolveTypeName(
479
- routeName.usage,
480
- this.config.extractingOptions.requestBodySuffix,
481
- this.config.extractingOptions.requestBodyNameResolver,
482
- );
586
+ typeName = this.schemaUtils.resolveTypeName(routeName.usage, {
587
+ suffixes: this.config.extractingOptions.requestBodySuffix,
588
+ resolver: this.config.extractingOptions.requestBodyNameResolver,
589
+ });
483
590
  }
484
591
 
485
592
  if (routeParams.formData.length) {
486
593
  contentKind = CONTENT_KIND.FORM_DATA;
487
594
  schema = this.convertRouteParamsIntoObject(routeParams.formData);
488
- type = this.schemaParser.getInlineParseContent(schema, typeName);
595
+ content = this.schemaParserFabric.getInlineParseContent(
596
+ schema,
597
+ typeName,
598
+ [operationId],
599
+ );
489
600
  } else if (contentKind === CONTENT_KIND.FORM_DATA) {
490
601
  schema = this.getSchemaFromRequestType(requestBody);
491
- type = this.schemaParser.getInlineParseContent(schema, typeName);
602
+ content = this.schemaParserFabric.getInlineParseContent(
603
+ schema,
604
+ typeName,
605
+ [operationId],
606
+ );
492
607
  } else if (requestBody) {
493
608
  schema = this.getSchemaFromRequestType(requestBody);
494
- type = this.schemaParser.schemaUtils.safeAddNullToType(
609
+ content = this.schemaParserFabric.schemaUtils.safeAddNullToType(
495
610
  requestBody,
496
611
  this.getTypeFromRequestInfo({
497
612
  requestInfo: requestBody,
@@ -504,23 +619,38 @@ class SchemaRoutes {
504
619
  // TODO: Refactor that.
505
620
  // It needed for cases when swagger schema is not declared request body type as form data
506
621
  // but request body data type contains form data types like File
507
- if (this.FORM_DATA_TYPES.some((dataType) => _.includes(type, `: ${dataType}`))) {
622
+ if (
623
+ this.FORM_DATA_TYPES.some((dataType) =>
624
+ _.includes(content, `: ${dataType}`),
625
+ )
626
+ ) {
508
627
  contentKind = CONTENT_KIND.FORM_DATA;
509
628
  }
510
629
  }
511
630
 
512
631
  if (schema && !schema.$ref && this.config.extractRequestBody) {
513
- schema = this.schemaComponentMap.createComponent("schemas", typeName, { ...schema });
514
- type = this.schemaParser.getInlineParseContent(schema);
632
+ schema = this.schemaParserFabric.createParsedComponent({
633
+ schema,
634
+ typeName,
635
+ schemaPath: [operationId],
636
+ });
637
+ content = this.schemaParserFabric.getInlineParseContent({
638
+ $ref: schema.$ref,
639
+ });
515
640
  }
516
641
 
517
642
  return {
518
- paramName: requestBodyName || (requestBody && requestBody.name) || DEFAULT_BODY_ARG_NAME,
643
+ paramName:
644
+ requestBodyName ||
645
+ (requestBody && requestBody.name) ||
646
+ DEFAULT_BODY_ARG_NAME,
519
647
  contentTypes,
520
648
  contentKind,
521
649
  schema,
522
- type,
523
- required: requestBody && (typeof requestBody.required === "undefined" || !!requestBody.required),
650
+ type: content,
651
+ required:
652
+ requestBody &&
653
+ (typeof requestBody.required === 'undefined' || !!requestBody.required),
524
654
  };
525
655
  };
526
656
 
@@ -539,7 +669,7 @@ class SchemaRoutes {
539
669
  if (pathArgSchema.name) {
540
670
  acc[pathArgSchema.name] = {
541
671
  ...pathArgSchema,
542
- in: "path",
672
+ in: 'path',
543
673
  };
544
674
  }
545
675
 
@@ -549,12 +679,12 @@ class SchemaRoutes {
549
679
  );
550
680
 
551
681
  const fixedQueryParams = _.reduce(
552
- _.get(queryObjectSchema, "properties", {}),
682
+ _.get(queryObjectSchema, 'properties', {}),
553
683
  (acc, property, name) => {
554
684
  if (name && _.isObject(property)) {
555
685
  acc[name] = {
556
686
  ...property,
557
- in: "query",
687
+ in: 'query',
558
688
  };
559
689
  }
560
690
 
@@ -576,34 +706,50 @@ class SchemaRoutes {
576
706
  if (fixedSchema) return fixedSchema;
577
707
 
578
708
  if (extractRequestParams) {
579
- const typeName = this.schemaUtils.resolveTypeName(
709
+ const generatedTypeName = this.schemaUtils.resolveTypeName(
580
710
  routeName.usage,
581
- this.config.extractingOptions.requestParamsSuffix,
582
- this.config.extractingOptions.requestParamsNameResolver,
711
+ {
712
+ suffixes: this.config.extractingOptions.requestParamsSuffix,
713
+ resolver: this.config.extractingOptions.requestParamsNameResolver,
714
+ },
583
715
  );
584
716
 
585
- return this.schemaComponentMap.createComponent("schemas", typeName, { ...schema });
717
+ return this.schemaParserFabric.createParsedComponent({
718
+ typeName: generatedTypeName,
719
+ schema: schema,
720
+ });
586
721
  }
587
722
 
588
723
  return schema;
589
724
  };
590
725
 
591
726
  extractResponseBodyIfItNeeded = (routeInfo, responseBodyInfo, routeName) => {
592
- if (responseBodyInfo.responses.length && responseBodyInfo.success && responseBodyInfo.success.schema) {
593
- const typeName = this.schemaUtils.resolveTypeName(
594
- routeName.usage,
595
- this.config.extractingOptions.responseBodySuffix,
596
- this.config.extractingOptions.responseBodyNameResolver,
597
- );
727
+ if (
728
+ responseBodyInfo.responses.length &&
729
+ responseBodyInfo.success &&
730
+ responseBodyInfo.success.schema
731
+ ) {
732
+ const typeName = this.schemaUtils.resolveTypeName(routeName.usage, {
733
+ suffixes: this.config.extractingOptions.responseBodySuffix,
734
+ resolver: this.config.extractingOptions.responseBodyNameResolver,
735
+ });
598
736
 
599
- const idx = responseBodyInfo.responses.indexOf(responseBodyInfo.success.schema);
737
+ const idx = responseBodyInfo.responses.indexOf(
738
+ responseBodyInfo.success.schema,
739
+ );
600
740
 
601
741
  let successResponse = responseBodyInfo.success;
602
742
 
603
743
  if (successResponse.schema && !successResponse.schema.$ref) {
604
744
  const schema = this.getSchemaFromRequestType(successResponse.schema);
605
- successResponse.schema = this.schemaComponentMap.createComponent("schemas", typeName, { ...schema });
606
- successResponse.type = this.schemaParser.getInlineParseContent(successResponse.schema);
745
+ successResponse.schema = this.schemaParserFabric.createParsedComponent({
746
+ schema,
747
+ typeName,
748
+ schemaPath: [routeInfo.operationId],
749
+ });
750
+ successResponse.type = this.schemaParserFabric.getInlineParseContent({
751
+ $ref: successResponse.schema.$ref,
752
+ });
607
753
 
608
754
  if (idx > -1) {
609
755
  _.assign(responseBodyInfo.responses[idx], {
@@ -616,31 +762,45 @@ class SchemaRoutes {
616
762
  };
617
763
 
618
764
  extractResponseErrorIfItNeeded = (routeInfo, responseBodyInfo, routeName) => {
619
- if (responseBodyInfo.responses.length && responseBodyInfo.error.schemas && responseBodyInfo.error.schemas.length) {
620
- const typeName = this.schemaUtils.resolveTypeName(
621
- routeName.usage,
622
- this.config.extractingOptions.responseErrorSuffix,
623
- this.config.extractingOptions.responseErrorNameResolver,
624
- );
765
+ if (
766
+ responseBodyInfo.responses.length &&
767
+ responseBodyInfo.error.schemas &&
768
+ responseBodyInfo.error.schemas.length
769
+ ) {
770
+ const typeName = this.schemaUtils.resolveTypeName(routeName.usage, {
771
+ suffixes: this.config.extractingOptions.responseErrorSuffix,
772
+ resolver: this.config.extractingOptions.responseErrorNameResolver,
773
+ });
625
774
 
626
- const errorSchemas = responseBodyInfo.error.schemas.map(this.getSchemaFromRequestType).filter(Boolean);
775
+ const errorSchemas = responseBodyInfo.error.schemas
776
+ .map(this.getSchemaFromRequestType)
777
+ .filter(Boolean);
627
778
 
628
779
  if (!errorSchemas.length) return;
629
780
 
630
- const schema = this.schemaParser.parseSchema({
631
- oneOf: errorSchemas,
632
- title: errorSchemas
633
- .map((schema) => schema.title)
634
- .filter(Boolean)
635
- .join(" "),
636
- description: errorSchemas
637
- .map((schema) => schema.description)
638
- .filter(Boolean)
639
- .join("\n"),
640
- });
641
- const component = this.schemaComponentMap.createComponent("schemas", typeName, { ...schema });
781
+ const schema = this.schemaParserFabric.parseSchema(
782
+ {
783
+ oneOf: errorSchemas,
784
+ title: errorSchemas
785
+ .map((schema) => schema.title)
786
+ .filter(Boolean)
787
+ .join(' '),
788
+ description: errorSchemas
789
+ .map((schema) => schema.description)
790
+ .filter(Boolean)
791
+ .join('\n'),
792
+ },
793
+ null,
794
+ [routeInfo.operationId],
795
+ );
796
+ const component = this.schemaComponentsMap.createComponent(
797
+ this.schemaComponentsMap.createRef(['components', 'schemas', typeName]),
798
+ { ...schema },
799
+ );
642
800
  responseBodyInfo.error.schemas = [component];
643
- responseBodyInfo.error.type = this.typeName.format(component.typeName);
801
+ responseBodyInfo.error.type = this.typeNameFormatter.format(
802
+ component.typeName,
803
+ );
644
804
  }
645
805
  };
646
806
 
@@ -649,16 +809,26 @@ class SchemaRoutes {
649
809
  const { routeNameDuplicatesMap, templatesToRender } = this.config;
650
810
  const routeNameTemplate = templatesToRender.routeName;
651
811
 
652
- const routeNameFromTemplate = this.templates.renderTemplate(routeNameTemplate, {
653
- routeInfo: rawRouteInfo,
654
- });
812
+ const routeNameFromTemplate = this.templatesWorker.renderTemplate(
813
+ routeNameTemplate,
814
+ {
815
+ routeInfo: rawRouteInfo,
816
+ },
817
+ );
655
818
 
656
- const routeName = this.config.hooks.onFormatRouteName(rawRouteInfo, routeNameFromTemplate) || routeNameFromTemplate;
819
+ const routeName =
820
+ this.config.hooks.onFormatRouteName(
821
+ rawRouteInfo,
822
+ routeNameFromTemplate,
823
+ ) || routeNameFromTemplate;
657
824
 
658
825
  const duplicateIdentifier = `${moduleName}|${routeName}`;
659
826
 
660
827
  if (routeNameDuplicatesMap.has(duplicateIdentifier)) {
661
- routeNameDuplicatesMap.set(duplicateIdentifier, routeNameDuplicatesMap.get(duplicateIdentifier) + 1);
828
+ routeNameDuplicatesMap.set(
829
+ duplicateIdentifier,
830
+ routeNameDuplicatesMap.get(duplicateIdentifier) + 1,
831
+ );
662
832
 
663
833
  this.logger.warn(
664
834
  `Module "${moduleName}" already has method "${routeName}()"`,
@@ -673,26 +843,38 @@ class SchemaRoutes {
673
843
  const duplicates = routeNameDuplicatesMap.get(duplicateIdentifier);
674
844
 
675
845
  const routeNameInfo = {
676
- usage: routeName + (duplicates > 1 ? duplicates : ""),
846
+ usage: routeName + (duplicates > 1 ? duplicates : ''),
677
847
  original: routeName,
678
848
  duplicate: duplicates > 1,
679
849
  };
680
850
 
681
- return this.config.hooks.onCreateRouteName(routeNameInfo, rawRouteInfo) || routeNameInfo;
851
+ return (
852
+ this.config.hooks.onCreateRouteName(routeNameInfo, rawRouteInfo) ||
853
+ routeNameInfo
854
+ );
682
855
  };
683
856
 
684
- parseRouteInfo = (rawRouteName, routeInfo, method, usageSchema, parsedSchemas) => {
857
+ parseRouteInfo = (
858
+ rawRouteName,
859
+ routeInfo,
860
+ method,
861
+ usageSchema,
862
+ parsedSchemas,
863
+ ) => {
685
864
  const { security: globalSecurity } = usageSchema;
686
- const { moduleNameIndex, moduleNameFirstTag, extractRequestParams } = this.config;
865
+ const { moduleNameIndex, moduleNameFirstTag, extractRequestParams } =
866
+ this.config;
687
867
  const {
688
868
  operationId,
689
869
  requestBody,
690
870
  security,
871
+ // eslint-disable-next-line no-unused-vars
691
872
  parameters,
692
873
  summary,
693
874
  description,
694
875
  tags,
695
876
  responses,
877
+ // eslint-disable-next-line no-unused-vars
696
878
  requestBodyName,
697
879
  produces,
698
880
  consumes,
@@ -709,13 +891,17 @@ class SchemaRoutes {
709
891
  const moduleName =
710
892
  moduleNameFirstTag && firstTag
711
893
  ? _.camelCase(firstTag)
712
- : _.camelCase(_.compact(_.split(route, "/"))[moduleNameIndex]);
894
+ : _.camelCase(_.compact(_.split(route, '/'))[moduleNameIndex]);
713
895
  let hasSecurity = !!(globalSecurity && globalSecurity.length);
714
896
  if (security) {
715
897
  hasSecurity = security.length > 0;
716
898
  }
717
899
 
718
- const routeParams = this.getRouteParams(routeInfo, pathParamsFromRouteName, queryParamsFromRouteName);
900
+ const routeParams = this.getRouteParams(
901
+ routeInfo,
902
+ pathParamsFromRouteName,
903
+ queryParamsFromRouteName,
904
+ );
719
905
 
720
906
  const pathArgs = routeParams.path.map((pathArgSchema) => ({
721
907
  name: pathArgSchema.name,
@@ -745,13 +931,24 @@ class SchemaRoutes {
745
931
  consumes,
746
932
  };
747
933
 
748
- const queryObjectSchema = this.convertRouteParamsIntoObject(routeParams.query);
749
- const pathObjectSchema = this.convertRouteParamsIntoObject(routeParams.path);
750
- const headersObjectSchema = this.convertRouteParamsIntoObject(routeParams.header);
934
+ const queryObjectSchema = this.convertRouteParamsIntoObject(
935
+ routeParams.query,
936
+ );
937
+ const pathObjectSchema = this.convertRouteParamsIntoObject(
938
+ routeParams.path,
939
+ );
940
+ const headersObjectSchema = this.convertRouteParamsIntoObject(
941
+ routeParams.header,
942
+ );
751
943
 
752
944
  const routeName = this.getRouteName(rawRouteInfo);
753
945
 
754
- const requestBodyInfo = this.getRequestBodyInfo(routeInfo, routeParams, parsedSchemas, routeName);
946
+ const requestBodyInfo = this.getRequestBodyInfo(
947
+ routeInfo,
948
+ routeParams,
949
+ parsedSchemas,
950
+ routeName,
951
+ );
755
952
 
756
953
  const requestParamsSchema = this.createRequestParamsSchema({
757
954
  queryParams: routeParams.query,
@@ -762,42 +959,68 @@ class SchemaRoutes {
762
959
  });
763
960
 
764
961
  if (this.config.extractResponseBody) {
765
- this.extractResponseBodyIfItNeeded(routeInfo, responseBodyInfo, routeName);
962
+ this.extractResponseBodyIfItNeeded(
963
+ routeInfo,
964
+ responseBodyInfo,
965
+ routeName,
966
+ );
766
967
  }
767
968
  if (this.config.extractResponseError) {
768
- this.extractResponseErrorIfItNeeded(routeInfo, responseBodyInfo, routeName);
969
+ this.extractResponseErrorIfItNeeded(
970
+ routeInfo,
971
+ responseBodyInfo,
972
+ routeName,
973
+ );
769
974
  }
770
975
 
771
- const typeName = this.schemaUtils.resolveTypeName(
772
- routeName.usage,
773
- this.config.extractingOptions.requestParamsSuffix,
774
- this.config.extractingOptions.requestParamsNameResolver,
775
- false,
776
- );
976
+ const typeName = this.schemaUtils.resolveTypeName(routeName.usage, {
977
+ suffixes: this.config.extractingOptions.requestParamsSuffix,
978
+ resolver: this.config.extractingOptions.requestParamsNameResolver,
979
+ shouldReserve: false,
980
+ });
777
981
 
778
982
  const queryType = routeParams.query.length
779
- ? this.schemaParser.getInlineParseContent(queryObjectSchema, typeName)
983
+ ? this.schemaParserFabric.getInlineParseContent(queryObjectSchema, null, [
984
+ typeName,
985
+ ])
780
986
  : null;
781
987
  const pathType = routeParams.path.length
782
- ? this.schemaParser.getInlineParseContent(pathObjectSchema, typeName)
988
+ ? this.schemaParserFabric.getInlineParseContent(pathObjectSchema, null, [
989
+ typeName,
990
+ ])
783
991
  : null;
784
992
  const headersType = routeParams.header.length
785
- ? this.schemaParser.getInlineParseContent(headersObjectSchema, typeName)
993
+ ? this.schemaParserFabric.getInlineParseContent(
994
+ headersObjectSchema,
995
+ null,
996
+ [typeName],
997
+ )
786
998
  : null;
787
999
 
788
- const nameResolver = new SpecificArgNameResolver(this.logger, pathArgsNames);
1000
+ const nameResolver = new SpecificArgNameResolver(
1001
+ this.config,
1002
+ this.logger,
1003
+ pathArgsNames,
1004
+ );
789
1005
 
790
1006
  const specificArgs = {
791
1007
  query: queryType
792
1008
  ? {
793
1009
  name: nameResolver.resolve(RESERVED_QUERY_ARG_NAMES),
794
- optional: this.schemaParser.parseSchema(queryObjectSchema).allFieldsAreOptional,
1010
+ optional: this.schemaParserFabric.parseSchema(
1011
+ queryObjectSchema,
1012
+ null,
1013
+ [routeName.usage],
1014
+ ).allFieldsAreOptional,
795
1015
  type: queryType,
796
1016
  }
797
1017
  : void 0,
798
1018
  body: requestBodyInfo.type
799
1019
  ? {
800
- name: nameResolver.resolve([requestBodyInfo.paramName, ...RESERVED_BODY_ARG_NAMES]),
1020
+ name: nameResolver.resolve([
1021
+ requestBodyInfo.paramName,
1022
+ ...RESERVED_BODY_ARG_NAMES,
1023
+ ]),
801
1024
  optional: !requestBodyInfo.required,
802
1025
  type: requestBodyInfo.type,
803
1026
  }
@@ -805,26 +1028,38 @@ class SchemaRoutes {
805
1028
  pathParams: pathType
806
1029
  ? {
807
1030
  name: nameResolver.resolve(RESERVED_PATH_ARG_NAMES),
808
- optional: this.schemaParser.parseSchema(pathObjectSchema).allFieldsAreOptional,
1031
+ optional: this.schemaParserFabric.parseSchema(
1032
+ pathObjectSchema,
1033
+ null,
1034
+ [routeName.usage],
1035
+ ).allFieldsAreOptional,
809
1036
  type: pathType,
810
1037
  }
811
1038
  : void 0,
812
1039
  headers: headersType
813
1040
  ? {
814
1041
  name: nameResolver.resolve(RESERVED_HEADER_ARG_NAMES),
815
- optional: this.schemaParser.parseSchema(headersObjectSchema).allFieldsAreOptional,
1042
+ optional: this.schemaParserFabric.parseSchema(
1043
+ headersObjectSchema,
1044
+ null,
1045
+ [routeName.usage],
1046
+ ).allFieldsAreOptional,
816
1047
  type: headersType,
817
1048
  }
818
1049
  : void 0,
819
1050
  };
820
1051
 
821
1052
  pathArgs.forEach((pathArg, i) => {
822
- pathArg.type = this.schemaParser.getInlineParseContent(routeParams.path[i].schema, typeName);
1053
+ pathArg.type = this.schemaParserFabric.getInlineParseContent(
1054
+ routeParams.path[i].schema,
1055
+ null,
1056
+ [typeName],
1057
+ );
823
1058
  });
824
1059
 
825
1060
  return {
826
1061
  id: routeId,
827
- namespace: _.replace(moduleName, /^(\d)/, "v$1"),
1062
+ namespace: _.replace(moduleName, /^(\d)/, 'v$1'),
828
1063
  routeName,
829
1064
  routeParams,
830
1065
  requestBodyInfo,
@@ -870,22 +1105,29 @@ class SchemaRoutes {
870
1105
  const routeInfosMap = this.createRequestsMap(routeInfoByMethodsMap);
871
1106
 
872
1107
  _.forEach(routeInfosMap, (routeInfo, method) => {
873
- const parsedRouteInfo = this.parseRouteInfo(rawRouteName, routeInfo, method, usageSchema, parsedSchemas);
874
- const processedRouteInfo = this.config.hooks.onCreateRoute(parsedRouteInfo);
1108
+ const parsedRouteInfo = this.parseRouteInfo(
1109
+ rawRouteName,
1110
+ routeInfo,
1111
+ method,
1112
+ usageSchema,
1113
+ parsedSchemas,
1114
+ );
1115
+ const processedRouteInfo =
1116
+ this.config.hooks.onCreateRoute(parsedRouteInfo);
875
1117
  if (processedRouteInfo !== false) {
876
- const route = processedRouteInfo || parsedRouteInfo;
877
-
878
- if (!this.hasSecurityRoutes && route.security) {
879
- this.hasSecurityRoutes = route.security;
880
- }
881
- if (!this.hasQueryRoutes && route.hasQuery) {
882
- this.hasQueryRoutes = route.hasQuery;
883
- }
884
- if (!this.hasFormDataRoutes && route.hasFormDataParams) {
885
- this.hasFormDataRoutes = route.hasFormDataParams;
886
- }
887
-
888
- this.routes.push(route);
1118
+ const route = processedRouteInfo || parsedRouteInfo;
1119
+
1120
+ if (!this.hasSecurityRoutes && route.security) {
1121
+ this.hasSecurityRoutes = route.security;
1122
+ }
1123
+ if (!this.hasQueryRoutes && route.hasQuery) {
1124
+ this.hasQueryRoutes = route.hasQuery;
1125
+ }
1126
+ if (!this.hasFormDataRoutes && route.hasFormDataParams) {
1127
+ this.hasFormDataRoutes = route.hasFormDataParams;
1128
+ }
1129
+
1130
+ this.routes.push(route);
889
1131
  }
890
1132
  });
891
1133
  });
@@ -911,10 +1153,10 @@ class SchemaRoutes {
911
1153
  },
912
1154
  );
913
1155
 
914
- return _.reduce(
1156
+ const routeGroups = _.reduce(
915
1157
  groupedRoutes,
916
1158
  (acc, routesGroup, moduleName) => {
917
- if (moduleName === "$outOfModule") {
1159
+ if (moduleName === '$outOfModule') {
918
1160
  acc.outOfModule = routesGroup;
919
1161
  } else {
920
1162
  if (!acc.combined) acc.combined = [];
@@ -922,14 +1164,19 @@ class SchemaRoutes {
922
1164
  acc.combined.push({
923
1165
  moduleName,
924
1166
  routes: _.map(routesGroup, (route) => {
925
- const { original: originalName, usage: usageName } = route.routeName;
1167
+ const { original: originalName, usage: usageName } =
1168
+ route.routeName;
926
1169
 
927
1170
  // TODO: https://github.com/acacode/swagger-typescript-api/issues/152
928
1171
  // TODO: refactor
929
1172
  if (
930
1173
  routesGroup.length > 1 &&
931
1174
  usageName !== originalName &&
932
- !_.some(routesGroup, ({ routeName, id }) => id !== route.id && originalName === routeName.original)
1175
+ !_.some(
1176
+ routesGroup,
1177
+ ({ routeName, id }) =>
1178
+ id !== route.id && originalName === routeName.original,
1179
+ )
933
1180
  ) {
934
1181
  return {
935
1182
  ...route,
@@ -948,6 +1195,28 @@ class SchemaRoutes {
948
1195
  },
949
1196
  {},
950
1197
  );
1198
+
1199
+ if (this.config.sortRoutes) {
1200
+ if (routeGroups.outOfModule) {
1201
+ routeGroups.outOfModule = this.sortRoutes(routeGroups.outOfModule);
1202
+ }
1203
+ if (routeGroups.combined) {
1204
+ routeGroups.combined = this.sortRoutes(routeGroups.combined);
1205
+ }
1206
+ }
1207
+
1208
+ return routeGroups;
1209
+ };
1210
+
1211
+ sortRoutes = (routeInfo) => {
1212
+ if (routeInfo) {
1213
+ routeInfo.forEach((routeInfo) => {
1214
+ routeInfo.routes.sort((routeA, routeB) =>
1215
+ routeA.routeName.usage.localeCompare(routeB.routeName.usage),
1216
+ );
1217
+ });
1218
+ }
1219
+ return routeInfo;
951
1220
  };
952
1221
  }
953
1222