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,57 +1,59 @@
1
- const { SwaggerSchemaResolver } = require("./swagger-schema-resolver.js");
2
- const { SchemaComponentsMap } = require("./schema-components-map.js");
3
- const { NameResolver } = require("./util/name-resolver");
4
- const { Logger } = require("./util/logger.js");
5
- const { TypeName } = require("./type-name.js");
6
- const _ = require("lodash");
7
- const { SchemaParser } = require("./schema-parser/schema-parser.js");
8
- const { SchemaRoutes } = require("./schema-parser/schema-routes.js");
9
- const { CodeGenConfig } = require("./configuration.js");
10
- const { FileSystem } = require("./util/file-system");
11
- const { Templates } = require("./templates");
12
- const { translate: translateToJS } = require("./translators/JavaScript");
13
- const ts = require("typescript");
14
- const { CodeFormatter } = require("./code-formatter");
15
- const { pascalCase } = require("./util/pascal-case");
16
- const { internalCase } = require("./util/internal-case");
1
+ const { SwaggerSchemaResolver } = require('./swagger-schema-resolver.js');
2
+ const { SchemaComponentsMap } = require('./schema-components-map.js');
3
+ const { NameResolver } = require('./util/name-resolver');
4
+ const { Logger } = require('./util/logger.js');
5
+ const { TypeNameFormatter } = require('./type-name-formatter.js');
6
+ const _ = require('lodash');
7
+ const { SchemaParserFabric } = require('./schema-parser/schema-parser-fabric');
8
+ const { SchemaRoutes } = require('./schema-routes/schema-routes.js');
9
+ const { CodeGenConfig } = require('./configuration.js');
10
+ const { SchemaWalker } = require('./schema-walker');
11
+ const { FileSystem } = require('./util/file-system');
12
+ const { TemplatesWorker } = require('./templates-worker');
13
+ const { JavascriptTranslator } = require('./translators/javascript');
14
+ const ts = require('typescript');
15
+ const { CodeFormatter } = require('./code-formatter');
16
+ const { pascalCase } = require('./util/pascal-case');
17
+ const { internalCase } = require('./util/internal-case');
18
+ const { sortByProperty } = require('./util/sort-by-property');
19
+
20
+ const PATCHABLE_INSTANCES = [
21
+ 'schemaWalker',
22
+ 'swaggerSchemaResolver',
23
+ 'schemaComponentsMap',
24
+ 'typeNameFormatter',
25
+ 'templatesWorker',
26
+ 'codeFormatter',
27
+ 'schemaParserFabric',
28
+ 'schemaRoutes',
29
+ 'javascriptTranslator',
30
+ ];
17
31
 
