swagger-typescript-api 13.6.10 → 13.7.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.
@@ -208,7 +208,7 @@ var ComponentTypeNameResolver = class extends NameResolver {
208
208
  //#endregion
209
209
  //#region package.json
210
210
  var name = "swagger-typescript-api";
211
- var version = "13.6.10";
211
+ var version = "13.7.0";
212
212
  var description = "Generate the API client for Fetch or Axios from an OpenAPI Specification";
213
213
  //#endregion
214
214
  //#region src/constants.ts
@@ -373,13 +373,19 @@ var CodeGenConfig = class {
373
373
  httpClientType = HTTP_CLIENT.FETCH;
374
374
  unwrapResponseData = false;
375
375
  disableThrowOnError = false;
376
+ disableFormatTypeNames = false;
376
377
  sortTypes = false;
377
378
  sortRoutes = false;
378
379
  templatePaths = {
380
+ /** `templates/base` */
379
381
  base: "",
382
+ /** `templates/default` */
380
383
  default: "",
384
+ /** `templates/modular` */
381
385
  modular: "",
386
+ /** usage path if `--templates` option is not set */
382
387
  original: "",
388
+ /** custom path to templates (`--templates`) */
383
389
  custom: ""
384
390
  };
385
391
  /** Record<templateName, templateContent> */
@@ -400,6 +406,7 @@ var CodeGenConfig = class {
400
406
  silent = false;
401
407
  typePrefix = "";
402
408
  typeSuffix = "";
409
+ typeNameSeparator = "_";
403
410
  enumKeyPrefix = "";
404
411
  enumKeySuffix = "";
405
412
  patch = false;
@@ -479,18 +486,48 @@ var CodeGenConfig = class {
479
486
  Ts = {
480
487
  Keyword: structuredClone(TsKeyword),
481
488
  CodeGenKeyword: structuredClone(TsCodeGenKeyword),
489
+ /**
490
+ * $A[] or Array<$A>
491
+ */
482
492
  ArrayType: (content) => {
483
493
  if (this.anotherArrayType) return this.Ts.TypeWithGeneric(this.Ts.Keyword.Array, [content]);
484
494
  return `${this.Ts.ExpressionGroup(content)}[]`;
485
495
  },
496
+ /**
497
+ * "$A"
498
+ */
486
499
  StringValue: (content) => `"${content}"`,
500
+ /**
501
+ * $A
502
+ */
487
503
  BooleanValue: (content) => `${content}`,
504
+ /**
505
+ * $A
506
+ */
488
507
  NumberValue: (content) => `${content}`,
508
+ /**
509
+ * $A
510
+ */
489
511
  NullValue: () => "null",
512
+ /**
513
+ * $A1 | $A2
514
+ */
490
515
  UnionType: (contents) => (0, es_toolkit.uniq)(contents).join(` ${this.Ts.Keyword.Union} `),
516
+ /**
517
+ * ($A1)
518
+ */
491
519
  ExpressionGroup: (content) => content ? `(${content})` : "",
520
+ /**
521
+ * $A1 & $A2
522
+ */
492
523
  IntersectionType: (contents) => (0, es_toolkit.uniq)(contents).join(` ${this.Ts.Keyword.Intersection} `),
524
+ /**
525
+ * Record<$A1, $A2>
526
+ */
493
527
  RecordType: (key, value) => this.Ts.TypeWithGeneric(this.Ts.Keyword.Record, [key, value]),
528
+ /**
529
+ * readonly $key?:$value
530
+ */
494
531
  TypeField: ({ readonly, key, optional, value }) => (0, es_toolkit.compact)([
495
532
  readonly && "readonly ",
496
533
  key,
@@ -498,25 +535,57 @@ var CodeGenConfig = class {
498
535
  ": ",
499
536
  value
500
537
  ]).join(""),
538
+ /**
539
+ * [key: $A1]: $A2
540
+ */
501
541
  InterfaceDynamicField: (key, value) => `[key: ${key}]: ${value}`,
542
+ /**
543
+ * EnumName.EnumKey
544
+ */
502
545
  EnumUsageKey: (enumStruct, key) => `${enumStruct}.${key}`,
546
+ /**
547
+ * $A1 = $A2
548
+ */
503
549
  EnumField: (key, value) => `${key} = ${value}`,
550
+ /**
551
+ * /\** description \*\/
552
+ */
504
553
  EnumFieldDescription: (description) => {
505
554
  if (description) return ` /** ${description} */`;
506
555
  else return "";
507
556
  },
557
+ /**
558
+ * /\** $A0.description \*\/
559
+ * $A0.key = $A0.value,
560
+ * /\** $A1.description \*\/
561
+ * $A1.key = $A1.value,
562
+ * /\** $AN.description \*\/
563
+ * $AN.key = $AN.value,
564
+ */
508
565
  EnumFieldsWrapper: (contents) => contents.map(({ key, value, description }) => {
509
566
  return (0, es_toolkit.compact)([this.Ts.EnumFieldDescription(description), ` ${this.Ts.EnumField(key, value)}`]).join("\n");
510
567
  }).join(",\n"),
568
+ /**
569
+ * {\n $A \n}
570
+ */
511
571
  ObjectWrapper: (content) => `{\n${content}\n}`,
572
+ /**
573
+ * /** $A *\/
574
+ */
512
575
  MultilineComment: (contents, formatFn) => [...contents.length === 1 ? [`/** ${contents[0]} */`] : [
513
576
  "/**",
514
577
  ...contents.map((content) => ` * ${content}`),
515
578
  " */"
516
579
  ]].map((part) => `${formatFn ? formatFn(part) : part}\n`),
580
+ /**
581
+ * $A1<...$A2.join(,)>
582
+ */
517
583
  TypeWithGeneric: (typeName, genericArgs) => {
518
584
  return `${typeName}${genericArgs.length ? `<${genericArgs.join(",")}>` : ""}`;
519
585
  },
586
+ /**
587
+ * [$A1, $A2, ...$AN]
588
+ */
520
589
  Tuple: (values) => {
521
590
  return `[${values.join(", ")}]`;
522
591
  }
@@ -533,6 +602,7 @@ var CodeGenConfig = class {
533
602
  file: () => this.Ts.Keyword.File,
534
603
  string: {
535
604
  $default: this.Ts.Keyword.String,
605
+ /** formats */
536
606
  binary: () => this.Ts.Keyword.File,
537
607
  byte: () => this.Ts.Keyword.Blob,
538
608
  file: () => this.Ts.Keyword.File,
@@ -656,6 +726,7 @@ var SchemaComponentsMap = class {
656
726
  typeName,
657
727
  rawTypeData,
658
728
  componentName: rawComponentName === "definitions" ? "schemas" : rawComponentName,
729
+ /** result from schema parser */
659
730
  typeData: null
660
731
  };
661
732
  }
@@ -1195,10 +1266,11 @@ var ObjectSchemaParser = class extends MonoSchemaParser {
1195
1266
  const rawTypeData = (0, es_toolkit_compat.get)(this.schemaUtils.getSchemaRefType(property), "rawTypeData", {});
1196
1267
  const nullable = !!(rawTypeData.nullable || property.nullable);
1197
1268
  const fieldName = this.typeNameFormatter.isValidName(name) ? name : this.config.Ts.StringValue(name);
1198
- const fieldValue = this.schemaParserFabric.createSchemaParser({
1269
+ const rawFieldValue = this.schemaParserFabric.createSchemaParser({
1199
1270
  schema: property,
1200
1271
  schemaPath: [...this.schemaPath, name]
1201
1272
  }).getInlineParseContent();
1273
+ const fieldValue = nullable ? this.schemaUtils.safeAddNullToType(property, rawFieldValue) : rawFieldValue;
1202
1274
  const readOnly = property.readOnly;
1203
1275
  const complexType = this.schemaUtils.getComplexType(property);
1204
1276
  const rawDataComplexType = this.schemaUtils.getComplexType(rawTypeData);
@@ -1493,7 +1565,10 @@ var SchemaUtils = class {
1493
1565
  };
1494
1566
  isNullMissingInType = (schema, type) => {
1495
1567
  const { nullable, type: schemaType } = schema || {};
1496
- return (nullable || !!(0, es_toolkit_compat.get)(schema, "x-nullable") || schemaType === this.config.Ts.Keyword.Null) && typeof type === "string" && !type.includes(` ${this.config.Ts.Keyword.Null}`) && !type.includes(`${this.config.Ts.Keyword.Null} `);
1568
+ if (!(nullable || !!(0, es_toolkit_compat.get)(schema, "x-nullable") || schemaType === this.config.Ts.Keyword.Null) || typeof type !== "string") return false;
1569
+ const nullKeyword = this.config.Ts.Keyword.Null;
1570
+ const lastLine = type.trimEnd().split("\n").pop() ?? type;
1571
+ return !lastLine.includes(` ${nullKeyword}`) && !lastLine.includes(`${nullKeyword} `);
1497
1572
  };
1498
1573
  safeAddNullToType = (schema, type) => {
1499
1574
  if (this.isNullMissingInType(schema, type)) return this.config.Ts.UnionType([type, this.config.Ts.Keyword.Null]);
@@ -3002,10 +3077,15 @@ var TemplatesWorker = class {
3002
3077
  const defaultTemplatesPath = node_path.resolve(__dirname, "../templates/default");
3003
3078
  const modularTemplatesPath = node_path.resolve(__dirname, "../templates/modular");
3004
3079
  return {
3080
+ /** `templates/base` */
3005
3081
  base: baseTemplatesPath,
3082
+ /** `templates/default` */
3006
3083
  default: defaultTemplatesPath,
3084
+ /** `templates/modular` */
3007
3085
  modular: modularTemplatesPath,
3086
+ /** usage path if `--templates` option is not set */
3008
3087
  original: config.modular ? modularTemplatesPath : defaultTemplatesPath,
3088
+ /** custom path to templates (`--templates`) */
3009
3089
  custom: config.templates && node_path.resolve(process.cwd(), config.templates)
3010
3090
  };
3011
3091
  };
@@ -3125,39 +3205,119 @@ var JavascriptTranslator = class extends Translator {
3125
3205
  //#region src/type-name-formatter.ts
3126
3206
  var TypeNameFormatter = class {
3127
3207
  formattedModelNamesMap = /* @__PURE__ */ new Map();
3208
+ usedFormattedTypeNames = /* @__PURE__ */ new Map();
3128
3209
  config;
3129
3210
  constructor(config) {
3130
3211
  this.config = config;
3131
3212
  }
3213
+ /**
3214
+ * Return the TypeScript identifier for a raw OpenAPI name. Fast path is a
3215
+ * cache hit on names resolved by `precommit`. The fallback (for names
3216
+ * discovered after precommit, e.g. enum keys inside schemas or types added
3217
+ * dynamically by `extractEnums`/`extractResponses`) computes the identifier
3218
+ * inline WITHOUT collision handling — collision resolution is the sole
3219
+ * responsibility of `precommit`. Callers expecting collision safety must
3220
+ * list every raw name in the precommit input.
3221
+ */
3132
3222
  format = (name, options = {}) => {
3133
3223
  const schemaType = options.type ?? "type-name";
3134
- const typePrefix = schemaType === "enum-key" ? this.config.enumKeyPrefix : this.config.typePrefix;
3135
- const typeSuffix = schemaType === "enum-key" ? this.config.enumKeySuffix : this.config.typeSuffix;
3224
+ const { typePrefix, typeSuffix } = this.getAffixes(schemaType);
3136
3225
  const hashKey = `${typePrefix}_${name}_${typeSuffix}`;
3226
+ const cached = this.formattedModelNamesMap.get(hashKey);
3227
+ if (cached !== void 0) return cached;
3137
3228
  if (typeof name !== "string") {
3138
3229
  consola.consola.warn("wrong model name", name);
3139
3230
  return name;
3140
3231
  }
3141
- if (/^(?!\d)([A-Z0-9_]{1,})$/g.test(name)) return (0, es_toolkit.compact)([
3142
- typePrefix,
3143
- name,
3144
- typeSuffix
3145
- ]).join("_");
3146
- if (this.formattedModelNamesMap.has(hashKey)) return this.formattedModelNamesMap.get(hashKey);
3147
- const formattedName = (0, es_toolkit_compat.startCase)(`${typePrefix}_${this.fixModelName(name, { type: schemaType })}_${typeSuffix}`).replace(/\s/g, "");
3148
- const formattedResultName = this.config.hooks.onFormatTypeName?.(formattedName, name, schemaType) || formattedName;
3149
- this.formattedModelNamesMap.set(hashKey, formattedResultName);
3150
- return formattedResultName;
3232
+ const result = this.computeFormattedName(name, schemaType, typePrefix, typeSuffix);
3233
+ this.formattedModelNamesMap.set(hashKey, result);
3234
+ return result;
3235
+ };
3236
+ /**
3237
+ * Resolve the TypeScript identifier for every raw schema name passed in,
3238
+ * populating `formattedModelNamesMap` and `usedFormattedTypeNames`. Must be
3239
+ * called once, before any `format()` call from the schema parser, so that
3240
+ * every subsequent `format()` for these names is a cache hit and returns
3241
+ * the collision-resolved identifier.
3242
+ *
3243
+ * Two passes:
3244
+ * 1. Claim every raw name whose formatted output equals the raw name
3245
+ * itself ("canonical"). User-declared identifiers like `FooBar` or
3246
+ * `FooBar1` are preserved regardless of the source order in which
3247
+ * the generator later visits them.
3248
+ * 2. For non-canonical names (e.g. `Foo_Bar` → `FooBar`), suffix with
3249
+ * the smallest integer not already claimed, so collisions produce
3250
+ * `FooBar`, `FooBar1`, `FooBar2`, … deterministically.
3251
+ *
3252
+ * Only type-names go through collision resolution here. Enum keys use the
3253
+ * fallback path in `format()` and are handled per-enum by the template.
3254
+ */
3255
+ precommit = (rawNames) => {
3256
+ const schemaType = "type-name";
3257
+ const { typePrefix, typeSuffix } = this.getAffixes(schemaType);
3258
+ const seen = /* @__PURE__ */ new Set();
3259
+ const names = [];
3260
+ for (const name of rawNames) {
3261
+ if (typeof name !== "string") continue;
3262
+ if (seen.has(name)) continue;
3263
+ seen.add(name);
3264
+ names.push(name);
3265
+ }
3266
+ for (const name of names) {
3267
+ const formatted = this.computeFormattedName(name, schemaType, typePrefix, typeSuffix);
3268
+ if (name !== formatted) continue;
3269
+ if (this.usedFormattedTypeNames.has(formatted)) continue;
3270
+ this.usedFormattedTypeNames.set(formatted, name);
3271
+ const hashKey = `${typePrefix}_${name}_${typeSuffix}`;
3272
+ this.formattedModelNamesMap.set(hashKey, formatted);
3273
+ }
3274
+ for (const name of names) {
3275
+ const hashKey = `${typePrefix}_${name}_${typeSuffix}`;
3276
+ if (this.formattedModelNamesMap.has(hashKey)) continue;
3277
+ const formatted = this.computeFormattedName(name, schemaType, typePrefix, typeSuffix);
3278
+ let final = formatted;
3279
+ if (this.usedFormattedTypeNames.has(final)) {
3280
+ let suffix = 1;
3281
+ while (this.usedFormattedTypeNames.has(`${formatted}${suffix}`)) suffix += 1;
3282
+ final = `${formatted}${suffix}`;
3283
+ }
3284
+ this.usedFormattedTypeNames.set(final, name);
3285
+ this.formattedModelNamesMap.set(hashKey, final);
3286
+ }
3151
3287
  };
3152
3288
  isValidName = (name) => /^([A-Za-z$_]{1,})$/g.test(name);
3153
3289
  fixModelName = (name, options) => {
3154
3290
  if (!this.isValidName(name)) {
3155
3291
  if (!/^[a-zA-Z_$]/g.test(name)) return `${options.type === "enum-key" ? this.config.fixInvalidEnumKeyPrefix : this.config.fixInvalidTypeNamePrefix} ${name}`;
3156
3292
  if (name.includes(".")) return name.replace(/Exclude_keyof[A-Za-z]+/g, () => "ExcludeKeys").replace(/%22~AND~%22/g, "And").replace(/%22~OR~%22/g, "Or").replace(/(\.?%22)|\./g, "_").replace(/__+$/, "");
3157
- if (name.includes("-")) return (0, es_toolkit_compat.startCase)(name).replace(/ /g, "");
3293
+ if (name.includes("-")) return this.config.disableFormatTypeNames ? name.replace(/-/g, "_") : (0, es_toolkit_compat.startCase)(name).replace(/ /g, "");
3158
3294
  }
3159
3295
  return name;
3160
3296
  };
3297
+ getAffixes = (schemaType) => ({
3298
+ typePrefix: schemaType === "enum-key" ? this.config.enumKeyPrefix : this.config.typePrefix,
3299
+ typeSuffix: schemaType === "enum-key" ? this.config.enumKeySuffix : this.config.typeSuffix
3300
+ });
3301
+ computeFormattedName = (name, schemaType, typePrefix, typeSuffix) => {
3302
+ const typeNameSeparator = this.config.typeNameSeparator;
3303
+ let resultName = name;
3304
+ if (this.config.disableFormatTypeNames) resultName = (0, es_toolkit.compact)([
3305
+ typePrefix,
3306
+ resultName,
3307
+ typeSuffix
3308
+ ]).join(typeNameSeparator);
3309
+ else if (/^(?!\d)([A-Z0-9_]{1,})$/g.test(resultName)) resultName = (0, es_toolkit.compact)([
3310
+ typePrefix,
3311
+ resultName,
3312
+ typeSuffix
3313
+ ]).join(typeNameSeparator);
3314
+ else resultName = (0, es_toolkit_compat.startCase)((0, es_toolkit.compact)([
3315
+ typePrefix,
3316
+ this.fixModelName(resultName, { type: schemaType }),
3317
+ typeSuffix
3318
+ ]).join(typeNameSeparator)).replace(/\s/g, "");
3319
+ return this.config.hooks.onFormatTypeName?.(resultName, name, schemaType) || resultName;
3320
+ };
3161
3321
  };
3162
3322
  //#endregion
3163
3323
  //#region src/util/file-system.ts
@@ -3276,7 +3436,9 @@ var CodeGenProcess = class {
3276
3436
  ]), rawTypeData);
3277
3437
  this.schemaComponentsMap.discriminatorsFirst();
3278
3438
  this.schemaComponentsMap.enumsFirst();
3279
- const parsedSchemas = this.schemaComponentsMap.filter((0, es_toolkit.compact)(["schemas", this.config.extractResponses && "responses"])).map((schemaComponent) => {
3439
+ const componentsToParse = this.schemaComponentsMap.filter((0, es_toolkit.compact)(["schemas", this.config.extractResponses && "responses"]));
3440
+ this.typeNameFormatter.precommit(componentsToParse.map((c) => c.typeName));
3441
+ const parsedSchemas = componentsToParse.map((schemaComponent) => {
3280
3442
  const parsed = this.schemaParserFabric.parseSchema(schemaComponent.rawTypeData, schemaComponent.typeName);
3281
3443
  schemaComponent.typeData = parsed;
3282
3444
  return parsed;
@@ -3739,4 +3901,4 @@ Object.defineProperty(exports, "version", {
3739
3901
  }
3740
3902
  });
3741
3903
 
3742
- //# sourceMappingURL=src-DsH2wrQK.cjs.map
3904
+ //# sourceMappingURL=src-DTdmNLxQ.cjs.map