swagger-typescript-api 13.0.0-experimental-1 → 13.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +22 -12
  3. package/cli/constants.js +3 -3
  4. package/cli/execute.js +52 -31
  5. package/cli/index.d.ts +1 -2
  6. package/cli/index.js +18 -17
  7. package/cli/operations/display-help.js +51 -29
  8. package/cli/parse-args.js +3 -3
  9. package/cli/process-option.js +28 -20
  10. package/index.d.ts +113 -8
  11. package/index.js +158 -135
  12. package/package.json +35 -30
  13. package/src/code-formatter.js +28 -13
  14. package/src/code-gen-process.js +357 -259
  15. package/src/commands/generate-templates/configuration.js +2 -2
  16. package/src/commands/generate-templates/index.js +1 -2
  17. package/src/commands/generate-templates/templates-gen-process.js +62 -35
  18. package/src/component-type-name-resolver.js +44 -0
  19. package/src/configuration.js +167 -95
  20. package/src/constants.js +28 -22
  21. package/src/index.js +3 -4
  22. package/src/schema-components-map.js +39 -23
  23. package/src/schema-parser/base-schema-parsers/array.js +43 -0
  24. package/src/schema-parser/base-schema-parsers/complex.js +51 -0
  25. package/src/schema-parser/base-schema-parsers/discriminator.js +301 -0
  26. package/src/schema-parser/base-schema-parsers/enum.js +158 -0
  27. package/src/schema-parser/base-schema-parsers/object.js +105 -0
  28. package/src/schema-parser/base-schema-parsers/primitive.js +63 -0
  29. package/src/schema-parser/complex-schema-parsers/all-of.js +26 -0
  30. package/src/schema-parser/complex-schema-parsers/any-of.js +34 -0
  31. package/src/schema-parser/complex-schema-parsers/not.js +9 -0
  32. package/src/schema-parser/complex-schema-parsers/one-of.js +27 -0
  33. package/src/schema-parser/mono-schema-parser.js +48 -0
  34. package/src/schema-parser/schema-formatters.js +69 -60
  35. package/src/schema-parser/schema-parser-fabric.js +131 -0
  36. package/src/schema-parser/schema-parser.js +208 -427
  37. package/src/schema-parser/schema-utils.js +123 -58
  38. package/src/schema-parser/util/enum-key-resolver.js +26 -0
  39. package/src/schema-routes/schema-routes.js +1225 -0
  40. package/src/schema-routes/util/specific-arg-name-resolver.js +26 -0
  41. package/src/schema-walker.js +93 -0
  42. package/src/swagger-schema-resolver.js +61 -28
  43. package/src/templates-worker.js +240 -0
  44. package/src/translators/javascript.js +83 -0
  45. package/src/translators/translator.js +35 -0
  46. package/src/type-name-formatter.js +33 -18
  47. package/src/util/file-system.js +30 -14
  48. package/src/util/id.js +2 -2
  49. package/src/util/internal-case.js +1 -1
  50. package/src/util/logger.js +46 -20
  51. package/src/util/name-resolver.js +52 -60
  52. package/src/util/object-assign.js +7 -3
  53. package/src/util/pascal-case.js +1 -1
  54. package/src/util/request.js +5 -5
  55. package/src/util/sort-by-property.js +17 -0
  56. package/templates/README.md +17 -17
  57. package/templates/base/README.md +7 -7
  58. package/templates/base/data-contract-jsdoc.ejs +37 -37
  59. package/templates/base/data-contracts.ejs +40 -27
  60. package/templates/base/enum-data-contract.ejs +12 -12
  61. package/templates/base/http-client.ejs +3 -3
  62. package/templates/base/http-clients/axios-http-client.ejs +139 -138
  63. package/templates/base/http-clients/fetch-http-client.ejs +224 -224
  64. package/templates/base/interface-data-contract.ejs +10 -10
  65. package/templates/base/object-field-jsdoc.ejs +28 -28
  66. package/templates/base/route-docs.ejs +30 -30
  67. package/templates/base/route-name.ejs +42 -42
  68. package/templates/base/route-type.ejs +22 -21
  69. package/templates/base/type-data-contract.ejs +15 -15
  70. package/templates/default/README.md +6 -6
  71. package/templates/default/api.ejs +69 -68
  72. package/templates/default/procedure-call.ejs +100 -100
  73. package/templates/default/route-types.ejs +32 -32
  74. package/templates/modular/README.md +6 -6
  75. package/templates/modular/api.ejs +28 -28
  76. package/templates/modular/procedure-call.ejs +100 -100
  77. package/templates/modular/route-types.ejs +18 -18
  78. package/src/schema-parser/schema-processor.js +0 -79
  79. package/src/schema-parser/schema-routes.js +0 -950
  80. package/src/templates.js +0 -182
  81. package/src/translators/JavaScript.js +0 -60
