@orval/core 8.0.2 → 8.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -234,7 +234,7 @@ function joinSafe(...values) {
234
234
  * @param property
235
235
  */
236
236
  function isReference(obj) {
237
- return Object.hasOwn(obj, "$ref");
237
+ return !isNull(obj) && Object.hasOwn(obj, "$ref");
238
238
  }
239
239
  function isDirectory(path$2) {
240
240
  return !extname(path$2);
@@ -810,6 +810,14 @@ function jsStringEscape(input) {
810
810
  }
811
811
  });
812
812
  }
813
+ /**
814
+ * Deduplicates a TypeScript union type string.
815
+ * Handles types like "A | B | B" → "A | B" and "null | null" → "null".
816
+ */
817
+ function dedupeUnionType(unionType) {
818
+ const parts = unionType.split("|").map((part) => part.trim());
819
+ return [...new Set(parts)].join(" | ");
820
+ }
813
821
 
814
822
  //#endregion
815
823
  //#region src/utils/tsconfig.ts
@@ -895,6 +903,76 @@ const toNumberKey = (value) => {
895
903
  const getUnion = (value, enumName) => {
896
904
  return `export type ${enumName} = ${value};`;
897
905
  };
906
+ function getEnumUnionFromSchema(schema) {
907
+ if (!schema?.enum) return "";
908
+ return schema.enum.filter((val) => val !== null).map((val) => isString(val) ? `'${escape(val)}'` : `${val}`).join(" | ");
909
+ }
910
+ const stripNullUnion = (value) => value.replace(/\s*\|\s*null/g, "").trim();
911
+ const isSpreadableEnumRef = (schema, refName) => {
912
+ if (!schema?.enum || !refName) return false;
913
+ if (!getEnumUnionFromSchema(schema)) return false;
914
+ const type = schema.type;
915
+ if (type === "boolean" || Array.isArray(type) && type.includes("boolean")) return false;
916
+ return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(refName);
917
+ };
918
+ const buildInlineEnum = (schema, enumValue) => {
919
+ const names = getEnumNames(schema);
920
+ const descriptions = getEnumDescriptions(schema);
921
+ return getEnumImplementation(enumValue ?? getEnumUnionFromSchema(schema), names, descriptions);
922
+ };
923
+ function getCombinedEnumValue(inputs) {
924
+ const valueImports = [];
925
+ const hasNull = inputs.some((input) => {
926
+ if (input.value.includes("| null")) return true;
927
+ const schema = input.schema;
928
+ if (!schema) return false;
929
+ if (schema.nullable === true) return true;
930
+ if (Array.isArray(schema.type) && schema.type.includes("null")) return true;
931
+ return schema.enum?.includes(null) ?? false;
932
+ });
933
+ const addValueImport = (name) => {
934
+ if (!valueImports.includes(name)) valueImports.push(name);
935
+ };
936
+ if (inputs.length === 1) {
937
+ const input = inputs[0];
938
+ if (input.isRef) {
939
+ const refName = stripNullUnion(input.value);
940
+ if (isSpreadableEnumRef(input.schema, refName)) {
941
+ addValueImport(refName);
942
+ return {
943
+ value: refName,
944
+ valueImports,
945
+ hasNull
946
+ };
947
+ }
948
+ return {
949
+ value: `{${buildInlineEnum(input.schema)}} as const`,
950
+ valueImports,
951
+ hasNull
952
+ };
953
+ }
954
+ return {
955
+ value: `{${buildInlineEnum(input.schema, stripNullUnion(input.value))}} as const`,
956
+ valueImports,
957
+ hasNull
958
+ };
959
+ }
960
+ return {
961
+ value: `{${inputs.map((input) => {
962
+ if (input.isRef) {
963
+ const refName = stripNullUnion(input.value);
964
+ if (isSpreadableEnumRef(input.schema, refName)) {
965
+ addValueImport(refName);
966
+ return `...${refName},`;
967
+ }
968
+ return buildInlineEnum(input.schema);
969
+ }
970
+ return buildInlineEnum(input.schema, stripNullUnion(input.value));
971
+ }).join("")}} as const`,
972
+ valueImports,
973
+ hasNull
974
+ };
975
+ }
898
976
 
899
977
  //#endregion
900
978
  //#region src/getters/ref.ts
@@ -1383,12 +1461,13 @@ function getScalar({ item, name, context }) {
1383
1461
  function combineValues({ resolvedData, resolvedValue, separator: separator$1, context }) {
1384
1462
  if (resolvedData.isEnum.every(Boolean)) return `${resolvedData.values.join(` | `)}${resolvedValue ? ` | ${resolvedValue.value}` : ""}`;
1385
1463
  if (separator$1 === "allOf") {
1386
- let resolvedDataValue = resolvedData.values.join(` & `);
1464
+ let resolvedDataValue = resolvedData.values.map((v) => v.includes(" | ") ? `(${v})` : v).join(` & `);
1387
1465
  if (resolvedData.originalSchema.length > 0 && resolvedValue) {
1388
1466
  const discriminatedPropertySchemas = resolvedData.originalSchema.filter((s) => s?.discriminator && resolvedValue.value.includes(` ${s.discriminator.propertyName}:`));
1389
1467
  if (discriminatedPropertySchemas.length > 0) resolvedDataValue = `Omit<${resolvedDataValue}, '${discriminatedPropertySchemas.map((s) => s.discriminator?.propertyName).join("' | '")}'>`;
1390
1468
  }
1391
- const joined = `${resolvedDataValue}${resolvedValue ? ` & ${resolvedValue.value}` : ""}`;
1469
+ const resolvedValueStr = resolvedValue?.value.includes(" | ") ? `(${resolvedValue.value})` : resolvedValue?.value;
1470
+ const joined = `${resolvedDataValue}${resolvedValue ? ` & ${resolvedValueStr}` : ""}`;
1392
1471
  const overrideRequiredProperties = resolvedData.requiredProperties.filter((prop$1) => !resolvedData.originalSchema.some((schema) => schema?.properties?.[prop$1] && schema.required?.includes(prop$1)));
1393
1472
  if (overrideRequiredProperties.length > 0) return `${joined} & Required<Pick<${joined}, '${overrideRequiredProperties.join("' | '")}'>>`;
1394
1473
  return joined;
@@ -1460,13 +1539,20 @@ function combineSchemas({ name, schema, separator: separator$1, context, nullabl
1460
1539
  examples: resolveExampleRefs(schema.examples, context),
1461
1540
  requiredProperties: separator$1 === "allOf" ? schema.required ?? [] : []
1462
1541
  });
1463
- if (resolvedData.isEnum.every(Boolean) && name && items.length > 1 && separator$1 !== "oneOf") {
1464
- const newEnum = `export const ${pascal(name)} = ${getCombineEnumValue(resolvedData)}`;
1542
+ if (resolvedData.isEnum.every(Boolean) && name && items.length > 1 && context.output.override.enumGenerationType !== EnumGeneration.UNION) {
1543
+ const { value: combinedEnumValue, valueImports, hasNull } = getCombinedEnumValue(resolvedData.values.map((value, index) => ({
1544
+ value,
1545
+ isRef: resolvedData.isRef[index],
1546
+ schema: resolvedData.originalSchema[index]
1547
+ })));
1548
+ const newEnum = `export const ${pascal(name)} = ${combinedEnumValue}`;
1549
+ const valueImportSet = new Set(valueImports);
1550
+ const typeSuffix = `${nullable}${hasNull && !nullable.includes("null") ? " | null" : ""}`;
1465
1551
  return {
1466
- value: `typeof ${pascal(name)}[keyof typeof ${pascal(name)}] ${nullable}`,
1552
+ value: `typeof ${pascal(name)}[keyof typeof ${pascal(name)}]${typeSuffix}`,
1467
1553
  imports: [{ name: pascal(name) }],
1468
1554
  schemas: [...resolvedData.schemas, {
1469
- imports: resolvedData.imports.map((toImport) => ({
1555
+ imports: resolvedData.imports.filter((toImport) => valueImportSet.has(toImport.alias ?? toImport.name)).map((toImport) => ({
1470
1556
  ...toImport,
1471
1557
  values: true
1472
1558
  })),
@@ -1488,13 +1574,23 @@ function combineSchemas({ name, schema, separator: separator$1, context, nullabl
1488
1574
  name,
1489
1575
  context
1490
1576
  });
1577
+ else if (separator$1 === "allOf" && (schema.oneOf || schema.anyOf)) {
1578
+ const siblingCombiner = schema.oneOf ? "oneOf" : "anyOf";
1579
+ resolvedValue = combineSchemas({
1580
+ schema: { [siblingCombiner]: schema[siblingCombiner] },
1581
+ name,
1582
+ separator: siblingCombiner,
1583
+ context,
1584
+ nullable: ""
1585
+ });
1586
+ }
1491
1587
  return {
1492
- value: combineValues({
1588
+ value: dedupeUnionType(combineValues({
1493
1589
  resolvedData,
1494
1590
  separator: separator$1,
1495
1591
  resolvedValue,
1496
1592
  context
1497
- }) + nullable,
1593
+ }) + nullable),
1498
1594
  imports: resolvedValue ? [...resolvedData.imports, ...resolvedValue.imports] : resolvedData.imports,
1499
1595
  schemas: resolvedValue ? [...resolvedData.schemas, ...resolvedValue.schemas] : resolvedData.schemas,
1500
1596
  dependencies: resolvedValue ? [...resolvedData.dependencies, ...resolvedValue.dependencies] : resolvedData.dependencies,
@@ -1506,16 +1602,6 @@ function combineSchemas({ name, schema, separator: separator$1, context, nullabl
1506
1602
  examples: resolveExampleRefs(schema.examples, context)
1507
1603
  };
1508
1604
  }
1509
- const getCombineEnumValue = ({ values, isRef, originalSchema }) => {
1510
- if (values.length === 1) {
1511
- if (isRef[0]) return values[0];
1512
- return `{${getEnumImplementation(values[0])}} as const`;
1513
- }
1514
- return `{${values.map((e, i) => {
1515
- if (isRef[i]) return `...${e},`;
1516
- return getEnumImplementation(e, getEnumNames(originalSchema[i]), getEnumDescriptions(originalSchema[i]));
1517
- }).join("")}} as const`;
1518
- };
1519
1605
 
1520
1606
  //#endregion
1521
1607
  //#region src/getters/keys.ts
@@ -1541,6 +1627,11 @@ function getIndexSignatureKey(item) {
1541
1627
  if (enumValues && enumValues.length > 0) return enumValues.map((val) => `'${val}'`).join(" | ");
1542
1628
  return "string";
1543
1629
  }
1630
+ function getPropertyNamesRecordType(item, valueType) {
1631
+ const enumValues = getPropertyNamesEnum(item);
1632
+ if (!enumValues || enumValues.length === 0) return;
1633
+ return `Partial<Record<${enumValues.map((val) => `'${val}'`).join(" | ")}, ${valueType}>>`;
1634
+ }
1544
1635
  /**
1545
1636
  * Return the output type from an object
1546
1637
  *
@@ -1624,23 +1715,39 @@ function getObject({ item, name, context, nullable, propertyOverrides }) {
1624
1715
  imports: aliasedImports
1625
1716
  });
1626
1717
  const propValue = needsValueImport ? alias : constLiteral ?? alias;
1627
- acc.value += `\n ${doc ? `${doc} ` : ""}${isReadOnly && !context.output.override.suppressReadonlyModifier ? "readonly " : ""}${getKey(key)}${isRequired ? "" : "?"}: ${propValue};`;
1718
+ const finalPropValue = isRequired ? propValue : context.output.override.useNullForOptional === true ? `${propValue} | null` : propValue;
1719
+ acc.value += `\n ${doc ? `${doc} ` : ""}${isReadOnly && !context.output.override.suppressReadonlyModifier ? "readonly " : ""}${getKey(key)}${isRequired ? "" : "?"}: ${finalPropValue};`;
1628
1720
  acc.schemas.push(...resolvedValue.schemas);
1629
1721
  acc.dependencies.push(...resolvedValue.dependencies);
1630
1722
  if (arr.length - 1 === index) {
1631
- if (item.additionalProperties) {
1632
- const keyType$1 = getIndexSignatureKey(item);
1633
- if (isBoolean(item.additionalProperties)) acc.value += `\n [key: ${keyType$1}]: unknown;\n }`;
1634
- else {
1635
- const resolvedValue$1 = resolveValue({
1636
- schema: item.additionalProperties,
1637
- name,
1638
- context
1639
- });
1723
+ if (item.additionalProperties) if (isBoolean(item.additionalProperties)) {
1724
+ const recordType$1 = getPropertyNamesRecordType(item, "unknown");
1725
+ if (recordType$1) {
1726
+ acc.value += "\n}";
1727
+ acc.value += ` & ${recordType$1}`;
1728
+ acc.useTypeAlias = true;
1729
+ } else {
1730
+ const keyType$1 = getIndexSignatureKey(item);
1731
+ acc.value += `\n [key: ${keyType$1}]: unknown;\n }`;
1732
+ }
1733
+ } else {
1734
+ const resolvedValue$1 = resolveValue({
1735
+ schema: item.additionalProperties,
1736
+ name,
1737
+ context
1738
+ });
1739
+ const recordType$1 = getPropertyNamesRecordType(item, resolvedValue$1.value);
1740
+ if (recordType$1) {
1741
+ acc.value += "\n}";
1742
+ acc.value += ` & ${recordType$1}`;
1743
+ acc.useTypeAlias = true;
1744
+ } else {
1745
+ const keyType$1 = getIndexSignatureKey(item);
1640
1746
  acc.value += `\n [key: ${keyType$1}]: ${resolvedValue$1.value};\n}`;
1641
- acc.dependencies.push(...resolvedValue$1.dependencies);
1642
1747
  }
1643
- } else acc.value += "\n}";
1748
+ acc.dependencies.push(...resolvedValue$1.dependencies);
1749
+ }
1750
+ else acc.value += "\n}";
1644
1751
  acc.value += nullable;
1645
1752
  }
1646
1753
  return acc;
@@ -1653,36 +1760,64 @@ function getObject({ item, name, context, nullable, propertyOverrides }) {
1653
1760
  isRef: false,
1654
1761
  schema: {},
1655
1762
  hasReadonlyProps: false,
1763
+ useTypeAlias: false,
1656
1764
  dependencies: [],
1657
1765
  example: item.example,
1658
1766
  examples: resolveExampleRefs(item.examples, context)
1659
1767
  });
1660
1768
  }
1661
1769
  if (item.additionalProperties) {
1662
- const keyType$1 = getIndexSignatureKey(item);
1663
- if (isBoolean(item.additionalProperties)) return {
1664
- value: `{ [key: ${keyType$1}]: unknown }` + nullable,
1665
- imports: [],
1666
- schemas: [],
1667
- isEnum: false,
1668
- type: "object",
1669
- isRef: false,
1670
- hasReadonlyProps: item.readOnly || false,
1671
- dependencies: []
1672
- };
1770
+ if (isBoolean(item.additionalProperties)) {
1771
+ const recordType$2 = getPropertyNamesRecordType(item, "unknown");
1772
+ if (recordType$2) return {
1773
+ value: recordType$2 + nullable,
1774
+ imports: [],
1775
+ schemas: [],
1776
+ isEnum: false,
1777
+ type: "object",
1778
+ isRef: false,
1779
+ hasReadonlyProps: item.readOnly || false,
1780
+ useTypeAlias: true,
1781
+ dependencies: []
1782
+ };
1783
+ return {
1784
+ value: `{ [key: ${getIndexSignatureKey(item)}]: unknown }` + nullable,
1785
+ imports: [],
1786
+ schemas: [],
1787
+ isEnum: false,
1788
+ type: "object",
1789
+ isRef: false,
1790
+ hasReadonlyProps: item.readOnly || false,
1791
+ useTypeAlias: false,
1792
+ dependencies: []
1793
+ };
1794
+ }
1673
1795
  const resolvedValue = resolveValue({
1674
1796
  schema: item.additionalProperties,
1675
1797
  name,
1676
1798
  context
1677
1799
  });
1800
+ const recordType$1 = getPropertyNamesRecordType(item, resolvedValue.value);
1801
+ if (recordType$1) return {
1802
+ value: recordType$1 + nullable,
1803
+ imports: resolvedValue.imports ?? [],
1804
+ schemas: resolvedValue.schemas ?? [],
1805
+ isEnum: false,
1806
+ type: "object",
1807
+ isRef: false,
1808
+ hasReadonlyProps: resolvedValue.hasReadonlyProps,
1809
+ useTypeAlias: true,
1810
+ dependencies: resolvedValue.dependencies
1811
+ };
1678
1812
  return {
1679
- value: `{[key: ${keyType$1}]: ${resolvedValue.value}}` + nullable,
1813
+ value: `{[key: ${getIndexSignatureKey(item)}]: ${resolvedValue.value}}` + nullable,
1680
1814
  imports: resolvedValue.imports ?? [],
1681
1815
  schemas: resolvedValue.schemas ?? [],
1682
1816
  isEnum: false,
1683
1817
  type: "object",
1684
1818
  isRef: false,
1685
1819
  hasReadonlyProps: resolvedValue.hasReadonlyProps,
1820
+ useTypeAlias: false,
1686
1821
  dependencies: resolvedValue.dependencies
1687
1822
  };
1688
1823
  }
@@ -1698,6 +1833,18 @@ function getObject({ item, name, context, nullable, propertyOverrides }) {
1698
1833
  dependencies: []
1699
1834
  };
1700
1835
  const keyType = item.type === "object" ? getIndexSignatureKey(item) : "string";
1836
+ const recordType = getPropertyNamesRecordType(item, "unknown");
1837
+ if (item.type === "object" && recordType) return {
1838
+ value: recordType + nullable,
1839
+ imports: [],
1840
+ schemas: [],
1841
+ isEnum: false,
1842
+ type: "object",
1843
+ isRef: false,
1844
+ hasReadonlyProps: item.readOnly || false,
1845
+ useTypeAlias: true,
1846
+ dependencies: []
1847
+ };
1701
1848
  return {
1702
1849
  value: (item.type === "object" ? `{ [key: ${keyType}]: unknown }` : "unknown") + nullable,
1703
1850
  imports: [],
@@ -1706,6 +1853,7 @@ function getObject({ item, name, context, nullable, propertyOverrides }) {
1706
1853
  type: "object",
1707
1854
  isRef: false,
1708
1855
  hasReadonlyProps: item.readOnly || false,
1856
+ useTypeAlias: false,
1709
1857
  dependencies: []
1710
1858
  };
1711
1859
  }
@@ -1804,10 +1952,15 @@ function getResReqTypes(responsesOrRequests, name, context, defaultType = "unkno
1804
1952
  if (res.content) return Object.entries(res.content).map(([contentType, mediaType], index, arr) => {
1805
1953
  let propName = key ? pascal(name) + pascal(key) : void 0;
1806
1954
  if (propName && arr.length > 1) propName = propName + pascal(getNumberWord(index + 1));
1955
+ let effectivePropName = propName;
1956
+ if (mediaType.schema && isReference(mediaType.schema)) {
1957
+ const { imports } = resolveRef(mediaType.schema, context);
1958
+ if (imports[0]?.name) effectivePropName = imports[0].name;
1959
+ }
1807
1960
  const isFormData = formDataContentTypes.has(contentType);
1808
1961
  const resolvedValue = getResReqContentTypes({
1809
1962
  mediaType,
1810
- propName,
1963
+ propName: effectivePropName,
1811
1964
  context,
1812
1965
  isFormData,
1813
1966
  contentType
@@ -1827,7 +1980,7 @@ function getResReqTypes(responsesOrRequests, name, context, defaultType = "unkno
1827
1980
  return;
1828
1981
  }
1829
1982
  const isFormUrlEncoded = formUrlEncodedContentTypes.has(contentType);
1830
- if (!isFormData && !isFormUrlEncoded || !propName) return {
1983
+ if (!isFormData && !isFormUrlEncoded || !effectivePropName) return {
1831
1984
  ...resolvedValue,
1832
1985
  imports: resolvedValue.imports,
1833
1986
  contentType,
@@ -1835,18 +1988,20 @@ function getResReqTypes(responsesOrRequests, name, context, defaultType = "unkno
1835
1988
  examples: resolveExampleRefs(mediaType.examples, context)
1836
1989
  };
1837
1990
  const formData = isFormData ? getSchemaFormDataAndUrlEncoded({
1838
- name: propName,
1991
+ name: effectivePropName,
1839
1992
  schemaObject: mediaType.schema,
1840
1993
  context,
1841
1994
  isRequestBodyOptional: "required" in res && res.required === false,
1995
+ isRef: true,
1842
1996
  encoding: mediaType.encoding
1843
1997
  }) : void 0;
1844
1998
  const formUrlEncoded = isFormUrlEncoded ? getSchemaFormDataAndUrlEncoded({
1845
- name: propName,
1999
+ name: effectivePropName,
1846
2000
  schemaObject: mediaType.schema,
1847
2001
  context,
1848
2002
  isUrlEncoded: true,
1849
2003
  isRequestBodyOptional: "required" in res && res.required === false,
2004
+ isRef: true,
1850
2005
  encoding: mediaType.encoding
1851
2006
  }) : void 0;
1852
2007
  const additionalImports = getFormDataAdditionalImports({
@@ -2222,7 +2377,7 @@ function resolveDiscriminators(schemas, context) {
2222
2377
  //#endregion
2223
2378
  //#region src/getters/operation.ts
2224
2379
  function getOperationId(operation, route, verb) {
2225
- if (operation.operationId) return operation.operationId;
2380
+ if (isString(operation.operationId)) return operation.operationId;
2226
2381
  return pascal([verb, ...route.split("/").map((p) => sanitize(p, {
2227
2382
  dash: true,
2228
2383
  underscore: "-",
@@ -2313,10 +2468,10 @@ function getParams({ route, pathParams = [], operationId, context, output }) {
2313
2468
  function getProps({ body, queryParams, params, operationName, headers, context }) {
2314
2469
  const bodyProp = {
2315
2470
  name: body.implementation,
2316
- definition: `${body.implementation}${body.isOptional ? "?" : ""}: ${body.definition}`,
2317
- implementation: `${body.implementation}${body.isOptional ? "?" : ""}: ${body.definition}`,
2471
+ definition: `${body.implementation}${body.isOptional && !context.output.optionsParamRequired ? "?" : ""}: ${body.definition}`,
2472
+ implementation: `${body.implementation}${body.isOptional && !context.output.optionsParamRequired ? "?" : ""}: ${body.definition}`,
2318
2473
  default: false,
2319
- required: !body.isOptional,
2474
+ required: !body.isOptional || context.output.optionsParamRequired,
2320
2475
  type: GetterPropType.BODY
2321
2476
  };
2322
2477
  const queryParamsProp = {
@@ -2324,15 +2479,15 @@ function getProps({ body, queryParams, params, operationName, headers, context }
2324
2479
  definition: getQueryParamDefinition(queryParams, context),
2325
2480
  implementation: getQueryParamDefinition(queryParams, context),
2326
2481
  default: false,
2327
- required: isUndefined(queryParams?.isOptional) ? !context.output.allParamsOptional : !queryParams?.isOptional && !context.output.allParamsOptional,
2482
+ required: isUndefined(queryParams?.isOptional) ? !context.output.allParamsOptional || context.output.optionsParamRequired : !queryParams?.isOptional && !context.output.allParamsOptional || context.output.optionsParamRequired,
2328
2483
  type: GetterPropType.QUERY_PARAM
2329
2484
  };
2330
2485
  const headersProp = {
2331
2486
  name: "headers",
2332
- definition: `headers${headers?.isOptional ? "?" : ""}: ${headers?.schema.name}`,
2333
- implementation: `headers${headers?.isOptional ? "?" : ""}: ${headers?.schema.name}`,
2487
+ definition: `headers${headers?.isOptional && !context.output.optionsParamRequired ? "?" : ""}: ${headers?.schema.name}`,
2488
+ implementation: `headers${headers?.isOptional && !context.output.optionsParamRequired ? "?" : ""}: ${headers?.schema.name}`,
2334
2489
  default: false,
2335
- required: isUndefined(headers?.isOptional) ? false : !headers?.isOptional,
2490
+ required: isUndefined(headers?.isOptional) ? false : !headers?.isOptional || context.output.optionsParamRequired,
2336
2491
  type: GetterPropType.HEADER
2337
2492
  };
2338
2493
  let paramGetterProps;
@@ -2340,7 +2495,7 @@ function getProps({ body, queryParams, params, operationName, headers, context }
2340
2495
  const parameterTypeName = `${pascal(operationName)}PathParameters`;
2341
2496
  const name = "pathParams";
2342
2497
  const namedParametersTypeDefinition = `export type ${parameterTypeName} = {\n ${params.map((property) => property.definition).join(",\n ")},\n }`;
2343
- const isOptional = params.every((param) => param.default);
2498
+ const isOptional = context.output.optionsParamRequired || params.every((param) => param.default);
2344
2499
  const implementation = `{ ${params.map((property) => property.default ? `${property.name} = ${property.default}` : property.name).join(", ")} }: ${parameterTypeName}${isOptional ? " = {}" : ""}`;
2345
2500
  const destructured = `{ ${params.map((property) => property.name).join(", ")} }`;
2346
2501
  paramGetterProps = [{
@@ -2371,7 +2526,7 @@ function getProps({ body, queryParams, params, operationName, headers, context }
2371
2526
  function getQueryParamDefinition(queryParams, context) {
2372
2527
  let paramType = queryParams?.schema.name;
2373
2528
  if (OutputClient.ANGULAR === context.output.client) paramType = `DeepNonNullable<${paramType}>`;
2374
- return `params${queryParams?.isOptional || context.output.allParamsOptional ? "?" : ""}: ${paramType}`;
2529
+ return `params${(queryParams?.isOptional || context.output.allParamsOptional) && !context.output.optionsParamRequired ? "?" : ""}: ${paramType}`;
2375
2530
  }
2376
2531
 
2377
2532
  //#endregion
@@ -2480,8 +2635,8 @@ function getResponse({ responses, operationName, context, contentType }) {
2480
2635
  success: [],
2481
2636
  errors: []
2482
2637
  });
2483
- const success = groupedByStatus.success.map(({ value, formData }) => formData ? "Blob" : value).join(" | ");
2484
- const errors = groupedByStatus.errors.map(({ value }) => value).join(" | ");
2638
+ const success = dedupeUnionType(groupedByStatus.success.map(({ value, formData }) => formData ? "Blob" : value).join(" | "));
2639
+ const errors = dedupeUnionType(groupedByStatus.errors.map(({ value }) => value).join(" | "));
2485
2640
  const defaultType = filteredTypes.find(({ key }) => key === "default")?.value;
2486
2641
  return {
2487
2642
  imports,
@@ -2875,18 +3030,20 @@ function generateBodyOptions(body, isFormData, isFormUrlEncoded) {
2875
3030
  if (body.implementation) return `\n ${body.implementation},`;
2876
3031
  return "";
2877
3032
  }
2878
- function generateAxiosOptions({ response, isExactOptionalPropertyTypes, queryParams, headers, requestOptions, hasSignal, isVue, isAngular, paramsSerializer, paramsSerializerOptions }) {
3033
+ function generateAxiosOptions({ response, isExactOptionalPropertyTypes, queryParams, headers, requestOptions, hasSignal, hasSignalParam = false, isVue, isAngular, paramsSerializer, paramsSerializerOptions }) {
2879
3034
  const isRequestOptions = requestOptions !== false;
3035
+ const signalVar = hasSignalParam ? "querySignal" : "signal";
3036
+ const signalProp = hasSignalParam ? `signal: ${signalVar}` : "signal";
2880
3037
  if (!queryParams && !headers && !response.isBlob && response.definition.success !== "string") {
2881
3038
  if (isRequestOptions) return "options";
2882
- if (hasSignal) return isExactOptionalPropertyTypes ? "...(signal ? { signal } : {})" : "signal";
3039
+ if (hasSignal) return isExactOptionalPropertyTypes ? `...(${signalVar} ? { ${signalProp} } : {})` : signalProp;
2883
3040
  return "";
2884
3041
  }
2885
3042
  let value = "";
2886
3043
  if (!isRequestOptions) {
2887
3044
  if (queryParams) value += "\n params,";
2888
3045
  if (headers) value += "\n headers,";
2889
- if (hasSignal) value += isExactOptionalPropertyTypes ? "\n ...(signal ? { signal } : {})," : "\n signal,";
3046
+ if (hasSignal) value += isExactOptionalPropertyTypes ? `\n ...(${signalVar} ? { ${signalProp} } : {}),` : `\n ${signalProp},`;
2890
3047
  }
2891
3048
  if (!isObject(requestOptions) || !requestOptions.hasOwnProperty("responseType")) {
2892
3049
  if (response.isBlob) value += `\n responseType: 'blob',`;
@@ -2903,7 +3060,7 @@ function generateAxiosOptions({ response, isExactOptionalPropertyTypes, queryPar
2903
3060
  if (!isAngular && queryParams && (paramsSerializer || paramsSerializerOptions?.qs)) value += paramsSerializer ? `\n paramsSerializer: ${paramsSerializer.name},` : `\n paramsSerializer: (params) => qs.stringify(params, ${JSON.stringify(paramsSerializerOptions.qs)}),`;
2904
3061
  return value;
2905
3062
  }
2906
- function generateOptions({ route, body, headers, queryParams, response, verb, requestOptions, isFormData, isFormUrlEncoded, isAngular, isExactOptionalPropertyTypes, hasSignal, isVue, paramsSerializer, paramsSerializerOptions }) {
3063
+ function generateOptions({ route, body, headers, queryParams, response, verb, requestOptions, isFormData, isFormUrlEncoded, isAngular, isExactOptionalPropertyTypes, hasSignal, hasSignalParam, isVue, paramsSerializer, paramsSerializerOptions }) {
2907
3064
  const bodyOptions = getIsBodyVerb(verb) ? generateBodyOptions(body, isFormData, isFormUrlEncoded) : "";
2908
3065
  const axiosOptions = generateAxiosOptions({
2909
3066
  response,
@@ -2912,6 +3069,7 @@ function generateOptions({ route, body, headers, queryParams, response, verb, re
2912
3069
  requestOptions,
2913
3070
  isExactOptionalPropertyTypes,
2914
3071
  hasSignal,
3072
+ hasSignalParam,
2915
3073
  isVue: isVue ?? false,
2916
3074
  isAngular: isAngular ?? false,
2917
3075
  paramsSerializer,
@@ -2937,11 +3095,13 @@ function generateQueryParamsAxiosConfig(response, isVue, queryParams) {
2937
3095
  if (response.isBlob) value += `,\n responseType: 'blob'`;
2938
3096
  return value;
2939
3097
  }
2940
- function generateMutatorConfig({ route, body, headers, queryParams, response, verb, isFormData, isFormUrlEncoded, hasSignal, isExactOptionalPropertyTypes, isVue }) {
3098
+ function generateMutatorConfig({ route, body, headers, queryParams, response, verb, isFormData, isFormUrlEncoded, hasSignal, hasSignalParam = false, isExactOptionalPropertyTypes, isVue }) {
2941
3099
  const bodyOptions = getIsBodyVerb(verb) ? generateBodyMutatorConfig(body, isFormData, isFormUrlEncoded) : "";
2942
3100
  const queryParamsOptions = generateQueryParamsAxiosConfig(response, isVue ?? false, queryParams);
2943
3101
  const headerOptions = body.contentType ? `,\n headers: {'Content-Type': '${body.contentType}', ${headers ? "...headers" : ""}}` : headers ? ",\n headers" : "";
2944
- return `{url: \`${route}\`, method: '${verb.toUpperCase()}'${headerOptions}${bodyOptions}${queryParamsOptions}${hasSignal ? `, ${isExactOptionalPropertyTypes ? "...(signal ? { signal }: {})" : "signal"}` : ""}\n }`;
3102
+ const signalVar = hasSignalParam ? "querySignal" : "signal";
3103
+ const signalProp = hasSignalParam ? `signal: ${signalVar}` : "signal";
3104
+ return `{url: \`${route}\`, method: '${verb.toUpperCase()}'${headerOptions}${bodyOptions}${queryParamsOptions}${hasSignal ? `, ${isExactOptionalPropertyTypes ? `...(${signalVar} ? { ${signalProp} }: {})` : signalProp}` : ""}\n }`;
2945
3105
  }
2946
3106
  function generateMutatorRequestOptions(requestOptions, hasSecondArgument) {
2947
3107
  if (!hasSecondArgument) return isObject(requestOptions) ? `{${stringify(requestOptions)?.slice(1, -1)}}` : "";
@@ -3020,10 +3180,11 @@ function generateInterface({ name, schema, context }) {
3020
3180
  context
3021
3181
  });
3022
3182
  const isEmptyObject = scalar.value === "{}";
3183
+ const shouldUseTypeAlias = context?.output.override?.useTypeOverInterfaces || scalar.useTypeAlias;
3023
3184
  let model = "";
3024
3185
  model += jsDoc(schema);
3025
3186
  if (isEmptyObject) model += "// eslint-disable-next-line @typescript-eslint/no-empty-interface\n";
3026
- if (scalar.type === "object" && !context?.output.override?.useTypeOverInterfaces) if (scalar.type === "object" && schema.properties && Object.values(schema.properties).length > 0 && Object.values(schema.properties).every((item) => "const" in item)) {
3187
+ if (scalar.type === "object" && !shouldUseTypeAlias) if (scalar.type === "object" && schema.properties && Object.values(schema.properties).length > 0 && Object.values(schema.properties).every((item) => "const" in item)) {
3027
3188
  const mappedScalarValue = scalar.value.replaceAll(";", ",").replaceAll("?:", ":");
3028
3189
  model += `export const ${name}Value = ${mappedScalarValue} as const;\nexport type ${name} = typeof ${name}Value;\n`;
3029
3190
  } else {
@@ -3175,7 +3336,7 @@ function generateSchemaDefinitions(schemaName, schema, context, suffix) {
3175
3336
  async function generateVerbOptions({ verb, output, operation, route, pathRoute, verbParameters = [], context }) {
3176
3337
  const { responses, requestBody, parameters: operationParameters, tags = [], deprecated, description, summary } = operation;
3177
3338
  const operationId = getOperationId(operation, route, verb);
3178
- const overrideOperation = output.override.operations[operation.operationId];
3339
+ const overrideOperation = output.override.operations[operationId];
3179
3340
  const overrideTag = Object.entries(output.override.tags).reduce((acc, [tag, options]) => tags.includes(tag) && options ? mergeDeep(acc, options) : acc, {});
3180
3341
  const override = mergeDeep(mergeDeep(output.override, overrideTag), overrideOperation);
3181
3342
  const overrideOperationName = overrideOperation?.operationName ?? output.override.operationName;
@@ -3364,7 +3525,7 @@ function fixSchemaImports(schemas, targetSchemaNames, fromPath, toPath, namingCo
3364
3525
  const fileName = conventionName(imp.name, namingConvention);
3365
3526
  return {
3366
3527
  ...imp,
3367
- importPath: join(relativePath, fileName)
3528
+ importPath: joinSafe(relativePath, fileName)
3368
3529
  };
3369
3530
  }
3370
3531
  return imp;
@@ -3495,7 +3656,13 @@ async function writeSchemas({ schemaPath, schemas, target, namingConvention, fil
3495
3656
  const ext = fileExtension.endsWith(".ts") ? fileExtension.slice(0, -3) : fileExtension;
3496
3657
  const conventionNamesSet = new Set(Object.values(schemaGroups).map((group) => conventionName(group[0].name, namingConvention)));
3497
3658
  try {
3498
- const fileContent = `${header}\n${[...conventionNamesSet].map((schemaName) => `export * from './${schemaName}${ext}';`).toSorted((a, b) => a.localeCompare(b)).join("\n")}`;
3659
+ const currentExports = [...conventionNamesSet].map((schemaName) => `export * from './${schemaName}${ext}';`).toSorted((a, b) => a.localeCompare(b));
3660
+ const existingExports = (await fs$1.readFile(schemaFilePath, "utf8")).match(/export\s+\*\s+from\s+['"][^'"]+['"]/g)?.map((statement) => {
3661
+ const match = statement.match(/export\s+\*\s+from\s+['"]([^'"]+)['"]/);
3662
+ if (!match) return void 0;
3663
+ return `export * from '${match[1]}';`;
3664
+ }).filter((statement) => Boolean(statement)) ?? [];
3665
+ const fileContent = `${header}\n${[...new Set([...existingExports, ...currentExports])].toSorted((a, b) => a.localeCompare(b)).join("\n")}`;
3499
3666
  await fs$1.writeFile(schemaFilePath, fileContent, { encoding: "utf8" });
3500
3667
  } catch (error) {
3501
3668
  throw new Error(`Oups... 🍻. An Error occurred while writing schema index file ${schemaFilePath} => ${error}`);
@@ -3510,12 +3677,13 @@ function generateImportsForBuilder(output, imports, relativeSchemasPath) {
3510
3677
  if (!output.indexFiles) return uniqueBy(imports, (x) => x.name).map((i) => {
3511
3678
  const name = conventionName(i.schemaName || i.name, output.namingConvention);
3512
3679
  const suffix = isZodSchemaOutput ? ".zod" : "";
3680
+ const importExtension = output.fileExtension?.replace(/\.ts$/, "") || "";
3513
3681
  return {
3514
3682
  exports: isZodSchemaOutput ? [{
3515
3683
  ...i,
3516
3684
  values: true
3517
3685
  }] : [i],
3518
- dependency: joinSafe(relativeSchemasPath, `${name}${suffix}`)
3686
+ dependency: joinSafe(relativeSchemasPath, `${name}${suffix}${importExtension}`)
3519
3687
  };
3520
3688
  });
3521
3689
  else if (isZodSchemaOutput) return [{
@@ -4080,5 +4248,5 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema
4080
4248
  }
4081
4249
 
4082
4250
  //#endregion
4083
- export { BODY_TYPE_NAME, EnumGeneration, ErrorWithTag, FormDataArrayHandling, GetterPropType, LogLevels, NamingConvention, OutputClient, OutputHttpClient, OutputMockType, OutputMode, PropertySortOrder, RefComponentSuffix, SchemaType, TEMPLATE_TAG_REGEX, URL_REGEX, VERBS_WITH_BODY, Verbs, _filteredVerbs, addDependency, asyncReduce, camel, combineSchemas, compareVersions, conventionName, count, createDebugger, createLogger, createSuccessMessage, createTypeAliasIfNeeded, dynamicImport, escape, fixCrossDirectoryImports, fixRegularSchemaImports, generalJSTypes, generalJSTypesWithArray, generateAxiosOptions, generateBodyMutatorConfig, generateBodyOptions, generateComponentDefinition, generateDependencyImports, generateFormDataAndUrlEncodedFunction, generateImports, generateModelInline, generateModelsInline, generateMutator, generateMutatorConfig, generateMutatorImports, generateMutatorRequestOptions, generateOptions, generateParameterDefinition, generateQueryParamsAxiosConfig, generateSchemasDefinition, generateTarget, generateTargetForTags, generateVerbImports, generateVerbOptions, generateVerbsOptions, getArray, getBody, getDefaultContentType, getEnum, getEnumDescriptions, getEnumImplementation, getEnumNames, getExtension, getFileInfo, getFormDataFieldFileType, getFullRoute, getIsBodyVerb, getKey, getMockFileExtensionByTypeName, getNumberWord, getObject, getOperationId, getOrvalGeneratedTypes, getParameters, getParams, getParamsInPath, getPropertySafe, getProps, getQueryParams, getRefInfo, getResReqTypes, getResponse, getResponseTypeCategory, getRoute, getRouteAsArray, getScalar, getTypedResponse, isBinaryContentType, isBoolean, isDirectory, isFunction, isModule, isNull, isNumber, isNumeric, isObject, isReference, isSchema, isString, isSyntheticDefaultImportsAllow, isUndefined, isUrl, isVerb, jsDoc, jsStringEscape, kebab, keyValuePairsToJsDoc, log, logError, mergeDeep, mismatchArgsMessage, pascal, removeFilesAndEmptyFolders, resolveDiscriminators, resolveExampleRefs, resolveObject, resolveRef, resolveValue, sanitize, snake, sortByPriority, splitSchemasByType, startMessage, stringify, toObjectString, path_exports as upath, upper, writeModelInline, writeModelsInline, writeSchema, writeSchemas, writeSingleMode, writeSplitMode, writeSplitTagsMode, writeTagsMode };
4251
+ export { BODY_TYPE_NAME, EnumGeneration, ErrorWithTag, FormDataArrayHandling, GetterPropType, LogLevels, NamingConvention, OutputClient, OutputHttpClient, OutputMockType, OutputMode, PropertySortOrder, RefComponentSuffix, SchemaType, TEMPLATE_TAG_REGEX, URL_REGEX, VERBS_WITH_BODY, Verbs, _filteredVerbs, addDependency, asyncReduce, camel, combineSchemas, compareVersions, conventionName, count, createDebugger, createLogger, createSuccessMessage, createTypeAliasIfNeeded, dedupeUnionType, dynamicImport, escape, fixCrossDirectoryImports, fixRegularSchemaImports, generalJSTypes, generalJSTypesWithArray, generateAxiosOptions, generateBodyMutatorConfig, generateBodyOptions, generateComponentDefinition, generateDependencyImports, generateFormDataAndUrlEncodedFunction, generateImports, generateModelInline, generateModelsInline, generateMutator, generateMutatorConfig, generateMutatorImports, generateMutatorRequestOptions, generateOptions, generateParameterDefinition, generateQueryParamsAxiosConfig, generateSchemasDefinition, generateTarget, generateTargetForTags, generateVerbImports, generateVerbOptions, generateVerbsOptions, getArray, getBody, getCombinedEnumValue, getDefaultContentType, getEnum, getEnumDescriptions, getEnumImplementation, getEnumNames, getEnumUnionFromSchema, getExtension, getFileInfo, getFormDataFieldFileType, getFullRoute, getIsBodyVerb, getKey, getMockFileExtensionByTypeName, getNumberWord, getObject, getOperationId, getOrvalGeneratedTypes, getParameters, getParams, getParamsInPath, getPropertySafe, getProps, getQueryParams, getRefInfo, getResReqTypes, getResponse, getResponseTypeCategory, getRoute, getRouteAsArray, getScalar, getTypedResponse, isBinaryContentType, isBoolean, isDirectory, isFunction, isModule, isNull, isNumber, isNumeric, isObject, isReference, isSchema, isString, isSyntheticDefaultImportsAllow, isUndefined, isUrl, isVerb, jsDoc, jsStringEscape, kebab, keyValuePairsToJsDoc, log, logError, mergeDeep, mismatchArgsMessage, pascal, removeFilesAndEmptyFolders, resolveDiscriminators, resolveExampleRefs, resolveObject, resolveRef, resolveValue, sanitize, snake, sortByPriority, splitSchemasByType, startMessage, stringify, toObjectString, path_exports as upath, upper, writeModelInline, writeModelsInline, writeSchema, writeSchemas, writeSingleMode, writeSplitMode, writeSplitTagsMode, writeTagsMode };
4084
4252
  //# sourceMappingURL=index.mjs.map