swagger-typescript-api 12.0.1 → 13.0.0-experimental-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.
package/README.md CHANGED
@@ -399,16 +399,15 @@ generateApi({
399
399
  ### `primitiveTypeConstructs`
400
400
 
401
401
  It is type mapper or translator swagger schema objects. `primitiveTypeConstructs` translates `type`/`format` schema fields to typescript structs.
402
- This option has type
402
+ This option has type
403
+
403
404
  ```ts
404
405
  type PrimitiveTypeStructValue =
405
- | string
406
- | ((schema: Record<string, any>, parser: import("./src/schema-parser/schema-parser").SchemaParser) => string);
406
+ | string
407
+ | ((schema: Record<string, any>, parser: import("./schema-parser-engine").SchemaProcessor) => string);
407
408
 
408
- type PrimitiveTypeStruct = Record<
409
- "integer" | "number" | "boolean" | "object" | "file" | "string" | "array",
410
- string | ({ $default: PrimitiveTypeStructValue } & Record<string, PrimitiveTypeStructValue>)
411
- >
409
+ type PrimitiveTypeStruct = Record<"integer" | "number" | "boolean" | "object" | "file" | "string" | "array",
410
+ string | ({ $default: PrimitiveTypeStructValue } & Record<string, PrimitiveTypeStructValue>)>
412
411
 
413
412
  declare const primitiveTypeConstructs: (struct: PrimitiveTypeStruct) => Partial<PrimitiveTypeStruct>
414
413
 
@@ -443,8 +442,8 @@ generateApi({
443
442
  "relative-json-pointer": () => "string",
444
443
  regex: () => "string",
445
444
  },
446
- array: (schema, parser) => {
447
- const content = parser.getInlineParseContent(schema.items);
445
+ array: async (schema, parser) => {
446
+ const content = await parser.getInlineParseContent(schema.items);
448
447
  return parser.safeAddNullToType(schema, `(${content})[]`);
449
448
  },
450
449
  })
package/index.d.ts CHANGED
@@ -201,7 +201,7 @@ type CodeGenConstruct = {
201
201
 
202
202
  type PrimitiveTypeStructValue =
203
203
  | string
204
- | ((schema: Record<string, any>, parser: import("./src/schema-parser/schema-parser").SchemaParser) => string);
204
+ | ((schema: Record<string, any>, parser: import("./src/schema-parser/schema-processor").SchemaProcessor) => string);
205
205
 
206
206
  type PrimitiveTypeStruct = Record<
207
207
  "integer" | "number" | "boolean" | "object" | "file" | "string" | "array",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "swagger-typescript-api",
3
- "version": "12.0.1",
3
+ "version": "13.0.0-experimental-1",
4
4
  "description": "Generate typescript/javascript api from swagger schema",
5
5
  "scripts": {
6
6
  "cli:json": "node index.js -r -d -p ./swagger-test-cli.json -n swagger-test-cli.ts",
@@ -2,9 +2,9 @@ const { SwaggerSchemaResolver } = require("./swagger-schema-resolver.js");
2
2
  const { SchemaComponentsMap } = require("./schema-components-map.js");
3
3
  const { NameResolver } = require("./util/name-resolver");
4
4
  const { Logger } = require("./util/logger.js");
5
- const { TypeName } = require("./type-name.js");
5
+ const { TypeNameFormatter } = require("./type-name-formatter.js");
6
6
  const _ = require("lodash");
7
- const { SchemaParser } = require("./schema-parser/schema-parser.js");
7
+ const { SchemaProcessor } = require("./schema-parser/schema-processor.js");
8
8
  const { SchemaRoutes } = require("./schema-parser/schema-routes.js");
9
9
  const { CodeGenConfig } = require("./configuration.js");
10
10
  const { FileSystem } = require("./util/file-system");
@@ -33,11 +33,11 @@ class CodeGenProcess {
33
33
  */
34
34
  logger;
35
35
  /**
36
- * @type {TypeName}
36
+ * @type {TypeNameFormatter}
37
37
  */
38
38
  typeName;
39
39
  /**
40
- * @type {SchemaParser}
40
+ * @type {SchemaProcessor}
41
41
  */
42
42
  schemaParser;
43
43
  /**
@@ -63,10 +63,10 @@ class CodeGenProcess {
63
63
  this.fileSystem = new FileSystem();
64
64
  this.swaggerSchemaResolver = new SwaggerSchemaResolver(this.config, this.logger, this.fileSystem);
65
65
  this.schemaComponentMap = new SchemaComponentsMap(this.config);
66
- this.typeName = new TypeName(this.config, this.logger);
66
+ this.typeName = new TypeNameFormatter(this.config, this.logger);
67
67
  this.templates = new Templates(this.config, this.logger, this.fileSystem, this.getRenderTemplateData);
68
68
  this.codeFormatter = new CodeFormatter(this.config);
69
- this.schemaParser = new SchemaParser(
69
+ this.schemaParser = new SchemaProcessor(
70
70
  this.config,
71
71
  this.logger,
72
72
  this.templates,
@@ -85,6 +85,7 @@ class CodeGenProcess {
85
85
  }
86
86
 
87
87
  async start() {
88
+ await this.schemaRoutes.init();
88
89
  this.config.update({ templatePaths: this.templates.getTemplatePaths(this.config) });
89
90
  this.config.update({ templatesToRender: this.templates.getTemplates(this.config) });
90
91
 
@@ -107,11 +108,13 @@ class CodeGenProcess {
107
108
 
108
109
  this.config.componentTypeNameResolver.reserve(componentSchemaNames);
109
110
 
110
- const parsedSchemas = _.map(_.get(swagger.usageSchema.components, "schemas"), (schema, typeName) =>
111
- this.schemaParser.parseSchema(schema, typeName),
111
+ const parsedSchemas = await Promise.all(
112
+ _.map(_.get(swagger.usageSchema.components, "schemas"), (schema, typeName) =>
113
+ this.schemaParser.parseSchema(schema, typeName),
114
+ ),
112
115
  );
113
116
 
114
- this.schemaRoutes.attachSchema({
117
+ await this.schemaRoutes.attachSchema({
115
118
  usageSchema: swagger.usageSchema,
116
119
  parsedSchemas,
117
120
  });
@@ -150,10 +153,14 @@ class CodeGenProcess {
150
153
  return schemas;
151
154
  };
152
155
 
156
+ const modelTypes = (await Promise.all(_.map(sortSchemas(usageComponentSchemas), this.prepareModelType))).filter(
157
+ Boolean,
158
+ );
159
+
153
160
  const rawConfiguration = {
154
161
  apiConfig: this.createApiConfig(swagger.usageSchema),
155
162
  config: this.config,
156
- modelTypes: _.map(sortSchemas(usageComponentSchemas), this.prepareModelType).filter(Boolean),
163
+ modelTypes: modelTypes,
157
164
  rawModelTypes: usageComponentSchemas,
158
165
  hasSecurityRoutes: this.schemaRoutes.hasSecurityRoutes,
159
166
  hasQueryRoutes: this.schemaRoutes.hasQueryRoutes,
@@ -178,7 +185,7 @@ class CodeGenProcess {
178
185
  this.fileSystem.createDir(this.config.output);
179
186
  }
180
187
 
181
- const files = this.generateOutputFiles({
188
+ const files = await this.generateOutputFiles({
182
189
  configuration: configuration,
183
190
  });
184
191
 
@@ -218,7 +225,7 @@ class CodeGenProcess {
218
225
  files: generatedFiles,
219
226
  configuration,
220
227
  getTemplate: this.templates.getTemplate,
221
- renderTemplate: this.templates.renderTemplate,
228
+ renderTemplate: await this.templates.renderTemplate,
222
229
  createFile: this.fileSystem.createFile,
223
230
  formatTSContent: this.codeFormatter.formatCode,
224
231
  };
@@ -253,14 +260,15 @@ class CodeGenProcess {
253
260
  };
254
261
  };
255
262
 
256
- prepareModelType = (typeInfo) => {
263
+ prepareModelType = async (typeInfo) => {
257
264
  if (!typeInfo.typeData) {
258
- typeInfo.typeData = this.schemaParser.parseSchema(typeInfo.rawTypeData, typeInfo.typeName);
265
+ typeInfo.typeData = await this.schemaParser.parseSchema(typeInfo.rawTypeData, typeInfo.typeName);
259
266
  }
260
- const rawTypeData = typeInfo.typeData;
261
- const typeData = this.schemaParser.schemaFormatters.base[rawTypeData.type]
262
- ? this.schemaParser.schemaFormatters.base[rawTypeData.type](rawTypeData)
263
- : rawTypeData;
267
+ const typeData = await this.schemaParser.schemaFormatters.formatSchema(typeInfo.typeData, {
268
+ formatType: "base",
269
+ schemaType: typeInfo.typeData.type,
270
+ });
271
+
264
272
  let { typeIdentifier, name: originalName, content, description } = typeData;
265
273
  const name = this.typeName.format(originalName);
266
274
 
@@ -271,43 +279,48 @@ class CodeGenProcess {
271
279
  typeIdentifier,
272
280
  name,
273
281
  description,
274
- $content: rawTypeData.content,
275
- rawContent: rawTypeData.content,
282
+ $content: typeInfo.typeData.content,
283
+ rawContent: typeInfo.typeData.content,
276
284
  content: content,
277
285
  typeData,
278
286
  };
279
287
  };
280
288
 
281
- generateOutputFiles = ({ configuration }) => {
289
+ generateOutputFiles = async ({ configuration }) => {
282
290
  const { modular, templatesToRender } = this.config;
283
291
 
284
292
  const output = modular
285
- ? this.createMultipleFileInfos(templatesToRender, configuration)
286
- : this.createSingleFileInfo(templatesToRender, configuration);
293
+ ? await this.createMultipleFileInfos(templatesToRender, configuration)
294
+ : await this.createSingleFileInfo(templatesToRender, configuration);
287
295
 
288
296
  if (!_.isEmpty(configuration.extraTemplates)) {
289
297
  output.push(
290
- ..._.map(configuration.extraTemplates, (extraTemplate) => {
291
- return this.createOutputFileInfo(
292
- configuration,
293
- extraTemplate.name,
294
- this.templates.renderTemplate(this.fileSystem.getFileContent(extraTemplate.path), configuration),
295
- );
296
- }),
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
+ )),
297
310
  );
298
311
  }
299
312
 
300
313
  return output.filter((fileInfo) => !!fileInfo && !!fileInfo.content);
301
314
  };
302
315
 
303
- createMultipleFileInfos = (templatesToRender, configuration) => {
316
+ createMultipleFileInfos = async (templatesToRender, configuration) => {
304
317
  const { routes } = configuration;
305
318
  const { fileNames, generateRouteTypes, generateClient } = configuration.config;
306
319
  const modularApiFileInfos = [];
307
320
 
308
321
  if (routes.$outOfModule) {
309
322
  if (generateRouteTypes) {
310
- const outOfModuleRouteContent = this.templates.renderTemplate(templatesToRender.routeTypes, {
323
+ const outOfModuleRouteContent = await this.templates.renderTemplate(templatesToRender.routeTypes, {
311
324
  ...configuration,
312
325
  route: configuration.routes.$outOfModule,
313
326
  });
@@ -317,7 +330,7 @@ class CodeGenProcess {
317
330
  );
318
331
  }
319
332
  if (generateClient) {
320
- const outOfModuleApiContent = this.templates.renderTemplate(templatesToRender.api, {
333
+ const outOfModuleApiContent = await this.templates.renderTemplate(templatesToRender.api, {
321
334
  ...configuration,
322
335
  route: configuration.routes.$outOfModule,
323
336
  });
@@ -329,56 +342,48 @@ class CodeGenProcess {
329
342
  }
330
343
 
331
344
  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
- );
345
+ for await (const route of routes.combined) {
346
+ if (generateRouteTypes) {
347
+ const routeModuleContent = await this.templates.renderTemplate(templatesToRender.routeTypes, {
348
+ ...configuration,
349
+ route,
350
+ });
351
+
352
+ modularApiFileInfos.push(
353
+ this.createOutputFileInfo(configuration, pascalCase(`${route.moduleName}_Route`), routeModuleContent),
354
+ );
355
+ }
356
+
357
+ if (generateClient) {
358
+ const apiModuleContent = await this.templates.renderTemplate(templatesToRender.api, {
359
+ ...configuration,
360
+ route,
361
+ });
362
+
363
+ modularApiFileInfos.push(
364
+ this.createOutputFileInfo(configuration, pascalCase(route.moduleName), apiModuleContent),
365
+ );
366
+ }
367
+ }
363
368
  }
364
369
 
365
370
  return [
366
371
  this.createOutputFileInfo(
367
372
  configuration,
368
373
  fileNames.dataContracts,
369
- this.templates.renderTemplate(templatesToRender.dataContracts, configuration),
374
+ await this.templates.renderTemplate(templatesToRender.dataContracts, configuration),
370
375
  ),
371
376
  generateClient &&
372
377
  this.createOutputFileInfo(
373
378
  configuration,
374
379
  fileNames.httpClient,
375
- this.templates.renderTemplate(templatesToRender.httpClient, configuration),
380
+ await this.templates.renderTemplate(templatesToRender.httpClient, configuration),
376
381
  ),
377
382
  ...modularApiFileInfos,
378
383
  ];
379
384
  };
380
385
 
381
- createSingleFileInfo = (templatesToRender, configuration) => {
386
+ createSingleFileInfo = async (templatesToRender, configuration) => {
382
387
  const { generateRouteTypes, generateClient } = configuration.config;
383
388
 
384
389
  return [
@@ -386,10 +391,10 @@ class CodeGenProcess {
386
391
  configuration,
387
392
  configuration.fileName,
388
393
  _.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),
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)),
393
398
  ]).join("\n"),
394
399
  ),
395
400
  ];
@@ -263,7 +263,7 @@ class CodeGenConfig {
263
263
  /**
264
264
  * swagger schema type -> typescript type
265
265
  * https://json-schema.org/understanding-json-schema/reference/string.html#dates-and-times
266
- * @type {Record<string, string | ((schema: any, parser: SchemaParser) => string) | ({ $default: string } & Record<string, string | ((schema: any, parser: SchemaParser) => string)>)>}
266
+ * @type {Record<string, string | ((schema: any, parser: SchemaProcessor) => string) | ({ $default: string } & Record<string, string | ((schema: any, parser: SchemaParser) => string)>)>}
267
267
  */
268
268
  primitiveTypes = {
269
269
  integer: () => this.Ts.Keyword.Number,
@@ -294,10 +294,6 @@ class CodeGenConfig {
294
294
  "relative-json-pointer": () => this.Ts.Keyword.String,
295
295
  regex: () => this.Ts.Keyword.String,
296
296
  },
297
- array: ({ items, ...schemaPart }, parser) => {
298
- const content = parser.getInlineParseContent(items);
299
- return parser.schemaUtils.safeAddNullToType(schemaPart, this.Ts.ArrayType(content));
300
- },
301
297
  };
302
298
 
303
299
  templateInfos = [
@@ -11,7 +11,7 @@ class SchemaFormatters {
11
11
  */
12
12
  logger;
13
13
  /**
14
- * @type {SchemaParser}
14
+ * @type {SchemaProcessor}
15
15
  */
16
16
  schemaParser;
17
17
  /**
@@ -42,12 +42,12 @@ class SchemaFormatters {
42
42
  content: this.config.Ts.EnumFieldsWrapper(parsedSchema.content),
43
43
  };
44
44
  },
45
- [SCHEMA_TYPES.OBJECT]: (parsedSchema) => {
45
+ [SCHEMA_TYPES.OBJECT]: async (parsedSchema) => {
46
46
  if (parsedSchema.nullable) return this.inline[SCHEMA_TYPES.OBJECT](parsedSchema);
47
47
  return {
48
48
  ...parsedSchema,
49
49
  $content: parsedSchema.content,
50
- content: this.formatObjectContent(parsedSchema.content),
50
+ content: await this.formatObjectContent(parsedSchema.content),
51
51
  };
52
52
  },
53
53
  [SCHEMA_TYPES.PRIMITIVE]: (parsedSchema) => {
@@ -71,7 +71,7 @@ class SchemaFormatters {
71
71
  ),
72
72
  };
73
73
  },
74
- [SCHEMA_TYPES.OBJECT]: (parsedSchema) => {
74
+ [SCHEMA_TYPES.OBJECT]: async (parsedSchema) => {
75
75
  if (_.isString(parsedSchema.content)) {
76
76
  return {
77
77
  ...parsedSchema,
@@ -86,7 +86,7 @@ class SchemaFormatters {
86
86
  content: this.schemaParser.schemaUtils.safeAddNullToType(
87
87
  parsedSchema,
88
88
  parsedSchema.content.length
89
- ? this.config.Ts.ObjectWrapper(this.formatObjectContent(parsedSchema.content))
89
+ ? this.config.Ts.ObjectWrapper(await this.formatObjectContent(parsedSchema.content))
90
90
  : this.config.Ts.RecordType(Ts.Keyword.String, this.config.Ts.Keyword.Any),
91
91
  ),
92
92
  };
@@ -95,12 +95,13 @@ class SchemaFormatters {
95
95
 
96
96
  /**
97
97
  * @param parsedSchema {Record<string, any>}
98
- * @param formatType {"base" | "inline"}
98
+ * @param cfg {{ formatType?: "base" | "inline", schemaType?: string } }
99
99
  */
100
- formatSchema = (parsedSchema, formatType = "base") => {
101
- const schemaType = _.get(parsedSchema, ["schemaType"]) || _.get(parsedSchema, ["$parsed", "schemaType"]);
100
+ formatSchema = async (parsedSchema, { schemaType: outerSchemaType, formatType = "base" } = {}) => {
101
+ const schemaType =
102
+ outerSchemaType || _.get(parsedSchema, ["schemaType"]) || _.get(parsedSchema, ["$parsed", "schemaType"]);
102
103
  const formatterFn = _.get(this, [formatType, schemaType]);
103
- return (formatterFn && formatterFn(parsedSchema)) || parsedSchema;
104
+ return (formatterFn && (await formatterFn(parsedSchema))) || parsedSchema;
104
105
  };
105
106
 
106
107
  formatDescription = (description, inline) => {
@@ -126,24 +127,28 @@ class SchemaFormatters {
126
127
  return _.replace(prettified, /\n$/g, "");
127
128
  };
128
129
 
129
- formatObjectContent = (content) => {
130
- return _.map(content, (part) => {
131
- const extraSpace = " ";
132
- const result = `${extraSpace}${part.field},\n`;
130
+ formatObjectContent = async (content) => {
131
+ return (
132
+ await Promise.all(
133
+ _.map(content, async (part) => {
134
+ const extraSpace = " ";
135
+ const result = `${extraSpace}${part.field},\n`;
133
136
 
134
- const renderedJsDoc = this.templates.renderTemplate(this.config.templatesToRender.dataContractJsDoc, {
135
- data: part,
136
- });
137
+ const renderedJsDoc = await this.templates.renderTemplate(this.config.templatesToRender.dataContractJsDoc, {
138
+ data: part,
139
+ });
137
140
 
138
- const routeNameFromTemplate = renderedJsDoc
139
- .split("\n")
140
- .map((c) => `${extraSpace}${c}`)
141
- .join("\n");
141
+ const routeNameFromTemplate = renderedJsDoc
142
+ .split("\n")
143
+ .map((c) => `${extraSpace}${c}`)
144
+ .join("\n");
142
145
 
143
- if (routeNameFromTemplate) return `${routeNameFromTemplate}${result}`;
146
+ if (routeNameFromTemplate) return `${routeNameFromTemplate}${result}`;
144
147
 
145
- return `${result}`;
146
- }).join("");
148
+ return `${result}`;
149
+ }),
150
+ )
151
+ ).join("");
147
152
  };
148
153
  }
149
154