@orval/core 8.15.0 → 8.17.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) ? `'${jsStringLiteralEscape(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) => `'${jsStringLiteralEscape(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: `'${jsStringLiteralEscape(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 = `'${jsStringLiteralEscape(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" ? `'${jsStringLiteralEscape(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) ? `'${jsStringLiteralEscape(enumItem)}'` : `${enumItem}`).filter(Boolean).join(` | `);
2092
2156
  isEnum = true;
2093
2157
  }
2094
2158
  if (!formDataContext?.urlEncoded) {
@@ -2100,7 +2164,7 @@ function getScalar({ item, name, context, formDataContext }) {
2100
2164
  }
2101
2165
  if (context.output.override.useDates && (schemaFormat === "date" || schemaFormat === "date-time")) value = "Date";
2102
2166
  value += nullable;
2103
- if (schemaConst) value = `'${schemaConst}'`;
2167
+ if (schemaConst) value = `'${jsStringLiteralEscape(schemaConst)}'`;
2104
2168
  return {
2105
2169
  value,
2106
2170
  isEnum,
@@ -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) ? `'${jsStringLiteralEscape(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) {
@@ -4380,8 +4457,9 @@ function findRefs(value) {
4380
4457
  if (!value || typeof value !== "object") return [];
4381
4458
  if (Array.isArray(value)) return value.flatMap((item) => findRefs(item));
4382
4459
  const obj = value;
4383
- if (typeof obj.$ref === "string") return [obj.$ref];
4384
- return Object.values(obj).flatMap((val) => findRefs(val));
4460
+ const refs = [];
4461
+ if (typeof obj.$ref === "string") refs.push(obj.$ref);
4462
+ return refs.concat(Object.values(obj).flatMap((val) => findRefs(val)));
4385
4463
  }
4386
4464
  function parseComponentRef(ref) {
4387
4465
  const parts = ref.split("/");
@@ -4467,15 +4545,27 @@ function parseFile(file, name) {
4467
4545
  ecmaVersion: "latest",
4468
4546
  sourceType: "module"
4469
4547
  });
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) {
4548
+ const foundExport = ast.body.filter((x) => x.type === "ExportNamedDeclaration").map((declaration) => ({
4549
+ declaration,
4550
+ specifier: declaration.specifiers.find((specifier) => specifier.exported.type === "Identifier" && specifier.exported.name === name && specifier.local.type === "Identifier")
4551
+ })).find((item) => item.specifier);
4552
+ const foundSpecifier = foundExport?.specifier;
4553
+ if (foundExport && foundSpecifier && "name" in foundSpecifier.local) {
4472
4554
  const exportedFuncName = foundSpecifier.local.name;
4473
- return parseFunction(ast, exportedFuncName);
4555
+ const mutatorInfo = parseFunction(ast, exportedFuncName);
4556
+ if (mutatorInfo) return mutatorInfo;
4557
+ if (foundExport.declaration.source || isImportedBinding(ast, exportedFuncName)) return standardMutatorInfo();
4474
4558
  }
4475
4559
  } catch {
4476
4560
  return;
4477
4561
  }
4478
4562
  }
4563
+ function isImportedBinding(ast, name) {
4564
+ return ast.body.some((node) => {
4565
+ if (node.type !== "ImportDeclaration") return false;
4566
+ return node.specifiers.some((specifier) => "name" in specifier.local && specifier.local.name === name);
4567
+ });
4568
+ }
4479
4569
  function standardMutatorInfo() {
4480
4570
  return { numberOfParams: 1 };
4481
4571
  }
@@ -5655,11 +5745,21 @@ async function writeSchemas({ schemaPath, schemas, target, namingConvention, fil
5655
5745
  }
5656
5746
  }
5657
5747
  //#endregion
5748
+ //#region src/writers/finalize-mock-implementation.ts
5749
+ function getFinalizeMockImplementationOptions(output, mockOutputs) {
5750
+ const strictSchemaTypeNames = [...new Set((Array.isArray(mockOutputs) ? mockOutputs : [mockOutputs]).flatMap((mockOutput) => mockOutput.strictMockSchemaTypeNames ?? []))];
5751
+ return {
5752
+ mockOptions: output.override.mock,
5753
+ strictSchemaTypeNames: strictSchemaTypeNames.length > 0 ? strictSchemaTypeNames : void 0
5754
+ };
5755
+ }
5756
+ //#endregion
5658
5757
  //#region src/writers/generate-imports-for-builder.ts
5659
5758
  function generateImportsForBuilder(output, imports, relativeSchemasPath) {
5759
+ const isPackageImport = isObject(output.schemas) && !!output.schemas.importPath;
5660
5760
  const isZodSchemaOutput = isObject(output.schemas) && output.schemas.type === "zod";
5661
5761
  const schemaFactoryImports = imports.filter((i) => i.schemaFactory);
5662
- const schemaFactoryImportExtension = getImportExtension(output.fileExtension, output.tsconfig);
5762
+ const schemaFactoryImportExtension = isPackageImport ? "" : getImportExtension(output.fileExtension, output.tsconfig);
5663
5763
  const schemaFactoryDeps = schemaFactoryImports.length > 0 ? [{
5664
5764
  exports: uniqueBy(schemaFactoryImports, (entry) => `${entry.name}|${entry.alias ?? ""}`),
5665
5765
  dependency: joinSafe(relativeSchemasPath, `index.faker${schemaFactoryImportExtension}`)
@@ -5676,7 +5776,7 @@ function generateImportsForBuilder(output, imports, relativeSchemasPath) {
5676
5776
  else {
5677
5777
  const importsByDependency = /* @__PURE__ */ new Map();
5678
5778
  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)}`);
5779
+ const dependency = joinSafe(relativeSchemasPath, `${conventionName(isZodSchemaOutput ? schemaImport.name : schemaImport.schemaName ?? schemaImport.name, output.namingConvention)}${isZodSchemaOutput ? ".zod" : ""}${isPackageImport ? "" : getImportExtension(output.fileExtension, output.tsconfig)}`);
5680
5780
  if (!importsByDependency.has(dependency)) importsByDependency.set(dependency, []);
5681
5781
  importsByDependency.get(dependency)?.push(schemaImport);
5682
5782
  }
