@orval/core 8.12.1 → 8.12.3

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
@@ -2,7 +2,7 @@ import { t as __exportAll } from "./chunk-BpYLSNr0.mjs";
2
2
  import { createRequire } from "node:module";
3
3
  import { entries, groupBy, isArray, isBoolean, isBoolean as isBoolean$1, isEmptyish, isFunction, isFunction as isFunction$1, isNullish, isNullish as isNullish$1, isNumber, isString, isString as isString$1, prop, unique, uniqueBy, uniqueWith } from "remeda";
4
4
  import { keyword } from "esutils";
5
- import path from "node:path";
5
+ import nodePath from "node:path";
6
6
  import { compare } from "compare-versions";
7
7
  import debug from "debug";
8
8
  import { pathToFileURL } from "node:url";
@@ -144,7 +144,7 @@ function isReference(obj) {
144
144
  return !isNullish$1(obj) && Object.hasOwn(obj, "$ref");
145
145
  }
146
146
  function isDirectory(pathValue) {
147
- return !path.extname(pathValue);
147
+ return !nodePath.extname(pathValue);
148
148
  }
149
149
  function isObject(x) {
150
150
  return Object.prototype.toString.call(x) === "[object Object]";
@@ -507,8 +507,8 @@ async function dynamicImport(toImport, from = process.cwd(), takeDefault = true)
507
507
  if (!toImport) return toImport;
508
508
  try {
509
509
  if (isString(toImport)) {
510
- const filePath = path.resolve(from, toImport);
511
- const extension = path.extname(filePath);
510
+ const filePath = nodePath.resolve(from, toImport);
511
+ const extension = nodePath.extname(filePath);
512
512
  if (TS_MODULE_EXTENSIONS.has(extension)) {
513
513
  const data = await createJiti(from, { interopDefault: true }).import(filePath);
514
514
  if (takeDefault && (isObject(data) || isModule(data)) && data.default) return data.default;
@@ -533,14 +533,14 @@ function getExtension(path) {
533
533
  //#region src/utils/file.ts
534
534
  function getFileInfo(target = "", { backupFilename = "filename", extension = ".ts" } = {}) {
535
535
  const isDir = isDirectory(target);
536
- const filePath = isDir ? path.join(target, backupFilename + extension) : target;
536
+ const filePath = isDir ? nodePath.join(target, backupFilename + extension) : target;
537
537
  return {
538
538
  path: filePath,
539
539
  pathWithoutExtension: filePath.replace(/\.[^/.]+$/, ""),
540
540
  extension,
541
541
  isDirectory: isDir,
542
- dirname: path.dirname(filePath),
543
- filename: path.basename(filePath, extension.startsWith(".") ? extension : `.${extension}`)
542
+ dirname: nodePath.dirname(filePath),
543
+ filename: nodePath.basename(filePath, extension.startsWith(".") ? extension : `.${extension}`)
544
544
  };
545
545
  }
546
546
  async function removeFilesAndEmptyFolders(patterns, dir) {
@@ -754,13 +754,13 @@ function toUnix(value) {
754
754
  return value;
755
755
  }
756
756
  function join(...args) {
757
- return toUnix(path.join(...args.map((a) => toUnix(a))));
757
+ return toUnix(nodePath.join(...args.map((a) => toUnix(a))));
758
758
  }
759
759
  /**
760
760
  * Behaves exactly like `path.relative(from, to)`, but keeps the first meaningful "./"
761
761
  */
762
762
  function relativeSafe(from, to) {
763
- return normalizeSafe(`./${toUnix(path.relative(toUnix(from), toUnix(to)))}`);
763
+ return normalizeSafe(`./${toUnix(nodePath.relative(toUnix(from), toUnix(to)))}`);
764
764
  }
765
765
  function getSchemaFileName(path) {
766
766
  return path.replace(`.${getExtension(path)}`, "").slice(path.lastIndexOf("/") + 1);
@@ -768,13 +768,13 @@ function getSchemaFileName(path) {
768
768
  function normalizeSafe(value) {
769
769
  let result;
770
770
  value = toUnix(value);
771
- result = toUnix(path.normalize(value));
771
+ result = toUnix(nodePath.normalize(value));
772
772
  if (value.startsWith("./") && !result.startsWith("./") && !result.startsWith("..")) result = "./" + result;
773
773
  else if (value.startsWith("//") && !result.startsWith("//")) result = value.startsWith("//./") ? "//." + result : "/" + result;
774
774
  return result;
775
775
  }
776
776
  function joinSafe(...values) {
777
- let result = toUnix(path.join(...values.map((v) => toUnix(v))));
777
+ let result = toUnix(nodePath.join(...values.map((v) => toUnix(v))));
778
778
  if (values.length > 0) {
779
779
  const firstValue = toUnix(values[0]);
780
780
  if (firstValue.startsWith("./") && !result.startsWith("./") && !result.startsWith("..")) result = "./" + result;
@@ -805,14 +805,14 @@ function joinSafe(...values) {
805
805
  * @returns The relative import path string.
806
806
  */
807
807
  function getRelativeImportPath(importerFilePath, exporterFilePath, includeFileExtension = false) {
808
- if (!path.isAbsolute(importerFilePath)) throw new Error(`'importerFilePath' is not an absolute path. "${importerFilePath}"`);
809
- if (!path.isAbsolute(exporterFilePath)) throw new Error(`'exporterFilePath' is not an absolute path. "${exporterFilePath}"`);
810
- const importerDir = path.dirname(importerFilePath);
811
- const relativePath = path.relative(importerDir, exporterFilePath);
812
- let posixPath = path.posix.join(...relativePath.split(path.sep));
808
+ if (!nodePath.isAbsolute(importerFilePath)) throw new Error(`'importerFilePath' is not an absolute path. "${importerFilePath}"`);
809
+ if (!nodePath.isAbsolute(exporterFilePath)) throw new Error(`'exporterFilePath' is not an absolute path. "${exporterFilePath}"`);
810
+ const importerDir = nodePath.dirname(importerFilePath);
811
+ const relativePath = nodePath.relative(importerDir, exporterFilePath);
812
+ let posixPath = nodePath.posix.join(...relativePath.split(nodePath.sep));
813
813
  if (!posixPath.startsWith("./") && !posixPath.startsWith("../")) posixPath = `./${posixPath}`;
814
814
  if (!includeFileExtension) {
815
- const ext = path.extname(posixPath);
815
+ const ext = nodePath.extname(posixPath);
816
816
  if (ext && posixPath.endsWith(ext)) posixPath = posixPath.slice(0, -ext.length);
817
817
  }
818
818
  return posixPath;
@@ -821,20 +821,20 @@ function getRelativeImportPath(importerFilePath, exporterFilePath, includeFileEx
821
821
  //#region src/utils/resolve-version.ts
822
822
  function resolveInstalledVersion(packageName, fromDir) {
823
823
  try {
824
- const require = createRequire(path.join(fromDir, "noop.js"));
824
+ const require = createRequire(nodePath.join(fromDir, "noop.js"));
825
825
  try {
826
826
  return require(`${packageName}/package.json`).version;
827
827
  } catch (directError) {
828
828
  if (directError instanceof Error && "code" in directError && directError.code === "ERR_PACKAGE_PATH_NOT_EXPORTED") {
829
829
  const entryPath = require.resolve(packageName);
830
- let dir = path.dirname(entryPath);
831
- while (dir !== path.parse(dir).root) {
832
- const pkgPath = path.join(dir, "package.json");
830
+ let dir = nodePath.dirname(entryPath);
831
+ while (dir !== nodePath.parse(dir).root) {
832
+ const pkgPath = nodePath.join(dir, "package.json");
833
833
  if (existsSync(pkgPath)) {
834
834
  const pkgData = JSON.parse(readFileSync(pkgPath, "utf8"));
835
835
  if (pkgData.name === packageName) return pkgData.version;
836
836
  }
837
- dir = path.dirname(dir);
837
+ dir = nodePath.dirname(dir);
838
838
  }
839
839
  return;
840
840
  }
@@ -1358,1589 +1358,1616 @@ function getRefInfo($ref, context) {
1358
1358
  };
1359
1359
  }
1360
1360
  //#endregion
1361
- //#region src/resolvers/ref.ts
1362
- const REF_NOT_FOUND_PREFIX = "Oops... 🍻. Ref not found";
1363
- /**
1364
- * Recursively resolves a `$ref` in an OpenAPI document, following
1365
- * nested schema refs and collecting imports along the way.
1366
- *
1367
- * Handles OpenAPI 3.0 `nullable` and 3.1 type-array hints on direct refs.
1368
- *
1369
- * @see https://spec.openapis.org/oas/v3.0.3#reference-object
1370
- * @see https://spec.openapis.org/oas/v3.1.0#reference-object
1371
- */
1372
- function resolveRef(schema, context, imports = []) {
1373
- const refPath = "$ref" in schema ? schema.$ref : void 0;
1374
- const nestedSchema = "schema" in schema ? schema.schema : void 0;
1375
- if (isObject(nestedSchema) && isReference(nestedSchema) && typeof nestedSchema.$ref === "string") {
1376
- const resolvedRef = resolveRef(nestedSchema, context, imports);
1377
- if ("examples" in schema) {
1378
- const schemaWithExamples = schema;
1379
- schemaWithExamples.examples = resolveExampleRefs(schemaWithExamples.examples, context);
1380
- }
1381
- if ("examples" in resolvedRef.schema) {
1382
- const resolvedWithExamples = resolvedRef.schema;
1383
- resolvedWithExamples.examples = resolveExampleRefs(resolvedWithExamples.examples, context);
1384
- }
1385
- return {
1386
- schema: {
1387
- ...schema,
1388
- schema: resolvedRef.schema
1389
- },
1390
- imports: resolvedRef.imports
1391
- };
1392
- }
1393
- if (isDereferenced(schema)) {
1394
- if ("examples" in schema) {
1395
- const schemaWithExamples = schema;
1396
- schemaWithExamples.examples = resolveExampleRefs(schemaWithExamples.examples, context);
1397
- }
1361
+ //#region src/getters/imports.ts
1362
+ function getAliasedImports({ name, resolvedValue, context }) {
1363
+ return context.output.schemas && resolvedValue.isRef ? resolvedValue.imports.map((imp) => {
1364
+ if (!needCreateImportAlias({
1365
+ name,
1366
+ imp
1367
+ })) return imp;
1398
1368
  return {
1399
- schema,
1400
- imports
1369
+ ...imp,
1370
+ alias: `__${imp.name}`
1401
1371
  };
1402
- }
1403
- if (!refPath) throw new Error(`${REF_NOT_FOUND_PREFIX}: missing $ref`);
1404
- const { currentSchema, refInfo: { name, originalName } } = getSchema$1(schema, context);
1405
- if (!currentSchema) throw new Error(`${REF_NOT_FOUND_PREFIX}: ${refPath}`);
1406
- return resolveRef(currentSchema, { ...context }, [...imports, {
1407
- name,
1408
- schemaName: originalName
1409
- }]);
1372
+ }) : resolvedValue.imports;
1410
1373
  }
1411
- /**
1412
- * Looks up a schema by its `$ref` path in the spec, applying suffix resolution.
1413
- *
1414
- * Preserves OpenAPI 3.0 `nullable` and 3.1 type-array (`["object", "null"]`)
1415
- * hints from the referencing schema onto the resolved target.
1416
- *
1417
- * @see https://spec.openapis.org/oas/v3.0.3#fixed-fields-18 (nullable)
1418
- * @see https://spec.openapis.org/oas/v3.1.0#schema-object (type as array)
1419
- */
1420
- function getSchema$1(schema, context) {
1421
- if (!schema.$ref) throw new Error(`${REF_NOT_FOUND_PREFIX}: missing $ref`);
1422
- const refInfo = getRefInfo(schema.$ref, context);
1423
- const { refPaths } = refInfo;
1424
- const schemaByRefPaths = Array.isArray(refPaths) ? prop(context.spec, ...refPaths) : void 0;
1425
- if (isObject(schemaByRefPaths) && isReference(schemaByRefPaths)) return getSchema$1(schemaByRefPaths, context);
1426
- let currentSchema = schemaByRefPaths;
1427
- if (isObject(currentSchema) && "nullable" in schema) {
1428
- const nullable = schema.nullable;
1429
- currentSchema = {
1430
- ...currentSchema,
1431
- nullable
1432
- };
1433
- }
1434
- if (isObject(currentSchema) && "type" in schema && Array.isArray(schema.type)) {
1435
- const type = schema.type;
1436
- currentSchema = {
1437
- ...currentSchema,
1438
- type
1439
- };
1440
- }
1441
- return {
1442
- currentSchema,
1443
- refInfo
1444
- };
1374
+ function needCreateImportAlias({ imp, name }) {
1375
+ return !imp.alias && imp.name === name;
1445
1376
  }
1446
- /** Recursively resolves `$ref` entries in an examples array or record. */
1447
- function resolveExampleRefs(examples, context) {
1448
- if (!examples) return;
1449
- return Array.isArray(examples) ? examples.map((example) => {
1450
- if (isObject(example) && isReference(example)) {
1451
- const { schema } = resolveRef(example, context);
1452
- return schema.value;
1453
- }
1454
- return example;
1455
- }) : (() => {
1456
- const result = {};
1457
- for (const [key, example] of Object.entries(examples)) result[key] = isObject(example) && isReference(example) ? resolveRef(example, context).schema.value : example;
1458
- return result;
1459
- })();
1377
+ function getImportAliasForRefOrValue({ context, imports, resolvedValue }) {
1378
+ if (!context.output.schemas || !resolvedValue.isRef) return resolvedValue.value;
1379
+ return imports.find((imp) => imp.name === resolvedValue.value)?.alias ?? resolvedValue.value;
1460
1380
  }
1461
1381
  //#endregion
1462
- //#region src/resolvers/value.ts
1463
- function resolveValue({ schema, name, context, formDataContext }) {
1464
- if (isReference(schema)) {
1465
- const refValue = schema.$ref;
1466
- const { schema: schemaObject, imports } = resolveRef(schema, context);
1467
- if (refValue && !isComponentRef(refValue)) {
1468
- if (context.parents?.includes(refValue)) return {
1469
- value: "unknown",
1470
- imports: [],
1471
- schemas: [],
1472
- type: "unknown",
1473
- isEnum: false,
1474
- originalSchema: schemaObject,
1475
- hasReadonlyProps: false,
1476
- isRef: false,
1477
- dependencies: []
1478
- };
1479
- return {
1480
- ...getScalar({
1481
- item: schemaObject,
1482
- name,
1483
- context: {
1484
- ...context,
1485
- parents: [...context.parents ?? [], refValue]
1486
- },
1487
- formDataContext
1488
- }),
1489
- originalSchema: schemaObject,
1490
- isRef: false
1491
- };
1382
+ //#region src/getters/combine.ts
1383
+ const mergeableAllOfKeys = new Set([
1384
+ "type",
1385
+ "properties",
1386
+ "required"
1387
+ ]);
1388
+ function isMergeableAllOfObject(schema) {
1389
+ if (isNullish$1(schema.properties)) return false;
1390
+ if (schema.allOf || schema.anyOf || schema.oneOf) return false;
1391
+ if (!isNullish$1(schema.type) && schema.type !== "object") return false;
1392
+ return Object.keys(schema).every((key) => mergeableAllOfKeys.has(key));
1393
+ }
1394
+ function normalizeAllOfSchema(schema) {
1395
+ const schemaAllOf = schema.allOf;
1396
+ if (!schemaAllOf) return schema;
1397
+ let didMerge = false;
1398
+ const schemaProperties = schema.properties;
1399
+ const schemaRequired = schema.required;
1400
+ const mergedProperties = schemaProperties ? { ...schemaProperties } : {};
1401
+ const mergedRequired = new Set(schemaRequired);
1402
+ const remainingAllOf = [];
1403
+ for (const subSchema of schemaAllOf) {
1404
+ if (isSchema(subSchema) && isMergeableAllOfObject(subSchema)) {
1405
+ didMerge = true;
1406
+ if (subSchema.properties) Object.assign(mergedProperties, subSchema.properties);
1407
+ const subRequired = subSchema.required;
1408
+ if (subRequired) for (const prop of subRequired) mergedRequired.add(prop);
1409
+ continue;
1492
1410
  }
1493
- const resolvedImport = imports[0];
1494
- let hasReadonlyProps = false;
1495
- const refName = resolvedImport.name;
1496
- if (!context.parents?.includes(refName)) hasReadonlyProps = getScalar({
1497
- item: schemaObject,
1498
- name: refName,
1499
- context: {
1500
- ...context,
1501
- parents: [...context.parents ?? [], refName]
1502
- }
1503
- }).hasReadonlyProps;
1504
- const isAnyOfNullable = schemaObject.anyOf?.some((anyOfItem) => !isReference(anyOfItem) && (anyOfItem.type === "null" || Array.isArray(anyOfItem.type) && anyOfItem.type.includes("null")));
1505
- const schemaType = schemaObject.type;
1506
- const nullable = Array.isArray(schemaType) && schemaType.includes("null") || schemaObject.nullable === true || isAnyOfNullable ? " | null" : "";
1507
- return {
1508
- value: resolvedImport.name + nullable,
1509
- imports: [{
1510
- name: resolvedImport.name,
1511
- schemaName: resolvedImport.schemaName
1512
- }],
1513
- type: schemaObject.type ?? "object",
1514
- schemas: [],
1515
- isEnum: !!schemaObject.enum,
1516
- originalSchema: schemaObject,
1517
- hasReadonlyProps,
1518
- isRef: true,
1519
- dependencies: [resolvedImport.name]
1520
- };
1411
+ remainingAllOf.push(subSchema);
1521
1412
  }
1413
+ if (!didMerge || remainingAllOf.length === 0) return schema;
1522
1414
  return {
1523
- ...getScalar({
1524
- item: schema,
1525
- name,
1526
- context,
1527
- formDataContext
1528
- }),
1529
- originalSchema: schema,
1530
- isRef: false
1531
- };
1532
- }
1533
- //#endregion
1534
- //#region src/resolvers/object.ts
1535
- /**
1536
- * Wraps inline object type in a type alias.
1537
- * E.g. `{ foo: string }` → value becomes `FooBody`, schema gets `export type FooBody = { foo: string };`
1538
- */
1539
- function createTypeAliasIfNeeded({ resolvedValue, propName, context }) {
1540
- if (!propName) return;
1541
- if (resolvedValue.isEnum || resolvedValue.type !== "object") return;
1542
- const aliasPattern = context.output.override.aliasCombinedTypes ? String.raw`{|&|\|` : "{";
1543
- if (!new RegExp(aliasPattern).test(resolvedValue.value)) return;
1544
- const { originalSchema } = resolvedValue;
1545
- const doc = jsDoc(originalSchema);
1546
- const isConstant = "const" in originalSchema;
1547
- const constantIsString = "type" in originalSchema && (originalSchema.type === "string" || Array.isArray(originalSchema.type) && originalSchema.type.includes("string"));
1548
- const model = isConstant ? `${doc}export const ${propName} = ${constantIsString ? `'${originalSchema.const}'` : originalSchema.const} as const;\n` : `${doc}export type ${propName} = ${resolvedValue.value};\n`;
1549
- return {
1550
- value: propName,
1551
- imports: [{
1552
- name: propName,
1553
- isConstant
1554
- }],
1555
- schemas: [...resolvedValue.schemas, {
1556
- name: propName,
1557
- model,
1558
- imports: resolvedValue.imports,
1559
- dependencies: resolvedValue.dependencies
1560
- }],
1561
- isEnum: false,
1562
- type: "object",
1563
- isRef: resolvedValue.isRef,
1564
- hasReadonlyProps: resolvedValue.hasReadonlyProps,
1565
- dependencies: resolvedValue.dependencies
1415
+ ...schema,
1416
+ ...Object.keys(mergedProperties).length > 0 && { properties: mergedProperties },
1417
+ ...mergedRequired.size > 0 && { required: [...mergedRequired] },
1418
+ ...remainingAllOf.length > 0 && { allOf: remainingAllOf }
1566
1419
  };
1567
1420
  }
1568
- function resolveObjectOriginal({ schema, propName, combined = false, context, formDataContext }) {
1569
- const resolvedValue = resolveValue({
1570
- schema,
1571
- name: propName,
1572
- context,
1573
- formDataContext
1574
- });
1575
- const aliased = createTypeAliasIfNeeded({
1576
- resolvedValue,
1577
- propName,
1578
- context
1579
- });
1580
- if (aliased) return {
1581
- ...aliased,
1582
- originalSchema: resolvedValue.originalSchema
1421
+ function combineValues({ resolvedData, resolvedValue, separator, context, parentSchema }) {
1422
+ if (resolvedData.isEnum.every(Boolean)) return `${resolvedData.values.join(` | `)}${resolvedValue ? ` | ${resolvedValue.value}` : ""}`;
1423
+ if (separator === "allOf") {
1424
+ let resolvedDataValue = resolvedData.values.map((v) => v.includes(" | ") ? `(${v})` : v).join(` & `);
1425
+ if (resolvedData.originalSchema.length > 0 && resolvedValue) {
1426
+ const discriminatedPropertySchemas = resolvedData.originalSchema.filter((s) => {
1427
+ const disc = s?.discriminator;
1428
+ return disc && resolvedValue.value.includes(` ${disc.propertyName}:`);
1429
+ });
1430
+ if (discriminatedPropertySchemas.length > 0) resolvedDataValue = `Omit<${resolvedDataValue}, '${discriminatedPropertySchemas.map((s) => s.discriminator?.propertyName).join("' | '")}'>`;
1431
+ }
1432
+ const resolvedValueStr = resolvedValue?.value.includes(" | ") ? `(${resolvedValue.value})` : resolvedValue?.value;
1433
+ const joined = `${resolvedDataValue}${resolvedValue ? ` & ${resolvedValueStr}` : ""}`;
1434
+ const overrideRequiredProperties = resolvedData.requiredProperties.filter((prop) => !resolvedData.originalSchema.some((schema) => {
1435
+ const props = schema?.properties;
1436
+ const req = schema?.required;
1437
+ return props?.[prop] && req?.includes(prop);
1438
+ }) && !(() => {
1439
+ const parentProps = parentSchema?.properties;
1440
+ const parentReq = parentSchema?.required;
1441
+ return !!(parentProps?.[prop] && parentReq?.includes(prop));
1442
+ })());
1443
+ if (overrideRequiredProperties.length > 0) return `${joined} & Required<Pick<${joined}, '${overrideRequiredProperties.join("' | '")}'>>`;
1444
+ return joined;
1445
+ }
1446
+ let values = resolvedData.values;
1447
+ if (resolvedData.allProperties.length && context.output.unionAddMissingProperties) {
1448
+ values = [];
1449
+ for (let i = 0; i < resolvedData.values.length; i += 1) {
1450
+ const subSchema = resolvedData.originalSchema[i];
1451
+ if (subSchema?.type !== "object" || !subSchema.properties) {
1452
+ values.push(resolvedData.values[i]);
1453
+ continue;
1454
+ }
1455
+ const subSchemaProps = subSchema.properties;
1456
+ const missingProperties = unique(resolvedData.allProperties.filter((p) => !Object.keys(subSchemaProps).includes(p)));
1457
+ values.push(`${resolvedData.values[i]}${missingProperties.length > 0 ? ` & {${missingProperties.map((p) => `${p}?: never`).join("; ")}}` : ""}`);
1458
+ }
1459
+ }
1460
+ if (resolvedValue) return `(${values.join(` & ${resolvedValue.value}) | (`)} & ${resolvedValue.value})`;
1461
+ return values.join(" | ");
1462
+ }
1463
+ function combineSchemas({ name, schema, separator, context, nullable, formDataContext }) {
1464
+ const normalizedSchema = separator === "allOf" && !context.output.override.aliasCombinedTypes && !schema.oneOf && !schema.anyOf ? normalizeAllOfSchema(schema) : schema;
1465
+ const items = normalizedSchema[separator] ?? [];
1466
+ const resolvedData = {
1467
+ values: [],
1468
+ imports: [],
1469
+ schemas: [],
1470
+ isEnum: [],
1471
+ isRef: [],
1472
+ types: [],
1473
+ dependencies: [],
1474
+ originalSchema: [],
1475
+ allProperties: [],
1476
+ hasReadonlyProps: false,
1477
+ example: schema.example,
1478
+ examples: resolveExampleRefs(schema.examples, context),
1479
+ requiredProperties: separator === "allOf" ? schema.required ?? [] : []
1583
1480
  };
1584
- if (propName && resolvedValue.isEnum && !combined && !resolvedValue.isRef) {
1585
- const doc = jsDoc(resolvedValue.originalSchema);
1586
- const enumValue = getEnum(resolvedValue.value, propName, getEnumNames(resolvedValue.originalSchema), context.output.override.enumGenerationType, getEnumDescriptions(resolvedValue.originalSchema), context.output.override.namingConvention.enum);
1481
+ for (const subSchema of items) {
1482
+ let propName;
1483
+ if (context.output.override.aliasCombinedTypes) {
1484
+ propName = name ? name + pascal(separator) : void 0;
1485
+ if (propName && resolvedData.schemas.length > 0) propName = propName + pascal(getNumberWord(resolvedData.schemas.length + 1));
1486
+ }
1487
+ if (separator === "allOf" && isSchema(subSchema) && subSchema.required) resolvedData.requiredProperties.push(...subSchema.required);
1488
+ const resolvedValue = resolveObject({
1489
+ schema: subSchema,
1490
+ propName,
1491
+ combined: true,
1492
+ context,
1493
+ formDataContext
1494
+ });
1495
+ const aliasedImports = getAliasedImports({
1496
+ context,
1497
+ name,
1498
+ resolvedValue
1499
+ });
1500
+ const value = getImportAliasForRefOrValue({
1501
+ context,
1502
+ resolvedValue,
1503
+ imports: aliasedImports
1504
+ });
1505
+ resolvedData.values.push(value);
1506
+ resolvedData.imports.push(...aliasedImports);
1507
+ resolvedData.schemas.push(...resolvedValue.schemas);
1508
+ resolvedData.dependencies.push(...resolvedValue.dependencies);
1509
+ resolvedData.isEnum.push(resolvedValue.isEnum);
1510
+ resolvedData.types.push(resolvedValue.type);
1511
+ resolvedData.isRef.push(resolvedValue.isRef);
1512
+ resolvedData.originalSchema.push(resolvedValue.originalSchema);
1513
+ if (resolvedValue.hasReadonlyProps) resolvedData.hasReadonlyProps = true;
1514
+ const originalProps = resolvedValue.originalSchema.properties;
1515
+ if (resolvedValue.type === "object" && originalProps) resolvedData.allProperties.push(...Object.keys(originalProps));
1516
+ }
1517
+ if (resolvedData.isEnum.every(Boolean) && name && items.length > 1 && context.output.override.enumGenerationType !== EnumGeneration.UNION) {
1518
+ const { value: combinedEnumValue, valueImports, hasNull } = getCombinedEnumValue(resolvedData.values.map((value, index) => ({
1519
+ value,
1520
+ isRef: resolvedData.isRef[index],
1521
+ schema: resolvedData.originalSchema[index]
1522
+ })));
1523
+ const newEnum = `export const ${pascal(name)} = ${combinedEnumValue}`;
1524
+ const valueImportSet = new Set(valueImports);
1525
+ const typeSuffix = `${nullable}${hasNull && !nullable.includes("null") ? " | null" : ""}`;
1587
1526
  return {
1588
- value: propName,
1589
- imports: [{ name: propName }],
1590
- schemas: [...resolvedValue.schemas, {
1591
- name: propName,
1592
- model: doc + enumValue,
1593
- imports: resolvedValue.imports,
1594
- dependencies: resolvedValue.dependencies
1527
+ value: `typeof ${pascal(name)}[keyof typeof ${pascal(name)}]${typeSuffix}`,
1528
+ imports: [{ name: pascal(name) }],
1529
+ schemas: [...resolvedData.schemas, {
1530
+ imports: resolvedData.imports.filter((toImport) => valueImportSet.has(toImport.alias ?? toImport.name)).map((toImport) => ({
1531
+ ...toImport,
1532
+ values: true
1533
+ })),
1534
+ model: newEnum,
1535
+ name
1595
1536
  }],
1596
1537
  isEnum: false,
1597
- type: "enum",
1598
- originalSchema: resolvedValue.originalSchema,
1599
- isRef: resolvedValue.isRef,
1600
- hasReadonlyProps: resolvedValue.hasReadonlyProps,
1601
- dependencies: [...resolvedValue.dependencies, propName]
1538
+ type: "object",
1539
+ isRef: false,
1540
+ hasReadonlyProps: resolvedData.hasReadonlyProps,
1541
+ dependencies: resolvedData.dependencies,
1542
+ example: schema.example,
1543
+ examples: resolveExampleRefs(schema.examples, context)
1602
1544
  };
1603
1545
  }
1604
- return resolvedValue;
1605
- }
1606
- const resolveObjectCacheMap = /* @__PURE__ */ new Map();
1607
- function resolveObject({ schema, propName, combined = false, context, formDataContext }) {
1608
- const hashKey = JSON.stringify({
1609
- schema,
1610
- propName,
1611
- combined,
1612
- projectName: context.projectName ?? context.output.target,
1613
- formDataContext
1614
- });
1615
- if (resolveObjectCacheMap.has(hashKey)) return resolveObjectCacheMap.get(hashKey);
1616
- const result = resolveObjectOriginal({
1617
- schema,
1618
- propName,
1619
- combined,
1546
+ let resolvedValue;
1547
+ const normalizedProperties = normalizedSchema.properties;
1548
+ const schemaOneOf = schema.oneOf;
1549
+ const schemaAnyOf = schema.anyOf;
1550
+ if (normalizedProperties) resolvedValue = getScalar({
1551
+ item: Object.fromEntries(Object.entries(normalizedSchema).filter(([key]) => key !== separator)),
1552
+ name,
1620
1553
  context,
1621
1554
  formDataContext
1622
1555
  });
1623
- resolveObjectCacheMap.set(hashKey, result);
1624
- return result;
1625
- }
1626
- //#endregion
1627
- //#region src/getters/array.ts
1628
- /**
1629
- * Return the output type from an array
1630
- *
1631
- * @param item item with type === "array"
1632
- */
1633
- function getArray({ schema, name, context, formDataContext }) {
1634
- const schemaPrefixItems = schema.prefixItems;
1635
- const schemaItems = schema.items;
1636
- const schemaExample = schema.example;
1637
- const schemaExamples = schema.examples;
1638
- const itemSuffix = context.output.override.components.schemas.itemSuffix;
1639
- if (schemaPrefixItems) {
1640
- const resolvedObjects = schemaPrefixItems.map((item, index) => resolveObject({
1641
- schema: item,
1642
- propName: name ? name + itemSuffix + String(index) : void 0,
1643
- context
1644
- }));
1645
- if (schemaItems) {
1646
- const additional = resolveObject({
1647
- schema: schemaItems,
1648
- propName: name ? name + itemSuffix + "Additional" : void 0,
1649
- context
1650
- });
1651
- resolvedObjects.push({
1652
- ...additional,
1653
- value: `...${additional.value}[]`
1654
- });
1655
- }
1656
- return {
1657
- type: "array",
1658
- isEnum: false,
1659
- isRef: false,
1660
- value: `[${resolvedObjects.map((o) => o.value).join(", ")}]`,
1661
- imports: resolvedObjects.flatMap((o) => o.imports),
1662
- schemas: resolvedObjects.flatMap((o) => o.schemas),
1663
- dependencies: resolvedObjects.flatMap((o) => o.dependencies),
1664
- hasReadonlyProps: resolvedObjects.some((o) => o.hasReadonlyProps),
1665
- example: schemaExample,
1666
- examples: resolveExampleRefs(schemaExamples, context)
1667
- };
1668
- }
1669
- if (schemaItems) {
1670
- const resolvedObject = resolveObject({
1671
- schema: schemaItems,
1672
- propName: name ? name + itemSuffix : void 0,
1556
+ else if (separator === "allOf" && (schemaOneOf || schemaAnyOf)) {
1557
+ const siblingCombiner = schemaOneOf ? "oneOf" : "anyOf";
1558
+ const siblingSchemas = schemaOneOf ?? schemaAnyOf;
1559
+ resolvedValue = combineSchemas({
1560
+ schema: { [siblingCombiner]: siblingSchemas },
1561
+ name,
1562
+ separator: siblingCombiner,
1673
1563
  context,
1674
- formDataContext
1564
+ nullable: ""
1675
1565
  });
1676
- return {
1677
- value: `${schema.readOnly === true && !context.output.override.suppressReadonlyModifier ? "readonly " : ""}${resolvedObject.value.includes("|") || resolvedObject.value.includes("&") ? `(${resolvedObject.value})[]` : `${resolvedObject.value}[]`}`,
1678
- imports: resolvedObject.imports,
1679
- schemas: resolvedObject.schemas,
1680
- dependencies: resolvedObject.dependencies,
1681
- isEnum: false,
1682
- type: "array",
1683
- isRef: false,
1684
- hasReadonlyProps: resolvedObject.hasReadonlyProps,
1685
- example: schemaExample,
1686
- examples: resolveExampleRefs(schemaExamples, context)
1687
- };
1688
- } else if (compareVersions(context.spec.openapi ?? "3.0.0", "3.1", ">=")) return {
1689
- value: "unknown[]",
1690
- imports: [],
1691
- schemas: [],
1692
- dependencies: [],
1566
+ }
1567
+ return {
1568
+ value: dedupeUnionType(combineValues({
1569
+ resolvedData,
1570
+ separator,
1571
+ resolvedValue,
1572
+ context,
1573
+ parentSchema: normalizedSchema
1574
+ }) + nullable),
1575
+ imports: resolvedValue ? [...resolvedData.imports, ...resolvedValue.imports] : resolvedData.imports,
1576
+ schemas: resolvedValue ? [...resolvedData.schemas, ...resolvedValue.schemas] : resolvedData.schemas,
1577
+ dependencies: resolvedValue ? [...resolvedData.dependencies, ...resolvedValue.dependencies] : resolvedData.dependencies,
1693
1578
  isEnum: false,
1694
- type: "array",
1579
+ type: "object",
1695
1580
  isRef: false,
1696
- hasReadonlyProps: false
1581
+ hasReadonlyProps: resolvedData.hasReadonlyProps || (resolvedValue?.hasReadonlyProps ?? false),
1582
+ example: schema.example,
1583
+ examples: resolveExampleRefs(schema.examples, context)
1697
1584
  };
1698
- else throw new Error(`All arrays must have an \`items\` key defined (name=${name}, schema=${JSON.stringify(schema)})`);
1699
1585
  }
1700
1586
  //#endregion
1701
- //#region src/getters/res-req-types.ts
1702
- const getSchemaType$1 = (s) => s.type;
1703
- const getSchemaCombined = (s) => s.oneOf ?? s.anyOf ?? s.allOf;
1704
- const getSchemaOneOf = (s) => s.oneOf;
1705
- const getSchemaAnyOf = (s) => s.anyOf;
1706
- const getSchemaItems = (s) => s.items;
1707
- const getSchemaRequired = (s) => s.required;
1708
- const getSchemaProperties = (s) => s.properties;
1709
- const resolveSchemaRef = (schema, context) => resolveRef(schema, context);
1710
- const resolveResponseOrRequestRef = (schema, context) => resolveRef(schema, context);
1711
- const formDataContentTypes = new Set(["multipart/form-data"]);
1712
- const formUrlEncodedContentTypes = new Set(["application/x-www-form-urlencoded"]);
1713
- function getResReqContentTypes({ mediaType, propName, context, isFormData, contentType }) {
1714
- if (!mediaType.schema) return;
1715
- const isFormUrlEncoded = formUrlEncodedContentTypes.has(contentType);
1716
- const formDataContext = isFormData ? {
1717
- atPart: false,
1718
- encoding: mediaType.encoding ?? {}
1719
- } : isFormUrlEncoded ? {
1720
- atPart: false,
1721
- encoding: mediaType.encoding ?? {},
1722
- urlEncoded: true
1723
- } : void 0;
1724
- const resolvedObject = resolveObject({
1725
- schema: mediaType.schema,
1726
- propName,
1727
- context,
1728
- formDataContext
1587
+ //#region src/getters/keys.ts
1588
+ function getKey(key) {
1589
+ return keyword.isIdentifierNameES5(key) ? key : `'${key}'`;
1590
+ }
1591
+ //#endregion
1592
+ //#region src/getters/object.ts
1593
+ function getPropertyNamesEnumKeyType(item) {
1594
+ if (!("propertyNames" in item) || !item.propertyNames) return;
1595
+ const propertyNames = item.propertyNames;
1596
+ if (Array.isArray(propertyNames.enum)) {
1597
+ const enumValues = propertyNames.enum.filter((val) => isString(val));
1598
+ if (enumValues.length > 0) return {
1599
+ value: enumValues.map((val) => `'${escape(val)}'`).join(" | "),
1600
+ imports: [],
1601
+ dependencies: []
1602
+ };
1603
+ }
1604
+ if (isString(propertyNames.const)) return {
1605
+ value: `'${escape(propertyNames.const)}'`,
1606
+ imports: [],
1607
+ dependencies: []
1608
+ };
1609
+ }
1610
+ /**
1611
+ * Resolve a narrowed key type from OpenAPI 3.1 propertyNames.
1612
+ * Supports inline enum/const and $ref string enums.
1613
+ */
1614
+ function getPropertyNamesKeyType(item, context) {
1615
+ const inlineKeyType = getPropertyNamesEnumKeyType(item);
1616
+ if (inlineKeyType) return inlineKeyType;
1617
+ const propertyNames = item.propertyNames;
1618
+ if (!propertyNames || !isReference(propertyNames)) return;
1619
+ const resolvedValue = resolveValue({
1620
+ schema: propertyNames,
1621
+ context
1729
1622
  });
1730
- if (!isFormData && isBinaryContentType(contentType)) return {
1731
- ...resolvedObject,
1732
- value: "Blob"
1623
+ const resolvedConst = resolvedValue.originalSchema.const;
1624
+ const isStringConst = resolvedValue.type === "string" && isString(resolvedConst);
1625
+ if (!resolvedValue.isEnum && !isStringConst) return;
1626
+ return {
1627
+ value: resolvedValue.value,
1628
+ imports: resolvedValue.imports,
1629
+ dependencies: resolvedValue.dependencies
1733
1630
  };
1734
- return resolvedObject;
1735
1631
  }
1736
- function getResReqTypes(responsesOrRequests, name, context, defaultType = "unknown", uniqueKey = (item) => item.value) {
1737
- return uniqueBy(responsesOrRequests.filter(([, res]) => Boolean(res)).map(([key, res]) => {
1738
- if (isReference(res)) {
1739
- const { schema: bodySchema, imports: [{ name, schemaName }] } = resolveResponseOrRequestRef(res, context);
1740
- const firstEntry = Object.entries(bodySchema.content ?? {}).at(0);
1741
- if (!firstEntry) return [{
1742
- value: name,
1743
- imports: [{
1744
- name,
1745
- schemaName
1746
- }],
1747
- schemas: [],
1748
- type: "unknown",
1749
- isEnum: false,
1750
- isRef: true,
1751
- hasReadonlyProps: false,
1752
- dependencies: [name],
1753
- originalSchema: void 0,
1754
- example: void 0,
1755
- examples: void 0,
1756
- key,
1757
- contentType: ""
1758
- }];
1759
- const [contentType, mediaType] = firstEntry;
1760
- const isFormData = formDataContentTypes.has(contentType);
1761
- const isFormUrlEncoded = formUrlEncodedContentTypes.has(contentType);
1762
- if (!isFormData && !isFormUrlEncoded || !mediaType.schema) return [{
1763
- value: name,
1764
- imports: [{
1765
- name,
1766
- schemaName
1767
- }],
1768
- schemas: [],
1769
- type: "unknown",
1770
- isEnum: false,
1771
- isRef: true,
1772
- hasReadonlyProps: false,
1773
- dependencies: [name],
1774
- originalSchema: mediaType.schema,
1775
- example: mediaType.example,
1776
- examples: resolveExampleRefs(mediaType.examples, context),
1777
- key,
1778
- contentType
1779
- }];
1780
- const formData = isFormData ? getSchemaFormDataAndUrlEncoded({
1781
- name,
1782
- schemaObject: mediaType.schema,
1632
+ /**
1633
+ * Generate index signature key type based on propertyNames enum or const
1634
+ * Returns union type string like "'foo' | 'bar'", "'x'", or 'string' if neither
1635
+ */
1636
+ function getIndexSignatureKey(item) {
1637
+ return getPropertyNamesEnumKeyType(item)?.value ?? "string";
1638
+ }
1639
+ function getPropertyNamesRecordType(item, valueType, context) {
1640
+ const keyType = getPropertyNamesKeyType(item, context);
1641
+ if (!keyType) return;
1642
+ return {
1643
+ ...keyType,
1644
+ value: `Partial<Record<${keyType.value}, ${valueType}>>`
1645
+ };
1646
+ }
1647
+ /**
1648
+ * Return the output type from an object
1649
+ *
1650
+ * @param item item with type === "object"
1651
+ */
1652
+ function getObject({ item, name, context, nullable, formDataContext }) {
1653
+ if (isReference(item)) {
1654
+ const { name } = getRefInfo(item.$ref, context);
1655
+ return {
1656
+ value: name + nullable,
1657
+ imports: [{ name }],
1658
+ schemas: [],
1659
+ isEnum: false,
1660
+ type: "object",
1661
+ isRef: true,
1662
+ hasReadonlyProps: item.readOnly ?? false,
1663
+ dependencies: [name],
1664
+ example: item.example,
1665
+ examples: resolveExampleRefs(item.examples, context)
1666
+ };
1667
+ }
1668
+ const schemaItem = item;
1669
+ const itemAllOf = schemaItem.allOf;
1670
+ const itemOneOf = schemaItem.oneOf;
1671
+ const itemAnyOf = schemaItem.anyOf;
1672
+ const itemType = schemaItem.type;
1673
+ if (itemAllOf || itemOneOf || itemAnyOf) return combineSchemas({
1674
+ schema: schemaItem,
1675
+ name,
1676
+ separator: itemAllOf ? "allOf" : itemOneOf ? "oneOf" : "anyOf",
1677
+ context,
1678
+ nullable,
1679
+ formDataContext
1680
+ });
1681
+ if (Array.isArray(itemType)) {
1682
+ const typeArray = itemType;
1683
+ const baseItem = schemaItem;
1684
+ return combineSchemas({
1685
+ schema: { anyOf: typeArray.map((type) => ({
1686
+ ...baseItem,
1687
+ type
1688
+ })) },
1689
+ name,
1690
+ separator: "anyOf",
1691
+ context,
1692
+ nullable
1693
+ });
1694
+ }
1695
+ const itemProperties = schemaItem.properties;
1696
+ if (itemProperties && Object.entries(itemProperties).length > 0) {
1697
+ const entries = Object.entries(itemProperties);
1698
+ if (context.output.propertySortOrder === PropertySortOrder.ALPHABETICAL) entries.sort((a, b) => {
1699
+ return a[0].localeCompare(b[0], "en", { numeric: true });
1700
+ });
1701
+ const acc = {
1702
+ imports: [],
1703
+ schemas: [],
1704
+ value: "",
1705
+ isEnum: false,
1706
+ type: "object",
1707
+ isRef: false,
1708
+ hasReadonlyProps: false,
1709
+ useTypeAlias: false,
1710
+ dependencies: [],
1711
+ example: schemaItem.example,
1712
+ examples: resolveExampleRefs(schemaItem.examples, context)
1713
+ };
1714
+ const itemRequired = schemaItem.required;
1715
+ for (const [index, [key, schema]] of entries.entries()) {
1716
+ const isRequired = (Array.isArray(itemRequired) ? itemRequired : []).includes(key);
1717
+ let propName = "";
1718
+ if (name) {
1719
+ const isKeyStartWithUnderscore = key.startsWith("_");
1720
+ propName += pascal(`${isKeyStartWithUnderscore ? "_" : ""}${name}_${key}`);
1721
+ }
1722
+ const allSpecSchemas = context.spec.components?.schemas ?? {};
1723
+ if (Object.keys(allSpecSchemas).some((schemaName) => pascal(schemaName) === propName)) propName = propName + "Property";
1724
+ const propertyFormDataContext = formDataContext && !formDataContext.atPart ? {
1725
+ atPart: true,
1726
+ partContentType: formDataContext.encoding[key]?.contentType,
1727
+ urlEncoded: formDataContext.urlEncoded
1728
+ } : void 0;
1729
+ const resolvedValue = resolveObject({
1730
+ schema,
1731
+ propName,
1783
1732
  context,
1784
- isRequestBodyOptional: bodySchema.required !== true,
1785
- isRef: true,
1786
- encoding: mediaType.encoding
1787
- }) : void 0;
1788
- const formUrlEncoded = isFormUrlEncoded ? getSchemaFormDataAndUrlEncoded({
1733
+ formDataContext: propertyFormDataContext
1734
+ });
1735
+ const isReadOnly = Boolean(schemaItem.readOnly) || Boolean(schema.readOnly);
1736
+ if (!index) acc.value += "{";
1737
+ const doc = jsDoc(schema, true, context);
1738
+ const propertyDoc = doc ? `${doc.trimEnd().split("\n").map((line) => ` ${line}`).join("\n")}\n` : "";
1739
+ if (isReadOnly || resolvedValue.hasReadonlyProps) acc.hasReadonlyProps = true;
1740
+ const constValue = "const" in schema ? schema.const : void 0;
1741
+ const hasConst = constValue !== void 0;
1742
+ let constLiteral;
1743
+ if (!hasConst) constLiteral = void 0;
1744
+ else if (isString(constValue)) constLiteral = `'${escape(constValue)}'`;
1745
+ else constLiteral = JSON.stringify(constValue);
1746
+ const needsValueImport = hasConst && (resolvedValue.isEnum || resolvedValue.type === "enum");
1747
+ const usedResolvedValue = !hasConst || needsValueImport;
1748
+ const aliasedImports = needsValueImport ? resolvedValue.imports.map((imp) => ({
1749
+ ...imp,
1750
+ isConstant: true
1751
+ })) : hasConst ? [] : getAliasedImports({
1789
1752
  name,
1790
- schemaObject: mediaType.schema,
1791
1753
  context,
1792
- isRequestBodyOptional: bodySchema.required !== true,
1793
- isUrlEncoded: true,
1794
- isRef: true,
1795
- encoding: mediaType.encoding
1796
- }) : void 0;
1797
- const additionalImports = getFormDataAdditionalImports({
1798
- schemaObject: mediaType.schema,
1799
- context
1754
+ resolvedValue
1800
1755
  });
1801
- return [{
1802
- value: name,
1803
- imports: [{
1804
- name,
1805
- schemaName
1806
- }, ...additionalImports],
1807
- schemas: [],
1808
- type: "unknown",
1809
- isEnum: false,
1810
- hasReadonlyProps: false,
1811
- dependencies: [name],
1812
- formData,
1813
- formUrlEncoded,
1814
- isRef: true,
1815
- originalSchema: mediaType.schema,
1816
- example: mediaType.example,
1817
- examples: resolveExampleRefs(mediaType.examples, context),
1818
- key,
1819
- contentType
1820
- }];
1821
- }
1822
- if (res.content) return Object.entries(res.content).map(([contentType, mediaType], index, arr) => {
1823
- let propName = key ? pascal(name) + pascal(key) : void 0;
1824
- if (propName && arr.length > 1) propName = propName + pascal(getNumberWord(index + 1));
1825
- const isFormData = formDataContentTypes.has(contentType);
1826
- const isFormUrlEncoded = formUrlEncodedContentTypes.has(contentType);
1827
- let effectivePropName = propName;
1828
- if (mediaType.schema && isReference(mediaType.schema)) {
1829
- const { imports } = resolveSchemaRef(mediaType.schema, context);
1830
- if (imports[0]?.name) effectivePropName = imports[0].name;
1831
- } else if ((isFormData || isFormUrlEncoded) && mediaType.schema) {
1832
- const combinedRefs = getSchemaOneOf(mediaType.schema) ?? getSchemaAnyOf(mediaType.schema);
1833
- if (combinedRefs) {
1834
- const names = [];
1835
- for (const ref of combinedRefs) {
1836
- if (!isReference(ref)) continue;
1837
- const refName = resolveSchemaRef(ref, context).imports[0]?.name;
1838
- if (refName) names.push(refName);
1839
- }
1840
- if (names.length > 0) effectivePropName = names.join("");
1841
- }
1842
- }
1843
- const resolvedValue = getResReqContentTypes({
1844
- mediaType,
1845
- propName: effectivePropName,
1756
+ if (aliasedImports.length > 0) acc.imports.push(...aliasedImports);
1757
+ const alias = getImportAliasForRefOrValue({
1846
1758
  context,
1847
- isFormData,
1848
- contentType
1759
+ resolvedValue,
1760
+ imports: aliasedImports
1849
1761
  });
1850
- if (!resolvedValue) {
1851
- if (isBinaryContentType(contentType)) return {
1852
- value: "Blob",
1853
- imports: [],
1854
- schemas: [],
1855
- type: "Blob",
1856
- isEnum: false,
1857
- key,
1858
- isRef: false,
1859
- hasReadonlyProps: false,
1860
- contentType
1861
- };
1862
- return;
1762
+ const propValue = needsValueImport ? alias : constLiteral ?? alias;
1763
+ const finalPropValue = isRequired ? propValue : context.output.override.useNullForOptional === true ? `${propValue} | null` : propValue;
1764
+ acc.value += `\n${propertyDoc}${isReadOnly && !context.output.override.suppressReadonlyModifier ? " readonly " : " "}${getKey(key)}${isRequired ? "" : "?"}: ${finalPropValue};`;
1765
+ if (usedResolvedValue) {
1766
+ acc.schemas.push(...resolvedValue.schemas);
1767
+ acc.dependencies.push(...resolvedValue.dependencies);
1768
+ }
1769
+ if (entries.length - 1 === index) {
1770
+ const additionalProps = schemaItem.additionalProperties;
1771
+ if (additionalProps) if (additionalProps === true) {
1772
+ const recordType = getPropertyNamesRecordType(schemaItem, "unknown", context);
1773
+ if (recordType) {
1774
+ acc.value += "\n}";
1775
+ acc.value += ` & ${recordType.value}`;
1776
+ acc.useTypeAlias = true;
1777
+ acc.imports.push(...recordType.imports);
1778
+ acc.dependencies.push(...recordType.dependencies);
1779
+ } else {
1780
+ const keyType = getIndexSignatureKey(schemaItem);
1781
+ acc.value += `\n [key: ${keyType}]: unknown;\n }`;
1782
+ }
1783
+ } else {
1784
+ const resolvedValue = resolveValue({
1785
+ schema: additionalProps,
1786
+ name,
1787
+ context
1788
+ });
1789
+ const recordType = getPropertyNamesRecordType(schemaItem, resolvedValue.value, context);
1790
+ if (recordType) {
1791
+ acc.value += "\n}";
1792
+ acc.value += ` & ${recordType.value}`;
1793
+ acc.useTypeAlias = true;
1794
+ acc.imports.push(...recordType.imports);
1795
+ acc.dependencies.push(...recordType.dependencies);
1796
+ } else {
1797
+ const keyType = getIndexSignatureKey(schemaItem);
1798
+ acc.value += `\n [key: ${keyType}]: ${resolvedValue.value};\n}`;
1799
+ }
1800
+ acc.imports.push(...resolvedValue.imports);
1801
+ acc.schemas.push(...resolvedValue.schemas);
1802
+ acc.dependencies.push(...resolvedValue.dependencies);
1803
+ }
1804
+ else acc.value += "\n}";
1805
+ acc.value += nullable;
1863
1806
  }
1864
- if (!isFormData && !isFormUrlEncoded || !effectivePropName || !mediaType.schema) return {
1865
- ...resolvedValue,
1866
- imports: resolvedValue.imports,
1867
- dependencies: resolvedValue.dependencies,
1868
- contentType,
1869
- example: mediaType.example,
1870
- examples: resolveExampleRefs(mediaType.examples, context)
1807
+ }
1808
+ return acc;
1809
+ }
1810
+ const outerAdditionalProps = schemaItem.additionalProperties;
1811
+ const readOnlyFlag = schemaItem.readOnly;
1812
+ if (outerAdditionalProps) {
1813
+ if (outerAdditionalProps === true) {
1814
+ const recordType = getPropertyNamesRecordType(schemaItem, "unknown", context);
1815
+ if (recordType) return {
1816
+ value: recordType.value + nullable,
1817
+ imports: recordType.imports,
1818
+ schemas: [],
1819
+ isEnum: false,
1820
+ type: "object",
1821
+ isRef: false,
1822
+ hasReadonlyProps: readOnlyFlag ?? false,
1823
+ useTypeAlias: true,
1824
+ dependencies: recordType.dependencies
1871
1825
  };
1872
- const formData = isFormData ? getSchemaFormDataAndUrlEncoded({
1873
- name: effectivePropName,
1874
- schemaObject: mediaType.schema,
1875
- context,
1876
- isRequestBodyOptional: res.required !== true,
1877
- isRef: true,
1878
- encoding: mediaType.encoding
1879
- }) : void 0;
1880
- const formUrlEncoded = isFormUrlEncoded ? getSchemaFormDataAndUrlEncoded({
1881
- name: effectivePropName,
1882
- schemaObject: mediaType.schema,
1883
- context,
1884
- isUrlEncoded: true,
1885
- isRequestBodyOptional: res.required !== true,
1886
- isRef: true,
1887
- encoding: mediaType.encoding
1888
- }) : void 0;
1889
- const additionalImports = getFormDataAdditionalImports({
1890
- schemaObject: mediaType.schema,
1891
- context
1892
- });
1893
1826
  return {
1894
- ...resolvedValue,
1895
- imports: [...resolvedValue.imports, ...additionalImports],
1896
- formData,
1897
- formUrlEncoded,
1898
- contentType,
1899
- example: mediaType.example,
1900
- examples: resolveExampleRefs(mediaType.examples, context)
1827
+ value: `{ [key: ${getIndexSignatureKey(schemaItem)}]: unknown }` + nullable,
1828
+ imports: [],
1829
+ schemas: [],
1830
+ isEnum: false,
1831
+ type: "object",
1832
+ isRef: false,
1833
+ hasReadonlyProps: readOnlyFlag ?? false,
1834
+ useTypeAlias: false,
1835
+ dependencies: []
1901
1836
  };
1902
- }).filter(Boolean).map((x) => ({
1903
- ...x,
1904
- key
1905
- }));
1906
- const swaggerSchema = "schema" in res ? res.schema : void 0;
1907
- if (swaggerSchema) return [{
1908
- ...resolveObject({
1909
- schema: swaggerSchema,
1910
- propName: key ? pascal(name) + pascal(key) : void 0,
1911
- context
1912
- }),
1913
- contentType: "application/json",
1914
- key
1915
- }];
1916
- return [{
1917
- value: defaultType,
1837
+ }
1838
+ const resolvedValue = resolveValue({
1839
+ schema: outerAdditionalProps,
1840
+ name,
1841
+ context
1842
+ });
1843
+ const recordType = getPropertyNamesRecordType(schemaItem, resolvedValue.value, context);
1844
+ if (recordType) return {
1845
+ value: recordType.value + nullable,
1846
+ imports: [...recordType.imports, ...resolvedValue.imports],
1847
+ schemas: resolvedValue.schemas,
1848
+ isEnum: false,
1849
+ type: "object",
1850
+ isRef: false,
1851
+ hasReadonlyProps: resolvedValue.hasReadonlyProps,
1852
+ useTypeAlias: true,
1853
+ dependencies: [...recordType.dependencies, ...resolvedValue.dependencies]
1854
+ };
1855
+ return {
1856
+ value: `{[key: ${getIndexSignatureKey(schemaItem)}]: ${resolvedValue.value}}` + nullable,
1857
+ imports: resolvedValue.imports,
1858
+ schemas: resolvedValue.schemas,
1859
+ isEnum: false,
1860
+ type: "object",
1861
+ isRef: false,
1862
+ hasReadonlyProps: resolvedValue.hasReadonlyProps,
1863
+ useTypeAlias: false,
1864
+ dependencies: resolvedValue.dependencies
1865
+ };
1866
+ }
1867
+ const constValue = schemaItem.const;
1868
+ if (constValue !== void 0) {
1869
+ let type;
1870
+ if (Array.isArray(constValue)) type = "array";
1871
+ else if (constValue === null) type = "null";
1872
+ else if (typeof constValue === "string") type = "string";
1873
+ else if (typeof constValue === "number") type = "number";
1874
+ else if (typeof constValue === "boolean") type = "boolean";
1875
+ else type = "object";
1876
+ return {
1877
+ value: typeof constValue === "string" ? `'${escape(constValue)}'` : JSON.stringify(constValue),
1918
1878
  imports: [],
1919
1879
  schemas: [],
1920
- type: defaultType,
1921
1880
  isEnum: false,
1922
- dependencies: [],
1923
- key,
1881
+ type,
1924
1882
  isRef: false,
1925
- hasReadonlyProps: false,
1926
- contentType: "application/json"
1927
- }];
1928
- }).flat(), uniqueKey);
1929
- }
1930
- /**
1931
- * Determine the responseType option based on success content types only.
1932
- * This avoids error-response content types influencing the responseType.
1933
- */
1934
- function getSuccessResponseType(response) {
1935
- const successContentTypes = response.types.success.map((t) => t.contentType).filter(Boolean);
1936
- if (response.isBlob) return "blob";
1937
- const hasJsonResponse = successContentTypes.some((contentType) => contentType.includes("json") || contentType.includes("+json"));
1938
- const hasTextResponse = successContentTypes.some((contentType) => contentType.startsWith("text/") || contentType.includes("xml"));
1939
- if (!hasJsonResponse && hasTextResponse) return "text";
1940
- }
1941
- /**
1942
- * Determine the response type category for a given content type.
1943
- * Used to set the correct responseType option in HTTP clients.
1944
- *
1945
- * @param contentType - The MIME content type (e.g., 'application/json', 'text/plain')
1946
- * @returns The response type category to use for parsing
1947
- */
1948
- function getResponseTypeCategory(contentType) {
1949
- if (isBinaryContentType(contentType)) return "blob";
1950
- if (contentType === "application/json" || contentType.includes("+json") || contentType.includes("-json")) return "json";
1951
- return "text";
1883
+ hasReadonlyProps: readOnlyFlag ?? false,
1884
+ dependencies: []
1885
+ };
1886
+ }
1887
+ const keyType = itemType === "object" ? getIndexSignatureKey(schemaItem) : "string";
1888
+ const recordType = getPropertyNamesRecordType(schemaItem, "unknown", context);
1889
+ if (itemType === "object" && recordType) return {
1890
+ value: recordType.value + nullable,
1891
+ imports: recordType.imports,
1892
+ schemas: [],
1893
+ isEnum: false,
1894
+ type: "object",
1895
+ isRef: false,
1896
+ hasReadonlyProps: readOnlyFlag ?? false,
1897
+ useTypeAlias: true,
1898
+ dependencies: recordType.dependencies
1899
+ };
1900
+ return {
1901
+ value: (itemType === "object" ? `{ [key: ${keyType}]: unknown }` : "unknown") + nullable,
1902
+ imports: [],
1903
+ schemas: [],
1904
+ isEnum: false,
1905
+ type: "object",
1906
+ isRef: false,
1907
+ hasReadonlyProps: readOnlyFlag ?? false,
1908
+ useTypeAlias: false,
1909
+ dependencies: []
1910
+ };
1952
1911
  }
1912
+ //#endregion
1913
+ //#region src/getters/scalar.ts
1953
1914
  /**
1954
- * Get the default content type from a list of content types.
1955
- * Priority: application/json > any JSON-like type > first in list
1915
+ * Returns true when a schema describes a raw binary string scalar — i.e. one
1916
+ * that getScalar's `case 'string':` branch would coerce to `Blob` outside a
1917
+ * url-encoded context (see the formDataContext.urlEncoded gate below). Shared
1918
+ * with resolveValue so the component-`$ref` urlEncoded short-circuit and the
1919
+ * inline scalar path stay in lockstep when new binary shapes are added
1920
+ * (#1624 / #3395 / #2410).
1956
1921
  *
1957
- * @param contentTypes - Array of content types from OpenAPI spec
1958
- * @returns The default content type to use
1959
- */
1960
- function getDefaultContentType(contentTypes) {
1961
- if (contentTypes.length === 0) return "application/json";
1962
- if (contentTypes.includes("application/json")) return "application/json";
1963
- const jsonType = contentTypes.find((ct) => ct.includes("+json") || ct.includes("-json"));
1964
- if (jsonType) return jsonType;
1965
- return contentTypes[0];
1966
- }
1967
- function getFormDataAdditionalImports({ schemaObject, context }) {
1968
- const { schema } = resolveSchemaRef(schemaObject, context);
1969
- if (schema.type !== "object") return [];
1970
- const combinedSchemas = getSchemaOneOf(schema) ?? getSchemaAnyOf(schema);
1971
- if (!combinedSchemas) return [];
1972
- return combinedSchemas.map((subSchema) => resolveSchemaRef(subSchema, context).imports[0]).filter(Boolean);
1973
- }
1974
- function getSchemaFormDataAndUrlEncoded({ name, schemaObject, context, isRequestBodyOptional, isUrlEncoded, isRef, encoding }) {
1975
- const { schema, imports } = resolveSchemaRef(schemaObject, context);
1976
- const propName = camel(!isRef && isReference(schemaObject) ? imports[0].name : name);
1977
- const variableName = isUrlEncoded ? "formUrlEncoded" : "formData";
1978
- let form = isUrlEncoded ? `const ${variableName} = new URLSearchParams();\n` : `const ${variableName} = new FormData();\n`;
1979
- const combinedSchemas = getSchemaCombined(schema);
1980
- if (schema.type === "object" || schema.type === void 0 && combinedSchemas) {
1981
- if (combinedSchemas) if (!!getSchemaOneOf(schema) || !!getSchemaAnyOf(schema)) {
1982
- const directProperties = getSchemaProperties(schema);
1983
- const directKeys = directProperties ? Object.entries(directProperties).filter(([, value]) => !resolveSchemaRef(value, context).schema.readOnly).map(([key]) => key) : [];
1984
- const skipLine = directKeys.length > 0 ? ` if ([${directKeys.map((k) => JSON.stringify(k)).join(", ")}].includes(key)) return;\n` : "";
1985
- form += `Object.entries(${propName} ?? {}).forEach(([key, value]) => {\n`;
1986
- form += skipLine;
1987
- form += ` if (value !== undefined && value !== null) {\n`;
1988
- if (isUrlEncoded) {
1989
- form += ` if (Array.isArray(value)) {\n`;
1990
- form += ` value.forEach(v => {\n`;
1991
- form += ` ${variableName}.append(key, typeof v === 'object' ? JSON.stringify(v) : String(v));\n`;
1992
- form += ` });\n`;
1993
- form += ` } else if (typeof value === 'object') {\n`;
1994
- form += ` ${variableName}.append(key, JSON.stringify(value));\n`;
1995
- form += ` } else {\n`;
1996
- form += ` ${variableName}.append(key, String(value));\n`;
1997
- form += ` }\n`;
1998
- } else {
1999
- form += ` if ((typeof File !== 'undefined' && value instanceof File) || value instanceof Blob) {\n`;
2000
- form += ` ${variableName}.append(key, value);\n`;
2001
- form += ` } else if (typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) {\n`;
2002
- form += ` ${variableName}.append(key, new Blob([Uint8Array.from(value)]));\n`;
2003
- form += ` } else if (Array.isArray(value)) {\n`;
2004
- form += ` value.forEach(v => {\n`;
2005
- form += ` if ((typeof File !== 'undefined' && v instanceof File) || v instanceof Blob) {\n`;
2006
- form += ` ${variableName}.append(key, v);\n`;
2007
- form += ` } else if (typeof Buffer !== 'undefined' && Buffer.isBuffer(v)) {\n`;
2008
- form += ` ${variableName}.append(key, new Blob([Uint8Array.from(v)]));\n`;
2009
- form += ` } else {\n`;
2010
- form += ` ${variableName}.append(key, typeof v === 'object' ? JSON.stringify(v) : String(v));\n`;
2011
- form += ` }\n`;
2012
- form += ` });\n`;
2013
- form += ` } else if (typeof value === 'object') {\n`;
2014
- form += ` ${variableName}.append(key, JSON.stringify(value));\n`;
2015
- form += ` } else {\n`;
2016
- form += ` ${variableName}.append(key, String(value));\n`;
2017
- form += ` }\n`;
1922
+ * Accepts OAS 3.1 nullable unions (`type: ['string', 'null']`) since getScalar
1923
+ * normalizes those into `case 'string':` before invoking this predicate.
1924
+ */
1925
+ function isBinaryScalarSchema(schema) {
1926
+ const schemaType = schema.type;
1927
+ if (!(schemaType === "string" || isArray(schemaType) && schemaType.includes("string") && schemaType.every((type) => type === "string" || type === "null"))) return false;
1928
+ if (schema.format === "binary") return true;
1929
+ const contentMediaType = schema.contentMediaType;
1930
+ const contentEncoding = schema.contentEncoding;
1931
+ return contentMediaType === "application/octet-stream" && !contentEncoding;
1932
+ }
1933
+ /**
1934
+ * Return the typescript equivalent of open-api data type
1935
+ *
1936
+ * @param item
1937
+ * @ref https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.1.md#data-types
1938
+ */
1939
+ function getScalar({ item, name, context, formDataContext }) {
1940
+ const schemaEnum = item.enum;
1941
+ const schemaType = item.type;
1942
+ const schemaReadOnly = item.readOnly;
1943
+ const schemaExample = item.example;
1944
+ const schemaExamples = item.examples;
1945
+ const schemaConst = item.const;
1946
+ const schemaFormat = item.format;
1947
+ const schemaNullable = item.nullable;
1948
+ const nullable = isArray(schemaType) && schemaType.includes("null") || schemaNullable === true ? " | null" : "";
1949
+ const enumItems = schemaEnum?.filter((enumItem) => enumItem !== null);
1950
+ let itemType = schemaType;
1951
+ if (!itemType && item.items) {
1952
+ item.type = "array";
1953
+ itemType = "array";
1954
+ }
1955
+ if (isArray(schemaType) && schemaType.includes("null")) {
1956
+ const typesWithoutNull = schemaType.filter((x) => x !== "null");
1957
+ itemType = typesWithoutNull.length === 1 ? typesWithoutNull[0] : typesWithoutNull;
1958
+ }
1959
+ switch (itemType) {
1960
+ case "number":
1961
+ case "integer": {
1962
+ let value = context.output.override.useBigInt && (schemaFormat === "int64" || schemaFormat === "uint64") ? "bigint" : "number";
1963
+ let isEnum = false;
1964
+ if (enumItems) {
1965
+ value = enumItems.map((enumItem) => `${enumItem}`).join(" | ");
1966
+ isEnum = true;
2018
1967
  }
2019
- form += ` }\n`;
2020
- form += `});\n`;
2021
- } else {
2022
- const combinedSchemasFormData = combinedSchemas.map((subSchema) => {
2023
- const { schema: combinedSchema } = resolveSchemaRef(subSchema, context);
2024
- return resolveSchemaPropertiesToFormData({
2025
- schema: combinedSchema,
2026
- variableName,
2027
- propName,
2028
- context,
2029
- isRequestBodyOptional,
2030
- encoding
2031
- });
2032
- }).filter(Boolean).join("\n");
2033
- form += combinedSchemasFormData;
1968
+ value += nullable;
1969
+ if (schemaConst !== void 0) value = schemaConst;
1970
+ return {
1971
+ value,
1972
+ isEnum,
1973
+ type: "number",
1974
+ schemas: [],
1975
+ imports: [],
1976
+ isRef: false,
1977
+ hasReadonlyProps: schemaReadOnly ?? false,
1978
+ dependencies: [],
1979
+ example: schemaExample,
1980
+ examples: resolveExampleRefs(schemaExamples, context)
1981
+ };
2034
1982
  }
2035
- if (schema.properties) {
2036
- const formDataValues = resolveSchemaPropertiesToFormData({
2037
- schema,
2038
- variableName,
2039
- propName,
1983
+ case "boolean": {
1984
+ let value = "boolean";
1985
+ if (enumItems && !(enumItems.includes(true) && enumItems.includes(false))) value = enumItems.map((enumItem) => `${enumItem}`).join(" | ");
1986
+ value += nullable;
1987
+ if (schemaConst !== void 0) value = schemaConst;
1988
+ return {
1989
+ value,
1990
+ type: "boolean",
1991
+ isEnum: false,
1992
+ schemas: [],
1993
+ imports: [],
1994
+ isRef: false,
1995
+ hasReadonlyProps: schemaReadOnly ?? false,
1996
+ dependencies: [],
1997
+ example: schemaExample,
1998
+ examples: resolveExampleRefs(schemaExamples, context)
1999
+ };
2000
+ }
2001
+ case "array": {
2002
+ const { value, ...rest } = getArray({
2003
+ schema: item,
2004
+ name,
2040
2005
  context,
2041
- isRequestBodyOptional,
2042
- encoding
2006
+ formDataContext
2043
2007
  });
2044
- form += formDataValues;
2045
- }
2046
- return form;
2047
- }
2048
- if (schema.type === "array") {
2049
- let valueStr = "value";
2050
- const schemaItems = getSchemaItems(schema);
2051
- if (schemaItems) {
2052
- const { schema: itemSchema } = resolveSchemaRef(schemaItems, context);
2053
- if (itemSchema.type === "object" || itemSchema.type === "array") valueStr = "JSON.stringify(value)";
2054
- else if (itemSchema.type === "number" || itemSchema.type === "integer" || itemSchema.type === "boolean") valueStr = "value.toString()";
2008
+ return {
2009
+ value: value + nullable,
2010
+ ...rest,
2011
+ dependencies: rest.dependencies
2012
+ };
2055
2013
  }
2056
- return `${form}${propName}.forEach(value => ${variableName}.append('data', ${valueStr}))\n`;
2057
- }
2058
- if (schema.type === "number" || schema.type === "integer" || schema.type === "boolean") return `${form}${variableName}.append('data', ${propName}.toString())\n`;
2059
- return `${form}${variableName}.append('data', ${propName})\n`;
2060
- }
2061
- function resolveSchemaPropertiesToFormData({ schema, variableName, propName, context, isRequestBodyOptional, keyPrefix = "", depth = 0, encoding }) {
2062
- let formDataValues = "";
2063
- const isUrlEncoded = variableName === "formUrlEncoded";
2064
- const schemaProps = getSchemaProperties(schema) ?? {};
2065
- for (const [key, value] of Object.entries(schemaProps)) {
2066
- const { schema: property } = resolveSchemaRef(value, context);
2067
- if (property.readOnly) continue;
2068
- let formDataValue = "";
2069
- const partContentType = (depth === 0 ? encoding?.[key] : void 0)?.contentType;
2070
- const formattedKeyPrefix = isRequestBodyOptional ? keyword.isIdentifierNameES5(key) ? "?" : "?." : "";
2071
- const formattedKey = keyword.isIdentifierNameES5(key) ? `.${key}` : `['${key}']`;
2072
- const valueKey = `${propName}${formattedKeyPrefix}${formattedKey}`;
2073
- const nonOptionalValueKey = `${propName}${formattedKey}`;
2074
- const fileType = getFormDataFieldFileType(property, partContentType);
2075
- const effectiveContentType = partContentType ?? property.contentMediaType;
2076
- if (isUrlEncoded && (fileType || property.format === "binary")) formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey});\n`;
2077
- else if (fileType === "binary" || property.format === "binary") formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey});\n`;
2078
- else if (fileType === "text") formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey} instanceof Blob ? ${nonOptionalValueKey} : new Blob([${nonOptionalValueKey}], { type: '${effectiveContentType}' }));\n`;
2079
- else if (property.type === "object") formDataValue = context.output.override.formData.arrayHandling === FormDataArrayHandling.EXPLODE ? resolveSchemaPropertiesToFormData({
2080
- schema: property,
2081
- variableName,
2082
- propName: nonOptionalValueKey,
2083
- context,
2084
- isRequestBodyOptional,
2085
- keyPrefix: `${keyPrefix}${key}.`,
2086
- depth: depth + 1,
2087
- encoding
2088
- }) : `${variableName}.append(\`${keyPrefix}${key}\`, JSON.stringify(${nonOptionalValueKey}));\n`;
2089
- else if (property.type === "array") {
2090
- let valueStr = "value";
2091
- let hasNonPrimitiveChild = false;
2092
- const propertyItems = getSchemaItems(property);
2093
- if (propertyItems) {
2094
- const { schema: itemSchema } = resolveSchemaRef(propertyItems, context);
2095
- if (itemSchema.type === "object" || itemSchema.type === "array") if (context.output.override.formData.arrayHandling === FormDataArrayHandling.EXPLODE) {
2096
- hasNonPrimitiveChild = true;
2097
- const resolvedValue = resolveSchemaPropertiesToFormData({
2098
- schema: itemSchema,
2099
- variableName,
2100
- propName: "value",
2101
- context,
2102
- isRequestBodyOptional,
2103
- keyPrefix: `${keyPrefix}${key}[\${index${depth > 0 ? depth : ""}}].`,
2104
- depth: depth + 1
2105
- });
2106
- formDataValue = `${valueKey}.forEach((value, index${depth > 0 ? depth : ""}) => {
2107
- ${resolvedValue}});\n`;
2108
- } else valueStr = "JSON.stringify(value)";
2109
- else {
2110
- const itemType = getSchemaType$1(itemSchema);
2111
- 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()";
2112
- }
2014
+ case "string": {
2015
+ let value = "string";
2016
+ let isEnum = false;
2017
+ if (enumItems) {
2018
+ value = enumItems.map((enumItem) => isString(enumItem) ? `'${escape(enumItem)}'` : `${enumItem}`).filter(Boolean).join(` | `);
2019
+ isEnum = true;
2113
2020
  }
2114
- if (context.output.override.formData.arrayHandling === FormDataArrayHandling.EXPLODE) {
2115
- if (!hasNonPrimitiveChild) formDataValue = `${valueKey}.forEach((value, index${depth > 0 ? depth : ""}) => ${variableName}.append(\`${keyPrefix}${key}[\${index${depth > 0 ? depth : ""}}]\`, ${valueStr}));\n`;
2116
- } else formDataValue = `${valueKey}.forEach(value => ${variableName}.append(\`${keyPrefix}${key}${context.output.override.formData.arrayHandling === FormDataArrayHandling.SERIALIZE_WITH_BRACKETS ? "[]" : ""}\`, ${valueStr}));\n`;
2117
- } else if ((() => {
2118
- const propType = getSchemaType$1(property);
2119
- return propType === "number" || Array.isArray(propType) && propType.includes("number") || propType === "integer" || Array.isArray(propType) && propType.includes("integer") || propType === "boolean" || Array.isArray(propType) && propType.includes("boolean");
2120
- })()) formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey}.toString())\n`;
2121
- else formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey});\n`;
2122
- let existSubSchemaNullable = false;
2123
- const combine = getSchemaCombined(property);
2124
- if (combine) {
2125
- const subSchemas = combine.map((c) => resolveObject({
2126
- schema: c,
2127
- combined: true,
2128
- context
2129
- }));
2130
- if (subSchemas.some((subSchema) => {
2131
- return [
2132
- "number",
2133
- "integer",
2134
- "boolean"
2135
- ].includes(subSchema.type);
2136
- })) formDataValue = `${variableName}.append(\`${key}\`, ${nonOptionalValueKey}.toString())\n`;
2137
- if (subSchemas.some((subSchema) => {
2138
- return subSchema.type === "null";
2139
- })) existSubSchemaNullable = true;
2140
- }
2141
- const isRequired = getSchemaRequired(schema)?.includes(key) && !isRequestBodyOptional;
2142
- const propType = getSchemaType$1(property);
2143
- if (property.nullable || Array.isArray(propType) && propType.includes("null") || existSubSchemaNullable) {
2144
- if (isRequired) {
2145
- formDataValues += `if(${valueKey} !== null) {\n ${formDataValue} }\n`;
2146
- continue;
2021
+ if (!formDataContext?.urlEncoded) {
2022
+ if (schemaFormat === "binary") value = "Blob";
2023
+ else if (formDataContext?.atPart) {
2024
+ const fileType = getFormDataFieldFileType(item, formDataContext.partContentType);
2025
+ if (fileType) value = fileType === "binary" ? "Blob" : "Blob | string";
2026
+ } else if (isBinaryScalarSchema(item)) value = "Blob";
2147
2027
  }
2148
- formDataValues += `if(${valueKey} !== undefined && ${nonOptionalValueKey} !== null) {\n ${formDataValue} }\n`;
2149
- continue;
2028
+ if (context.output.override.useDates && (schemaFormat === "date" || schemaFormat === "date-time")) value = "Date";
2029
+ value += nullable;
2030
+ if (schemaConst) value = `'${schemaConst}'`;
2031
+ return {
2032
+ value,
2033
+ isEnum,
2034
+ type: "string",
2035
+ imports: [],
2036
+ schemas: [],
2037
+ isRef: false,
2038
+ hasReadonlyProps: schemaReadOnly ?? false,
2039
+ dependencies: [],
2040
+ example: schemaExample,
2041
+ examples: resolveExampleRefs(schemaExamples, context)
2042
+ };
2150
2043
  }
2151
- if (isRequired) {
2152
- formDataValues += formDataValue;
2153
- continue;
2044
+ case "null": return {
2045
+ value: "null",
2046
+ isEnum: false,
2047
+ type: "null",
2048
+ imports: [],
2049
+ schemas: [],
2050
+ isRef: false,
2051
+ hasReadonlyProps: schemaReadOnly ?? false,
2052
+ dependencies: []
2053
+ };
2054
+ default: {
2055
+ if (isArray(itemType)) return combineSchemas({
2056
+ schema: { anyOf: itemType.map((type) => Object.assign({}, item, { type })) },
2057
+ name,
2058
+ separator: "anyOf",
2059
+ context,
2060
+ nullable
2061
+ });
2062
+ if (enumItems) return {
2063
+ value: enumItems.map((enumItem) => isString(enumItem) ? `'${escape(enumItem)}'` : String(enumItem)).filter(Boolean).join(` | `) + nullable,
2064
+ isEnum: true,
2065
+ type: "string",
2066
+ imports: [],
2067
+ schemas: [],
2068
+ isRef: false,
2069
+ hasReadonlyProps: schemaReadOnly ?? false,
2070
+ dependencies: [],
2071
+ example: schemaExample,
2072
+ examples: resolveExampleRefs(schemaExamples, context)
2073
+ };
2074
+ const hasCombiners = item.allOf ?? item.anyOf ?? item.oneOf;
2075
+ const { value, ...rest } = getObject({
2076
+ item,
2077
+ name,
2078
+ context,
2079
+ nullable,
2080
+ formDataContext: formDataContext?.atPart === false || formDataContext?.atPart && hasCombiners ? formDataContext : void 0
2081
+ });
2082
+ return {
2083
+ value,
2084
+ ...rest
2085
+ };
2154
2086
  }
2155
- formDataValues += `if(${valueKey} !== undefined) {\n ${formDataValue} }\n`;
2156
2087
  }
2157
- return formDataValues;
2158
2088
  }
2159
2089
  //#endregion
2160
- //#region src/getters/body.ts
2161
- function buildBody(filteredBodyTypes, requestBody, operationName, context) {
2162
- const imports = filteredBodyTypes.flatMap(({ imports }) => imports);
2163
- const schemas = filteredBodyTypes.flatMap(({ schemas }) => schemas);
2164
- const definition = filteredBodyTypes.map(({ value }) => value).join(" | ");
2165
- const nonReadonlyDefinition = filteredBodyTypes.some((x) => x.hasReadonlyProps) && definition && context.output.override.preserveReadonlyRequestBodies !== "preserve" ? `NonReadonly<${definition}>` : definition;
2166
- let implementation = generalJSTypesWithArray.includes(definition.toLowerCase()) || filteredBodyTypes.length > 1 ? camel(operationName) + context.output.override.components.requestBodies.suffix : camel(definition);
2167
- let isOptional = false;
2168
- if (implementation) {
2169
- implementation = sanitize(implementation, {
2170
- underscore: "_",
2171
- whitespace: "_",
2172
- dash: true,
2173
- es5keyword: true,
2174
- es5IdentifierName: true
2175
- });
2176
- if (isReference(requestBody)) {
2177
- const { schema: bodySchema } = resolveRef(requestBody, context);
2178
- isOptional = bodySchema.required !== true;
2179
- } else isOptional = requestBody.required !== true;
2180
- }
2181
- return {
2182
- originalSchema: requestBody,
2183
- definition: nonReadonlyDefinition,
2184
- implementation,
2185
- imports,
2186
- schemas,
2187
- isOptional,
2188
- ...filteredBodyTypes.length === 1 ? {
2189
- formData: filteredBodyTypes[0].formData,
2190
- formUrlEncoded: filteredBodyTypes[0].formUrlEncoded,
2191
- contentType: filteredBodyTypes[0].contentType
2192
- } : {
2193
- formData: "",
2194
- formUrlEncoded: "",
2195
- contentType: ""
2196
- }
2197
- };
2198
- }
2199
- function getBody({ requestBody, operationName, context, contentType }) {
2200
- return buildBody(filterByContentType(getResReqTypes([[context.output.override.components.requestBodies.suffix, requestBody]], operationName, context), contentType), requestBody, operationName, context);
2201
- }
2090
+ //#region src/resolvers/ref.ts
2091
+ const REF_NOT_FOUND_PREFIX = "Oops... 🍻. Ref not found";
2202
2092
  /**
2203
- * Returns per-content-type bodies when `splitByContentType` is enabled.
2204
- * Each entry includes a `contentTypeSuffix` for generating distinct function names.
2093
+ * Recursively resolves a `$ref` in an OpenAPI document, following
2094
+ * nested schema refs and collecting imports along the way.
2095
+ *
2096
+ * Handles OpenAPI 3.0 `nullable` and 3.1 type-array hints on direct refs.
2097
+ *
2098
+ * @see https://spec.openapis.org/oas/v3.0.3#reference-object
2099
+ * @see https://spec.openapis.org/oas/v3.1.0#reference-object
2205
2100
  */
2206
- function getBodiesByContentType({ requestBody, operationName, context, contentType }) {
2207
- const filteredBodyTypes = filterByContentType(getResReqTypes([[context.output.override.components.requestBodies.suffix, requestBody]], operationName, context, void 0, (item) => `${item.value}::${item.contentType}`), contentType);
2208
- if (filteredBodyTypes.length <= 1) return [{
2209
- ...buildBody(filteredBodyTypes, requestBody, operationName, context),
2210
- contentTypeSuffix: ""
2211
- }];
2212
- return filteredBodyTypes.map((bodyType) => {
2213
- const suffix = getContentTypeSuffix(bodyType.contentType);
2101
+ function resolveRef(schema, context, imports = []) {
2102
+ const refPath = "$ref" in schema ? schema.$ref : void 0;
2103
+ const nestedSchema = "schema" in schema ? schema.schema : void 0;
2104
+ if (isObject(nestedSchema) && isReference(nestedSchema) && typeof nestedSchema.$ref === "string") {
2105
+ const resolvedRef = resolveRef(nestedSchema, context, imports);
2106
+ if ("examples" in schema) {
2107
+ const schemaWithExamples = schema;
2108
+ schemaWithExamples.examples = resolveExampleRefs(schemaWithExamples.examples, context);
2109
+ }
2110
+ if ("examples" in resolvedRef.schema) {
2111
+ const resolvedWithExamples = resolvedRef.schema;
2112
+ resolvedWithExamples.examples = resolveExampleRefs(resolvedWithExamples.examples, context);
2113
+ }
2214
2114
  return {
2215
- ...buildBody([bodyType], requestBody, operationName, context),
2216
- contentTypeSuffix: suffix
2115
+ schema: {
2116
+ ...schema,
2117
+ schema: resolvedRef.schema
2118
+ },
2119
+ imports: resolvedRef.imports
2217
2120
  };
2218
- });
2219
- }
2220
- const CONTENT_TYPE_SUFFIX_MAP = {
2221
- "application/json": "Json",
2222
- "multipart/form-data": "FormData",
2223
- "application/x-www-form-urlencoded": "UrlEncoded",
2224
- "text/plain": "Text",
2225
- "application/xml": "Xml",
2226
- "text/xml": "Xml",
2227
- "application/octet-stream": "Blob"
2228
- };
2229
- function getContentTypeSuffix(contentType) {
2230
- if (CONTENT_TYPE_SUFFIX_MAP[contentType]) return CONTENT_TYPE_SUFFIX_MAP[contentType];
2231
- return (contentType.split("/")[1] ?? contentType).split(/[-+.]/).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
2232
- }
2233
- //#endregion
2234
- //#region src/getters/imports.ts
2235
- function getAliasedImports({ name, resolvedValue, context }) {
2236
- return context.output.schemas && resolvedValue.isRef ? resolvedValue.imports.map((imp) => {
2237
- if (!needCreateImportAlias({
2238
- name,
2239
- imp
2240
- })) return imp;
2121
+ }
2122
+ if (isDereferenced(schema)) {
2123
+ if ("examples" in schema) {
2124
+ const schemaWithExamples = schema;
2125
+ schemaWithExamples.examples = resolveExampleRefs(schemaWithExamples.examples, context);
2126
+ }
2241
2127
  return {
2242
- ...imp,
2243
- alias: `__${imp.name}`
2128
+ schema,
2129
+ imports
2244
2130
  };
2245
- }) : resolvedValue.imports;
2246
- }
2247
- function needCreateImportAlias({ imp, name }) {
2248
- return !imp.alias && imp.name === name;
2131
+ }
2132
+ if (!refPath) throw new Error(`${REF_NOT_FOUND_PREFIX}: missing $ref`);
2133
+ const { currentSchema, refInfo: { name, originalName } } = getSchema$1(schema, context);
2134
+ if (!currentSchema) throw new Error(`${REF_NOT_FOUND_PREFIX}: ${refPath}`);
2135
+ return resolveRef(currentSchema, { ...context }, [...imports, {
2136
+ name,
2137
+ schemaName: originalName
2138
+ }]);
2249
2139
  }
2250
- function getImportAliasForRefOrValue({ context, imports, resolvedValue }) {
2251
- if (!context.output.schemas || !resolvedValue.isRef) return resolvedValue.value;
2252
- return imports.find((imp) => imp.name === resolvedValue.value)?.alias ?? resolvedValue.value;
2140
+ /**
2141
+ * Looks up a schema by its `$ref` path in the spec, applying suffix resolution.
2142
+ *
2143
+ * Preserves OpenAPI 3.0 `nullable` and 3.1 type-array (`["object", "null"]`)
2144
+ * hints from the referencing schema onto the resolved target.
2145
+ *
2146
+ * @see https://spec.openapis.org/oas/v3.0.3#fixed-fields-18 (nullable)
2147
+ * @see https://spec.openapis.org/oas/v3.1.0#schema-object (type as array)
2148
+ */
2149
+ function getSchema$1(schema, context) {
2150
+ if (!schema.$ref) throw new Error(`${REF_NOT_FOUND_PREFIX}: missing $ref`);
2151
+ const refInfo = getRefInfo(schema.$ref, context);
2152
+ const { refPaths } = refInfo;
2153
+ const schemaByRefPaths = Array.isArray(refPaths) ? prop(context.spec, ...refPaths) : void 0;
2154
+ if (isObject(schemaByRefPaths) && isReference(schemaByRefPaths)) return getSchema$1(schemaByRefPaths, context);
2155
+ let currentSchema = schemaByRefPaths;
2156
+ if (isObject(currentSchema) && "nullable" in schema) {
2157
+ const nullable = schema.nullable;
2158
+ currentSchema = {
2159
+ ...currentSchema,
2160
+ nullable
2161
+ };
2162
+ }
2163
+ if (isObject(currentSchema) && "type" in schema && Array.isArray(schema.type)) {
2164
+ const type = schema.type;
2165
+ currentSchema = {
2166
+ ...currentSchema,
2167
+ type
2168
+ };
2169
+ }
2170
+ return {
2171
+ currentSchema,
2172
+ refInfo
2173
+ };
2253
2174
  }
2254
- //#endregion
2255
- //#region src/getters/keys.ts
2256
- function getKey(key) {
2257
- return keyword.isIdentifierNameES5(key) ? key : `'${key}'`;
2175
+ /** Recursively resolves `$ref` entries in an examples array or record. */
2176
+ function resolveExampleRefs(examples, context) {
2177
+ if (!examples) return;
2178
+ return Array.isArray(examples) ? examples.map((example) => {
2179
+ if (isObject(example) && isReference(example)) {
2180
+ const { schema } = resolveRef(example, context);
2181
+ return schema.value;
2182
+ }
2183
+ return example;
2184
+ }) : (() => {
2185
+ const result = {};
2186
+ for (const [key, example] of Object.entries(examples)) result[key] = isObject(example) && isReference(example) ? resolveRef(example, context).schema.value : example;
2187
+ return result;
2188
+ })();
2258
2189
  }
2259
2190
  //#endregion
2260
- //#region src/getters/object.ts
2261
- function getPropertyNamesEnumKeyType(item) {
2262
- if (!("propertyNames" in item) || !item.propertyNames) return;
2263
- const propertyNames = item.propertyNames;
2264
- if (Array.isArray(propertyNames.enum)) {
2265
- const enumValues = propertyNames.enum.filter((val) => isString(val));
2266
- if (enumValues.length > 0) return {
2267
- value: enumValues.map((val) => `'${escape(val)}'`).join(" | "),
2268
- imports: [],
2269
- dependencies: []
2191
+ //#region src/resolvers/value.ts
2192
+ function resolveValue({ schema, name, context, formDataContext }) {
2193
+ if (isReference(schema)) {
2194
+ const refValue = schema.$ref;
2195
+ const { schema: schemaObject, imports } = resolveRef(schema, context);
2196
+ if (refValue && !isComponentRef(refValue)) {
2197
+ if (context.parents?.includes(refValue)) return {
2198
+ value: "unknown",
2199
+ imports: [],
2200
+ schemas: [],
2201
+ type: "unknown",
2202
+ isEnum: false,
2203
+ originalSchema: schemaObject,
2204
+ hasReadonlyProps: false,
2205
+ isRef: false,
2206
+ dependencies: []
2207
+ };
2208
+ return {
2209
+ ...getScalar({
2210
+ item: schemaObject,
2211
+ name,
2212
+ context: {
2213
+ ...context,
2214
+ parents: [...context.parents ?? [], refValue]
2215
+ },
2216
+ formDataContext
2217
+ }),
2218
+ originalSchema: schemaObject,
2219
+ isRef: false
2220
+ };
2221
+ }
2222
+ if (formDataContext?.urlEncoded && isBinaryScalarSchema(schemaObject)) return {
2223
+ ...getScalar({
2224
+ item: schemaObject,
2225
+ name,
2226
+ context,
2227
+ formDataContext
2228
+ }),
2229
+ originalSchema: schemaObject,
2230
+ isRef: false
2231
+ };
2232
+ const resolvedImport = imports[0];
2233
+ let hasReadonlyProps = false;
2234
+ const refName = resolvedImport.name;
2235
+ if (!context.parents?.includes(refName)) hasReadonlyProps = getScalar({
2236
+ item: schemaObject,
2237
+ name: refName,
2238
+ context: {
2239
+ ...context,
2240
+ parents: [...context.parents ?? [], refName]
2241
+ }
2242
+ }).hasReadonlyProps;
2243
+ const isAnyOfNullable = schemaObject.anyOf?.some((anyOfItem) => !isReference(anyOfItem) && (anyOfItem.type === "null" || Array.isArray(anyOfItem.type) && anyOfItem.type.includes("null")));
2244
+ const schemaType = schemaObject.type;
2245
+ const nullable = Array.isArray(schemaType) && schemaType.includes("null") || schemaObject.nullable === true || isAnyOfNullable ? " | null" : "";
2246
+ return {
2247
+ value: resolvedImport.name + nullable,
2248
+ imports: [{
2249
+ name: resolvedImport.name,
2250
+ schemaName: resolvedImport.schemaName
2251
+ }],
2252
+ type: schemaObject.type ?? "object",
2253
+ schemas: [],
2254
+ isEnum: !!schemaObject.enum,
2255
+ originalSchema: schemaObject,
2256
+ hasReadonlyProps,
2257
+ isRef: true,
2258
+ dependencies: [resolvedImport.name]
2270
2259
  };
2271
2260
  }
2272
- if (isString(propertyNames.const)) return {
2273
- value: `'${escape(propertyNames.const)}'`,
2274
- imports: [],
2275
- dependencies: []
2261
+ return {
2262
+ ...getScalar({
2263
+ item: schema,
2264
+ name,
2265
+ context,
2266
+ formDataContext
2267
+ }),
2268
+ originalSchema: schema,
2269
+ isRef: false
2276
2270
  };
2277
2271
  }
2272
+ //#endregion
2273
+ //#region src/resolvers/object.ts
2278
2274
  /**
2279
- * Resolve a narrowed key type from OpenAPI 3.1 propertyNames.
2280
- * Supports inline enum/const and $ref string enums.
2275
+ * Wraps inline object type in a type alias.
2276
+ * E.g. `{ foo: string }` → value becomes `FooBody`, schema gets `export type FooBody = { foo: string };`
2281
2277
  */
2282
- function getPropertyNamesKeyType(item, context) {
2283
- const inlineKeyType = getPropertyNamesEnumKeyType(item);
2284
- if (inlineKeyType) return inlineKeyType;
2285
- const propertyNames = item.propertyNames;
2286
- if (!propertyNames || !isReference(propertyNames)) return;
2287
- const resolvedValue = resolveValue({
2288
- schema: propertyNames,
2289
- context
2290
- });
2291
- const resolvedConst = resolvedValue.originalSchema.const;
2292
- const isStringConst = resolvedValue.type === "string" && isString(resolvedConst);
2293
- if (!resolvedValue.isEnum && !isStringConst) return;
2278
+ function createTypeAliasIfNeeded({ resolvedValue, propName, context }) {
2279
+ if (!propName) return;
2280
+ if (resolvedValue.isEnum || resolvedValue.type !== "object") return;
2281
+ const aliasPattern = context.output.override.aliasCombinedTypes ? String.raw`{|&|\|` : "{";
2282
+ if (!new RegExp(aliasPattern).test(resolvedValue.value)) return;
2283
+ const { originalSchema } = resolvedValue;
2284
+ const doc = jsDoc(originalSchema);
2285
+ const isConstant = "const" in originalSchema;
2286
+ const constantIsString = "type" in originalSchema && (originalSchema.type === "string" || Array.isArray(originalSchema.type) && originalSchema.type.includes("string"));
2287
+ const model = isConstant ? `${doc}export const ${propName} = ${constantIsString ? `'${originalSchema.const}'` : originalSchema.const} as const;\n` : `${doc}export type ${propName} = ${resolvedValue.value};\n`;
2294
2288
  return {
2295
- value: resolvedValue.value,
2296
- imports: resolvedValue.imports,
2289
+ value: propName,
2290
+ imports: [{
2291
+ name: propName,
2292
+ isConstant
2293
+ }],
2294
+ schemas: [...resolvedValue.schemas, {
2295
+ name: propName,
2296
+ model,
2297
+ imports: resolvedValue.imports,
2298
+ dependencies: resolvedValue.dependencies
2299
+ }],
2300
+ isEnum: false,
2301
+ type: "object",
2302
+ isRef: resolvedValue.isRef,
2303
+ hasReadonlyProps: resolvedValue.hasReadonlyProps,
2297
2304
  dependencies: resolvedValue.dependencies
2298
2305
  };
2299
2306
  }
2300
- /**
2301
- * Generate index signature key type based on propertyNames enum or const
2302
- * Returns union type string like "'foo' | 'bar'", "'x'", or 'string' if neither
2303
- */
2304
- function getIndexSignatureKey(item) {
2305
- return getPropertyNamesEnumKeyType(item)?.value ?? "string";
2306
- }
2307
- function getPropertyNamesRecordType(item, valueType, context) {
2308
- const keyType = getPropertyNamesKeyType(item, context);
2309
- if (!keyType) return;
2310
- return {
2311
- ...keyType,
2312
- value: `Partial<Record<${keyType.value}, ${valueType}>>`
2307
+ function resolveObjectOriginal({ schema, propName, combined = false, context, formDataContext }) {
2308
+ const resolvedValue = resolveValue({
2309
+ schema,
2310
+ name: propName,
2311
+ context,
2312
+ formDataContext
2313
+ });
2314
+ const aliased = createTypeAliasIfNeeded({
2315
+ resolvedValue,
2316
+ propName,
2317
+ context
2318
+ });
2319
+ if (aliased) return {
2320
+ ...aliased,
2321
+ originalSchema: resolvedValue.originalSchema
2313
2322
  };
2323
+ if (propName && resolvedValue.isEnum && !combined && !resolvedValue.isRef) {
2324
+ const doc = jsDoc(resolvedValue.originalSchema);
2325
+ const enumValue = getEnum(resolvedValue.value, propName, getEnumNames(resolvedValue.originalSchema), context.output.override.enumGenerationType, getEnumDescriptions(resolvedValue.originalSchema), context.output.override.namingConvention.enum);
2326
+ return {
2327
+ value: propName,
2328
+ imports: [{ name: propName }],
2329
+ schemas: [...resolvedValue.schemas, {
2330
+ name: propName,
2331
+ model: doc + enumValue,
2332
+ imports: resolvedValue.imports,
2333
+ dependencies: resolvedValue.dependencies
2334
+ }],
2335
+ isEnum: false,
2336
+ type: "enum",
2337
+ originalSchema: resolvedValue.originalSchema,
2338
+ isRef: resolvedValue.isRef,
2339
+ hasReadonlyProps: resolvedValue.hasReadonlyProps,
2340
+ dependencies: [...resolvedValue.dependencies, propName]
2341
+ };
2342
+ }
2343
+ return resolvedValue;
2344
+ }
2345
+ const resolveObjectCacheMap = /* @__PURE__ */ new Map();
2346
+ function resolveObject({ schema, propName, combined = false, context, formDataContext }) {
2347
+ const hashKey = JSON.stringify({
2348
+ schema,
2349
+ propName,
2350
+ combined,
2351
+ projectName: context.projectName ?? context.output.target,
2352
+ formDataContext
2353
+ });
2354
+ if (resolveObjectCacheMap.has(hashKey)) return resolveObjectCacheMap.get(hashKey);
2355
+ const result = resolveObjectOriginal({
2356
+ schema,
2357
+ propName,
2358
+ combined,
2359
+ context,
2360
+ formDataContext
2361
+ });
2362
+ resolveObjectCacheMap.set(hashKey, result);
2363
+ return result;
2314
2364
  }
2365
+ //#endregion
2366
+ //#region src/getters/array.ts
2315
2367
  /**
2316
- * Return the output type from an object
2368
+ * Return the output type from an array
2317
2369
  *
2318
- * @param item item with type === "object"
2370
+ * @param item item with type === "array"
2319
2371
  */
2320
- function getObject({ item, name, context, nullable, formDataContext }) {
2321
- if (isReference(item)) {
2322
- const { name } = getRefInfo(item.$ref, context);
2372
+ function getArray({ schema, name, context, formDataContext }) {
2373
+ const schemaPrefixItems = schema.prefixItems;
2374
+ const schemaItems = schema.items;
2375
+ const schemaExample = schema.example;
2376
+ const schemaExamples = schema.examples;
2377
+ const itemSuffix = context.output.override.components.schemas.itemSuffix;
2378
+ if (schemaPrefixItems) {
2379
+ const resolvedObjects = schemaPrefixItems.map((item, index) => resolveObject({
2380
+ schema: item,
2381
+ propName: name ? name + itemSuffix + String(index) : void 0,
2382
+ context
2383
+ }));
2384
+ if (schemaItems) {
2385
+ const additional = resolveObject({
2386
+ schema: schemaItems,
2387
+ propName: name ? name + itemSuffix + "Additional" : void 0,
2388
+ context
2389
+ });
2390
+ resolvedObjects.push({
2391
+ ...additional,
2392
+ value: `...${additional.value}[]`
2393
+ });
2394
+ }
2323
2395
  return {
2324
- value: name + nullable,
2325
- imports: [{ name }],
2326
- schemas: [],
2396
+ type: "array",
2327
2397
  isEnum: false,
2328
- type: "object",
2329
- isRef: true,
2330
- hasReadonlyProps: item.readOnly ?? false,
2331
- dependencies: [name],
2332
- example: item.example,
2333
- examples: resolveExampleRefs(item.examples, context)
2398
+ isRef: false,
2399
+ value: `[${resolvedObjects.map((o) => o.value).join(", ")}]`,
2400
+ imports: resolvedObjects.flatMap((o) => o.imports),
2401
+ schemas: resolvedObjects.flatMap((o) => o.schemas),
2402
+ dependencies: resolvedObjects.flatMap((o) => o.dependencies),
2403
+ hasReadonlyProps: resolvedObjects.some((o) => o.hasReadonlyProps),
2404
+ example: schemaExample,
2405
+ examples: resolveExampleRefs(schemaExamples, context)
2334
2406
  };
2335
2407
  }
2336
- const schemaItem = item;
2337
- const itemAllOf = schemaItem.allOf;
2338
- const itemOneOf = schemaItem.oneOf;
2339
- const itemAnyOf = schemaItem.anyOf;
2340
- const itemType = schemaItem.type;
2341
- if (itemAllOf || itemOneOf || itemAnyOf) return combineSchemas({
2342
- schema: schemaItem,
2343
- name,
2344
- separator: itemAllOf ? "allOf" : itemOneOf ? "oneOf" : "anyOf",
2408
+ if (schemaItems) {
2409
+ const resolvedObject = resolveObject({
2410
+ schema: schemaItems,
2411
+ propName: name ? name + itemSuffix : void 0,
2412
+ context,
2413
+ formDataContext
2414
+ });
2415
+ return {
2416
+ value: `${schema.readOnly === true && !context.output.override.suppressReadonlyModifier ? "readonly " : ""}${resolvedObject.value.includes("|") || resolvedObject.value.includes("&") ? `(${resolvedObject.value})[]` : `${resolvedObject.value}[]`}`,
2417
+ imports: resolvedObject.imports,
2418
+ schemas: resolvedObject.schemas,
2419
+ dependencies: resolvedObject.dependencies,
2420
+ isEnum: false,
2421
+ type: "array",
2422
+ isRef: false,
2423
+ hasReadonlyProps: resolvedObject.hasReadonlyProps,
2424
+ example: schemaExample,
2425
+ examples: resolveExampleRefs(schemaExamples, context)
2426
+ };
2427
+ } else if (compareVersions(context.spec.openapi ?? "3.0.0", "3.1", ">=")) return {
2428
+ value: "unknown[]",
2429
+ imports: [],
2430
+ schemas: [],
2431
+ dependencies: [],
2432
+ isEnum: false,
2433
+ type: "array",
2434
+ isRef: false,
2435
+ hasReadonlyProps: false
2436
+ };
2437
+ else throw new Error(`All arrays must have an \`items\` key defined (name=${name}, schema=${JSON.stringify(schema)})`);
2438
+ }
2439
+ //#endregion
2440
+ //#region src/getters/res-req-types.ts
2441
+ const getSchemaType$1 = (s) => s.type;
2442
+ const getSchemaCombined = (s) => s.oneOf ?? s.anyOf ?? s.allOf;
2443
+ const getSchemaOneOf = (s) => s.oneOf;
2444
+ const getSchemaAnyOf = (s) => s.anyOf;
2445
+ const getSchemaItems = (s) => s.items;
2446
+ const getSchemaRequired = (s) => s.required;
2447
+ const getSchemaProperties = (s) => s.properties;
2448
+ const resolveSchemaRef = (schema, context) => resolveRef(schema, context);
2449
+ const resolveResponseOrRequestRef = (schema, context) => resolveRef(schema, context);
2450
+ const formDataContentTypes = new Set(["multipart/form-data"]);
2451
+ const formUrlEncodedContentTypes = new Set(["application/x-www-form-urlencoded"]);
2452
+ function getResReqContentTypes({ mediaType, propName, context, isFormData, contentType }) {
2453
+ if (!mediaType.schema) return;
2454
+ const isFormUrlEncoded = formUrlEncodedContentTypes.has(contentType);
2455
+ const formDataContext = isFormData ? {
2456
+ atPart: false,
2457
+ encoding: mediaType.encoding ?? {}
2458
+ } : isFormUrlEncoded ? {
2459
+ atPart: false,
2460
+ encoding: mediaType.encoding ?? {},
2461
+ urlEncoded: true
2462
+ } : void 0;
2463
+ const resolvedObject = resolveObject({
2464
+ schema: mediaType.schema,
2465
+ propName,
2345
2466
  context,
2346
- nullable,
2347
2467
  formDataContext
2348
2468
  });
2349
- if (Array.isArray(itemType)) {
2350
- const typeArray = itemType;
2351
- const baseItem = schemaItem;
2352
- return combineSchemas({
2353
- schema: { anyOf: typeArray.map((type) => ({
2354
- ...baseItem,
2355
- type
2356
- })) },
2357
- name,
2358
- separator: "anyOf",
2359
- context,
2360
- nullable
2361
- });
2362
- }
2363
- const itemProperties = schemaItem.properties;
2364
- if (itemProperties && Object.entries(itemProperties).length > 0) {
2365
- const entries = Object.entries(itemProperties);
2366
- if (context.output.propertySortOrder === PropertySortOrder.ALPHABETICAL) entries.sort((a, b) => {
2367
- return a[0].localeCompare(b[0], "en", { numeric: true });
2368
- });
2369
- const acc = {
2370
- imports: [],
2371
- schemas: [],
2372
- value: "",
2373
- isEnum: false,
2374
- type: "object",
2375
- isRef: false,
2376
- hasReadonlyProps: false,
2377
- useTypeAlias: false,
2378
- dependencies: [],
2379
- example: schemaItem.example,
2380
- examples: resolveExampleRefs(schemaItem.examples, context)
2381
- };
2382
- const itemRequired = schemaItem.required;
2383
- for (const [index, [key, schema]] of entries.entries()) {
2384
- const isRequired = (Array.isArray(itemRequired) ? itemRequired : []).includes(key);
2385
- let propName = "";
2386
- if (name) {
2387
- const isKeyStartWithUnderscore = key.startsWith("_");
2388
- propName += pascal(`${isKeyStartWithUnderscore ? "_" : ""}${name}_${key}`);
2389
- }
2390
- const allSpecSchemas = context.spec.components?.schemas ?? {};
2391
- if (Object.keys(allSpecSchemas).some((schemaName) => pascal(schemaName) === propName)) propName = propName + "Property";
2392
- const propertyFormDataContext = formDataContext && !formDataContext.atPart ? {
2393
- atPart: true,
2394
- partContentType: formDataContext.encoding[key]?.contentType,
2395
- urlEncoded: formDataContext.urlEncoded
2396
- } : void 0;
2397
- const resolvedValue = resolveObject({
2398
- schema,
2399
- propName,
2400
- context,
2401
- formDataContext: propertyFormDataContext
2402
- });
2403
- const isReadOnly = Boolean(schemaItem.readOnly) || Boolean(schema.readOnly);
2404
- if (!index) acc.value += "{";
2405
- const doc = jsDoc(schema, true, context);
2406
- const propertyDoc = doc ? `${doc.trimEnd().split("\n").map((line) => ` ${line}`).join("\n")}\n` : "";
2407
- if (isReadOnly || resolvedValue.hasReadonlyProps) acc.hasReadonlyProps = true;
2408
- const constValue = "const" in schema ? schema.const : void 0;
2409
- const hasConst = constValue !== void 0;
2410
- let constLiteral;
2411
- if (!hasConst) constLiteral = void 0;
2412
- else if (isString(constValue)) constLiteral = `'${escape(constValue)}'`;
2413
- else constLiteral = JSON.stringify(constValue);
2414
- const needsValueImport = hasConst && (resolvedValue.isEnum || resolvedValue.type === "enum");
2415
- const usedResolvedValue = !hasConst || needsValueImport;
2416
- const aliasedImports = needsValueImport ? resolvedValue.imports.map((imp) => ({
2417
- ...imp,
2418
- isConstant: true
2419
- })) : hasConst ? [] : getAliasedImports({
2469
+ if (!isFormData && isBinaryContentType(contentType)) return {
2470
+ ...resolvedObject,
2471
+ value: "Blob"
2472
+ };
2473
+ return resolvedObject;
2474
+ }
2475
+ function getResReqTypes(responsesOrRequests, name, context, defaultType = "unknown", uniqueKey = (item) => item.value) {
2476
+ return uniqueBy(responsesOrRequests.filter(([, res]) => Boolean(res)).map(([key, res]) => {
2477
+ if (isReference(res)) {
2478
+ const { schema: bodySchema, imports: [{ name, schemaName }] } = resolveResponseOrRequestRef(res, context);
2479
+ const firstEntry = Object.entries(bodySchema.content ?? {}).at(0);
2480
+ if (!firstEntry) return [{
2481
+ value: name,
2482
+ imports: [{
2483
+ name,
2484
+ schemaName
2485
+ }],
2486
+ schemas: [],
2487
+ type: "unknown",
2488
+ isEnum: false,
2489
+ isRef: true,
2490
+ hasReadonlyProps: false,
2491
+ dependencies: [name],
2492
+ originalSchema: void 0,
2493
+ example: void 0,
2494
+ examples: void 0,
2495
+ key,
2496
+ contentType: ""
2497
+ }];
2498
+ const [contentType, mediaType] = firstEntry;
2499
+ const isFormData = formDataContentTypes.has(contentType);
2500
+ const isFormUrlEncoded = formUrlEncodedContentTypes.has(contentType);
2501
+ if (!isFormData && !isFormUrlEncoded || !mediaType.schema) return [{
2502
+ value: name,
2503
+ imports: [{
2504
+ name,
2505
+ schemaName
2506
+ }],
2507
+ schemas: [],
2508
+ type: "unknown",
2509
+ isEnum: false,
2510
+ isRef: true,
2511
+ hasReadonlyProps: false,
2512
+ dependencies: [name],
2513
+ originalSchema: mediaType.schema,
2514
+ example: mediaType.example,
2515
+ examples: resolveExampleRefs(mediaType.examples, context),
2516
+ key,
2517
+ contentType
2518
+ }];
2519
+ const formData = isFormData ? getSchemaFormDataAndUrlEncoded({
2420
2520
  name,
2521
+ schemaObject: mediaType.schema,
2421
2522
  context,
2422
- resolvedValue
2423
- });
2424
- if (aliasedImports.length > 0) acc.imports.push(...aliasedImports);
2425
- const alias = getImportAliasForRefOrValue({
2523
+ isRequestBodyOptional: bodySchema.required !== true,
2524
+ isRef: true,
2525
+ encoding: mediaType.encoding
2526
+ }) : void 0;
2527
+ const formUrlEncoded = isFormUrlEncoded ? getSchemaFormDataAndUrlEncoded({
2528
+ name,
2529
+ schemaObject: mediaType.schema,
2426
2530
  context,
2427
- resolvedValue,
2428
- imports: aliasedImports
2531
+ isRequestBodyOptional: bodySchema.required !== true,
2532
+ isUrlEncoded: true,
2533
+ isRef: true,
2534
+ encoding: mediaType.encoding
2535
+ }) : void 0;
2536
+ const additionalImports = getFormDataAdditionalImports({
2537
+ schemaObject: mediaType.schema,
2538
+ context
2429
2539
  });
2430
- const propValue = needsValueImport ? alias : constLiteral ?? alias;
2431
- const finalPropValue = isRequired ? propValue : context.output.override.useNullForOptional === true ? `${propValue} | null` : propValue;
2432
- acc.value += `\n${propertyDoc}${isReadOnly && !context.output.override.suppressReadonlyModifier ? " readonly " : " "}${getKey(key)}${isRequired ? "" : "?"}: ${finalPropValue};`;
2433
- if (usedResolvedValue) {
2434
- acc.schemas.push(...resolvedValue.schemas);
2435
- acc.dependencies.push(...resolvedValue.dependencies);
2436
- }
2437
- if (entries.length - 1 === index) {
2438
- const additionalProps = schemaItem.additionalProperties;
2439
- if (additionalProps) if (additionalProps === true) {
2440
- const recordType = getPropertyNamesRecordType(schemaItem, "unknown", context);
2441
- if (recordType) {
2442
- acc.value += "\n}";
2443
- acc.value += ` & ${recordType.value}`;
2444
- acc.useTypeAlias = true;
2445
- acc.imports.push(...recordType.imports);
2446
- acc.dependencies.push(...recordType.dependencies);
2447
- } else {
2448
- const keyType = getIndexSignatureKey(schemaItem);
2449
- acc.value += `\n [key: ${keyType}]: unknown;\n }`;
2450
- }
2451
- } else {
2452
- const resolvedValue = resolveValue({
2453
- schema: additionalProps,
2454
- name,
2455
- context
2456
- });
2457
- const recordType = getPropertyNamesRecordType(schemaItem, resolvedValue.value, context);
2458
- if (recordType) {
2459
- acc.value += "\n}";
2460
- acc.value += ` & ${recordType.value}`;
2461
- acc.useTypeAlias = true;
2462
- acc.imports.push(...recordType.imports);
2463
- acc.dependencies.push(...recordType.dependencies);
2464
- } else {
2465
- const keyType = getIndexSignatureKey(schemaItem);
2466
- acc.value += `\n [key: ${keyType}]: ${resolvedValue.value};\n}`;
2540
+ return [{
2541
+ value: name,
2542
+ imports: [{
2543
+ name,
2544
+ schemaName
2545
+ }, ...additionalImports],
2546
+ schemas: [],
2547
+ type: "unknown",
2548
+ isEnum: false,
2549
+ hasReadonlyProps: false,
2550
+ dependencies: [name],
2551
+ formData,
2552
+ formUrlEncoded,
2553
+ isRef: true,
2554
+ originalSchema: mediaType.schema,
2555
+ example: mediaType.example,
2556
+ examples: resolveExampleRefs(mediaType.examples, context),
2557
+ key,
2558
+ contentType
2559
+ }];
2560
+ }
2561
+ if (res.content) return Object.entries(res.content).map(([contentType, mediaType], index, arr) => {
2562
+ let propName = key ? pascal(name) + pascal(key) : void 0;
2563
+ if (propName && arr.length > 1) propName = propName + pascal(getNumberWord(index + 1));
2564
+ const isFormData = formDataContentTypes.has(contentType);
2565
+ const isFormUrlEncoded = formUrlEncodedContentTypes.has(contentType);
2566
+ let effectivePropName = propName;
2567
+ if (mediaType.schema && isReference(mediaType.schema)) {
2568
+ const { imports } = resolveSchemaRef(mediaType.schema, context);
2569
+ if (imports[0]?.name) effectivePropName = imports[0].name;
2570
+ } else if ((isFormData || isFormUrlEncoded) && mediaType.schema) {
2571
+ const combinedRefs = getSchemaOneOf(mediaType.schema) ?? getSchemaAnyOf(mediaType.schema);
2572
+ if (combinedRefs) {
2573
+ const names = [];
2574
+ for (const ref of combinedRefs) {
2575
+ if (!isReference(ref)) continue;
2576
+ const refName = resolveSchemaRef(ref, context).imports[0]?.name;
2577
+ if (refName) names.push(refName);
2467
2578
  }
2468
- acc.imports.push(...resolvedValue.imports);
2469
- acc.schemas.push(...resolvedValue.schemas);
2470
- acc.dependencies.push(...resolvedValue.dependencies);
2579
+ if (names.length > 0) effectivePropName = names.join("");
2471
2580
  }
2472
- else acc.value += "\n}";
2473
- acc.value += nullable;
2474
2581
  }
2475
- }
2476
- return acc;
2477
- }
2478
- const outerAdditionalProps = schemaItem.additionalProperties;
2479
- const readOnlyFlag = schemaItem.readOnly;
2480
- if (outerAdditionalProps) {
2481
- if (outerAdditionalProps === true) {
2482
- const recordType = getPropertyNamesRecordType(schemaItem, "unknown", context);
2483
- if (recordType) return {
2484
- value: recordType.value + nullable,
2485
- imports: recordType.imports,
2486
- schemas: [],
2487
- isEnum: false,
2488
- type: "object",
2489
- isRef: false,
2490
- hasReadonlyProps: readOnlyFlag ?? false,
2491
- useTypeAlias: true,
2492
- dependencies: recordType.dependencies
2582
+ const resolvedValue = getResReqContentTypes({
2583
+ mediaType,
2584
+ propName: effectivePropName,
2585
+ context,
2586
+ isFormData,
2587
+ contentType
2588
+ });
2589
+ if (!resolvedValue) {
2590
+ if (isBinaryContentType(contentType)) return {
2591
+ value: "Blob",
2592
+ imports: [],
2593
+ schemas: [],
2594
+ type: "Blob",
2595
+ isEnum: false,
2596
+ key,
2597
+ isRef: false,
2598
+ hasReadonlyProps: false,
2599
+ contentType
2600
+ };
2601
+ return;
2602
+ }
2603
+ if (!isFormData && !isFormUrlEncoded || !effectivePropName || !mediaType.schema) return {
2604
+ ...resolvedValue,
2605
+ imports: resolvedValue.imports,
2606
+ dependencies: resolvedValue.dependencies,
2607
+ contentType,
2608
+ example: mediaType.example,
2609
+ examples: resolveExampleRefs(mediaType.examples, context)
2493
2610
  };
2611
+ const formData = isFormData ? getSchemaFormDataAndUrlEncoded({
2612
+ name: effectivePropName,
2613
+ schemaObject: mediaType.schema,
2614
+ context,
2615
+ isRequestBodyOptional: res.required !== true,
2616
+ isRef: true,
2617
+ encoding: mediaType.encoding
2618
+ }) : void 0;
2619
+ const formUrlEncoded = isFormUrlEncoded ? getSchemaFormDataAndUrlEncoded({
2620
+ name: effectivePropName,
2621
+ schemaObject: mediaType.schema,
2622
+ context,
2623
+ isUrlEncoded: true,
2624
+ isRequestBodyOptional: res.required !== true,
2625
+ isRef: true,
2626
+ encoding: mediaType.encoding
2627
+ }) : void 0;
2628
+ const additionalImports = getFormDataAdditionalImports({
2629
+ schemaObject: mediaType.schema,
2630
+ context
2631
+ });
2494
2632
  return {
2495
- value: `{ [key: ${getIndexSignatureKey(schemaItem)}]: unknown }` + nullable,
2496
- imports: [],
2497
- schemas: [],
2498
- isEnum: false,
2499
- type: "object",
2500
- isRef: false,
2501
- hasReadonlyProps: readOnlyFlag ?? false,
2502
- useTypeAlias: false,
2503
- dependencies: []
2633
+ ...resolvedValue,
2634
+ imports: [...resolvedValue.imports, ...additionalImports],
2635
+ formData,
2636
+ formUrlEncoded,
2637
+ contentType,
2638
+ example: mediaType.example,
2639
+ examples: resolveExampleRefs(mediaType.examples, context)
2504
2640
  };
2505
- }
2506
- const resolvedValue = resolveValue({
2507
- schema: outerAdditionalProps,
2508
- name,
2509
- context
2510
- });
2511
- const recordType = getPropertyNamesRecordType(schemaItem, resolvedValue.value, context);
2512
- if (recordType) return {
2513
- value: recordType.value + nullable,
2514
- imports: [...recordType.imports, ...resolvedValue.imports],
2515
- schemas: resolvedValue.schemas,
2516
- isEnum: false,
2517
- type: "object",
2518
- isRef: false,
2519
- hasReadonlyProps: resolvedValue.hasReadonlyProps,
2520
- useTypeAlias: true,
2521
- dependencies: [...recordType.dependencies, ...resolvedValue.dependencies]
2522
- };
2523
- return {
2524
- value: `{[key: ${getIndexSignatureKey(schemaItem)}]: ${resolvedValue.value}}` + nullable,
2525
- imports: resolvedValue.imports,
2526
- schemas: resolvedValue.schemas,
2527
- isEnum: false,
2528
- type: "object",
2529
- isRef: false,
2530
- hasReadonlyProps: resolvedValue.hasReadonlyProps,
2531
- useTypeAlias: false,
2532
- dependencies: resolvedValue.dependencies
2533
- };
2534
- }
2535
- const constValue = schemaItem.const;
2536
- if (constValue !== void 0) {
2537
- let type;
2538
- if (Array.isArray(constValue)) type = "array";
2539
- else if (constValue === null) type = "null";
2540
- else if (typeof constValue === "string") type = "string";
2541
- else if (typeof constValue === "number") type = "number";
2542
- else if (typeof constValue === "boolean") type = "boolean";
2543
- else type = "object";
2544
- return {
2545
- value: typeof constValue === "string" ? `'${escape(constValue)}'` : JSON.stringify(constValue),
2641
+ }).filter(Boolean).map((x) => ({
2642
+ ...x,
2643
+ key
2644
+ }));
2645
+ const swaggerSchema = "schema" in res ? res.schema : void 0;
2646
+ if (swaggerSchema) return [{
2647
+ ...resolveObject({
2648
+ schema: swaggerSchema,
2649
+ propName: key ? pascal(name) + pascal(key) : void 0,
2650
+ context
2651
+ }),
2652
+ contentType: "application/json",
2653
+ key
2654
+ }];
2655
+ return [{
2656
+ value: defaultType,
2546
2657
  imports: [],
2547
2658
  schemas: [],
2659
+ type: defaultType,
2548
2660
  isEnum: false,
2549
- type,
2661
+ dependencies: [],
2662
+ key,
2550
2663
  isRef: false,
2551
- hasReadonlyProps: readOnlyFlag ?? false,
2552
- dependencies: []
2553
- };
2554
- }
2555
- const keyType = itemType === "object" ? getIndexSignatureKey(schemaItem) : "string";
2556
- const recordType = getPropertyNamesRecordType(schemaItem, "unknown", context);
2557
- if (itemType === "object" && recordType) return {
2558
- value: recordType.value + nullable,
2559
- imports: recordType.imports,
2560
- schemas: [],
2561
- isEnum: false,
2562
- type: "object",
2563
- isRef: false,
2564
- hasReadonlyProps: readOnlyFlag ?? false,
2565
- useTypeAlias: true,
2566
- dependencies: recordType.dependencies
2567
- };
2568
- return {
2569
- value: (itemType === "object" ? `{ [key: ${keyType}]: unknown }` : "unknown") + nullable,
2570
- imports: [],
2571
- schemas: [],
2572
- isEnum: false,
2573
- type: "object",
2574
- isRef: false,
2575
- hasReadonlyProps: readOnlyFlag ?? false,
2576
- useTypeAlias: false,
2577
- dependencies: []
2578
- };
2664
+ hasReadonlyProps: false,
2665
+ contentType: "application/json"
2666
+ }];
2667
+ }).flat(), uniqueKey);
2579
2668
  }
2580
- //#endregion
2581
- //#region src/getters/scalar.ts
2582
2669
  /**
2583
- * Return the typescript equivalent of open-api data type
2584
- *
2585
- * @param item
2586
- * @ref https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.1.md#data-types
2670
+ * Determine the responseType option based on success content types only.
2671
+ * This avoids error-response content types influencing the responseType.
2587
2672
  */
2588
- function getScalar({ item, name, context, formDataContext }) {
2589
- const schemaEnum = item.enum;
2590
- const schemaType = item.type;
2591
- const schemaReadOnly = item.readOnly;
2592
- const schemaExample = item.example;
2593
- const schemaExamples = item.examples;
2594
- const schemaConst = item.const;
2595
- const schemaFormat = item.format;
2596
- const schemaNullable = item.nullable;
2597
- const schemaContentMediaType = item.contentMediaType;
2598
- const schemaContentEncoding = item.contentEncoding;
2599
- const nullable = isArray(schemaType) && schemaType.includes("null") || schemaNullable === true ? " | null" : "";
2600
- const enumItems = schemaEnum?.filter((enumItem) => enumItem !== null);
2601
- let itemType = schemaType;
2602
- if (!itemType && item.items) {
2603
- item.type = "array";
2604
- itemType = "array";
2605
- }
2606
- if (isArray(schemaType) && schemaType.includes("null")) {
2607
- const typesWithoutNull = schemaType.filter((x) => x !== "null");
2608
- itemType = typesWithoutNull.length === 1 ? typesWithoutNull[0] : typesWithoutNull;
2609
- }
2610
- switch (itemType) {
2611
- case "number":
2612
- case "integer": {
2613
- let value = context.output.override.useBigInt && (schemaFormat === "int64" || schemaFormat === "uint64") ? "bigint" : "number";
2614
- let isEnum = false;
2615
- if (enumItems) {
2616
- value = enumItems.map((enumItem) => `${enumItem}`).join(" | ");
2617
- isEnum = true;
2618
- }
2619
- value += nullable;
2620
- if (schemaConst !== void 0) value = schemaConst;
2621
- return {
2622
- value,
2623
- isEnum,
2624
- type: "number",
2625
- schemas: [],
2626
- imports: [],
2627
- isRef: false,
2628
- hasReadonlyProps: schemaReadOnly ?? false,
2629
- dependencies: [],
2630
- example: schemaExample,
2631
- examples: resolveExampleRefs(schemaExamples, context)
2632
- };
2633
- }
2634
- case "boolean": {
2635
- let value = "boolean";
2636
- if (enumItems && !(enumItems.includes(true) && enumItems.includes(false))) value = enumItems.map((enumItem) => `${enumItem}`).join(" | ");
2637
- value += nullable;
2638
- if (schemaConst !== void 0) value = schemaConst;
2639
- return {
2640
- value,
2641
- type: "boolean",
2642
- isEnum: false,
2643
- schemas: [],
2644
- imports: [],
2645
- isRef: false,
2646
- hasReadonlyProps: schemaReadOnly ?? false,
2647
- dependencies: [],
2648
- example: schemaExample,
2649
- examples: resolveExampleRefs(schemaExamples, context)
2650
- };
2651
- }
2652
- case "array": {
2653
- const { value, ...rest } = getArray({
2654
- schema: item,
2655
- name,
2656
- context,
2657
- formDataContext
2658
- });
2659
- return {
2660
- value: value + nullable,
2661
- ...rest,
2662
- dependencies: rest.dependencies
2663
- };
2664
- }
2665
- case "string": {
2666
- let value = "string";
2667
- let isEnum = false;
2668
- if (enumItems) {
2669
- value = enumItems.map((enumItem) => isString(enumItem) ? `'${escape(enumItem)}'` : `${enumItem}`).filter(Boolean).join(` | `);
2670
- isEnum = true;
2671
- }
2672
- if (!formDataContext?.urlEncoded) {
2673
- if (schemaFormat === "binary") value = "Blob";
2674
- else if (formDataContext?.atPart) {
2675
- const fileType = getFormDataFieldFileType(item, formDataContext.partContentType);
2676
- if (fileType) value = fileType === "binary" ? "Blob" : "Blob | string";
2677
- } else if (schemaContentMediaType === "application/octet-stream" && !schemaContentEncoding) value = "Blob";
2673
+ function getSuccessResponseType(response) {
2674
+ const successContentTypes = response.types.success.map((t) => t.contentType).filter(Boolean);
2675
+ if (response.isBlob) return "blob";
2676
+ const hasJsonResponse = successContentTypes.some((contentType) => contentType.includes("json") || contentType.includes("+json"));
2677
+ const hasTextResponse = successContentTypes.some((contentType) => contentType.startsWith("text/") || contentType.includes("xml"));
2678
+ if (!hasJsonResponse && hasTextResponse) return "text";
2679
+ }
2680
+ /**
2681
+ * Determine the response type category for a given content type.
2682
+ * Used to set the correct responseType option in HTTP clients.
2683
+ *
2684
+ * @param contentType - The MIME content type (e.g., 'application/json', 'text/plain')
2685
+ * @returns The response type category to use for parsing
2686
+ */
2687
+ function getResponseTypeCategory(contentType) {
2688
+ if (isBinaryContentType(contentType)) return "blob";
2689
+ if (contentType === "application/json" || contentType.includes("+json") || contentType.includes("-json")) return "json";
2690
+ return "text";
2691
+ }
2692
+ /**
2693
+ * Get the default content type from a list of content types.
2694
+ * Priority: application/json > any JSON-like type > first in list
2695
+ *
2696
+ * @param contentTypes - Array of content types from OpenAPI spec
2697
+ * @returns The default content type to use
2698
+ */
2699
+ function getDefaultContentType(contentTypes) {
2700
+ if (contentTypes.length === 0) return "application/json";
2701
+ if (contentTypes.includes("application/json")) return "application/json";
2702
+ const jsonType = contentTypes.find((ct) => ct.includes("+json") || ct.includes("-json"));
2703
+ if (jsonType) return jsonType;
2704
+ return contentTypes[0];
2705
+ }
2706
+ function getFormDataAdditionalImports({ schemaObject, context }) {
2707
+ const { schema } = resolveSchemaRef(schemaObject, context);
2708
+ if (schema.type !== "object") return [];
2709
+ const combinedSchemas = getSchemaOneOf(schema) ?? getSchemaAnyOf(schema);
2710
+ if (!combinedSchemas) return [];
2711
+ return combinedSchemas.map((subSchema) => resolveSchemaRef(subSchema, context).imports[0]).filter(Boolean);
2712
+ }
2713
+ function getSchemaFormDataAndUrlEncoded({ name, schemaObject, context, isRequestBodyOptional, isUrlEncoded, isRef, encoding }) {
2714
+ const { schema, imports } = resolveSchemaRef(schemaObject, context);
2715
+ const propName = camel(!isRef && isReference(schemaObject) ? imports[0].name : name);
2716
+ const variableName = isUrlEncoded ? "formUrlEncoded" : "formData";
2717
+ let form = isUrlEncoded ? `const ${variableName} = new URLSearchParams();\n` : `const ${variableName} = new FormData();\n`;
2718
+ const combinedSchemas = getSchemaCombined(schema);
2719
+ if (schema.type === "object" || schema.type === void 0 && combinedSchemas) {
2720
+ if (combinedSchemas) if (!!getSchemaOneOf(schema) || !!getSchemaAnyOf(schema)) {
2721
+ const directProperties = getSchemaProperties(schema);
2722
+ const directKeys = directProperties ? Object.entries(directProperties).filter(([, value]) => !resolveSchemaRef(value, context).schema.readOnly).map(([key]) => key) : [];
2723
+ const skipLine = directKeys.length > 0 ? ` if ([${directKeys.map((k) => JSON.stringify(k)).join(", ")}].includes(key)) return;\n` : "";
2724
+ form += `Object.entries(${propName} ?? {}).forEach(([key, value]) => {\n`;
2725
+ form += skipLine;
2726
+ form += ` if (value !== undefined && value !== null) {\n`;
2727
+ if (isUrlEncoded) {
2728
+ form += ` if (Array.isArray(value)) {\n`;
2729
+ form += ` value.forEach(v => {\n`;
2730
+ form += ` ${variableName}.append(key, typeof v === 'object' ? JSON.stringify(v) : String(v));\n`;
2731
+ form += ` });\n`;
2732
+ form += ` } else if (typeof value === 'object') {\n`;
2733
+ form += ` ${variableName}.append(key, JSON.stringify(value));\n`;
2734
+ form += ` } else {\n`;
2735
+ form += ` ${variableName}.append(key, String(value));\n`;
2736
+ form += ` }\n`;
2737
+ } else {
2738
+ form += ` if ((typeof File !== 'undefined' && value instanceof File) || value instanceof Blob) {\n`;
2739
+ form += ` ${variableName}.append(key, value);\n`;
2740
+ form += ` } else if (typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) {\n`;
2741
+ form += ` ${variableName}.append(key, new Blob([Uint8Array.from(value)]));\n`;
2742
+ form += ` } else if (Array.isArray(value)) {\n`;
2743
+ form += ` value.forEach(v => {\n`;
2744
+ form += ` if ((typeof File !== 'undefined' && v instanceof File) || v instanceof Blob) {\n`;
2745
+ form += ` ${variableName}.append(key, v);\n`;
2746
+ form += ` } else if (typeof Buffer !== 'undefined' && Buffer.isBuffer(v)) {\n`;
2747
+ form += ` ${variableName}.append(key, new Blob([Uint8Array.from(v)]));\n`;
2748
+ form += ` } else {\n`;
2749
+ form += ` ${variableName}.append(key, typeof v === 'object' ? JSON.stringify(v) : String(v));\n`;
2750
+ form += ` }\n`;
2751
+ form += ` });\n`;
2752
+ form += ` } else if (typeof value === 'object') {\n`;
2753
+ form += ` ${variableName}.append(key, JSON.stringify(value));\n`;
2754
+ form += ` } else {\n`;
2755
+ form += ` ${variableName}.append(key, String(value));\n`;
2756
+ form += ` }\n`;
2678
2757
  }
2679
- if (context.output.override.useDates && (schemaFormat === "date" || schemaFormat === "date-time")) value = "Date";
2680
- value += nullable;
2681
- if (schemaConst) value = `'${schemaConst}'`;
2682
- return {
2683
- value,
2684
- isEnum,
2685
- type: "string",
2686
- imports: [],
2687
- schemas: [],
2688
- isRef: false,
2689
- hasReadonlyProps: schemaReadOnly ?? false,
2690
- dependencies: [],
2691
- example: schemaExample,
2692
- examples: resolveExampleRefs(schemaExamples, context)
2693
- };
2758
+ form += ` }\n`;
2759
+ form += `});\n`;
2760
+ } else {
2761
+ const combinedSchemasFormData = combinedSchemas.map((subSchema) => {
2762
+ const { schema: combinedSchema } = resolveSchemaRef(subSchema, context);
2763
+ return resolveSchemaPropertiesToFormData({
2764
+ schema: combinedSchema,
2765
+ variableName,
2766
+ propName,
2767
+ context,
2768
+ isRequestBodyOptional,
2769
+ encoding
2770
+ });
2771
+ }).filter(Boolean).join("\n");
2772
+ form += combinedSchemasFormData;
2694
2773
  }
2695
- case "null": return {
2696
- value: "null",
2697
- isEnum: false,
2698
- type: "null",
2699
- imports: [],
2700
- schemas: [],
2701
- isRef: false,
2702
- hasReadonlyProps: schemaReadOnly ?? false,
2703
- dependencies: []
2704
- };
2705
- default: {
2706
- if (isArray(itemType)) return combineSchemas({
2707
- schema: { anyOf: itemType.map((type) => Object.assign({}, item, { type })) },
2708
- name,
2709
- separator: "anyOf",
2710
- context,
2711
- nullable
2712
- });
2713
- if (enumItems) return {
2714
- value: enumItems.map((enumItem) => isString(enumItem) ? `'${escape(enumItem)}'` : String(enumItem)).filter(Boolean).join(` | `) + nullable,
2715
- isEnum: true,
2716
- type: "string",
2717
- imports: [],
2718
- schemas: [],
2719
- isRef: false,
2720
- hasReadonlyProps: schemaReadOnly ?? false,
2721
- dependencies: [],
2722
- example: schemaExample,
2723
- examples: resolveExampleRefs(schemaExamples, context)
2724
- };
2725
- const hasCombiners = item.allOf ?? item.anyOf ?? item.oneOf;
2726
- const { value, ...rest } = getObject({
2727
- item,
2728
- name,
2774
+ if (schema.properties) {
2775
+ const formDataValues = resolveSchemaPropertiesToFormData({
2776
+ schema,
2777
+ variableName,
2778
+ propName,
2729
2779
  context,
2730
- nullable,
2731
- formDataContext: formDataContext?.atPart === false || formDataContext?.atPart && hasCombiners ? formDataContext : void 0
2780
+ isRequestBodyOptional,
2781
+ encoding
2732
2782
  });
2733
- return {
2734
- value,
2735
- ...rest
2736
- };
2783
+ form += formDataValues;
2737
2784
  }
2785
+ return form;
2738
2786
  }
2739
- }
2740
- //#endregion
2741
- //#region src/getters/combine.ts
2742
- const mergeableAllOfKeys = new Set([
2743
- "type",
2744
- "properties",
2745
- "required"
2746
- ]);
2747
- function isMergeableAllOfObject(schema) {
2748
- if (isNullish$1(schema.properties)) return false;
2749
- if (schema.allOf || schema.anyOf || schema.oneOf) return false;
2750
- if (!isNullish$1(schema.type) && schema.type !== "object") return false;
2751
- return Object.keys(schema).every((key) => mergeableAllOfKeys.has(key));
2752
- }
2753
- function normalizeAllOfSchema(schema) {
2754
- const schemaAllOf = schema.allOf;
2755
- if (!schemaAllOf) return schema;
2756
- let didMerge = false;
2757
- const schemaProperties = schema.properties;
2758
- const schemaRequired = schema.required;
2759
- const mergedProperties = schemaProperties ? { ...schemaProperties } : {};
2760
- const mergedRequired = new Set(schemaRequired);
2761
- const remainingAllOf = [];
2762
- for (const subSchema of schemaAllOf) {
2763
- if (isSchema(subSchema) && isMergeableAllOfObject(subSchema)) {
2764
- didMerge = true;
2765
- if (subSchema.properties) Object.assign(mergedProperties, subSchema.properties);
2766
- const subRequired = subSchema.required;
2767
- if (subRequired) for (const prop of subRequired) mergedRequired.add(prop);
2768
- continue;
2787
+ if (schema.type === "array") {
2788
+ let valueStr = "value";
2789
+ const schemaItems = getSchemaItems(schema);
2790
+ if (schemaItems) {
2791
+ const { schema: itemSchema } = resolveSchemaRef(schemaItems, context);
2792
+ if (itemSchema.type === "object" || itemSchema.type === "array") valueStr = "JSON.stringify(value)";
2793
+ else if (itemSchema.type === "number" || itemSchema.type === "integer" || itemSchema.type === "boolean") valueStr = "value.toString()";
2769
2794
  }
2770
- remainingAllOf.push(subSchema);
2795
+ return `${form}${propName}.forEach(value => ${variableName}.append('data', ${valueStr}))\n`;
2771
2796
  }
2772
- if (!didMerge || remainingAllOf.length === 0) return schema;
2773
- return {
2774
- ...schema,
2775
- ...Object.keys(mergedProperties).length > 0 && { properties: mergedProperties },
2776
- ...mergedRequired.size > 0 && { required: [...mergedRequired] },
2777
- ...remainingAllOf.length > 0 && { allOf: remainingAllOf }
2778
- };
2797
+ if (schema.type === "number" || schema.type === "integer" || schema.type === "boolean") return `${form}${variableName}.append('data', ${propName}.toString())\n`;
2798
+ return `${form}${variableName}.append('data', ${propName})\n`;
2779
2799
  }
2780
- function combineValues({ resolvedData, resolvedValue, separator, context, parentSchema }) {
2781
- if (resolvedData.isEnum.every(Boolean)) return `${resolvedData.values.join(` | `)}${resolvedValue ? ` | ${resolvedValue.value}` : ""}`;
2782
- if (separator === "allOf") {
2783
- let resolvedDataValue = resolvedData.values.map((v) => v.includes(" | ") ? `(${v})` : v).join(` & `);
2784
- if (resolvedData.originalSchema.length > 0 && resolvedValue) {
2785
- const discriminatedPropertySchemas = resolvedData.originalSchema.filter((s) => {
2786
- const disc = s?.discriminator;
2787
- return disc && resolvedValue.value.includes(` ${disc.propertyName}:`);
2788
- });
2789
- if (discriminatedPropertySchemas.length > 0) resolvedDataValue = `Omit<${resolvedDataValue}, '${discriminatedPropertySchemas.map((s) => s.discriminator?.propertyName).join("' | '")}'>`;
2800
+ function resolveSchemaPropertiesToFormData({ schema, variableName, propName, context, isRequestBodyOptional, keyPrefix = "", depth = 0, encoding }) {
2801
+ let formDataValues = "";
2802
+ const isUrlEncoded = variableName === "formUrlEncoded";
2803
+ const schemaProps = getSchemaProperties(schema) ?? {};
2804
+ for (const [key, value] of Object.entries(schemaProps)) {
2805
+ const { schema: property } = resolveSchemaRef(value, context);
2806
+ if (property.readOnly) continue;
2807
+ let formDataValue = "";
2808
+ const partContentType = (depth === 0 ? encoding?.[key] : void 0)?.contentType;
2809
+ const formattedKeyPrefix = isRequestBodyOptional ? keyword.isIdentifierNameES5(key) ? "?" : "?." : "";
2810
+ const formattedKey = keyword.isIdentifierNameES5(key) ? `.${key}` : `['${key}']`;
2811
+ const valueKey = `${propName}${formattedKeyPrefix}${formattedKey}`;
2812
+ const nonOptionalValueKey = `${propName}${formattedKey}`;
2813
+ const fileType = getFormDataFieldFileType(property, partContentType);
2814
+ const effectiveContentType = partContentType ?? property.contentMediaType;
2815
+ if (isUrlEncoded && (fileType || property.format === "binary")) formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey});\n`;
2816
+ else if (fileType === "binary" || property.format === "binary") formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey});\n`;
2817
+ else if (fileType === "text") formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey} instanceof Blob ? ${nonOptionalValueKey} : new Blob([${nonOptionalValueKey}], { type: '${effectiveContentType}' }));\n`;
2818
+ else if (property.type === "object" || Array.isArray(property.type) && property.type.includes("object")) formDataValue = context.output.override.formData.arrayHandling === FormDataArrayHandling.EXPLODE ? resolveSchemaPropertiesToFormData({
2819
+ schema: property,
2820
+ variableName,
2821
+ propName: nonOptionalValueKey,
2822
+ context,
2823
+ isRequestBodyOptional,
2824
+ keyPrefix: `${keyPrefix}${key}.`,
2825
+ depth: depth + 1,
2826
+ encoding
2827
+ }) : `${variableName}.append(\`${keyPrefix}${key}\`, JSON.stringify(${nonOptionalValueKey}));\n`;
2828
+ else if (property.type === "array" || Array.isArray(property.type) && property.type.includes("array")) {
2829
+ let valueStr = "value";
2830
+ let hasNonPrimitiveChild = false;
2831
+ const propertyItems = getSchemaItems(property);
2832
+ if (propertyItems) {
2833
+ const { schema: itemSchema } = resolveSchemaRef(propertyItems, context);
2834
+ if (itemSchema.type === "object" || itemSchema.type === "array") if (context.output.override.formData.arrayHandling === FormDataArrayHandling.EXPLODE) {
2835
+ hasNonPrimitiveChild = true;
2836
+ const resolvedValue = resolveSchemaPropertiesToFormData({
2837
+ schema: itemSchema,
2838
+ variableName,
2839
+ propName: "value",
2840
+ context,
2841
+ isRequestBodyOptional,
2842
+ keyPrefix: `${keyPrefix}${key}[\${index${depth > 0 ? depth : ""}}].`,
2843
+ depth: depth + 1
2844
+ });
2845
+ formDataValue = `${valueKey}.forEach((value, index${depth > 0 ? depth : ""}) => {
2846
+ ${resolvedValue}});\n`;
2847
+ } else valueStr = "JSON.stringify(value)";
2848
+ else {
2849
+ const itemType = getSchemaType$1(itemSchema);
2850
+ 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()";
2851
+ }
2852
+ }
2853
+ if (context.output.override.formData.arrayHandling === FormDataArrayHandling.EXPLODE) {
2854
+ if (!hasNonPrimitiveChild) formDataValue = `${valueKey}.forEach((value, index${depth > 0 ? depth : ""}) => ${variableName}.append(\`${keyPrefix}${key}[\${index${depth > 0 ? depth : ""}}]\`, ${valueStr}));\n`;
2855
+ } else formDataValue = `${valueKey}.forEach(value => ${variableName}.append(\`${keyPrefix}${key}${context.output.override.formData.arrayHandling === FormDataArrayHandling.SERIALIZE_WITH_BRACKETS ? "[]" : ""}\`, ${valueStr}));\n`;
2856
+ } else if ((() => {
2857
+ const propType = getSchemaType$1(property);
2858
+ return propType === "number" || Array.isArray(propType) && propType.includes("number") || propType === "integer" || Array.isArray(propType) && propType.includes("integer") || propType === "boolean" || Array.isArray(propType) && propType.includes("boolean");
2859
+ })()) formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey}.toString())\n`;
2860
+ else formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey});\n`;
2861
+ let existSubSchemaNullable = false;
2862
+ const combine = getSchemaCombined(property);
2863
+ if (combine) {
2864
+ const subSchemas = combine.map((c) => resolveObject({
2865
+ schema: c,
2866
+ combined: true,
2867
+ context
2868
+ }));
2869
+ if (subSchemas.some((subSchema) => {
2870
+ return [
2871
+ "number",
2872
+ "integer",
2873
+ "boolean"
2874
+ ].includes(subSchema.type);
2875
+ })) formDataValue = `${variableName}.append(\`${key}\`, ${nonOptionalValueKey}.toString())\n`;
2876
+ if (subSchemas.some((subSchema) => {
2877
+ return subSchema.type === "null";
2878
+ })) existSubSchemaNullable = true;
2790
2879
  }
2791
- const resolvedValueStr = resolvedValue?.value.includes(" | ") ? `(${resolvedValue.value})` : resolvedValue?.value;
2792
- const joined = `${resolvedDataValue}${resolvedValue ? ` & ${resolvedValueStr}` : ""}`;
2793
- const overrideRequiredProperties = resolvedData.requiredProperties.filter((prop) => !resolvedData.originalSchema.some((schema) => {
2794
- const props = schema?.properties;
2795
- const req = schema?.required;
2796
- return props?.[prop] && req?.includes(prop);
2797
- }) && !(() => {
2798
- const parentProps = parentSchema?.properties;
2799
- const parentReq = parentSchema?.required;
2800
- return !!(parentProps?.[prop] && parentReq?.includes(prop));
2801
- })());
2802
- if (overrideRequiredProperties.length > 0) return `${joined} & Required<Pick<${joined}, '${overrideRequiredProperties.join("' | '")}'>>`;
2803
- return joined;
2804
- }
2805
- let values = resolvedData.values;
2806
- if (resolvedData.allProperties.length && context.output.unionAddMissingProperties) {
2807
- values = [];
2808
- for (let i = 0; i < resolvedData.values.length; i += 1) {
2809
- const subSchema = resolvedData.originalSchema[i];
2810
- if (subSchema?.type !== "object" || !subSchema.properties) {
2811
- values.push(resolvedData.values[i]);
2880
+ const isRequired = getSchemaRequired(schema)?.includes(key) && !isRequestBodyOptional;
2881
+ const propType = getSchemaType$1(property);
2882
+ if (property.nullable || Array.isArray(propType) && propType.includes("null") || existSubSchemaNullable) {
2883
+ if (isRequired) {
2884
+ formDataValues += `if(${valueKey} !== null) {\n ${formDataValue} }\n`;
2812
2885
  continue;
2813
2886
  }
2814
- const subSchemaProps = subSchema.properties;
2815
- const missingProperties = unique(resolvedData.allProperties.filter((p) => !Object.keys(subSchemaProps).includes(p)));
2816
- values.push(`${resolvedData.values[i]}${missingProperties.length > 0 ? ` & {${missingProperties.map((p) => `${p}?: never`).join("; ")}}` : ""}`);
2887
+ formDataValues += `if(${valueKey} !== undefined && ${nonOptionalValueKey} !== null) {\n ${formDataValue} }\n`;
2888
+ continue;
2889
+ }
2890
+ if (isRequired) {
2891
+ formDataValues += formDataValue;
2892
+ continue;
2817
2893
  }
2894
+ formDataValues += `if(${valueKey} !== undefined) {\n ${formDataValue} }\n`;
2818
2895
  }
2819
- if (resolvedValue) return `(${values.join(` & ${resolvedValue.value}) | (`)} & ${resolvedValue.value})`;
2820
- return values.join(" | ");
2896
+ return formDataValues;
2821
2897
  }
2822
- function combineSchemas({ name, schema, separator, context, nullable, formDataContext }) {
2823
- const normalizedSchema = separator === "allOf" && !context.output.override.aliasCombinedTypes && !schema.oneOf && !schema.anyOf ? normalizeAllOfSchema(schema) : schema;
2824
- const items = normalizedSchema[separator] ?? [];
2825
- const resolvedData = {
2826
- values: [],
2827
- imports: [],
2828
- schemas: [],
2829
- isEnum: [],
2830
- isRef: [],
2831
- types: [],
2832
- dependencies: [],
2833
- originalSchema: [],
2834
- allProperties: [],
2835
- hasReadonlyProps: false,
2836
- example: schema.example,
2837
- examples: resolveExampleRefs(schema.examples, context),
2838
- requiredProperties: separator === "allOf" ? schema.required ?? [] : []
2839
- };
2840
- for (const subSchema of items) {
2841
- let propName;
2842
- if (context.output.override.aliasCombinedTypes) {
2843
- propName = name ? name + pascal(separator) : void 0;
2844
- if (propName && resolvedData.schemas.length > 0) propName = propName + pascal(getNumberWord(resolvedData.schemas.length + 1));
2845
- }
2846
- if (separator === "allOf" && isSchema(subSchema) && subSchema.required) resolvedData.requiredProperties.push(...subSchema.required);
2847
- const resolvedValue = resolveObject({
2848
- schema: subSchema,
2849
- propName,
2850
- combined: true,
2851
- context,
2852
- formDataContext
2853
- });
2854
- const aliasedImports = getAliasedImports({
2855
- context,
2856
- name,
2857
- resolvedValue
2858
- });
2859
- const value = getImportAliasForRefOrValue({
2860
- context,
2861
- resolvedValue,
2862
- imports: aliasedImports
2898
+ //#endregion
2899
+ //#region src/getters/body.ts
2900
+ function buildBody(filteredBodyTypes, requestBody, operationName, context) {
2901
+ const imports = filteredBodyTypes.flatMap(({ imports }) => imports);
2902
+ const schemas = filteredBodyTypes.flatMap(({ schemas }) => schemas);
2903
+ const definition = filteredBodyTypes.map(({ value }) => value).join(" | ");
2904
+ const nonReadonlyDefinition = filteredBodyTypes.some((x) => x.hasReadonlyProps) && definition && context.output.override.preserveReadonlyRequestBodies !== "preserve" ? `NonReadonly<${definition}>` : definition;
2905
+ let implementation = generalJSTypesWithArray.includes(definition.toLowerCase()) || filteredBodyTypes.length > 1 ? camel(operationName) + context.output.override.components.requestBodies.suffix : camel(definition);
2906
+ let isOptional = false;
2907
+ if (implementation) {
2908
+ implementation = sanitize(implementation, {
2909
+ underscore: "_",
2910
+ whitespace: "_",
2911
+ dash: true,
2912
+ es5keyword: true,
2913
+ es5IdentifierName: true
2863
2914
  });
2864
- resolvedData.values.push(value);
2865
- resolvedData.imports.push(...aliasedImports);
2866
- resolvedData.schemas.push(...resolvedValue.schemas);
2867
- resolvedData.dependencies.push(...resolvedValue.dependencies);
2868
- resolvedData.isEnum.push(resolvedValue.isEnum);
2869
- resolvedData.types.push(resolvedValue.type);
2870
- resolvedData.isRef.push(resolvedValue.isRef);
2871
- resolvedData.originalSchema.push(resolvedValue.originalSchema);
2872
- if (resolvedValue.hasReadonlyProps) resolvedData.hasReadonlyProps = true;
2873
- const originalProps = resolvedValue.originalSchema.properties;
2874
- if (resolvedValue.type === "object" && originalProps) resolvedData.allProperties.push(...Object.keys(originalProps));
2915
+ if (isReference(requestBody)) {
2916
+ const { schema: bodySchema } = resolveRef(requestBody, context);
2917
+ isOptional = bodySchema.required !== true;
2918
+ } else isOptional = requestBody.required !== true;
2875
2919
  }
2876
- if (resolvedData.isEnum.every(Boolean) && name && items.length > 1 && context.output.override.enumGenerationType !== EnumGeneration.UNION) {
2877
- const { value: combinedEnumValue, valueImports, hasNull } = getCombinedEnumValue(resolvedData.values.map((value, index) => ({
2878
- value,
2879
- isRef: resolvedData.isRef[index],
2880
- schema: resolvedData.originalSchema[index]
2881
- })));
2882
- const newEnum = `export const ${pascal(name)} = ${combinedEnumValue}`;
2883
- const valueImportSet = new Set(valueImports);
2884
- const typeSuffix = `${nullable}${hasNull && !nullable.includes("null") ? " | null" : ""}`;
2920
+ return {
2921
+ originalSchema: requestBody,
2922
+ definition: nonReadonlyDefinition,
2923
+ implementation,
2924
+ imports,
2925
+ schemas,
2926
+ isOptional,
2927
+ ...filteredBodyTypes.length === 1 ? {
2928
+ formData: filteredBodyTypes[0].formData,
2929
+ formUrlEncoded: filteredBodyTypes[0].formUrlEncoded,
2930
+ contentType: filteredBodyTypes[0].contentType
2931
+ } : {
2932
+ formData: "",
2933
+ formUrlEncoded: "",
2934
+ contentType: ""
2935
+ }
2936
+ };
2937
+ }
2938
+ function getBody({ requestBody, operationName, context, contentType }) {
2939
+ return buildBody(filterByContentType(getResReqTypes([[context.output.override.components.requestBodies.suffix, requestBody]], operationName, context), contentType), requestBody, operationName, context);
2940
+ }
2941
+ /**
2942
+ * Returns per-content-type bodies when `splitByContentType` is enabled.
2943
+ * Each entry includes a `contentTypeSuffix` for generating distinct function names.
2944
+ */
2945
+ function getBodiesByContentType({ requestBody, operationName, context, contentType }) {
2946
+ const filteredBodyTypes = filterByContentType(getResReqTypes([[context.output.override.components.requestBodies.suffix, requestBody]], operationName, context, void 0, (item) => `${item.value}::${item.contentType}`), contentType);
2947
+ if (filteredBodyTypes.length <= 1) return [{
2948
+ ...buildBody(filteredBodyTypes, requestBody, operationName, context),
2949
+ contentTypeSuffix: ""
2950
+ }];
2951
+ return filteredBodyTypes.map((bodyType) => {
2952
+ const suffix = getContentTypeSuffix(bodyType.contentType);
2885
2953
  return {
2886
- value: `typeof ${pascal(name)}[keyof typeof ${pascal(name)}]${typeSuffix}`,
2887
- imports: [{ name: pascal(name) }],
2888
- schemas: [...resolvedData.schemas, {
2889
- imports: resolvedData.imports.filter((toImport) => valueImportSet.has(toImport.alias ?? toImport.name)).map((toImport) => ({
2890
- ...toImport,
2891
- values: true
2892
- })),
2893
- model: newEnum,
2894
- name
2895
- }],
2896
- isEnum: false,
2897
- type: "object",
2898
- isRef: false,
2899
- hasReadonlyProps: resolvedData.hasReadonlyProps,
2900
- dependencies: resolvedData.dependencies,
2901
- example: schema.example,
2902
- examples: resolveExampleRefs(schema.examples, context)
2954
+ ...buildBody([bodyType], requestBody, operationName, context),
2955
+ contentTypeSuffix: suffix
2903
2956
  };
2904
- }
2905
- let resolvedValue;
2906
- const normalizedProperties = normalizedSchema.properties;
2907
- const schemaOneOf = schema.oneOf;
2908
- const schemaAnyOf = schema.anyOf;
2909
- if (normalizedProperties) resolvedValue = getScalar({
2910
- item: Object.fromEntries(Object.entries(normalizedSchema).filter(([key]) => key !== separator)),
2911
- name,
2912
- context,
2913
- formDataContext
2914
2957
  });
2915
- else if (separator === "allOf" && (schemaOneOf || schemaAnyOf)) {
2916
- const siblingCombiner = schemaOneOf ? "oneOf" : "anyOf";
2917
- const siblingSchemas = schemaOneOf ?? schemaAnyOf;
2918
- resolvedValue = combineSchemas({
2919
- schema: { [siblingCombiner]: siblingSchemas },
2920
- name,
2921
- separator: siblingCombiner,
2922
- context,
2923
- nullable: ""
2924
- });
2925
- }
2926
- return {
2927
- value: dedupeUnionType(combineValues({
2928
- resolvedData,
2929
- separator,
2930
- resolvedValue,
2931
- context,
2932
- parentSchema: normalizedSchema
2933
- }) + nullable),
2934
- imports: resolvedValue ? [...resolvedData.imports, ...resolvedValue.imports] : resolvedData.imports,
2935
- schemas: resolvedValue ? [...resolvedData.schemas, ...resolvedValue.schemas] : resolvedData.schemas,
2936
- dependencies: resolvedValue ? [...resolvedData.dependencies, ...resolvedValue.dependencies] : resolvedData.dependencies,
2937
- isEnum: false,
2938
- type: "object",
2939
- isRef: false,
2940
- hasReadonlyProps: resolvedData.hasReadonlyProps || (resolvedValue?.hasReadonlyProps ?? false),
2941
- example: schema.example,
2942
- examples: resolveExampleRefs(schema.examples, context)
2943
- };
2958
+ }
2959
+ const CONTENT_TYPE_SUFFIX_MAP = {
2960
+ "application/json": "Json",
2961
+ "multipart/form-data": "FormData",
2962
+ "application/x-www-form-urlencoded": "UrlEncoded",
2963
+ "text/plain": "Text",
2964
+ "application/xml": "Xml",
2965
+ "text/xml": "Xml",
2966
+ "application/octet-stream": "Blob"
2967
+ };
2968
+ function getContentTypeSuffix(contentType) {
2969
+ if (CONTENT_TYPE_SUFFIX_MAP[contentType]) return CONTENT_TYPE_SUFFIX_MAP[contentType];
2970
+ return (contentType.split("/")[1] ?? contentType).split(/[-+.]/).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
2944
2971
  }
2945
2972
  //#endregion
2946
2973
  //#region src/getters/discriminators.ts
@@ -4636,8 +4663,8 @@ function getSchema({ schema: { imports, model }, header, namingConvention = Nami
4636
4663
  file += model;
4637
4664
  return file;
4638
4665
  }
4639
- function getPath(path$1, name, fileExtension) {
4640
- return path.join(path$1, `${name}${fileExtension}`);
4666
+ function getPath(path, name, fileExtension) {
4667
+ return nodePath.join(path, `${name}${fileExtension}`);
4641
4668
  }
4642
4669
  function writeModelInline(acc, model) {
4643
4670
  return acc + `${model}\n`;
@@ -4689,7 +4716,7 @@ async function writeSchemas({ schemaPath, schemas, target, namingConvention, fil
4689
4716
  });
4690
4717
  }
4691
4718
  if (indexFiles) {
4692
- const schemaFilePath = path.join(schemaPath, `index.ts`);
4719
+ const schemaFilePath = nodePath.join(schemaPath, `index.ts`);
4693
4720
  await fs$1.ensureFile(schemaFilePath);
4694
4721
  const ext = getImportExtension(fileExtension, tsconfig);
4695
4722
  const conventionNamesSet = new Set(Object.values(schemaGroups).map((group) => conventionName(group[0].name, namingConvention)));
@@ -5000,7 +5027,7 @@ async function writeSplitMode({ builder, output, projectName, header, needSchema
5000
5027
  packageJson: output.packageJson,
5001
5028
  output
5002
5029
  });
5003
- const schemasPath = !output.schemas && needSchema ? path.join(dirname, filename + ".schemas" + extension) : void 0;
5030
+ const schemasPath = !output.schemas && needSchema ? nodePath.join(dirname, filename + ".schemas" + extension) : void 0;
5004
5031
  if (schemasPath) await writeGeneratedFile(schemasPath, generateSchemasInline ? header + generateSchemasInline() : header + generateModelsInline(builder.schemas));
5005
5032
  if (mutators) implementationData += generateMutatorImports({
5006
5033
  mutators,
@@ -5022,7 +5049,7 @@ async function writeSplitMode({ builder, output, projectName, header, needSchema
5022
5049
  }
5023
5050
  implementationData += `\n${implementation}`;
5024
5051
  const implementationFilename = filename + (OutputClient.ANGULAR === output.client ? ".service" : "") + extension;
5025
- const implementationPath = path.join(dirname, implementationFilename);
5052
+ const implementationPath = nodePath.join(dirname, implementationFilename);
5026
5053
  await writeGeneratedFile(implementationPath, implementationData);
5027
5054
  const mockPaths = [];
5028
5055
  for (const mockOutput of mockOutputs) {
@@ -5039,7 +5066,7 @@ async function writeSplitMode({ builder, output, projectName, header, needSchema
5039
5066
  options: entry
5040
5067
  });
5041
5068
  mockData += `\n${mockOutput.implementation}`;
5042
- const mockPath = path.join(dirname, filename + "." + getMockFileExtensionByTypeName(entry) + extension);
5069
+ const mockPath = nodePath.join(dirname, filename + "." + getMockFileExtensionByTypeName(entry) + extension);
5043
5070
  await writeGeneratedFile(mockPath, mockData);
5044
5071
  mockPaths.push(mockPath);
5045
5072
  }
@@ -5235,7 +5262,7 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
5235
5262
  const indexFilePathsByType = /* @__PURE__ */ new Map();
5236
5263
  if (output.mock.indexMockFiles) for (const entry of generatorEntries) {
5237
5264
  const ext = getMockFileExtensionByTypeName(entry);
5238
- const indexPath = path.join(dirname, `index.${ext}${extension}`);
5265
+ const indexPath = nodePath.join(dirname, `index.${ext}${extension}`);
5239
5266
  indexFilePathsByType.set(ext, indexPath);
5240
5267
  await fs$1.outputFile(indexPath, "");
5241
5268
  }
@@ -5244,19 +5271,19 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
5244
5271
  try {
5245
5272
  const { imports, implementation, mockOutputs, mutators, clientMutators, formData, fetchReviver, formUrlEncoded, paramsSerializer, paramsFilter } = target;
5246
5273
  let implementationData = header;
5247
- const importerPath = path.join(dirname, tag, tag + extension);
5274
+ const importerPath = nodePath.join(dirname, tag, tag + extension);
5248
5275
  const relativeSchemasPath = output.schemas ? getRelativeImportPath(importerPath, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : "../" + filename + ".schemas" + extension.replace(/\.ts$/, "");
5249
5276
  const tagNames = new Set(tagEntries.map(([t]) => t));
5250
5277
  const serviceSuffix = OutputClient.ANGULAR === output.client ? ".service" : "";
5251
5278
  const importsForBuilder = generateImportsForBuilder(output, imports.map((imp) => {
5252
5279
  if (!imp.importPath) return imp;
5253
5280
  if (!imp.importPath.startsWith(".")) return imp;
5254
- const resolvedPath = path.resolve(dirname, imp.importPath);
5255
- const targetBasename = path.basename(resolvedPath);
5281
+ const resolvedPath = nodePath.resolve(dirname, imp.importPath);
5282
+ const targetBasename = nodePath.basename(resolvedPath);
5256
5283
  let targetFile;
5257
5284
  if (tagNames.has(targetBasename)) {
5258
5285
  const tagFilename = targetBasename + serviceSuffix + extension;
5259
- targetFile = path.join(resolvedPath, tagFilename);
5286
+ targetFile = nodePath.join(resolvedPath, tagFilename);
5260
5287
  } else targetFile = resolvedPath + extension;
5261
5288
  const adjustedPath = getRelativeImportPath(importerPath, targetFile);
5262
5289
  return {
@@ -5277,7 +5304,7 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
5277
5304
  packageJson: output.packageJson,
5278
5305
  output
5279
5306
  });
5280
- const schemasPath = !output.schemas && needSchema ? path.join(dirname, filename + ".schemas" + extension) : void 0;
5307
+ const schemasPath = !output.schemas && needSchema ? nodePath.join(dirname, filename + ".schemas" + extension) : void 0;
5281
5308
  if (schemasPath) await writeGeneratedFile(schemasPath, generateSchemasInline ? header + generateSchemasInline() : header + generateModelsInline(builder.schemas));
5282
5309
  if (mutators) implementationData += generateMutatorImports({
5283
5310
  mutators,
@@ -5318,7 +5345,7 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
5318
5345
  }
5319
5346
  implementationData += `\n${implementation}`;
5320
5347
  const implementationFilename = tag + (OutputClient.ANGULAR === output.client ? ".service" : "") + extension;
5321
- const implementationPath = path.join(dirname, tag, implementationFilename);
5348
+ const implementationPath = nodePath.join(dirname, tag, implementationFilename);
5322
5349
  await writeGeneratedFile(implementationPath, implementationData);
5323
5350
  const mockPaths = [];
5324
5351
  for (const mockOutput of mockOutputs) {
@@ -5335,7 +5362,7 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
5335
5362
  options: entry
5336
5363
  });
5337
5364
  mockData += `\n${mockOutput.implementation}`;
5338
- const mockPath = path.join(dirname, tag, tag + "." + getMockFileExtensionByTypeName(entry) + extension);
5365
+ const mockPath = nodePath.join(dirname, tag, tag + "." + getMockFileExtensionByTypeName(entry) + extension);
5339
5366
  await writeGeneratedFile(mockPath, mockData);
5340
5367
  mockPaths.push(mockPath);
5341
5368
  }
@@ -5413,7 +5440,7 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema,
5413
5440
  options: entry && !isFunction(entry) ? entry : void 0
5414
5441
  });
5415
5442
  }
5416
- const schemasPath = !output.schemas && needSchema ? path.join(dirname, filename + ".schemas" + extension) : void 0;
5443
+ const schemasPath = !output.schemas && needSchema ? nodePath.join(dirname, filename + ".schemas" + extension) : void 0;
5417
5444
  if (schemasPath) await writeGeneratedFile(schemasPath, generateSchemasInline ? header + generateSchemasInline() : header + generateModelsInline(builder.schemas));
5418
5445
  if (mutators) data += generateMutatorImports({
5419
5446
  mutators,
@@ -5439,7 +5466,7 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema,
5439
5466
  data += "\n\n";
5440
5467
  data += implementationMock;
5441
5468
  }
5442
- const implementationPath = path.join(dirname, `${kebab(tag)}${extension}`);
5469
+ const implementationPath = nodePath.join(dirname, `${kebab(tag)}${extension}`);
5443
5470
  await writeGeneratedFile(implementationPath, data);
5444
5471
  return [implementationPath, ...schemasPath ? [schemasPath] : []];
5445
5472
  } catch (error) {
@@ -5448,6 +5475,6 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema,
5448
5475
  }))).flat();
5449
5476
  }
5450
5477
  //#endregion
5451
- export { BODY_TYPE_NAME, DefaultTag, EnumGeneration, ErrorWithTag, FormDataArrayHandling, GetterPropType, LogLevels, NAMED_COMPONENT_SECTIONS, NamingConvention, OutputClient, OutputHttpClient, OutputMockType, OutputMode, PropertySortOrder, RefComponentSuffix, SchemaType, SupportedFormatter, TEMPLATE_TAG_REGEX, URL_REGEX, VERBS_WITH_BODY, Verbs, addDependency, asyncReduce, buildAngularParamsFilterExpression, camel, collectReferencedComponents, combineSchemas, compareVersions, conventionName, count, createDebugger, createLogger, createSuccessMessage, createTypeAliasIfNeeded, dedupeUnionType, dynamicImport, escape, escapeRegExp, filterByContentType, filteredVerbs, 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, getAngularFilteredParamsCallExpression, getAngularFilteredParamsExpression, getAngularFilteredParamsHelperBody, getArray, getBaseUrlRuntimeImports, getBodiesByContentType, getBody, getCombinedEnumValue, getDefaultContentType, getEnum, getEnumDescriptions, getEnumImplementation, getEnumNames, getEnumUnionFromSchema, getExtension, getFileInfo, getFormDataFieldFileType, getFullRoute, getImportExtension, getIsBodyVerb, getKey, getMockFileExtensionByTypeName, getNumberWord, getObject, getOperationId, getOrvalGeneratedTypes, getParameters, getParams, getParamsInPath, getPropertySafe, getProps, getQueryParams, getRefInfo, getResReqTypes, getResponse, getResponseTypeCategory, getRoute, getRouteAsArray, getScalar, getSuccessResponseType, getTypedResponse, getWarningCount, isBinaryContentType, isBoolean, isComponentRef, isDirectory, isFakerMock, isFunction, isModule, isMswMock, isNullish, isNumber, isNumeric, isObject, isReference, isSchema, isString, isStringLike, isSyntheticDefaultImportsAllow, isUrl, isVerb, isVerbose, jsDoc, jsStringEscape, kebab, keyValuePairsToJsDoc, log, logError, logVerbose, logWarning, makeRouteSafe, mergeDeep, mismatchArgsMessage, pascal, removeFilesAndEmptyFolders, resetWarnings, resolveDiscriminators, resolveExampleRefs, resolveInstalledVersion, resolveInstalledVersions, resolveObject, resolveRef, resolveValue, sanitize, setVerbose, snake, sortByPriority, splitSchemasByType, startMessage, stringify, toObjectString, path_exports as upath, upper, wrapRouteParameters, writeModelInline, writeModelsInline, writeSchema, writeSchemas, writeSingleMode, writeSplitMode, writeSplitTagsMode, writeTagsMode };
5478
+ export { BODY_TYPE_NAME, DefaultTag, EnumGeneration, ErrorWithTag, FormDataArrayHandling, GetterPropType, LogLevels, NAMED_COMPONENT_SECTIONS, NamingConvention, OutputClient, OutputHttpClient, OutputMockType, OutputMode, PropertySortOrder, RefComponentSuffix, SchemaType, SupportedFormatter, TEMPLATE_TAG_REGEX, URL_REGEX, VERBS_WITH_BODY, Verbs, addDependency, asyncReduce, buildAngularParamsFilterExpression, camel, collectReferencedComponents, combineSchemas, compareVersions, conventionName, count, createDebugger, createLogger, createSuccessMessage, createTypeAliasIfNeeded, dedupeUnionType, dynamicImport, escape, escapeRegExp, filterByContentType, filteredVerbs, 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, getAngularFilteredParamsCallExpression, getAngularFilteredParamsExpression, getAngularFilteredParamsHelperBody, getArray, getBaseUrlRuntimeImports, getBodiesByContentType, getBody, getCombinedEnumValue, getDefaultContentType, getEnum, getEnumDescriptions, getEnumImplementation, getEnumNames, getEnumUnionFromSchema, getExtension, getFileInfo, getFormDataFieldFileType, getFullRoute, getImportExtension, getIsBodyVerb, getKey, getMockFileExtensionByTypeName, getNumberWord, getObject, getOperationId, getOrvalGeneratedTypes, getParameters, getParams, getParamsInPath, getPropertySafe, getProps, getQueryParams, getRefInfo, getResReqTypes, getResponse, getResponseTypeCategory, getRoute, getRouteAsArray, getScalar, getSuccessResponseType, getTypedResponse, getWarningCount, isBinaryContentType, isBinaryScalarSchema, isBoolean, isComponentRef, isDirectory, isFakerMock, isFunction, isModule, isMswMock, isNullish, isNumber, isNumeric, isObject, isReference, isSchema, isString, isStringLike, isSyntheticDefaultImportsAllow, isUrl, isVerb, isVerbose, jsDoc, jsStringEscape, kebab, keyValuePairsToJsDoc, log, logError, logVerbose, logWarning, makeRouteSafe, mergeDeep, mismatchArgsMessage, pascal, removeFilesAndEmptyFolders, resetWarnings, resolveDiscriminators, resolveExampleRefs, resolveInstalledVersion, resolveInstalledVersions, resolveObject, resolveRef, resolveValue, sanitize, setVerbose, snake, sortByPriority, splitSchemasByType, startMessage, stringify, toObjectString, path_exports as upath, upper, wrapRouteParameters, writeModelInline, writeModelsInline, writeSchema, writeSchemas, writeSingleMode, writeSplitMode, writeSplitTagsMode, writeTagsMode };
5452
5479
 
5453
5480
  //# sourceMappingURL=index.mjs.map