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.
package/dist/bin/orval.mjs
CHANGED
|
@@ -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-
|
|
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.
|
|
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
|
-
|
|
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,
|
|
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(
|
|
1072
|
-
...outputOptions.override?.zod?.preprocess?.query ? { query: normalizeMutator(
|
|
1073
|
-
...outputOptions.override?.zod?.preprocess?.header ? { header: normalizeMutator(
|
|
1074
|
-
...outputOptions.override?.zod?.preprocess?.body ? { body: normalizeMutator(
|
|
1075
|
-
...outputOptions.override?.zod?.preprocess?.response ? { response: normalizeMutator(
|
|
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(
|
|
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
|
|
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.
|
|
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.
|
|
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
|
|
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-
|
|
2355
|
+
//# sourceMappingURL=config-CXPetEiJ.mjs.map
|