swagger-typescript-api 13.0.0-experimental-1 → 13.0.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.
Files changed (81) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +26 -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 +164 -135
  12. package/package.json +36 -30
  13. package/src/code-formatter.js +28 -13
  14. package/src/code-gen-process.js +367 -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 +172 -96
  20. package/src/constants.js +28 -22
  21. package/src/index.js +3 -4
  22. package/src/schema-components-map.js +43 -25
  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 +304 -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 +27 -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 +234 -425
  37. package/src/schema-parser/schema-utils.js +165 -67
  38. package/src/schema-parser/util/enum-key-resolver.js +26 -0
  39. package/src/schema-routes/schema-routes.js +1222 -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 +43 -22
  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,415 +1,262 @@
1
- const { SchemaFormatters } = require("./schema-formatters");
2
- const { SchemaUtils } = require("./schema-utils");
3
- const { SCHEMA_TYPES } = require("../constants");
4
- const _ = require("lodash");
5
- const { internalCase } = require("../util/internal-case");
6
- const { camelCase } = require("lodash");
1
+ /* eslint-disable no-unused-vars */
2
+ const { SCHEMA_TYPES } = require('../constants.js');
3
+ const _ = require('lodash');
4
+ const { SchemaFormatters } = require('./schema-formatters');
5
+ const { SchemaUtils } = require('./schema-utils');
6
+ const {
7
+ DiscriminatorSchemaParser,
8
+ } = require('./base-schema-parsers/discriminator');
9
+ const { EnumSchemaParser } = require('./base-schema-parsers/enum');
10
+ const { ObjectSchemaParser } = require('./base-schema-parsers/object');
11
+ const { PrimitiveSchemaParser } = require('./base-schema-parsers/primitive');
12
+ const { ComplexSchemaParser } = require('./base-schema-parsers/complex');
13
+ const { OneOfSchemaParser } = require('./complex-schema-parsers/one-of');
14
+ const { AllOfSchemaParser } = require('./complex-schema-parsers/all-of');
15
+ const { AnyOfSchemaParser } = require('./complex-schema-parsers/any-of');
16
+ const { NotSchemaParser } = require('./complex-schema-parsers/not');
17
+ const { ArraySchemaParser } = require('./base-schema-parsers/array');
18
+ const { sortByProperty } = require('../util/sort-by-property');
7
19
 
