orval 8.16.0 → 8.18.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.
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { c as description, i as startWatcher, l as name, n as loadConfigFile, r as generateSpec, s as normalizeOptions, t as findConfigFile, u as version } from "../config-4RhXX__A.mjs";
2
+ import { c as description, i as startWatcher, l as name, n as loadConfigFile, r as generateSpec, s as normalizeOptions, t as findConfigFile, u as version } from "../config-CXPetEiJ.mjs";
3
3
  import path from "node:path";
4
4
  import { Option, program } from "@commander-js/extra-typings";
5
5
  import { ErrorWithTag, OutputClient, OutputMode, SupportedFormatter, getWarningCount, isString, log, logError, resetWarnings, setVerbose, startMessage } from "@orval/core";
@@ -28,7 +28,7 @@ import fs$2 from "node:fs";
28
28
  import { createJiti } from "jiti";
29
29
  //#region package.json
30
30
  var name = "orval";
31
- var version = "8.16.0";
31
+ var version = "8.18.0";
32
32
  var description = "A swagger client generator for typescript";
33
33
  //#endregion
34
34
  //#region src/client.ts
@@ -173,7 +173,8 @@ const generateOperations = (outputClient = DEFAULT_CLIENT, verbsOptions, options
173
173
  type: isFunction(entry) ? OutputMockType.MSW : entry.type,
174
174
  implementation: generated.implementation,
175
175
  imports: generated.imports,
176
- strictMockSchemaTypeNames: generated.strictMockSchemaTypeNames
176
+ strictMockSchemaTypeNames: generated.strictMockSchemaTypeNames,
177
+ strictMockSchemaKinds: generated.strictMockSchemaKinds
177
178
  };
178
179
  });
179
180
  const hasImplementation = client.implementation.trim().length > 0;
