orval 8.22.0 → 8.23.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-18E5SVPo.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";
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import { DefaultTag, FormDataArrayHandling, GetterPropType, NamingConvention, OutputClient, OutputHttpClient, OutputMockType, OutputMode, PropertySortOrder, RefComponentSuffix, SupportedFormatter, asyncReduce, buildDynamicScope, buildSchemaTagMap, collectReferencedComponents, conventionName, createSuccessMessage, dynamicImport, fixCrossDirectoryImports, fixRegularSchemaImports, generateComponentDefinition, generateDependencyImports, generateMutator, generateParameterDefinition, generateSchemasDefinition, generateVerbsOptions, getBaseUrlRuntimeImports, getFileInfo, getFullRoute, getImportExtension, getMockFileExtensionByTypeName, getRefInfo, getRoute, isBoolean, isComponentRef, isFunction, isNullish, isObject, isReference, isString, isUrl, jsDoc, kebab, log, logError, logVerbose, logWarning, pascal, removeFilesAndEmptyFolders, resolveInstalledVersions, resolveRef, resolveValue, splitSchemasByType, upath, writeGeneratedFile, writeSchemas, writeSchemasTagsSplit, writeSingleMode, writeSplitMode, writeSplitTagsMode, writeTagsMode } from "@orval/core";
|
|
3
|
+
import { DefaultTag, FormDataArrayHandling, GetterPropType, NamingConvention, OutputClient, OutputHttpClient, OutputMockType, OutputMode, PropertySortOrder, RefComponentSuffix, SupportedFormatter, asyncReduce, buildDynamicScope, buildSchemaTagMap, collectReferencedComponents, conventionName, createSuccessMessage, dynamicImport, fixCrossDirectoryImports, fixRegularSchemaImports, generateComponentDefinition, generateDependencyImports, generateMutator, generateParameterDefinition, generateSchemasDefinition, generateVerbsOptions, getBaseUrlRuntimeImports, getFileInfo, getFullRoute, getImportExtension, getMockFileExtensionByTypeName, getRefInfo, getRoute, isBoolean, isComponentRef, isFunction, isNullish, isObject, isReference, isString, isUrl, jsDoc, kebab, log, logError, logVerbose, logWarning, pascal, removeFilesAndEmptyFolders, resolveInstalledVersions, resolveRef, resolveValue, splitSchemasByType, upath, writeGeneratedFile, writeSchemas, writeSchemasTagsSplit, writeSingleMode, writeSplitMode, writeSplitTagsMode, writeTagsMode, writeTagsOperationsMode, writeTagsOperationsSplitMode } from "@orval/core";
|
|
4
4
|
import { bundle } from "@scalar/json-magic/bundle";
|
|
5
5
|
import { fetchUrls, parseJson, parseYaml, readFiles } from "@scalar/json-magic/bundle/plugins/node";
|
|
6
6
|
import { upgrade, validate } from "@scalar/openapi-parser";
|
|
7
7
|
import fs, { access, readFile } from "node:fs/promises";
|
|
8
|
-
import { isNullish as isNullish$1, pick
|
|
8
|
+
import { isNullish as isNullish$1, pick } from "remeda";
|
|
9
9
|
import jsYaml from "js-yaml";
|
|
10
10
|
import * as mock from "@orval/mock";
|
|
11
11
|
import { dedupeStrictMockTypeDeclarations, generateFakerForSchemas, generateMockImports, getDefaultMockOptionsForType } from "@orval/mock";
|
|
@@ -29,7 +29,7 @@ import { parseArgsStringToArgv } from "string-argv";
|
|
|
29
29
|
import { createJiti } from "jiti";
|
|
30
30
|
//#region package.json
|
|
31
31
|
var name = "orval";
|
|
32
|
-
var version = "8.
|
|
32
|
+
var version = "8.23.0";
|
|
33
33
|
var description = "A swagger client generator for typescript";
|
|
34
34
|
//#endregion
|
|
35
35
|
//#region src/client.ts
|
|
@@ -545,6 +545,7 @@ function createFormData(workspace, formData) {
|
|
|
545
545
|
function normalizeSchemasOption(schemas, workspace) {
|
|
546
546
|
if (!schemas) return;
|
|
547
547
|
if (isString(schemas)) return normalizePath(schemas, workspace);
|
|
548
|
+
if (!isString(schemas.path) || schemas.path.trim() === "") throw new Error(styleText("red", `\`schemas.path\` is required when \`schemas\` is an object (e.g. \`schemas: { path: './model', type: 'zod' }\`). To generate schemas alongside the target instead, omit \`schemas\` or set \`schemas: false\`.`));
|
|
548
549
|
validatePackageSpecifier(schemas.importPath, "schemas.importPath");
|
|
549
550
|
return {
|
|
550
551
|
path: normalizePath(schemas.path, workspace),
|
|
@@ -607,7 +608,8 @@ function normalizeEffectOptions(effect) {
|
|
|
607
608
|
response: effect?.generate?.response ?? true
|
|
608
609
|
},
|
|
609
610
|
generateEachHttpStatus: effect?.generateEachHttpStatus ?? false,
|
|
610
|
-
useBrandedTypes: effect?.useBrandedTypes ?? false
|
|
611
|
+
useBrandedTypes: effect?.useBrandedTypes ?? false,
|
|
612
|
+
exactOptional: effect?.exactOptional ?? false
|
|
611
613
|
};
|
|
612
614
|
}
|
|
613
615
|
async function normalizeOptions(optionsExport, workspace = process.cwd(), globalOptions = {}) {
|
|
@@ -784,6 +786,7 @@ async function normalizeOptions(optionsExport, workspace = process.cwd(), global
|
|
|
784
786
|
generateReusableSchemas: outputOptions.override?.zod?.generateReusableSchemas ?? false,
|
|
785
787
|
generateMeta: outputOptions.override?.zod?.generateMeta ?? false,
|
|
786
788
|
generateDiscriminatedUnion: outputOptions.override?.zod?.generateDiscriminatedUnion ?? false,
|
|
789
|
+
exactOptional: outputOptions.override?.zod?.exactOptional ?? false,
|
|
787
790
|
dateTimeOptions: outputOptions.override?.zod?.dateTimeOptions ?? { offset: true },
|
|
788
791
|
timeOptions: outputOptions.override?.zod?.timeOptions ?? {}
|
|
789
792
|
},
|
|
@@ -1527,6 +1530,30 @@ async function collectFilePaths(paths) {
|
|
|
1527
1530
|
return results;
|
|
1528
1531
|
}
|
|
1529
1532
|
//#endregion
|
|
1533
|
+
//#region src/utils/barrel.ts
|
|
1534
|
+
const RE_EXPORT_SPECIFIER = /export\s+\*\s+from\s*['"]([^'"]+)['"]/g;
|
|
1535
|
+
/**
|
|
1536
|
+
* Extract the set of `export * from '...'` module specifiers from barrel
|
|
1537
|
+
* content. Quote-agnostic (matches both `'` and `"`) so it is unaffected by a
|
|
1538
|
+
* formatter changing quote style between generations.
|
|
1539
|
+
*/
|
|
1540
|
+
function readReExportSpecifiers(content) {
|
|
1541
|
+
return new Set([...content.matchAll(RE_EXPORT_SPECIFIER)].map((m) => m[1]));
|
|
1542
|
+
}
|
|
1543
|
+
/**
|
|
1544
|
+
* Return the deduplicated list of specifiers for a barrel by unioning the
|
|
1545
|
+
* freshly generated `specifiers` with whatever re-exports already exist on
|
|
1546
|
+
* disk. Merging on the bare specifier (rather than the formatted line) makes
|
|
1547
|
+
* the barrel idempotent across regenerations regardless of how an external
|
|
1548
|
+
* formatter rewrites quotes, semicolons, or whitespace. On-disk order is
|
|
1549
|
+
* preserved and new specifiers are appended — matching the previous append
|
|
1550
|
+
* ordering — so callers control any sorting they want.
|
|
1551
|
+
*/
|
|
1552
|
+
async function mergeBarrelSpecifiers(filePath, specifiers) {
|
|
1553
|
+
const existing = await fs$2.pathExists(filePath) ? readReExportSpecifiers(await fs$2.readFile(filePath, "utf8")) : /* @__PURE__ */ new Set();
|
|
1554
|
+
return [...new Set([...existing, ...specifiers])];
|
|
1555
|
+
}
|
|
1556
|
+
//#endregion
|
|
1530
1557
|
//#region src/utils/execute-hook.ts
|
|
1531
1558
|
const executeHook = async (name, commands = [], args = []) => {
|
|
1532
1559
|
log(styleText("white", `Running ${name} hook...`));
|
|
@@ -1650,7 +1677,7 @@ const generateReusableSchemaSet = (refs, context, options) => {
|
|
|
1650
1677
|
operationId: "",
|
|
1651
1678
|
location: "schema",
|
|
1652
1679
|
schemaName: name
|
|
1653
|
-
} : void 0, options.variant);
|
|
1680
|
+
} : void 0, options.variant, options.exactOptional);
|
|
1654
1681
|
entries.push({
|
|
1655
1682
|
ref,
|
|
1656
1683
|
name,
|
|
@@ -1915,19 +1942,11 @@ const groupSchemasByFilePath = (schemas) => {
|
|
|
1915
1942
|
async function writeZodSchemaIndex(schemasPath, fileExtension, header, schemaNames, namingConvention, shouldMergeExisting = false, tsconfig) {
|
|
1916
1943
|
const importFileExtension = getImportExtension(fileExtension, tsconfig);
|
|
1917
1944
|
const indexPath = path.join(schemasPath, `index.ts`);
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
existingExports = existingContent.slice(headerPart.length).trim();
|
|
1924
|
-
}
|
|
1925
|
-
const newExports = schemaNames.map((schemaName) => {
|
|
1926
|
-
return `export * from './${conventionName(schemaName, namingConvention)}${importFileExtension}';`;
|
|
1927
|
-
}).toSorted().join("\n");
|
|
1928
|
-
const allExports = existingExports ? `${existingExports}\n${newExports}` : newExports;
|
|
1929
|
-
const uniqueExports = [...new Set(allExports.split("\n"))].filter((line) => line.trim()).toSorted().join("\n");
|
|
1930
|
-
await fs$2.outputFile(indexPath, `${header}\n${uniqueExports}\n`);
|
|
1945
|
+
const newSpecifiers = [...new Set(schemaNames.map((schemaName) => {
|
|
1946
|
+
return `./${conventionName(schemaName, namingConvention)}${importFileExtension}`;
|
|
1947
|
+
}))];
|
|
1948
|
+
const exports = (shouldMergeExisting ? await mergeBarrelSpecifiers(indexPath, newSpecifiers) : newSpecifiers).toSorted().map((specifier) => `export * from '${specifier}';`).join("\n");
|
|
1949
|
+
await fs$2.outputFile(indexPath, `${header}\n${exports}\n`);
|
|
1931
1950
|
}
|
|
1932
1951
|
async function writeZodSchemaTagsSplitBarrel(schemasPath, fileExtension, header, componentDirs, verbDirs, namingConvention, tsconfig) {
|
|
1933
1952
|
const importExt = getImportExtension(fileExtension, tsconfig);
|
|
@@ -1975,7 +1994,7 @@ function generateZodSchemasInline(builder, output, includeZodImport = true, para
|
|
|
1975
1994
|
const parsedZodDefinition = parseZodValidationSchemaDefinition(generateZodValidationSchemaDefinition(dereference(schemaObject, context), context, name, strict, isZodV4, {
|
|
1976
1995
|
required: true,
|
|
1977
1996
|
emitMeta: output.override.zod.generateMeta
|
|
1978
|
-
}), context, coerce, strict, isZodV4, void 0, void 0, output.override.zod.variant);
|
|
1997
|
+
}), context, coerce, strict, isZodV4, void 0, void 0, output.override.zod.variant, output.override.zod.exactOptional);
|
|
1979
1998
|
schemas.push({
|
|
1980
1999
|
schemaName: name,
|
|
1981
2000
|
consts: parsedZodDefinition.consts,
|
|
@@ -2009,6 +2028,7 @@ function generateZodSchemasInlineReusable(builder, output, includeZodImport = tr
|
|
|
2009
2028
|
coerce,
|
|
2010
2029
|
variant: output.override.zod.variant,
|
|
2011
2030
|
generateMeta: output.override.zod.generateMeta,
|
|
2031
|
+
exactOptional: output.override.zod.exactOptional,
|
|
2012
2032
|
paramsMutator
|
|
2013
2033
|
})).map((entry) => renderReusableSchemaEntry(entry, context, output.override.zod.variant).content).join("\n\n");
|
|
2014
2034
|
const zodImport = includeZodImport ? `${getZodSchemaImportStatement(output.override.zod.variant)}\n` : "";
|
|
@@ -2042,7 +2062,7 @@ async function writeZodSchemas(builder, schemasPath, fileExtension, header, outp
|
|
|
2042
2062
|
const parsedZodDefinition = parseZodValidationSchemaDefinition(generateZodValidationSchemaDefinition(dereference(schemaObject, context), context, name, strict, isZodV4, {
|
|
2043
2063
|
required: true,
|
|
2044
2064
|
emitMeta: output.override.zod.generateMeta
|
|
2045
|
-
}), context, coerce, strict, isZodV4, void 0, void 0, output.override.zod.variant);
|
|
2065
|
+
}), context, coerce, strict, isZodV4, void 0, void 0, output.override.zod.variant, output.override.zod.exactOptional);
|
|
2046
2066
|
schemasToWrite.push({
|
|
2047
2067
|
schemaName: name,
|
|
2048
2068
|
filePath,
|
|
@@ -2092,6 +2112,7 @@ async function writeZodSchemasReusable(builder, schemasPath, fileExtension, head
|
|
|
2092
2112
|
coerce,
|
|
2093
2113
|
variant: output.override.zod.variant,
|
|
2094
2114
|
generateMeta: output.override.zod.generateMeta,
|
|
2115
|
+
exactOptional: output.override.zod.exactOptional,
|
|
2095
2116
|
paramsMutator
|
|
2096
2117
|
}));
|
|
2097
2118
|
const componentNames = new Set(Object.keys(builder.spec.components?.schemas ?? {}).map((schemaName) => resolveSchemaName(`#/components/schemas/${schemaName}`, context)));
|
|
@@ -2220,7 +2241,7 @@ async function writeZodSchemasFromVerbs(verbOptions, schemasPath, fileExtension,
|
|
|
2220
2241
|
const parsedZodDefinition = parseZodValidationSchemaDefinition("bodyContentType" in entry && entry.bodyContentType === "multipart/form-data" ? generateFormDataZodSchema(schema, zodContext, name, strict, isZodV4, "encoding" in entry ? entry.encoding : void 0, useReusableSchemas) : generateZodValidationSchemaDefinition(schema, zodContext, name, strict, isZodV4, {
|
|
2221
2242
|
required: true,
|
|
2222
2243
|
useReusableSchemas
|
|
2223
|
-
}), zodContext, coerce, strict, isZodV4, void 0, void 0, output.override.zod.variant);
|
|
2244
|
+
}), zodContext, coerce, strict, isZodV4, void 0, void 0, output.override.zod.variant, output.override.zod.exactOptional);
|
|
2224
2245
|
let zodExpression = parsedZodDefinition.zod;
|
|
2225
2246
|
let importStatements;
|
|
2226
2247
|
if (useReusableSchemas && parsedZodDefinition.usedRefs.size > 0) {
|
|
@@ -2323,8 +2344,7 @@ async function addOperationSchemasReExport(schemaPath, operationSchemasPath, hea
|
|
|
2323
2344
|
const esmImportPath = upath.getRelativeImportPath(schemaIndexPath, operationSchemasPath);
|
|
2324
2345
|
const exportLine = `export * from '${esmImportPath}';\n`;
|
|
2325
2346
|
if (await fs$2.pathExists(schemaIndexPath)) {
|
|
2326
|
-
|
|
2327
|
-
if (!new RegExp(String.raw`export\s*\*\s*from\s*['"]${esmImportPath.replaceAll(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`)}['"]`).test(existingContent)) await fs$2.appendFile(schemaIndexPath, exportLine);
|
|
2347
|
+
if (!readReExportSpecifiers(await fs$2.readFile(schemaIndexPath, "utf8")).has(esmImportPath)) await fs$2.appendFile(schemaIndexPath, exportLine);
|
|
2328
2348
|
} else {
|
|
2329
2349
|
const content = header && header.trim().length > 0 ? `${header}\n${exportLine}` : exportLine;
|
|
2330
2350
|
await fs$2.outputFile(schemaIndexPath, content);
|
|
@@ -2431,9 +2451,15 @@ function shouldGenerateSchemas(output, hasOperations) {
|
|
|
2431
2451
|
function getImplementationPathsForIndex(output, implementationPaths, indexFile) {
|
|
2432
2452
|
const shouldExcludeSelf = output.indexFiles;
|
|
2433
2453
|
const paths = shouldExcludeSelf ? excludeFilePath(implementationPaths, indexFile) : implementationPaths;
|
|
2434
|
-
if (
|
|
2454
|
+
if (shouldExcludeSelf && output.mode === OutputMode.SPLIT && getComparableFilePath(output.target) === getComparableFilePath(indexFile)) {
|
|
2455
|
+
const targetInfo = getFileInfo(output.target, { extension: output.fileExtension });
|
|
2456
|
+
return excludeFilePath(paths, path.join(targetInfo.dirname, `${targetInfo.filename}.schemas${output.fileExtension}`));
|
|
2457
|
+
}
|
|
2458
|
+
if (!(output.mode === OutputMode.TAGS_OPERATIONS || output.mode === OutputMode.TAGS_OPERATIONS_SPLIT) || !shouldExcludeSelf) return paths;
|
|
2435
2459
|
const targetInfo = getFileInfo(output.target, { extension: output.fileExtension });
|
|
2436
|
-
|
|
2460
|
+
const rootBarrel = path.join(targetInfo.dirname, `index${output.fileExtension}`);
|
|
2461
|
+
const globalSchemas = path.join(targetInfo.dirname, `${targetInfo.filename}.schemas${output.fileExtension}`);
|
|
2462
|
+
return paths.filter((p) => getComparableFilePath(p) === getComparableFilePath(rootBarrel) || getComparableFilePath(p) === getComparableFilePath(globalSchemas));
|
|
2437
2463
|
}
|
|
2438
2464
|
async function writeSpecs(builder, workspace, options, projectName) {
|
|
2439
2465
|
const { info, schemas, target } = builder;
|
|
@@ -2569,8 +2595,7 @@ async function writeSpecs(builder, workspace, options, projectName) {
|
|
|
2569
2595
|
const indexFile = path.join(workspacePath, "index.ts");
|
|
2570
2596
|
const mockExtensions = output.mock.generators.map((g) => getMockFileExtensionByTypeName(g));
|
|
2571
2597
|
const importExtension = getImportExtension(output.fileExtension, output.tsconfig);
|
|
2572
|
-
const
|
|
2573
|
-
const imports = implementationPathsForIndex.filter((p) => mockExtensions.length === 0 || !mockExtensions.some((ext) => p.endsWith(`.${ext}.ts`))).map((p) => {
|
|
2598
|
+
const imports = getImplementationPathsForIndex(output, implementationPaths, indexFile).filter((p) => mockExtensions.length === 0 || !mockExtensions.some((ext) => p.endsWith(`.${ext}.ts`))).map((p) => {
|
|
2574
2599
|
const relative = upath.getRelativeImportPath(indexFile, p, true);
|
|
2575
2600
|
return (relative.endsWith(output.fileExtension) ? relative.slice(0, -output.fileExtension.length) : relative.replace(/\.[^/.]+$/, "")) + importExtension;
|
|
2576
2601
|
});
|
|
@@ -2581,11 +2606,11 @@ async function writeSpecs(builder, workspace, options, projectName) {
|
|
|
2581
2606
|
if (output.operationSchemas) imports.push(upath.getRelativeImportPath(indexFile, getFileInfo(output.operationSchemas).dirname));
|
|
2582
2607
|
if (output.indexFiles) {
|
|
2583
2608
|
if (await fs$2.pathExists(indexFile)) {
|
|
2584
|
-
const
|
|
2585
|
-
const
|
|
2586
|
-
await fs$2.appendFile(indexFile,
|
|
2587
|
-
} else await fs$2.outputFile(indexFile,
|
|
2588
|
-
implementationPaths = [indexFile, ...
|
|
2609
|
+
const declared = readReExportSpecifiers(await fs$2.readFile(indexFile, "utf8"));
|
|
2610
|
+
const toAdd = [...new Set(imports.filter((imp) => !declared.has(imp)))];
|
|
2611
|
+
if (toAdd.length > 0) await fs$2.appendFile(indexFile, toAdd.map((imp) => `export * from '${imp}';\n`).join(""));
|
|
2612
|
+
} else await fs$2.outputFile(indexFile, `${[...new Set(imports)].map((imp) => `export * from '${imp}';`).join("\n")}\n`);
|
|
2613
|
+
implementationPaths = [indexFile, ...excludeFilePath(implementationPaths, indexFile)];
|
|
2589
2614
|
}
|
|
2590
2615
|
}
|
|
2591
2616
|
if (builder.extraFiles.length > 0) {
|
|
@@ -2636,6 +2661,8 @@ function getWriteMode(mode) {
|
|
|
2636
2661
|
case OutputMode.SPLIT: return writeSplitMode;
|
|
2637
2662
|
case OutputMode.TAGS: return writeTagsMode;
|
|
2638
2663
|
case OutputMode.TAGS_SPLIT: return writeSplitTagsMode;
|
|
2664
|
+
case OutputMode.TAGS_OPERATIONS: return writeTagsOperationsMode;
|
|
2665
|
+
case OutputMode.TAGS_OPERATIONS_SPLIT: return writeTagsOperationsSplitMode;
|
|
2639
2666
|
default: return writeSingleMode;
|
|
2640
2667
|
}
|
|
2641
2668
|
}
|
|
@@ -2725,4 +2752,4 @@ async function loadConfigFile(configFilePath) {
|
|
|
2725
2752
|
//#endregion
|
|
2726
2753
|
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 };
|
|
2727
2754
|
|
|
2728
|
-
//# sourceMappingURL=config-
|
|
2755
|
+
//# sourceMappingURL=config-18E5SVPo.mjs.map
|