@@ -5712,6 +5812,21 @@ function collapseInlineMockOutputs(mockOutputs) {
5712
5812
  return mockOutputs.filter((m) => m.type !== OutputMockType.FAKER);
5713
5813
  }
5714
5814
  //#endregion
5815
+ //#region src/writers/mock-utils.ts
5816
+ function getMockDir(entry, mockConfig) {
5817
+ if (!isFunction(entry) && entry.path) return entry.path;
5818
+ return mockConfig.path;
5819
+ }
5820
+ function hasAnyMockPath(mockConfig) {
5821
+ if (mockConfig.path) return true;
5822
+ return mockConfig.generators.some((g) => !isFunction(g) && !!g.path);
5823
+ }
5824
+ function resolveMockSchemasPath(mockFilePath, schemasTarget) {
5825
+ const ext = nodePath.extname(mockFilePath);
5826
+ const targetExt = nodePath.extname(schemasTarget);
5827
+ return getRelativeImportPath(mockFilePath, targetExt === ".schemas" ? schemasTarget + ext : targetExt ? schemasTarget : schemasTarget + ext);
5828
+ }
5829
+ //#endregion
5715
5830
  //#region src/writers/target.ts
5716
5831
  function emptyMockOutputFull$1(type) {
5717
5832
  return {
@@ -5728,7 +5843,8 @@ function flattenMockOutput$1(full) {
5728
5843
  return {
5729
5844
  type: full.type,
5730
5845
  implementation: full.implementation.function + full.implementation.handler,
5731
- imports: full.imports
5846
+ imports: full.imports,
5847
+ strictMockSchemaTypeNames: full.strictMockSchemaTypeNames
5732
5848
  };
5733
5849
  }
5734
5850
  function generateTarget(builder, options) {
@@ -5763,6 +5879,7 @@ function generateTarget(builder, options) {
5763
5879
  target.mockOutputs.push(acc);
5764
5880
  }
5765
5881
  acc.imports.push(...opMock.imports);
5882
+ if (opMock.strictMockSchemaTypeNames?.length) acc.strictMockSchemaTypeNames = [...new Set([...acc.strictMockSchemaTypeNames ?? [], ...opMock.strictMockSchemaTypeNames])];
5766
5883
  acc.implementation.function += opMock.implementation.function;
5767
5884
  acc.implementation.handler += opMock.implementation.handler;
5768
5885
  if (opMock.implementation.handlerName) {
@@ -5860,28 +5977,33 @@ interface TypedResponse<T> extends Response {
5860
5977
  //#region src/writers/single-mode.ts
5861
5978
  async function writeSingleMode({ builder, output, projectName, header, needSchema, generateSchemasInline }) {
5862
5979
  try {
5863
- const { path } = getFileInfo(output.target, {
5980
+ const { path: targetPath, filename, dirname, extension } = getFileInfo(output.target, {
5864
5981
  backupFilename: conventionName(builder.info.title ?? "filename", output.namingConvention),
5865
5982
  extension: output.fileExtension
5866
5983
  });
5867
5984
  const { imports, mockOutputs: rawMockOutputs, implementation, mutators, clientMutators, formData, formUrlEncoded, paramsSerializer, paramsFilter, fetchReviver } = generateTarget(builder, output);
5868
- const mockOutputs = collapseInlineMockOutputs(rawMockOutputs);
5869
- const implementationMock = mockOutputs.map((m) => m.implementation).join("\n\n");
5870
- const importsMock = mockOutputs.flatMap((m) => m.imports);
5871
- 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;
5873
5985
  const isAllowSyntheticDefaultImports = isSyntheticDefaultImportsAllow(output.tsconfig);
5986
+ const shouldDeinlineMocks = hasAnyMockPath(output.mock);
5987
+ const schemaCustomImportPath = getSchemasImportPath(output.schemas);
5988
+ const schemasPath = output.schemas ? schemaCustomImportPath ?? getRelativeImportPath(targetPath, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : void 0;
5989
+ const relativeSchemasPath = schemasPath ?? "./" + filename + ".schemas" + extension.replace(/\.ts$/, "");
5990
+ const schemasTarget = output.schemas ? getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname : targetPath;
5874
5991
  const normalizedImports = imports.filter((imp) => {
5875
5992
  const searchWords = [imp.alias, imp.name].filter((part) => Boolean(part?.length)).map((part) => escapeRegExp(part)).join("|");
5876
5993
  if (!searchWords) return false;
5877
5994
  return new RegExp(String.raw`\b(${searchWords})\b`, "g").test(implementation);
5878
5995
  }).map((imp) => ({ ...imp }));
5879
- for (const mockImport of importsMock) {
5880
- const matchingImport = normalizedImports.find((imp) => imp.name === mockImport.name && (imp.alias ?? "") === (mockImport.alias ?? ""));
5881
- if (!matchingImport) continue;
5882
- if (!!mockImport.values || !!mockImport.isConstant || !!mockImport.default || !!mockImport.namespaceImport || !!mockImport.syntheticDefaultImport) matchingImport.values = true;
5996
+ const collapsedMockOutputs = shouldDeinlineMocks ? [] : collapseInlineMockOutputs(rawMockOutputs);
5997
+ if (!shouldDeinlineMocks) {
5998
+ const importsMock = collapsedMockOutputs.flatMap((m) => m.imports);
5999
+ for (const mockImport of importsMock) {
6000
+ const matchingImport = normalizedImports.find((imp) => imp.name === mockImport.name && (imp.alias ?? "") === (mockImport.alias ?? ""));
6001
+ if (!matchingImport) continue;
6002
+ if (!!mockImport.values || !!mockImport.isConstant || !!mockImport.default || !!mockImport.namespaceImport || !!mockImport.syntheticDefaultImport) matchingImport.values = true;
6003
+ }
5883
6004
  }
5884
- const importsForBuilder = schemasPath ? generateImportsForBuilder(output, normalizedImports, schemasPath) : generateImportsForBuilder(output, normalizedImports.filter((imp) => !!imp.importPath), ".");
6005
+ let data = header;
6006
+ const importsForBuilder = schemasPath ? generateImportsForBuilder(output, normalizedImports, relativeSchemasPath) : generateImportsForBuilder(output, normalizedImports.filter((imp) => !!imp.importPath), ".");
5885
6007
  data += builder.imports({
5886
6008
  client: output.client,
5887
6009
  implementation,
@@ -5895,10 +6017,10 @@ async function writeSingleMode({ builder, output, projectName, header, needSchem
5895
6017
  packageJson: output.packageJson,
5896
6018
  output
5897
6019
  });
5898
- for (const mockOutput of mockOutputs) {
6020
+ if (!shouldDeinlineMocks) for (const mockOutput of collapsedMockOutputs) {
5899
6021
  const entry = output.mock.generators.find((g) => !isFunction(g) && g.type === mockOutput.type);
5900
6022
  const filteredMockImports = mockOutput.imports.filter((impMock) => !normalizedImports.some((imp) => imp.name === impMock.name && (imp.alias ?? "") === (impMock.alias ?? "")));
5901
- const importsMockForBuilder = schemasPath ? generateImportsForBuilder(output, filteredMockImports, schemasPath) : generateImportsForBuilder(output, filteredMockImports.filter((imp) => !!imp.importPath), ".");
6023
+ const importsMockForBuilder = schemasPath ? generateImportsForBuilder(output, filteredMockImports, relativeSchemasPath) : generateImportsForBuilder(output, filteredMockImports.filter((imp) => !!imp.importPath), ".");
5902
6024
  data += builder.importsMock({
5903
6025
  implementation: mockOutput.implementation,
5904
6026
  imports: importsMockForBuilder,
@@ -5928,12 +6050,62 @@ async function writeSingleMode({ builder, output, projectName, header, needSchem
5928
6050
  }
5929
6051
  if (!output.schemas && needSchema) data += generateSchemasInline ? generateSchemasInline() : generateModelsInline(builder.schemas);
5930
6052
  data += `${implementation.trim()}\n`;
5931
- if (mockOutputs.length > 0) {
5932
- data += "\n\n";
5933
- data += implementationMock;
6053
+ if (!shouldDeinlineMocks) {
6054
+ const implementationMock = collapsedMockOutputs.map((m) => m.implementation).join("\n\n");
6055
+ const finalizedImplementationMock = builder.finalizeMockImplementation ? builder.finalizeMockImplementation(implementationMock, getFinalizeMockImplementationOptions(output, collapsedMockOutputs)) : implementationMock;
6056
+ if (collapsedMockOutputs.length > 0) {
6057
+ data += "\n\n";
6058
+ data += finalizedImplementationMock;
6059
+ }
5934
6060
  }
5935
- await writeGeneratedFile(path, data);
5936
- return [path];
6061
+ await writeGeneratedFile(targetPath, data);
6062
+ const extraPaths = [];
6063
+ if (shouldDeinlineMocks) {
6064
+ const seenMockIndexKeys = /* @__PURE__ */ new Set();
6065
+ const writtenMockEntries = [];
6066
+ for (const mockOutput of rawMockOutputs) {
6067
+ const rawEntry = output.mock.generators.find((g) => {
6068
+ if (isFunction(g)) return mockOutput.type === OutputMockType.MSW;
6069
+ return g.type === mockOutput.type;
6070
+ });
6071
+ if (!rawEntry) continue;
6072
+ const mockExtension = isFunction(rawEntry) ? OutputMockType.MSW : getMockFileExtensionByTypeName(rawEntry);
6073
+ const mockDir = getMockDir(rawEntry, output.mock) ?? dirname;
6074
+ const mockFilePath = nodePath.join(mockDir, filename + "." + mockExtension + extension);
6075
+ const mockRelativeSchemasPath = schemaCustomImportPath ?? resolveMockSchemasPath(mockFilePath, schemasTarget);
6076
+ const importsMockForBuilder = schemasPath || mockDir !== dirname ? generateImportsForBuilder(output, mockOutput.imports, mockRelativeSchemasPath) : generateImportsForBuilder(output, mockOutput.imports.filter((imp) => !!imp.importPath), ".");
6077
+ let mockData = header;
6078
+ const finalizedMockImplementation = builder.finalizeMockImplementation ? builder.finalizeMockImplementation(mockOutput.implementation, getFinalizeMockImplementationOptions(output, mockOutput)) : mockOutput.implementation;
6079
+ mockData += builder.importsMock({
6080
+ implementation: finalizedMockImplementation,
6081
+ imports: importsMockForBuilder,
6082
+ projectName,
6083
+ hasSchemaDir: !!output.schemas,
6084
+ isAllowSyntheticDefaultImports,
6085
+ options: isFunction(rawEntry) ? void 0 : rawEntry
6086
+ });
6087
+ mockData += `\n${finalizedMockImplementation}`;
6088
+ await writeGeneratedFile(mockFilePath, mockData);
6089
+ extraPaths.push(mockFilePath);
6090
+ const indexKey = `${mockExtension}::${mockDir}`;
6091
+ if (!seenMockIndexKeys.has(indexKey)) {
6092
+ seenMockIndexKeys.add(indexKey);
6093
+ writtenMockEntries.push({
6094
+ extension: mockExtension,
6095
+ mockDir
6096
+ });
6097
+ }
6098
+ }
6099
+ if (output.mock.indexMockFiles) {
6100
+ const importExtension = getImportExtension(output.fileExtension, output.tsconfig);
6101
+ for (const { extension: mockExt, mockDir } of writtenMockEntries) {
6102
+ const indexMockPath = nodePath.join(mockDir, `index.${mockExt}${extension}`);
6103
+ await writeGeneratedFile(indexMockPath, `export * from './${filename}.${mockExt}${importExtension}'\n`);
6104
+ extraPaths.push(indexMockPath);
6105
+ }
6106
+ }
6107
+ }
6108
+ return [targetPath, ...extraPaths];
5937
6109
  } catch (error) {
5938
6110
  const errorMsg = error instanceof Error ? error.message : "unknown error";
5939
6111
  throw new Error(`Oups... 🍻. An Error occurred while writing file => ${errorMsg}`, { cause: error });
@@ -5949,7 +6121,9 @@ async function writeSplitMode({ builder, output, projectName, header, needSchema
5949
6121
  });
5950
6122
  const { imports, implementation, mockOutputs, mutators, clientMutators, formData, formUrlEncoded, paramsSerializer, paramsFilter, fetchReviver } = generateTarget(builder, output);
5951
6123
  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$/, "");
6124
+ const schemaCustomImportPath = getSchemasImportPath(output.schemas);
6125
+ 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$/, "");
6126
+ const schemasTarget = output.schemas ? getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname : nodePath.join(dirname, filename + ".schemas" + extension.replace(/\.ts$/, ""));
5953
6127
  const isAllowSyntheticDefaultImports = isSyntheticDefaultImportsAllow(output.tsconfig);
5954
6128
  const importsForBuilder = generateImportsForBuilder(output, imports, relativeSchemasPath);
5955
6129
  implementationData += builder.imports({
@@ -5990,28 +6164,55 @@ async function writeSplitMode({ builder, output, projectName, header, needSchema
5990
6164
  const implementationPath = nodePath.join(dirname, implementationFilename);
5991
6165
  await writeGeneratedFile(implementationPath, implementationData);
5992
6166
  const mockPaths = [];
6167
+ const seenMockIndexKeys = /* @__PURE__ */ new Set();
6168
+ const writtenMockEntries = [];
5993
6169
  for (const mockOutput of mockOutputs) {
5994
- const entry = output.mock.generators.find((g) => !isFunction(g) && g.type === mockOutput.type);
5995
- if (!entry) continue;
5996
- const importsMockForBuilder = generateImportsForBuilder(output, mockOutput.imports, relativeSchemasPath);
6170
+ const rawEntry = output.mock.generators.find((g) => {
6171
+ if (isFunction(g)) return mockOutput.type === OutputMockType.MSW;
6172
+ return g.type === mockOutput.type;
6173
+ });
6174
+ if (!rawEntry) continue;
6175
+ const mockExtension = isFunction(rawEntry) ? OutputMockType.MSW : getMockFileExtensionByTypeName(rawEntry);
6176
+ const mockDir = getMockDir(rawEntry, output.mock) ?? dirname;
6177
+ const mockFilePath = nodePath.join(mockDir, filename + "." + mockExtension + extension);
6178
+ const mockRelativeSchemasPath = schemaCustomImportPath ?? resolveMockSchemasPath(mockFilePath, schemasTarget);
6179
+ const importsMockForBuilder = generateImportsForBuilder(output, mockOutput.imports, mockRelativeSchemasPath);
5997
6180
  let mockData = header;
6181
+ const finalizedMockImplementation = builder.finalizeMockImplementation ? builder.finalizeMockImplementation(mockOutput.implementation, getFinalizeMockImplementationOptions(output, mockOutput)) : mockOutput.implementation;
5998
6182
  mockData += builder.importsMock({
5999
- implementation: mockOutput.implementation,
6183
+ implementation: finalizedMockImplementation,
6000
6184
  imports: importsMockForBuilder,
6001
6185
  projectName,
6002
6186
  hasSchemaDir: !!output.schemas,
6003
6187
  isAllowSyntheticDefaultImports,
6004
- options: entry
6188
+ options: isFunction(rawEntry) ? void 0 : rawEntry
6005
6189
  });
6006
- mockData += `\n${mockOutput.implementation}`;
6007
- const mockPath = nodePath.join(dirname, filename + "." + getMockFileExtensionByTypeName(entry) + extension);
6008
- await writeGeneratedFile(mockPath, mockData);
6009
- mockPaths.push(mockPath);
6190
+ mockData += `\n${finalizedMockImplementation}`;
6191
+ await writeGeneratedFile(mockFilePath, mockData);
6192
+ mockPaths.push(mockFilePath);
6193
+ const indexKey = `${mockExtension}::${mockDir}`;
6194
+ if (!seenMockIndexKeys.has(indexKey)) {
6195
+ seenMockIndexKeys.add(indexKey);
6196
+ writtenMockEntries.push({
6197
+ extension: mockExtension,
6198
+ mockDir
6199
+ });
6200
+ }
6201
+ }
6202
+ const indexMockPaths = [];
6203
+ if (output.mock.indexMockFiles) {
6204
+ const importExtension = getImportExtension(output.fileExtension, output.tsconfig);
6205
+ for (const { extension: mockExt, mockDir } of writtenMockEntries) {
6206
+ const indexMockPath = nodePath.join(mockDir, `index.${mockExt}${extension}`);
6207
+ await writeGeneratedFile(indexMockPath, `export * from './${filename}.${mockExt}${importExtension}'\n`);
6208
+ indexMockPaths.push(indexMockPath);
6209
+ }
6010
6210
  }
6011
6211
  return [
6012
6212
  implementationPath,
6013
6213
  ...schemasPath ? [schemasPath] : [],
6014
- ...mockPaths
6214
+ ...mockPaths,
6215
+ ...indexMockPaths
6015
6216
  ];
6016
6217
  } catch (error) {
6017
6218
  throw new Error(`Oups... 🍻. An Error occurred while splitting => ${String(error)}`, { cause: error });
@@ -6046,14 +6247,16 @@ function flattenMockOutput(full) {
6046
6247
  return {
6047
6248
  type: full.type,
6048
6249
  implementation: full.implementation.function + full.implementation.handler,
6049
- imports: full.imports
6250
+ imports: full.imports,
6251
+ strictMockSchemaTypeNames: full.strictMockSchemaTypeNames
6050
6252
  };
6051
6253
  }
6052
6254
  function mergeOperationMockOutputs(accMockOutputs, opMockOutputs) {
6053
6255
  const result = accMockOutputs.map((m) => ({
6054
6256
  type: m.type,
6055
6257
  implementation: { ...m.implementation },
6056
- imports: [...m.imports]
6258
+ imports: [...m.imports],
6259
+ strictMockSchemaTypeNames: m.strictMockSchemaTypeNames ? [...m.strictMockSchemaTypeNames] : void 0
6057
6260
  }));
6058
6261
  for (const op of opMockOutputs) {
6059
6262
  let acc = result.find((m) => m.type === op.type);
@@ -6062,6 +6265,7 @@ function mergeOperationMockOutputs(accMockOutputs, opMockOutputs) {
6062
6265
  result.push(acc);
6063
6266
  }
6064
6267
  acc.imports.push(...op.imports);
6268
+ if (op.strictMockSchemaTypeNames?.length) acc.strictMockSchemaTypeNames = [...new Set([...acc.strictMockSchemaTypeNames ?? [], ...op.strictMockSchemaTypeNames])];
6065
6269
  acc.implementation.function += op.implementation.function;
6066
6270
  acc.implementation.handler += op.implementation.handler;
6067
6271
  if (op.implementation.handlerName) {
@@ -6079,7 +6283,8 @@ function initialMockOutputsForOperation(op) {
6079
6283
  handler: m.implementation.handler,
6080
6284
  handlerName: m.implementation.handlerName ? " " + m.implementation.handlerName + "()" : ""
6081
6285
  },
6082
- imports: [...m.imports]
6286
+ imports: [...m.imports],
6287
+ strictMockSchemaTypeNames: m.strictMockSchemaTypeNames ? [...m.strictMockSchemaTypeNames] : void 0
6083
6288
  }));
6084
6289
  }
6085
6290
  function generateTargetTags(currentAcc, operation) {
@@ -6161,7 +6366,8 @@ function generateTargetForTags(builder, options) {
6161
6366
  handler: m.implementation.handlerName ? m.implementation.handler + header.implementationMock + m.implementation.handlerName + footer.implementationMock : m.implementation.handler,
6162
6367
  handlerName: m.implementation.handlerName
6163
6368
  },
6164
- imports: m.imports
6369
+ imports: m.imports,
6370
+ strictMockSchemaTypeNames: m.strictMockSchemaTypeNames
6165
6371
  }));
6166
6372
  transformed[tag] = {
6167
6373
  implementation: header.implementation + target.implementation + footer.implementation,
@@ -6195,22 +6401,17 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
6195
6401
  });
6196
6402
  const target = generateTargetForTags(builder, output);
6197
6403
  const isAllowSyntheticDefaultImports = isSyntheticDefaultImportsAllow(output.tsconfig);
6198
- if (output.mock.generators.some((g) => isFunction(g))) throw new Error("Function mock generators (ClientMockBuilder) are not supported in tags-split mode. Use typed generators ({ type: \"msw\" } or { type: \"faker\" }).");
6199
- const generatorEntries = output.mock.generators.filter((g) => !isFunction(g));
6200
- const indexFilePathsByType = /* @__PURE__ */ new Map();
6201
- if (output.mock.indexMockFiles) for (const entry of generatorEntries) {
6202
- const ext = getMockFileExtensionByTypeName(entry);
6203
- const indexPath = nodePath.join(dirname, `index.${ext}${extension}`);
6204
- indexFilePathsByType.set(ext, indexPath);
6205
- await fs$1.outputFile(indexPath, "");
6206
- }
6207
- const tagEntries = Object.entries(target);
6404
+ const mockIndexEntries = [];
6405
+ const seenMockIndexKeys = /* @__PURE__ */ new Set();
6406
+ const schemasTarget = output.schemas ? getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname : nodePath.join(dirname, filename + ".schemas" + extension.replace(/\.ts$/, ""));
6407
+ const tagEntries = Object.entries(target).toSorted(([a], [b]) => a.localeCompare(b));
6208
6408
  const generatedFilePathsArray = await Promise.all(tagEntries.map(async ([tag, target]) => {
6209
6409
  try {
6210
6410
  const { imports, implementation, mockOutputs, mutators, clientMutators, formData, fetchReviver, formUrlEncoded, paramsSerializer, paramsFilter } = target;
6211
6411
  let implementationData = header;
6212
6412
  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$/, "");
6413
+ const schemaCustomImportPath = getSchemasImportPath(output.schemas);
6414
+ 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
6415
  const tagNames = new Set(tagEntries.map(([t]) => t));
6215
6416
  const serviceSuffix = OutputClient.ANGULAR === output.client ? ".service" : "";
6216
6417
  const importsForBuilder = generateImportsForBuilder(output, imports.map((imp) => {
@@ -6287,22 +6488,41 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
6287
6488
  await writeGeneratedFile(implementationPath, implementationData);
6288
6489
  const mockPaths = [];
6289
6490
  for (const mockOutput of mockOutputs) {
6290
- const entry = output.mock.generators.find((g) => !isFunction(g) && g.type === mockOutput.type);
6291
- if (!entry) continue;
6292
- const importsMockForBuilder = generateImportsForBuilder(output, mockOutput.imports, relativeSchemasPath);
6491
+ const rawEntry = output.mock.generators.find((g) => {
6492
+ if (isFunction(g)) return mockOutput.type === OutputMockType.MSW;
6493
+ return g.type === mockOutput.type;
6494
+ });
6495
+ if (!rawEntry) continue;
6496
+ const mockExtension = isFunction(rawEntry) ? OutputMockType.MSW : getMockFileExtensionByTypeName(rawEntry);
6497
+ const mockDir = getMockDir(rawEntry, output.mock) ?? dirname;
6498
+ const mockFilePath = nodePath.join(mockDir, tag, tag + "." + mockExtension + extension);
6499
+ const mockRelativeSchemasPath = schemaCustomImportPath ?? resolveMockSchemasPath(mockFilePath, schemasTarget);
6500
+ const importsMockForBuilder = generateImportsForBuilder(output, mockOutput.imports, mockRelativeSchemasPath);
6501
+ const finalizedMockImplementation = builder.finalizeMockImplementation ? builder.finalizeMockImplementation(mockOutput.implementation, getFinalizeMockImplementationOptions(output, mockOutput)) : mockOutput.implementation;
6293
6502
  let mockData = header;
6294
6503
  mockData += builder.importsMock({
6295
- implementation: mockOutput.implementation,
6504
+ implementation: finalizedMockImplementation,
6296
6505
  imports: importsMockForBuilder,
6297
6506
  projectName,
6298
6507
  hasSchemaDir: !!output.schemas,
6299
6508
  isAllowSyntheticDefaultImports,
6300
- options: entry
6509
+ options: isFunction(rawEntry) ? void 0 : rawEntry
6301
6510
  });
6302
- mockData += `\n${mockOutput.implementation}`;
6303
- const mockPath = nodePath.join(dirname, tag, tag + "." + getMockFileExtensionByTypeName(entry) + extension);
6304
- await writeGeneratedFile(mockPath, mockData);
6305
- mockPaths.push(mockPath);
6511
+ mockData += `\n${finalizedMockImplementation}`;
6512
+ await writeGeneratedFile(mockFilePath, mockData);
6513
+ mockPaths.push(mockFilePath);
6514
+ const indexKey = `${mockExtension}::${mockDir}`;
6515
+ let indexEntry = mockIndexEntries.find((e) => e.ext === mockExtension && e.mockDir === mockDir);
6516
+ if (!indexEntry) {
6517
+ indexEntry = {
6518
+ ext: mockExtension,
6519
+ mockDir,
6520
+ tags: []
6521
+ };
6522
+ mockIndexEntries.push(indexEntry);
6523
+ seenMockIndexKeys.add(indexKey);
6524
+ }
6525
+ if (!indexEntry.tags.includes(tag)) indexEntry.tags.push(tag);
6306
6526
  }
6307
6527
  return [
6308
6528
  implementationPath,
@@ -6313,17 +6533,11 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
6313
6533
  throw new Error(`Oups... 🍻. An Error occurred while splitting tag ${tag} => ${String(error)}`, { cause: error });
6314
6534
  }
6315
6535
  }));
6316
- if (output.mock.indexMockFiles) for (const entry of generatorEntries) {
6317
- const ext = getMockFileExtensionByTypeName(entry);
6318
- const indexFilePath = indexFilePathsByType.get(ext);
6319
- if (!indexFilePath) continue;
6320
- const indexContent = tagEntries.map(([tag]) => {
6321
- const localMockPath = joinSafe("./", tag, tag + "." + ext);
6322
- return ext === OutputMockType.MSW ? `export { get${pascal(tag)}Mock } from '${localMockPath}'\n` : `export * from '${localMockPath}'\n`;
6323
- }).join("");
6324
- await fs$1.appendFile(indexFilePath, indexContent);
6325
- }
6326
- return [...new Set([...indexFilePathsByType.values(), ...generatedFilePathsArray.flat()])];
6536
+ if (output.mock.indexMockFiles) for (const { ext, mockDir, tags } of mockIndexEntries) await writeGeneratedFile(nodePath.join(mockDir, `index.${ext}${extension}`), tags.toSorted((a, b) => a.localeCompare(b)).map((tag) => {
6537
+ const localMockPath = joinSafe("./", tag, tag + "." + ext);
6538
+ return ext === OutputMockType.MSW ? `export { get${pascal(tag)}Mock } from '${localMockPath}'\n` : `export * from '${localMockPath}'\n`;
6539
+ }).join(""));
6540
+ return [...new Set([...output.mock.indexMockFiles ? mockIndexEntries.map(({ mockDir, ext }) => nodePath.join(mockDir, `index.${ext}${extension}`)) : [], ...generatedFilePathsArray.flat()])];
6327
6541
  }
6328
6542
  //#endregion
6329
6543
  //#region src/writers/tags-mode.ts
@@ -6334,23 +6548,30 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema,
6334
6548
  });
6335
6549
  const target = generateTargetForTags(builder, output);
6336
6550
  const isAllowSyntheticDefaultImports = isSyntheticDefaultImportsAllow(output.tsconfig);
6337
- return (await Promise.all(Object.entries(target).map(async ([tag, target]) => {
6551
+ const shouldDeinlineMocks = hasAnyMockPath(output.mock);
6552
+ const mockIndexEntries = [];
6553
+ const seenMockIndexKeys = /* @__PURE__ */ new Set();
6554
+ const schemaCustomImportPath = getSchemasImportPath(output.schemas);
6555
+ 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$/, "");
6556
+ const schemasTarget = output.schemas ? getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname : nodePath.join(dirname, filename + ".schemas" + extension.replace(/\.ts$/, ""));
6557
+ const tagEntries = Object.entries(target).toSorted(([a], [b]) => a.localeCompare(b));
6558
+ const generatedFilePathsArray = await Promise.all(tagEntries.map(async ([tag, target]) => {
6338
6559
  try {
6339
6560
  const { imports, implementation, mockOutputs: rawMockOutputs, mutators, clientMutators, formData, formUrlEncoded, fetchReviver, paramsSerializer, paramsFilter } = target;
6340
- const mockOutputs = collapseInlineMockOutputs(rawMockOutputs);
6341
- const importsMock = mockOutputs.flatMap((m) => m.imports);
6342
- const implementationMock = mockOutputs.map((m) => m.implementation).join("\n\n");
6343
- 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$/, "");
6345
6561
  const normalizedImports = imports.filter((imp) => {
6346
6562
  const searchWords = [imp.alias, imp.name].filter((part) => Boolean(part?.length)).map((part) => escapeRegExp(part)).join("|");
6347
6563
  if (!searchWords) return false;
6348
6564
  return new RegExp(String.raw`\b(${searchWords})\b`, "g").test(implementation);
6349
6565
  }).map((imp) => ({ ...imp }));
6350
- for (const mockImport of importsMock) {
6351
- const matchingImport = normalizedImports.find((imp) => imp.name === mockImport.name && (imp.alias ?? "") === (mockImport.alias ?? ""));
6352
- if (!matchingImport) continue;
6353
- if (!!mockImport.values || !!mockImport.isConstant || !!mockImport.default || !!mockImport.namespaceImport || !!mockImport.syntheticDefaultImport) matchingImport.values = true;
6566
+ const collapsedMockOutputs = shouldDeinlineMocks ? [] : collapseInlineMockOutputs(rawMockOutputs);
6567
+ let data = header;
6568
+ if (!shouldDeinlineMocks) {
6569
+ const importsMock = collapsedMockOutputs.flatMap((m) => m.imports);
6570
+ for (const mockImport of importsMock) {
6571
+ const matchingImport = normalizedImports.find((imp) => imp.name === mockImport.name && (imp.alias ?? "") === (mockImport.alias ?? ""));
6572
+ if (!matchingImport) continue;
6573
+ if (!!mockImport.values || !!mockImport.isConstant || !!mockImport.default || !!mockImport.namespaceImport || !!mockImport.syntheticDefaultImport) matchingImport.values = true;
6574
+ }
6354
6575
  }
6355
6576
  const importsForBuilder = generateImportsForBuilder(output, normalizedImports, schemasPathRelative);
6356
6577
  data += builder.imports({
@@ -6366,7 +6587,7 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema,
6366
6587
  packageJson: output.packageJson,
6367
6588
  output
6368
6589
  });
6369
- for (const mockOutput of mockOutputs) {
6590
+ if (!shouldDeinlineMocks) for (const mockOutput of collapsedMockOutputs) {
6370
6591
  const entry = output.mock.generators.find((g) => !isFunction(g) && g.type === mockOutput.type);
6371
6592
  const importsMockForBuilder = generateImportsForBuilder(output, mockOutput.imports.filter((impMock) => !normalizedImports.some((imp) => imp.name === impMock.name && (imp.alias ?? "") === (impMock.alias ?? ""))), schemasPathRelative);
6372
6593
  data += builder.importsMock({
@@ -6400,19 +6621,75 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema,
6400
6621
  data += "\n";
6401
6622
  }
6402
6623
  data += implementation;
6403
- if (mockOutputs.length > 0) {
6404
- data += "\n\n";
6405
- data += implementationMock;
6624
+ if (!shouldDeinlineMocks) {
6625
+ const implementationMock = collapsedMockOutputs.map((m) => m.implementation).join("\n\n");
6626
+ const finalizedImplementationMock = builder.finalizeMockImplementation ? builder.finalizeMockImplementation(implementationMock, getFinalizeMockImplementationOptions(output, collapsedMockOutputs)) : implementationMock;
6627
+ if (collapsedMockOutputs.length > 0) {
6628
+ data += "\n\n";
6629
+ data += finalizedImplementationMock;
6630
+ }
6406
6631
  }
6407
- const implementationPath = nodePath.join(dirname, `${kebab(tag)}${extension}`);
6632
+ const kebabTag = kebab(tag);
6633
+ const implementationPath = nodePath.join(dirname, `${kebabTag}${extension}`);
6408
6634
  await writeGeneratedFile(implementationPath, data);
6409
- return [implementationPath, ...schemasPath ? [schemasPath] : []];
6635
+ const extraPaths = [];
6636
+ if (shouldDeinlineMocks) for (const mockOutput of rawMockOutputs) {
6637
+ const rawEntry = output.mock.generators.find((g) => {
6638
+ if (isFunction(g)) return mockOutput.type === OutputMockType.MSW;
6639
+ return g.type === mockOutput.type;
6640
+ });
6641
+ if (!rawEntry) continue;
6642
+ const mockExtension = isFunction(rawEntry) ? OutputMockType.MSW : getMockFileExtensionByTypeName(rawEntry);
6643
+ const mockDir = getMockDir(rawEntry, output.mock) ?? dirname;
6644
+ const mockFilePath = nodePath.join(mockDir, kebabTag, kebabTag + "." + mockExtension + extension);
6645
+ const mockRelativeSchemasPath = schemaCustomImportPath ?? resolveMockSchemasPath(mockFilePath, schemasTarget);
6646
+ const importsMockForBuilder = generateImportsForBuilder(output, mockOutput.imports, mockRelativeSchemasPath);
6647
+ let mockData = header;
6648
+ const finalizedMockImplementation = builder.finalizeMockImplementation ? builder.finalizeMockImplementation(mockOutput.implementation, getFinalizeMockImplementationOptions(output, mockOutput)) : mockOutput.implementation;
6649
+ mockData += builder.importsMock({
6650
+ implementation: finalizedMockImplementation,
6651
+ imports: importsMockForBuilder,
6652
+ projectName,
6653
+ hasSchemaDir: !!output.schemas,
6654
+ isAllowSyntheticDefaultImports,
6655
+ options: isFunction(rawEntry) ? void 0 : rawEntry
6656
+ });
6657
+ mockData += `\n${finalizedMockImplementation}`;
6658
+ await writeGeneratedFile(mockFilePath, mockData);
6659
+ extraPaths.push(mockFilePath);
6660
+ const indexKey = `${mockExtension}::${mockDir}`;
6661
+ let indexEntry = mockIndexEntries.find((e) => e.ext === mockExtension && e.mockDir === mockDir);
6662
+ if (!indexEntry) {
6663
+ indexEntry = {
6664
+ ext: mockExtension,
6665
+ mockDir,
6666
+ tags: []
6667
+ };
6668
+ mockIndexEntries.push(indexEntry);
6669
+ seenMockIndexKeys.add(indexKey);
6670
+ }
6671
+ if (!indexEntry.tags.includes(kebabTag)) indexEntry.tags.push(kebabTag);
6672
+ }
6673
+ return [
6674
+ implementationPath,
6675
+ ...schemasPath ? [schemasPath] : [],
6676
+ ...extraPaths
6677
+ ];
6410
6678
  } catch (error) {
6411
6679
  throw new Error(`Oups... 🍻. An Error occurred while writing tag ${tag} => ${String(error)}`, { cause: error });
6412
6680
  }
6413
- }))).flat();
6681
+ }));
6682
+ if (shouldDeinlineMocks && output.mock.indexMockFiles) for (const { ext, mockDir, tags } of mockIndexEntries) {
6683
+ const indexPath = nodePath.join(mockDir, `index.${ext}${extension}`);
6684
+ await writeGeneratedFile(indexPath, tags.toSorted((a, b) => a.localeCompare(b)).map((kebabTag) => {
6685
+ const localMockPath = joinSafe("./", kebabTag, kebabTag + "." + ext);
6686
+ return ext === OutputMockType.MSW ? `export { get${pascal(kebabTag)}Mock } from '${localMockPath}'\n` : `export * from '${localMockPath}'\n`;
6687
+ }).join(""));
6688
+ generatedFilePathsArray.push([indexPath]);
6689
+ }
6690
+ return generatedFilePathsArray.flat();
6414
6691
  }
6415
6692
  //#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 };
6693
+ 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
6694
 
6418
6695
  //# sourceMappingURL=index.mjs.map