@orval/core 8.2.0 → 8.3.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.
package/dist/index.mjs CHANGED
@@ -1,12 +1,12 @@
1
1
  import { t as __export } from "./chunk-C6wwvPpM.mjs";
2
- import { entries, groupBy, isArray, isEmptyish, prop, unique, uniqueBy, uniqueWith } from "remeda";
2
+ import { entries, groupBy, isArray, isBoolean, isBoolean as isBoolean$1, isEmptyish, isFunction, isNullish, isNullish as isNullish$1, isNumber, isString, isString as isString$1, prop, unique, uniqueBy, uniqueWith } from "remeda";
3
3
  import { keyword } from "esutils";
4
4
  import path from "node:path";
5
- import fs from "node:fs";
6
- import { globby } from "globby";
7
5
  import { compare } from "compare-versions";
8
6
  import debug from "debug";
9
7
  import { pathToFileURL } from "node:url";
8
+ import fs from "node:fs";
9
+ import { globby } from "globby";
10
10
  import readline from "node:readline";
11
11
  import chalk from "chalk";
12
12
  import { isDereferenced } from "@scalar/openapi-types/helpers";
@@ -108,124 +108,20 @@ const generalJSTypes = [
108
108
  "object",
109
109
  "blob"
110
110
  ];
111
- const generalJSTypesWithArray = generalJSTypes.reduce((acc, type) => {
112
- acc.push(type, `Array<${type}>`, `${type}[]`);
113
- return acc;
114
- }, []);
111
+ const generalJSTypesWithArray = generalJSTypes.flatMap((type) => [
112
+ type,
113
+ `Array<${type}>`,
114
+ `${type}[]`
115
+ ]);
115
116
  const VERBS_WITH_BODY = [
116
117
  Verbs.POST,
117
118
  Verbs.PUT,
118
119
  Verbs.PATCH,
119
120
  Verbs.DELETE
120
121
  ];
