swagger-typescript-api 13.0.17 → 13.0.18

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.
@@ -0,0 +1,1832 @@
1
+ import * as eta from 'eta';
2
+ import * as lodash from 'lodash';
3
+ import * as swagger_schema_official from 'swagger-schema-official';
4
+
5
+ declare class NameResolver {
6
+ reservedNames = [];
7
+ getFallbackName = null;
8
+
9
+ /** @type {CodeGenConfig} */
10
+ config;
11
+ /** @type {Logger} */
12
+ logger;
13
+
14
+ /**
15
+ * @param {CodeGenConfig} config;
16
+ * @param {Logger} logger;
17
+ * @param {string[]} reservedNames
18
+ */
19
+ constructor(config, logger, reservedNames, getFallbackName) {
20
+ this.config = config;
21
+ this.logger = logger;
22
+ this.getFallbackName = getFallbackName;
23
+ this.reserve(reservedNames);
24
+ }
25
+
26
+ /**
27
+ * @param {string[]} names
28
+ */
29
+ reserve(names) {
30
+ const fixedNames = lodash.uniq(lodash.compact(names));
31
+ for (const name of fixedNames) {
32
+ if (this.reservedNames.indexOf(name) === -1) {
33
+ this.reservedNames.push(name);
34
+ }
35
+ }
36
+ }
37
+
38
+ unreserve(names) {
39
+ this.reservedNames.filter(
40
+ (reservedName) => !names.some((name) => name === reservedName),
41
+ );
42
+ }
43
+
44
+ isReserved(name) {
45
+ return this.reservedNames.some((reservedName) => reservedName === name);
46
+ }
47
+
48
+ /**
49
+ *
50
+ * @param {(string[])} variants
51
+ * @param {(reserved: string[]) => string)} [resolver]
52
+ * @param {any} [extras]
53
+ * @returns {string | null}
54
+ */
55
+ resolve(variants, resolver, extras, shouldReserve = true) {
56
+ if (typeof resolver === "function") {
57
+ let usageName = null;
58
+ while (usageName === null) {
59
+ const variant = resolver(variants, extras);
60
+
61
+ if (variant === undefined) {
62
+ this.logger.warn(
63
+ "unable to resolve name. current reserved names: ",
64
+ this.reservedNames,
65
+ );
66
+ return null;
67
+ }
68
+ if (!shouldReserve || !this.isReserved(variant)) {
69
+ usageName = variant;
70
+ }
71
+ }
72
+
73
+ shouldReserve && this.reserve([usageName]);
74
+ return usageName;
75
+ }
76
+
77
+ if (Array.isArray(variants)) {
78
+ let usageName = null;
79
+ const uniqVariants = lodash.uniq(lodash.compact(variants));
80
+
81
+ for (const variant of uniqVariants) {
82
+ if (!usageName && (!shouldReserve || !this.isReserved(variant))) {
83
+ usageName = variant;
84
+ }
85
+ }
86
+
87
+ if (usageName) {
88
+ shouldReserve && this.reserve([usageName]);
89
+ return usageName;
90
+ }
91
+
92
+ this.logger.debug(
93
+ "trying to resolve name with using fallback name generator using variants",
94
+ variants,
95
+ );
96
+ return this.resolve(variants, this.getFallbackName, extras);
97
+ }
98
+
99
+ this.logger.debug(
100
+ "problem with reserving names. current reserved names: ",
101
+ this.reservedNames,
102
+ );
103
+ return null;
104
+ }
105
+ }
106
+
107
+ declare class ComponentTypeNameResolver extends NameResolver {
108
+ counter = 1;
109
+ fallbackNameCounter = 1;
110
+ countersByVariant = new Map();
111
+
112
+ /**
113
+ * @param {CodeGenConfig} config;
114
+ * @param {Logger} logger;
115
+ * @param {string[]} reservedNames
116
+ */
117
+ constructor(config, logger, reservedNames) {
118
+ super(config, logger, reservedNames, (variants) => {
119
+ const randomVariant = variants[getRandomInt(0, variants.length - 1)];
120
+ if (randomVariant) {
121
+ if (!this.countersByVariant.has(randomVariant)) {
122
+ this.countersByVariant.set(randomVariant, 0);
123
+ }
124
+ const variantCounter = this.countersByVariant.get(randomVariant) + 1;
125
+ this.countersByVariant.set(randomVariant, variantCounter);
126
+ const dirtyResolvedName = `${randomVariant}${variantCounter}`;
127
+ this.logger.debug(
128
+ "generated dirty resolved type name for component - ",
129
+ dirtyResolvedName,
130
+ );
131
+ return dirtyResolvedName;
132
+ }
133
+
134
+ const fallbackName = `${this.config.componentTypeNameResolver}${this
135
+ .fallbackNameCounter++}`;
136
+ this.logger.debug(
137
+ "generated fallback type name for component - ",
138
+ fallbackName,
139
+ );
140
+ return fallbackName;
141
+ });
142
+ }
143
+ }
144
+
145
+ declare class MonoSchemaParser {
146
+ schema;
147
+ typeName;
148
+ schemaPath;
149
+
150
+ /** @type {Logger} */
151
+ logger;
152
+ /** @type {SchemaParser} */
153
+ schemaParser;
154
+ /** @type {SchemaParserFabric} */
155
+ schemaParserFabric;
156
+ /** @type {TypeNameFormatter} */
157
+ typeNameFormatter;
158
+ /** @type {SchemaComponentsMap} */
159
+ schemaComponentsMap;
160
+ /** @type {SchemaUtils} */
161
+ schemaUtils;
162
+ /** @type {CodeGenConfig} */
163
+ config;
164
+ /** @type {SchemaFormatters} */
165
+ schemaFormatters;
166
+
167
+ constructor(schemaParser, schema, typeName = null, schemaPath = []) {
168
+ this.schemaParser = schemaParser;
169
+ this.schemaParserFabric = schemaParser.schemaParserFabric;
170
+ this.logger = schemaParser.logger;
171
+ this.schema = schema;
172
+ this.typeName = typeName;
173
+ this.typeNameFormatter = schemaParser.typeNameFormatter;
174
+ this.schemaPath = schemaPath;
175
+ this.schemaComponentsMap = this.schemaParser.schemaComponentsMap;
176
+ this.schemaUtils = this.schemaParser.schemaUtils;
177
+ this.config = this.schemaParser.config;
178
+ this.schemaFormatters = this.schemaParser.schemaFormatters;
179
+ }
180
+
181
+ parse() {
182
+ throw new Error("not implemented");
183
+ }
184
+
185
+ buildTypeNameFromPath = () => {
186
+ return this.schemaUtils.buildTypeNameFromPath(this.schemaPath);
187
+ };
188
+ }
189
+
190
+ declare class SchemaParser {
191
+ /** @type {SchemaParserFabric} */
192
+ schemaParserFabric;
193
+ /** @type {CodeGenConfig} */
194
+ config;
195
+ /** @type {Logger} */
196
+ logger;
197
+ /** @type {SchemaComponentsMap} */
198
+ schemaComponentsMap;
199
+ /** @type {TypeNameFormatter} */
200
+ typeNameFormatter;
201
+ /** @type {SchemaFormatters} */
202
+ schemaFormatters;
203
+ /** @type {SchemaUtils} */
204
+ schemaUtils;
205
+ /** @type {TemplatesWorker} */
206
+ templatesWorker;
207
+ /** @type {SchemaWalker} */
208
+ schemaWalker;
209
+
210
+ typeName;
211
+ schema;
212
+ schemaPath = [];
213
+
214
+ constructor(schemaParserFabric, { typeName, schema, schemaPath } = {}) {
215
+ this.schemaParserFabric = schemaParserFabric;
216
+ this.config = schemaParserFabric.config;
217
+ this.logger = schemaParserFabric.logger;
218
+ this.templatesWorker = schemaParserFabric.templatesWorker;
219
+ this.schemaComponentsMap = schemaParserFabric.schemaComponentsMap;
220
+ this.typeNameFormatter = schemaParserFabric.typeNameFormatter;
221
+ this.schemaWalker = schemaParserFabric.schemaWalker;
222
+ this.schemaFormatters = schemaParserFabric.schemaFormatters;
223
+ this.schemaUtils = schemaParserFabric.schemaUtils;
224
+
225
+ this.typeName = typeName || null;
226
+ this.schema = schema;
227
+ this.schemaPath = [...(schemaPath || [])];
228
+ }
229
+
230
+ _complexSchemaParsers = {
231
+ [SCHEMA_TYPES.COMPLEX_ONE_OF]: (schema) => {
232
+ const SchemaParser =
233
+ this.config.schemaParsers.complexOneOf || OneOfSchemaParser;
234
+ const schemaParser = new SchemaParser(
235
+ this,
236
+ schema,
237
+ null,
238
+ this.schemaPath,
239
+ );
240
+ return schemaParser.parse();
241
+ },
242
+ [SCHEMA_TYPES.COMPLEX_ALL_OF]: (schema) => {
243
+ const SchemaParser =
244
+ this.config.schemaParsers.complexAllOf || AllOfSchemaParser;
245
+ const schemaParser = new SchemaParser(
246
+ this,
247
+ schema,
248
+ null,
249
+ this.schemaPath,
250
+ );
251
+ return schemaParser.parse();
252
+ },
253
+ [SCHEMA_TYPES.COMPLEX_ANY_OF]: (schema) => {
254
+ const SchemaParser =
255
+ this.config.schemaParsers.complexAnyOf || AnyOfSchemaParser;
256
+ const schemaParser = new SchemaParser(
257
+ this,
258
+ schema,
259
+ null,
260
+ this.schemaPath,
261
+ );
262
+ return schemaParser.parse();
263
+ },
264
+ [SCHEMA_TYPES.COMPLEX_NOT]: (schema) => {
265
+ const SchemaParser =
266
+ this.config.schemaParsers.complexNot || NotSchemaParser;
267
+ const schemaParser = new SchemaParser(
268
+ this,
269
+ schema,
270
+ null,
271
+ this.schemaPath,
272
+ );
273
+ return schemaParser.parse();
274
+ },
275
+ };
276
+
277
+ _baseSchemaParsers = {
278
+ [SCHEMA_TYPES.ENUM]: (schema, typeName) => {
279
+ const SchemaParser = this.config.schemaParsers.enum || EnumSchemaParser;
280
+ const schemaParser = new SchemaParser(
281
+ this,
282
+ schema,
283
+ typeName,
284
+ this.schemaPath,
285
+ );
286
+ return schemaParser.parse();
287
+ },
288
+ [SCHEMA_TYPES.OBJECT]: (schema, typeName) => {
289
+ const SchemaParser =
290
+ this.config.schemaParsers.object || ObjectSchemaParser;
291
+ const schemaParser = new SchemaParser(
292
+ this,
293
+ schema,
294
+ typeName,
295
+ this.schemaPath,
296
+ );
297
+ return schemaParser.parse();
298
+ },
299
+ [SCHEMA_TYPES.COMPLEX]: (schema, typeName) => {
300
+ const SchemaParser =
301
+ this.config.schemaParsers.complex || ComplexSchemaParser;
302
+ const schemaParser = new SchemaParser(
303
+ this,
304
+ schema,
305
+ typeName,
306
+ this.schemaPath,
307
+ );
308
+ return schemaParser.parse();
309
+ },
310
+ [SCHEMA_TYPES.PRIMITIVE]: (schema, typeName) => {
311
+ const SchemaParser =
312
+ this.config.schemaParsers.primitive || PrimitiveSchemaParser;
313
+ const schemaParser = new SchemaParser(
314
+ this,
315
+ schema,
316
+ typeName,
317
+ this.schemaPath,
318
+ );
319
+ return schemaParser.parse();
320
+ },
321
+ [SCHEMA_TYPES.DISCRIMINATOR]: (schema, typeName) => {
322
+ const SchemaParser =
323
+ this.config.schemaParsers.discriminator || DiscriminatorSchemaParser;
324
+ const schemaParser = new SchemaParser(
325
+ this,
326
+ schema,
327
+ typeName,
328
+ this.schemaPath,
329
+ );
330
+ return schemaParser.parse();
331
+ },
332
+ [SCHEMA_TYPES.ARRAY]: (schema, typeName) => {
333
+ const SchemaParser = this.config.schemaParsers.array || ArraySchemaParser;
334
+ const schemaParser = new SchemaParser(
335
+ this,
336
+ schema,
337
+ typeName,
338
+ this.schemaPath,
339
+ );
340
+ return schemaParser.parse();
341
+ },
342
+ };
343
+
344
+ /**
345
+ * @return {Record<string, any>}
346
+ */
347
+ parseSchema = () => {
348
+ if (!this.schema)
349
+ return this._baseSchemaParsers[SCHEMA_TYPES.PRIMITIVE](
350
+ null,
351
+ this.typeName,
352
+ );
353
+
354
+ let schemaType = null;
355
+ let parsedSchema = null;
356
+
357
+ if (typeof this.schema === "string") {
358
+ return this.schema;
359
+ }
360
+
361
+ if (!this.schema.$parsed) {
362
+ if (!this.typeName && this.schemaUtils.isRefSchema(this.schema)) {
363
+ this.typeName = this.schemaUtils.getSchemaType(this.schema);
364
+ }
365
+
366
+ //#region swagger schemas fixes
367
+
368
+ // schema has items but don't have array type
369
+ if (
370
+ this.schema.items &&
371
+ !Array.isArray(this.schema.items) &&
372
+ !this.schema.type
373
+ ) {
374
+ this.schema.type = SCHEMA_TYPES.ARRAY;
375
+ }
376
+ // schema is enum with one null value
377
+ if (
378
+ Array.isArray(this.schema.enum) &&
379
+ this.schema.enum.length === 1 &&
380
+ this.schema.enum[0] == null
381
+ ) {
382
+ this.logger.debug("invalid enum schema", this.schema);
383
+ this.schema = { type: this.config.Ts.Keyword.Null };
384
+ }
385
+ // schema is response schema
386
+ if ("content" in this.schema && typeof this.schema.content === "object") {
387
+ const schema = this.extractSchemaFromResponseStruct(this.schema);
388
+ const schemaParser = this.schemaParserFabric.createSchemaParser({
389
+ schema,
390
+ typeName: this.typeName,
391
+ schemaPath: this.schemaPath,
392
+ });
393
+ this.schema.$parsed = schemaParser.parseSchema();
394
+ return this.schema.$parsed;
395
+ }
396
+
397
+ //#endregion
398
+
399
+ schemaType = this.schemaUtils.getInternalSchemaType(this.schema);
400
+
401
+ this.schemaPath.push(this.typeName);
402
+
403
+ lodash.merge(
404
+ this.schema,
405
+ this.config.hooks.onPreParseSchema(
406
+ this.schema,
407
+ this.typeName,
408
+ schemaType,
409
+ ),
410
+ );
411
+ parsedSchema = this._baseSchemaParsers[schemaType](
412
+ this.schema,
413
+ this.typeName,
414
+ );
415
+ this.schema.$parsed =
416
+ this.config.hooks.onParseSchema(this.schema, parsedSchema) ||
417
+ parsedSchema;
418
+
419
+ if (
420
+ this.config.sortTypes &&
421
+ Array.isArray(this.schema.$parsed?.content)
422
+ ) {
423
+ this.schema.$parsed.content = this.schema.$parsed.content.sort(
424
+ sortByProperty("name"),
425
+ );
426
+ }
427
+ }
428
+
429
+ this.schemaPath.pop();
430
+
431
+ return this.schema.$parsed;
432
+ };
433
+
434
+ getInlineParseContent = () => {
435
+ const parsedSchema = this.parseSchema();
436
+ const formattedSchema = this.schemaFormatters.formatSchema(
437
+ parsedSchema,
438
+ "inline",
439
+ );
440
+ return formattedSchema.content;
441
+ };
442
+
443
+ getParseContent = () => {
444
+ const parsedSchema = this.parseSchema();
445
+ const formattedSchema = this.schemaFormatters.formatSchema(
446
+ parsedSchema,
447
+ "base",
448
+ );
449
+ return formattedSchema.content;
450
+ };
451
+
452
+ extractSchemaFromResponseStruct = (responseStruct) => {
453
+ const { content, ...extras } = responseStruct;
454
+
455
+ const firstResponse = lodash.first(lodash.values(content));
456
+ const firstSchema = lodash.get(firstResponse, "schema");
457
+
458
+ if (!firstSchema) return;
459
+
460
+ return {
461
+ ...extras,
462
+ ...lodash.omit(firstResponse, "schema"),
463
+ ...firstSchema,
464
+ };
465
+ };
466
+ }
467
+
468
+ /**
469
+ * @typedef {{ fileName: string, fileExtension: string, fileContent: string }} TranslatorIO
470
+ */
471
+
472
+ declare class Translator {
473
+ /** @type {Logger} */
474
+ logger;
475
+ /** @type {CodeGenConfig} */
476
+ config;
477
+ /** @type {CodeFormatter} */
478
+ codeFormatter;
479
+
480
+ /**
481
+ * @param codeGenProcess
482
+ */
483
+ constructor(codeGenProcess) {
484
+ this.logger = codeGenProcess.logger;
485
+ this.config = codeGenProcess.config;
486
+ this.codeFormatter = codeGenProcess.codeFormatter;
487
+ }
488
+
489
+ /**
490
+ *
491
+ * @param input {TranslatorIO}
492
+ * @return {Promise<TranslatorIO[]>}
493
+ */
494
+ // eslint-disable-next-line no-unused-vars
495
+ translate(input) {
496
+ throw new Error("not implemented");
497
+ }
498
+ }
499
+
500
+ declare class CodeGenProcess {
501
+ /** @type {CodeGenConfig} */
502
+ config;
503
+ /** @type {SwaggerSchemaResolver} */
504
+ swaggerSchemaResolver;
505
+ /** @type {SchemaComponentsMap} */
506
+ schemaComponentsMap;
507
+ /** @type {Logger} */
508
+ logger;
509
+ /** @type {TypeNameFormatter} */
510
+ typeNameFormatter;
511
+ /** @type {SchemaParserFabric} */
512
+ schemaParserFabric;
513
+ /** @type {SchemaRoutes} */
514
+ schemaRoutes;
515
+ /** @type {FileSystem} */
516
+ fileSystem;
517
+ /** @type {CodeFormatter} */
518
+ codeFormatter;
519
+ /** type {TemplatesWorker} */
520
+ templatesWorker;
521
+ /** @type {SchemaWalker} */
522
+ schemaWalker;
523
+ /** @type {JavascriptTranslator} */
524
+ javascriptTranslator;
525
+
526
+ /**
527
+ *
528
+ * @param config {Partial<import("../index.d.ts").GenerateApiConfiguration['config']>}
529
+ */
530
+ constructor(config) {
531
+ this.config = new CodeGenConfig(config);
532
+ this.logger = new Logger(this);
533
+ this.fileSystem = new FileSystem(this);
534
+ this.schemaWalker = new SchemaWalker(this);
535
+ this.swaggerSchemaResolver = new SwaggerSchemaResolver(this);
536
+ this.schemaComponentsMap = new SchemaComponentsMap(this);
537
+ this.typeNameFormatter = new TypeNameFormatter(this);
538
+ this.templatesWorker = new TemplatesWorker(this);
539
+ this.codeFormatter = new CodeFormatter(this);
540
+ this.schemaParserFabric = new SchemaParserFabric(this);
541
+ this.schemaRoutes = new SchemaRoutes(this);
542
+ this.javascriptTranslator = new JavascriptTranslator(this);
543
+ this.config.componentTypeNameResolver.logger = this.logger;
544
+ }
545
+
546
+ async start() {
547
+ this.config.update({
548
+ templatePaths: this.templatesWorker.getTemplatePaths(this.config),
549
+ });
550
+ this.config.update({
551
+ templatesToRender: this.templatesWorker.getTemplates(this.config),
552
+ });
553
+
554
+ const swagger = await this.swaggerSchemaResolver.create();
555
+
556
+ this.swaggerSchemaResolver.fixSwaggerSchema(swagger);
557
+
558
+ this.config.update({
559
+ swaggerSchema: swagger.usageSchema,
560
+ originalSchema: swagger.originalSchema,
561
+ });
562
+
563
+ this.schemaWalker.addSchema("$usage", swagger.usageSchema);
564
+ this.schemaWalker.addSchema("$original", swagger.originalSchema);
565
+
566
+ this.logger.event("start generating your typescript api");
567
+
568
+ this.config.update(
569
+ this.config.hooks.onInit(this.config, this) || this.config,
570
+ );
571
+
572
+ this.schemaComponentsMap.clear();
573
+
574
+ lodash.each(swagger.usageSchema.components, (component, componentName) =>
575
+ lodash.each(component, (rawTypeData, typeName) => {
576
+ this.schemaComponentsMap.createComponent(
577
+ this.schemaComponentsMap.createRef([
578
+ "components",
579
+ componentName,
580
+ typeName,
581
+ ]),
582
+ rawTypeData,
583
+ );
584
+ }),
585
+ );
586
+
587
+ /**
588
+ * @type {SchemaComponent[]}
589
+ */
590
+ const componentsToParse = this.schemaComponentsMap.filter(
591
+ lodash.compact(["schemas", this.config.extractResponses && "responses"]),
592
+ );
593
+
594
+ const parsedSchemas = componentsToParse.map((schemaComponent) => {
595
+ const parsed = this.schemaParserFabric.parseSchema(
596
+ schemaComponent.rawTypeData,
597
+ schemaComponent.typeName,
598
+ );
599
+ schemaComponent.typeData = parsed;
600
+ return parsed;
601
+ });
602
+
603
+ this.schemaRoutes.attachSchema({
604
+ usageSchema: swagger.usageSchema,
605
+ parsedSchemas,
606
+ });
607
+
608
+ const rawConfiguration = {
609
+ apiConfig: this.createApiConfig(swagger.usageSchema),
610
+ config: this.config,
611
+ modelTypes: this.collectModelTypes(),
612
+ hasSecurityRoutes: this.schemaRoutes.hasSecurityRoutes,
613
+ hasQueryRoutes: this.schemaRoutes.hasQueryRoutes,
614
+ hasFormDataRoutes: this.schemaRoutes.hasFormDataRoutes,
615
+ generateResponses: this.config.generateResponses,
616
+ routes: this.schemaRoutes.getGroupedRoutes(),
617
+ extraTemplates: this.config.extraTemplates,
618
+ fileName: this.config.fileName,
619
+ translateToJavaScript: this.config.toJS,
620
+ customTranslator: this.config.customTranslator
621
+ ? new this.config.customTranslator(this)
622
+ : null,
623
+ utils: this.getRenderTemplateData().utils,
624
+ };
625
+
626
+ const configuration =
627
+ this.config.hooks.onPrepareConfig(rawConfiguration) || rawConfiguration;
628
+
629
+ if (this.fileSystem.pathIsExist(this.config.output)) {
630
+ if (this.config.cleanOutput) {
631
+ this.logger.debug(`cleaning dir ${this.config.output}`);
632
+ this.fileSystem.cleanDir(this.config.output);
633
+ }
634
+ } else {
635
+ this.logger.debug(
636
+ `path ${this.config.output} is not exist. creating dir by this path`,
637
+ );
638
+ this.fileSystem.createDir(this.config.output);
639
+ }
640
+
641
+ const files = await this.generateOutputFiles({
642
+ configuration: configuration,
643
+ });
644
+
645
+ const isDirPath = this.fileSystem.pathIsDir(this.config.output);
646
+
647
+ if (isDirPath) {
648
+ for (const file of files) {
649
+ this.fileSystem.createFile({
650
+ path: this.config.output,
651
+ fileName: `${file.fileName}${file.fileExtension}`,
652
+ content: file.fileContent,
653
+ withPrefix: true,
654
+ });
655
+
656
+ this.logger.success(
657
+ "api file",
658
+ `"${file.fileName}${file.fileExtension}"`,
659
+ `created in ${this.config.output}`,
660
+ );
661
+ }
662
+ }
663
+
664
+ return {
665
+ files,
666
+ configuration,
667
+ getTemplate: this.templatesWorker.getTemplate,
668
+ renderTemplate: this.templatesWorker.renderTemplate,
669
+ createFile: this.fileSystem.createFile,
670
+ formatTSContent: this.codeFormatter.formatCode,
671
+ };
672
+ }
673
+
674
+ getRenderTemplateData = () => {
675
+ return {
676
+ utils: {
677
+ Ts: this.config.Ts,
678
+ formatDescription:
679
+ this.schemaParserFabric.schemaFormatters.formatDescription,
680
+ internalCase: internalCase,
681
+ classNameCase: pascalCase,
682
+ pascalCase: pascalCase,
683
+ getInlineParseContent: this.schemaParserFabric.getInlineParseContent,
684
+ getParseContent: this.schemaParserFabric.getParseContent,
685
+ getComponentByRef: this.schemaComponentsMap.get,
686
+ parseSchema: this.schemaParserFabric.parseSchema,
687
+ checkAndAddNull: this.schemaParserFabric.schemaUtils.safeAddNullToType,
688
+ safeAddNullToType:
689
+ this.schemaParserFabric.schemaUtils.safeAddNullToType,
690
+ isNeedToAddNull:
691
+ this.schemaParserFabric.schemaUtils.isNullMissingInType,
692
+ inlineExtraFormatters: this.schemaParserFabric.schemaFormatters.inline,
693
+ formatters: this.schemaParserFabric.schemaFormatters.base,
694
+ formatModelName: this.typeNameFormatter.format,
695
+ fmtToJSDocLine: function fmtToJSDocLine(line, { eol = true }) {
696
+ return ` * ${line}${eol ? "\n" : ""}`;
697
+ },
698
+ NameResolver: NameResolver,
699
+ _: lodash,
700
+ require: this.templatesWorker.requireFnFromTemplate,
701
+ },
702
+ config: this.config,
703
+ };
704
+ };
705
+
706
+ collectModelTypes = () => {
707
+ const components = this.schemaComponentsMap.getComponents();
708
+ let modelTypes = [];
709
+
710
+ const modelTypeComponents = lodash.compact([
711
+ "schemas",
712
+ this.config.extractResponses && "responses",
713
+ ]);
714
+
715
+ const getSchemaComponentsCount = () =>
716
+ this.schemaComponentsMap.filter(...modelTypeComponents).length;
717
+
718
+ let schemaComponentsCount = getSchemaComponentsCount();
719
+ let processedCount = 0;
720
+
721
+ while (processedCount < schemaComponentsCount) {
722
+ modelTypes = [];
723
+ processedCount = 0;
724
+ for (const component of components) {
725
+ if (modelTypeComponents.includes(component.componentName)) {
726
+ const modelType = this.prepareModelType(component);
727
+ if (modelType) {
728
+ modelTypes.push(modelType);
729
+ }
730
+ processedCount++;
731
+ }
732
+ }
733
+ schemaComponentsCount = getSchemaComponentsCount();
734
+ }
735
+
736
+ if (this.config.sortTypes) {
737
+ return modelTypes.sort(sortByProperty("name"));
738
+ }
739
+
740
+ return modelTypes;
741
+ };
742
+
743
+ prepareModelType = (typeInfo) => {
744
+ if (typeInfo.$prepared) return typeInfo.$prepared;
745
+
746
+ if (!typeInfo.typeData) {
747
+ typeInfo.typeData = this.schemaParserFabric.parseSchema(
748
+ typeInfo.rawTypeData,
749
+ typeInfo.typeName,
750
+ );
751
+ }
752
+ const rawTypeData = typeInfo.typeData;
753
+ const typeData = this.schemaParserFabric.schemaFormatters.base[
754
+ rawTypeData.type
755
+ ]
756
+ ? this.schemaParserFabric.schemaFormatters.base[rawTypeData.type](
757
+ rawTypeData,
758
+ )
759
+ : rawTypeData;
760
+ const {
761
+ typeIdentifier,
762
+ name: originalName,
763
+ content,
764
+ description,
765
+ } = typeData;
766
+ const name = this.typeNameFormatter.format(originalName);
767
+
768
+ if (name === null) return null;
769
+
770
+ const preparedModelType = {
771
+ ...typeData,
772
+ typeIdentifier,
773
+ name,
774
+ description,
775
+ $content: rawTypeData.content,
776
+ rawContent: rawTypeData.content,
777
+ content: content,
778
+ typeData,
779
+ };
780
+
781
+ typeInfo.$prepared = preparedModelType;
782
+
783
+ return preparedModelType;
784
+ };
785
+
786
+ /**
787
+ *
788
+ * @param configuration
789
+ * @returns {Promise<TranslatorIO[]>}
790
+ */
791
+ generateOutputFiles = async ({ configuration }) => {
792
+ const { modular, templatesToRender } = this.config;
793
+
794
+ const output = modular
795
+ ? await this.createMultipleFileInfos(templatesToRender, configuration)
796
+ : await this.createSingleFileInfo(templatesToRender, configuration);
797
+
798
+ if (!lodash.isEmpty(configuration.extraTemplates)) {
799
+ for (const extraTemplate of configuration.extraTemplates) {
800
+ const content = this.templatesWorker.renderTemplate(
801
+ this.fileSystem.getFileContent(extraTemplate.path),
802
+ configuration,
803
+ );
804
+ output.push(
805
+ ...(await this.createOutputFileInfo(
806
+ configuration,
807
+ extraTemplate.name,
808
+ content,
809
+ )),
810
+ );
811
+ }
812
+ }
813
+
814
+ return output.filter((fileInfo) => !!fileInfo && !!fileInfo.fileContent);
815
+ };
816
+
817
+ /**
818
+ * @param templatesToRender
819
+ * @param configuration
820
+ * @returns {Promise<TranslatorIO[]>}
821
+ */
822
+ createMultipleFileInfos = async (templatesToRender, configuration) => {
823
+ const { routes } = configuration;
824
+ const { fileNames, generateRouteTypes, generateClient } =
825
+ configuration.config;
826
+ /**
827
+ * @type {TranslatorIO[]}
828
+ */
829
+ const modularApiFileInfos = [];
830
+
831
+ if (routes.$outOfModule) {
832
+ if (generateRouteTypes) {
833
+ const outOfModuleRouteContent = this.templatesWorker.renderTemplate(
834
+ templatesToRender.routeTypes,
835
+ {
836
+ ...configuration,
837
+ route: configuration.routes.$outOfModule,
838
+ },
839
+ );
840
+
841
+ modularApiFileInfos.push(
842
+ ...(await this.createOutputFileInfo(
843
+ configuration,
844
+ fileNames.outOfModuleApi,
845
+ outOfModuleRouteContent,
846
+ )),
847
+ );
848
+ }
849
+ if (generateClient) {
850
+ const outOfModuleApiContent = this.templatesWorker.renderTemplate(
851
+ templatesToRender.api,
852
+ {
853
+ ...configuration,
854
+ route: configuration.routes.$outOfModule,
855
+ },
856
+ );
857
+
858
+ modularApiFileInfos.push(
859
+ ...(await this.createOutputFileInfo(
860
+ configuration,
861
+ fileNames.outOfModuleApi,
862
+ outOfModuleApiContent,
863
+ )),
864
+ );
865
+ }
866
+ }
867
+
868
+ if (routes.combined) {
869
+ for (const route of routes.combined) {
870
+ if (generateRouteTypes) {
871
+ const routeModuleContent = this.templatesWorker.renderTemplate(
872
+ templatesToRender.routeTypes,
873
+ {
874
+ ...configuration,
875
+ route,
876
+ },
877
+ );
878
+
879
+ modularApiFileInfos.push(
880
+ ...(await this.createOutputFileInfo(
881
+ configuration,
882
+ pascalCase(`${route.moduleName}_Route`),
883
+ routeModuleContent,
884
+ )),
885
+ );
886
+ }
887
+
888
+ if (generateClient) {
889
+ const apiModuleContent = this.templatesWorker.renderTemplate(
890
+ templatesToRender.api,
891
+ {
892
+ ...configuration,
893
+ route,
894
+ },
895
+ );
896
+
897
+ modularApiFileInfos.push(
898
+ ...(await this.createOutputFileInfo(
899
+ configuration,
900
+ pascalCase(route.moduleName),
901
+ apiModuleContent,
902
+ )),
903
+ );
904
+ }
905
+ }
906
+ }
907
+
908
+ return [
909
+ ...(await this.createOutputFileInfo(
910
+ configuration,
911
+ fileNames.dataContracts,
912
+ this.templatesWorker.renderTemplate(
913
+ templatesToRender.dataContracts,
914
+ configuration,
915
+ ),
916
+ )),
917
+ ...(generateClient
918
+ ? await this.createOutputFileInfo(
919
+ configuration,
920
+ fileNames.httpClient,
921
+ this.templatesWorker.renderTemplate(
922
+ templatesToRender.httpClient,
923
+ configuration,
924
+ ),
925
+ )
926
+ : []),
927
+ ...modularApiFileInfos,
928
+ ];
929
+ };
930
+
931
+ /**
932
+ *
933
+ * @param templatesToRender
934
+ * @param configuration
935
+ * @returns {Promise<TranslatorIO[]>}
936
+ */
937
+ createSingleFileInfo = async (templatesToRender, configuration) => {
938
+ const { generateRouteTypes, generateClient } = configuration.config;
939
+
940
+ return await this.createOutputFileInfo(
941
+ configuration,
942
+ configuration.fileName,
943
+ lodash
944
+ .compact([
945
+ this.templatesWorker.renderTemplate(
946
+ templatesToRender.dataContracts,
947
+ configuration,
948
+ ),
949
+ generateRouteTypes &&
950
+ this.templatesWorker.renderTemplate(
951
+ templatesToRender.routeTypes,
952
+ configuration,
953
+ ),
954
+ generateClient &&
955
+ this.templatesWorker.renderTemplate(
956
+ templatesToRender.httpClient,
957
+ configuration,
958
+ ),
959
+ generateClient &&
960
+ this.templatesWorker.renderTemplate(
961
+ templatesToRender.api,
962
+ configuration,
963
+ ),
964
+ ])
965
+ .join("\n"),
966
+ );
967
+ };
968
+
969
+ /**
970
+ *
971
+ * @param configuration
972
+ * @param fileNameFull
973
+ * @param content
974
+ * @returns {Promise<TranslatorIO[]>}
975
+ */
976
+ createOutputFileInfo = async (configuration, fileNameFull, content) => {
977
+ const fileName = this.fileSystem.cropExtension(fileNameFull);
978
+ const fileExtension = typescript.Extension.Ts;
979
+
980
+ if (configuration.translateToJavaScript) {
981
+ this.logger.debug("using js translator for", fileName);
982
+ return await this.javascriptTranslator.translate({
983
+ fileName: fileName,
984
+ fileExtension: fileExtension,
985
+ fileContent: content,
986
+ });
987
+ }
988
+
989
+ if (configuration.customTranslator) {
990
+ this.logger.debug("using custom translator for", fileName);
991
+ return await configuration.customTranslator.translate({
992
+ fileName: fileName,
993
+ fileExtension: fileExtension,
994
+ fileContent: content,
995
+ });
996
+ }
997
+
998
+ this.logger.debug("generating output for", `${fileName}${fileExtension}`);
999
+
1000
+ return [
1001
+ {
1002
+ fileName,
1003
+ fileExtension: fileExtension,
1004
+ fileContent: await this.codeFormatter.formatCode(content),
1005
+ },
1006
+ ];
1007
+ };
1008
+
1009
+ createApiConfig = (swaggerSchema) => {
1010
+ const { info, servers, host, basePath, externalDocs, tags } = swaggerSchema;
1011
+ const server = servers?.[0] || { url: "" };
1012
+ const { title = "No title", version } = info || {};
1013
+ const { url: serverUrl } = server;
1014
+
1015
+ return {
1016
+ info: info || {},
1017
+ servers: servers || [],
1018
+ basePath,
1019
+ host,
1020
+ externalDocs: lodash.merge(
1021
+ {
1022
+ url: "",
1023
+ description: "",
1024
+ },
1025
+ externalDocs,
1026
+ ),
1027
+ tags: lodash.compact(tags),
1028
+ baseUrl: serverUrl,
1029
+ title,
1030
+ version,
1031
+ };
1032
+ };
1033
+
1034
+ injectClassInstance = (key, value) => {
1035
+ this[key] = value;
1036
+ for (const instanceKey of PATCHABLE_INSTANCES) {
1037
+ if (instanceKey !== key && key in this[instanceKey]) {
1038
+ this[instanceKey][key] = value;
1039
+ }
1040
+ }
1041
+ };
1042
+ }
1043
+
1044
+ type HttpClientType = "axios" | "fetch";
1045
+
1046
+ interface GenerateApiParamsBase {
1047
+ /**
1048
+ * default 'api.ts'
1049
+ */
1050
+ name?: string;
1051
+
1052
+ /**
1053
+ * name of the main exported class
1054
+ */
1055
+ apiClassName?: string;
1056
+
1057
+ /**
1058
+ * path to folder where will be located the created api module.
1059
+ *
1060
+ * may set to `false` to skip writing content to disk. in this case,
1061
+ * you may access the `files` on the return value.
1062
+ */
1063
+ output?: string | false;
1064
+
1065
+ /**
1066
+ * path to folder containing templates (default: ./src/templates)
1067
+ */
1068
+ templates?: string;
1069
+
1070
+ /**
1071
+ * generate all "enum" types as union types (T1 | T2 | TN) (default: false)
1072
+ */
1073
+ generateUnionEnums?: boolean;
1074
+
1075
+ /**
1076
+ * generate type definitions for API routes (default: false)
1077
+ */
1078
+ generateRouteTypes?: boolean;
1079
+
1080
+ /**
1081
+ * do not generate an API class
1082
+ */
1083
+ generateClient?: boolean;
1084
+ /**
1085
+ * generated http client type
1086
+ */
1087
+ httpClientType?: HttpClientType;
1088
+ /**
1089
+ * use "default" response status code as success response too.
1090
+ * some swagger schemas use "default" response status code as success response type by default.
1091
+ */
1092
+ defaultResponseAsSuccess?: boolean;
1093
+
1094
+ /**
1095
+ * generate additional information about request responses
1096
+ * also add typings for bad responses
1097
+ */
1098
+ generateResponses?: boolean;
1099
+
1100
+ /**
1101
+ * unwrap the data item from the response
1102
+ */
1103
+ unwrapResponseData?: boolean;
1104
+
1105
+ /**
1106
+ * sort data contracts in alphabetical order
1107
+ */
1108
+ sortTypes?: boolean;
1109
+
1110
+ /**
1111
+ * sort routes in alphabetical order
1112
+ */
1113
+ sortRoutes?: boolean;
1114
+
1115
+ /**
1116
+ * generate js api module with declaration file (default: false)
1117
+ */
1118
+ toJS?: boolean;
1119
+
1120
+ /**
1121
+ * determines which path index should be used for routes separation
1122
+ */
1123
+ moduleNameIndex?: number;
1124
+ /**
1125
+ * users operation's first tag for route separation
1126
+ */
1127
+ moduleNameFirstTag?: boolean;
1128
+ /**
1129
+ * disabled SSL check
1130
+ */
1131
+ disableStrictSSL?: boolean;
1132
+ /**
1133
+ * disabled Proxy
1134
+ */
1135
+ disableProxy?: boolean;
1136
+ /**
1137
+ * generate separated files for http client, data contracts, and routes (default: false)
1138
+ */
1139
+ modular?: boolean;
1140
+ /**
1141
+ * extract request params to data contract (Also combine path params and query params into one object)
1142
+ */
1143
+ extractRequestParams?: boolean;
1144
+ /**
1145
+ * extract request body type to data contract
1146
+ */
1147
+ extractRequestBody?: boolean;
1148
+ /**
1149
+ * extract response body type to data contract
1150
+ */
1151
+ extractResponseBody?: boolean;
1152
+ /**
1153
+ * extract response error type to data contract
1154
+ */
1155
+ extractResponseError?: boolean;
1156
+ /**
1157
+ * prettier configuration
1158
+ */
1159
+ prettier?: object;
1160
+ /**
1161
+ * Output only errors to console (default: false)
1162
+ */
1163
+ silent?: boolean;
1164
+ /**
1165
+ * default type for empty response schema (default: "void")
1166
+ */
1167
+ defaultResponseType?: string;
1168
+ /**
1169
+ * Ability to send HttpClient instance to Api constructor
1170
+ */
1171
+ singleHttpClient?: boolean;
1172
+ cleanOutput?: boolean;
1173
+ enumNamesAsValues?: boolean;
1174
+
1175
+ hooks?: Partial<Hooks>;
1176
+ /**
1177
+ * extra templates
1178
+ */
1179
+ extraTemplates?: { name: string; path: string }[];
1180
+
1181
+ /**
1182
+ * fix up small errors in the swagger source definition
1183
+ */
1184
+ patch?: boolean;
1185
+ /**
1186
+ * authorization token
1187
+ */
1188
+ authorizationToken?: string;
1189
+ /**
1190
+ * generate readonly properties (default: false)
1191
+ */
1192
+ addReadonly?: boolean;
1193
+
1194
+ primitiveTypeConstructs?: (
1195
+ struct: PrimitiveTypeStruct,
1196
+ ) => Partial<PrimitiveTypeStruct>;
1197
+
1198
+ codeGenConstructs?: (struct: CodeGenConstruct) => Partial<CodeGenConstruct>;
1199
+
1200
+ /** extract all enums from nested types\interfaces to `enum` construction */
1201
+ extractEnums?: boolean;
1202
+
1203
+ /** prefix string value needed to fix invalid type names (default: 'Type') */
1204
+ fixInvalidTypeNamePrefix?: string;
1205
+
1206
+ /** prefix string value needed to fix invalid enum keys (default: 'Value') */
1207
+ fixInvalidEnumKeyPrefix?: string;
1208
+
1209
+ /** prefix string value for enum keys */
1210
+ enumKeyPrefix?: string;
1211
+
1212
+ /** suffix string value for enum keys */
1213
+ enumKeySuffix?: string;
1214
+
1215
+ /** prefix string value for type names */
1216
+ typePrefix?: string;
1217
+
1218
+ /** suffix string value for type names */
1219
+ typeSuffix?: string;
1220
+
1221
+ /** extra configuration for extracting type names operations */
1222
+ extractingOptions?: Partial<ExtractingOptions>;
1223
+
1224
+ /** configuration for fetching swagger schema requests */
1225
+ requestOptions?: null | Partial<RequestInit>;
1226
+
1227
+ /** ts compiler configuration object (for --to-js option) */
1228
+ compilerTsConfig?: Record<string, unknown>;
1229
+
1230
+ /**
1231
+ * custom ts->* translator
1232
+ * do not use constructor args, it can break functionality of this property, just send class reference
1233
+ *
1234
+ * @example
1235
+ * ```ts
1236
+ * import { Translator } from "swagger-typescript-api/src/translators/translator";
1237
+ *
1238
+ * class MyTranslator extends Translator {
1239
+ *
1240
+ * translate({ fileName, fileExtension, fileContent }) {
1241
+ * this.codeFormatter.format()
1242
+ * this.config.
1243
+ * this.logger.
1244
+ *
1245
+ * return [
1246
+ * {
1247
+ * fileName,
1248
+ * fileExtension,
1249
+ * fileContent,
1250
+ * }
1251
+ * ]
1252
+ * }
1253
+ * }
1254
+ * ```
1255
+ */
1256
+ customTranslator?: new () => typeof Translator;
1257
+ /** fallback name for enum key resolver */
1258
+ enumKeyResolverName?: string;
1259
+ /** fallback name for type name resolver */
1260
+ typeNameResolverName?: string;
1261
+ /** fallback name for specific arg name resolver */
1262
+ specificArgNameResolverName?: string;
1263
+ schemaParsers?: {
1264
+ complexOneOf?: MonoSchemaParser;
1265
+ complexAllOf?: MonoSchemaParser;
1266
+ complexAnyOf?: MonoSchemaParser;
1267
+ complexNot?: MonoSchemaParser;
1268
+ enum?: MonoSchemaParser;
1269
+ object?: MonoSchemaParser;
1270
+ complex?: MonoSchemaParser;
1271
+ primitive?: MonoSchemaParser;
1272
+ discriminator?: MonoSchemaParser;
1273
+ array?: MonoSchemaParser;
1274
+ };
1275
+ }
1276
+
1277
+ type CodeGenConstruct = {
1278
+ Keyword: {
1279
+ Number: string;
1280
+ String: string;
1281
+ Boolean: string;
1282
+ Any: string;
1283
+ Void: string;
1284
+ Unknown: string;
1285
+ Null: string;
1286
+ Undefined: string;
1287
+ Object: string;
1288
+ File: string;
1289
+ Date: string;
1290
+ Type: string;
1291
+ Enum: string;
1292
+ Interface: string;
1293
+ Array: string;
1294
+ Record: string;
1295
+ Intersection: string;
1296
+ Union: string;
1297
+ };
1298
+ CodeGenKeyword: {
1299
+ UtilRequiredKeys: string;
1300
+ };
1301
+ ArrayType: (content: unknown) => string;
1302
+ StringValue: (content: unknown) => string;
1303
+ BooleanValue: (content: unknown) => string;
1304
+ NumberValue: (content: unknown) => string;
1305
+ NullValue: (content: unknown) => string;
1306
+ UnionType: (content: unknown) => string;
1307
+ ExpressionGroup: (content: unknown) => string;
1308
+ IntersectionType: (content: unknown) => string;
1309
+ RecordType: (content: unknown) => string;
1310
+ TypeField: (content: unknown) => string;
1311
+ InterfaceDynamicField: (content: unknown) => string;
1312
+ EnumField: (content: unknown) => string;
1313
+ EnumFieldsWrapper: (content: unknown) => string;
1314
+ ObjectWrapper: (content: unknown) => string;
1315
+ MultilineComment: (content: unknown) => string;
1316
+ TypeWithGeneric: (content: unknown) => string;
1317
+ };
1318
+
1319
+ type PrimitiveTypeStructValue =
1320
+ | string
1321
+ | ((
1322
+ schema: Record<string, unknown>,
1323
+ parser: SchemaParser,
1324
+ ) => string);
1325
+
1326
+ type PrimitiveTypeStruct = Record<
1327
+ "integer" | "number" | "boolean" | "object" | "file" | "string" | "array",
1328
+ | string
1329
+ | ({ $default: PrimitiveTypeStructValue } & Record<
1330
+ string,
1331
+ PrimitiveTypeStructValue
1332
+ >)
1333
+ >;
1334
+
1335
+ interface GenerateApiParamsFromPath extends GenerateApiParamsBase {
1336
+ /**
1337
+ * path to swagger schema
1338
+ */
1339
+ input: string;
1340
+ }
1341
+
1342
+ interface GenerateApiParamsFromUrl extends GenerateApiParamsBase {
1343
+ /**
1344
+ * url to swagger schema
1345
+ */
1346
+ url: string;
1347
+ }
1348
+
1349
+ interface GenerateApiParamsFromSpecLiteral extends GenerateApiParamsBase {
1350
+ /**
1351
+ * swagger schema JSON
1352
+ */
1353
+ spec: swagger_schema_official.Spec;
1354
+ }
1355
+
1356
+ type GenerateApiParams =
1357
+ | GenerateApiParamsFromPath
1358
+ | GenerateApiParamsFromUrl
1359
+ | GenerateApiParamsFromSpecLiteral;
1360
+
1361
+ type BuildRouteParam = {
1362
+ /** {bar} */
1363
+ $match: string;
1364
+ name: string;
1365
+ required: boolean;
1366
+ type: "string";
1367
+ description: string;
1368
+ schema: {
1369
+ type: string;
1370
+ };
1371
+ in: "path" | "query";
1372
+ };
1373
+
1374
+ type BuildRoutePath = {
1375
+ /** /foo/{bar}/baz */
1376
+ originalRoute: string;
1377
+ /** /foo/${bar}/baz */
1378
+ route: string;
1379
+ pathParams: BuildRouteParam[];
1380
+ queryParams: BuildRouteParam[];
1381
+ };
1382
+
1383
+ interface Hooks {
1384
+ /** calls before parse\process route path */
1385
+ onPreBuildRoutePath: (routePath: string) => string | undefined;
1386
+ /** calls after parse\process route path */
1387
+ onBuildRoutePath: (data: BuildRoutePath) => BuildRoutePath | undefined;
1388
+ /** calls before insert path param name into string path interpolation */
1389
+ onInsertPathParam: (
1390
+ paramName: string,
1391
+ index: number,
1392
+ arr: BuildRouteParam[],
1393
+ resultRoute: string,
1394
+ ) => string | undefined;
1395
+ /** calls after parse schema component */
1396
+ onCreateComponent: (
1397
+ component: SchemaComponent,
1398
+ ) => SchemaComponent | undefined;
1399
+ /** calls before parse any kind of schema */
1400
+ onPreParseSchema: (
1401
+ originalSchema: unknown,
1402
+ typeName: string,
1403
+ schemaType: string,
1404
+ ) => undefined;
1405
+ /** calls after parse any kind of schema */
1406
+ onParseSchema: (
1407
+ originalSchema: unknown,
1408
+ parsedSchema: unknown,
1409
+ ) => unknown | undefined;
1410
+ /** calls after parse route (return type: customized route (ParsedRoute), nothing change (void), false (ignore this route)) */
1411
+ onCreateRoute: (routeData: ParsedRoute) => ParsedRoute | false | undefined;
1412
+ /** Start point of work this tool (after fetching schema) */
1413
+ onInit?: <C extends GenerateApiConfiguration["config"]>(
1414
+ configuration: C,
1415
+ codeGenProcess: CodeGenProcess,
1416
+ ) => C | undefined;
1417
+ /** customize configuration object before sending it to ETA templates */
1418
+ onPrepareConfig?: <C extends GenerateApiConfiguration>(
1419
+ currentConfiguration: C,
1420
+ ) => C | undefined;
1421
+ /** customize route name as you need */
1422
+ onCreateRouteName?: (
1423
+ routeNameInfo: RouteNameInfo,
1424
+ rawRouteInfo: RawRouteInfo,
1425
+ ) => RouteNameInfo | undefined;
1426
+ /** customize request params (path params, query params) */
1427
+ onCreateRequestParams?: (
1428
+ rawType: SchemaComponent["rawTypeData"],
1429
+ ) => SchemaComponent["rawTypeData"] | undefined;
1430
+ /** customize name of model type */
1431
+ onFormatTypeName?: (
1432
+ typeName: string,
1433
+ rawTypeName?: string,
1434
+ schemaType?: "type-name" | "enum-key",
1435
+ ) => string | undefined;
1436
+ /** customize name of route (operationId), you can do it with using onCreateRouteName too */
1437
+ onFormatRouteName?: (
1438
+ routeInfo: RawRouteInfo,
1439
+ templateRouteName: string,
1440
+ ) => string | undefined;
1441
+ }
1442
+
1443
+ type RouteNameRouteInfo = Record<string, unknown>;
1444
+
1445
+ type RouteNameInfo = {
1446
+ usage: string;
1447
+ original: string;
1448
+ duplicate: boolean;
1449
+ };
1450
+
1451
+ type SchemaTypePrimitiveContent = {
1452
+ $parsedSchema: boolean;
1453
+ schemaType: string;
1454
+ type: string;
1455
+ typeIdentifier: string;
1456
+ name?: unknown;
1457
+ description: string;
1458
+ content: string;
1459
+ };
1460
+
1461
+ type SchemaTypeObjectContent = {
1462
+ $$raw: {
1463
+ type: string;
1464
+ required: boolean;
1465
+ $parsed: SchemaTypePrimitiveContent;
1466
+ };
1467
+ isRequired: boolean;
1468
+ field: string;
1469
+ }[];
1470
+
1471
+ type SchemaTypeEnumContent = {
1472
+ key: string;
1473
+ type: string;
1474
+ value: string;
1475
+ };
1476
+
1477
+ interface ParsedSchema<C> {
1478
+ $parsedSchema: boolean;
1479
+ schemaType: string;
1480
+ type: string;
1481
+ typeIdentifier: string;
1482
+ name: string;
1483
+ description?: string;
1484
+ allFieldsAreOptional?: boolean;
1485
+ content: C;
1486
+ }
1487
+
1488
+ interface PathArgInfo {
1489
+ name: string;
1490
+ optional: boolean;
1491
+ type: string;
1492
+ description?: string;
1493
+ }
1494
+
1495
+ interface SchemaComponent {
1496
+ $ref: string;
1497
+ typeName: string;
1498
+ rawTypeData?: {
1499
+ type: string;
1500
+ required?: string[];
1501
+ properties?: Record<
1502
+ string,
1503
+ {
1504
+ name?: string;
1505
+ type: string;
1506
+ required: boolean;
1507
+ $parsed?: SchemaTypePrimitiveContent;
1508
+ }
1509
+ >;
1510
+ discriminator?: {
1511
+ propertyName?: string;
1512
+ };
1513
+ $parsed: ParsedSchema<
1514
+ | SchemaTypeObjectContent
1515
+ | SchemaTypeEnumContent
1516
+ | SchemaTypePrimitiveContent
1517
+ >;
1518
+ };
1519
+ componentName: "schemas" | "paths";
1520
+ typeData: ParsedSchema<
1521
+ SchemaTypeObjectContent | SchemaTypeEnumContent | SchemaTypePrimitiveContent
1522
+ > | null;
1523
+ }
1524
+
1525
+ declare enum RequestContentKind {
1526
+ JSON = "JSON",
1527
+ URL_ENCODED = "URL_ENCODED",
1528
+ FORM_DATA = "FORM_DATA",
1529
+ IMAGE = "IMAGE",
1530
+ OTHER = "OTHER",
1531
+ TEXT = "TEXT",
1532
+ }
1533
+
1534
+ interface RequestResponseInfo {
1535
+ contentTypes: string[];
1536
+ contentKind: RequestContentKind;
1537
+ type: string;
1538
+ description: string;
1539
+ status: string | number;
1540
+ isSuccess: boolean;
1541
+ }
1542
+
1543
+ type RawRouteInfo = {
1544
+ operationId: string;
1545
+ method: string;
1546
+ route: string;
1547
+ moduleName: string;
1548
+ responsesTypes: RequestResponseInfo[];
1549
+ description?: string;
1550
+ tags?: string[];
1551
+ summary?: string;
1552
+ responses?: swagger_schema_official.Spec["responses"];
1553
+ produces?: string[];
1554
+ requestBody?: object;
1555
+ consumes?: string[];
1556
+ };
1557
+
1558
+ interface ParsedRoute {
1559
+ id: string;
1560
+ jsDocLines: string;
1561
+ namespace: string;
1562
+ request: Request;
1563
+ response: Response;
1564
+ routeName: RouteNameInfo;
1565
+ raw: RawRouteInfo;
1566
+ }
1567
+
1568
+ type ModelType = {
1569
+ typeIdentifier: string;
1570
+ name: string;
1571
+ rawContent: string;
1572
+ description: string;
1573
+ content: string;
1574
+ };
1575
+
1576
+ declare enum SCHEMA_TYPES {
1577
+ ARRAY = "array",
1578
+ OBJECT = "object",
1579
+ ENUM = "enum",
1580
+ REF = "$ref",
1581
+ PRIMITIVE = "primitive",
1582
+ COMPLEX = "complex",
1583
+ COMPLEX_ONE_OF = "oneOf",
1584
+ COMPLEX_ANY_OF = "anyOf",
1585
+ COMPLEX_ALL_OF = "allOf",
1586
+ COMPLEX_NOT = "not",
1587
+ COMPLEX_UNKNOWN = "__unknown",
1588
+ }
1589
+
1590
+ type MAIN_SCHEMA_TYPES =
1591
+ | SCHEMA_TYPES.PRIMITIVE
1592
+ | SCHEMA_TYPES.OBJECT
1593
+ | SCHEMA_TYPES.ENUM;
1594
+
1595
+ type ExtractingOptions = {
1596
+ requestBodySuffix: string[];
1597
+ responseBodySuffix: string[];
1598
+ responseErrorSuffix: string[];
1599
+ requestParamsSuffix: string[];
1600
+ enumSuffix: string[];
1601
+ discriminatorMappingSuffix: string[];
1602
+ discriminatorAbstractPrefix: string[];
1603
+ requestBodyNameResolver: (
1604
+ name: string,
1605
+ reservedNames: string,
1606
+ ) => string | undefined;
1607
+ responseBodyNameResolver: (
1608
+ name: string,
1609
+ reservedNames: string,
1610
+ ) => string | undefined;
1611
+ responseErrorNameResolver: (
1612
+ name: string,
1613
+ reservedNames: string,
1614
+ ) => string | undefined;
1615
+ requestParamsNameResolver: (
1616
+ name: string,
1617
+ reservedNames: string,
1618
+ ) => string | undefined;
1619
+ enumNameResolver: (name: string, reservedNames: string) => string | undefined;
1620
+ discriminatorMappingNameResolver: (
1621
+ name: string,
1622
+ reservedNames: string,
1623
+ ) => string | undefined;
1624
+ discriminatorAbstractResolver: (
1625
+ name: string,
1626
+ reservedNames: string,
1627
+ ) => string | undefined;
1628
+ };
1629
+
1630
+ interface GenerateApiConfiguration {
1631
+ apiConfig: {
1632
+ baseUrl: string;
1633
+ title: string;
1634
+ version: string;
1635
+ description: string[];
1636
+ hasDescription: boolean;
1637
+ };
1638
+ config: {
1639
+ input: string;
1640
+ output: string;
1641
+ url: string;
1642
+ spec: unknown;
1643
+ fileName: string;
1644
+ templatePaths: {
1645
+ /** `templates/base` */
1646
+ base: string;
1647
+ /** `templates/default` */
1648
+ default: string;
1649
+ /** `templates/modular` */
1650
+ modular: string;
1651
+ /** usage path if `--templates` option is not set */
1652
+ original: string;
1653
+ /** custom path to templates (`--templates`) */
1654
+ custom: string | null;
1655
+ };
1656
+ authorizationToken?: string;
1657
+ generateResponses: boolean;
1658
+ defaultResponseAsSuccess: boolean;
1659
+ generateRouteTypes: boolean;
1660
+ generateClient: boolean;
1661
+ generateUnionEnums: boolean;
1662
+ swaggerSchema: object;
1663
+ originalSchema: object;
1664
+ componentsMap: Record<string, SchemaComponent>;
1665
+ convertedFromSwagger2: boolean;
1666
+ moduleNameIndex: number;
1667
+ moduleNameFirstTag: boolean;
1668
+ extraTemplates: { name: string; path: string }[];
1669
+ disableStrictSSL: boolean;
1670
+ disableProxy: boolean;
1671
+ extractRequestParams: boolean;
1672
+ unwrapResponseData: boolean;
1673
+ sortTypes: boolean;
1674
+ sortRoutes: boolean;
1675
+ singleHttpClient: boolean;
1676
+ typePrefix: string;
1677
+ typeSuffix: string;
1678
+ enumKeyPrefix: string;
1679
+ enumKeySuffix: string;
1680
+ patch: boolean;
1681
+ cleanOutput: boolean;
1682
+ debug: boolean;
1683
+ anotherArrayType: boolean;
1684
+ extractRequestBody: boolean;
1685
+ httpClientType: "axios" | "fetch";
1686
+ addReadonly: boolean;
1687
+ extractResponseBody: boolean;
1688
+ extractResponseError: boolean;
1689
+ extractEnums: boolean;
1690
+ fixInvalidTypeNamePrefix: string;
1691
+ fixInvalidEnumKeyPrefix: string;
1692
+ defaultResponseType: string;
1693
+ toJS: boolean;
1694
+ disableThrowOnError: boolean;
1695
+ silent: boolean;
1696
+ hooks: Hooks;
1697
+ enumNamesAsValues: boolean;
1698
+ version: string;
1699
+ compilerTsConfig: Record<string, unknown>;
1700
+ enumKeyResolverName: string;
1701
+ typeNameResolverName: string;
1702
+ specificArgNameResolverName: string;
1703
+ /** do not use constructor args, it can break functionality of this property, just send class reference */
1704
+ customTranslator?: new (
1705
+ ...args: never[]
1706
+ ) => typeof Translator;
1707
+ internalTemplateOptions: {
1708
+ addUtilRequiredKeysType: boolean;
1709
+ };
1710
+ componentTypeNameResolver: typeof ComponentTypeNameResolver;
1711
+ fileNames: {
1712
+ dataContracts: string;
1713
+ routeTypes: string;
1714
+ httpClient: string;
1715
+ outOfModuleApi: string;
1716
+ };
1717
+ templatesToRender: {
1718
+ api: string;
1719
+ dataContracts: string;
1720
+ httpClient: string;
1721
+ routeTypes: string;
1722
+ routeName: string;
1723
+ dataContractJsDoc: string;
1724
+ interfaceDataContract: string;
1725
+ typeDataContract: string;
1726
+ enumDataContract: string;
1727
+ objectFieldJsDoc: string;
1728
+ };
1729
+ routeNameDuplicatesMap: Map<string, string>;
1730
+ apiClassName: string;
1731
+ requestOptions?: RequestInit;
1732
+ extractingOptions: ExtractingOptions;
1733
+ };
1734
+ modelTypes: ModelType[];
1735
+ hasFormDataRoutes: boolean;
1736
+ hasSecurityRoutes: boolean;
1737
+ hasQueryRoutes: boolean;
1738
+ generateResponses: boolean;
1739
+ routes: {
1740
+ outOfModule: ParsedRoute[];
1741
+ combined?: {
1742
+ moduleName: string;
1743
+ routes: ParsedRoute[];
1744
+ }[];
1745
+ };
1746
+ requestOptions?: null | Partial<RequestInit>;
1747
+ utils: {
1748
+ formatDescription: (description: string, inline?: boolean) => string;
1749
+ internalCase: (value: string) => string;
1750
+ /** @deprecated */
1751
+ classNameCase: (value: string) => string;
1752
+ pascalCase: (value: string) => string;
1753
+ getInlineParseContent: (
1754
+ rawTypeData: SchemaComponent["rawTypeData"],
1755
+ typeName?: string,
1756
+ ) => string;
1757
+ getParseContent: (
1758
+ rawTypeData: SchemaComponent["rawTypeData"],
1759
+ typeName?: string,
1760
+ ) => ModelType;
1761
+ getComponentByRef: (ref: string) => SchemaComponent;
1762
+ parseSchema: (
1763
+ rawSchema: string | SchemaComponent["rawTypeData"],
1764
+ typeName?: string,
1765
+ formattersMap?: Record<MAIN_SCHEMA_TYPES, (content: ModelType) => string>,
1766
+ ) => ModelType;
1767
+ formatters: Record<
1768
+ MAIN_SCHEMA_TYPES,
1769
+ (content: string | object | string[] | object[]) => string
1770
+ >;
1771
+ inlineExtraFormatters: Record<
1772
+ Exclude<MAIN_SCHEMA_TYPES, SCHEMA_TYPES.PRIMITIVE>,
1773
+ (schema: ModelType) => string
1774
+ >;
1775
+ formatModelName: (name: string) => string;
1776
+ fmtToJSDocLine: (line: string, params?: { eol?: boolean }) => string;
1777
+ _: lodash.LoDashStatic;
1778
+ require: (path: string) => unknown;
1779
+ };
1780
+ }
1781
+
1782
+ type FileInfo = {
1783
+ /** @example myFilename */
1784
+ fileName: string;
1785
+ /** @example .d.ts */
1786
+ fileExtension: string;
1787
+ /** content of the file */
1788
+ fileContent: string;
1789
+ };
1790
+
1791
+ interface GenerateApiOutput {
1792
+ configuration: GenerateApiConfiguration;
1793
+ files: FileInfo[];
1794
+ createFile: (params: {
1795
+ path: string;
1796
+ fileName: string;
1797
+ content: string;
1798
+ withPrefix: boolean;
1799
+ }) => void;
1800
+ renderTemplate: (
1801
+ templateContent: string,
1802
+ data: Record<string, unknown>,
1803
+ etaOptions?: Partial<eta.EtaConfig>,
1804
+ ) => Promise<string> | string;
1805
+ getTemplate: (params: {
1806
+ fileName?: string;
1807
+ name?: string;
1808
+ path?: string;
1809
+ }) => string;
1810
+ formatTSContent: (content: string) => Promise<string>;
1811
+ }
1812
+
1813
+ declare function generateApi(
1814
+ params: GenerateApiParams,
1815
+ ): Promise<GenerateApiOutput>;
1816
+
1817
+ interface GenerateTemplatesParams {
1818
+ cleanOutput?: boolean;
1819
+ output?: string;
1820
+ httpClientType?: HttpClientType;
1821
+ modular?: boolean;
1822
+ silent?: boolean;
1823
+ }
1824
+
1825
+ interface GenerateTemplatesOutput
1826
+ extends Pick<GenerateApiOutput, "files" | "createFile"> {}
1827
+
1828
+ declare function generateTemplates(
1829
+ params: GenerateTemplatesParams,
1830
+ ): Promise<GenerateTemplatesOutput>;
1831
+
1832
+ export { type GenerateApiConfiguration, type GenerateApiOutput, type GenerateApiParams, type GenerateTemplatesOutput, type GenerateTemplatesParams, type Hooks, type ModelType, type ParsedRoute, type ParsedSchema, type PathArgInfo, type RawRouteInfo, RequestContentKind, type RequestResponseInfo, type RouteNameInfo, type RouteNameRouteInfo, SCHEMA_TYPES, type SchemaComponent, type SchemaTypeEnumContent, type SchemaTypeObjectContent, type SchemaTypePrimitiveContent, generateApi, generateTemplates };