18
32
  class CodeGenProcess {
19
- /**
20
- * @type {CodeGenConfig}
21
- */
33
+ /** @type {CodeGenConfig} */
22
34
  config;
23
- /**
24
- * @type {SwaggerSchemaResolver}
25
- */
35
+ /** @type {SwaggerSchemaResolver} */
26
36
  swaggerSchemaResolver;
27
- /**
28
- * @type {SchemaComponentsMap}
29
- */
30
- schemaComponentMap;
31
- /**
32
- * @type {Logger}
33
- */
37
+ /** @type {SchemaComponentsMap} */
38
+ schemaComponentsMap;
39
+ /** @type {Logger} */
34
40
  logger;
35
- /**
36
- * @type {TypeName}
37
- */
38
- typeName;
39
- /**
40
- * @type {SchemaParser}
41
- */
42
- schemaParser;
43
- /**
44
- * @type {SchemaRoutes}
45
- */
41
+ /** @type {TypeNameFormatter} */
42
+ typeNameFormatter;
43
+ /** @type {SchemaParserFabric} */
44
+ schemaParserFabric;
45
+ /** @type {SchemaRoutes} */
46
46
  schemaRoutes;
47
- /**
48
- * @type {FileSystem}
49
- */
47
+ /** @type {FileSystem} */
50
48
  fileSystem;
51
- /**
52
- * @type {CodeFormatter}
53
- */
49
+ /** @type {CodeFormatter} */
54
50
  codeFormatter;
51
+ /** type {TemplatesWorker} */
52
+ templatesWorker;
53
+ /** @type {SchemaWalker} */
54
+ schemaWalker;
55
+ /** @type {JavascriptTranslator} */
56
+ javascriptTranslator;
55
57
 
56
58
  /**
57
59
  *
@@ -59,34 +61,27 @@ class CodeGenProcess {
59
61
  */
60
62
  constructor(config) {
61
63
  this.config = new CodeGenConfig(config);
62
- this.logger = new Logger(this.config);
63
- this.fileSystem = new FileSystem();
64
- this.swaggerSchemaResolver = new SwaggerSchemaResolver(this.config, this.logger, this.fileSystem);
65
- this.schemaComponentMap = new SchemaComponentsMap(this.config);
66
- this.typeName = new TypeName(this.config, this.logger);
67
- this.templates = new Templates(this.config, this.logger, this.fileSystem, this.getRenderTemplateData);
68
- this.codeFormatter = new CodeFormatter(this.config);
69
- this.schemaParser = new SchemaParser(
70
- this.config,
71
- this.logger,
72
- this.templates,
73
- this.schemaComponentMap,
74
- this.typeName,
75
- );
76
- this.schemaRoutes = new SchemaRoutes(
77
- this.config,
78
- this.schemaParser,
79
- this.schemaComponentMap,
80
- this.logger,
81
- this.templates,
82
- this.typeName,
83
- );
64
+ this.logger = new Logger(this);
65
+ this.fileSystem = new FileSystem(this);
66
+ this.schemaWalker = new SchemaWalker(this);
67
+ this.swaggerSchemaResolver = new SwaggerSchemaResolver(this);
68
+ this.schemaComponentsMap = new SchemaComponentsMap(this);
69
+ this.typeNameFormatter = new TypeNameFormatter(this);
70
+ this.templatesWorker = new TemplatesWorker(this);
71
+ this.codeFormatter = new CodeFormatter(this);
72
+ this.schemaParserFabric = new SchemaParserFabric(this);
73
+ this.schemaRoutes = new SchemaRoutes(this);
74
+ this.javascriptTranslator = new JavascriptTranslator(this);
84
75
  this.config.componentTypeNameResolver.logger = this.logger;
85
76
  }
86
77
 
87
78
  async start() {
88
- this.config.update({ templatePaths: this.templates.getTemplatePaths(this.config) });
89
- this.config.update({ templatesToRender: this.templates.getTemplates(this.config) });
79
+ this.config.update({
80
+ templatePaths: this.templatesWorker.getTemplatePaths(this.config),
81
+ });
82
+ this.config.update({
83
+ templatesToRender: this.templatesWorker.getTemplates(this.config),
84
+ });
90
85
 
91
86
  const swagger = await this.swaggerSchemaResolver.create();
92
87
 
@@ -97,64 +92,50 @@ class CodeGenProcess {
97
92
  originalSchema: swagger.originalSchema,
98
93
  });
99
94
 
100
- this.logger.event("start generating your typescript api");
95
+ this.schemaWalker.addSchema('$usage', swagger.usageSchema);
96
+ this.schemaWalker.addSchema('$original', swagger.originalSchema);
101
97
 
102
- this.config.update(this.config.hooks.onInit(this.config) || this.config);
98
+ this.logger.event('start generating your typescript api');
103
99
 
104
- this.schemaComponentMap.processSchema(swagger.usageSchema);
100
+ this.config.update(
101
+ this.config.hooks.onInit(this.config, this) || this.config,
102
+ );
105
103
 
106
- const componentSchemaNames = this.schemaComponentMap.filter("schemas").map((c) => c.typeName);
104
+ this.schemaComponentsMap.clear();
105
+
106
+ _.each(swagger.usageSchema.components, (component, componentName) =>
107
+ _.each(component, (rawTypeData, typeName) => {
108
+ this.schemaComponentsMap.createComponent(
109
+ this.schemaComponentsMap.createRef([
110
+ 'components',
111
+ componentName,
112
+ typeName,
113
+ ]),
114
+ rawTypeData,
115
+ );
116
+ }),
117
+ );
107
118
 
108
- this.config.componentTypeNameResolver.reserve(componentSchemaNames);
119
+ const schemaComponents = this.schemaComponentsMap.filter('schemas');
109
120
 
110
- const parsedSchemas = _.map(_.get(swagger.usageSchema.components, "schemas"), (schema, typeName) =>
111
- this.schemaParser.parseSchema(schema, typeName),
112
- );
121
+ const parsedSchemas = schemaComponents.map((schemaComponent) => {
122
+ const parsed = this.schemaParserFabric.parseSchema(
123
+ schemaComponent.rawTypeData,
124
+ schemaComponent.typeName,
125
+ );
126
+ schemaComponent.typeData = parsed;
127
+ return parsed;
128
+ });
113
129
 
114
130
  this.schemaRoutes.attachSchema({
115
131
  usageSchema: swagger.usageSchema,
116
132
  parsedSchemas,
117
133
  });
118
134
 
119
- const usageComponentSchemas = this.schemaComponentMap.filter("schemas");
120
- const sortByProperty = (propertyName) => (o1, o2) => {
121
- if (o1[propertyName] > o2[propertyName]) {
122
- return 1;
123
- }
124
- if (o1[propertyName] < o2[propertyName]) {
125
- return -1;
126
- }
127
- return 0;
128
- };
129
-
130
- const sortSchemas = (schemas) => {
131
- if (this.config.sortTypes) {
132
- return schemas.sort(sortByProperty("typeName")).map((schema) => {
133
- if (schema.rawTypeData?.properties) {
134
- return {
135
- ...schema,
136
- rawTypeData: {
137
- ...schema.rawTypeData,
138
- $parsed: schema.rawTypeData["$parsed"] && {
139
- ...schema.rawTypeData["$parsed"],
140
- content: Array.isArray(schema.rawTypeData["$parsed"].content)
141
- ? schema.rawTypeData["$parsed"].content.sort(sortByProperty("name"))
142
- : schema.rawTypeData["$parsed"].content,
143
- },
144
- },
145
- };
146
- }
147
- return schema;
148
- });
149
- }
150
- return schemas;
151
- };
152
-
153
135
  const rawConfiguration = {
154
136
  apiConfig: this.createApiConfig(swagger.usageSchema),
155
137
  config: this.config,
156
- modelTypes: _.map(sortSchemas(usageComponentSchemas), this.prepareModelType).filter(Boolean),
157
- rawModelTypes: usageComponentSchemas,
138
+ modelTypes: this.collectModelTypes(),
158
139
  hasSecurityRoutes: this.schemaRoutes.hasSecurityRoutes,
159
140
  hasQueryRoutes: this.schemaRoutes.hasQueryRoutes,
160
141
  hasFormDataRoutes: this.schemaRoutes.hasFormDataRoutes,
@@ -163,10 +144,14 @@ class CodeGenProcess {
163
144
  extraTemplates: this.config.extraTemplates,
164
145
  fileName: this.config.fileName,
165
146
  translateToJavaScript: this.config.toJS,
147
+ customTranslator: this.config.customTranslator
148
+ ? new this.config.customTranslator(this)
149
+ : null,
166
150
  utils: this.getRenderTemplateData().utils,
167
151
  };
168
152
 
169
- const configuration = this.config.hooks.onPrepareConfig(rawConfiguration) || rawConfiguration;
153
+ const configuration =
154
+ this.config.hooks.onPrepareConfig(rawConfiguration) || rawConfiguration;
170
155
 
171
156
  if (this.fileSystem.pathIsExist(this.config.output)) {
172
157
  if (this.config.cleanOutput) {
@@ -174,51 +159,40 @@ class CodeGenProcess {
174
159
  this.fileSystem.cleanDir(this.config.output);
175
160
  }
176
161
  } else {
177
- this.logger.debug(`path ${this.config.output} is not exist. creating dir by this path`);
162
+ this.logger.debug(
163
+ `path ${this.config.output} is not exist. creating dir by this path`,
164
+ );
178
165
  this.fileSystem.createDir(this.config.output);
179
166
  }
180
167
 
181
- const files = this.generateOutputFiles({
168
+ const files = await this.generateOutputFiles({
182
169
  configuration: configuration,
183
170
  });
184
171
 
185
172
  const isDirPath = this.fileSystem.pathIsDir(this.config.output);
186
173
 
187
- const generatedFiles = files.map((file) => {
188
- if (!isDirPath) return file;
189
-
190
- if (this.config.toJS) {
191
- this.fileSystem.createFile({
192
- path: this.config.output,
193
- fileName: file.name,
194
- content: file.content,
195
- withPrefix: true,
196
- });
197
- this.fileSystem.createFile({
198
- path: this.config.output,
199
- fileName: file.declaration.name,
200
- content: file.declaration.content,
201
- withPrefix: true,
202
- });
203
- this.logger.success(`javascript api file`, file.name, `created in ${this.config.output}`);
204
- } else {
174
+ if (isDirPath) {
175
+ files.forEach((file) => {
205
176
  this.fileSystem.createFile({
206
177
  path: this.config.output,
207
- fileName: file.name,
208
- content: file.content,
178
+ fileName: `${file.fileName}${file.fileExtension}`,
179
+ content: file.fileContent,
209
180
  withPrefix: true,
210
181
  });
211
- this.logger.success(`typescript api file`, file.name, `created in ${this.config.output}`);
212
- }
213
182
 
214
- return file;
215
- });
183
+ this.logger.success(
184
+ `api file`,
185
+ `"${file.fileName}${file.fileExtension}"`,
186
+ `created in ${this.config.output}`,
187
+ );
188
+ });
189
+ }
216
190
 
217
191
  return {
218
- files: generatedFiles,
192
+ files,
219
193
  configuration,
220
- getTemplate: this.templates.getTemplate,
221
- renderTemplate: this.templates.renderTemplate,
194
+ getTemplate: this.templatesWorker.getTemplate,
195
+ renderTemplate: this.templatesWorker.renderTemplate,
222
196
  createFile: this.fileSystem.createFile,
223
197
  formatTSContent: this.codeFormatter.formatCode,
224
198
  };
@@ -228,45 +202,89 @@ class CodeGenProcess {
228
202
  return {
229
203
  utils: {
230
204
  Ts: this.config.Ts,
231
- formatDescription: this.schemaParser.schemaFormatters.formatDescription,
205
+ formatDescription:
206
+ this.schemaParserFabric.schemaFormatters.formatDescription,
232
207
  internalCase: internalCase,
233
208
  classNameCase: pascalCase,
234
209
  pascalCase: pascalCase,
235
- getInlineParseContent: this.schemaParser.getInlineParseContent,
236
- getParseContent: this.schemaParser.getParseContent,
237
- getComponentByRef: this.schemaComponentMap.get,
238
- parseSchema: this.schemaParser.parseSchema,
239
- checkAndAddNull: this.schemaParser.schemaUtils.safeAddNullToType,
240
- safeAddNullToType: this.schemaParser.schemaUtils.safeAddNullToType,
241
- isNeedToAddNull: this.schemaParser.schemaUtils.isNullMissingInType,
242
- inlineExtraFormatters: this.schemaParser.schemaFormatters.inline,
243
- formatters: this.schemaParser.schemaFormatters.base,
244
- formatModelName: this.typeName.format,
210
+ getInlineParseContent: this.schemaParserFabric.getInlineParseContent,
211
+ getParseContent: this.schemaParserFabric.getParseContent,
212
+ getComponentByRef: this.schemaComponentsMap.get,
213
+ parseSchema: this.schemaParserFabric.parseSchema,
214
+ checkAndAddNull: this.schemaParserFabric.schemaUtils.safeAddNullToType,
215
+ safeAddNullToType:
216
+ this.schemaParserFabric.schemaUtils.safeAddNullToType,
217
+ isNeedToAddNull:
218
+ this.schemaParserFabric.schemaUtils.isNullMissingInType,
219
+ inlineExtraFormatters: this.schemaParserFabric.schemaFormatters.inline,
220
+ formatters: this.schemaParserFabric.schemaFormatters.base,
221
+ formatModelName: this.typeNameFormatter.format,
245
222
  fmtToJSDocLine: function fmtToJSDocLine(line, { eol = true }) {
246
- return ` * ${line}${eol ? "\n" : ""}`;
223
+ return ` * ${line}${eol ? '\n' : ''}`;
247
224
  },
248
225
  NameResolver: NameResolver,
249
226
  _,
250
- require: this.templates.requireFnFromTemplate,
227
+ require: this.templatesWorker.requireFnFromTemplate,
251
228
  },
252
229
  config: this.config,
253
230
  };
254
231
  };
255
232
 
233
+ collectModelTypes = () => {
234
+ const components = this.schemaComponentsMap.getComponents();
235
+ let modelTypes = [];
236
+
237
+ const getSchemaComponentsCount = () =>
238
+ components.filter((c) => c.componentName === 'schemas').length;
239
+
240
+ let schemaComponentsCount = getSchemaComponentsCount();
241
+ let processedCount = 0;
242
+
243
+ while (processedCount < schemaComponentsCount) {
244
+ modelTypes = [];
245
+ processedCount = 0;
246
+ for (const component of components) {
247
+ if (component.componentName === 'schemas') {
248
+ const modelType = this.prepareModelType(component);
249
+ if (modelType) {
250
+ modelTypes.push(modelType);
251
+ }
252
+ processedCount++;
253
+ }
254
+ }
255
+ schemaComponentsCount = getSchemaComponentsCount();
256
+ }
257
+
258
+ if (this.config.sortTypes) {
259
+ return modelTypes.sort(sortByProperty('name'));
260
+ }
261
+
262
+ return modelTypes;
263
+ };
264
+
256
265
  prepareModelType = (typeInfo) => {
266
+ if (typeInfo.$prepared) return typeInfo.$prepared;
267
+
257
268
  if (!typeInfo.typeData) {
258
- typeInfo.typeData = this.schemaParser.parseSchema(typeInfo.rawTypeData, typeInfo.typeName);
269
+ typeInfo.typeData = this.schemaParserFabric.parseSchema(
270
+ typeInfo.rawTypeData,
271
+ typeInfo.typeName,
272
+ );
259
273
  }
260
274
  const rawTypeData = typeInfo.typeData;
261
- const typeData = this.schemaParser.schemaFormatters.base[rawTypeData.type]
262
- ? this.schemaParser.schemaFormatters.base[rawTypeData.type](rawTypeData)
275
+ const typeData = this.schemaParserFabric.schemaFormatters.base[
276
+ rawTypeData.type
277
+ ]
278
+ ? this.schemaParserFabric.schemaFormatters.base[rawTypeData.type](
279
+ rawTypeData,
280
+ )
263
281
  : rawTypeData;
264
282
  let { typeIdentifier, name: originalName, content, description } = typeData;
265
- const name = this.typeName.format(originalName);
283
+ const name = this.typeNameFormatter.format(originalName);
266
284
 
267
285
  if (name === null) return null;
268
286
 
269
- return {
287
+ const preparedModelType = {
270
288
  ...typeData,
271
289
  typeIdentifier,
272
290
  name,
@@ -276,161 +294,237 @@ class CodeGenProcess {
276
294
  content: content,
277
295
  typeData,
278
296
  };
297
+
298
+ typeInfo.$prepared = preparedModelType;
299
+
300
+ return preparedModelType;
279
301
  };
280
302
 
281
- generateOutputFiles = ({ configuration }) => {
303
+ /**
304
+ *
305
+ * @param configuration
306
+ * @returns {Promise<TranslatorIO[]>}
307
+ */
308
+ generateOutputFiles = async ({ configuration }) => {
282
309
  const { modular, templatesToRender } = this.config;
283
310
 
284
311
  const output = modular
285
- ? this.createMultipleFileInfos(templatesToRender, configuration)
286
- : this.createSingleFileInfo(templatesToRender, configuration);
312
+ ? await this.createMultipleFileInfos(templatesToRender, configuration)
313
+ : await this.createSingleFileInfo(templatesToRender, configuration);
287
314
 
288
315
  if (!_.isEmpty(configuration.extraTemplates)) {
289
- output.push(
290
- ..._.map(configuration.extraTemplates, (extraTemplate) => {
291
- return this.createOutputFileInfo(
316
+ for (const extraTemplate of configuration.extraTemplates) {
317
+ const content = this.templatesWorker.renderTemplate(
318
+ this.fileSystem.getFileContent(extraTemplate.path),
319
+ configuration,
320
+ );
321
+ output.push(
322
+ ...(await this.createOutputFileInfo(
292
323
  configuration,
293
324
  extraTemplate.name,
294
- this.templates.renderTemplate(this.fileSystem.getFileContent(extraTemplate.path), configuration),
295
- );
296
- }),
297
- );
325
+ content,
326
+ )),
327
+ );
328
+ }
298
329
  }
299
330
 
300
- return output.filter((fileInfo) => !!fileInfo && !!fileInfo.content);
331
+ return output.filter((fileInfo) => !!fileInfo && !!fileInfo.fileContent);
301
332
  };
302
333
 
303
- createMultipleFileInfos = (templatesToRender, configuration) => {
334
+ /**
335
+ * @param templatesToRender
336
+ * @param configuration
337
+ * @returns {Promise<TranslatorIO[]>}
338
+ */
339
+ createMultipleFileInfos = async (templatesToRender, configuration) => {
304
340
  const { routes } = configuration;
305
- const { fileNames, generateRouteTypes, generateClient } = configuration.config;
341
+ const { fileNames, generateRouteTypes, generateClient } =
342
+ configuration.config;
343
+ /**
344
+ * @type {TranslatorIO[]}
345
+ */
306
346
  const modularApiFileInfos = [];
307
347
 
308
348
  if (routes.$outOfModule) {
309
349
  if (generateRouteTypes) {
310
- const outOfModuleRouteContent = this.templates.renderTemplate(templatesToRender.routeTypes, {
311
- ...configuration,
312
- route: configuration.routes.$outOfModule,
313
- });
350
+ const outOfModuleRouteContent = this.templatesWorker.renderTemplate(
351
+ templatesToRender.routeTypes,
352
+ {
353
+ ...configuration,
354
+ route: configuration.routes.$outOfModule,
355
+ },
356
+ );
314
357
 
315
358
  modularApiFileInfos.push(
316
- this.createOutputFileInfo(configuration, fileNames.outOfModuleApi, outOfModuleRouteContent),
359
+ ...(await this.createOutputFileInfo(
360
+ configuration,
361
+ fileNames.outOfModuleApi,
362
+ outOfModuleRouteContent,
363
+ )),
317
364
  );
318
365
  }
319
366
  if (generateClient) {
320
- const outOfModuleApiContent = this.templates.renderTemplate(templatesToRender.api, {
321
- ...configuration,
322
- route: configuration.routes.$outOfModule,
323
- });
367
+ const outOfModuleApiContent = this.templatesWorker.renderTemplate(
368
+ templatesToRender.api,
369
+ {
370
+ ...configuration,
371
+ route: configuration.routes.$outOfModule,
372
+ },
373
+ );
324
374
 
325
375
  modularApiFileInfos.push(
326
- this.createOutputFileInfo(configuration, fileNames.outOfModuleApi, outOfModuleApiContent),
376
+ ...(await this.createOutputFileInfo(
377
+ configuration,
378
+ fileNames.outOfModuleApi,
379
+ outOfModuleApiContent,
380
+ )),
327
381
  );
328
382
  }
329
383
  }
330
384
 
331
385
  if (routes.combined) {
332
- modularApiFileInfos.push(
333
- ..._.reduce(
334
- routes.combined,
335
- (apiFileInfos, route) => {
336
- if (generateRouteTypes) {
337
- const routeModuleContent = this.templates.renderTemplate(templatesToRender.routeTypes, {
338
- ...configuration,
339
- route,
340
- });
341
-
342
- apiFileInfos.push(
343
- this.createOutputFileInfo(configuration, pascalCase(`${route.moduleName}_Route`), routeModuleContent),
344
- );
345
- }
346
-
347
- if (generateClient) {
348
- const apiModuleContent = this.templates.renderTemplate(templatesToRender.api, {
349
- ...configuration,
350
- route,
351
- });
352
-
353
- apiFileInfos.push(
354
- this.createOutputFileInfo(configuration, pascalCase(route.moduleName), apiModuleContent),
355
- );
356
- }
357
-
358
- return apiFileInfos;
359
- },
360
- [],
361
- ),
362
- );
386
+ for (const route of routes.combined) {
387
+ if (generateRouteTypes) {
388
+ const routeModuleContent = this.templatesWorker.renderTemplate(
389
+ templatesToRender.routeTypes,
390
+ {
391
+ ...configuration,
392
+ route,
393
+ },
394
+ );
395
+
396
+ modularApiFileInfos.push(
397
+ ...(await this.createOutputFileInfo(
398
+ configuration,
399
+ pascalCase(`${route.moduleName}_Route`),
400
+ routeModuleContent,
401
+ )),
402
+ );
403
+ }
404
+
405
+ if (generateClient) {
406
+ const apiModuleContent = this.templatesWorker.renderTemplate(
407
+ templatesToRender.api,
408
+ {
409
+ ...configuration,
410
+ route,
411
+ },
412
+ );
413
+
414
+ modularApiFileInfos.push(
415
+ ...(await this.createOutputFileInfo(
416
+ configuration,
417
+ pascalCase(route.moduleName),
418
+ apiModuleContent,
419
+ )),
420
+ );
421
+ }
422
+ }
363
423
  }
364
424
 
365
425
  return [
366
- this.createOutputFileInfo(
426
+ ...(await this.createOutputFileInfo(
367
427
  configuration,
368
428
  fileNames.dataContracts,
369
- this.templates.renderTemplate(templatesToRender.dataContracts, configuration),
370
- ),
371
- generateClient &&
372
- this.createOutputFileInfo(
429
+ this.templatesWorker.renderTemplate(
430
+ templatesToRender.dataContracts,
373
431
  configuration,
374
- fileNames.httpClient,
375
- this.templates.renderTemplate(templatesToRender.httpClient, configuration),
376
432
  ),
433
+ )),
434
+ ...(generateClient
435
+ ? await this.createOutputFileInfo(
436
+ configuration,
437
+ fileNames.httpClient,
438
+ this.templatesWorker.renderTemplate(
439
+ templatesToRender.httpClient,
440
+ configuration,
441
+ ),
442
+ )
443
+ : []),
377
444
  ...modularApiFileInfos,
378
445
  ];
379
446
  };
380
447
 
381
- createSingleFileInfo = (templatesToRender, configuration) => {
448
+ /**
449
+ *
450
+ * @param templatesToRender
451
+ * @param configuration
452
+ * @returns {Promise<TranslatorIO[]>}
453
+ */
454
+ createSingleFileInfo = async (templatesToRender, configuration) => {
382
455
  const { generateRouteTypes, generateClient } = configuration.config;
383
456
 
384
- return [
385
- this.createOutputFileInfo(
386
- configuration,
387
- configuration.fileName,
388
- _.compact([
389
- this.templates.renderTemplate(templatesToRender.dataContracts, configuration),
390
- generateRouteTypes && this.templates.renderTemplate(templatesToRender.routeTypes, configuration),
391
- generateClient && this.templates.renderTemplate(templatesToRender.httpClient, configuration),
392
- generateClient && this.templates.renderTemplate(templatesToRender.api, configuration),
393
- ]).join("\n"),
394
- ),
395
- ];
457
+ return await this.createOutputFileInfo(
458
+ configuration,
459
+ configuration.fileName,
460
+ _.compact([
461
+ this.templatesWorker.renderTemplate(
462
+ templatesToRender.dataContracts,
463
+ configuration,
464
+ ),
465
+ generateRouteTypes &&
466
+ this.templatesWorker.renderTemplate(
467
+ templatesToRender.routeTypes,
468
+ configuration,
469
+ ),
470
+ generateClient &&
471
+ this.templatesWorker.renderTemplate(
472
+ templatesToRender.httpClient,
473
+ configuration,
474
+ ),
475
+ generateClient &&
476
+ this.templatesWorker.renderTemplate(
477
+ templatesToRender.api,
478
+ configuration,
479
+ ),
480
+ ]).join('\n'),
481
+ );
396
482
  };
397
483
 
398
- createOutputFileInfo = (configuration, fileName, content) => {
399
- const fixedFileName = this.fileSystem.cropExtension(fileName);
484
+ /**
485
+ *
486
+ * @param configuration
487
+ * @param fileNameFull
488
+ * @param content
489
+ * @returns {Promise<TranslatorIO[]>}
490
+ */
491
+ createOutputFileInfo = async (configuration, fileNameFull, content) => {
492
+ const fileName = this.fileSystem.cropExtension(fileNameFull);
493
+ const fileExtension = ts.Extension.Ts;
400
494
 
401
495
  if (configuration.translateToJavaScript) {
402
- const { sourceContent, declarationContent } = translateToJS(`${fixedFileName}${ts.Extension.Ts}`, content);
403
-
404
- this.logger.debug("generating output for", `${fixedFileName}${ts.Extension.Js}`);
405
- this.logger.debug(sourceContent);
406
-
407
- this.logger.debug("generating output for", `${fixedFileName}${ts.Extension.Js}`);
408
- this.logger.debug(declarationContent);
496
+ this.logger.debug('using js translator for', fileName);
497
+ return await this.javascriptTranslator.translate({
498
+ fileName: fileName,
499
+ fileExtension: fileExtension,
500
+ fileContent: content,
501
+ });
502
+ }
409
503
 
410
- return {
411
- name: `${fixedFileName}${ts.Extension.Js}`,
412
- content: this.codeFormatter.formatCode(sourceContent),
413
- declaration: {
414
- name: `${fixedFileName}${ts.Extension.Dts}`,
415
- content: this.codeFormatter.formatCode(declarationContent),
416
- },
417
- };
504
+ if (configuration.customTranslator) {
505
+ this.logger.debug('using custom translator for', fileName);
506
+ return await configuration.customTranslator.translate({
507
+ fileName: fileName,
508
+ fileExtension: fileExtension,
509
+ fileContent: content,
510
+ });
418
511
  }
419
512
 
420
- this.logger.debug("generating output for", `${fixedFileName}${ts.Extension.Js}`);
421
- this.logger.debug(content);
513
+ this.logger.debug('generating output for', `${fileName}${fileExtension}`);
422
514
 
423
- return {
424
- name: `${fixedFileName}${ts.Extension.Ts}`,
425
- content: this.codeFormatter.formatCode(content),
426
- declaration: null,
427
- };
515
+ return [
516
+ {
517
+ fileName,
518
+ fileExtension: fileExtension,
519
+ fileContent: await this.codeFormatter.formatCode(content),
520
+ },
521
+ ];
428
522
  };
429
523
 
430
524
  createApiConfig = (swaggerSchema) => {
431
525
  const { info, servers, host, basePath, externalDocs, tags } = swaggerSchema;
432
- const server = (servers && servers[0]) || { url: "" };
433
- const { title = "No title", version, description: schemaDescription = "" } = info || {};
526
+ const server = (servers && servers[0]) || { url: '' };
527
+ const { title = 'No title', version } = info || {};
434
528
  const { url: serverUrl } = server;
435
529
 
436
530
  return {
@@ -440,8 +534,8 @@ class CodeGenProcess {
440
534
  host,
441
535
  externalDocs: _.merge(
442
536
  {
443
- url: "",
444
- description: "",
537
+ url: '',
538
+ description: '',
445
539
  },
446
540
  externalDocs,
447
541
  ),
@@ -451,6 +545,15 @@ class CodeGenProcess {
451
545
  version,
452
546
  };
453
547
  };
548
+
549
+ injectClassInstance = (key, value) => {
550
+ this[key] = value;
551
+ PATCHABLE_INSTANCES.forEach((instanceKey) => {
552
+ if (instanceKey !== key && key in this[instanceKey]) {
553
+ this[instanceKey][key] = value;
554
+ }
555
+ });
556
+ };
454
557
  }
455
558
 
456
559
  module.exports = {