121
- const URL_REGEX = /^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&'\(\)\*\+,;=.]+$/;
122
+ const URL_REGEX = /^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w.-]+)+[\w\-._~:/?#[\]@!$&'()*+,;=.]+$/;
122
123
  const TEMPLATE_TAG_REGEX = /\${(.+?)}/g;
123
124
 
124
- //#endregion
125
- //#region src/utils/extension.ts
126
- function getExtension(path$2) {
127
- return path$2.toLowerCase().includes(".yaml") || path$2.toLowerCase().includes(".yml") ? "yaml" : "json";
128
- }
129
-
130
- //#endregion
131
- //#region src/utils/file.ts
132
- function getFileInfo(target = "", { backupFilename = "filename", extension = ".ts" } = {}) {
133
- const isDir = isDirectory(target);
134
- const filePath = isDir ? path.join(target, backupFilename + extension) : target;
135
- return {
136
- path: filePath,
137
- pathWithoutExtension: filePath.replace(/\.[^/.]+$/, ""),
138
- extension,
139
- isDirectory: isDir,
140
- dirname: path.dirname(filePath),
141
- filename: path.basename(filePath, extension.startsWith(".") ? extension : `.${extension}`)
142
- };
143
- }
144
- async function removeFilesAndEmptyFolders(patterns, dir) {
145
- const files = await globby(patterns, {
146
- cwd: dir,
147
- absolute: true
148
- });
149
- await Promise.all(files.map((file) => fs.promises.unlink(file)));
150
- const sortedDirectories = (await globby(["**/*"], {
151
- cwd: dir,
152
- absolute: true,
153
- onlyDirectories: true
154
- })).toSorted((a, b) => {
155
- const depthA = a.split("/").length;
156
- return b.split("/").length - depthA;
157
- });
158
- for (const directory of sortedDirectories) try {
159
- if ((await fs.promises.readdir(directory)).length === 0) await fs.promises.rmdir(directory);
160
- } catch {}
161
- }
162
-
163
- //#endregion
164
- //#region src/utils/path.ts
165
- var path_exports = /* @__PURE__ */ __export({
166
- basename: () => basename,
167
- dirname: () => dirname,
168
- extname: () => extname,
169
- getSchemaFileName: () => getSchemaFileName,
170
- isAbsolute: () => isAbsolute,
171
- join: () => join,
172
- joinSafe: () => joinSafe,
173
- normalizeSafe: () => normalizeSafe,
174
- relativeSafe: () => relativeSafe,
175
- resolve: () => resolve,
176
- separator: () => separator
177
- });
178
- const path$1 = {};
179
- const isFunction$1 = (val) => typeof val == "function";
180
- const isString$1 = (val) => {
181
- if (typeof val === "string") return true;
182
- if (typeof val === "object" && val !== null) return Object.toString.call(val) == "[object String]";
183
- return false;
184
- };
185
- for (const [propName, propValue] of Object.entries(path)) if (isFunction$1(propValue)) path$1[propName] = ((propName$1) => {
186
- return (...args) => {
187
- args = args.map((p) => {
188
- return isString$1(p) ? toUnix(p) : p;
189
- });
190
- const result = path[propName$1](...args);
191
- return isString$1(result) ? toUnix(result) : result;
192
- };
193
- })(propName);
194
- else path$1[propName] = propValue;
195
- const { join, resolve, extname, dirname, basename, isAbsolute } = path$1;
196
- /**
197
- * Behaves exactly like `path.relative(from, to)`, but keeps the first meaningful "./"
198
- */
199
- function relativeSafe(from, to) {
200
- return normalizeSafe(`.${separator}${path$1.relative(from, to)}`);
201
- }
202
- function getSchemaFileName(path$2) {
203
- return path$2.replace(`.${getExtension(path$2)}`, "").slice(path$2.lastIndexOf("/") + 1);
204
- }
205
- const separator = "/";
206
- const toUnix = function(value) {
207
- value = value.replaceAll("\\", "/");
208
- value = value.replaceAll(/(?<!^)\/+/g, "/");
209
- return value;
210
- };
211
- function normalizeSafe(value) {
212
- let result;
213
- value = toUnix(value);
214
- result = path$1.normalize(value);
215
- if (value.startsWith("./") && !result.startsWith("./") && !result.startsWith("..")) result = "./" + result;
216
- else if (value.startsWith("//") && !result.startsWith("//")) result = value.startsWith("//./") ? "//." + result : "/" + result;
217
- return result;
218
- }
219
- function joinSafe(...values) {
220
- let result = path$1.join(...values);
221
- if (values.length > 0) {
222
- const firstValue = toUnix(values[0]);
223
- if (firstValue.startsWith("./") && !result.startsWith("./") && !result.startsWith("..")) result = "./" + result;
224
- else if (firstValue.startsWith("//") && !result.startsWith("//")) result = firstValue.startsWith("//./") ? "//." + result : "/" + result;
225
- }
226
- return result;
227
- }
228
-
229
125
  //#endregion
230
126
  //#region src/utils/assertion.ts
231
127
  /**
@@ -234,42 +130,29 @@ function joinSafe(...values) {
234
130
  * @param property
235
131
  */
236
132
  function isReference(obj) {
237
- return !isNull(obj) && Object.hasOwn(obj, "$ref");
133
+ return !isNullish$1(obj) && Object.hasOwn(obj, "$ref");
238
134
  }
239
- function isDirectory(path$2) {
240
- return !extname(path$2);
135
+ function isDirectory(pathValue) {
136
+ return !path.extname(pathValue);
241
137
  }
242
138
  function isObject(x) {
243
139
  return Object.prototype.toString.call(x) === "[object Object]";
244
140
  }
141
+ function isStringLike(val) {
142
+ if (isString$1(val)) return true;
143
+ return Object.prototype.toString.call(val) === "[object String]";
144
+ }
245
145
  function isModule(x) {
246
146
  return Object.prototype.toString.call(x) === "[object Module]";
247
147
  }
248
- function isString(x) {
249
- return typeof x === "string";
250
- }
251
- function isNumber(x) {
252
- return typeof x === "number";
253
- }
254
148
  function isNumeric(x) {
255
- return /^-?\d+$/.test(x);
256
- }
257
- function isBoolean(x) {
258
- return typeof x === "boolean";
259
- }
260
- function isFunction(x) {
261
- return typeof x === "function";
262
- }
263
- function isUndefined(x) {
264
- return x === void 0;
265
- }
266
- function isNull(x) {
267
- return x === null;
149
+ if (typeof x === "number") return Number.isInteger(x);
150
+ return isString$1(x) && /^-?\d+$/.test(x);
268
151
  }
269
152
  function isSchema(x) {
270
153
  if (!isObject(x)) return false;
271
- if (isString(x.type) && Object.values(SchemaType).includes(x.type)) return true;
272
- const combine = x.allOf || x.anyOf || x.oneOf;
154
+ if (isString$1(x.type) && Object.values(SchemaType).includes(x.type)) return true;
155
+ const combine = x.allOf ?? x.anyOf ?? x.oneOf;
273
156
  if (Array.isArray(combine)) return true;
274
157
  if (isObject(x.properties)) return true;
275
158
  return false;
@@ -278,27 +161,26 @@ function isVerb(verb) {
278
161
  return Object.values(Verbs).includes(verb);
279
162
  }
280
163
  function isUrl(str) {
281
- let givenURL;
164
+ if (!str.trim()) return false;
282
165
  try {
283
- givenURL = new URL(str);
166
+ const url = new URL(str);
167
+ return ["http:", "https:"].includes(url.protocol);
284
168
  } catch {
285
169
  return false;
286
170
  }
287
- return givenURL.protocol === "http:" || givenURL.protocol === "https:";
288
171
  }
289
172
 
290
173
  //#endregion
291
174
  //#region src/utils/async-reduce.ts
292
175
  async function asyncReduce(array, reducer, initValue) {
293
- let accumulate = typeof initValue === "object" ? Object.create(initValue) : initValue;
176
+ let accumulate = initValue === null || initValue === Object(initValue) && !isFunction(initValue) ? Object.create(initValue) : initValue;
294
177
  for (const item of array) accumulate = await reducer(accumulate, item);
295
178
  return accumulate;
296
179
  }
297
180
 
298
181
  //#endregion
299
182
  //#region src/utils/case.ts
300
- const unicodes = function(s, prefix) {
301
- prefix = prefix || "";
183
+ const unicodes = function(s, prefix = "") {
302
184
  return s.replaceAll(/(^|-)/g, String.raw`$1\u` + prefix).replaceAll(",", String.raw`\u` + prefix);
303
185
  };
304
186
  const symbols = unicodes("20-26,28-2F,3A-40,5B-60,7B-7E,A0-BF,D7,F7", "00");
@@ -320,8 +202,8 @@ const regexps = {
320
202
  const deapostrophe = (s) => {
321
203
  return s.replace(regexps.apostrophe, "");
322
204
  };
323
- const up = String.prototype.toUpperCase;
324
- const low = String.prototype.toLowerCase;
205
+ const up = (s) => s.toUpperCase();
206
+ const low = (s) => s.toLowerCase();
325
207
  const fill = (s, fillWith, isDeapostrophe = false) => {
326
208
  s = s.replace(regexps.fill, function(m, next) {
327
209
  return next ? fillWith + next : "";
@@ -330,14 +212,13 @@ const fill = (s, fillWith, isDeapostrophe = false) => {
330
212
  return s;
331
213
  };
332
214
  const decap = (s, char = 0) => {
333
- return low.call(s.charAt(char)) + s.slice(char + 1);
215
+ return low(s.charAt(char)) + s.slice(char + 1);
334
216
  };
335
217
  const relax = (m, before, acronym, caps) => {
336
218
  return before + " " + (acronym ? acronym + " " : "") + caps;
337
219
  };
338
220
  const prep = (s, isFill = false, isPascal = false, isUpper = false) => {
339
- s = s == void 0 ? "" : s + "";
340
- if (!isUpper && regexps.upper.test(s)) s = low.call(s);
221
+ if (!isUpper && regexps.upper.test(s)) s = low(s);
341
222
  if (!isFill && !regexps.hole.test(s)) {
342
223
  var holey = fill(s, " ");
343
224
  if (regexps.hole.test(holey)) s = holey;
@@ -346,20 +227,20 @@ const prep = (s, isFill = false, isPascal = false, isUpper = false) => {
346
227
  return s;
347
228
  };
348
229
  const lower = (s, fillWith, isDeapostrophe) => {
349
- return fill(low.call(prep(s, !!fillWith)), fillWith, isDeapostrophe);
230
+ return fill(low(prep(s, !!fillWith)), fillWith, isDeapostrophe);
350
231
  };
351
232
  const pascalMemory = {};
352
- function pascal(s) {
233
+ function pascal(s = "") {
353
234
  if (pascalMemory[s]) return pascalMemory[s];
354
- const isStartWithUnderscore = s?.startsWith("_");
355
- if (regexps.upper.test(s)) s = low.call(s);
356
- const pascalString = (s?.match(/[a-zA-Z0-9\u00C0-\u017F]+/g) || []).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join("");
235
+ const isStartWithUnderscore = s.startsWith("_");
236
+ if (regexps.upper.test(s)) s = low(s);
237
+ const pascalString = (s.match(/[a-zA-Z0-9\u00C0-\u017F]+/g) ?? []).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join("");
357
238
  const pascalWithUnderscore = isStartWithUnderscore ? `_${pascalString}` : pascalString;
358
239
  pascalMemory[s] = pascalWithUnderscore;
359
240
  return pascalWithUnderscore;
360
241
  }
361
- function camel(s) {
362
- const isStartWithUnderscore = s?.startsWith("_");
242
+ function camel(s = "") {
243
+ const isStartWithUnderscore = s.startsWith("_");
363
244
  const camelString = decap(pascal(s), isStartWithUnderscore ? 1 : 0);
364
245
  return isStartWithUnderscore ? `_${camelString}` : camelString;
365
246
  }
@@ -370,7 +251,7 @@ function kebab(s) {
370
251
  return lower(s, "-", true);
371
252
  }
372
253
  function upper(s, fillWith, isDeapostrophe) {
373
- return fill(up.call(prep(s, !!fillWith, false, true)), fillWith, isDeapostrophe);
254
+ return fill(up(prep(s, !!fillWith, false, true)), fillWith, isDeapostrophe);
374
255
  }
375
256
  function conventionName(name, convention) {
376
257
  let nameConventionTransform = camel;
@@ -388,6 +269,14 @@ function conventionName(name, convention) {
388
269
  return nameConventionTransform(name);
389
270
  }
390
271
 
272
+ //#endregion
273
+ //#region src/utils/compare-version.ts
274
+ function compareVersions(firstVersion, secondVersions, operator = ">=") {
275
+ if (firstVersion === "latest" || firstVersion === "*") return true;
276
+ if (firstVersion.startsWith("catalog:")) return true;
277
+ return compare(firstVersion.replace(/(\s(.*))/, ""), secondVersions, operator);
278
+ }
279
+
391
280
  //#endregion
392
281
  //#region src/utils/content-type.ts
393
282
  /**
@@ -435,16 +324,38 @@ function isBinaryContentType(contentType) {
435
324
  function getFormDataFieldFileType(resolvedSchema, partContentType) {
436
325
  if (resolvedSchema.type !== "string") return;
437
326
  if (resolvedSchema.contentEncoding) return;
438
- const effectiveContentType = partContentType ?? resolvedSchema.contentMediaType;
327
+ const contentMediaType = resolvedSchema.contentMediaType;
328
+ const effectiveContentType = partContentType ?? contentMediaType;
439
329
  if (effectiveContentType) return isBinaryContentType(effectiveContentType) ? "binary" : "text";
440
330
  }
441
-
442
- //#endregion
443
- //#region src/utils/compare-version.ts
444
- function compareVersions(firstVersion, secondVersions, operator = ">=") {
445
- if (firstVersion === "latest" || firstVersion === "*") return true;
446
- if (firstVersion.startsWith("catalog:")) return true;
447
- return compare(firstVersion.replace(/(\s(.*))/, ""), secondVersions, operator);
331
+ /**
332
+ * Filters items by content type based on include/exclude rules
333
+ *
334
+ * @param items - Array of items with contentType property
335
+ * @param filter - Optional filter configuration
336
+ * @returns Filtered array
337
+ *
338
+ * @example
339
+ * ```ts
340
+ * const types = [
341
+ * { contentType: 'application/json', value: '...' },
342
+ * { contentType: 'text/xml', value: '...' }
343
+ * ];
344
+ *
345
+ * // Include only JSON
346
+ * filterByContentType(types, { include: ['application/json'] });
347
+ *
348
+ * // Exclude XML
349
+ * filterByContentType(types, { exclude: ['text/xml'] });
350
+ * ```
351
+ */
352
+ function filterByContentType(items, filter$1) {
353
+ if (!filter$1) return items;
354
+ return items.filter((item) => {
355
+ const shouldInclude = !filter$1.include || filter$1.include.includes(item.contentType);
356
+ const shouldExclude = filter$1.exclude?.includes(item.contentType) ?? false;
357
+ return shouldInclude && !shouldExclude;
358
+ });
448
359
  }
449
360
 
450
361
  //#endregion
@@ -454,7 +365,7 @@ const DEBUG = process.env.DEBUG;
454
365
  function createDebugger(ns, options = {}) {
455
366
  const log$1 = debug(ns);
456
367
  const { onlyWhenFocused } = options;
457
- const focus = typeof onlyWhenFocused === "string" ? onlyWhenFocused : ns;
368
+ const focus = isString(onlyWhenFocused) ? onlyWhenFocused : ns;
458
369
  return (msg, ...args) => {
459
370
  if (filter && !msg.includes(filter)) return;
460
371
  if (onlyWhenFocused && !DEBUG?.includes(focus)) return;
@@ -468,13 +379,13 @@ const search = String.raw`\*/`;
468
379
  const replacement = String.raw`*\/`;
469
380
  const regex$1 = new RegExp(search, "g");
470
381
  function jsDoc(schema, tryOneLine = false, context) {
471
- if (context?.output?.override?.jsDoc) {
382
+ if (context?.output.override.jsDoc) {
472
383
  const { filter: filter$1 } = context.output.override.jsDoc;
473
384
  if (filter$1) return keyValuePairsToJsDoc(filter$1(schema));
474
385
  }
475
386
  const { description, deprecated, summary, minLength, maxLength, minimum, maximum, exclusiveMinimum, exclusiveMaximum, minItems, maxItems, pattern } = schema;
476
387
  const isNullable = schema.type === "null" || Array.isArray(schema.type) && schema.type.includes("null");
477
- const lines = (Array.isArray(description) ? description.filter((d) => !d.includes("eslint-disable")) : [description || ""]).map((line) => line.replaceAll(regex$1, replacement));
388
+ const lines = (Array.isArray(description) ? description.filter((d) => !d.includes("eslint-disable")) : [description ?? ""]).map((line) => line.replaceAll(regex$1, replacement));
478
389
  const count$1 = [
479
390
  description,
480
391
  deprecated,
@@ -489,7 +400,7 @@ function jsDoc(schema, tryOneLine = false, context) {
489
400
  maxItems?.toString(),
490
401
  isNullable ? "null" : "",
491
402
  pattern
492
- ].reduce((acc, it) => it ? acc + 1 : acc, 0);
403
+ ].filter(Boolean).length;
493
404
  if (!count$1) return "";
494
405
  const oneLine = count$1 === 1 && tryOneLine;
495
406
  const eslintDisable = Array.isArray(description) ? description.find((d) => d.includes("eslint-disable"))?.replaceAll(regex$1, replacement) : void 0;
@@ -556,10 +467,49 @@ async function dynamicImport(toImport, from = process.cwd(), takeDefault = true)
556
467
  }
557
468
  return toImport;
558
469
  } catch (error) {
559
- throw new Error(`Oups... 🍻. Path: ${toImport} => ${error}`);
470
+ throw new Error(`Oups... 🍻. Path: ${String(toImport)} => ${String(error)}`);
560
471
  }
561
472
  }
562
473
 
474
+ //#endregion
475
+ //#region src/utils/extension.ts
476
+ function getExtension(path$2) {
477
+ return path$2.toLowerCase().includes(".yaml") || path$2.toLowerCase().includes(".yml") ? "yaml" : "json";
478
+ }
479
+
480
+ //#endregion
481
+ //#region src/utils/file.ts
482
+ function getFileInfo(target = "", { backupFilename = "filename", extension = ".ts" } = {}) {
483
+ const isDir = isDirectory(target);
484
+ const filePath = isDir ? path.join(target, backupFilename + extension) : target;
485
+ return {
486
+ path: filePath,
487
+ pathWithoutExtension: filePath.replace(/\.[^/.]+$/, ""),
488
+ extension,
489
+ isDirectory: isDir,
490
+ dirname: path.dirname(filePath),
491
+ filename: path.basename(filePath, extension.startsWith(".") ? extension : `.${extension}`)
492
+ };
493
+ }
494
+ async function removeFilesAndEmptyFolders(patterns, dir) {
495
+ const files = await globby(patterns, {
496
+ cwd: dir,
497
+ absolute: true
498
+ });
499
+ await Promise.all(files.map((file) => fs.promises.unlink(file)));
500
+ const sortedDirectories = (await globby(["**/*"], {
501
+ cwd: dir,
502
+ absolute: true,
503
+ onlyDirectories: true
504
+ })).toSorted((a, b) => {
505
+ const depthA = a.split("/").length;
506
+ return b.split("/").length - depthA;
507
+ });
508
+ for (const directory of sortedDirectories) try {
509
+ if ((await fs.promises.readdir(directory)).length === 0) await fs.promises.rmdir(directory);
510
+ } catch {}
511
+ }
512
+
563
513
  //#endregion
564
514
  //#region src/utils/file-extensions.ts
565
515
  function getMockFileExtensionByTypeName(mock) {
@@ -608,7 +558,7 @@ function logError(err, tag) {
608
558
  if (err instanceof Error) {
609
559
  message = (err.message || err.stack) ?? "Unknown error";
610
560
  if (err.cause) {
611
- const causeMsg = err.cause instanceof Error ? err.cause.message : typeof err.cause === "string" ? err.cause : JSON.stringify(err.cause, void 0, 2);
561
+ const causeMsg = err.cause instanceof Error ? err.cause.message : isString(err.cause) ? err.cause : JSON.stringify(err.cause, void 0, 2);
612
562
  message += `\n Cause: ${causeMsg}`;
613
563
  }
614
564
  } else message = String(err);
@@ -695,16 +645,16 @@ function createLogger(level = "info", options = {}) {
695
645
 
696
646
  //#endregion
697
647
  //#region src/utils/merge-deep.ts
698
- const isObject$1 = (obj) => obj && typeof obj === "object";
699
648
  function mergeDeep(source, target) {
700
- if (!isObject$1(target) || !isObject$1(source)) return source;
701
- return Object.entries(target).reduce((acc, [key, value]) => {
649
+ if (!isObject(target) || !isObject(source)) return source;
650
+ const acc = Object.assign({}, source);
651
+ for (const [key, value] of Object.entries(target)) {
702
652
  const sourceValue = acc[key];
703
653
  if (Array.isArray(sourceValue) && Array.isArray(value)) acc[key] = [...sourceValue, ...value];
704
- else if (isObject$1(sourceValue) && isObject$1(value)) acc[key] = mergeDeep(sourceValue, value);
654
+ else if (isObject(sourceValue) && isObject(value)) acc[key] = mergeDeep(sourceValue, value);
705
655
  else acc[key] = value;
706
- return acc;
707
- }, Object.assign({}, source));
656
+ }
657
+ return acc;
708
658
  }
709
659
 
710
660
  //#endregion
@@ -714,9 +664,65 @@ function count(str = "", key) {
714
664
  return (str.match(new RegExp(key, "g")) ?? []).length;
715
665
  }
716
666
 
667
+ //#endregion
668
+ //#region src/utils/path.ts
669
+ var path_exports = /* @__PURE__ */ __export({
670
+ basename: () => basename,
671
+ dirname: () => dirname,
672
+ extname: () => extname,
673
+ getSchemaFileName: () => getSchemaFileName,
674
+ isAbsolute: () => isAbsolute,
675
+ join: () => join,
676
+ joinSafe: () => joinSafe,
677
+ normalizeSafe: () => normalizeSafe,
678
+ relativeSafe: () => relativeSafe,
679
+ resolve: () => resolve,
680
+ separator: () => separator
681
+ });
682
+ function wrapPathFn(fn) {
683
+ return (...args) => {
684
+ const result = fn(...args.map((p) => isStringLike(p) ? toUnix(p) : p));
685
+ return isStringLike(result) ? toUnix(result) : result;
686
+ };
687
+ }
688
+ const path$1 = Object.fromEntries(Object.entries(path).map(([key, value]) => [key, isFunction(value) ? wrapPathFn(value) : value]));
689
+ const { join, resolve, extname, dirname, basename, isAbsolute } = path$1;
690
+ /**
691
+ * Behaves exactly like `path.relative(from, to)`, but keeps the first meaningful "./"
692
+ */
693
+ function relativeSafe(from, to) {
694
+ return normalizeSafe(`.${separator}${path$1.relative(from, to)}`);
695
+ }
696
+ function getSchemaFileName(path$2) {
697
+ return path$2.replace(`.${getExtension(path$2)}`, "").slice(path$2.lastIndexOf("/") + 1);
698
+ }
699
+ const separator = "/";
700
+ const toUnix = function(value) {
701
+ value = value.replaceAll("\\", "/");
702
+ value = value.replaceAll(/(?<!^)\/+/g, "/");
703
+ return value;
704
+ };
705
+ function normalizeSafe(value) {
706
+ let result;
707
+ value = toUnix(value);
708
+ result = path$1.normalize(value);
709
+ if (value.startsWith("./") && !result.startsWith("./") && !result.startsWith("..")) result = "./" + result;
710
+ else if (value.startsWith("//") && !result.startsWith("//")) result = value.startsWith("//./") ? "//." + result : "/" + result;
711
+ return result;
712
+ }
713
+ function joinSafe(...values) {
714
+ let result = path$1.join(...values);
715
+ if (values.length > 0) {
716
+ const firstValue = toUnix(values[0]);
717
+ if (firstValue.startsWith("./") && !result.startsWith("./") && !result.startsWith("..")) result = "./" + result;
718
+ else if (firstValue.startsWith("//") && !result.startsWith("//")) result = firstValue.startsWith("//./") ? "//." + result : "/" + result;
719
+ }
720
+ return result;
721
+ }
722
+
717
723
  //#endregion
718
724
  //#region src/utils/sort.ts
719
- const sortByPriority = (arr) => arr.sort((a, b) => {
725
+ const sortByPriority = (arr) => arr.toSorted((a, b) => {
720
726
  if (a.default) return 1;
721
727
  if (b.default) return -1;
722
728
  if (a.required && b.required) return 0;
@@ -740,17 +746,20 @@ const sortByPriority = (arr) => arr.sort((a, b) => {
740
746
  * stringify({ a: 1, b: 'test' }) // returns "{ a: 1, b: 'test', }"
741
747
  */
742
748
  function stringify(data) {
743
- if (isUndefined(data) || isNull(data)) return;
749
+ if (isNullish$1(data)) return;
744
750
  if (isString(data)) return `'${data.replaceAll("'", String.raw`\'`)}'`;
745
- if (isNumber(data) || isBoolean(data) || isFunction(data)) return `${data}`;
746
- if (Array.isArray(data)) return `[${data.map(stringify).join(", ")}]`;
747
- return Object.entries(data).reduce((acc, [key, value], index, arr) => {
751
+ if (isNumber(data) || isBoolean(data) || isFunction(data)) return String(data);
752
+ if (Array.isArray(data)) return `[${data.map((item) => stringify(item)).join(", ")}]`;
753
+ const entries$1 = Object.entries(data);
754
+ let result = "";
755
+ for (const [index, [key, value]] of entries$1.entries()) {
748
756
  const strValue = stringify(value);
749
- if (arr.length === 1) return `{ ${key}: ${strValue}, }`;
750
- if (!index) return `{ ${key}: ${strValue}, `;
751
- if (arr.length - 1 === index) return acc + `${key}: ${strValue}, }`;
752
- return acc + `${key}: ${strValue}, `;
753
- }, "");
757
+ if (entries$1.length === 1) result = `{ ${key}: ${strValue}, }`;
758
+ else if (!index) result = `{ ${key}: ${strValue}, `;
759
+ else if (entries$1.length - 1 === index) result += `${key}: ${strValue}, }`;
760
+ else result += `${key}: ${strValue}, `;
761
+ }
762
+ return result;
754
763
  }
755
764
  /**
756
765
  * Sanitizes a string value by removing or replacing special characters and ensuring
@@ -774,7 +783,7 @@ function stringify(data) {
774
783
  function sanitize(value, options) {
775
784
  const { whitespace = "", underscore = "", dot = "", dash = "", es5keyword = false, es5IdentifierName = false, special = false } = options ?? {};
776
785
  let newValue = value;
777
- if (!special) newValue = newValue.replaceAll(/[!"`'#%&,:;<>=@{}~\$\(\)\*\+\/\\\?\[\]\^\|]/g, "");
786
+ if (!special) newValue = newValue.replaceAll(/[!"`'#%&,:;<>=@{}~$()*+/\\?[\]^|]/g, "");
778
787
  if (whitespace !== true) newValue = newValue.replaceAll(/[\s]/g, whitespace);
779
788
  if (underscore !== true) newValue = newValue.replaceAll(/['_']/g, underscore);
780
789
  if (dot !== true) newValue = newValue.replaceAll(/[.]/g, dot);
@@ -799,7 +808,11 @@ function sanitize(value, options) {
799
808
  */
800
809
  function toObjectString(props, path$2) {
801
810
  if (props.length === 0) return "";
802
- return (typeof path$2 === "string" ? props.map((prop$1) => path$2.split(".").reduce((obj, key) => obj && typeof obj === "object" ? obj[key] : void 0, prop$1)) : props).join(",\n ") + ",";
811
+ return (isString(path$2) ? props.map((prop$1) => {
812
+ let obj = prop$1;
813
+ for (const key of path$2.split(".")) obj = obj && (isObject(obj) || Array.isArray(obj)) ? obj[key] : void 0;
814
+ return obj;
815
+ }) : props).join(",\n ") + ",";
803
816
  }
804
817
  const NUMBERS = {
805
818
  "0": "zero",
@@ -823,7 +836,7 @@ const NUMBERS = {
823
836
  * getNumberWord(42) // returns "fourtwo"
824
837
  */
825
838
  function getNumberWord(num) {
826
- return num.toString().split("").reduce((acc, n) => acc + NUMBERS[n], "");
839
+ return [...num.toString()].reduce((acc, n) => acc + NUMBERS[n], "");
827
840
  }
828
841
  /**
829
842
  * Escapes a specific character in a string by prefixing it with a backslash.
@@ -917,8 +930,7 @@ function getEnumDescriptions(schemaObject) {
917
930
  function getEnum(value, enumName, names, enumGenerationType, descriptions, enumNamingConvention) {
918
931
  if (enumGenerationType === EnumGeneration.CONST) return getTypeConstEnum(value, enumName, names, descriptions, enumNamingConvention);
919
932
  if (enumGenerationType === EnumGeneration.ENUM) return getNativeEnum(value, enumName, names, enumNamingConvention);
920
- if (enumGenerationType === EnumGeneration.UNION) return getUnion(value, enumName);
921
- throw new Error(`Invalid enumGenerationType: ${enumGenerationType}`);
933
+ return getUnion(value, enumName);
922
934
  }
923
935
  const getTypeConstEnum = (value, enumName, names, descriptions, enumNamingConvention) => {
924
936
  let enumValue = `export type ${enumName} = typeof ${enumName}[keyof typeof ${enumName}]`;
@@ -934,11 +946,16 @@ const getTypeConstEnum = (value, enumName, names, descriptions, enumNamingConven
934
946
  };
935
947
  function getEnumImplementation(value, names, descriptions, enumNamingConvention) {
936
948
  if (value === "") return "";
937
- return [...new Set(value.split(" | "))].reduce((acc, val, index) => {
949
+ const uniqueValues = [...new Set(value.split(" | "))];
950
+ let result = "";
951
+ for (const [index, val] of uniqueValues.entries()) {
938
952
  const name = names?.[index];
939
953
  const description = descriptions?.[index];
940
954
  const comment = description ? ` /** ${description} */\n` : "";
941
- if (name) return acc + comment + ` ${keyword.isIdentifierNameES5(name) ? name : `'${name}'`}: ${val},\n`;
955
+ if (name) {
956
+ result += comment + ` ${keyword.isIdentifierNameES5(name) ? name : `'${name}'`}: ${val},\n`;
957
+ continue;
958
+ }
942
959
  let key = val.startsWith("'") ? val.slice(1, -1) : val;
943
960
  if (isNumeric(key)) key = toNumberKey(key);
944
961
  if (key.length > 1) key = sanitize(key, {
@@ -948,17 +965,23 @@ function getEnumImplementation(value, names, descriptions, enumNamingConvention)
948
965
  special: true
949
966
  });
950
967
  if (enumNamingConvention) key = conventionName(key, enumNamingConvention);
951
- return acc + comment + ` ${keyword.isIdentifierNameES5(key) ? key : `'${key}'`}: ${val},\n`;
952
- }, "");
968
+ result += comment + ` ${keyword.isIdentifierNameES5(key) ? key : `'${key}'`}: ${val},\n`;
969
+ }
970
+ return result;
953
971
  }
954
972
  const getNativeEnum = (value, enumName, names, enumNamingConvention) => {
955
973
  return `export enum ${enumName} {\n${getNativeEnumItems(value, names, enumNamingConvention)}\n}`;
956
974
  };
957
975
  const getNativeEnumItems = (value, names, enumNamingConvention) => {
958
976
  if (value === "") return "";
959
- return [...new Set(value.split(" | "))].reduce((acc, val, index) => {
977
+ const uniqueValues = [...new Set(value.split(" | "))];
978
+ let result = "";
979
+ for (const [index, val] of uniqueValues.entries()) {
960
980
  const name = names?.[index];
961
- if (name) return acc + ` ${keyword.isIdentifierNameES5(name) ? name : `'${name}'`}= ${val},\n`;
981
+ if (name) {
982
+ result += ` ${keyword.isIdentifierNameES5(name) ? name : `'${name}'`}= ${val},\n`;
983
+ continue;
984
+ }
962
985
  let key = val.startsWith("'") ? val.slice(1, -1) : val;
963
986
  if (isNumeric(key)) key = toNumberKey(key);
964
987
  if (key.length > 1) key = sanitize(key, {
@@ -968,8 +991,9 @@ const getNativeEnumItems = (value, names, enumNamingConvention) => {
968
991
  special: true
969
992
  });
970
993
  if (enumNamingConvention) key = conventionName(key, enumNamingConvention);
971
- return acc + ` ${keyword.isIdentifierNameES5(key) ? key : `'${key}'`}= ${val},\n`;
972
- }, "");
994
+ result += ` ${keyword.isIdentifierNameES5(key) ? key : `'${key}'`}= ${val},\n`;
995
+ }
996
+ return result;
973
997
  };
974
998
  const toNumberKey = (value) => {
975
999
  if (value.startsWith("-")) return `NUMBER_MINUS_${value.slice(1)}`;
@@ -981,9 +1005,9 @@ const getUnion = (value, enumName) => {
981
1005
  };
982
1006
  function getEnumUnionFromSchema(schema) {
983
1007
  if (!schema?.enum) return "";
984
- return schema.enum.filter((val) => val !== null).map((val) => isString(val) ? `'${escape(val)}'` : `${val}`).join(" | ");
1008
+ return schema.enum.filter((val) => val !== null).map((val) => isString(val) ? `'${escape(val)}'` : String(val)).join(" | ");
985
1009
  }
986
- const stripNullUnion = (value) => value.replace(/\s*\|\s*null/g, "").trim();
1010
+ const stripNullUnion = (value) => value.replaceAll(/\s*\|\s*null/g, "").trim();
987
1011
  const isSpreadableEnumRef = (schema, refName) => {
988
1012
  if (!schema?.enum || !refName) return false;
989
1013
  if (!getEnumUnionFromSchema(schema)) return false;
@@ -1129,17 +1153,23 @@ function getSchema$1(schema, context) {
1129
1153
  const refInfo = getRefInfo(schema.$ref, context);
1130
1154
  const { refPaths } = refInfo;
1131
1155
  let schemaByRefPaths = Array.isArray(refPaths) ? prop(context.spec, ...refPaths) : void 0;
1132
- if (!schemaByRefPaths) schemaByRefPaths = context.spec;
1156
+ schemaByRefPaths ??= context.spec;
1133
1157
  if (isReference(schemaByRefPaths)) return getSchema$1(schemaByRefPaths, context);
1134
- let currentSchema = schemaByRefPaths ? schemaByRefPaths : context.spec;
1135
- if ("nullable" in schema) currentSchema = {
1136
- ...currentSchema,
1137
- nullable: schema.nullable
1138
- };
1139
- if ("type" in schema && Array.isArray(schema.type)) currentSchema = {
1140
- ...currentSchema,
1141
- type: schema.type
1142
- };
1158
+ let currentSchema = schemaByRefPaths || context.spec;
1159
+ if ("nullable" in schema) {
1160
+ const nullable = schema.nullable;
1161
+ currentSchema = {
1162
+ ...currentSchema,
1163
+ nullable
1164
+ };
1165
+ }
1166
+ if ("type" in schema && Array.isArray(schema.type)) {
1167
+ const type = schema.type;
1168
+ currentSchema = {
1169
+ ...currentSchema,
1170
+ type
1171
+ };
1172
+ }
1143
1173
  return {
1144
1174
  currentSchema,
1145
1175
  refInfo
@@ -1153,14 +1183,11 @@ function resolveExampleRefs(examples, context) {
1153
1183
  return schema.value;
1154
1184
  }
1155
1185
  return example;
1156
- }) : Object.entries(examples).reduce((acc, [key, example]) => {
1157
- let schema = example;
1158
- if (isReference(example)) schema = resolveRef(example, context).schema.value;
1159
- return {
1160
- ...acc,
1161
- [key]: schema
1162
- };
1163
- }, {});
1186
+ }) : (() => {
1187
+ const result = {};
1188
+ for (const [key, example] of Object.entries(examples)) result[key] = isReference(example) ? resolveRef(example, context).schema.value : example;
1189
+ return result;
1190
+ })();
1164
1191
  }
1165
1192
 
1166
1193
  //#endregion
@@ -1179,7 +1206,8 @@ function resolveValue({ schema, name, context, formDataContext }) {
1179
1206
  parents: [...context.parents ?? [], refName]
1180
1207
  }
1181
1208
  }).hasReadonlyProps;
1182
- const nullable = Array.isArray(schemaObject.type) && schemaObject.type.includes("null") || schemaObject.nullable === true ? " | null" : "";
1209
+ const isAnyOfNullable = schemaObject.anyOf?.some((anyOfItem) => !isReference(anyOfItem) && (anyOfItem.type === "null" || Array.isArray(anyOfItem.type) && anyOfItem.type.includes("null")));
1210
+ const nullable = Array.isArray(schemaObject.type) && schemaObject.type.includes("null") || schemaObject.nullable === true || isAnyOfNullable ? " | null" : "";
1183
1211
  return {
1184
1212
  value: resolvedImport.name + nullable,
1185
1213
  imports: [{
@@ -1216,7 +1244,7 @@ function resolveValue({ schema, name, context, formDataContext }) {
1216
1244
  function createTypeAliasIfNeeded({ resolvedValue, propName, context }) {
1217
1245
  if (!propName) return;
1218
1246
  if (resolvedValue.isEnum || resolvedValue.type !== "object") return;
1219
- const aliasPattern = context.output.override.aliasCombinedTypes ? "{|&|\\|" : "{";
1247
+ const aliasPattern = context.output.override.aliasCombinedTypes ? String.raw`{|&|\|` : "{";
1220
1248
  if (!new RegExp(aliasPattern).test(resolvedValue.value)) return;
1221
1249
  const { originalSchema } = resolvedValue;
1222
1250
  const doc = jsDoc(originalSchema);
@@ -1259,8 +1287,8 @@ function resolveObjectOriginal({ schema, propName, combined = false, context, fo
1259
1287
  originalSchema: resolvedValue.originalSchema
1260
1288
  };
1261
1289
  if (propName && resolvedValue.isEnum && !combined && !resolvedValue.isRef) {
1262
- const doc = jsDoc(resolvedValue.originalSchema ?? {});
1263
- const enumValue = getEnum(resolvedValue.value, propName, getEnumNames(resolvedValue.originalSchema), context.output.override.enumGenerationType, getEnumDescriptions(resolvedValue.originalSchema), context.output.override.namingConvention?.enum);
1290
+ const doc = jsDoc(resolvedValue.originalSchema);
1291
+ const enumValue = getEnum(resolvedValue.value, propName, getEnumNames(resolvedValue.originalSchema), context.output.override.enumGenerationType, getEnumDescriptions(resolvedValue.originalSchema), context.output.override.namingConvention.enum);
1264
1292
  return {
1265
1293
  value: propName,
1266
1294
  imports: [{ name: propName }],
@@ -1309,17 +1337,20 @@ function resolveObject({ schema, propName, combined = false, context, formDataCo
1309
1337
  * @param item item with type === "array"
1310
1338
  */
1311
1339
  function getArray({ schema, name, context, formDataContext }) {
1312
- const schema31 = schema;
1340
+ const schemaPrefixItems = schema.prefixItems;
1341
+ const schemaItems = schema.items;
1342
+ const schemaExample = schema.example;
1343
+ const schemaExamples = schema.examples;
1313
1344
  const itemSuffix = context.output.override.components.schemas.itemSuffix;
1314
- if (schema31.prefixItems) {
1315
- const resolvedObjects = schema31.prefixItems.map((item, index) => resolveObject({
1345
+ if (schemaPrefixItems) {
1346
+ const resolvedObjects = schemaPrefixItems.map((item, index) => resolveObject({
1316
1347
  schema: item,
1317
- propName: name ? name + itemSuffix + index : void 0,
1348
+ propName: name ? name + itemSuffix + String(index) : void 0,
1318
1349
  context
1319
1350
  }));
1320
- if (schema31.items) {
1351
+ if (schemaItems) {
1321
1352
  const additional = resolveObject({
1322
- schema: schema31.items,
1353
+ schema: schemaItems,
1323
1354
  propName: name ? name + itemSuffix + "Additional" : void 0,
1324
1355
  context
1325
1356
  });
@@ -1337,13 +1368,13 @@ function getArray({ schema, name, context, formDataContext }) {
1337
1368
  schemas: resolvedObjects.flatMap((o) => o.schemas),
1338
1369
  dependencies: resolvedObjects.flatMap((o) => o.dependencies),
1339
1370
  hasReadonlyProps: resolvedObjects.some((o) => o.hasReadonlyProps),
1340
- example: schema.example,
1341
- examples: resolveExampleRefs(schema.examples, context)
1371
+ example: schemaExample,
1372
+ examples: resolveExampleRefs(schemaExamples, context)
1342
1373
  };
1343
1374
  }
1344
- if (schema.items) {
1375
+ if (schemaItems) {
1345
1376
  const resolvedObject = resolveObject({
1346
- schema: schema.items,
1377
+ schema: schemaItems,
1347
1378
  propName: name ? name + itemSuffix : void 0,
1348
1379
  context,
1349
1380
  formDataContext
@@ -1357,8 +1388,8 @@ function getArray({ schema, name, context, formDataContext }) {
1357
1388
  type: "array",
1358
1389
  isRef: false,
1359
1390
  hasReadonlyProps: resolvedObject.hasReadonlyProps,
1360
- example: schema.example,
1361
- examples: resolveExampleRefs(schema.examples, context)
1391
+ example: schemaExample,
1392
+ examples: resolveExampleRefs(schemaExamples, context)
1362
1393
  };
1363
1394
  } else if (compareVersions(context.spec.openapi, "3.1", ">=")) return {
1364
1395
  value: "unknown[]",
@@ -1375,6 +1406,13 @@ function getArray({ schema, name, context, formDataContext }) {
1375
1406
 
1376
1407
  //#endregion
1377
1408
  //#region src/getters/res-req-types.ts
1409
+ const getSchemaType = (s) => s.type;
1410
+ const getSchemaCombined = (s) => s.oneOf ?? s.anyOf ?? s.allOf;
1411
+ const getSchemaOneOf = (s) => s.oneOf;
1412
+ const getSchemaAnyOf = (s) => s.anyOf;
1413
+ const getSchemaItems = (s) => s.items;
1414
+ const getSchemaRequired = (s) => s.required;
1415
+ const getSchemaProperties = (s) => s.properties;
1378
1416
  const formDataContentTypes = new Set(["multipart/form-data"]);
1379
1417
  const formUrlEncodedContentTypes = new Set(["application/x-www-form-urlencoded"]);
1380
1418
  function getResReqContentTypes({ mediaType, propName, context, isFormData, contentType }) {
@@ -1396,7 +1434,7 @@ function getResReqContentTypes({ mediaType, propName, context, isFormData, conte
1396
1434
  return resolvedObject;
1397
1435
  }
1398
1436
  function getResReqTypes(responsesOrRequests, name, context, defaultType = "unknown", uniqueKey = (item) => item.value) {
1399
- return uniqueBy(responsesOrRequests.filter(([_, res]) => Boolean(res)).map(([key, res]) => {
1437
+ return uniqueBy(responsesOrRequests.filter(([, res]) => Boolean(res)).map(([key, res]) => {
1400
1438
  if (isReference(res)) {
1401
1439
  const { schema: bodySchema, imports: [{ name: name$1, schemaName }] } = resolveRef(res, context);
1402
1440
  const [contentType, mediaType] = Object.entries(bodySchema.content ?? {})[0] ?? [];
@@ -1413,9 +1451,9 @@ function getResReqTypes(responsesOrRequests, name, context, defaultType = "unkno
1413
1451
  isEnum: false,
1414
1452
  isRef: true,
1415
1453
  hasReadonlyProps: false,
1416
- originalSchema: mediaType?.schema,
1417
- example: mediaType?.example,
1418
- examples: resolveExampleRefs(mediaType?.examples, context),
1454
+ originalSchema: mediaType.schema,
1455
+ example: mediaType.example,
1456
+ examples: resolveExampleRefs(mediaType.examples, context),
1419
1457
  key,
1420
1458
  contentType
1421
1459
  }];
@@ -1491,7 +1529,7 @@ function getResReqTypes(responsesOrRequests, name, context, defaultType = "unkno
1491
1529
  return;
1492
1530
  }
1493
1531
  const isFormUrlEncoded = formUrlEncodedContentTypes.has(contentType);
1494
- if (!isFormData && !isFormUrlEncoded || !effectivePropName) return {
1532
+ if (!isFormData && !isFormUrlEncoded || !effectivePropName || !mediaType.schema) return {
1495
1533
  ...resolvedValue,
1496
1534
  imports: resolvedValue.imports,
1497
1535
  contentType,
@@ -1584,9 +1622,9 @@ function getDefaultContentType(contentTypes) {
1584
1622
  function getFormDataAdditionalImports({ schemaObject, context }) {
1585
1623
  const { schema } = resolveRef(schemaObject, context);
1586
1624
  if (schema.type !== "object") return [];
1587
- const combinedSchemas = schema.oneOf || schema.anyOf;
1625
+ const combinedSchemas = getSchemaOneOf(schema) ?? getSchemaAnyOf(schema);
1588
1626
  if (!combinedSchemas) return [];
1589
- return combinedSchemas.map((schema$1) => resolveRef(schema$1, context).imports[0]).filter(Boolean);
1627
+ return combinedSchemas.map((subSchema) => resolveRef(subSchema, context).imports[0]).filter(Boolean);
1590
1628
  }
1591
1629
  function getSchemaFormDataAndUrlEncoded({ name, schemaObject, context, isRequestBodyOptional, isUrlEncoded, isRef, encoding }) {
1592
1630
  const { schema, imports } = resolveRef(schemaObject, context);
@@ -1594,12 +1632,12 @@ function getSchemaFormDataAndUrlEncoded({ name, schemaObject, context, isRequest
1594
1632
  const additionalImports = [];
1595
1633
  const variableName = isUrlEncoded ? "formUrlEncoded" : "formData";
1596
1634
  let form = isUrlEncoded ? `const ${variableName} = new URLSearchParams();\n` : `const ${variableName} = new FormData();\n`;
1597
- const combinedSchemas = schema.oneOf || schema.anyOf || schema.allOf;
1635
+ const combinedSchemas = getSchemaCombined(schema);
1598
1636
  if (schema.type === "object" || schema.type === void 0 && combinedSchemas) {
1599
1637
  if (combinedSchemas) {
1600
- const shouldCast = !!schema.oneOf || !!schema.anyOf;
1601
- const combinedSchemasFormData = combinedSchemas.map((schema$1) => {
1602
- const { schema: combinedSchema, imports: imports$1 } = resolveRef(schema$1, context);
1638
+ const shouldCast = !!getSchemaOneOf(schema) || !!getSchemaAnyOf(schema);
1639
+ const combinedSchemasFormData = combinedSchemas.map((subSchema) => {
1640
+ const { schema: combinedSchema, imports: imports$1 } = resolveRef(subSchema, context);
1603
1641
  let newPropName = propName;
1604
1642
  let newPropDefinition = "";
1605
1643
  if (shouldCast && imports$1[0]) {
@@ -1633,8 +1671,9 @@ function getSchemaFormDataAndUrlEncoded({ name, schemaObject, context, isRequest
1633
1671
  }
1634
1672
  if (schema.type === "array") {
1635
1673
  let valueStr = "value";
1636
- if (schema.items) {
1637
- const { schema: itemSchema } = resolveRef(schema.items, context);
1674
+ const schemaItems = getSchemaItems(schema);
1675
+ if (schemaItems) {
1676
+ const { schema: itemSchema } = resolveRef(schemaItems, context);
1638
1677
  if (itemSchema.type === "object" || itemSchema.type === "array") valueStr = "JSON.stringify(value)";
1639
1678
  else if (itemSchema.type === "number" || itemSchema.type === "integer" || itemSchema.type === "boolean") valueStr = "value.toString()";
1640
1679
  }
@@ -1644,9 +1683,11 @@ function getSchemaFormDataAndUrlEncoded({ name, schemaObject, context, isRequest
1644
1683
  return `${form}${variableName}.append('data', ${propName})\n`;
1645
1684
  }
1646
1685
  function resolveSchemaPropertiesToFormData({ schema, variableName, propName, context, isRequestBodyOptional, keyPrefix = "", depth = 0, encoding }) {
1647
- return Object.entries(schema.properties ?? {}).reduce((acc, [key, value]) => {
1686
+ let formDataValues = "";
1687
+ const schemaProps = getSchemaProperties(schema) ?? {};
1688
+ for (const [key, value] of Object.entries(schemaProps)) {
1648
1689
  const { schema: property } = resolveRef(value, context);
1649
- if (property.readOnly) return acc;
1690
+ if (property.readOnly) continue;
1650
1691
  let formDataValue = "";
1651
1692
  const partContentType = (depth === 0 ? encoding?.[key] : void 0)?.contentType;
1652
1693
  const formattedKeyPrefix = isRequestBodyOptional ? keyword.isIdentifierNameES5(key) ? "?" : "?." : "";
@@ -1670,8 +1711,9 @@ function resolveSchemaPropertiesToFormData({ schema, variableName, propName, con
1670
1711
  else if (property.type === "array") {
1671
1712
  let valueStr = "value";
1672
1713
  let hasNonPrimitiveChild = false;
1673
- if (property.items) {
1674
- const { schema: itemSchema } = resolveRef(property.items, context);
1714
+ const propertyItems = getSchemaItems(property);
1715
+ if (propertyItems) {
1716
+ const { schema: itemSchema } = resolveRef(propertyItems, context);
1675
1717
  if (itemSchema.type === "object" || itemSchema.type === "array") if (context.output.override.formData.arrayHandling === FormDataArrayHandling.EXPLODE) {
1676
1718
  hasNonPrimitiveChild = true;
1677
1719
  const resolvedValue = resolveSchemaPropertiesToFormData({
@@ -1686,52 +1728,69 @@ function resolveSchemaPropertiesToFormData({ schema, variableName, propName, con
1686
1728
  formDataValue = `${valueKey}.forEach((value, index${depth > 0 ? depth : ""}) => {
1687
1729
  ${resolvedValue}});\n`;
1688
1730
  } else valueStr = "JSON.stringify(value)";
1689
- else if (itemSchema.type === "number" || itemSchema.type?.includes("number") || itemSchema.type === "integer" || itemSchema.type?.includes("integer") || itemSchema.type === "boolean" || itemSchema.type?.includes("boolean")) valueStr = "value.toString()";
1731
+ else {
1732
+ const itemType = getSchemaType(itemSchema);
1733
+ if (itemType === "number" || Array.isArray(itemType) && itemType.includes("number") || itemType === "integer" || Array.isArray(itemType) && itemType.includes("integer") || itemType === "boolean" || Array.isArray(itemType) && itemType.includes("boolean")) valueStr = "value.toString()";
1734
+ }
1690
1735
  }
1691
1736
  if (context.output.override.formData.arrayHandling === FormDataArrayHandling.EXPLODE) {
1692
1737
  if (!hasNonPrimitiveChild) formDataValue = `${valueKey}.forEach((value, index${depth > 0 ? depth : ""}) => ${variableName}.append(\`${keyPrefix}${key}[\${index${depth > 0 ? depth : ""}}]\`, ${valueStr}));\n`;
1693
1738
  } else formDataValue = `${valueKey}.forEach(value => ${variableName}.append(\`${keyPrefix}${key}${context.output.override.formData.arrayHandling === FormDataArrayHandling.SERIALIZE_WITH_BRACKETS ? "[]" : ""}\`, ${valueStr}));\n`;
1694
- } else if (property.type === "number" || property.type?.includes("number") || property.type === "integer" || property.type?.includes("integer") || property.type === "boolean" || property.type?.includes("boolean")) formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey}.toString())\n`;
1739
+ } else if ((() => {
1740
+ const propType$1 = getSchemaType(property);
1741
+ return propType$1 === "number" || Array.isArray(propType$1) && propType$1.includes("number") || propType$1 === "integer" || Array.isArray(propType$1) && propType$1.includes("integer") || propType$1 === "boolean" || Array.isArray(propType$1) && propType$1.includes("boolean");
1742
+ })()) formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey}.toString())\n`;
1695
1743
  else formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey});\n`;
1696
1744
  let existSubSchemaNullable = false;
1697
- if (property.allOf || property.anyOf || property.oneOf) {
1698
- const subSchemas = (property.allOf || property.anyOf || property.oneOf)?.map((c) => resolveObject({
1745
+ const combine = getSchemaCombined(property);
1746
+ if (combine) {
1747
+ const subSchemas = combine.map((c) => resolveObject({
1699
1748
  schema: c,
1700
1749
  combined: true,
1701
1750
  context
1702
1751
  }));
1703
- if (subSchemas?.some((subSchema) => {
1752
+ if (subSchemas.some((subSchema) => {
1704
1753
  return [
1705
1754
  "number",
1706
1755
  "integer",
1707
1756
  "boolean"
1708
1757
  ].includes(subSchema.type);
1709
1758
  })) formDataValue = `${variableName}.append(\`${key}\`, ${nonOptionalValueKey}.toString())\n`;
1710
- if (subSchemas?.some((subSchema) => {
1759
+ if (subSchemas.some((subSchema) => {
1711
1760
  return subSchema.type === "null";
1712
1761
  })) existSubSchemaNullable = true;
1713
1762
  }
1714
- const isRequired = schema.required?.includes(key) && !isRequestBodyOptional;
1715
- if (property.nullable || property.type?.includes("null") || existSubSchemaNullable) {
1716
- if (isRequired) return acc + `if(${valueKey} !== null) {\n ${formDataValue} }\n`;
1717
- return acc + `if(${valueKey} !== undefined && ${nonOptionalValueKey} !== null) {\n ${formDataValue} }\n`;
1763
+ const isRequired = getSchemaRequired(schema)?.includes(key) && !isRequestBodyOptional;
1764
+ const propType = getSchemaType(property);
1765
+ if (property.nullable || Array.isArray(propType) && propType.includes("null") || existSubSchemaNullable) {
1766
+ if (isRequired) {
1767
+ formDataValues += `if(${valueKey} !== null) {\n ${formDataValue} }\n`;
1768
+ continue;
1769
+ }
1770
+ formDataValues += `if(${valueKey} !== undefined && ${nonOptionalValueKey} !== null) {\n ${formDataValue} }\n`;
1771
+ continue;
1772
+ }
1773
+ if (isRequired) {
1774
+ formDataValues += formDataValue;
1775
+ continue;
1718
1776
  }
1719
- if (isRequired) return acc + formDataValue;
1720
- return acc + `if(${valueKey} !== undefined) {\n ${formDataValue} }\n`;
1721
- }, "");
1777
+ formDataValues += `if(${valueKey} !== undefined) {\n ${formDataValue} }\n`;
1778
+ }
1779
+ return formDataValues;
1722
1780
  }
1723
1781
 
1724
1782
  //#endregion
1725
1783
  //#region src/getters/body.ts
1784
+ /**
1785
+ * Extract all content types from a requestBody (#2812)
1786
+ */
1787
+ function getRequestBodyContentTypes(requestBody, context) {
1788
+ if (!requestBody) return [];
1789
+ const content = (isReference(requestBody) ? resolveRef(requestBody, context).schema : requestBody).content;
1790
+ return content ? Object.keys(content) : [];
1791
+ }
1726
1792
  function getBody({ requestBody, operationName, context, contentType }) {
1727
- const allBodyTypes = getResReqTypes([[context.output.override.components.requestBodies.suffix, requestBody]], operationName, context);
1728
- const filteredBodyTypes = contentType ? allBodyTypes.filter((type) => {
1729
- let include = true;
1730
- let exclude = false;
1731
- if (contentType.include) include = contentType.include.includes(type.contentType);
1732
- if (contentType.exclude) exclude = contentType.exclude.includes(type.contentType);
1733
- return include && !exclude;
1734
- }) : allBodyTypes;
1793
+ const filteredBodyTypes = filterByContentType(getResReqTypes([[context.output.override.components.requestBodies.suffix, requestBody]], operationName, context), contentType);
1735
1794
  const imports = filteredBodyTypes.flatMap(({ imports: imports$1 }) => imports$1);
1736
1795
  const schemas = filteredBodyTypes.flatMap(({ schemas: schemas$1 }) => schemas$1);
1737
1796
  const definition = filteredBodyTypes.map(({ value }) => value).join(" | ");
@@ -1805,7 +1864,10 @@ function getKey(key) {
1805
1864
  * Returns undefined if propertyNames doesn't have an enum
1806
1865
  */
1807
1866
  function getPropertyNamesEnum(item) {
1808
- if ("propertyNames" in item && item.propertyNames && "enum" in item.propertyNames && Array.isArray(item.propertyNames.enum)) return item.propertyNames.enum.filter((val) => typeof val === "string");
1867
+ if ("propertyNames" in item && item.propertyNames && "enum" in item.propertyNames) {
1868
+ const propertyNames = item.propertyNames;
1869
+ if (Array.isArray(propertyNames.enum)) return propertyNames.enum.filter((val) => isString(val));
1870
+ }
1809
1871
  }
1810
1872
  /**
1811
1873
  * Generate index signature key type based on propertyNames enum
@@ -1850,23 +1912,43 @@ function getObject({ item, name, context, nullable, formDataContext }) {
1850
1912
  nullable,
1851
1913
  formDataContext
1852
1914
  });
1853
- if (Array.isArray(item.type)) return combineSchemas({
1854
- schema: { anyOf: item.type.map((type) => ({
1855
- ...item,
1856
- type
1857
- })) },
1858
- name,
1859
- separator: "anyOf",
1860
- context,
1861
- nullable
1862
- });
1863
- if (item.properties && Object.entries(item.properties).length > 0) {
1864
- const entries$1 = Object.entries(item.properties);
1915
+ if (Array.isArray(item.type)) {
1916
+ const typeArray = item.type;
1917
+ const baseItem = item;
1918
+ return combineSchemas({
1919
+ schema: { anyOf: typeArray.map((type) => ({
1920
+ ...baseItem,
1921
+ type
1922
+ })) },
1923
+ name,
1924
+ separator: "anyOf",
1925
+ context,
1926
+ nullable
1927
+ });
1928
+ }
1929
+ const itemProperties = item.properties;
1930
+ if (itemProperties && Object.entries(itemProperties).length > 0) {
1931
+ const entries$1 = Object.entries(itemProperties);
1865
1932
  if (context.output.propertySortOrder === PropertySortOrder.ALPHABETICAL) entries$1.sort((a, b) => {
1866
1933
  return a[0].localeCompare(b[0]);
1867
1934
  });
1868
- return entries$1.reduce((acc, [key, schema], index, arr) => {
1869
- const isRequired = (Array.isArray(item.required) ? item.required : []).includes(key);
1935
+ const acc = {
1936
+ imports: [],
1937
+ schemas: [],
1938
+ value: "",
1939
+ isEnum: false,
1940
+ type: "object",
1941
+ isRef: false,
1942
+ schema: {},
1943
+ hasReadonlyProps: false,
1944
+ useTypeAlias: false,
1945
+ dependencies: [],
1946
+ example: item.example,
1947
+ examples: resolveExampleRefs(item.examples, context)
1948
+ };
1949
+ const itemRequired = item.required;
1950
+ for (const [index, [key, schema]] of entries$1.entries()) {
1951
+ const isRequired = (Array.isArray(itemRequired) ? itemRequired : []).includes(key);
1870
1952
  let propName = "";
1871
1953
  if (name) {
1872
1954
  const isKeyStartWithUnderscore = key.startsWith("_");
@@ -1884,16 +1966,16 @@ function getObject({ item, name, context, nullable, formDataContext }) {
1884
1966
  context,
1885
1967
  formDataContext: propertyFormDataContext
1886
1968
  });
1887
- const isReadOnly = item.readOnly || schema.readOnly;
1969
+ const isReadOnly = item.readOnly ?? schema.readOnly;
1888
1970
  if (!index) acc.value += "{";
1889
1971
  const doc = jsDoc(schema, true, context);
1890
- acc.hasReadonlyProps ||= isReadOnly || false;
1891
- const constValue = "const" in schema ? schema.const : void 0;
1892
- const hasConst = constValue !== void 0;
1972
+ if (isReadOnly ?? false) acc.hasReadonlyProps = true;
1973
+ const constValue$1 = "const" in schema ? schema.const : void 0;
1974
+ const hasConst = constValue$1 !== void 0;
1893
1975
  let constLiteral;
1894
1976
  if (!hasConst) constLiteral = void 0;
1895
- else if (typeof constValue === "string") constLiteral = `'${escape(constValue)}'`;
1896
- else constLiteral = JSON.stringify(constValue);
1977
+ else if (isString(constValue$1)) constLiteral = `'${escape(constValue$1)}'`;
1978
+ else constLiteral = JSON.stringify(constValue$1);
1897
1979
  const needsValueImport = hasConst && (resolvedValue.isEnum || resolvedValue.type === "enum");
1898
1980
  const aliasedImports = needsValueImport ? resolvedValue.imports.map((imp) => ({
1899
1981
  ...imp,
@@ -1914,8 +1996,9 @@ function getObject({ item, name, context, nullable, formDataContext }) {
1914
1996
  acc.value += `\n ${doc ? `${doc} ` : ""}${isReadOnly && !context.output.override.suppressReadonlyModifier ? "readonly " : ""}${getKey(key)}${isRequired ? "" : "?"}: ${finalPropValue};`;
1915
1997
  acc.schemas.push(...resolvedValue.schemas);
1916
1998
  acc.dependencies.push(...resolvedValue.dependencies);
1917
- if (arr.length - 1 === index) {
1918
- if (item.additionalProperties) if (isBoolean(item.additionalProperties)) {
1999
+ if (entries$1.length - 1 === index) {
2000
+ const additionalProps = item.additionalProperties;
2001
+ if (additionalProps) if (isBoolean(additionalProps)) {
1919
2002
  const recordType$1 = getPropertyNamesRecordType(item, "unknown");
1920
2003
  if (recordType$1) {
1921
2004
  acc.value += "\n}";
@@ -1927,7 +2010,7 @@ function getObject({ item, name, context, nullable, formDataContext }) {
1927
2010
  }
1928
2011
  } else {
1929
2012
  const resolvedValue$1 = resolveValue({
1930
- schema: item.additionalProperties,
2013
+ schema: additionalProps,
1931
2014
  name,
1932
2015
  context
1933
2016
  });
@@ -1945,24 +2028,13 @@ function getObject({ item, name, context, nullable, formDataContext }) {
1945
2028
  else acc.value += "\n}";
1946
2029
  acc.value += nullable;
1947
2030
  }
1948
- return acc;
1949
- }, {
1950
- imports: [],
1951
- schemas: [],
1952
- value: "",
1953
- isEnum: false,
1954
- type: "object",
1955
- isRef: false,
1956
- schema: {},
1957
- hasReadonlyProps: false,
1958
- useTypeAlias: false,
1959
- dependencies: [],
1960
- example: item.example,
1961
- examples: resolveExampleRefs(item.examples, context)
1962
- });
2031
+ }
2032
+ return acc;
1963
2033
  }
1964
- if (item.additionalProperties) {
1965
- if (isBoolean(item.additionalProperties)) {
2034
+ const outerAdditionalProps = item.additionalProperties;
2035
+ const readOnlyFlag = item.readOnly;
2036
+ if (outerAdditionalProps) {
2037
+ if (isBoolean(outerAdditionalProps)) {
1966
2038
  const recordType$2 = getPropertyNamesRecordType(item, "unknown");
1967
2039
  if (recordType$2) return {
1968
2040
  value: recordType$2 + nullable,
@@ -1971,7 +2043,7 @@ function getObject({ item, name, context, nullable, formDataContext }) {
1971
2043
  isEnum: false,
1972
2044
  type: "object",
1973
2045
  isRef: false,
1974
- hasReadonlyProps: item.readOnly || false,
2046
+ hasReadonlyProps: readOnlyFlag ?? false,
1975
2047
  useTypeAlias: true,
1976
2048
  dependencies: []
1977
2049
  };
@@ -1982,21 +2054,21 @@ function getObject({ item, name, context, nullable, formDataContext }) {
1982
2054
  isEnum: false,
1983
2055
  type: "object",
1984
2056
  isRef: false,
1985
- hasReadonlyProps: item.readOnly || false,
2057
+ hasReadonlyProps: readOnlyFlag ?? false,
1986
2058
  useTypeAlias: false,
1987
2059
  dependencies: []
1988
2060
  };
1989
2061
  }
1990
2062
  const resolvedValue = resolveValue({
1991
- schema: item.additionalProperties,
2063
+ schema: outerAdditionalProps,
1992
2064
  name,
1993
2065
  context
1994
2066
  });
1995
2067
  const recordType$1 = getPropertyNamesRecordType(item, resolvedValue.value);
1996
2068
  if (recordType$1) return {
1997
2069
  value: recordType$1 + nullable,
1998
- imports: resolvedValue.imports ?? [],
1999
- schemas: resolvedValue.schemas ?? [],
2070
+ imports: resolvedValue.imports,
2071
+ schemas: resolvedValue.schemas,
2000
2072
  isEnum: false,
2001
2073
  type: "object",
2002
2074
  isRef: false,
@@ -2006,8 +2078,8 @@ function getObject({ item, name, context, nullable, formDataContext }) {
2006
2078
  };
2007
2079
  return {
2008
2080
  value: `{[key: ${getIndexSignatureKey(item)}]: ${resolvedValue.value}}` + nullable,
2009
- imports: resolvedValue.imports ?? [],
2010
- schemas: resolvedValue.schemas ?? [],
2081
+ imports: resolvedValue.imports,
2082
+ schemas: resolvedValue.schemas,
2011
2083
  isEnum: false,
2012
2084
  type: "object",
2013
2085
  isRef: false,
@@ -2016,15 +2088,15 @@ function getObject({ item, name, context, nullable, formDataContext }) {
2016
2088
  dependencies: resolvedValue.dependencies
2017
2089
  };
2018
2090
  }
2019
- const itemWithConst = item;
2020
- if (itemWithConst.const) return {
2021
- value: `'${itemWithConst.const}'`,
2091
+ const constValue = item.const;
2092
+ if (constValue) return {
2093
+ value: `'${constValue}'`,
2022
2094
  imports: [],
2023
2095
  schemas: [],
2024
2096
  isEnum: false,
2025
2097
  type: "string",
2026
2098
  isRef: false,
2027
- hasReadonlyProps: item.readOnly || false,
2099
+ hasReadonlyProps: readOnlyFlag ?? false,
2028
2100
  dependencies: []
2029
2101
  };
2030
2102
  const keyType = item.type === "object" ? getIndexSignatureKey(item) : "string";
@@ -2036,7 +2108,7 @@ function getObject({ item, name, context, nullable, formDataContext }) {
2036
2108
  isEnum: false,
2037
2109
  type: "object",
2038
2110
  isRef: false,
2039
- hasReadonlyProps: item.readOnly || false,
2111
+ hasReadonlyProps: readOnlyFlag ?? false,
2040
2112
  useTypeAlias: true,
2041
2113
  dependencies: []
2042
2114
  };
@@ -2047,7 +2119,7 @@ function getObject({ item, name, context, nullable, formDataContext }) {
2047
2119
  isEnum: false,
2048
2120
  type: "object",
2049
2121
  isRef: false,
2050
- hasReadonlyProps: item.readOnly || false,
2122
+ hasReadonlyProps: readOnlyFlag ?? false,
2051
2123
  useTypeAlias: false,
2052
2124
  dependencies: []
2053
2125
  };
@@ -2062,29 +2134,36 @@ function getObject({ item, name, context, nullable, formDataContext }) {
2062
2134
  * @ref https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.1.md#data-types
2063
2135
  */
2064
2136
  function getScalar({ item, name, context, formDataContext }) {
2065
- const nullable = isArray(item.type) && item.type.includes("null") || item.nullable === true ? " | null" : "";
2066
- const enumItems = item.enum?.filter((enumItem) => enumItem !== null);
2067
- let itemType = item.type;
2137
+ const schemaEnum = item.enum;
2138
+ const schemaType = item.type;
2139
+ const schemaReadOnly = item.readOnly;
2140
+ const schemaExample = item.example;
2141
+ const schemaExamples = item.examples;
2142
+ const schemaConst = item.const;
2143
+ const schemaFormat = item.format;
2144
+ const schemaNullable = item.nullable;
2145
+ const nullable = isArray(schemaType) && schemaType.includes("null") || schemaNullable === true ? " | null" : "";
2146
+ const enumItems = schemaEnum?.filter((enumItem) => enumItem !== null);
2147
+ let itemType = schemaType;
2068
2148
  if (!itemType && item.items) {
2069
2149
  item.type = "array";
2070
2150
  itemType = "array";
2071
2151
  }
2072
- if (isArray(item.type) && item.type.includes("null")) {
2073
- const typesWithoutNull = item.type.filter((x) => x !== "null");
2152
+ if (isArray(schemaType) && schemaType.includes("null")) {
2153
+ const typesWithoutNull = schemaType.filter((x) => x !== "null");
2074
2154
  itemType = typesWithoutNull.length === 1 ? typesWithoutNull[0] : typesWithoutNull;
2075
2155
  }
2076
2156
  switch (itemType) {
2077
2157
  case "number":
2078
2158
  case "integer": {
2079
- let value = context.output.override.useBigInt && (item.format === "int64" || item.format === "uint64") ? "bigint" : "number";
2159
+ let value = context.output.override.useBigInt && (schemaFormat === "int64" || schemaFormat === "uint64") ? "bigint" : "number";
2080
2160
  let isEnum = false;
2081
2161
  if (enumItems) {
2082
2162
  value = enumItems.map((enumItem) => `${enumItem}`).join(" | ");
2083
2163
  isEnum = true;
2084
2164
  }
2085
2165
  value += nullable;
2086
- const itemWithConst = item;
2087
- if (itemWithConst.const !== void 0) value = itemWithConst.const;
2166
+ if (schemaConst !== void 0) value = schemaConst;
2088
2167
  return {
2089
2168
  value,
2090
2169
  isEnum,
@@ -2092,16 +2171,15 @@ function getScalar({ item, name, context, formDataContext }) {
2092
2171
  schemas: [],
2093
2172
  imports: [],
2094
2173
  isRef: false,
2095
- hasReadonlyProps: item.readOnly || false,
2174
+ hasReadonlyProps: schemaReadOnly ?? false,
2096
2175
  dependencies: [],
2097
- example: item.example,
2098
- examples: resolveExampleRefs(item.examples, context)
2176
+ example: schemaExample,
2177
+ examples: resolveExampleRefs(schemaExamples, context)
2099
2178
  };
2100
2179
  }
2101
2180
  case "boolean": {
2102
2181
  let value = "boolean" + nullable;
2103
- const itemWithConst = item;
2104
- if (itemWithConst.const !== void 0) value = itemWithConst.const;
2182
+ if (schemaConst !== void 0) value = schemaConst;
2105
2183
  return {
2106
2184
  value,
2107
2185
  type: "boolean",
@@ -2109,10 +2187,10 @@ function getScalar({ item, name, context, formDataContext }) {
2109
2187
  schemas: [],
2110
2188
  imports: [],
2111
2189
  isRef: false,
2112
- hasReadonlyProps: item.readOnly || false,
2190
+ hasReadonlyProps: schemaReadOnly ?? false,
2113
2191
  dependencies: [],
2114
- example: item.example,
2115
- examples: resolveExampleRefs(item.examples, context)
2192
+ example: schemaExample,
2193
+ examples: resolveExampleRefs(schemaExamples, context)
2116
2194
  };
2117
2195
  }
2118
2196
  case "array": {
@@ -2125,7 +2203,7 @@ function getScalar({ item, name, context, formDataContext }) {
2125
2203
  return {
2126
2204
  value: value + nullable,
2127
2205
  ...rest,
2128
- dependencies: rest.dependencies ?? []
2206
+ dependencies: rest.dependencies
2129
2207
  };
2130
2208
  }
2131
2209
  case "string": {
@@ -2135,15 +2213,14 @@ function getScalar({ item, name, context, formDataContext }) {
2135
2213
  value = enumItems.map((enumItem) => isString(enumItem) ? `'${escape(enumItem)}'` : `${enumItem}`).filter(Boolean).join(` | `);
2136
2214
  isEnum = true;
2137
2215
  }
2138
- if (item.format === "binary") value = "Blob";
2216
+ if (schemaFormat === "binary") value = "Blob";
2139
2217
  else if (formDataContext?.atPart) {
2140
2218
  const fileType = getFormDataFieldFileType(item, formDataContext.partContentType);
2141
2219
  if (fileType) value = fileType === "binary" ? "Blob" : "Blob | string";
2142
2220
  }
2143
- if (context.output.override.useDates && (item.format === "date" || item.format === "date-time")) value = "Date";
2221
+ if (context.output.override.useDates && (schemaFormat === "date" || schemaFormat === "date-time")) value = "Date";
2144
2222
  value += nullable;
2145
- const itemWithConst = item;
2146
- if (itemWithConst.const) value = `'${itemWithConst.const}'`;
2223
+ if (schemaConst) value = `'${schemaConst}'`;
2147
2224
  return {
2148
2225
  value,
2149
2226
  isEnum,
@@ -2151,10 +2228,10 @@ function getScalar({ item, name, context, formDataContext }) {
2151
2228
  imports: [],
2152
2229
  schemas: [],
2153
2230
  isRef: false,
2154
- hasReadonlyProps: item.readOnly || false,
2231
+ hasReadonlyProps: schemaReadOnly ?? false,
2155
2232
  dependencies: [],
2156
- example: item.example,
2157
- examples: resolveExampleRefs(item.examples, context)
2233
+ example: schemaExample,
2234
+ examples: resolveExampleRefs(schemaExamples, context)
2158
2235
  };
2159
2236
  }
2160
2237
  case "null": return {
@@ -2164,34 +2241,30 @@ function getScalar({ item, name, context, formDataContext }) {
2164
2241
  imports: [],
2165
2242
  schemas: [],
2166
2243
  isRef: false,
2167
- hasReadonlyProps: item.readOnly || false,
2244
+ hasReadonlyProps: schemaReadOnly ?? false,
2168
2245
  dependencies: []
2169
2246
  };
2170
- case "object":
2171
2247
  default: {
2172
2248
  if (isArray(itemType)) return combineSchemas({
2173
- schema: { anyOf: itemType.map((type) => ({
2174
- ...item,
2175
- type
2176
- })) },
2249
+ schema: { anyOf: itemType.map((type) => Object.assign({}, item, { type })) },
2177
2250
  name,
2178
2251
  separator: "anyOf",
2179
2252
  context,
2180
2253
  nullable
2181
2254
  });
2182
2255
  if (enumItems) return {
2183
- value: enumItems.map((enumItem) => isString(enumItem) ? `'${escape(enumItem)}'` : `${enumItem}`).filter(Boolean).join(` | `) + nullable,
2256
+ value: enumItems.map((enumItem) => isString(enumItem) ? `'${escape(enumItem)}'` : String(enumItem)).filter(Boolean).join(` | `) + nullable,
2184
2257
  isEnum: true,
2185
2258
  type: "string",
2186
2259
  imports: [],
2187
2260
  schemas: [],
2188
2261
  isRef: false,
2189
- hasReadonlyProps: item.readOnly || false,
2262
+ hasReadonlyProps: schemaReadOnly ?? false,
2190
2263
  dependencies: [],
2191
- example: item.example,
2192
- examples: resolveExampleRefs(item.examples, context)
2264
+ example: schemaExample,
2265
+ examples: resolveExampleRefs(schemaExamples, context)
2193
2266
  };
2194
- const hasCombiners = item.allOf || item.anyOf || item.oneOf;
2267
+ const hasCombiners = item.allOf ?? item.anyOf ?? item.oneOf;
2195
2268
  const { value, ...rest } = getObject({
2196
2269
  item,
2197
2270
  name,
@@ -2209,17 +2282,66 @@ function getScalar({ item, name, context, formDataContext }) {
2209
2282
 
2210
2283
  //#endregion
2211
2284
  //#region src/getters/combine.ts
2212
- function combineValues({ resolvedData, resolvedValue, separator: separator$1, context }) {
2285
+ const mergeableAllOfKeys = new Set([
2286
+ "type",
2287
+ "properties",
2288
+ "required"
2289
+ ]);
2290
+ function isMergeableAllOfObject(schema) {
2291
+ if (isNullish$1(schema.properties)) return false;
2292
+ if (schema.allOf || schema.anyOf || schema.oneOf) return false;
2293
+ if (!isNullish$1(schema.type) && schema.type !== "object") return false;
2294
+ return Object.keys(schema).every((key) => mergeableAllOfKeys.has(key));
2295
+ }
2296
+ function normalizeAllOfSchema(schema) {
2297
+ const schemaAllOf = schema.allOf;
2298
+ if (!schemaAllOf) return schema;
2299
+ let didMerge = false;
2300
+ const schemaProperties = schema.properties;
2301
+ const schemaRequired = schema.required;
2302
+ const mergedProperties = { ...schemaProperties };
2303
+ const mergedRequired = new Set(schemaRequired);
2304
+ const remainingAllOf = [];
2305
+ for (const subSchema of schemaAllOf) {
2306
+ if (isSchema(subSchema) && isMergeableAllOfObject(subSchema)) {
2307
+ didMerge = true;
2308
+ if (subSchema.properties) Object.assign(mergedProperties, subSchema.properties);
2309
+ const subRequired = subSchema.required;
2310
+ if (subRequired) for (const prop$1 of subRequired) mergedRequired.add(prop$1);
2311
+ continue;
2312
+ }
2313
+ remainingAllOf.push(subSchema);
2314
+ }
2315
+ if (!didMerge || remainingAllOf.length === 0) return schema;
2316
+ return {
2317
+ ...schema,
2318
+ ...Object.keys(mergedProperties).length > 0 && { properties: mergedProperties },
2319
+ ...mergedRequired.size > 0 && { required: [...mergedRequired] },
2320
+ ...remainingAllOf.length > 0 && { allOf: remainingAllOf }
2321
+ };
2322
+ }
2323
+ function combineValues({ resolvedData, resolvedValue, separator: separator$1, context, parentSchema }) {
2213
2324
  if (resolvedData.isEnum.every(Boolean)) return `${resolvedData.values.join(` | `)}${resolvedValue ? ` | ${resolvedValue.value}` : ""}`;
2214
2325
  if (separator$1 === "allOf") {
2215
2326
  let resolvedDataValue = resolvedData.values.map((v) => v.includes(" | ") ? `(${v})` : v).join(` & `);
2216
2327
  if (resolvedData.originalSchema.length > 0 && resolvedValue) {
2217
- const discriminatedPropertySchemas = resolvedData.originalSchema.filter((s) => s?.discriminator && resolvedValue.value.includes(` ${s.discriminator.propertyName}:`));
2328
+ const discriminatedPropertySchemas = resolvedData.originalSchema.filter((s) => {
2329
+ const disc = s?.discriminator;
2330
+ return disc && resolvedValue.value.includes(` ${disc.propertyName}:`);
2331
+ });
2218
2332
  if (discriminatedPropertySchemas.length > 0) resolvedDataValue = `Omit<${resolvedDataValue}, '${discriminatedPropertySchemas.map((s) => s.discriminator?.propertyName).join("' | '")}'>`;
2219
2333
  }
2220
2334
  const resolvedValueStr = resolvedValue?.value.includes(" | ") ? `(${resolvedValue.value})` : resolvedValue?.value;
2221
2335
  const joined = `${resolvedDataValue}${resolvedValue ? ` & ${resolvedValueStr}` : ""}`;
2222
- const overrideRequiredProperties = resolvedData.requiredProperties.filter((prop$1) => !resolvedData.originalSchema.some((schema) => schema?.properties?.[prop$1] && schema.required?.includes(prop$1)));
2336
+ const overrideRequiredProperties = resolvedData.requiredProperties.filter((prop$1) => !resolvedData.originalSchema.some((schema) => {
2337
+ const props = schema?.properties;
2338
+ const req = schema?.required;
2339
+ return props?.[prop$1] && req?.includes(prop$1);
2340
+ }) && !(() => {
2341
+ const parentProps = parentSchema?.properties;
2342
+ const parentReq = parentSchema?.required;
2343
+ return !!(parentProps?.[prop$1] && parentReq?.includes(prop$1));
2344
+ })());
2223
2345
  if (overrideRequiredProperties.length > 0) return `${joined} & Required<Pick<${joined}, '${overrideRequiredProperties.join("' | '")}'>>`;
2224
2346
  return joined;
2225
2347
  }
@@ -2228,11 +2350,12 @@ function combineValues({ resolvedData, resolvedValue, separator: separator$1, co
2228
2350
  values = [];
2229
2351
  for (let i = 0; i < resolvedData.values.length; i += 1) {
2230
2352
  const subSchema = resolvedData.originalSchema[i];
2231
- if (subSchema?.type !== "object") {
2353
+ if (subSchema?.type !== "object" || !subSchema.properties) {
2232
2354
  values.push(resolvedData.values[i]);
2233
2355
  continue;
2234
2356
  }
2235
- const missingProperties = unique(resolvedData.allProperties.filter((p) => !Object.keys(subSchema.properties).includes(p)));
2357
+ const subSchemaProps = subSchema.properties;
2358
+ const missingProperties = unique(resolvedData.allProperties.filter((p) => !Object.keys(subSchemaProps).includes(p)));
2236
2359
  values.push(`${resolvedData.values[i]}${missingProperties.length > 0 ? ` & {${missingProperties.map((p) => `${p}?: never`).join("; ")}}` : ""}`);
2237
2360
  }
2238
2361
  }
@@ -2240,14 +2363,30 @@ function combineValues({ resolvedData, resolvedValue, separator: separator$1, co
2240
2363
  return values.join(" | ");
2241
2364
  }
2242
2365
  function combineSchemas({ name, schema, separator: separator$1, context, nullable, formDataContext }) {
2243
- const items = schema[separator$1] ?? [];
2244
- const resolvedData = items.reduce((acc, subSchema) => {
2366
+ const normalizedSchema = separator$1 === "allOf" && !context.output.override.aliasCombinedTypes && !schema.oneOf && !schema.anyOf ? normalizeAllOfSchema(schema) : schema;
2367
+ const items = normalizedSchema[separator$1] ?? [];
2368
+ const resolvedData = {
2369
+ values: [],
2370
+ imports: [],
2371
+ schemas: [],
2372
+ isEnum: [],
2373
+ isRef: [],
2374
+ types: [],
2375
+ dependencies: [],
2376
+ originalSchema: [],
2377
+ allProperties: [],
2378
+ hasReadonlyProps: false,
2379
+ example: schema.example,
2380
+ examples: resolveExampleRefs(schema.examples, context),
2381
+ requiredProperties: separator$1 === "allOf" ? schema.required ?? [] : []
2382
+ };
2383
+ for (const subSchema of items) {
2245
2384
  let propName;
2246
2385
  if (context.output.override.aliasCombinedTypes) {
2247
2386
  propName = name ? name + pascal(separator$1) : void 0;
2248
- if (propName && acc.schemas.length > 0) propName = propName + pascal(getNumberWord(acc.schemas.length + 1));
2387
+ if (propName && resolvedData.schemas.length > 0) propName = propName + pascal(getNumberWord(resolvedData.schemas.length + 1));
2249
2388
  }
2250
- if (separator$1 === "allOf" && isSchema(subSchema) && subSchema.required) acc.requiredProperties.push(...subSchema.required);
2389
+ if (separator$1 === "allOf" && isSchema(subSchema) && subSchema.required) resolvedData.requiredProperties.push(...subSchema.required);
2251
2390
  const resolvedValue$1 = resolveObject({
2252
2391
  schema: subSchema,
2253
2392
  propName,
@@ -2265,32 +2404,18 @@ function combineSchemas({ name, schema, separator: separator$1, context, nullabl
2265
2404
  resolvedValue: resolvedValue$1,
2266
2405
  imports: aliasedImports
2267
2406
  });
2268
- acc.values.push(value);
2269
- acc.imports.push(...aliasedImports);
2270
- acc.schemas.push(...resolvedValue$1.schemas);
2271
- acc.dependencies.push(...resolvedValue$1.dependencies);
2272
- acc.isEnum.push(resolvedValue$1.isEnum);
2273
- acc.types.push(resolvedValue$1.type);
2274
- acc.isRef.push(resolvedValue$1.isRef);
2275
- acc.originalSchema.push(resolvedValue$1.originalSchema);
2276
- acc.hasReadonlyProps ||= resolvedValue$1.hasReadonlyProps;
2277
- if (resolvedValue$1.type === "object" && resolvedValue$1.originalSchema.properties) acc.allProperties.push(...Object.keys(resolvedValue$1.originalSchema.properties));
2278
- return acc;
2279
- }, {
2280
- values: [],
2281
- imports: [],
2282
- schemas: [],
2283
- isEnum: [],
2284
- isRef: [],
2285
- types: [],
2286
- dependencies: [],
2287
- originalSchema: [],
2288
- allProperties: [],
2289
- hasReadonlyProps: false,
2290
- example: schema.example,
2291
- examples: resolveExampleRefs(schema.examples, context),
2292
- requiredProperties: separator$1 === "allOf" ? schema.required ?? [] : []
2293
- });
2407
+ resolvedData.values.push(value);
2408
+ resolvedData.imports.push(...aliasedImports);
2409
+ resolvedData.schemas.push(...resolvedValue$1.schemas);
2410
+ resolvedData.dependencies.push(...resolvedValue$1.dependencies);
2411
+ resolvedData.isEnum.push(resolvedValue$1.isEnum);
2412
+ resolvedData.types.push(resolvedValue$1.type);
2413
+ resolvedData.isRef.push(resolvedValue$1.isRef);
2414
+ resolvedData.originalSchema.push(resolvedValue$1.originalSchema);
2415
+ if (resolvedValue$1.hasReadonlyProps) resolvedData.hasReadonlyProps = true;
2416
+ const originalProps = resolvedValue$1.originalSchema.properties;
2417
+ if (resolvedValue$1.type === "object" && originalProps) resolvedData.allProperties.push(...Object.keys(originalProps));
2418
+ }
2294
2419
  if (resolvedData.isEnum.every(Boolean) && name && items.length > 1 && context.output.override.enumGenerationType !== EnumGeneration.UNION) {
2295
2420
  const { value: combinedEnumValue, valueImports, hasNull } = getCombinedEnumValue(resolvedData.values.map((value, index) => ({
2296
2421
  value,
@@ -2321,15 +2446,17 @@ function combineSchemas({ name, schema, separator: separator$1, context, nullabl
2321
2446
  };
2322
2447
  }
2323
2448
  let resolvedValue;
2324
- if (schema.properties) resolvedValue = getScalar({
2325
- item: Object.fromEntries(Object.entries(schema).filter(([key]) => key !== separator$1)),
2449
+ if (normalizedSchema.properties) resolvedValue = getScalar({
2450
+ item: Object.fromEntries(Object.entries(normalizedSchema).filter(([key]) => key !== separator$1)),
2326
2451
  name,
2327
- context
2452
+ context,
2453
+ formDataContext
2328
2454
  });
2329
2455
  else if (separator$1 === "allOf" && (schema.oneOf || schema.anyOf)) {
2330
2456
  const siblingCombiner = schema.oneOf ? "oneOf" : "anyOf";
2457
+ const siblingSchemas = schema[siblingCombiner];
2331
2458
  resolvedValue = combineSchemas({
2332
- schema: { [siblingCombiner]: schema[siblingCombiner] },
2459
+ schema: { [siblingCombiner]: siblingSchemas },
2333
2460
  name,
2334
2461
  separator: siblingCombiner,
2335
2462
  context,
@@ -2341,7 +2468,8 @@ function combineSchemas({ name, schema, separator: separator$1, context, nullabl
2341
2468
  resolvedData,
2342
2469
  separator: separator$1,
2343
2470
  resolvedValue,
2344
- context
2471
+ context,
2472
+ parentSchema: normalizedSchema
2345
2473
  }) + nullable),
2346
2474
  imports: resolvedValue ? [...resolvedData.imports, ...resolvedValue.imports] : resolvedData.imports,
2347
2475
  schemas: resolvedValue ? [...resolvedData.schemas, ...resolvedValue.schemas] : resolvedData.schemas,
@@ -2349,7 +2477,7 @@ function combineSchemas({ name, schema, separator: separator$1, context, nullabl
2349
2477
  isEnum: false,
2350
2478
  type: "object",
2351
2479
  isRef: false,
2352
- hasReadonlyProps: resolvedData?.hasReadonlyProps || resolvedValue?.hasReadonlyProps || false,
2480
+ hasReadonlyProps: resolvedData.hasReadonlyProps || (resolvedValue?.hasReadonlyProps ?? false),
2353
2481
  example: schema.example,
2354
2482
  examples: resolveExampleRefs(schema.examples, context)
2355
2483
  };
@@ -2360,7 +2488,9 @@ function combineSchemas({ name, schema, separator: separator$1, context, nullabl
2360
2488
  function resolveDiscriminators(schemas, context) {
2361
2489
  const transformedSchemas = schemas;
2362
2490
  for (const schema of Object.values(transformedSchemas)) {
2363
- if (typeof schema === "boolean") continue;
2491
+ if (isBoolean$1(schema)) continue;
2492
+ const discriminator = schema.discriminator;
2493
+ if (!schema.oneOf && isArray(discriminator?.oneOf)) schema.oneOf = discriminator.oneOf;
2364
2494
  if (schema.discriminator?.mapping) {
2365
2495
  const { mapping, propertyName } = schema.discriminator;
2366
2496
  for (const [mappingKey, mappingValue] of Object.entries(mapping)) {
@@ -2371,17 +2501,25 @@ function resolveDiscriminators(schemas, context) {
2371
2501
  } catch {
2372
2502
  subTypeSchema = transformedSchemas[mappingValue];
2373
2503
  }
2374
- if (typeof subTypeSchema === "boolean" || propertyName === void 0) continue;
2504
+ if (isBoolean$1(subTypeSchema) || propertyName === void 0) continue;
2375
2505
  const property = subTypeSchema.properties?.[propertyName];
2376
- if (typeof property === "boolean" || property === void 0) continue;
2506
+ if (isBoolean$1(property)) continue;
2507
+ const schemaProperty = property && !isReference(property) ? property : void 0;
2508
+ const enumProperty = schemaProperty ? getPropertySafe(schemaProperty, "enum") : {
2509
+ hasProperty: false,
2510
+ value: void 0
2511
+ };
2512
+ const mergedEnumValues = [...((enumProperty.hasProperty && Array.isArray(enumProperty.value) ? enumProperty.value : void 0) ?? []).filter((value) => value !== mappingKey), mappingKey];
2513
+ const mergedProperty = {
2514
+ ...schemaProperty,
2515
+ type: "string",
2516
+ enum: mergedEnumValues
2517
+ };
2377
2518
  subTypeSchema.properties = {
2378
2519
  ...subTypeSchema.properties,
2379
- [propertyName]: {
2380
- type: "string",
2381
- enum: [...property?.enum?.filter((value) => value !== mappingKey) ?? [], mappingKey]
2382
- }
2520
+ [propertyName]: mergedProperty
2383
2521
  };
2384
- subTypeSchema.required = [...subTypeSchema.required ?? [], propertyName];
2522
+ subTypeSchema.required = [...new Set([...subTypeSchema.required ?? [], propertyName])];
2385
2523
  }
2386
2524
  }
2387
2525
  }
@@ -2403,23 +2541,22 @@ function getOperationId(operation, route, verb) {
2403
2541
  //#endregion
2404
2542
  //#region src/getters/parameters.ts
2405
2543
  function getParameters({ parameters, context }) {
2406
- return parameters.reduce((acc, p) => {
2407
- if (isReference(p)) {
2408
- const { schema: parameter, imports } = resolveRef(p, context);
2409
- if (parameter.in === "path" || parameter.in === "query" || parameter.in === "header") acc[parameter.in].push({
2410
- parameter,
2411
- imports
2412
- });
2413
- } else if (p.in === "query" || p.in === "path" || p.in === "header") acc[p.in].push({
2414
- parameter: p,
2415
- imports: []
2416
- });
2417
- return acc;
2418
- }, {
2544
+ const result = {
2419
2545
  path: [],
2420
2546
  query: [],
2421
2547
  header: []
2548
+ };
2549
+ for (const p of parameters) if (isReference(p)) {
2550
+ const { schema: parameter, imports } = resolveRef(p, context);
2551
+ if (parameter.in === "path" || parameter.in === "query" || parameter.in === "header") result[parameter.in].push({
2552
+ parameter,
2553
+ imports
2554
+ });
2555
+ } else if (p.in === "query" || p.in === "path" || p.in === "header") result[p.in].push({
2556
+ parameter: p,
2557
+ imports: []
2422
2558
  });
2559
+ return result;
2423
2560
  }
2424
2561
 
2425
2562
  //#endregion
@@ -2463,16 +2600,18 @@ function getParams({ route, pathParams = [], operationId, context, output }) {
2463
2600
  schema,
2464
2601
  context
2465
2602
  });
2603
+ const originalSchema = resolvedValue.originalSchema;
2604
+ const schemaDefault = originalSchema.default;
2466
2605
  let paramType = resolvedValue.value;
2467
2606
  if (output.allParamsOptional) paramType = `${paramType} | undefined | null`;
2468
2607
  return {
2469
2608
  name,
2470
- definition: `${name}${!required || resolvedValue.originalSchema.default ? "?" : ""}: ${paramType}`,
2471
- implementation: `${name}${!required && !resolvedValue.originalSchema.default ? "?" : ""}${resolvedValue.originalSchema.default ? `: ${paramType} = ${stringify(resolvedValue.originalSchema.default)}` : `: ${paramType}`}`,
2472
- default: resolvedValue.originalSchema.default,
2609
+ definition: `${name}${!required || schemaDefault ? "?" : ""}: ${paramType}`,
2610
+ implementation: `${name}${!required && !schemaDefault ? "?" : ""}${schemaDefault ? `: ${paramType} = ${stringify(schemaDefault)}` : `: ${paramType}`}`,
2611
+ default: schemaDefault,
2473
2612
  required,
2474
2613
  imports: resolvedValue.imports,
2475
- originalSchema: resolvedValue.originalSchema
2614
+ originalSchema
2476
2615
  };
2477
2616
  });
2478
2617
  }
@@ -2493,7 +2632,7 @@ function getProps({ body, queryParams, params, operationName, headers, context }
2493
2632
  definition: getQueryParamDefinition(queryParams, context),
2494
2633
  implementation: getQueryParamDefinition(queryParams, context),
2495
2634
  default: false,
2496
- required: isUndefined(queryParams?.isOptional) ? !context.output.allParamsOptional || context.output.optionsParamRequired : !queryParams?.isOptional && !context.output.allParamsOptional || context.output.optionsParamRequired,
2635
+ required: isNullish(queryParams?.isOptional) ? !context.output.allParamsOptional || context.output.optionsParamRequired : !queryParams.isOptional && !context.output.allParamsOptional || context.output.optionsParamRequired,
2497
2636
  type: GetterPropType.QUERY_PARAM
2498
2637
  };
2499
2638
  const headersProp = {
@@ -2501,7 +2640,7 @@ function getProps({ body, queryParams, params, operationName, headers, context }
2501
2640
  definition: `headers${headers?.isOptional && !context.output.optionsParamRequired ? "?" : ""}: ${headers?.schema.name}`,
2502
2641
  implementation: `headers${headers?.isOptional && !context.output.optionsParamRequired ? "?" : ""}: ${headers?.schema.name}`,
2503
2642
  default: false,
2504
- required: isUndefined(headers?.isOptional) ? false : !headers?.isOptional || context.output.optionsParamRequired,
2643
+ required: isNullish(headers?.isOptional) ? false : !headers.isOptional || context.output.optionsParamRequired,
2505
2644
  type: GetterPropType.HEADER
2506
2645
  };
2507
2646
  let paramGetterProps;
@@ -2555,16 +2694,18 @@ function getQueryParamsTypes(queryParams, operationName, context) {
2555
2694
  es5keyword: true,
2556
2695
  es5IdentifierName: true
2557
2696
  });
2558
- const schema = schemaParam || content["application/json"].schema;
2697
+ const schema = schemaParam ?? content?.["application/json"]?.schema;
2698
+ if (!schema) throw new Error(`Query parameter "${name}" has no schema or content definition`);
2559
2699
  const resolvedValue = resolveValue({
2560
2700
  schema,
2561
2701
  context,
2562
2702
  name: queryName
2563
2703
  });
2564
2704
  const key = getKey(name);
2705
+ const schemaForDoc = schema;
2565
2706
  const doc = jsDoc({
2566
2707
  description: parameter.description,
2567
- ...schema
2708
+ ...schemaForDoc
2568
2709
  }, void 0, context);
2569
2710
  if (parameterImports.length > 0) return {
2570
2711
  definition: `${doc}${key}${!required || schema.default ? "?" : ""}: ${parameterImports[0].name};`,
@@ -2574,7 +2715,7 @@ function getQueryParamsTypes(queryParams, operationName, context) {
2574
2715
  };
2575
2716
  if (resolvedValue.isEnum && !resolvedValue.isRef) {
2576
2717
  const enumName = queryName;
2577
- const enumValue = getEnum(resolvedValue.value, enumName, getEnumNames(resolvedValue.originalSchema), context.output.override.enumGenerationType, getEnumDescriptions(resolvedValue.originalSchema), context.output.override.namingConvention?.enum);
2718
+ const enumValue = getEnum(resolvedValue.value, enumName, getEnumNames(resolvedValue.originalSchema), context.output.override.enumGenerationType, getEnumDescriptions(resolvedValue.originalSchema), context.output.override.namingConvention.enum);
2578
2719
  return {
2579
2720
  definition: `${doc}${key}${!required || schema.default ? "?" : ""}: ${enumName};`,
2580
2721
  imports: [{ name: enumName }],
@@ -2616,39 +2757,16 @@ function getQueryParams({ queryParams, operationName, context, suffix = "params"
2616
2757
  //#endregion
2617
2758
  //#region src/getters/response.ts
2618
2759
  function getResponse({ responses, operationName, context, contentType }) {
2619
- if (!responses) return {
2620
- imports: [],
2621
- definition: {
2622
- success: "",
2623
- errors: ""
2624
- },
2625
- isBlob: false,
2626
- types: {
2627
- success: [],
2628
- errors: []
2629
- },
2630
- schemas: [],
2631
- contentTypes: []
2632
- };
2633
- const types = getResReqTypes(Object.entries(responses), operationName, context, "void", (type) => `${type.key}-${type.value}`);
2634
- const filteredTypes = contentType ? types.filter((type) => {
2635
- let include = true;
2636
- let exclude = false;
2637
- if (contentType.include) include = contentType.include.includes(type.contentType);
2638
- if (contentType.exclude) exclude = contentType.exclude.includes(type.contentType);
2639
- return include && !exclude;
2640
- }) : types;
2760
+ const filteredTypes = filterByContentType(getResReqTypes(Object.entries(responses), operationName, context, "void", (type) => `${type.key}-${type.value}`), contentType);
2641
2761
  const imports = filteredTypes.flatMap(({ imports: imports$1 }) => imports$1);
2642
2762
  const schemas = filteredTypes.flatMap(({ schemas: schemas$1 }) => schemas$1);
2643
2763
  const contentTypes = [...new Set(filteredTypes.map(({ contentType: contentType$1 }) => contentType$1))];
2644
- const groupedByStatus = filteredTypes.reduce((acc, type) => {
2645
- if (type.key.startsWith("2")) acc.success.push(type);
2646
- else acc.errors.push(type);
2647
- return acc;
2648
- }, {
2764
+ const groupedByStatus = {
2649
2765
  success: [],
2650
2766
  errors: []
2651
- });
2767
+ };
2768
+ for (const type of filteredTypes) if (type.key.startsWith("2")) groupedByStatus.success.push(type);
2769
+ else groupedByStatus.errors.push(type);
2652
2770
  const success = dedupeUnionType(groupedByStatus.success.map(({ value, formData }) => formData ? "Blob" : value).join(" | "));
2653
2771
  const errors = dedupeUnionType(groupedByStatus.errors.map(({ value }) => value).join(" | "));
2654
2772
  const defaultType = filteredTypes.find(({ key }) => key === "default")?.value;
@@ -2684,16 +2802,18 @@ const getRoutePath = (path$2) => {
2684
2802
  return hasParam(path$2) ? `${prev}\${${param}}${next}` : `${prev}${param}${next}`;
2685
2803
  };
2686
2804
  function getRoute(route) {
2687
- return route.split("/").reduce((acc, path$2, i) => {
2688
- if (!path$2 && !i) return acc;
2689
- if (!path$2.includes("{")) return `${acc}/${path$2}`;
2690
- return `${acc}/${getRoutePath(path$2)}`;
2691
- }, "");
2805
+ const splittedRoute = route.split("/");
2806
+ let result = "";
2807
+ for (const [i, path$2] of splittedRoute.entries()) {
2808
+ if (!path$2 && !i) continue;
2809
+ result += path$2.includes("{") ? `/${getRoutePath(path$2)}` : `/${path$2}`;
2810
+ }
2811
+ return result;
2692
2812
  }
2693
2813
  function getFullRoute(route, servers, baseUrl) {
2694
2814
  const getBaseUrl = () => {
2695
2815
  if (!baseUrl) return "";
2696
- if (typeof baseUrl === "string") return baseUrl;
2816
+ if (isString(baseUrl)) return baseUrl;
2697
2817
  if (baseUrl.getBaseUrlFromSpecification) {
2698
2818
  if (!servers) throw new Error("Orval is configured to use baseUrl from the specifications 'servers' field, but there exist no servers in the specification.");
2699
2819
  const server = servers.at(Math.min(baseUrl.index ?? 0, servers.length - 1));
@@ -2768,25 +2888,26 @@ function generateImports({ imports, namingConvention = NamingConvention.CAMEL_CA
2768
2888
  }).join("\n");
2769
2889
  }
2770
2890
  function generateMutatorImports({ mutators, implementation, oneMore }) {
2771
- return uniqueWith(mutators, (a, b) => a.name === b.name && a.default === b.default).reduce((acc, mutator) => {
2891
+ let imports = "";
2892
+ for (const mutator of uniqueWith(mutators, (a, b) => a.name === b.name && a.default === b.default)) {
2772
2893
  const path$2 = `${oneMore ? "../" : ""}${mutator.path}`;
2773
2894
  const importDefault = mutator.default ? mutator.name : `{ ${mutator.name} }`;
2774
- acc += `import ${importDefault} from '${path$2}';`;
2775
- acc += "\n";
2895
+ imports += `import ${importDefault} from '${path$2}';`;
2896
+ imports += "\n";
2776
2897
  if (implementation && (mutator.hasErrorType || mutator.bodyTypeName)) {
2777
2898
  let errorImportName = "";
2778
2899
  const targetErrorImportName = mutator.default ? `ErrorType as ${mutator.errorTypeName}` : mutator.errorTypeName;
2779
- if (mutator.hasErrorType && implementation.includes(mutator.errorTypeName) && !acc.includes(`{ ${targetErrorImportName} `)) errorImportName = targetErrorImportName;
2900
+ if (mutator.hasErrorType && implementation.includes(mutator.errorTypeName) && !imports.includes(`{ ${targetErrorImportName} `)) errorImportName = targetErrorImportName;
2780
2901
  let bodyImportName = "";
2781
2902
  const targetBodyImportName = mutator.default ? `BodyType as ${mutator.bodyTypeName}` : mutator.bodyTypeName;
2782
- if (mutator.bodyTypeName && implementation.includes(mutator.bodyTypeName) && !acc.includes(` ${targetBodyImportName} }`)) bodyImportName = targetBodyImportName;
2903
+ if (mutator.bodyTypeName && implementation.includes(mutator.bodyTypeName) && !imports.includes(` ${targetBodyImportName} }`)) bodyImportName = targetBodyImportName ?? "";
2783
2904
  if (bodyImportName || errorImportName) {
2784
- acc += `import type { ${errorImportName}${errorImportName && bodyImportName ? " , " : ""}${bodyImportName} } from '${path$2}';`;
2785
- acc += "\n";
2905
+ imports += `import type { ${errorImportName}${errorImportName && bodyImportName ? " , " : ""}${bodyImportName} } from '${path$2}';`;
2906
+ imports += "\n";
2786
2907
  }
2787
2908
  }
2788
- return acc;
2789
- }, "");
2909
+ }
2910
+ return imports;
2790
2911
  }
2791
2912
  function generateDependency({ deps, isAllowSyntheticDefaultImports, dependency, projectName, key, onlyTypes }) {
2792
2913
  const defaultDep = deps.find((e) => e.default && (isAllowSyntheticDefaultImports || !e.syntheticDefaultImport));
@@ -2801,31 +2922,25 @@ function generateDependency({ deps, isAllowSyntheticDefaultImports, dependency,
2801
2922
  importString += `import ${onlyTypes ? "type " : ""}${defaultDep ? `${defaultDep.name}${depsString ? "," : ""}` : ""}${depsString ? `{\n ${depsString}\n}` : ""} from '${dependency}${key !== "default" && projectName ? `/${projectName}` : ""}';`;
2802
2923
  return importString;
2803
2924
  }
2804
- function addDependency({ implementation, exports, dependency, projectName, hasSchemaDir, isAllowSyntheticDefaultImports }) {
2925
+ function addDependency({ implementation, exports, dependency, projectName, isAllowSyntheticDefaultImports }) {
2805
2926
  const toAdds = exports.filter((e) => {
2806
2927
  const searchWords = [e.alias, e.name].filter((p) => p?.length).join("|");
2807
2928
  const pattern = new RegExp(String.raw`\b(${searchWords})\b`, "g");
2808
2929
  return implementation.match(pattern);
2809
2930
  });
2810
2931
  if (toAdds.length === 0) return;
2811
- const groupedBySpecKey = toAdds.reduce((acc, dep) => {
2932
+ const groupedBySpecKey = { default: {
2933
+ types: [],
2934
+ values: []
2935
+ } };
2936
+ for (const dep of toAdds) {
2812
2937
  const key = "default";
2813
- if (dep.values && (isAllowSyntheticDefaultImports || !dep.syntheticDefaultImport)) {
2814
- acc[key] = {
2815
- ...acc[key],
2816
- values: [...acc[key]?.values ?? [], dep]
2817
- };
2818
- return acc;
2819
- }
2820
- acc[key] = {
2821
- ...acc[key],
2822
- types: [...acc[key]?.types ?? [], dep]
2823
- };
2824
- return acc;
2825
- }, {});
2938
+ if (dep.values && (isAllowSyntheticDefaultImports || !dep.syntheticDefaultImport)) groupedBySpecKey[key].values.push(dep);
2939
+ else groupedBySpecKey[key].types.push(dep);
2940
+ }
2826
2941
  return Object.entries(groupedBySpecKey).map(([key, { values, types }]) => {
2827
2942
  let dep = "";
2828
- if (values) dep += generateDependency({
2943
+ if (values.length > 0) dep += generateDependency({
2829
2944
  deps: values,
2830
2945
  isAllowSyntheticDefaultImports,
2831
2946
  dependency,
@@ -2833,9 +2948,9 @@ function addDependency({ implementation, exports, dependency, projectName, hasSc
2833
2948
  key,
2834
2949
  onlyTypes: false
2835
2950
  });
2836
- if (types) {
2951
+ if (types.length > 0) {
2837
2952
  let uniqueTypes = types;
2838
- if (values) {
2953
+ if (values.length > 0) {
2839
2954
  uniqueTypes = types.filter((t) => !values.some((v) => v.name === t.name));
2840
2955
  dep += "\n";
2841
2956
  }
@@ -2862,7 +2977,7 @@ function generateDependencyImports(implementation, imports, projectName, hasSche
2862
2977
  projectName,
2863
2978
  hasSchemaDir,
2864
2979
  isAllowSyntheticDefaultImports
2865
- })).filter(Boolean).sort((a, b) => {
2980
+ })).filter((x) => Boolean(x)).toSorted((a, b) => {
2866
2981
  const aLib = getLibName(a);
2867
2982
  const bLib = getLibName(b);
2868
2983
  if (aLib === bLib) return 0;
@@ -2888,7 +3003,10 @@ function generateModelInline(acc, model) {
2888
3003
  return acc + `${model}\n`;
2889
3004
  }
2890
3005
  function generateModelsInline(obj) {
2891
- return Object.values(obj).flat().reduce((acc, { model }) => generateModelInline(acc, model), "");
3006
+ const schemas = Object.values(obj).flat();
3007
+ let result = "";
3008
+ for (const { model } of schemas) result = generateModelInline(result, model);
3009
+ return result;
2892
3010
  }
2893
3011
 
2894
3012
  //#endregion
@@ -2914,7 +3032,7 @@ async function bundleFile(root, fileName, alias, external, compilerOptions) {
2914
3032
  treeShaking: false,
2915
3033
  keepNames: false,
2916
3034
  alias,
2917
- external: external || ["*"]
3035
+ external: external ?? ["*"]
2918
3036
  })).outputFiles[0];
2919
3037
  return text;
2920
3038
  }
@@ -3059,7 +3177,7 @@ function generateAxiosOptions({ response, isExactOptionalPropertyTypes, queryPar
3059
3177
  if (headers) value += "\n headers,";
3060
3178
  if (hasSignal) value += isExactOptionalPropertyTypes ? `\n ...(${signalVar} ? { ${signalProp} } : {}),` : `\n ${signalProp},`;
3061
3179
  }
3062
- if (!isObject(requestOptions) || !requestOptions.hasOwnProperty("responseType")) {
3180
+ if (!isObject(requestOptions) || !Object.hasOwn(requestOptions, "responseType")) {
3063
3181
  if (response.isBlob) value += `\n responseType: 'blob',`;
3064
3182
  else if (response.contentTypes.at(0) === "text/plain") value += `\n responseType: 'text',`;
3065
3183
  }
@@ -3071,7 +3189,7 @@ function generateAxiosOptions({ response, isExactOptionalPropertyTypes, queryPar
3071
3189
  else value += "\n params: {...params, ...options?.params},";
3072
3190
  if (headers) value += "\n headers: {...headers, ...options?.headers},";
3073
3191
  }
3074
- if (!isAngular && queryParams && (paramsSerializer || paramsSerializerOptions?.qs)) value += paramsSerializer ? `\n paramsSerializer: ${paramsSerializer.name},` : `\n paramsSerializer: (params) => qs.stringify(params, ${JSON.stringify(paramsSerializerOptions.qs)}),`;
3192
+ if (!isAngular && queryParams && (paramsSerializer || paramsSerializerOptions?.qs)) value += paramsSerializer ? `\n paramsSerializer: ${paramsSerializer.name},` : `\n paramsSerializer: (params) => qs.stringify(params, ${JSON.stringify(paramsSerializerOptions?.qs)}),`;
3075
3193
  return value;
3076
3194
  }
3077
3195
  function generateOptions({ route, body, headers, queryParams, response, verb, requestOptions, isFormData, isFormUrlEncoded, isAngular, isExactOptionalPropertyTypes, hasSignal, hasSignalParam, isVue, paramsSerializer, paramsSerializerOptions }) {
@@ -3112,7 +3230,7 @@ function generateQueryParamsAxiosConfig(response, isVue, queryParams) {
3112
3230
  function generateMutatorConfig({ route, body, headers, queryParams, response, verb, isFormData, isFormUrlEncoded, hasSignal, hasSignalParam = false, isExactOptionalPropertyTypes, isVue }) {
3113
3231
  const bodyOptions = getIsBodyVerb(verb) ? generateBodyMutatorConfig(body, isFormData, isFormUrlEncoded) : "";
3114
3232
  const queryParamsOptions = generateQueryParamsAxiosConfig(response, isVue ?? false, queryParams);
3115
- const headerOptions = body.contentType ? `,\n headers: {'Content-Type': '${body.contentType}', ${headers ? "...headers" : ""}}` : headers ? ",\n headers" : "";
3233
+ const headerOptions = body.contentType && !["multipart/form-data"].includes(body.contentType) ? `,\n headers: {'Content-Type': '${body.contentType}', ${headers ? "...headers" : ""}}` : headers ? ",\n headers" : "";
3116
3234
  const signalVar = hasSignalParam ? "querySignal" : "signal";
3117
3235
  const signalProp = hasSignalParam ? `signal: ${signalVar}` : "signal";
3118
3236
  return `{url: \`${route}\`, method: '${verb.toUpperCase()}'${headerOptions}${bodyOptions}${queryParamsOptions}${hasSignal ? `, ${isExactOptionalPropertyTypes ? `...(${signalVar} ? { ${signalProp} }: {})` : signalProp}` : ""}\n }`;
@@ -3194,18 +3312,20 @@ function generateInterface({ name, schema, context }) {
3194
3312
  context
3195
3313
  });
3196
3314
  const isEmptyObject = scalar.value === "{}";
3197
- const shouldUseTypeAlias = context?.output.override?.useTypeOverInterfaces || scalar.useTypeAlias;
3315
+ const shouldUseTypeAlias = context.output.override.useTypeOverInterfaces ?? scalar.useTypeAlias;
3198
3316
  let model = "";
3199
3317
  model += jsDoc(schema);
3200
3318
  if (isEmptyObject) model += "// eslint-disable-next-line @typescript-eslint/no-empty-interface\n";
3201
- if (scalar.type === "object" && !shouldUseTypeAlias) if (scalar.type === "object" && schema.properties && Object.values(schema.properties).length > 0 && Object.values(schema.properties).every((item) => "const" in item)) {
3202
- const mappedScalarValue = scalar.value.replaceAll(";", ",").replaceAll("?:", ":");
3203
- model += `export const ${name}Value = ${mappedScalarValue} as const;\nexport type ${name} = typeof ${name}Value;\n`;
3204
- } else {
3205
- const blankInterfaceValue = scalar.value === "unknown" ? "{}" : scalar.value;
3206
- model += `export interface ${name} ${blankInterfaceValue}\n`;
3207
- }
3208
- else model += `export type ${name} = ${scalar.value};\n`;
3319
+ if (scalar.type === "object" && !shouldUseTypeAlias) {
3320
+ const properties = schema.properties;
3321
+ if (properties && Object.values(properties).length > 0 && Object.values(properties).every((item) => "const" in item)) {
3322
+ const mappedScalarValue = scalar.value.replaceAll(";", ",").replaceAll("?:", ":");
3323
+ model += `export const ${name}Value = ${mappedScalarValue} as const;\nexport type ${name} = typeof ${name}Value;\n`;
3324
+ } else {
3325
+ const blankInterfaceValue = scalar.value === "unknown" ? "{}" : scalar.value;
3326
+ model += `export interface ${name} ${blankInterfaceValue}\n`;
3327
+ }
3328
+ } else model += `export type ${name} = ${scalar.value};\n`;
3209
3329
  const externalModulesImportsOnly = scalar.imports.filter((importName) => importName.alias ? importName.alias !== name : importName.name !== name);
3210
3330
  return [...scalar.schemas, {
3211
3331
  name,
@@ -3255,7 +3375,7 @@ function sortSchemasByDependencies(schemas) {
3255
3375
  for (const dependencyName of schema.dependencies) if (dependencyName && schemaNames.has(dependencyName)) dependencies.add(dependencyName);
3256
3376
  }
3257
3377
  for (const imp of schema.imports) {
3258
- const dependencyName = imp.alias || imp.name;
3378
+ const dependencyName = imp.alias ?? imp.name;
3259
3379
  if (dependencyName && schemaNames.has(dependencyName)) dependencies.add(dependencyName);
3260
3380
  }
3261
3381
  dependencyMap.set(schema.name, dependencies);
@@ -3292,7 +3412,7 @@ function generateSchemaDefinitions(schemaName, schema, context, suffix) {
3292
3412
  es5keyword: true,
3293
3413
  es5IdentifierName: true
3294
3414
  });
3295
- if (typeof schema === "boolean") return [{
3415
+ if (isBoolean(schema)) return [{
3296
3416
  name: sanitizedSchemaName,
3297
3417
  model: `export type ${sanitizedSchemaName} = ${schema ? "any" : "never"};\n`,
3298
3418
  imports: [],
@@ -3311,7 +3431,7 @@ function generateSchemaDefinitions(schemaName, schema, context, suffix) {
3311
3431
  let output = "";
3312
3432
  let imports = resolvedValue.imports;
3313
3433
  output += jsDoc(schema);
3314
- if (resolvedValue.isEnum && !resolvedValue.isRef) output += getEnum(resolvedValue.value, sanitizedSchemaName, getEnumNames(resolvedValue.originalSchema), context.output.override.enumGenerationType, getEnumDescriptions(resolvedValue.originalSchema), context.output.override.namingConvention?.enum);
3434
+ if (resolvedValue.isEnum && !resolvedValue.isRef) output += getEnum(resolvedValue.value, sanitizedSchemaName, getEnumNames(resolvedValue.originalSchema), context.output.override.enumGenerationType, getEnumDescriptions(resolvedValue.originalSchema), context.output.override.namingConvention.enum);
3315
3435
  else if (sanitizedSchemaName === resolvedValue.value && resolvedValue.isRef) {
3316
3436
  const { schema: referredSchema } = resolveRef(schema, context);
3317
3437
  if (!shouldCreateInterface(referredSchema)) {
@@ -3330,7 +3450,7 @@ function generateSchemaDefinitions(schemaName, schema, context, suffix) {
3330
3450
  resolvedValue.schemas = resolvedValue.schemas.filter((schema$1) => {
3331
3451
  if (schema$1.name !== sanitizedSchemaName) return true;
3332
3452
  output += `${schema$1.model}\n`;
3333
- imports = imports.concat(schema$1.imports);
3453
+ imports = [...imports, ...schema$1.imports];
3334
3454
  resolvedValue.dependencies.push(...schema$1.dependencies ?? []);
3335
3455
  return false;
3336
3456
  });
@@ -3347,26 +3467,56 @@ function generateSchemaDefinitions(schemaName, schema, context, suffix) {
3347
3467
 
3348
3468
  //#endregion
3349
3469
  //#region src/generators/verbs-options.ts
3350
- async function generateVerbOptions({ verb, output, operation, route, pathRoute, verbParameters = [], context }) {
3351
- const { responses, requestBody, parameters: operationParameters, tags = [], deprecated, description, summary } = operation;
3470
+ /**
3471
+ * Get a content-type specific suffix for operation names (#2812)
3472
+ */
3473
+ function getContentTypeSuffix(contentType) {
3474
+ return {
3475
+ "application/json": "Json",
3476
+ "multipart/form-data": "FormData",
3477
+ "application/x-www-form-urlencoded": "UrlEncoded",
3478
+ "application/xml": "Xml",
3479
+ "text/plain": "Text"
3480
+ }[contentType] || pascal(contentType.replaceAll(/[^a-zA-Z0-9]/g, "_"));
3481
+ }
3482
+ async function generateVerbOptions({ verb, output, operation, route, pathRoute, verbParameters = [], context, contentType }) {
3483
+ const { responses, requestBody, parameters: operationParameters, tags: rawTags, deprecated: rawDeprecated, description: rawDescription, summary: rawSummary } = operation;
3484
+ const tags = rawTags ?? [];
3485
+ const deprecated = rawDeprecated;
3486
+ const description = rawDescription;
3487
+ const summary = rawSummary;
3352
3488
  const operationId = getOperationId(operation, route, verb);
3353
3489
  const overrideOperation = output.override.operations[operationId];
3354
- const overrideTag = Object.entries(output.override.tags).reduce((acc, [tag, options]) => tags.includes(tag) && options ? mergeDeep(acc, options) : acc, {});
3355
- const override = mergeDeep(mergeDeep(output.override, overrideTag), overrideOperation);
3490
+ let overrideTag = {};
3491
+ for (const [tag, options] of Object.entries(output.override.tags)) if (tags.includes(tag) && options) overrideTag = mergeDeep(overrideTag, options);
3492
+ const override = mergeDeep(mergeDeep(output.override, overrideTag), overrideOperation ?? {});
3493
+ const originalContentTypeFilter = override.contentType;
3494
+ const requestBodyContentTypeFilter = contentType ? { include: [contentType] } : override.contentType;
3356
3495
  const overrideOperationName = overrideOperation?.operationName ?? output.override.operationName;
3357
- const operationName = overrideOperationName ? overrideOperationName(operation, route, verb) : sanitize(camel(operationId), { es5keyword: true });
3496
+ let operationName = overrideOperationName ? overrideOperationName(operation, route, verb) : sanitize(camel(operationId), { es5keyword: true });
3497
+ if (contentType) operationName = operationName + "With" + getContentTypeSuffix(contentType);
3358
3498
  const response = getResponse({
3359
- responses,
3499
+ responses: responses ?? {},
3360
3500
  operationName,
3361
3501
  context,
3362
- contentType: override.contentType
3502
+ contentType: originalContentTypeFilter
3363
3503
  });
3364
- const body = getBody({
3504
+ const body = requestBody ? getBody({
3365
3505
  requestBody,
3366
3506
  operationName,
3367
3507
  context,
3368
- contentType: override.contentType
3369
- });
3508
+ contentType: requestBodyContentTypeFilter
3509
+ }) : {
3510
+ originalSchema: {},
3511
+ definition: "",
3512
+ implementation: "",
3513
+ imports: [],
3514
+ schemas: [],
3515
+ formData: "",
3516
+ formUrlEncoded: "",
3517
+ contentType: "",
3518
+ isOptional: false
3519
+ };
3370
3520
  const parameters = getParameters({
3371
3521
  parameters: [...verbParameters, ...operationParameters ?? []],
3372
3522
  context
@@ -3442,7 +3592,7 @@ async function generateVerbOptions({ verb, output, operation, route, pathRoute,
3442
3592
  tags,
3443
3593
  route,
3444
3594
  pathRoute,
3445
- summary: operation.summary,
3595
+ summary,
3446
3596
  operationId,
3447
3597
  operationName,
3448
3598
  response,
@@ -3467,23 +3617,39 @@ async function generateVerbOptions({ verb, output, operation, route, pathRoute,
3467
3617
  function generateVerbsOptions({ verbs, input, output, route, pathRoute, context }) {
3468
3618
  return asyncReduce(_filteredVerbs(verbs, input.filters), async (acc, [verb, operation]) => {
3469
3619
  if (isVerb(verb)) {
3470
- const verbOptions = await generateVerbOptions({
3471
- verb,
3472
- output,
3473
- verbParameters: verbs.parameters,
3474
- route,
3475
- pathRoute,
3476
- operation,
3477
- context
3478
- });
3479
- acc.push(verbOptions);
3620
+ const contentTypes = getRequestBodyContentTypes(operation.requestBody, context);
3621
+ if (contentTypes.length > 1) for (const contentType of contentTypes) {
3622
+ const verbOptions = await generateVerbOptions({
3623
+ verb,
3624
+ output,
3625
+ verbParameters: verbs.parameters,
3626
+ route,
3627
+ pathRoute,
3628
+ operation,
3629
+ context,
3630
+ contentType
3631
+ });
3632
+ acc.push(verbOptions);
3633
+ }
3634
+ else {
3635
+ const verbOptions = await generateVerbOptions({
3636
+ verb,
3637
+ output,
3638
+ verbParameters: verbs.parameters,
3639
+ route,
3640
+ pathRoute,
3641
+ operation,
3642
+ context
3643
+ });
3644
+ acc.push(verbOptions);
3645
+ }
3480
3646
  }
3481
3647
  return acc;
3482
3648
  }, []);
3483
3649
  }
3484
3650
  function _filteredVerbs(verbs, filters) {
3485
3651
  if (filters?.tags === void 0) return Object.entries(verbs);
3486
- const filterTags = filters.tags || [];
3652
+ const filterTags = filters.tags;
3487
3653
  const filterMode = filters.mode ?? "include";
3488
3654
  return Object.entries(verbs).filter(([, operation]) => {
3489
3655
  const isMatch = (operation.tags ?? []).some((tag) => filterTags.some((filterTag) => filterTag instanceof RegExp ? filterTag.test(tag) : filterTag === tag));
@@ -3529,17 +3695,25 @@ function splitSchemasByType(schemas) {
3529
3695
  };
3530
3696
  }
3531
3697
  /**
3698
+ * Get the import extension from a file extension.
3699
+ * Removes `.ts` suffix since TypeScript doesn't need it in imports.
3700
+ */
3701
+ function getImportExtension(fileExtension) {
3702
+ return fileExtension.replace(/\.ts$/, "") || "";
3703
+ }
3704
+ /**
3532
3705
  * Fix cross-directory imports when schemas reference other schemas in a different directory.
3533
3706
  * Updates import paths to use correct relative paths between directories.
3534
3707
  */
3535
- function fixSchemaImports(schemas, targetSchemaNames, fromPath, toPath, namingConvention) {
3708
+ function fixSchemaImports(schemas, targetSchemaNames, fromPath, toPath, namingConvention, fileExtension) {
3536
3709
  const relativePath = relativeSafe(fromPath, toPath);
3710
+ const importExtension = getImportExtension(fileExtension);
3537
3711
  for (const schema of schemas) schema.imports = schema.imports.map((imp) => {
3538
3712
  if (targetSchemaNames.has(imp.name)) {
3539
3713
  const fileName = conventionName(imp.name, namingConvention);
3540
3714
  return {
3541
3715
  ...imp,
3542
- importPath: joinSafe(relativePath, fileName)
3716
+ importPath: joinSafe(relativePath, fileName) + importExtension
3543
3717
  };
3544
3718
  }
3545
3719
  return imp;
@@ -3548,14 +3722,14 @@ function fixSchemaImports(schemas, targetSchemaNames, fromPath, toPath, namingCo
3548
3722
  /**
3549
3723
  * Fix imports in operation schemas that reference regular schemas.
3550
3724
  */
3551
- function fixCrossDirectoryImports(operationSchemas, regularSchemaNames, schemaPath, operationSchemaPath, namingConvention) {
3552
- fixSchemaImports(operationSchemas, regularSchemaNames, operationSchemaPath, schemaPath, namingConvention);
3725
+ function fixCrossDirectoryImports(operationSchemas, regularSchemaNames, schemaPath, operationSchemaPath, namingConvention, fileExtension) {
3726
+ fixSchemaImports(operationSchemas, regularSchemaNames, operationSchemaPath, schemaPath, namingConvention, fileExtension);
3553
3727
  }
3554
3728
  /**
3555
3729
  * Fix imports in regular schemas that reference operation schemas.
3556
3730
  */
3557
- function fixRegularSchemaImports(regularSchemas, operationSchemaNames, schemaPath, operationSchemaPath, namingConvention) {
3558
- fixSchemaImports(regularSchemas, operationSchemaNames, schemaPath, operationSchemaPath, namingConvention);
3731
+ function fixRegularSchemaImports(regularSchemas, operationSchemaNames, schemaPath, operationSchemaPath, namingConvention, fileExtension) {
3732
+ fixSchemaImports(regularSchemas, operationSchemaNames, schemaPath, operationSchemaPath, namingConvention, fileExtension);
3559
3733
  }
3560
3734
  function getSchemaKey(schemaPath, schemaName, namingConvention, fileExtension) {
3561
3735
  return getPath(schemaPath, conventionName(schemaName, namingConvention), fileExtension).toLowerCase().replaceAll("\\", "/");
@@ -3608,7 +3782,7 @@ function removeFileExtension(path$2, fileExtension) {
3608
3782
  function getSchema({ schema: { imports, model }, target, header, namingConvention = NamingConvention.CAMEL_CASE }) {
3609
3783
  let file = header;
3610
3784
  file += generateImports({
3611
- imports: imports.filter((imp) => !model.includes(`type ${imp.alias || imp.name} =`) && !model.includes(`interface ${imp.alias || imp.name} {`)),
3785
+ imports: imports.filter((imp) => !model.includes(`type ${imp.alias ?? imp.name} =`) && !model.includes(`interface ${imp.alias ?? imp.name} {`)),
3612
3786
  target,
3613
3787
  namingConvention
3614
3788
  });
@@ -3637,7 +3811,7 @@ async function writeSchema({ path: path$2, schema, target, namingConvention, fil
3637
3811
  namingConvention
3638
3812
  }));
3639
3813
  } catch (error) {
3640
- throw new Error(`Oups... 🍻. An Error occurred while writing schema ${name} => ${error}`);
3814
+ throw new Error(`Oups... 🍻. An Error occurred while writing schema ${name} => ${String(error)}`);
3641
3815
  }
3642
3816
  }
3643
3817
  async function writeSchemas({ schemaPath, schemas, target, namingConvention, fileExtension, header, indexFiles }) {
@@ -3672,14 +3846,14 @@ async function writeSchemas({ schemaPath, schemas, target, namingConvention, fil
3672
3846
  try {
3673
3847
  const currentExports = [...conventionNamesSet].map((schemaName) => `export * from './${schemaName}${ext}';`).toSorted((a, b) => a.localeCompare(b));
3674
3848
  const existingExports = (await fs$1.readFile(schemaFilePath, "utf8")).match(/export\s+\*\s+from\s+['"][^'"]+['"]/g)?.map((statement) => {
3675
- const match = statement.match(/export\s+\*\s+from\s+['"]([^'"]+)['"]/);
3676
- if (!match) return void 0;
3849
+ const match = /export\s+\*\s+from\s+['"]([^'"]+)['"]/.exec(statement);
3850
+ if (!match) return;
3677
3851
  return `export * from '${match[1]}';`;
3678
- }).filter((statement) => Boolean(statement)) ?? [];
3852
+ }).filter(Boolean) ?? [];
3679
3853
  const fileContent = `${header}\n${[...new Set([...existingExports, ...currentExports])].toSorted((a, b) => a.localeCompare(b)).join("\n")}`;
3680
3854
  await fs$1.writeFile(schemaFilePath, fileContent, { encoding: "utf8" });
3681
3855
  } catch (error) {
3682
- throw new Error(`Oups... 🍻. An Error occurred while writing schema index file ${schemaFilePath} => ${error}`);
3856
+ throw new Error(`Oups... 🍻. An Error occurred while writing schema index file ${schemaFilePath} => ${String(error)}`);
3683
3857
  }
3684
3858
  }
3685
3859
  }
@@ -3688,10 +3862,20 @@ async function writeSchemas({ schemaPath, schemas, target, namingConvention, fil
3688
3862
  //#region src/writers/generate-imports-for-builder.ts
3689
3863
  function generateImportsForBuilder(output, imports, relativeSchemasPath) {
3690
3864
  const isZodSchemaOutput = isObject(output.schemas) && output.schemas.type === "zod";
3691
- if (!output.indexFiles) return uniqueBy(imports, (x) => x.name).map((i) => {
3692
- const name = conventionName(i.schemaName || i.name, output.namingConvention);
3865
+ if (output.indexFiles) return isZodSchemaOutput ? [{
3866
+ exports: imports.map((i) => ({
3867
+ ...i,
3868
+ values: true
3869
+ })),
3870
+ dependency: joinSafe(relativeSchemasPath, "index.zod")
3871
+ }] : [{
3872
+ exports: imports,
3873
+ dependency: relativeSchemasPath
3874
+ }];
3875
+ else return uniqueBy(imports, (x) => x.name).map((i) => {
3876
+ const name = conventionName(i.schemaName ?? i.name, output.namingConvention);
3693
3877
  const suffix = isZodSchemaOutput ? ".zod" : "";
3694
- const importExtension = output.fileExtension?.replace(/\.ts$/, "") || "";
3878
+ const importExtension = output.fileExtension.replace(/\.ts$/, "") || "";
3695
3879
  return {
3696
3880
  exports: isZodSchemaOutput ? [{
3697
3881
  ...i,
@@ -3700,46 +3884,52 @@ function generateImportsForBuilder(output, imports, relativeSchemasPath) {
3700
3884
  dependency: joinSafe(relativeSchemasPath, `${name}${suffix}${importExtension}`)
3701
3885
  };
3702
3886
  });
3703
- else if (isZodSchemaOutput) return [{
3704
- exports: imports.map((i) => ({
3705
- ...i,
3706
- values: true
3707
- })),
3708
- dependency: joinSafe(relativeSchemasPath, "index.zod")
3709
- }];
3710
- else return [{
3711
- exports: imports,
3712
- dependency: relativeSchemasPath
3713
- }];
3714
3887
  }
3715
3888
 
3716
3889
  //#endregion
3717
3890
  //#region src/writers/target.ts
3718
3891
  function generateTarget(builder, options) {
3719
3892
  const operationNames = Object.values(builder.operations).map(({ operationName }) => operationName);
3720
- const isAngularClient = options?.client === OutputClient.ANGULAR;
3893
+ const isAngularClient = options.client === OutputClient.ANGULAR;
3721
3894
  const titles = builder.title({
3722
3895
  outputClient: options.client,
3723
3896
  title: pascal(builder.info.title),
3724
3897
  customTitleFunc: options.override.title,
3725
3898
  output: options
3726
3899
  });
3727
- const target = Object.values(builder.operations).reduce((acc, operation, index, arr) => {
3728
- acc.imports.push(...operation.imports);
3729
- acc.importsMock.push(...operation.importsMock);
3730
- acc.implementation += operation.implementation + "\n";
3731
- acc.implementationMock.function += operation.implementationMock.function;
3732
- acc.implementationMock.handler += operation.implementationMock.handler;
3733
- const handlerNameSeparator = acc.implementationMock.handlerName.length > 0 ? ",\n " : " ";
3734
- acc.implementationMock.handlerName += handlerNameSeparator + operation.implementationMock.handlerName + "()";
3735
- if (operation.mutator) acc.mutators.push(operation.mutator);
3736
- if (operation.formData) acc.formData.push(operation.formData);
3737
- if (operation.formUrlEncoded) acc.formUrlEncoded.push(operation.formUrlEncoded);
3738
- if (operation.paramsSerializer) acc.paramsSerializer.push(operation.paramsSerializer);
3739
- if (operation.clientMutators) acc.clientMutators.push(...operation.clientMutators);
3740
- if (operation.fetchReviver) acc.fetchReviver.push(operation.fetchReviver);
3741
- if (index === arr.length - 1) {
3742
- const isMutator = acc.mutators.some((mutator) => isAngularClient ? mutator.hasThirdArg : mutator.hasSecondArg);
3900
+ const target = {
3901
+ imports: [],
3902
+ implementation: "",
3903
+ implementationMock: {
3904
+ function: "",
3905
+ handler: "",
3906
+ handlerName: ""
3907
+ },
3908
+ importsMock: [],
3909
+ mutators: [],
3910
+ clientMutators: [],
3911
+ formData: [],
3912
+ formUrlEncoded: [],
3913
+ paramsSerializer: [],
3914
+ fetchReviver: []
3915
+ };
3916
+ const operations = Object.values(builder.operations);
3917
+ for (const [index, operation] of operations.entries()) {
3918
+ target.imports.push(...operation.imports);
3919
+ target.importsMock.push(...operation.importsMock);
3920
+ target.implementation += operation.implementation + "\n";
3921
+ target.implementationMock.function += operation.implementationMock.function;
3922
+ target.implementationMock.handler += operation.implementationMock.handler;
3923
+ const handlerNameSeparator = target.implementationMock.handlerName.length > 0 ? ",\n " : " ";
3924
+ target.implementationMock.handlerName += handlerNameSeparator + operation.implementationMock.handlerName + "()";
3925
+ if (operation.mutator) target.mutators.push(operation.mutator);
3926
+ if (operation.formData) target.formData.push(operation.formData);
3927
+ if (operation.formUrlEncoded) target.formUrlEncoded.push(operation.formUrlEncoded);
3928
+ if (operation.paramsSerializer) target.paramsSerializer.push(operation.paramsSerializer);
3929
+ if (operation.clientMutators) target.clientMutators.push(...operation.clientMutators);
3930
+ if (operation.fetchReviver) target.fetchReviver.push(operation.fetchReviver);
3931
+ if (index === operations.length - 1) {
3932
+ const isMutator = target.mutators.some((mutator) => isAngularClient ? mutator.hasThirdArg : mutator.hasSecondArg);
3743
3933
  const hasAwaitedType = compareVersions(options.packageJson?.dependencies?.typescript ?? options.packageJson?.devDependencies?.typescript ?? "4.4.0", "4.5.0");
3744
3934
  const header = builder.header({
3745
3935
  outputClient: options.client,
@@ -3751,38 +3941,22 @@ function generateTarget(builder, options) {
3751
3941
  titles,
3752
3942
  output: options,
3753
3943
  verbOptions: builder.verbOptions,
3754
- clientImplementation: acc.implementation
3944
+ clientImplementation: target.implementation
3755
3945
  });
3756
- acc.implementation = header.implementation + acc.implementation;
3757
- acc.implementationMock.handler = acc.implementationMock.handler + header.implementationMock + acc.implementationMock.handlerName;
3946
+ target.implementation = header.implementation + target.implementation;
3947
+ target.implementationMock.handler = target.implementationMock.handler + header.implementationMock + target.implementationMock.handlerName;
3758
3948
  const footer = builder.footer({
3759
- outputClient: options?.client,
3949
+ outputClient: options.client,
3760
3950
  operationNames,
3761
- hasMutator: acc.mutators.length > 0,
3951
+ hasMutator: target.mutators.length > 0,
3762
3952
  hasAwaitedType,
3763
3953
  titles,
3764
3954
  output: options
3765
3955
  });
3766
- acc.implementation += footer.implementation;
3767
- acc.implementationMock.handler += footer.implementationMock;
3956
+ target.implementation += footer.implementation;
3957
+ target.implementationMock.handler += footer.implementationMock;
3768
3958
  }
3769
- return acc;
3770
- }, {
3771
- imports: [],
3772
- implementation: "",
3773
- implementationMock: {
3774
- function: "",
3775
- handler: "",
3776
- handlerName: ""
3777
- },
3778
- importsMock: [],
3779
- mutators: [],
3780
- clientMutators: [],
3781
- formData: [],
3782
- formUrlEncoded: [],
3783
- paramsSerializer: [],
3784
- fetchReviver: []
3785
- });
3959
+ }
3786
3960
  return {
3787
3961
  ...target,
3788
3962
  implementationMock: target.implementationMock.function + target.implementationMock.handler
@@ -3838,7 +4012,7 @@ async function writeSingleMode({ builder, output, projectName, header, needSchem
3838
4012
  });
3839
4013
  const { imports, importsMock, implementation, implementationMock, mutators, clientMutators, formData, formUrlEncoded, paramsSerializer, fetchReviver } = generateTarget(builder, output);
3840
4014
  let data = header;
3841
- const schemasPath = output.schemas ? relativeSafe(dirname$1, getFileInfo(typeof output.schemas === "string" ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : void 0;
4015
+ const schemasPath = output.schemas ? relativeSafe(dirname$1, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : void 0;
3842
4016
  const isAllowSyntheticDefaultImports = isSyntheticDefaultImportsAllow(output.tsconfig);
3843
4017
  const importsForBuilder = schemasPath ? generateImportsForBuilder(output, imports.filter((imp) => !importsMock.some((impMock) => imp.name === impMock.name)), schemasPath) : [];
3844
4018
  data += builder.imports({
@@ -3907,7 +4081,7 @@ async function writeSplitMode({ builder, output, projectName, header, needSchema
3907
4081
  const { imports, implementation, implementationMock, importsMock, mutators, clientMutators, formData, formUrlEncoded, paramsSerializer, fetchReviver } = generateTarget(builder, output);
3908
4082
  let implementationData = header;
3909
4083
  let mockData = header;
3910
- const relativeSchemasPath = output.schemas ? relativeSafe(dirname$1, getFileInfo(typeof output.schemas === "string" ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : "./" + filename + ".schemas";
4084
+ const relativeSchemasPath = output.schemas ? relativeSafe(dirname$1, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : "./" + filename + ".schemas";
3911
4085
  const isAllowSyntheticDefaultImports = isSyntheticDefaultImportsAllow(output.tsconfig);
3912
4086
  const importsForBuilder = generateImportsForBuilder(output, imports, relativeSchemasPath);
3913
4087
  implementationData += builder.imports({
@@ -3967,7 +4141,7 @@ async function writeSplitMode({ builder, output, projectName, header, needSchema
3967
4141
  ...mockPath ? [mockPath] : []
3968
4142
  ];
3969
4143
  } catch (error) {
3970
- throw new Error(`Oups... 🍻. An Error occurred while splitting => ${error}`);
4144
+ throw new Error(`Oups... 🍻. An Error occurred while splitting => ${String(error)}`);
3971
4145
  }
3972
4146
  }
3973
4147
 
@@ -3981,8 +4155,7 @@ function addDefaultTagIfEmpty(operation) {
3981
4155
  }
3982
4156
  function generateTargetTags(currentAcc, operation) {
3983
4157
  const tag = kebab(operation.tags[0]);
3984
- const currentOperation = currentAcc[tag];
3985
- if (!currentOperation) {
4158
+ if (!(tag in currentAcc)) {
3986
4159
  currentAcc[tag] = {
3987
4160
  imports: operation.imports,
3988
4161
  importsMock: operation.importsMock,
@@ -4001,6 +4174,7 @@ function generateTargetTags(currentAcc, operation) {
4001
4174
  };
4002
4175
  return currentAcc;
4003
4176
  }
4177
+ const currentOperation = currentAcc[tag];
4004
4178
  currentAcc[tag] = {
4005
4179
  implementation: currentOperation.implementation + operation.implementation,
4006
4180
  imports: [...currentOperation.imports, ...operation.imports],
@@ -4021,66 +4195,69 @@ function generateTargetTags(currentAcc, operation) {
4021
4195
  }
4022
4196
  function generateTargetForTags(builder, options) {
4023
4197
  const isAngularClient = options.client === OutputClient.ANGULAR;
4024
- const allTargetTags = Object.values(builder.operations).map((operation) => addDefaultTagIfEmpty(operation)).reduce((acc, operation, index, arr) => {
4025
- const targetTags = generateTargetTags(acc, operation);
4026
- if (index === arr.length - 1) return Object.entries(targetTags).reduce((acc$1, [tag, target]) => {
4027
- const isMutator = !!target.mutators?.some((mutator) => isAngularClient ? mutator.hasThirdArg : mutator.hasSecondArg);
4028
- const operationNames = Object.values(builder.operations).filter(({ tags }) => tags.map((tag$1) => kebab(tag$1)).indexOf(kebab(tag)) === 0).map(({ operationName }) => operationName);
4029
- const hasAwaitedType = compareVersions(options.packageJson?.dependencies?.typescript ?? options.packageJson?.devDependencies?.typescript ?? "4.4.0", "4.5.0");
4030
- const titles = builder.title({
4031
- outputClient: options.client,
4032
- title: pascal(tag),
4033
- customTitleFunc: options.override.title,
4034
- output: options
4035
- });
4036
- const footer = builder.footer({
4037
- outputClient: options?.client,
4038
- operationNames,
4039
- hasMutator: !!target.mutators?.length,
4040
- hasAwaitedType,
4041
- titles,
4042
- output: options
4043
- });
4044
- const header = builder.header({
4045
- outputClient: options.client,
4046
- isRequestOptions: options.override.requestOptions !== false,
4047
- isMutator,
4048
- isGlobalMutator: !!options.override.mutator,
4049
- provideIn: options.override.angular.provideIn,
4050
- hasAwaitedType,
4051
- titles,
4052
- output: options,
4053
- verbOptions: builder.verbOptions,
4054
- tag,
4055
- clientImplementation: target.implementation
4056
- });
4057
- acc$1[tag] = {
4058
- implementation: header.implementation + target.implementation + footer.implementation,
4059
- implementationMock: {
4060
- function: target.implementationMock.function,
4061
- handler: target.implementationMock.handler + header.implementationMock + target.implementationMock.handlerName + footer.implementationMock,
4062
- handlerName: target.implementationMock.handlerName
4063
- },
4064
- imports: target.imports,
4065
- importsMock: target.importsMock,
4066
- mutators: target.mutators,
4067
- clientMutators: target.clientMutators,
4068
- formData: target.formData,
4069
- formUrlEncoded: target.formUrlEncoded,
4070
- paramsSerializer: target.paramsSerializer,
4071
- fetchReviver: target.fetchReviver
4072
- };
4073
- return acc$1;
4074
- }, {});
4075
- return targetTags;
4076
- }, {});
4077
- return Object.entries(allTargetTags).reduce((acc, [tag, target]) => {
4078
- acc[tag] = {
4079
- ...target,
4080
- implementationMock: target.implementationMock.function + target.implementationMock.handler
4081
- };
4082
- return acc;
4083
- }, {});
4198
+ const operations = Object.values(builder.operations).map((operation) => addDefaultTagIfEmpty(operation));
4199
+ let allTargetTags = {};
4200
+ for (const [index, operation] of operations.entries()) {
4201
+ allTargetTags = generateTargetTags(allTargetTags, operation);
4202
+ if (index === operations.length - 1) {
4203
+ const transformed = {};
4204
+ for (const [tag, target] of Object.entries(allTargetTags)) {
4205
+ const isMutator = !!target.mutators?.some((mutator) => isAngularClient ? mutator.hasThirdArg : mutator.hasSecondArg);
4206
+ const operationNames = Object.values(builder.operations).filter(({ tags }) => tags.map((tag$1) => kebab(tag$1)).indexOf(kebab(tag)) === 0).map(({ operationName }) => operationName);
4207
+ const hasAwaitedType = compareVersions(options.packageJson?.dependencies?.typescript ?? options.packageJson?.devDependencies?.typescript ?? "4.4.0", "4.5.0");
4208
+ const titles = builder.title({
4209
+ outputClient: options.client,
4210
+ title: pascal(tag),
4211
+ customTitleFunc: options.override.title,
4212
+ output: options
4213
+ });
4214
+ const footer = builder.footer({
4215
+ outputClient: options.client,
4216
+ operationNames,
4217
+ hasMutator: !!target.mutators?.length,
4218
+ hasAwaitedType,
4219
+ titles,
4220
+ output: options
4221
+ });
4222
+ const header = builder.header({
4223
+ outputClient: options.client,
4224
+ isRequestOptions: options.override.requestOptions !== false,
4225
+ isMutator,
4226
+ isGlobalMutator: !!options.override.mutator,
4227
+ provideIn: options.override.angular.provideIn,
4228
+ hasAwaitedType,
4229
+ titles,
4230
+ output: options,
4231
+ verbOptions: builder.verbOptions,
4232
+ tag,
4233
+ clientImplementation: target.implementation
4234
+ });
4235
+ transformed[tag] = {
4236
+ implementation: header.implementation + target.implementation + footer.implementation,
4237
+ implementationMock: {
4238
+ function: target.implementationMock.function,
4239
+ handler: target.implementationMock.handler + header.implementationMock + target.implementationMock.handlerName + footer.implementationMock,
4240
+ handlerName: target.implementationMock.handlerName
4241
+ },
4242
+ imports: target.imports,
4243
+ importsMock: target.importsMock,
4244
+ mutators: target.mutators,
4245
+ clientMutators: target.clientMutators,
4246
+ formData: target.formData,
4247
+ formUrlEncoded: target.formUrlEncoded,
4248
+ paramsSerializer: target.paramsSerializer,
4249
+ fetchReviver: target.fetchReviver
4250
+ };
4251
+ }
4252
+ allTargetTags = transformed;
4253
+ }
4254
+ }
4255
+ const result = {};
4256
+ for (const [tag, target] of Object.entries(allTargetTags)) result[tag] = {
4257
+ ...target,
4258
+ implementationMock: target.implementationMock.function + target.implementationMock.handler
4259
+ };
4260
+ return result;
4084
4261
  }
4085
4262
 
4086
4263
  //#endregion
@@ -4092,14 +4269,15 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
4092
4269
  });
4093
4270
  const target = generateTargetForTags(builder, output);
4094
4271
  const isAllowSyntheticDefaultImports = isSyntheticDefaultImportsAllow(output.tsconfig);
4095
- const indexFilePath = output.mock && !isFunction(output.mock) && output.mock.indexMockFiles ? join(dirname$1, "index." + getMockFileExtensionByTypeName(output.mock) + extension) : void 0;
4272
+ const mockOption = output.mock && !isFunction(output.mock) ? output.mock : void 0;
4273
+ const indexFilePath = mockOption?.indexMockFiles ? join(dirname$1, "index." + getMockFileExtensionByTypeName(mockOption) + extension) : void 0;
4096
4274
  if (indexFilePath) await fs$1.outputFile(indexFilePath, "");
4097
4275
  return (await Promise.all(Object.entries(target).map(async ([tag, target$1]) => {
4098
4276
  try {
4099
4277
  const { imports, implementation, implementationMock, importsMock, mutators, clientMutators, formData, fetchReviver, formUrlEncoded, paramsSerializer } = target$1;
4100
4278
  let implementationData = header;
4101
4279
  let mockData = header;
4102
- const relativeSchemasPath = output.schemas ? "../" + relativeSafe(dirname$1, getFileInfo(typeof output.schemas === "string" ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : "../" + filename + ".schemas";
4280
+ const relativeSchemasPath = output.schemas ? "../" + relativeSafe(dirname$1, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : "../" + filename + ".schemas";
4103
4281
  const importsForBuilder = generateImportsForBuilder(output, imports, relativeSchemasPath);
4104
4282
  implementationData += builder.imports({
4105
4283
  client: output.client,
@@ -4169,9 +4347,9 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
4169
4347
  const mockPath = output.mock ? join(dirname$1, tag, tag + "." + getMockFileExtensionByTypeName(output.mock) + extension) : void 0;
4170
4348
  if (mockPath) {
4171
4349
  await fs$1.outputFile(mockPath, mockData);
4172
- if (indexFilePath) {
4173
- const localMockPath = joinSafe("./", tag, tag + "." + getMockFileExtensionByTypeName(output.mock));
4174
- fs$1.appendFile(indexFilePath, `export { get${pascal(tag)}Mock } from '${localMockPath}'\n`);
4350
+ if (indexFilePath && mockOption) {
4351
+ const localMockPath = joinSafe("./", tag, tag + "." + getMockFileExtensionByTypeName(mockOption));
4352
+ await fs$1.appendFile(indexFilePath, `export { get${pascal(tag)}Mock } from '${localMockPath}'\n`);
4175
4353
  }
4176
4354
  }
4177
4355
  return [
@@ -4180,7 +4358,7 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
4180
4358
  ...mockPath ? [mockPath] : []
4181
4359
  ];
4182
4360
  } catch (error) {
4183
- throw new Error(`Oups... 🍻. An Error occurred while splitting tag ${tag} => ${error}`);
4361
+ throw new Error(`Oups... 🍻. An Error occurred while splitting tag ${tag} => ${String(error)}`);
4184
4362
  }
4185
4363
  }))).flat();
4186
4364
  }
@@ -4198,7 +4376,7 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema
4198
4376
  try {
4199
4377
  const { imports, implementation, implementationMock, importsMock, mutators, clientMutators, formData, formUrlEncoded, fetchReviver, paramsSerializer } = target$1;
4200
4378
  let data = header;
4201
- const schemasPathRelative = output.schemas ? relativeSafe(dirname$1, getFileInfo(typeof output.schemas === "string" ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : "./" + filename + ".schemas";
4379
+ const schemasPathRelative = output.schemas ? relativeSafe(dirname$1, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : "./" + filename + ".schemas";
4202
4380
  const importsForBuilder = generateImportsForBuilder(output, imports.filter((imp) => !importsMock.some((impMock) => imp.name === impMock.name)), schemasPathRelative);
4203
4381
  data += builder.imports({
4204
4382
  client: output.client,
@@ -4256,11 +4434,11 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema
4256
4434
  await fs$1.outputFile(implementationPath, data);
4257
4435
  return [implementationPath, ...schemasPath ? [schemasPath] : []];
4258
4436
  } catch (error) {
4259
- throw new Error(`Oups... 🍻. An Error occurred while writing tag ${tag} => ${error}`);
4437
+ throw new Error(`Oups... 🍻. An Error occurred while writing tag ${tag} => ${String(error)}`);
4260
4438
  }
4261
4439
  }))).flat();
4262
4440
  }
4263
4441
 
4264
4442
  //#endregion
4265
- export { BODY_TYPE_NAME, EnumGeneration, ErrorWithTag, FormDataArrayHandling, GetterPropType, LogLevels, NamingConvention, OutputClient, OutputHttpClient, OutputMockType, OutputMode, PropertySortOrder, RefComponentSuffix, SchemaType, TEMPLATE_TAG_REGEX, URL_REGEX, VERBS_WITH_BODY, Verbs, _filteredVerbs, addDependency, asyncReduce, camel, combineSchemas, compareVersions, conventionName, count, createDebugger, createLogger, createSuccessMessage, createTypeAliasIfNeeded, dedupeUnionType, dynamicImport, escape, fixCrossDirectoryImports, fixRegularSchemaImports, generalJSTypes, generalJSTypesWithArray, generateAxiosOptions, generateBodyMutatorConfig, generateBodyOptions, generateComponentDefinition, generateDependencyImports, generateFormDataAndUrlEncodedFunction, generateImports, generateModelInline, generateModelsInline, generateMutator, generateMutatorConfig, generateMutatorImports, generateMutatorRequestOptions, generateOptions, generateParameterDefinition, generateQueryParamsAxiosConfig, generateSchemasDefinition, generateTarget, generateTargetForTags, generateVerbImports, generateVerbOptions, generateVerbsOptions, getArray, getBody, getCombinedEnumValue, getDefaultContentType, getEnum, getEnumDescriptions, getEnumImplementation, getEnumNames, getEnumUnionFromSchema, getExtension, getFileInfo, getFormDataFieldFileType, getFullRoute, getIsBodyVerb, getKey, getMockFileExtensionByTypeName, getNumberWord, getObject, getOperationId, getOrvalGeneratedTypes, getParameters, getParams, getParamsInPath, getPropertySafe, getProps, getQueryParams, getRefInfo, getResReqTypes, getResponse, getResponseTypeCategory, getRoute, getRouteAsArray, getScalar, getTypedResponse, isBinaryContentType, isBoolean, isDirectory, isFunction, isModule, isNull, isNumber, isNumeric, isObject, isReference, isSchema, isString, isSyntheticDefaultImportsAllow, isUndefined, isUrl, isVerb, jsDoc, jsStringEscape, kebab, keyValuePairsToJsDoc, log, logError, mergeDeep, mismatchArgsMessage, pascal, removeFilesAndEmptyFolders, resolveDiscriminators, resolveExampleRefs, resolveObject, resolveRef, resolveValue, sanitize, snake, sortByPriority, splitSchemasByType, startMessage, stringify, toObjectString, path_exports as upath, upper, writeModelInline, writeModelsInline, writeSchema, writeSchemas, writeSingleMode, writeSplitMode, writeSplitTagsMode, writeTagsMode };
4443
+ export { BODY_TYPE_NAME, EnumGeneration, ErrorWithTag, FormDataArrayHandling, GetterPropType, LogLevels, NamingConvention, OutputClient, OutputHttpClient, OutputMockType, OutputMode, PropertySortOrder, RefComponentSuffix, SchemaType, TEMPLATE_TAG_REGEX, URL_REGEX, VERBS_WITH_BODY, Verbs, _filteredVerbs, addDependency, asyncReduce, camel, combineSchemas, compareVersions, conventionName, count, createDebugger, createLogger, createSuccessMessage, createTypeAliasIfNeeded, dedupeUnionType, dynamicImport, escape, filterByContentType, fixCrossDirectoryImports, fixRegularSchemaImports, generalJSTypes, generalJSTypesWithArray, generateAxiosOptions, generateBodyMutatorConfig, generateBodyOptions, generateComponentDefinition, generateDependencyImports, generateFormDataAndUrlEncodedFunction, generateImports, generateModelInline, generateModelsInline, generateMutator, generateMutatorConfig, generateMutatorImports, generateMutatorRequestOptions, generateOptions, generateParameterDefinition, generateQueryParamsAxiosConfig, generateSchemasDefinition, generateTarget, generateTargetForTags, generateVerbImports, generateVerbOptions, generateVerbsOptions, getArray, getBody, getCombinedEnumValue, getDefaultContentType, getEnum, getEnumDescriptions, getEnumImplementation, getEnumNames, getEnumUnionFromSchema, getExtension, getFileInfo, getFormDataFieldFileType, getFullRoute, getIsBodyVerb, getKey, getMockFileExtensionByTypeName, getNumberWord, getObject, getOperationId, getOrvalGeneratedTypes, getParameters, getParams, getParamsInPath, getPropertySafe, getProps, getQueryParams, getRefInfo, getRequestBodyContentTypes, getResReqTypes, getResponse, getResponseTypeCategory, getRoute, getRouteAsArray, getScalar, getTypedResponse, isBinaryContentType, isBoolean, isDirectory, isFunction, isModule, isNullish, isNumber, isNumeric, isObject, isReference, isSchema, isString, isStringLike, isSyntheticDefaultImportsAllow, isUrl, isVerb, jsDoc, jsStringEscape, kebab, keyValuePairsToJsDoc, log, logError, mergeDeep, mismatchArgsMessage, pascal, removeFilesAndEmptyFolders, resolveDiscriminators, resolveExampleRefs, resolveObject, resolveRef, resolveValue, sanitize, snake, sortByPriority, splitSchemasByType, startMessage, stringify, toObjectString, path_exports as upath, upper, writeModelInline, writeModelsInline, writeSchema, writeSchemas, writeSingleMode, writeSplitMode, writeSplitTagsMode, writeTagsMode };
4266
4444
  //# sourceMappingURL=index.mjs.map