@@ -883,17 +884,27 @@ function createFormData(workspace, formData) {
883
884
  function normalizeSchemasOption(schemas, workspace) {
884
885
  if (!schemas) return;
885
886
  if (isString(schemas)) return normalizePath(schemas, workspace);
886
- if (schemas.importPath !== void 0 && !schemas.importPath) throw new Error(`schemas.importPath must be a non-empty package specifier (e.g. '@acme/models'). Received an empty string.`);
887
- if (schemas.importPath?.trim() === "") throw new Error(`schemas.importPath must be a non-empty package specifier (e.g. '@acme/models'). Received a whitespace-only string.`);
888
- if (schemas.importPath && schemas.importPath.trim() !== schemas.importPath) throw new Error(`schemas.importPath must be a non-empty package specifier (e.g. '@acme/models'). Received a value with leading or trailing whitespace: "${schemas.importPath}"`);
889
- if (schemas.importPath?.startsWith(".")) throw new Error(`schemas.importPath must be a package specifier (e.g. '@acme/models'), not a relative path. Received: "${schemas.importPath}"`);
890
- if (schemas.importPath && (path.isAbsolute(schemas.importPath) || /^[A-Za-z]:[\\/]/.test(schemas.importPath) || schemas.importPath.startsWith("\\\\"))) throw new Error(`schemas.importPath must be a package specifier (e.g. '@acme/models'), not an absolute path. Received: "${schemas.importPath}"`);
887
+ validatePackageSpecifier(schemas.importPath, "schemas.importPath");
891
888
  return {
892
889
  path: normalizePath(schemas.path, workspace),
893
- type: schemas.type,
890
+ type: schemas.type ?? "typescript",
894
891
  importPath: schemas.importPath
895
892
  };
896
893
  }
894
+ /**
895
+ * Validates that a config value is a valid package specifier (bare specifier
896
+ * or sub-path import like `@acme/models` / `@acme/models/fakers`). Rejects
897
+ * empty, whitespace-only, relative (`./`, `../`), and absolute paths with a
898
+ * clear, actionable error message. No-op when the value is `undefined`.
899
+ */
900
+ function validatePackageSpecifier(value, fieldName) {
901
+ if (value === void 0) return;
902
+ if (!value) throw new Error(`\`${fieldName}\` must be a non-empty package specifier (e.g. '@acme/models'). Received an empty string.`);
903
+ if (value.trim() === "") throw new Error(`\`${fieldName}\` must be a non-empty package specifier (e.g. '@acme/models'). Received a whitespace-only string.`);
904
+ if (value.trim() !== value) throw new Error(`\`${fieldName}\` must be a non-empty package specifier (e.g. '@acme/models'). Received a value with leading or trailing whitespace: "${value}"`);
905
+ if (value.startsWith(".")) throw new Error(`\`${fieldName}\` must be a package specifier (e.g. '@acme/models'), not a relative path. Received: "${value}"`);
906
+ if (path.isAbsolute(value) || /^[A-Za-z]:[\\/]/.test(value) || value.startsWith("\\\\")) throw new Error(`\`${fieldName}\` must be a package specifier (e.g. '@acme/models'), not an absolute path. Received: "${value}"`);
907
+ }
897
908
  function normalizeEffectOptions(effect) {
898
909
  return {
899
910
  strict: {
@@ -939,11 +950,14 @@ async function normalizeOptions(optionsExport, workspace = process.cwd(), global
939
950
  };
940
951
  else if (mocksOption && typeof mocksOption === "object") {
941
952
  if (!Array.isArray(mocksOption.generators)) throw new TypeError("mock.generators must be an array of generator entries (e.g. [{ type: \"msw\" }]).");
953
+ const sharedMockPath = mocksOption.path && isString(mocksOption.path) ? normalizePath(mocksOption.path, outputWorkspace) : void 0;
942
954
  mocks = {
943
955
  indexMockFiles: mocksOption.indexMockFiles ?? false,
956
+ path: sharedMockPath,
944
957
  generators: mocksOption.generators.map((m) => isFunction(m) ? m : {
945
958
  ...getDefaultMockOptionsForType(m.type),
946
- ...m
959
+ ...m,
960
+ path: m.path && isString(m.path) ? normalizePath(m.path, outputWorkspace) : sharedMockPath
947
961
  })
948
962
  };
949
963
  }
@@ -952,6 +966,7 @@ async function normalizeOptions(optionsExport, workspace = process.cwd(), global
952
966
  if (isFunction(entry)) continue;
953
967
  if (seenMockTypes.has(entry.type)) throw new Error(`Duplicate mock generator type "${entry.type}". Each type can only appear once in mock.generators.`);
954
968
  seenMockTypes.add(entry.type);
969
+ if (entry.type === OutputMockType.FAKER) validatePackageSpecifier(entry.schemasImportPath, "mock.generators[faker].schemasImportPath");
955
970
  }
956
971
  const defaultFileExtension = ".ts";
957
972
  const defaultSchemaFileExtension = !!outputOptions.schemas && (!isString(outputOptions.schemas) && outputOptions.schemas.type === "zod" || isString(outputOptions.schemas) && (outputOptions.client ?? client) === "zod" && outputOptions.override?.zod?.generateReusableSchemas === true) ? ".zod.ts" : defaultFileExtension;
@@ -970,7 +985,7 @@ async function normalizeOptions(optionsExport, workspace = process.cwd(), global
970
985
  shouldExportQueryKey: true,
971
986
  shouldFilterQueryKey: false,
972
987
  shouldSplitQueryKey: false,
973
- ...normalizeQueryOptions(outputOptions.override?.query, workspace)
988
+ ...normalizeQueryOptions(outputOptions.override?.query, outputWorkspace)
974
989
  };
975
990
  const normalizedOptions = {
976
991
  input: {
@@ -1068,13 +1083,13 @@ async function normalizeOptions(optionsExport, workspace = process.cwd(), global
1068
1083
  response: outputOptions.override?.zod?.coerce?.response ?? false
1069
1084
  },
1070
1085
  preprocess: {
1071
- ...outputOptions.override?.zod?.preprocess?.param ? { param: normalizeMutator(workspace, outputOptions.override.zod.preprocess.param) } : {},
1072
- ...outputOptions.override?.zod?.preprocess?.query ? { query: normalizeMutator(workspace, outputOptions.override.zod.preprocess.query) } : {},
1073
- ...outputOptions.override?.zod?.preprocess?.header ? { header: normalizeMutator(workspace, outputOptions.override.zod.preprocess.header) } : {},
1074
- ...outputOptions.override?.zod?.preprocess?.body ? { body: normalizeMutator(workspace, outputOptions.override.zod.preprocess.body) } : {},
1075
- ...outputOptions.override?.zod?.preprocess?.response ? { response: normalizeMutator(workspace, outputOptions.override.zod.preprocess.response) } : {}
1086
+ ...outputOptions.override?.zod?.preprocess?.param ? { param: normalizeMutator(outputWorkspace, outputOptions.override.zod.preprocess.param) } : {},
1087
+ ...outputOptions.override?.zod?.preprocess?.query ? { query: normalizeMutator(outputWorkspace, outputOptions.override.zod.preprocess.query) } : {},
1088
+ ...outputOptions.override?.zod?.preprocess?.header ? { header: normalizeMutator(outputWorkspace, outputOptions.override.zod.preprocess.header) } : {},
1089
+ ...outputOptions.override?.zod?.preprocess?.body ? { body: normalizeMutator(outputWorkspace, outputOptions.override.zod.preprocess.body) } : {},
1090
+ ...outputOptions.override?.zod?.preprocess?.response ? { response: normalizeMutator(outputWorkspace, outputOptions.override.zod.preprocess.response) } : {}
1076
1091
  },
1077
- ...outputOptions.override?.zod?.params ? { params: normalizeMutator(workspace, outputOptions.override.zod.params) } : {},
1092
+ ...outputOptions.override?.zod?.params ? { params: normalizeMutator(outputWorkspace, outputOptions.override.zod.params) } : {},
1078
1093
  generateEachHttpStatus: outputOptions.override?.zod?.generateEachHttpStatus ?? false,
1079
1094
  useBrandedTypes: outputOptions.override?.zod?.useBrandedTypes ?? false,
1080
1095
  generateReusableSchemas: outputOptions.override?.zod?.generateReusableSchemas ?? false,
@@ -1118,6 +1133,11 @@ async function normalizeOptions(optionsExport, workspace = process.cwd(), global
1118
1133
  };
1119
1134
  if (!normalizedOptions.input.target) throw new Error(styleText("red", `Config requires an input target.`));
1120
1135
  if (!normalizedOptions.output.target && !normalizedOptions.output.schemas) throw new Error(styleText("red", `Config requires an output target or schemas.`));
1136
+ const fakerWithSchemasImportPath = normalizedOptions.output.mock.generators.find((g) => !isFunction(g) && g.type === OutputMockType.FAKER && !!g.schemasImportPath);
1137
+ if (fakerWithSchemasImportPath) {
1138
+ if (fakerWithSchemasImportPath.schemas !== true) throw new Error(styleText("red", `\`mock.generators[faker].schemasImportPath\` requires \`schemas: true\` on the same generator. Schema-level faker factories are only emitted when \`schemas: true\`.`));
1139
+ if (!(isObject(normalizedOptions.output.schemas) && normalizedOptions.output.schemas.importPath)) throw new Error(styleText("red", `\`mock.generators[faker].schemasImportPath\` requires \`schemas.importPath\` to also be set. It overrides the package specifier used for importing schema-level faker factories.`));
1140
+ }
1121
1141
  const usesAngularGenerator = normalizedOptions.output.client === OutputClient.ANGULAR || normalizedOptions.output.client === OutputClient.ANGULAR_QUERY && normalizedOptions.output.httpClient === OutputHttpClient.ANGULAR;
1122
1142
  if (normalizedOptions.output.override.paramsFilter && !usesAngularGenerator) throw new Error(styleText("red", `\`override.paramsFilter\` is only supported by the Angular generator (the \`angular\` client, or \`angular-query\` with \`httpClient: 'angular'\`). It has no effect for other clients — use \`override.paramsSerializer\` instead.`));
1123
1143
  if (!usesAngularGenerator) {
@@ -1695,8 +1715,8 @@ const groupSchemasByFilePath = (schemas) => {
1695
1715
  }
1696
1716
  return [...grouped.values()].map((group) => [...group].toSorted((a, b) => a.filePath.localeCompare(b.filePath, "en", { numeric: true }))).toSorted((a, b) => a[0].filePath.localeCompare(b[0].filePath, "en", { numeric: true }));
1697
1717
  };
1698
- async function writeZodSchemaIndex(schemasPath, fileExtension, header, schemaNames, namingConvention, shouldMergeExisting = false) {
1699
- const importFileExtension = fileExtension.replace(/\.ts$/, "");
1718
+ async function writeZodSchemaIndex(schemasPath, fileExtension, header, schemaNames, namingConvention, shouldMergeExisting = false, tsconfig) {
1719
+ const importFileExtension = getImportExtension(fileExtension, tsconfig);
1700
1720
  const indexPath = path.join(schemasPath, `index.ts`);
1701
1721
  let existingExports = "";
1702
1722
  if (shouldMergeExisting && await fs.pathExists(indexPath)) {
@@ -1803,7 +1823,7 @@ async function writeZodSchemas(builder, schemasPath, fileExtension, header, outp
1803
1823
  const fileContent = generateZodSchemaFileContent(header, schemaGroup);
1804
1824
  await fs.outputFile(schemaGroup[0].filePath, fileContent);
1805
1825
  }
1806
- if (output.indexFiles) await writeZodSchemaIndex(schemasPath, fileExtension, header, groupedSchemasToWrite.map((schemaGroup) => schemaGroup[0].schemaName), output.namingConvention, false);
1826
+ if (output.indexFiles) await writeZodSchemaIndex(schemasPath, fileExtension, header, groupedSchemasToWrite.map((schemaGroup) => schemaGroup[0].schemaName), output.namingConvention, false, output.tsconfig);
1807
1827
  }
1808
1828
  async function writeZodSchemasReusable(builder, schemasPath, fileExtension, header, output, paramsMutator) {
1809
1829
  const isZodV4 = !!output.packageJson && isZodVersionV4(output.packageJson);
@@ -1830,7 +1850,7 @@ async function writeZodSchemasReusable(builder, schemasPath, fileExtension, head
1830
1850
  for (const entry of rewritten) {
1831
1851
  const fileName = conventionName(entry.name, output.namingConvention);
1832
1852
  const filePath = path.join(schemasPath, `${fileName}${fileExtension}`);
1833
- const importExt = fileExtension.replace(/\.ts$/, "");
1853
+ const importExt = getImportExtension(fileExtension, output.tsconfig);
1834
1854
  const rendered = renderReusableSchemaEntry(entry, context);
1835
1855
  const refImports = buildSiblingImports({
1836
1856
  usedRefs: entry.usedRefs,
@@ -1844,7 +1864,7 @@ async function writeZodSchemasReusable(builder, schemasPath, fileExtension, head
1844
1864
  const fileContent = `${header}import { z as zod } from 'zod';\n` + (imports ? `${imports}\n\n` : "\n") + `${rendered.content}\n`;
1845
1865
  await fs.outputFile(filePath, fileContent);
1846
1866
  }
1847
- if (output.indexFiles && rewritten.length > 0) await writeZodSchemaIndex(schemasPath, fileExtension, header, rewritten.map((e) => e.name), output.namingConvention, true);
1867
+ if (output.indexFiles && rewritten.length > 0) await writeZodSchemaIndex(schemasPath, fileExtension, header, rewritten.map((e) => e.name), output.namingConvention, true, output.tsconfig);
1848
1868
  }
1849
1869
  async function writeZodSchemasFromVerbs(verbOptions, schemasPath, fileExtension, header, output, context) {
1850
1870
  const zodContext = context;
@@ -1928,7 +1948,7 @@ async function writeZodSchemasFromVerbs(verbOptions, schemasPath, fileExtension,
1928
1948
  let importStatements;
1929
1949
  if (useReusableSchemas && parsedZodDefinition.usedRefs.size > 0) {
1930
1950
  zodExpression = rewriteSentinelsToDirect(zodExpression);
1931
- const importExt = fileExtension.replace(/\.ts$/, "");
1951
+ const importExt = getImportExtension(fileExtension, output.tsconfig);
1932
1952
  importStatements = [...parsedZodDefinition.usedRefs].filter((refName) => refName !== name).toSorted().map((refName) => {
1933
1953
  return `import { ${refName} } from './${conventionName(refName, output.namingConvention)}${importExt}';`;
1934
1954
  });
@@ -1946,7 +1966,7 @@ async function writeZodSchemasFromVerbs(verbOptions, schemasPath, fileExtension,
1946
1966
  const fileContent = generateZodSchemaFileContent(header, schemaGroup);
1947
1967
  await fs.outputFile(schemaGroup[0].filePath, fileContent);
1948
1968
  }
1949
- if (output.indexFiles && uniqueVerbsSchemas.length > 0) await writeZodSchemaIndex(schemasPath, fileExtension, header, groupedSchemasToWrite.map((schemaGroup) => schemaGroup[0].schemaName), output.namingConvention, true);
1969
+ if (output.indexFiles && uniqueVerbsSchemas.length > 0) await writeZodSchemaIndex(schemasPath, fileExtension, header, groupedSchemasToWrite.map((schemaGroup) => schemaGroup[0].schemaName), output.namingConvention, true, output.tsconfig);
1950
1970
  }
1951
1971
  //#endregion
1952
1972
  //#region src/write-specs.ts
@@ -1986,6 +2006,10 @@ function getHeader(option, info) {
1986
2006
  /**
1987
2007
  * Add re-export of operation schemas from the main schemas index file.
1988
2008
  * Handles the case where the index file doesn't exist (no regular schemas).
2009
+ *
2010
+ * NOTE: `operationSchemasPath` is a directory, so under NodeNext the re-export
2011
+ * would need an `/index.js` suffix rather than a bare `.js`. That directory-
2012
+ * import case is tracked separately and intentionally left as-is here.
1989
2013
  */
1990
2014
  async function addOperationSchemasReExport(schemaPath, operationSchemasPath, header) {
1991
2015
  const schemaIndexPath = path.join(schemaPath, `index.ts`);
@@ -2013,7 +2037,7 @@ async function writeFakerSchemaMocks(builder, options, header) {
2013
2037
  if (!fakerEntry) return;
2014
2038
  const schemasWithDef = builder.schemas.filter((s) => !!s.schema);
2015
2039
  if (schemasWithDef.length === 0) return;
2016
- const { implementation, imports, strictMockSchemaTypeNames } = generateFakerForSchemas(schemasWithDef, {
2040
+ const { implementation, imports, strictMockSchemaTypeNames, strictMockSchemaKinds } = generateFakerForSchemas(schemasWithDef, {
2017
2041
  spec: builder.spec,
2018
2042
  target: builder.target,
2019
2043
  workspace: "",
@@ -2022,7 +2046,8 @@ async function writeFakerSchemaMocks(builder, options, header) {
2022
2046
  if (!implementation.trim()) return;
2023
2047
  const finalizedImplementation = builder.finalizeMockImplementation ? builder.finalizeMockImplementation(implementation, {
2024
2048
  mockOptions: output.override.mock,
2025
- strictSchemaTypeNames: strictMockSchemaTypeNames
2049
+ strictSchemaTypeNames: strictMockSchemaTypeNames,
2050
+ strictMockSchemaKinds
2026
2051
  }) : implementation;
2027
2052
  let filePath;
2028
2053
  let schemaImportPath;
@@ -2171,7 +2196,11 @@ async function writeSpecs(builder, workspace, options, projectName) {
2171
2196
  const workspacePath = output.workspace;
2172
2197
  const indexFile = path.join(workspacePath, "index.ts");
2173
2198
  const mockExtensions = output.mock.generators.map((g) => getMockFileExtensionByTypeName(g));
2174
- const imports = implementationPaths.filter((p) => mockExtensions.length === 0 || !mockExtensions.some((ext) => p.endsWith(`.${ext}.ts`))).map((p) => upath.getRelativeImportPath(indexFile, getFileInfo(p).pathWithoutExtension, true));
2199
+ const importExtension = getImportExtension(output.fileExtension, output.tsconfig);
2200
+ const imports = implementationPaths.filter((p) => mockExtensions.length === 0 || !mockExtensions.some((ext) => p.endsWith(`.${ext}.ts`))).map((p) => {
2201
+ const relative = upath.getRelativeImportPath(indexFile, p, true);
2202
+ return (relative.endsWith(output.fileExtension) ? relative.slice(0, -output.fileExtension.length) : relative.replace(/\.[^/.]+$/, "")) + importExtension;
2203
+ });
2175
2204
  if (output.schemas) {
2176
2205
  const schemasPath = isString(output.schemas) ? output.schemas : output.schemas.path;
2177
2206
  imports.push(upath.getRelativeImportPath(indexFile, getFileInfo(schemasPath).dirname));
@@ -2323,4 +2352,4 @@ async function loadConfigFile(configFilePath) {
2323
2352
  //#endregion
2324
2353
  export { defineConfig as a, description as c, startWatcher as i, name as l, loadConfigFile as n, defineTransformer as o, generateSpec as r, normalizeOptions as s, findConfigFile as t, version as u };
2325
2354
 
2326
- //# sourceMappingURL=config-4RhXX__A.mjs.map
2355
+ //# sourceMappingURL=config-CXPetEiJ.mjs.map