@orval/core 8.15.0 → 8.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { t as __exportAll } from "./chunk-BpYLSNr0.mjs";
1
+ import { t as __exportAll } from "./chunk-8H4AJuhK.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";
@@ -919,6 +919,16 @@ function resolveInstalledVersions(packageJson, fromDir) {
919
919
  return resolved;
920
920
  }
921
921
  //#endregion
922
+ //#region src/utils/schemas-options.ts
923
+ /**
924
+ * Extracts the custom package import specifier from a normalized `schemas`
925
+ * config. Returns `undefined` when `schemas` is a plain string, `false`,
926
+ * `undefined`, or when `importPath` is not set.
927
+ */
928
+ function getSchemasImportPath(schemas) {
929
+ if (isObject(schemas)) return schemas.importPath;
930
+ }
931
+ //#endregion
922
932
  //#region src/utils/sort.ts
923
933
  const sortByPriority = (arr) => arr.toSorted((a, b) => {
924
934
  if (a.default) return 1;
@@ -1089,6 +1099,34 @@ function jsStringEscape(input) {
1089
1099
  });
1090
1100
  }
1091
1101
  /**
1102
+ * Escape a string for embedding inside a single-quoted JS string literal.
1103
+ *
1104
+ * Unlike {@link jsStringEscape}, this escapes only what a string literal
1105
+ * actually needs: backslashes, single quotes, and line terminators. It
1106
+ * deliberately does NOT escape `/` or `*`, which are meaningless inside a
1107
+ * string literal, so escaping them produces "useless escapes" that round-trip
1108
+ * to the same value but trip ESLint's `no-useless-escape` in generated code
1109
+ * (e.g. RegExp pattern literals, see #3337).
1110
+ *
1111
+ * Use {@link jsStringEscape} instead when the value is embedded in a JS comment,
1112
+ * where the comment delimiters must be neutralized.
1113
+ *
1114
+ * @param input String to escape
1115
+ */
1116
+ function jsStringLiteralEscape(input) {
1117
+ return input.replaceAll(/['\\\n\r\u2028\u2029]/g, (character) => {
1118
+ switch (character) {
1119
+ case "'":
1120
+ case "\\": return "\\" + character;
1121
+ case "\n": return String.raw`\n`;
1122
+ case "\r": return String.raw`\r`;
1123
+ case "\u2028": return String.raw`\u2028`;
1124
+ case "\u2029": return String.raw`\u2029`;
1125
+ default: return "";
1126
+ }
1127
+ });
1128
+ }
1129
+ /**
1092
1130
  * Deduplicates a TypeScript union type string.
1093
1131
  * Handles types like "A | B | B" → "A | B" and "null | null" → "null".
1094
1132
  * Only splits on top-level | (not inside {} () [] <> or string literals).
@@ -1282,7 +1320,7 @@ const getUnion = (value, enumName) => {
1282
1320
  };
1283
1321
  function getEnumUnionFromSchema(schema) {
1284
1322
  if (!schema?.enum) return "";
1285
- return schema.enum.filter((val) => val !== null).map((val) => isString(val) ? `'${jsStringEscape(val)}'` : String(val)).join(" | ");
1323
+ return schema.enum.filter((val) => val !== null).map((val) => isString(val) ? `'${escape(val)}'` : String(val)).join(" | ");
1286
1324
  }
1287
1325
  const stripNullUnion = (value) => value.replaceAll(/\s*\|\s*null/g, "").trim();
1288
1326
  const isSpreadableEnumRef = (schema, refName) => {
@@ -1669,13 +1707,13 @@ function getPropertyNamesEnumKeyType(item) {
1669
1707
  if (Array.isArray(propertyNames.enum)) {
1670
1708
  const enumValues = propertyNames.enum.filter((val) => isString(val));
1671
1709
  if (enumValues.length > 0) return {
1672
- value: enumValues.map((val) => `'${jsStringEscape(val)}'`).join(" | "),
1710
+ value: enumValues.map((val) => `'${escape(val)}'`).join(" | "),
1673
1711
  imports: [],
1674
1712
  dependencies: []
1675
1713
  };
1676
1714
  }
1677
1715
  if (isString(propertyNames.const)) return {
1678
- value: `'${jsStringEscape(propertyNames.const)}'`,
1716
+ value: `'${escape(propertyNames.const)}'`,
1679
1717
  imports: [],
1680
1718
  dependencies: []
1681
1719
  };
@@ -1743,28 +1781,54 @@ function getObject({ item, name, context, nullable, formDataContext }) {
1743
1781
  const itemOneOf = schemaItem.oneOf;
1744
1782
  const itemAnyOf = schemaItem.anyOf;
1745
1783
  const itemType = schemaItem.type;
1746
- if (itemAllOf || itemOneOf || itemAnyOf) return combineSchemas({
1747
- schema: schemaItem,
1748
- name,
1749
- separator: itemAllOf ? "allOf" : itemOneOf ? "oneOf" : "anyOf",
1750
- context,
1751
- nullable,
1752
- formDataContext
1753
- });
1754
- if (Array.isArray(itemType)) {
1755
- const typeArray = itemType;
1756
- const baseItem = schemaItem;
1784
+ if (itemAllOf || itemOneOf || itemAnyOf) {
1785
+ const separator = itemAllOf ? "allOf" : itemOneOf ? "oneOf" : "anyOf";
1786
+ const members = separator === "anyOf" ? itemAnyOf : separator === "oneOf" ? itemOneOf : void 0;
1787
+ if (members) {
1788
+ const isNullMember = (member) => {
1789
+ if (isReference(member)) return false;
1790
+ const memberType = member.type;
1791
+ return memberType === "null" || Array.isArray(memberType) && memberType.length === 1 && memberType[0] === "null";
1792
+ };
1793
+ const nonNullMembers = members.filter((member) => !isNullMember(member));
1794
+ const nonNullMember = nonNullMembers[0];
1795
+ const nonNullMemberType = nonNullMember && !isReference(nonNullMember) ? nonNullMember.type : void 0;
1796
+ const nonNullMemberProperties = nonNullMember && !isReference(nonNullMember) ? nonNullMember.properties : void 0;
1797
+ if (members.some(isNullMember) && nonNullMembers.length === 1 && nonNullMember != null && !isReference(nonNullMember) && (nonNullMemberType === "object" || nonNullMemberType == null && nonNullMemberProperties != null) && nonNullMemberProperties != null && Object.keys(nonNullMemberProperties).length > 0) return getObject({
1798
+ item: nonNullMember,
1799
+ name,
1800
+ context,
1801
+ nullable: nullable || " | null",
1802
+ formDataContext
1803
+ });
1804
+ }
1757
1805
  return combineSchemas({
1758
- schema: { anyOf: typeArray.map((type) => ({
1759
- ...baseItem,
1760
- type
1761
- })) },
1806
+ schema: schemaItem,
1762
1807
  name,
1763
- separator: "anyOf",
1808
+ separator,
1764
1809
  context,
1765
- nullable
1810
+ nullable,
1811
+ formDataContext
1766
1812
  });
1767
1813
  }
1814
+ if (Array.isArray(itemType)) {
1815
+ const typeArray = itemType;
1816
+ const nonNullTypes = typeArray.filter((type) => type !== "null");
1817
+ const typeArrayProperties = schemaItem.properties;
1818
+ if (!(nonNullTypes.length === 1 && nonNullTypes[0] === "object" && typeArrayProperties != null && Object.keys(typeArrayProperties).length > 0)) {
1819
+ const baseItem = schemaItem;
1820
+ return combineSchemas({
1821
+ schema: { anyOf: typeArray.map((type) => ({
1822
+ ...baseItem,
1823
+ type
1824
+ })) },
1825
+ name,
1826
+ separator: "anyOf",
1827
+ context,
1828
+ nullable
1829
+ });
1830
+ }
1831
+ }
1768
1832
  const itemProperties = schemaItem.properties;
1769
1833
  if (itemProperties && Object.entries(itemProperties).length > 0) {
1770
1834
  const entries = Object.entries(itemProperties);
@@ -1814,7 +1878,7 @@ function getObject({ item, name, context, nullable, formDataContext }) {
1814
1878
  const hasConst = constValue !== void 0;
1815
1879
  let constLiteral;
1816
1880
  if (!hasConst) constLiteral = void 0;
1817
- else if (isString(constValue)) constLiteral = `'${jsStringEscape(constValue)}'`;
1881
+ else if (isString(constValue)) constLiteral = `'${escape(constValue)}'`;
1818
1882
  else constLiteral = JSON.stringify(constValue);
1819
1883
  const needsValueImport = hasConst && (resolvedValue.isEnum || resolvedValue.type === "enum");
1820
1884
  const usedResolvedValue = !hasConst || needsValueImport;
@@ -1866,13 +1930,13 @@ function getObject({ item, name, context, nullable, formDataContext }) {
1866
1930
  acc.useTypeAlias = true;
1867
1931
  acc.imports.push(...recordType.imports);
1868
1932
  acc.dependencies.push(...recordType.dependencies);
1933
+ acc.imports.push(...resolvedValue.imports);
1934
+ acc.schemas.push(...resolvedValue.schemas);
1935
+ acc.dependencies.push(...resolvedValue.dependencies);
1869
1936
  } else {
1870
1937
  const keyType = getIndexSignatureKey(schemaItem);
1871
- acc.value += `\n [key: ${keyType}]: ${resolvedValue.value};\n}`;
1938
+ acc.value += `\n [key: ${keyType}]: unknown;\n}`;
1872
1939
  }
1873
- acc.imports.push(...resolvedValue.imports);
1874
- acc.schemas.push(...resolvedValue.schemas);
1875
- acc.dependencies.push(...resolvedValue.dependencies);
1876
1940
  }
1877
1941
  else acc.value += "\n}";
1878
1942
  acc.value += nullable;
@@ -1947,7 +2011,7 @@ function getObject({ item, name, context, nullable, formDataContext }) {
1947
2011
  else if (typeof constValue === "boolean") type = "boolean";
1948
2012
  else type = "object";
1949
2013
  return {
1950
- value: typeof constValue === "string" ? `'${jsStringEscape(constValue)}'` : JSON.stringify(constValue),
2014
+ value: typeof constValue === "string" ? `'${escape(constValue)}'` : JSON.stringify(constValue),
1951
2015
  imports: [],
1952
2016
  schemas: [],
1953
2017
  isEnum: false,
@@ -2088,7 +2152,7 @@ function getScalar({ item, name, context, formDataContext }) {
2088
2152
  let value = "string";
2089
2153
  let isEnum = false;
2090
2154
  if (enumItems) {
2091
- value = enumItems.map((enumItem) => isString(enumItem) ? `'${jsStringEscape(enumItem)}'` : `${enumItem}`).filter(Boolean).join(` | `);
2155
+ value = enumItems.map((enumItem) => isString(enumItem) ? `'${escape(enumItem)}'` : `${enumItem}`).filter(Boolean).join(` | `);
2092
2156
  isEnum = true;
2093
2157
  }
2094
2158
  if (!formDataContext?.urlEncoded) {
@@ -2150,7 +2214,7 @@ function getScalar({ item, name, context, formDataContext }) {
2150
2214
  nullable
2151
2215
  });
2152
2216
  if (enumItems) return {
2153
- value: enumItems.map((enumItem) => isString(enumItem) ? `'${jsStringEscape(enumItem)}'` : String(enumItem)).filter(Boolean).join(` | `) + nullable,
2217
+ value: enumItems.map((enumItem) => isString(enumItem) ? `'${escape(enumItem)}'` : String(enumItem)).filter(Boolean).join(` | `) + nullable,
2154
2218
  isEnum: true,
2155
2219
  type: "string",
2156
2220
  imports: [],
@@ -3369,6 +3433,8 @@ function buildBody(filteredBodyTypes, requestBody, operationName, context) {
3369
3433
  const definition = filteredBodyTypes.map(({ value }) => value).join(" | ");
3370
3434
  const nonReadonlyDefinition = filteredBodyTypes.some((x) => x.hasReadonlyProps) && definition && context.output.override.preserveReadonlyRequestBodies !== "preserve" ? `NonReadonly<${definition}>` : definition;
3371
3435
  let implementation = generalJSTypesWithArray.includes(definition.toLowerCase()) || filteredBodyTypes.length > 1 ? camel(operationName) + context.output.override.components.requestBodies.suffix : camel(definition);
3436
+ const overrideName = getRequestBodyExtensionName(requestBody, context);
3437
+ if (overrideName) implementation = camel(overrideName);
3372
3438
  let isOptional = false;
3373
3439
  if (implementation) {
3374
3440
  implementation = sanitize(implementation, {
@@ -3422,6 +3488,14 @@ function getBodiesByContentType({ requestBody, operationName, context, contentTy
3422
3488
  };
3423
3489
  });
3424
3490
  }
3491
+ function getRequestBodyExtensionName(requestBody, context) {
3492
+ let value;
3493
+ if (isReference(requestBody)) {
3494
+ const { schema } = resolveRef(requestBody, context);
3495
+ value = schema?.["x-codegen-request-body-name"];
3496
+ } else value = requestBody?.["x-codegen-request-body-name"];
3497
+ return typeof value === "string" ? value : void 0;
3498
+ }
3425
3499
  const CONTENT_TYPE_SUFFIX_MAP = {
3426
3500
  "application/json": "Json",
3427
3501
  "multipart/form-data": "FormData",
@@ -3453,7 +3527,7 @@ function resolveDiscriminators(schemas, context) {
3453
3527
  } catch {
3454
3528
  subTypeSchema = transformedSchemas[mappingValue];
3455
3529
  }
3456
- if (isBoolean$1(subTypeSchema) || propertyName === void 0) continue;
3530
+ if (!subTypeSchema || isBoolean$1(subTypeSchema) || propertyName === void 0) continue;
3457
3531
  const property = subTypeSchema.properties?.[propertyName];
3458
3532
  if (isBoolean$1(property)) continue;
3459
3533
  const schemaProperty = property && !isReference(property) ? property : void 0;
@@ -4007,6 +4081,8 @@ function getSchemasPath(context) {
4007
4081
  }
4008
4082
  function getSchemaImportPath(refName, context) {
4009
4083
  if (context.output.factoryMethods?.mode === "single") return;
4084
+ const importPathBase = getSchemasImportPath(context.output.schemas);
4085
+ if (importPathBase) return joinSafe(importPathBase, conventionName(refName, context.output.namingConvention));
4010
4086
  let outputDir = context.output.factoryMethods?.outputDirectory;
4011
4087
  let schemasPath = getSchemasPath(context);
4012
4088
  if (context.output.workspace) {
@@ -4134,10 +4210,11 @@ function buildRefPayload(schema, context, parents, imports) {
4134
4210
  }
4135
4211
  function resolveImportPath(mode, refName, context) {
4136
4212
  const baseName = conventionName(refName, context.output.namingConvention);
4213
+ const pkgBase = getSchemasImportPath(context.output.schemas);
4137
4214
  switch (mode) {
4138
- case "split": return `./${baseName}.factory`;
4139
- case "single-split": return `./${conventionName("factoryMethods", context.output.namingConvention)}`;
4140
- case "single": return `./${baseName}`;
4215
+ case "split": return pkgBase ? joinSafe(pkgBase, `${baseName}.factory`) : `./${baseName}.factory`;
4216
+ case "single-split": return pkgBase ? joinSafe(pkgBase, conventionName("factoryMethods", context.output.namingConvention)) : `./${conventionName("factoryMethods", context.output.namingConvention)}`;
4217
+ case "single": return pkgBase ? joinSafe(pkgBase, baseName) : `./${baseName}`;
4141
4218
  }
4142
4219
  }
4143
4220
  function buildAllOfPayload(allOf, context, parents, imports) {
@@ -4467,15 +4544,27 @@ function parseFile(file, name) {
4467
4544
  ecmaVersion: "latest",
4468
4545
  sourceType: "module"
4469
4546
  });
4470
- const foundSpecifier = ast.body.filter((x) => x.type === "ExportNamedDeclaration").flatMap((x) => x.specifiers).find((x) => x.exported.type === "Identifier" && x.exported.name === name && x.local.type === "Identifier");
4471
- if (foundSpecifier && "name" in foundSpecifier.local) {
4547
+ const foundExport = ast.body.filter((x) => x.type === "ExportNamedDeclaration").map((declaration) => ({
4548
+ declaration,
4549
+ specifier: declaration.specifiers.find((specifier) => specifier.exported.type === "Identifier" && specifier.exported.name === name && specifier.local.type === "Identifier")
4550
+ })).find((item) => item.specifier);
4551
+ const foundSpecifier = foundExport?.specifier;
4552
+ if (foundExport && foundSpecifier && "name" in foundSpecifier.local) {
4472
4553
  const exportedFuncName = foundSpecifier.local.name;
4473
- return parseFunction(ast, exportedFuncName);
4554
+ const mutatorInfo = parseFunction(ast, exportedFuncName);
4555
+ if (mutatorInfo) return mutatorInfo;
4556
+ if (foundExport.declaration.source || isImportedBinding(ast, exportedFuncName)) return standardMutatorInfo();
4474
4557
  }
4475
4558
  } catch {
4476
4559
  return;
4477
4560
  }
4478
4561
  }
4562
+ function isImportedBinding(ast, name) {
4563
+ return ast.body.some((node) => {
4564
+ if (node.type !== "ImportDeclaration") return false;
4565
+ return node.specifiers.some((specifier) => "name" in specifier.local && specifier.local.name === name);
4566
+ });
4567
+ }
4479
4568
  function standardMutatorInfo() {
4480
4569
  return { numberOfParams: 1 };
4481
4570
  }
@@ -5655,11 +5744,21 @@ async function writeSchemas({ schemaPath, schemas, target, namingConvention, fil
5655
5744
  }
5656
5745
  }
5657
5746
  //#endregion
5747
+ //#region src/writers/finalize-mock-implementation.ts
5748
+ function getFinalizeMockImplementationOptions(output, mockOutputs) {
5749
+ const strictSchemaTypeNames = [...new Set((Array.isArray(mockOutputs) ? mockOutputs : [mockOutputs]).flatMap((mockOutput) => mockOutput.strictMockSchemaTypeNames ?? []))];
5750
+ return {
5751
+ mockOptions: output.override.mock,
5752
+ strictSchemaTypeNames: strictSchemaTypeNames.length > 0 ? strictSchemaTypeNames : void 0
5753
+ };
5754
+ }
5755
+ //#endregion
5658
5756
  //#region src/writers/generate-imports-for-builder.ts
5659
5757
  function generateImportsForBuilder(output, imports, relativeSchemasPath) {
5758
+ const isPackageImport = isObject(output.schemas) && !!output.schemas.importPath;
5660
5759
  const isZodSchemaOutput = isObject(output.schemas) && output.schemas.type === "zod";
5661
5760
  const schemaFactoryImports = imports.filter((i) => i.schemaFactory);
5662
- const schemaFactoryImportExtension = getImportExtension(output.fileExtension, output.tsconfig);
5761
+ const schemaFactoryImportExtension = isPackageImport ? "" : getImportExtension(output.fileExtension, output.tsconfig);
5663
5762
  const schemaFactoryDeps = schemaFactoryImports.length > 0 ? [{
5664
5763
  exports: uniqueBy(schemaFactoryImports, (entry) => `${entry.name}|${entry.alias ?? ""}`),
5665
5764
  dependency: joinSafe(relativeSchemasPath, `index.faker${schemaFactoryImportExtension}`)
@@ -5676,7 +5775,7 @@ function generateImportsForBuilder(output, imports, relativeSchemasPath) {
5676
5775
  else {
5677
5776
  const importsByDependency = /* @__PURE__ */ new Map();