8
20
  class SchemaParser {
9
- /**
10
- * @type {CodeGenConfig}
11
- */
21
+ /** @type {SchemaParserFabric} */
22
+ schemaParserFabric;
23
+ /** @type {CodeGenConfig} */
12
24
  config;
13
- /**
14
- * @type {SchemaComponentsMap}
15
- */
25
+ /** @type {Logger} */
26
+ logger;
27
+ /** @type {SchemaComponentsMap} */
16
28
  schemaComponentsMap;
17
- /**
18
- * @type {TypeNameFormatter}
19
- */
29
+ /** @type {TypeNameFormatter} */
20
30
  typeNameFormatter;
21
- /**
22
- * @type {SchemaFormatters}
23
- */
31
+ /** @type {SchemaFormatters} */
24
32
  schemaFormatters;
25
-
26
- /**
27
- * @type {SchemaUtils}
28
- */
33
+ /** @type {SchemaUtils} */
29
34
  schemaUtils;
30
-
31
- schemaPath = [];
35
+ /** @type {TemplatesWorker} */
36
+ templatesWorker;
37
+ /** @type {SchemaWalker} */
38
+ schemaWalker;
32
39
 
33
40
  typeName;
34
41
  schema;
42
+ schemaPath = [];
35
43
 
36
- constructor(
37
- config,
38
- schemaComponentsMap,
39
- typeNameFormatter,
40
- schemaFormatters,
41
- schemaUtils,
42
- schema,
43
- typeName = null,
44
- schemaPath = [],
45
- ) {
46
- this.config = config;
47
- this.schemaComponentsMap = schemaComponentsMap;
48
- this.typeNameFormatter = typeNameFormatter;
49
- this.schemaFormatters = schemaFormatters;
50
- this.schemaUtils = schemaUtils;
44
+ constructor(schemaParserFabric, { typeName, schema, schemaPath } = {}) {
45
+ this.schemaParserFabric = schemaParserFabric;
46
+ this.config = schemaParserFabric.config;
47
+ this.logger = schemaParserFabric.logger;
48
+ this.templatesWorker = schemaParserFabric.templatesWorker;
49
+ this.schemaComponentsMap = schemaParserFabric.schemaComponentsMap;
50
+ this.typeNameFormatter = schemaParserFabric.typeNameFormatter;
51
+ this.schemaWalker = schemaParserFabric.schemaWalker;
52
+ this.schemaFormatters = schemaParserFabric.schemaFormatters;
53
+ this.schemaUtils = schemaParserFabric.schemaUtils;
54
+
55
+ this.typeName = typeName || null;
51
56
  this.schema = schema;
52
- this.typeName = typeName;
53
- this.schemaPath = schemaPath;
57
+ this.schemaPath = [...(schemaPath || [])];
54
58
  }
55
59
 
56
60
  _complexSchemaParsers = {
57
- // T1 | T2
58
- [SCHEMA_TYPES.COMPLEX_ONE_OF]: async (schema) => {
59
- const ignoreTypes = [this.config.Ts.Keyword.Any];
60
- const combined = await Promise.all(
61
- _.map(schema.oneOf, (childSchema) =>
62
- this.createParser(
63
- this.schemaUtils.makeAddRequiredToChildSchema(schema, childSchema),
64
- undefined,
65
- this.schemaPath,
66
- ).getInlineContent(),
67
- ),
61
+ [SCHEMA_TYPES.COMPLEX_ONE_OF]: (schema) => {
62
+ const SchemaParser =
63
+ this.config.schemaParsers.complexOneOf || OneOfSchemaParser;
64
+ const schemaParser = new SchemaParser(
65
+ this,
66
+ schema,
67
+ null,
68
+ this.schemaPath,
68
69
  );
69
- const filtered = this.schemaUtils.filterSchemaContents(combined, (content) => !ignoreTypes.includes(content));
70
-
71
- const type = this.config.Ts.UnionType(filtered);
72
-
73
- return this.schemaUtils.safeAddNullToType(schema, type);
70
+ return schemaParser.parse();
74
71
  },
75
- // T1 & T2
76
- [SCHEMA_TYPES.COMPLEX_ALL_OF]: async (schema) => {
77
- const ignoreTypes = [...this.config.jsPrimitiveTypes, this.config.Ts.Keyword.Any];
78
- const combined = await Promise.all(
79
- _.map(schema.allOf, (childSchema) =>
80
- this.createParser(
81
- this.schemaUtils.makeAddRequiredToChildSchema(schema, childSchema),
82
- undefined,
83
- this.schemaPath,
84
- ).getInlineContent(),
85
- ),
72
+ [SCHEMA_TYPES.COMPLEX_ALL_OF]: (schema) => {
73
+ const SchemaParser =
74
+ this.config.schemaParsers.complexAllOf || AllOfSchemaParser;
75
+ const schemaParser = new SchemaParser(
76
+ this,
77
+ schema,
78
+ null,
79
+ this.schemaPath,
86
80
  );
87
- const filtered = this.schemaUtils.filterSchemaContents(combined, (content) => !ignoreTypes.includes(content));
88
-
89
- const type = this.config.Ts.IntersectionType(filtered);
90
-
91
- return this.schemaUtils.safeAddNullToType(schema, type);
81
+ return schemaParser.parse();
92
82
  },
93
- // T1 | T2 | (T1 & T2)
94
- [SCHEMA_TYPES.COMPLEX_ANY_OF]: async (schema) => {
95
- const ignoreTypes = [...this.config.jsPrimitiveTypes, this.config.Ts.Keyword.Any];
96
- const combined = await Promise.all(
97
- _.map(schema.anyOf, (childSchema) =>
98
- this.createParser(
99
- this.schemaUtils.makeAddRequiredToChildSchema(schema, childSchema),
100
- undefined,
101
- this.schemaPath,
102
- ).getInlineContent(),
103
- ),
104
- );
105
- const filtered = this.schemaUtils.filterSchemaContents(combined, (content) => !ignoreTypes.includes(content));
106
-
107
- const type = this.config.Ts.UnionType(
108
- _.compact([
109
- ...filtered,
110
- filtered.length > 1 && this.config.Ts.ExpressionGroup(this.config.Ts.IntersectionType(filtered)),
111
- ]),
83
+ [SCHEMA_TYPES.COMPLEX_ANY_OF]: (schema) => {
84
+ const SchemaParser =
85
+ this.config.schemaParsers.complexAnyOf || AnyOfSchemaParser;
86
+ const schemaParser = new SchemaParser(
87
+ this,
88
+ schema,
89
+ null,
90
+ this.schemaPath,
112
91
  );
113
-
114
- return this.schemaUtils.safeAddNullToType(schema, type);
92
+ return schemaParser.parse();
115
93
  },
116
- // TODO
117
94
  [SCHEMA_TYPES.COMPLEX_NOT]: (schema) => {
118
- // TODO
119
- return this.config.Ts.Keyword.Any;
95
+ const SchemaParser =
96
+ this.config.schemaParsers.complexNot || NotSchemaParser;
97
+ const schemaParser = new SchemaParser(
98
+ this,
99
+ schema,
100
+ null,
101
+ this.schemaPath,
102
+ );
103
+ return schemaParser.parse();
120
104
  },
121
105
  };
122
- _baseSchemaParsers = {
123
- [SCHEMA_TYPES.ENUM]: async (schema, typeName) => {
124
- if (this.config.extractEnums && !typeName) {
125
- const generatedTypeName = this.config.componentTypeNameResolver.resolve([this.buildTypeNameFromPath()]);
126
- const schemaComponent = this.schemaComponentsMap.createComponent("schemas", generatedTypeName, { ...schema });
127
- const parser = this.createParser(schemaComponent, generatedTypeName);
128
- return await parser.parse();
129
- }
130
-
131
- const refType = this.schemaUtils.getSchemaRefType(schema);
132
- const $ref = (refType && refType.$ref) || null;
133
-
134
- if (Array.isArray(schema.enum) && Array.isArray(schema.enum[0])) {
135
- return await this.createParser(
136
- {
137
- oneOf: schema.enum.map((enumNames) => ({
138
- type: "array",
139
- items: enumNames.map((enumName) => ({ type: "string", enum: [enumName] })),
140
- })),
141
- },
142
- typeName,
143
- this.schemaPath,
144
- ).parse();
145
- }
146
-
147
- const keyType = await this.schemaUtils.getSchemaType(schema);
148
- const enumNames = this.schemaUtils.getEnumNames(schema);
149
- let content = null;
150
-
151
- const formatValue = async (value) => {
152
- if (value === null) {
153
- return this.config.Ts.NullValue(value);
154
- }
155
- if (keyType === (await this.schemaUtils.getSchemaType({ type: "number" }))) {
156
- return this.config.Ts.NumberValue(value);
157
- }
158
- if (keyType === (await this.schemaUtils.getSchemaType({ type: "boolean" }))) {
159
- return this.config.Ts.BooleanValue(value);
160
- }
161
-
162
- return this.config.Ts.StringValue(value);
163
- };
164
-
165
- if (_.isArray(enumNames) && _.size(enumNames)) {
166
- content = await Promise.all(
167
- _.map(enumNames, async (enumName, index) => {
168
- const enumValue = _.get(schema.enum, index);
169
- const formattedKey =
170
- (enumName &&
171
- this.typeNameFormatter.format(enumName, {
172
- type: "enum-key",
173
- })) ||
174
- this.typeNameFormatter.format(`${enumValue}`, {
175
- type: "enum-key",
176
- });
177
-
178
- if (this.config.enumNamesAsValues || _.isUndefined(enumValue)) {
179
- return {
180
- key: formattedKey,
181
- type: this.config.Ts.Keyword.String,
182
- value: this.config.Ts.StringValue(enumName),
183
- };
184
- }
185
-
186
- return {
187
- key: formattedKey,
188
- type: keyType,
189
- value: await formatValue(enumValue),
190
- };
191
- }),
192
- );
193
- } else {
194
- content = await Promise.all(
195
- _.map(schema.enum, async (key) => {
196
- return {
197
- key: this.typeNameFormatter.format(`${key}`, {
198
- type: "enum-key",
199
- }),
200
- type: keyType,
201
- value: await formatValue(key),
202
- };
203
- }),
204
- );
205
- }
206
106
 
207
- return {
208
- ...(_.isObject(schema) ? schema : {}),
209
- $ref: $ref,
210
- typeName: typeName || ($ref && refType.typeName) || null,
211
- $parsedSchema: true,
212
- schemaType: SCHEMA_TYPES.ENUM,
213
- type: SCHEMA_TYPES.ENUM,
214
- keyType: keyType,
215
- typeIdentifier: this.config.generateUnionEnums ? this.config.Ts.Keyword.Type : this.config.Ts.Keyword.Enum,
216
- name: typeName,
217
- description: this.schemaFormatters.formatDescription(schema.description),
218
- content,
219
- };
107
+ _baseSchemaParsers = {
108
+ [SCHEMA_TYPES.ENUM]: (schema, typeName) => {
109
+ const SchemaParser = this.config.schemaParsers.enum || EnumSchemaParser;
110
+ const schemaParser = new SchemaParser(
111
+ this,
112
+ schema,
113
+ typeName,
114
+ this.schemaPath,
115
+ );
116
+ return schemaParser.parse();
220
117
  },
221
- [SCHEMA_TYPES.OBJECT]: async (schema, typeName) => {
222
- const { properties, additionalProperties } = schema || {};
223
- const contentProperties = [];
224
-
225
- const propertyEntries = _.entries(properties);
226
-
227
- for await (const [name, property] of propertyEntries) {
228
- this.schemaPath.push(name);
229
- const required = this.schemaUtils.isPropertyRequired(name, property, schema);
230
- const rawTypeData = _.get(this.schemaUtils.getSchemaRefType(property), "rawTypeData", {});
231
- const nullable = !!(rawTypeData.nullable || property.nullable);
232
- const fieldName = this.typeNameFormatter.isValidName(name) ? name : this.config.Ts.StringValue(name);
233
- const fieldValue = await this.createParser(property, null, this.schemaPath).getInlineContent();
234
- const readOnly = property.readOnly;
235
-
236
- this.schemaPath.pop();
237
-
238
- contentProperties.push({
239
- ...property,
240
- $$raw: property,
241
- title: property.title,
242
- description:
243
- property.description ||
244
- _.compact(_.map(property[this.schemaUtils.getComplexType(property)], "description"))[0] ||
245
- rawTypeData.description ||
246
- _.compact(_.map(rawTypeData[this.schemaUtils.getComplexType(rawTypeData)], "description"))[0] ||
247
- "",
248
- isRequired: required,
249
- isNullable: nullable,
250
- name: fieldName,
251
- value: fieldValue,
252
- field: this.config.Ts.TypeField({
253
- readonly: readOnly && this.config.addReadonly,
254
- optional: !required,
255
- key: fieldName,
256
- value: fieldValue,
257
- }),
258
- });
259
- }
260
-
261
- if (additionalProperties) {
262
- contentProperties.push({
263
- $$raw: { additionalProperties },
264
- description: "",
265
- isRequired: false,
266
- field: this.config.Ts.InterfaceDynamicField(this.config.Ts.Keyword.String, this.config.Ts.Keyword.Any),
267
- });
268
- }
269
-
270
- return {
271
- ...(_.isObject(schema) ? schema : {}),
272
- $parsedSchema: true,
273
- schemaType: SCHEMA_TYPES.OBJECT,
274
- type: SCHEMA_TYPES.OBJECT,
275
- typeIdentifier: this.config.Ts.Keyword.Interface,
276
- name: typeName,
277
- description: this.schemaFormatters.formatDescription(schema.description),
278
- allFieldsAreOptional: !_.some(_.values(contentProperties), (part) => part.isRequired),
279
- content: contentProperties,
280
- };
118
+ [SCHEMA_TYPES.OBJECT]: (schema, typeName) => {
119
+ const SchemaParser =
120
+ this.config.schemaParsers.object || ObjectSchemaParser;
121
+ const schemaParser = new SchemaParser(
122
+ this,
123
+ schema,
124
+ typeName,
125
+ this.schemaPath,
126
+ );
127
+ return schemaParser.parse();
281
128
  },
282
- [SCHEMA_TYPES.COMPLEX]: async (schema, typeName) => {
283
- const complexType = this.schemaUtils.getComplexType(schema);
284
- const simpleSchema = _.omit(_.clone(schema), _.keys(this._complexSchemaParsers));
285
- const complexSchemaContent = await this._complexSchemaParsers[complexType](schema);
286
-
287
- return {
288
- ...(_.isObject(schema) ? schema : {}),
289
- $parsedSchema: true,
290
- schemaType: SCHEMA_TYPES.COMPLEX,
291
- type: SCHEMA_TYPES.PRIMITIVE,
292
- typeIdentifier: this.config.Ts.Keyword.Type,
293
- name: typeName,
294
- description: this.schemaFormatters.formatDescription(
295
- schema.description || _.compact(_.map(schema[complexType], "description"))[0] || "",
296
- ),
297
- content:
298
- this.config.Ts.IntersectionType(
299
- _.compact([
300
- this.config.Ts.ExpressionGroup(complexSchemaContent),
301
- this.schemaUtils.getInternalSchemaType(simpleSchema) === SCHEMA_TYPES.OBJECT &&
302
- this.config.Ts.ExpressionGroup(
303
- await this.createParser(simpleSchema, null, this.schemaPath).getInlineContent(),
304
- ),
305
- ]),
306
- ) || this.config.Ts.Keyword.Any,
307
- };
129
+ [SCHEMA_TYPES.COMPLEX]: (schema, typeName) => {
130
+ const SchemaParser =
131
+ this.config.schemaParsers.complex || ComplexSchemaParser;
132
+ const schemaParser = new SchemaParser(
133
+ this,
134
+ schema,
135
+ typeName,
136
+ this.schemaPath,
137
+ );
138
+ return schemaParser.parse();
308
139
  },
309
- [SCHEMA_TYPES.ARRAY]: async (schema, typeName) => {
310
- let contentType;
311
- const { type, description, items } = schema || {};
312
-
313
- if (_.isArray(items) && type === SCHEMA_TYPES.ARRAY) {
314
- const tupleContent = await Promise.all(
315
- items.map((item) => this.createParser(item, null, this.schemaPath).getInlineContent()),
316
- );
317
- contentType = this.config.Ts.Tuple(tupleContent);
318
- } else {
319
- const content = await this.createParser(items, null, this.schemaPath).getInlineContent();
320
- contentType = this.config.Ts.ArrayType(content);
321
- }
322
-
323
- return {
324
- ...(_.isObject(schema) ? schema : {}),
325
- $parsedSchema: true,
326
- schemaType: SCHEMA_TYPES.PRIMITIVE,
327
- type: SCHEMA_TYPES.PRIMITIVE,
328
- typeIdentifier: this.config.Ts.Keyword.Type,
329
- name: typeName,
330
- description: this.schemaFormatters.formatDescription(description),
331
- content: this.schemaUtils.safeAddNullToType(schema, contentType),
332
- };
140
+ [SCHEMA_TYPES.PRIMITIVE]: (schema, typeName) => {
141
+ const SchemaParser =
142
+ this.config.schemaParsers.primitive || PrimitiveSchemaParser;
143
+ const schemaParser = new SchemaParser(
144
+ this,
145
+ schema,
146
+ typeName,
147
+ this.schemaPath,
148
+ );
149
+ return schemaParser.parse();
333
150
  },
334
- [SCHEMA_TYPES.PRIMITIVE]: async (schema, typeName) => {
335
- let contentType = null;
336
- const { additionalProperties, type, description, items } = schema || {};
337
-
338
- if (type === this.config.Ts.Keyword.Object && additionalProperties) {
339
- const fieldType = _.isObject(additionalProperties)
340
- ? await this.createParser(additionalProperties, null, this.schemaPath).getInlineContent()
341
- : this.config.Ts.Keyword.Any;
342
- contentType = this.config.Ts.RecordType(this.config.Ts.Keyword.String, fieldType);
343
- }
344
-
345
- if (_.isArray(type) && type.length) {
346
- contentType = await this._complexSchemaParsers.oneOf({
347
- ...(_.isObject(schema) ? schema : {}),
348
- oneOf: type.map((type) => ({ type })),
349
- });
350
- }
351
-
352
- if (_.isArray(items) && type === SCHEMA_TYPES.ARRAY) {
353
- contentType = this.config.Ts.Tuple(
354
- await Promise.all(items.map((item) => this.createParser(item, null, this.schemaPath).getInlineContent())),
355
- );
356
- }
357
-
358
- return {
359
- ...(_.isObject(schema) ? schema : {}),
360
- $parsedSchema: true,
361
- schemaType: SCHEMA_TYPES.PRIMITIVE,
362
- type: SCHEMA_TYPES.PRIMITIVE,
363
- typeIdentifier: this.config.Ts.Keyword.Type,
364
- name: typeName,
365
- description: this.schemaFormatters.formatDescription(description),
366
- // TODO: probably it should be refactored. `type === 'null'` is not flexible
367
- content:
368
- type === this.config.Ts.Keyword.Null ? type : contentType || (await this.schemaUtils.getSchemaType(schema)),
369
- };
151
+ [SCHEMA_TYPES.DISCRIMINATOR]: (schema, typeName) => {
152
+ const SchemaParser =
153
+ this.config.schemaParsers.discriminator || DiscriminatorSchemaParser;
154
+ const schemaParser = new SchemaParser(
155
+ this,
156
+ schema,
157
+ typeName,
158
+ this.schemaPath,
159
+ );
160
+ return schemaParser.parse();
161
+ },
162
+ [SCHEMA_TYPES.ARRAY]: (schema, typeName) => {
163
+ const SchemaParser = this.config.schemaParsers.array || ArraySchemaParser;
164
+ const schemaParser = new SchemaParser(
165
+ this,
166
+ schema,
167
+ typeName,
168
+ this.schemaPath,
169
+ );
170
+ return schemaParser.parse();
370
171
  },
371
- };
372
-
373
- buildTypeNameFromPath = () => {
374
- const schemaPath = _.uniq(_.compact(this.schemaPath));
375
-
376
- if (!schemaPath || !schemaPath[0]) return null;
377
-
378
- return internalCase(camelCase(`${schemaPath[0]}_${schemaPath[schemaPath.length - 1]}`));
379
172
  };
380
173
 
381
174
  /**
382
- *
383
- * @param schema {any}
384
- * @param typeName {null | string}
385
- * @param formatter {"inline" | "base"}
386
- * @return {Promise<Record<string, any>>}
175
+ * @return {Record<string, any>}
387
176
  */
388
- parse = async () => {
389
- if (!this.schema) return await this._baseSchemaParsers[SCHEMA_TYPES.PRIMITIVE](null, this.typeName);
177
+ parseSchema = () => {
178
+ if (!this.schema)
179
+ return this._baseSchemaParsers[SCHEMA_TYPES.PRIMITIVE](
180
+ null,
181
+ this.typeName,
182
+ );
390
183
 
391
184
  let schemaType = null;
392
185
  let parsedSchema = null;
393
186
 
394
- if (typeof this.schema === "string") {
187
+ if (typeof this.schema === 'string') {
395
188
  return this.schema;
396
189
  }
397
190
 
398
191
  if (!this.schema.$parsed) {
399
192
  if (!this.typeName && this.schemaUtils.isRefSchema(this.schema)) {
400
- this.typeName = await this.schemaUtils.getSchemaType(this.schema);
193
+ this.typeName = this.schemaUtils.getSchemaType(this.schema);
401
194
  }
402
195
 
403
- if (this.schema.items && !Array.isArray(this.schema.items) && !this.schema.type) {
196
+ //#region swagger schemas fixes
197
+
198
+ // schema has items but don't have array type
199
+ if (
200
+ this.schema.items &&
201
+ !Array.isArray(this.schema.items) &&
202
+ !this.schema.type
203
+ ) {
404
204
  this.schema.type = SCHEMA_TYPES.ARRAY;
405
205
  }
206
+ // schema is enum with one null value
207
+ if (
208
+ Array.isArray(this.schema.enum) &&
209
+ this.schema.enum.length === 1 &&
210
+ this.schema.enum[0] == null
211
+ ) {
212
+ this.logger.debug('invalid enum schema', this.schema);
213
+ this.schema = { type: this.config.Ts.Keyword.Null };
214
+ }
215
+ // schema is response schema
216
+ if (
217
+ 'content' in this.schema &&
218
+ typeof this.schema['content'] === 'object'
219
+ ) {
220
+ const schema = this.extractSchemaFromResponseStruct(this.schema);
221
+ const schemaParser = this.schemaParserFabric.createSchemaParser({
222
+ schema,
223
+ typeName: this.typeName,
224
+ schemaPath: this.schemaPath,
225
+ });
226
+ this.schema.$parsed = schemaParser.parseSchema();
227
+ return this.schema.$parsed;
228
+ }
229
+
230
+ //#endregion
231
+
406
232
  schemaType = this.schemaUtils.getInternalSchemaType(this.schema);
407
233
 
408
234
  this.schemaPath.push(this.typeName);
409
235
 
410
- _.merge(this.schema, this.config.hooks.onPreParseSchema(this.schema, this.typeName, schemaType));
411
- parsedSchema = await this._baseSchemaParsers[schemaType](this.schema, this.typeName);
412
- this.schema.$parsed = this.config.hooks.onParseSchema(this.schema, parsedSchema) || parsedSchema;
236
+ _.merge(
237
+ this.schema,
238
+ this.config.hooks.onPreParseSchema(
239
+ this.schema,
240
+ this.typeName,
241
+ schemaType,
242
+ ),
243
+ );
244
+ parsedSchema = this._baseSchemaParsers[schemaType](
245
+ this.schema,
246
+ this.typeName,
247
+ );
248
+ this.schema.$parsed =
249
+ this.config.hooks.onParseSchema(this.schema, parsedSchema) ||
250
+ parsedSchema;
251
+
252
+ if (
253
+ this.config.sortTypes &&
254
+ Array.isArray(this.schema.$parsed?.content)
255
+ ) {
256
+ this.schema.$parsed.content = this.schema.$parsed.content.sort(
257
+ sortByProperty('name'),
258
+ );
259
+ }
413
260
  }
414
261
 
415
262
  this.schemaPath.pop();
@@ -417,76 +264,38 @@ class SchemaParser {
417
264
  return this.schema.$parsed;
418
265
  };
419
266
 
420
- /**
421
- * @param cfg {{ formatType?: "base" | "inline", schemaType?: string } }
422
- * @return {Promise<Record<string, any>>}
423
- */
424
- format = async (cfg) => {
425
- const parsedSchema = await this.parse();
426
- return await this.schemaFormatters.formatSchema(parsedSchema, cfg);
267
+ getInlineParseContent = () => {
268
+ const parsedSchema = this.parseSchema();
269
+ const formattedSchema = this.schemaFormatters.formatSchema(
270
+ parsedSchema,
271
+ 'inline',
272
+ );
273
+ return formattedSchema.content;
427
274
  };
428
275
 
429
- getInlineContent = async () => {
430
- const schema = await this.format({ formatType: "inline" });
431
- return schema.content;
276
+ getParseContent = () => {
277
+ const parsedSchema = this.parseSchema();
278
+ const formattedSchema = this.schemaFormatters.formatSchema(
279
+ parsedSchema,
280
+ 'base',
281
+ );
282
+ return formattedSchema.content;
432
283
  };
433
284
 
434
- getContent = async () => {
435
- const schema = await this.format({ formatType: "base" });
436
- return schema.content;
437
- };
285
+ extractSchemaFromResponseStruct = (responseStruct) => {
286
+ const { content, ...extras } = responseStruct;
438
287
 
439
- /**
440
- * @param {Record<string, any>} [schema]
441
- * @param {string | null | undefined} [typeName]
442
- * @param {string[] | undefined} [schemaPath]
443
- * @return {SchemaParser}
444
- */
445
- createParser = (schema, typeName, schemaPath) => {
446
- return new SchemaParser(
447
- this.config,
448
- this.schemaComponentsMap,
449
- this.typeNameFormatter,
450
- this.schemaFormatters,
451
- this.schemaUtils,
452
- schema,
453
- typeName,
454
- schemaPath,
455
- );
456
- };
288
+ const firstResponse = _.first(_.values(content));
289
+ const firstSchema = _.get(firstResponse, 'schema');
457
290
 
458
- /**
459
- * @param config {CodeGenConfig}
460
- * @param schemaComponentsMap {SchemaComponentsMap}
461
- * @param typeNameFormatter {TypeNameFormatter}
462
- * @param schemaFormatters {SchemaFormatters}
463
- * @param schemaUtils {SchemaUtils}
464
- * @param {Record<string, any>} [schema]
465
- * @param {string | null | undefined} [typeName]
466
- * @param {string[] | undefined} [schemaPath]
467
- * @return {SchemaParser}
468
- */
469
- static create(
470
- config,
471
- schemaComponentsMap,
472
- typeNameFormatter,
473
- schemaFormatters,
474
- schemaUtils,
475
- schema,
476
- typeName,
477
- schemaPath,
478
- ) {
479
- return new SchemaParser(
480
- config,
481
- schemaComponentsMap,
482
- typeNameFormatter,
483
- schemaFormatters,
484
- schemaUtils,
485
- schema,
486
- typeName,
487
- schemaPath,
488
- );
489
- }
291
+ if (!firstSchema) return;
292
+
293
+ return {
294
+ ...extras,
295
+ ..._.omit(firstResponse, 'schema'),
296
+ ...firstSchema,
297
+ };
298
+ };
490
299
  }
491
300
 
492
301
  module.exports = {