@@ -1,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 { TypeNameFormatter } = require("./type-name-formatter.js");
6
- const _ = require("lodash");
7
- const { SchemaProcessor } = require("./schema-parser/schema-processor.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 {TypeNameFormatter}
37
- */
38
- typeName;
39
- /**
40
- * @type {SchemaProcessor}
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,35 +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 TypeNameFormatter(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 SchemaProcessor(
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
- await this.schemaRoutes.init();
89
- this.config.update({ templatePaths: this.templates.getTemplatePaths(this.config) });
90
- 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
+ });
91
85
 
92
86
  const swagger = await this.swaggerSchemaResolver.create();
93
87
 
@@ -98,70 +92,50 @@ class CodeGenProcess {
98
92
  originalSchema: swagger.originalSchema,
99
93
  });
100
94
 
101
- this.logger.event("start generating your typescript api");
95
+ this.schemaWalker.addSchema('$usage', swagger.usageSchema);
96
+ this.schemaWalker.addSchema('$original', swagger.originalSchema);
102
97
 
103
- this.config.update(this.config.hooks.onInit(this.config) || this.config);
98
+ this.logger.event('start generating your typescript api');
104
99
 
105
- this.schemaComponentMap.processSchema(swagger.usageSchema);
100
+ this.config.update(
101
+ this.config.hooks.onInit(this.config, this) || this.config,
102
+ );
106
103
 
107
- 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
+ );
108
118
 
109
- this.config.componentTypeNameResolver.reserve(componentSchemaNames);
119
+ const schemaComponents = this.schemaComponentsMap.filter('schemas');
110
120
 
111
- const parsedSchemas = await Promise.all(
112
- _.map(_.get(swagger.usageSchema.components, "schemas"), (schema, typeName) =>
113
- this.schemaParser.parseSchema(schema, typeName),
114
- ),
115
- );
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
+ });
116
129
 
117
- await this.schemaRoutes.attachSchema({
130
+ this.schemaRoutes.attachSchema({
118
131
  usageSchema: swagger.usageSchema,
119
132
  parsedSchemas,
120
133
  });
121
134
 
122
- const usageComponentSchemas = this.schemaComponentMap.filter("schemas");
123
- const sortByProperty = (propertyName) => (o1, o2) => {
124
- if (o1[propertyName] > o2[propertyName]) {
125
- return 1;
126
- }
127
- if (o1[propertyName] < o2[propertyName]) {
128
- return -1;
129
- }
130
- return 0;
131
- };
132
-
133
- const sortSchemas = (schemas) => {
134
- if (this.config.sortTypes) {
135
- return schemas.sort(sortByProperty("typeName")).map((schema) => {
136
- if (schema.rawTypeData?.properties) {
137
- return {
138
- ...schema,
139
- rawTypeData: {
140
- ...schema.rawTypeData,
141
- $parsed: schema.rawTypeData["$parsed"] && {
142
- ...schema.rawTypeData["$parsed"],
143
- content: Array.isArray(schema.rawTypeData["$parsed"].content)
144
- ? schema.rawTypeData["$parsed"].content.sort(sortByProperty("name"))
145
- : schema.rawTypeData["$parsed"].content,
146
- },
147
- },
148
- };
149
- }
150
- return schema;
151
- });
152
- }
153
- return schemas;
154
- };
155
-
156
- const modelTypes = (await Promise.all(_.map(sortSchemas(usageComponentSchemas), this.prepareModelType))).filter(
157
- Boolean,
158
- );
159
-
160
135
  const rawConfiguration = {
161
136
  apiConfig: this.createApiConfig(swagger.usageSchema),
162
137
  config: this.config,
163
- modelTypes: modelTypes,
164
- rawModelTypes: usageComponentSchemas,
138
+ modelTypes: this.collectModelTypes(),
165
139
  hasSecurityRoutes: this.schemaRoutes.hasSecurityRoutes,
166
140
  hasQueryRoutes: this.schemaRoutes.hasQueryRoutes,
167
141
  hasFormDataRoutes: this.schemaRoutes.hasFormDataRoutes,
@@ -170,10 +144,14 @@ class CodeGenProcess {
170
144
  extraTemplates: this.config.extraTemplates,
171
145
  fileName: this.config.fileName,
172
146
  translateToJavaScript: this.config.toJS,
147
+ customTranslator: this.config.customTranslator
148
+ ? new this.config.customTranslator(this)
149
+ : null,
173
150
  utils: this.getRenderTemplateData().utils,
174
151
  };
175
152
 
176
- const configuration = this.config.hooks.onPrepareConfig(rawConfiguration) || rawConfiguration;
153
+ const configuration =
154
+ this.config.hooks.onPrepareConfig(rawConfiguration) || rawConfiguration;
177
155
 
178
156
  if (this.fileSystem.pathIsExist(this.config.output)) {
179
157
  if (this.config.cleanOutput) {
@@ -181,7 +159,9 @@ class CodeGenProcess {
181
159
  this.fileSystem.cleanDir(this.config.output);
182
160
  }
183
161
  } else {
184
- 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
+ );
185
165
  this.fileSystem.createDir(this.config.output);
186
166
  }
187
167
 
@@ -191,41 +171,28 @@ class CodeGenProcess {
191
171
 
192
172
  const isDirPath = this.fileSystem.pathIsDir(this.config.output);
193
173
 
194
- const generatedFiles = files.map((file) => {
195
- if (!isDirPath) return file;
196
-
197
- if (this.config.toJS) {
198
- this.fileSystem.createFile({
199
- path: this.config.output,
200
- fileName: file.name,
201
- content: file.content,
202
- withPrefix: true,
203
- });
174
+ if (isDirPath) {
175
+ files.forEach((file) => {
204
176
  this.fileSystem.createFile({
205
177
  path: this.config.output,
206
- fileName: file.declaration.name,
207
- content: file.declaration.content,
178
+ fileName: `${file.fileName}${file.fileExtension}`,
179
+ content: file.fileContent,
208
180
  withPrefix: true,
209
181
  });
210
- this.logger.success(`javascript api file`, file.name, `created in ${this.config.output}`);
211
- } else {
212
- this.fileSystem.createFile({
213
- path: this.config.output,
214
- fileName: file.name,
215
- content: file.content,
216
- withPrefix: true,
217
- });
218
- this.logger.success(`typescript api file`, file.name, `created in ${this.config.output}`);
219
- }
220
182
 
221
- return file;
222
- });
183
+ this.logger.success(
184
+ `api file`,
185
+ `"${file.fileName}${file.fileExtension}"`,
186
+ `created in ${this.config.output}`,
187
+ );
188
+ });
189
+ }
223
190
 
224
191
  return {
225
- files: generatedFiles,
192
+ files,
226
193
  configuration,
227
- getTemplate: this.templates.getTemplate,
228
- renderTemplate: await this.templates.renderTemplate,
194
+ getTemplate: this.templatesWorker.getTemplate,
195
+ renderTemplate: this.templatesWorker.renderTemplate,
229
196
  createFile: this.fileSystem.createFile,
230
197
  formatTSContent: this.codeFormatter.formatCode,
231
198
  };
@@ -235,57 +202,109 @@ class CodeGenProcess {
235
202
  return {
236
203
  utils: {
237
204
  Ts: this.config.Ts,
238
- formatDescription: this.schemaParser.schemaFormatters.formatDescription,
205
+ formatDescription:
206
+ this.schemaParserFabric.schemaFormatters.formatDescription,
239
207
  internalCase: internalCase,
240
208
  classNameCase: pascalCase,
241
209
  pascalCase: pascalCase,
242
- getInlineParseContent: this.schemaParser.getInlineParseContent,
243
- getParseContent: this.schemaParser.getParseContent,
244
- getComponentByRef: this.schemaComponentMap.get,
245
- parseSchema: this.schemaParser.parseSchema,
246
- checkAndAddNull: this.schemaParser.schemaUtils.safeAddNullToType,
247
- safeAddNullToType: this.schemaParser.schemaUtils.safeAddNullToType,
248
- isNeedToAddNull: this.schemaParser.schemaUtils.isNullMissingInType,
249
- inlineExtraFormatters: this.schemaParser.schemaFormatters.inline,
250
- formatters: this.schemaParser.schemaFormatters.base,
251
- 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,
252
222
  fmtToJSDocLine: function fmtToJSDocLine(line, { eol = true }) {
253
- return ` * ${line}${eol ? "\n" : ""}`;
223
+ return ` * ${line}${eol ? '\n' : ''}`;
254
224
  },
255
225
  NameResolver: NameResolver,
256
226
  _,
257
- require: this.templates.requireFnFromTemplate,
227
+ require: this.templatesWorker.requireFnFromTemplate,
258
228
  },
259
229
  config: this.config,
260
230
  };
261
231
  };
262
232
 
263
- prepareModelType = async (typeInfo) => {
264
- if (!typeInfo.typeData) {
265
- typeInfo.typeData = await this.schemaParser.parseSchema(typeInfo.rawTypeData, typeInfo.typeName);
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();
266
256
  }
267
- const typeData = await this.schemaParser.schemaFormatters.formatSchema(typeInfo.typeData, {
268
- formatType: "base",
269
- schemaType: typeInfo.typeData.type,
270
- });
271
257
 
258
+ if (this.config.sortTypes) {
259
+ return modelTypes.sort(sortByProperty('name'));
260
+ }
261
+
262
+ return modelTypes;
263
+ };
264
+
265
+ prepareModelType = (typeInfo) => {
266
+ if (typeInfo.$prepared) return typeInfo.$prepared;
267
+
268
+ if (!typeInfo.typeData) {
269
+ typeInfo.typeData = this.schemaParserFabric.parseSchema(
270
+ typeInfo.rawTypeData,
271
+ typeInfo.typeName,
272
+ );
273
+ }
274
+ const rawTypeData = typeInfo.typeData;
275
+ const typeData = this.schemaParserFabric.schemaFormatters.base[
276
+ rawTypeData.type
277
+ ]
278
+ ? this.schemaParserFabric.schemaFormatters.base[rawTypeData.type](
279
+ rawTypeData,
280
+ )
281
+ : rawTypeData;
272
282
  let { typeIdentifier, name: originalName, content, description } = typeData;
273
- const name = this.typeName.format(originalName);
283
+ const name = this.typeNameFormatter.format(originalName);
274
284
 
275
285
  if (name === null) return null;
276
286
 
277
- return {
287
+ const preparedModelType = {
278
288
  ...typeData,
279
289
  typeIdentifier,
280
290
  name,
281
291
  description,
282
- $content: typeInfo.typeData.content,
283
- rawContent: typeInfo.typeData.content,
292
+ $content: rawTypeData.content,
293
+ rawContent: rawTypeData.content,
284
294
  content: content,
285
295
  typeData,
286
296
  };
297
+
298
+ typeInfo.$prepared = preparedModelType;
299
+
300
+ return preparedModelType;
287
301
  };
288
302
 
303
+ /**
304
+ *
305
+ * @param configuration
306
+ * @returns {Promise<TranslatorIO[]>}
307
+ */
289
308
  generateOutputFiles = async ({ configuration }) => {
290
309
  const { modular, templatesToRender } = this.config;
291
310
 
@@ -294,148 +313,218 @@ class CodeGenProcess {
294
313
  : await this.createSingleFileInfo(templatesToRender, configuration);
295
314
 
296
315
  if (!_.isEmpty(configuration.extraTemplates)) {
297
- output.push(
298
- ...(await Promise.all(
299
- _.map(configuration.extraTemplates, async (extraTemplate) => {
300
- return this.createOutputFileInfo(
301
- configuration,
302
- extraTemplate.name,
303
- await await this.templates.renderTemplate(
304
- this.fileSystem.getFileContent(extraTemplate.path),
305
- configuration,
306
- ),
307
- );
308
- }),
309
- )),
310
- );
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(
323
+ configuration,
324
+ extraTemplate.name,
325
+ content,
326
+ )),
327
+ );
328
+ }
311
329
  }