5678
5777
  for (const schemaImport of imports.filter((i) => !i.importPath)) {
5679
- const dependency = joinSafe(relativeSchemasPath, `${conventionName(isZodSchemaOutput ? schemaImport.name : schemaImport.schemaName ?? schemaImport.name, output.namingConvention)}${isZodSchemaOutput ? ".zod" : ""}${getImportExtension(output.fileExtension, output.tsconfig)}`);
5778
+ const dependency = joinSafe(relativeSchemasPath, `${conventionName(isZodSchemaOutput ? schemaImport.name : schemaImport.schemaName ?? schemaImport.name, output.namingConvention)}${isZodSchemaOutput ? ".zod" : ""}${isPackageImport ? "" : getImportExtension(output.fileExtension, output.tsconfig)}`);
5680
5779
  if (!importsByDependency.has(dependency)) importsByDependency.set(dependency, []);
5681
5780
  importsByDependency.get(dependency)?.push(schemaImport);
5682
5781
  }
@@ -5728,7 +5827,8 @@ function flattenMockOutput$1(full) {
5728
5827
  return {
5729
5828
  type: full.type,
5730
5829
  implementation: full.implementation.function + full.implementation.handler,
5731
- imports: full.imports
5830
+ imports: full.imports,
5831
+ strictMockSchemaTypeNames: full.strictMockSchemaTypeNames
5732
5832
  };
5733
5833
  }
5734
5834
  function generateTarget(builder, options) {
@@ -5763,6 +5863,7 @@ function generateTarget(builder, options) {
5763
5863
  target.mockOutputs.push(acc);
5764
5864
  }
5765
5865
  acc.imports.push(...opMock.imports);
5866
+ if (opMock.strictMockSchemaTypeNames?.length) acc.strictMockSchemaTypeNames = [...new Set([...acc.strictMockSchemaTypeNames ?? [], ...opMock.strictMockSchemaTypeNames])];
5766
5867
  acc.implementation.function += opMock.implementation.function;
5767
5868
  acc.implementation.handler += opMock.implementation.handler;
5768
5869
  if (opMock.implementation.handlerName) {
@@ -5867,9 +5968,11 @@ async function writeSingleMode({ builder, output, projectName, header, needSchem
5867
5968
  const { imports, mockOutputs: rawMockOutputs, implementation, mutators, clientMutators, formData, formUrlEncoded, paramsSerializer, paramsFilter, fetchReviver } = generateTarget(builder, output);
5868
5969
  const mockOutputs = collapseInlineMockOutputs(rawMockOutputs);
5869
5970
  const implementationMock = mockOutputs.map((m) => m.implementation).join("\n\n");
5971
+ const finalizedImplementationMock = builder.finalizeMockImplementation ? builder.finalizeMockImplementation(implementationMock, getFinalizeMockImplementationOptions(output, mockOutputs)) : implementationMock;
5870
5972
  const importsMock = mockOutputs.flatMap((m) => m.imports);
5871
5973
  let data = header;
5872
- const schemasPath = output.schemas ? getRelativeImportPath(path, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : void 0;
5974
+ const schemaCustomImportPath = getSchemasImportPath(output.schemas);
5975
+ const schemasPath = output.schemas ? schemaCustomImportPath ?? getRelativeImportPath(path, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : void 0;
5873
5976
  const isAllowSyntheticDefaultImports = isSyntheticDefaultImportsAllow(output.tsconfig);
5874
5977
  const normalizedImports = imports.filter((imp) => {
5875
5978
  const searchWords = [imp.alias, imp.name].filter((part) => Boolean(part?.length)).map((part) => escapeRegExp(part)).join("|");
@@ -5930,7 +6033,7 @@ async function writeSingleMode({ builder, output, projectName, header, needSchem
5930
6033
  data += `${implementation.trim()}\n`;
5931
6034
  if (mockOutputs.length > 0) {
5932
6035
  data += "\n\n";
5933
- data += implementationMock;
6036
+ data += finalizedImplementationMock;
5934
6037
  }
5935
6038
  await writeGeneratedFile(path, data);
5936
6039
  return [path];
@@ -5949,7 +6052,8 @@ async function writeSplitMode({ builder, output, projectName, header, needSchema
5949
6052
  });
5950
6053
  const { imports, implementation, mockOutputs, mutators, clientMutators, formData, formUrlEncoded, paramsSerializer, paramsFilter, fetchReviver } = generateTarget(builder, output);
5951
6054
  let implementationData = header;
5952
- const relativeSchemasPath = output.schemas ? getRelativeImportPath(targetPath, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : "./" + filename + ".schemas" + extension.replace(/\.ts$/, "");
6055
+ const schemaCustomImportPath = getSchemasImportPath(output.schemas);
6056
+ const relativeSchemasPath = output.schemas ? schemaCustomImportPath ?? getRelativeImportPath(targetPath, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : "./" + filename + ".schemas" + extension.replace(/\.ts$/, "");
5953
6057
  const isAllowSyntheticDefaultImports = isSyntheticDefaultImportsAllow(output.tsconfig);
5954
6058
  const importsForBuilder = generateImportsForBuilder(output, imports, relativeSchemasPath);
5955
6059
  implementationData += builder.imports({
@@ -5990,28 +6094,42 @@ async function writeSplitMode({ builder, output, projectName, header, needSchema
5990
6094
  const implementationPath = nodePath.join(dirname, implementationFilename);
5991
6095
  await writeGeneratedFile(implementationPath, implementationData);
5992
6096
  const mockPaths = [];
6097
+ const writtenMockExtensions = /* @__PURE__ */ new Set();
5993
6098
  for (const mockOutput of mockOutputs) {
5994
6099
  const entry = output.mock.generators.find((g) => !isFunction(g) && g.type === mockOutput.type);
5995
6100
  if (!entry) continue;
5996
6101
  const importsMockForBuilder = generateImportsForBuilder(output, mockOutput.imports, relativeSchemasPath);
5997
6102
  let mockData = header;
6103
+ const finalizedMockImplementation = builder.finalizeMockImplementation ? builder.finalizeMockImplementation(mockOutput.implementation, getFinalizeMockImplementationOptions(output, mockOutput)) : mockOutput.implementation;
5998
6104
  mockData += builder.importsMock({
5999
- implementation: mockOutput.implementation,
6105
+ implementation: finalizedMockImplementation,
6000
6106
  imports: importsMockForBuilder,
6001
6107
  projectName,
6002
6108
  hasSchemaDir: !!output.schemas,
6003
6109
  isAllowSyntheticDefaultImports,
6004
6110
  options: entry
6005
6111
  });
6006
- mockData += `\n${mockOutput.implementation}`;
6007
- const mockPath = nodePath.join(dirname, filename + "." + getMockFileExtensionByTypeName(entry) + extension);
6112
+ mockData += `\n${finalizedMockImplementation}`;
6113
+ const mockExtension = getMockFileExtensionByTypeName(entry);
6114
+ const mockPath = nodePath.join(dirname, filename + "." + mockExtension + extension);
6008
6115
  await writeGeneratedFile(mockPath, mockData);
6009
6116
  mockPaths.push(mockPath);
6117
+ writtenMockExtensions.add(mockExtension);
6118
+ }
6119
+ const indexMockPaths = [];
6120
+ if (output.mock.indexMockFiles) {
6121
+ const importExtension = getImportExtension(output.fileExtension, output.tsconfig);
6122
+ for (const mockExtension of writtenMockExtensions) {
6123
+ const indexMockPath = nodePath.join(dirname, `index.${mockExtension}${extension}`);
6124
+ await writeGeneratedFile(indexMockPath, `export * from './${filename}.${mockExtension}${importExtension}'\n`);
6125
+ indexMockPaths.push(indexMockPath);
6126
+ }
6010
6127
  }
6011
6128
  return [
6012
6129
  implementationPath,
6013
6130
  ...schemasPath ? [schemasPath] : [],
6014
- ...mockPaths
6131
+ ...mockPaths,
6132
+ ...indexMockPaths
6015
6133
  ];
6016
6134
  } catch (error) {
6017
6135
  throw new Error(`Oups... 🍻. An Error occurred while splitting => ${String(error)}`, { cause: error });
@@ -6046,7 +6164,8 @@ function flattenMockOutput(full) {
6046
6164
  return {
6047
6165
  type: full.type,
6048
6166
  implementation: full.implementation.function + full.implementation.handler,
6049
- imports: full.imports
6167
+ imports: full.imports,
6168
+ strictMockSchemaTypeNames: full.strictMockSchemaTypeNames
6050
6169
  };
6051
6170
  }
6052
6171
  function mergeOperationMockOutputs(accMockOutputs, opMockOutputs) {
@@ -6062,6 +6181,7 @@ function mergeOperationMockOutputs(accMockOutputs, opMockOutputs) {
6062
6181
  result.push(acc);
6063
6182
  }
6064
6183
  acc.imports.push(...op.imports);
6184
+ if (op.strictMockSchemaTypeNames?.length) acc.strictMockSchemaTypeNames = [...new Set([...acc.strictMockSchemaTypeNames ?? [], ...op.strictMockSchemaTypeNames])];
6065
6185
  acc.implementation.function += op.implementation.function;
6066
6186
  acc.implementation.handler += op.implementation.handler;
6067
6187
  if (op.implementation.handlerName) {
@@ -6210,7 +6330,8 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
6210
6330
  const { imports, implementation, mockOutputs, mutators, clientMutators, formData, fetchReviver, formUrlEncoded, paramsSerializer, paramsFilter } = target;
6211
6331
  let implementationData = header;
6212
6332
  const importerPath = nodePath.join(dirname, tag, tag + extension);
6213
- const relativeSchemasPath = output.schemas ? getRelativeImportPath(importerPath, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : "../" + filename + ".schemas" + extension.replace(/\.ts$/, "");
6333
+ const schemaCustomImportPath = getSchemasImportPath(output.schemas);
6334
+ const relativeSchemasPath = output.schemas ? schemaCustomImportPath ?? getRelativeImportPath(importerPath, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : "../" + filename + ".schemas" + extension.replace(/\.ts$/, "");
6214
6335
  const tagNames = new Set(tagEntries.map(([t]) => t));
6215
6336
  const serviceSuffix = OutputClient.ANGULAR === output.client ? ".service" : "";
6216
6337
  const importsForBuilder = generateImportsForBuilder(output, imports.map((imp) => {
@@ -6290,16 +6411,17 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
6290
6411
  const entry = output.mock.generators.find((g) => !isFunction(g) && g.type === mockOutput.type);
6291
6412
  if (!entry) continue;
6292
6413
  const importsMockForBuilder = generateImportsForBuilder(output, mockOutput.imports, relativeSchemasPath);
6414
+ const finalizedMockImplementation = builder.finalizeMockImplementation ? builder.finalizeMockImplementation(mockOutput.implementation, getFinalizeMockImplementationOptions(output, mockOutput)) : mockOutput.implementation;
6293
6415
  let mockData = header;
6294
6416
  mockData += builder.importsMock({
6295
- implementation: mockOutput.implementation,
6417
+ implementation: finalizedMockImplementation,
6296
6418
  imports: importsMockForBuilder,
6297
6419
  projectName,
6298
6420
  hasSchemaDir: !!output.schemas,
6299
6421
  isAllowSyntheticDefaultImports,
6300
6422
  options: entry
6301
6423
  });
6302
- mockData += `\n${mockOutput.implementation}`;
6424
+ mockData += `\n${finalizedMockImplementation}`;
6303
6425
  const mockPath = nodePath.join(dirname, tag, tag + "." + getMockFileExtensionByTypeName(entry) + extension);
6304
6426
  await writeGeneratedFile(mockPath, mockData);
6305
6427
  mockPaths.push(mockPath);
@@ -6340,8 +6462,10 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema,
6340
6462
  const mockOutputs = collapseInlineMockOutputs(rawMockOutputs);
6341
6463
  const importsMock = mockOutputs.flatMap((m) => m.imports);
6342
6464
  const implementationMock = mockOutputs.map((m) => m.implementation).join("\n\n");
6465
+ const finalizedImplementationMock = builder.finalizeMockImplementation ? builder.finalizeMockImplementation(implementationMock, getFinalizeMockImplementationOptions(output, mockOutputs)) : implementationMock;
6343
6466
  let data = header;
6344
- const schemasPathRelative = output.schemas ? getRelativeImportPath(targetPath, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : "./" + filename + ".schemas" + extension.replace(/\.ts$/, "");
6467
+ const schemaCustomImportPath = getSchemasImportPath(output.schemas);
6468
+ const schemasPathRelative = output.schemas ? schemaCustomImportPath ?? getRelativeImportPath(targetPath, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : "./" + filename + ".schemas" + extension.replace(/\.ts$/, "");
6345
6469
  const normalizedImports = imports.filter((imp) => {
6346
6470
  const searchWords = [imp.alias, imp.name].filter((part) => Boolean(part?.length)).map((part) => escapeRegExp(part)).join("|");
6347
6471
  if (!searchWords) return false;
@@ -6402,7 +6526,7 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema,
6402
6526
  data += implementation;
6403
6527
  if (mockOutputs.length > 0) {
6404
6528
  data += "\n\n";
6405
- data += implementationMock;
6529
+ data += finalizedImplementationMock;
6406
6530
  }
6407
6531
  const implementationPath = nodePath.join(dirname, `${kebab(tag)}${extension}`);
6408
6532
  await writeGeneratedFile(implementationPath, data);
@@ -6413,6 +6537,6 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema,
6413
6537
  }))).flat();
6414
6538
  }
6415
6539
  //#endregion
6416
- 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, buildDynamicScope, camel, collectReferencedComponents, combineSchemas, compareVersions, conventionName, count, createDebugger, createLogger, createSuccessMessage, createTypeAliasIfNeeded, dedupeUnionType, dynamicAnchorToParamName, dynamicAnchorsToUniqueParamNames, dynamicImport, escape, escapeRegExp, extractBoundAliasInfo, filterByContentType, filteredVerbs, fixCrossDirectoryImports, fixRegularSchemaImports, generalJSTypes, generalJSTypesWithArray, generateAxiosOptions, generateBodyMutatorConfig, generateBodyOptions, generateComponentDefinition, generateDependencyImports, generateFactory, 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, getDynamicAnchorName, 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, isDynamicReference, 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, resolveDynamicRef, resolveExampleRefs, resolveInstalledVersion, resolveInstalledVersions, resolveObject, resolveRef, resolveValue, sanitize, setVerbose, snake, sortByPriority, splitSchemasByType, startMessage, stringify, toObjectString, path_exports as upath, upper, wrapRouteParameters, writeGeneratedFile, writeModelInline, writeModelsInline, writeSchema, writeSchemas, writeSingleMode, writeSplitMode, writeSplitTagsMode, writeTagsMode };
6540
+ 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, buildDynamicScope, camel, collectReferencedComponents, combineSchemas, compareVersions, conventionName, count, createDebugger, createLogger, createSuccessMessage, createTypeAliasIfNeeded, dedupeUnionType, dynamicAnchorToParamName, dynamicAnchorsToUniqueParamNames, dynamicImport, escape, escapeRegExp, extractBoundAliasInfo, filterByContentType, filteredVerbs, fixCrossDirectoryImports, fixRegularSchemaImports, generalJSTypes, generalJSTypesWithArray, generateAxiosOptions, generateBodyMutatorConfig, generateBodyOptions, generateComponentDefinition, generateDependencyImports, generateFactory, 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, getDynamicAnchorName, 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, getSchemasImportPath, getSuccessResponseType, getTypedResponse, getWarningCount, isBinaryContentType, isBinaryScalarSchema, isBoolean, isComponentRef, isDirectory, isDynamicReference, isFakerMock, isFunction, isModule, isMswMock, isNullish, isNumber, isNumeric, isObject, isReference, isSchema, isString, isStringLike, isSyntheticDefaultImportsAllow, isUrl, isVerb, isVerbose, jsDoc, jsStringEscape, jsStringLiteralEscape, kebab, keyValuePairsToJsDoc, log, logError, logVerbose, logWarning, makeRouteSafe, mergeDeep, mismatchArgsMessage, pascal, removeFilesAndEmptyFolders, resetWarnings, resolveDiscriminators, resolveDynamicRef, resolveExampleRefs, resolveInstalledVersion, resolveInstalledVersions, resolveObject, resolveRef, resolveValue, sanitize, setVerbose, snake, sortByPriority, splitSchemasByType, startMessage, stringify, toObjectString, path_exports as upath, upper, wrapRouteParameters, writeGeneratedFile, writeModelInline, writeModelsInline, writeSchema, writeSchemas, writeSingleMode, writeSplitMode, writeSplitTagsMode, writeTagsMode };
6417
6541
 
6418
6542
  //# sourceMappingURL=index.mjs.map