312
330
 
313
- return output.filter((fileInfo) => !!fileInfo && !!fileInfo.content);
331
+ return output.filter((fileInfo) => !!fileInfo && !!fileInfo.fileContent);
314
332
  };
315
333
 
334
+ /**
335
+ * @param templatesToRender
336
+ * @param configuration
337
+ * @returns {Promise<TranslatorIO[]>}
338
+ */
316
339
  createMultipleFileInfos = async (templatesToRender, configuration) => {
317
340
  const { routes } = configuration;
318
- const { fileNames, generateRouteTypes, generateClient } = configuration.config;
341
+ const { fileNames, generateRouteTypes, generateClient } =
342
+ configuration.config;
343
+ /**
344
+ * @type {TranslatorIO[]}
345
+ */
319
346
  const modularApiFileInfos = [];
320
347
 
321
348
  if (routes.$outOfModule) {
322
349
  if (generateRouteTypes) {
323
- const outOfModuleRouteContent = await this.templates.renderTemplate(templatesToRender.routeTypes, {
324
- ...configuration,
325
- route: configuration.routes.$outOfModule,
326
- });
350
+ const outOfModuleRouteContent = this.templatesWorker.renderTemplate(
351
+ templatesToRender.routeTypes,
352
+ {
353
+ ...configuration,
354
+ route: configuration.routes.$outOfModule,
355
+ },
356
+ );
327
357
 
328
358
  modularApiFileInfos.push(
329
- this.createOutputFileInfo(configuration, fileNames.outOfModuleApi, outOfModuleRouteContent),
359
+ ...(await this.createOutputFileInfo(
360
+ configuration,
361
+ fileNames.outOfModuleApi,
362
+ outOfModuleRouteContent,
363
+ )),
330
364
  );
331
365
  }
332
366
  if (generateClient) {
333
- const outOfModuleApiContent = await this.templates.renderTemplate(templatesToRender.api, {
334
- ...configuration,
335
- route: configuration.routes.$outOfModule,
336
- });
367
+ const outOfModuleApiContent = this.templatesWorker.renderTemplate(
368
+ templatesToRender.api,
369
+ {
370
+ ...configuration,
371
+ route: configuration.routes.$outOfModule,
372
+ },
373
+ );
337
374
 
338
375
  modularApiFileInfos.push(
339
- this.createOutputFileInfo(configuration, fileNames.outOfModuleApi, outOfModuleApiContent),
376
+ ...(await this.createOutputFileInfo(
377
+ configuration,
378
+ fileNames.outOfModuleApi,
379
+ outOfModuleApiContent,
380
+ )),
340
381
  );
341
382
  }
342
383
  }
343
384
 
344
385
  if (routes.combined) {
345
- for await (const route of routes.combined) {
386
+ for (const route of routes.combined) {
346
387
  if (generateRouteTypes) {
347
- const routeModuleContent = await this.templates.renderTemplate(templatesToRender.routeTypes, {
348
- ...configuration,
349
- route,
350
- });
388
+ const routeModuleContent = this.templatesWorker.renderTemplate(
389
+ templatesToRender.routeTypes,
390
+ {
391
+ ...configuration,
392
+ route,
393
+ },
394
+ );
351
395
 
352
396
  modularApiFileInfos.push(
353
- this.createOutputFileInfo(configuration, pascalCase(`${route.moduleName}_Route`), routeModuleContent),
397
+ ...(await this.createOutputFileInfo(
398
+ configuration,
399
+ pascalCase(`${route.moduleName}_Route`),
400
+ routeModuleContent,
401
+ )),
354
402
  );
355
403
  }
356
404
 
357
405
  if (generateClient) {
358
- const apiModuleContent = await this.templates.renderTemplate(templatesToRender.api, {
359
- ...configuration,
360
- route,
361
- });
406
+ const apiModuleContent = this.templatesWorker.renderTemplate(
407
+ templatesToRender.api,
408
+ {
409
+ ...configuration,
410
+ route,
411
+ },
412
+ );
362
413
 
363
414
  modularApiFileInfos.push(
364
- this.createOutputFileInfo(configuration, pascalCase(route.moduleName), apiModuleContent),
415
+ ...(await this.createOutputFileInfo(
416
+ configuration,
417
+ pascalCase(route.moduleName),
418
+ apiModuleContent,
419
+ )),
365
420
  );
366
421
  }
367
422
  }
368
423
  }
369
424
 
370
425
  return [
371
- this.createOutputFileInfo(
426
+ ...(await this.createOutputFileInfo(
372
427
  configuration,
373
428
  fileNames.dataContracts,
374
- await this.templates.renderTemplate(templatesToRender.dataContracts, configuration),
375
- ),
376
- generateClient &&
377
- this.createOutputFileInfo(
429
+ this.templatesWorker.renderTemplate(
430
+ templatesToRender.dataContracts,
378
431
  configuration,
379
- fileNames.httpClient,
380
- await this.templates.renderTemplate(templatesToRender.httpClient, configuration),
381
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
+ : []),
382
444
  ...modularApiFileInfos,
383
445
  ];
384
446
  };
385
447
 
448
+ /**
449
+ *
450
+ * @param templatesToRender
451
+ * @param configuration
452
+ * @returns {Promise<TranslatorIO[]>}
453
+ */
386
454
  createSingleFileInfo = async (templatesToRender, configuration) => {
387
455
  const { generateRouteTypes, generateClient } = configuration.config;
388
456
 
389
- return [
390
- this.createOutputFileInfo(
391
- configuration,
392
- configuration.fileName,
393
- _.compact([
394
- await this.templates.renderTemplate(templatesToRender.dataContracts, configuration),
395
- generateRouteTypes && (await this.templates.renderTemplate(templatesToRender.routeTypes, configuration)),
396
- generateClient && (await this.templates.renderTemplate(templatesToRender.httpClient, configuration)),
397
- generateClient && (await this.templates.renderTemplate(templatesToRender.api, configuration)),
398
- ]).join("\n"),
399
- ),
400
- ];
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
+ );
401
482
  };
402
483
 
403
- createOutputFileInfo = (configuration, fileName, content) => {
404
- 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;
405
494
 
406
495
  if (configuration.translateToJavaScript) {
407
- const { sourceContent, declarationContent } = translateToJS(`${fixedFileName}${ts.Extension.Ts}`, content);
408
-
409
- this.logger.debug("generating output for", `${fixedFileName}${ts.Extension.Js}`);
410
- this.logger.debug(sourceContent);
411
-
412
- this.logger.debug("generating output for", `${fixedFileName}${ts.Extension.Js}`);
413
- 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
+ }
414
503
 
415
- return {
416
- name: `${fixedFileName}${ts.Extension.Js}`,
417
- content: this.codeFormatter.formatCode(sourceContent),
418
- declaration: {
419
- name: `${fixedFileName}${ts.Extension.Dts}`,
420
- content: this.codeFormatter.formatCode(declarationContent),
421
- },
422
- };
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
+ });
423
511
  }
424
512
 
425
- this.logger.debug("generating output for", `${fixedFileName}${ts.Extension.Js}`);
426
- this.logger.debug(content);
513
+ this.logger.debug('generating output for', `${fileName}${fileExtension}`);
427
514
 
428
- return {
429
- name: `${fixedFileName}${ts.Extension.Ts}`,
430
- content: this.codeFormatter.formatCode(content),
431
- declaration: null,
432
- };
515
+ return [
516
+ {
517
+ fileName,
518
+ fileExtension: fileExtension,
519
+ fileContent: await this.codeFormatter.formatCode(content),
520
+ },
521
+ ];
433
522
  };
434
523
 
435
524
  createApiConfig = (swaggerSchema) => {
436
525
  const { info, servers, host, basePath, externalDocs, tags } = swaggerSchema;
437
- const server = (servers && servers[0]) || { url: "" };
438
- const { title = "No title", version, description: schemaDescription = "" } = info || {};
526
+ const server = (servers && servers[0]) || { url: '' };
527
+ const { title = 'No title', version } = info || {};
439
528
  const { url: serverUrl } = server;
440
529
 
441
530
  return {
@@ -445,8 +534,8 @@ class CodeGenProcess {
445
534
  host,
446
535
  externalDocs: _.merge(
447
536
  {
448
- url: "",
449
- description: "",
537
+ url: '',
538
+ description: '',
450
539
  },
451
540
  externalDocs,
452
541
  ),
@@ -456,6 +545,15 @@ class CodeGenProcess {
456
545
  version,
457
546
  };
458
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
+ };
459
557
  }
460
558
 
461
559
  module.exports = {