@orval/zod 8.32.0 → 8.34.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.d.mts +28 -21
- package/dist/index.mjs +99 -5
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { ClientBuilder, ClientDependenciesBuilder, ClientGeneratorsBuilder, ContextSpec, GeneratorMutator, OpenApiParameterObject, OpenApiReferenceObject, OpenApiSchemaObject, PackageJson, ZodCoerceType, ZodVariantOption, ZodVersionOption } from "@orval/core";
|
|
1
|
+
import { ClientBuilder, ClientDependenciesBuilder, ClientGeneratorsBuilder, ContextSpec, GeneratorMutator, GeneratorVerbOptions, OpenApiParameterObject, OpenApiReferenceObject, OpenApiSchemaObject, PackageJson, ZodCoerceType, ZodVariantOption, ZodVersionOption } from "@orval/core";
|
|
2
2
|
//#region src/compatible-v4.d.ts
|
|
3
|
-
declare const isZodVersionV4: (packageJson: PackageJson) => boolean;
|
|
3
|
+
export declare const isZodVersionV4: (packageJson: PackageJson) => boolean;
|
|
4
4
|
/**
|
|
5
5
|
* Resolves whether to emit Zod 4-style output.
|
|
6
6
|
*
|
|
@@ -11,13 +11,13 @@ declare const isZodVersionV4: (packageJson: PackageJson) => boolean;
|
|
|
11
11
|
* still get the modern baseline. This keeps generation deterministic when a
|
|
12
12
|
* target is pinned while preserving package-detection for `'auto'`.
|
|
13
13
|
*/
|
|
14
|
-
declare const resolveIsZodV4: (version: ZodVersionOption | undefined, packageJson: PackageJson | undefined) => boolean;
|
|
15
|
-
declare const assertZodTarget: ({ variant, isZodV4 }: {
|
|
14
|
+
export declare const resolveIsZodV4: (version: ZodVersionOption | undefined, packageJson: PackageJson | undefined) => boolean;
|
|
15
|
+
export declare const assertZodTarget: ({ variant, isZodV4 }: {
|
|
16
16
|
variant: ZodVariantOption | undefined;
|
|
17
17
|
isZodV4: boolean;
|
|
18
18
|
}) => void;
|
|
19
|
-
declare const getZodImportSource: (variant: ZodVariantOption | undefined) => "zod/mini" | "zod";
|
|
20
|
-
declare const getZodTypeName: (variant: ZodVariantOption | undefined) => "ZodMiniType" | "ZodType";
|
|
19
|
+
export declare const getZodImportSource: (variant: ZodVariantOption | undefined) => "zod/mini" | "zod";
|
|
20
|
+
export declare const getZodTypeName: (variant: ZodVariantOption | undefined) => "ZodMiniType" | "ZodType";
|
|
21
21
|
//#endregion
|
|
22
22
|
//#region src/export-emitter.d.ts
|
|
23
23
|
/**
|
|
@@ -70,12 +70,12 @@ interface ZodExportBlock {
|
|
|
70
70
|
* or a recursive `zod.ZodType<X>` pin. See {@link ZodExportBlock} for what
|
|
71
71
|
* this deliberately leaves to the caller.
|
|
72
72
|
*/
|
|
73
|
-
declare const renderZodExport: (block: ZodExportBlock) => string;
|
|
73
|
+
export declare const renderZodExport: (block: ZodExportBlock) => string;
|
|
74
74
|
//#endregion
|
|
75
75
|
//#region src/index.d.ts
|
|
76
|
-
declare const getZodDependencies: ClientDependenciesBuilder;
|
|
77
|
-
declare const predefinedZodFormats: Set<string>;
|
|
78
|
-
interface ZodValidationSchemaDefinition {
|
|
76
|
+
export declare const getZodDependencies: ClientDependenciesBuilder;
|
|
77
|
+
export declare const predefinedZodFormats: Set<string>;
|
|
78
|
+
export interface ZodValidationSchemaDefinition {
|
|
79
79
|
functions: [string, unknown][];
|
|
80
80
|
consts: string[];
|
|
81
81
|
}
|
|
@@ -87,7 +87,7 @@ interface DateTimeOptions {
|
|
|
87
87
|
interface TimeOptions {
|
|
88
88
|
precision?: -1 | 0 | 1 | 2 | 3;
|
|
89
89
|
}
|
|
90
|
-
declare const generateZodValidationSchemaDefinition: (schema: OpenApiSchemaObject | OpenApiReferenceObject | undefined, context: ContextSpec, name: string, strict: boolean, isZodV4: boolean, rules?: {
|
|
90
|
+
export declare const generateZodValidationSchemaDefinition: (schema: OpenApiSchemaObject | OpenApiReferenceObject | undefined, context: ContextSpec, name: string, strict: boolean, isZodV4: boolean, rules?: {
|
|
91
91
|
required?: boolean;
|
|
92
92
|
/**
|
|
93
93
|
* Required keys inherited from sibling `allOf` members. Per JSON Schema /
|
|
@@ -138,7 +138,7 @@ declare const generateZodValidationSchemaDefinition: (schema: OpenApiSchemaObjec
|
|
|
138
138
|
* every emitted validator. Exported so consumers can type their function with
|
|
139
139
|
* `import type { ZodParamsContext } from 'orval'` instead of hand-writing it.
|
|
140
140
|
*/
|
|
141
|
-
interface ZodParamsContext {
|
|
141
|
+
export interface ZodParamsContext {
|
|
142
142
|
/** The OpenAPI `operationId`, or `''` for shared component schemas. */
|
|
143
143
|
operationId: string;
|
|
144
144
|
/** `'schema'` is used for shared component schemas with no owning operation. */
|
|
@@ -150,16 +150,16 @@ interface ZodParamsContext {
|
|
|
150
150
|
/** The Zod method being emitted, e.g. `'string'`, `'min'`, `'email'`. */
|
|
151
151
|
validator: string;
|
|
152
152
|
}
|
|
153
|
-
interface ZodParamsInjection extends Pick<ZodParamsContext, 'operationId' | 'location' | 'schemaName'> {
|
|
153
|
+
export interface ZodParamsInjection extends Pick<ZodParamsContext, 'operationId' | 'location' | 'schemaName'> {
|
|
154
154
|
mutator: GeneratorMutator;
|
|
155
155
|
}
|
|
156
|
-
interface ZodMetaArgs {
|
|
156
|
+
export interface ZodMetaArgs {
|
|
157
157
|
id?: string;
|
|
158
158
|
title?: string;
|
|
159
159
|
description?: string;
|
|
160
160
|
deprecated?: boolean;
|
|
161
161
|
}
|
|
162
|
-
declare const parseZodValidationSchemaDefinition: (input: ZodValidationSchemaDefinition, context: ContextSpec, coerceTypes: boolean | ZodCoerceType[] | undefined, strict: boolean, isZodV4: boolean, preprocess?: GeneratorMutator, paramsInjection?: ZodParamsInjection, variant?: ZodVariantOption, exactOptional?: boolean) => {
|
|
162
|
+
export declare const parseZodValidationSchemaDefinition: (input: ZodValidationSchemaDefinition, context: ContextSpec, coerceTypes: boolean | ZodCoerceType[] | undefined, strict: boolean, isZodV4: boolean, preprocess?: GeneratorMutator, paramsInjection?: ZodParamsInjection, variant?: ZodVariantOption, exactOptional?: boolean) => {
|
|
163
163
|
zod: string;
|
|
164
164
|
consts: string;
|
|
165
165
|
usedRefs: Set<string>;
|
|
@@ -178,16 +178,23 @@ declare const parseZodValidationSchemaDefinition: (input: ZodValidationSchemaDef
|
|
|
178
178
|
* 3. If resolved to a concrete schema, inline it (same as `$ref`).
|
|
179
179
|
* 4. If unresolved, external, or a generic parameter → return `{}`.
|
|
180
180
|
*/
|
|
181
|
-
declare const dereference: (schema: OpenApiSchemaObject | OpenApiReferenceObject, context: ContextSpec) => OpenApiSchemaObject;
|
|
181
|
+
export declare const dereference: (schema: OpenApiSchemaObject | OpenApiReferenceObject, context: ContextSpec) => OpenApiSchemaObject;
|
|
182
182
|
/**
|
|
183
183
|
* Generate zod schema for form-data request body.
|
|
184
184
|
* Handles file type detection for top-level properties based on encoding.contentType
|
|
185
185
|
* and contentMediaType. Mirrors type gen's resolveFormDataRootObject.
|
|
186
186
|
*/
|
|
187
|
-
declare const generateFormDataZodSchema: (schema: OpenApiSchemaObject, context: ContextSpec, name: string, strict: boolean, isZodV4: boolean, encoding?: Record<string, {
|
|
187
|
+
export declare const generateFormDataZodSchema: (schema: OpenApiSchemaObject, context: ContextSpec, name: string, strict: boolean, isZodV4: boolean, encoding?: Record<string, {
|
|
188
188
|
contentType?: string;
|
|
189
189
|
}>, useReusableSchemas?: boolean) => ZodValidationSchemaDefinition;
|
|
190
|
-
|
|
190
|
+
/** The success response is emitted as a plain `zod.object(...)`. */
|
|
191
|
+
export declare const isObjectResponseSchema: (verbOptions: Pick<GeneratorVerbOptions, "verb" | "pathRoute" | "override">, context: ContextSpec) => boolean;
|
|
192
|
+
/**
|
|
193
|
+
* A `<Operation>Response` schema that can be converted to JSON Schema is
|
|
194
|
+
* emitted for the success response.
|
|
195
|
+
*/
|
|
196
|
+
export declare const hasResponseSchema: (verbOptions: Pick<GeneratorVerbOptions, "verb" | "pathRoute" | "override">, context: ContextSpec) => boolean;
|
|
197
|
+
export declare const parseParameters: ({ data, context, operationName, isZodV4, strict, generate, useReusableSchemas }: {
|
|
191
198
|
data: (OpenApiParameterObject | OpenApiReferenceObject)[] | undefined;
|
|
192
199
|
context: ContextSpec;
|
|
193
200
|
operationName: string;
|
|
@@ -212,8 +219,8 @@ declare const parseParameters: ({ data, context, operationName, isZodV4, strict,
|
|
|
212
219
|
queryParams: ZodValidationSchemaDefinition;
|
|
213
220
|
params: ZodValidationSchemaDefinition;
|
|
214
221
|
};
|
|
215
|
-
declare const generateZod: ClientBuilder;
|
|
216
|
-
declare const builder: () => () => ClientGeneratorsBuilder;
|
|
222
|
+
export declare const generateZod: ClientBuilder;
|
|
223
|
+
export declare const builder: () => () => ClientGeneratorsBuilder;
|
|
217
224
|
//#endregion
|
|
218
|
-
export { type ZodExportBlock,
|
|
225
|
+
export { type ZodExportBlock, builder as default };
|
|
219
226
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.mjs
CHANGED
|
@@ -65,8 +65,37 @@ const getLooseObjectFunctionName = (isZodV4) => {
|
|
|
65
65
|
//#region src/export-emitter.ts
|
|
66
66
|
/** Marks a call as side-effect-free for bundlers' tree-shaking passes. */
|
|
67
67
|
const PURE_COMMENT = "/*#__PURE__*/ ";
|
|
68
|
+
/**
|
|
69
|
+
* A dotted path of JavaScript identifiers — the only shape a Zod method name
|
|
70
|
+
* may take. The dots are for zod v4's namespaced constructors (`iso.datetime`,
|
|
71
|
+
* `iso.date`), which the emitters reach through this same path.
|
|
72
|
+
*/
|
|
73
|
+
const ZOD_METHOD_NAME_PATTERN = /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*$/;
|
|
74
|
+
/**
|
|
75
|
+
* Refuses a Zod method name that is not a plain (optionally dotted) identifier.
|
|
76
|
+
*
|
|
77
|
+
* Method names are interpolated unquoted into generated source (`zod.<fn>()`,
|
|
78
|
+
* `.<fn>(...)`), so anything else there is executable code rather than a call.
|
|
79
|
+
* Every name reaching an emitter is generator-chosen, so this only fires when a
|
|
80
|
+
* spec-derived string has leaked into a code position — which is exactly how a
|
|
81
|
+
* schema's scalar `type` became import-time RCE.
|
|
82
|
+
*
|
|
83
|
+
* Called at each interpolation site rather than once up front: a definition
|
|
84
|
+
* tuple's name is not always a method name. The discriminator path smuggles
|
|
85
|
+
* `oneOf::discriminator::<property>` through the same field, and the branches
|
|
86
|
+
* that consume those decode them instead of emitting them.
|
|
87
|
+
*
|
|
88
|
+
* @see GHSA-v263-cp2v-vrrx
|
|
89
|
+
*/
|
|
90
|
+
const assertZodMethodName = (fn) => {
|
|
91
|
+
if (ZOD_METHOD_NAME_PATTERN.test(fn)) return;
|
|
92
|
+
throw new Error(`orval: refusing to generate a Zod schema with "${fn}" as a method name — it is not a plain identifier. This value would otherwise be emitted verbatim into generated source.`);
|
|
93
|
+
};
|
|
68
94
|
/** Renders a Zod Mini functional call, e.g. `zod.minLength(1)`, with the pure-call comment. */
|
|
69
|
-
const zodMiniCall = (fn, args = "") =>
|
|
95
|
+
const zodMiniCall = (fn, args = "") => {
|
|
96
|
+
assertZodMethodName(fn);
|
|
97
|
+
return `${PURE_COMMENT}zod.${fn}(${args})`;
|
|
98
|
+
};
|
|
70
99
|
const renderArrayWithBounds = (itemName, variant, rules) => {
|
|
71
100
|
if (variant === "mini") {
|
|
72
101
|
const checks = [...rules?.min ? [zodMiniCall("minLength", `${rules.min}`)] : [], ...rules?.max ? [zodMiniCall("maxLength", `${rules.max}`)] : []];
|
|
@@ -145,7 +174,7 @@ const resolveZodType = (schema) => {
|
|
|
145
174
|
if (type === "array" && "prefixItems" in schema) return "tuple";
|
|
146
175
|
return type;
|
|
147
176
|
}
|
|
148
|
-
const type = isString(schemaTypeValue) ? schemaTypeValue : void 0;
|
|
177
|
+
const type = isString(schemaTypeValue) && possibleSchemaTypes.has(schemaTypeValue) ? schemaTypeValue : void 0;
|
|
149
178
|
if (schema.type === "array" && "prefixItems" in schema) return "tuple";
|
|
150
179
|
if (!type && "const" in schema) {
|
|
151
180
|
const constValue = schema.const;
|
|
@@ -163,7 +192,10 @@ const COERCIBLE_TYPES = /* @__PURE__ */ new Set([
|
|
|
163
192
|
"bigint",
|
|
164
193
|
"date"
|
|
165
194
|
]);
|
|
166
|
-
const zodMiniCoerceCall = (fn, args = "") =>
|
|
195
|
+
const zodMiniCoerceCall = (fn, args = "") => {
|
|
196
|
+
assertZodMethodName(fn);
|
|
197
|
+
return `${PURE_COMMENT}zod.coerce.${fn}(${args})`;
|
|
198
|
+
};
|
|
167
199
|
const hasUnicodePropertyEscape = (pattern) => /(^|[^\\])(?:\\\\)*\\[pP]\{/.test(pattern);
|
|
168
200
|
const buildRegExpLiteral = (pattern) => {
|
|
169
201
|
const innerPattern = pattern.slice(pattern.startsWith("/") ? 1 : 0, pattern.endsWith("/") ? -1 : void 0);
|
|
@@ -1251,8 +1283,12 @@ ${Object.entries(objectArgs).map(([key, schema]) => {
|
|
|
1251
1283
|
if (shouldCoerce("number")) return `.coerce.number(${numberArgs}).int(${combinedArgs})`;
|
|
1252
1284
|
if (!isZodV4) return `.number(${numberArgs}).int(${combinedArgs})`;
|
|
1253
1285
|
}
|
|
1254
|
-
if (fn !== "date" && shouldCoerceType || fn === "date" && shouldCoerceType && context.output.override.useDates)
|
|
1286
|
+
if (fn !== "date" && shouldCoerceType || fn === "date" && shouldCoerceType && context.output.override.useDates) {
|
|
1287
|
+
assertZodMethodName(fn);
|
|
1288
|
+
return `.coerce.${fn}(${combinedArgs})`;
|
|
1289
|
+
}
|
|
1255
1290
|
if (exactOptional && isZodV4 && fn === "optional") return ".exactOptional()";
|
|
1291
|
+
assertZodMethodName(fn);
|
|
1256
1292
|
return `.${fn}(${combinedArgs})`;
|
|
1257
1293
|
};
|
|
1258
1294
|
appendConstsChunk(input.consts.join("\n"));
|
|
@@ -1501,6 +1537,64 @@ const getSingleResponse = (responses) => {
|
|
|
1501
1537
|
const otherSuccess = Object.entries(responses).find(([code]) => code.startsWith("2") && code !== "204" && code !== "205")?.[1];
|
|
1502
1538
|
return responses["200"] ?? responses["2XX"] ?? responses["2xx"] ?? otherSuccess ?? responses["204"] ?? responses["205"];
|
|
1503
1539
|
};
|
|
1540
|
+
const parseResponseSchema = ({ verb, pathRoute, override }, context) => {
|
|
1541
|
+
const isZodV4 = resolveIsZodV4(context.output.override.zod.version, context.output.packageJson);
|
|
1542
|
+
return {
|
|
1543
|
+
isZodV4,
|
|
1544
|
+
...parseBodyAndResponse({
|
|
1545
|
+
data: getSingleResponse(context.spec.paths?.[pathRoute]?.[verb]?.responses),
|
|
1546
|
+
context,
|
|
1547
|
+
name: "response",
|
|
1548
|
+
strict: override.zod.strict.response,
|
|
1549
|
+
generate: override.zod.generate.response,
|
|
1550
|
+
isZodV4,
|
|
1551
|
+
parseType: "response"
|
|
1552
|
+
})
|
|
1553
|
+
};
|
|
1554
|
+
};
|
|
1555
|
+
/** The success response is emitted as a plain `zod.object(...)`. */
|
|
1556
|
+
const isObjectResponseSchema = (verbOptions, context) => {
|
|
1557
|
+
if (context.output.override.zod.generateEachHttpStatus) return false;
|
|
1558
|
+
const { input, isArray, isZodV4 } = parseResponseSchema(verbOptions, context);
|
|
1559
|
+
const [root, ...modifiers] = input.functions;
|
|
1560
|
+
if (isArray || root === void 0) return false;
|
|
1561
|
+
if (verbOptions.override.zod.preprocess?.response || verbOptions.override.zod.useBrandedTypes && !isZodV4) return false;
|
|
1562
|
+
const objectRoots = /* @__PURE__ */ new Set([
|
|
1563
|
+
"object",
|
|
1564
|
+
"looseObject",
|
|
1565
|
+
"strictObject"
|
|
1566
|
+
]);
|
|
1567
|
+
const objectModifiers = /* @__PURE__ */ new Set([
|
|
1568
|
+
"strict",
|
|
1569
|
+
"passthrough",
|
|
1570
|
+
"describe"
|
|
1571
|
+
]);
|
|
1572
|
+
return objectRoots.has(root[0]) && modifiers.every(([fn]) => objectModifiers.has(fn));
|
|
1573
|
+
};
|
|
1574
|
+
/**
|
|
1575
|
+
* A `<Operation>Response` schema that can be converted to JSON Schema is
|
|
1576
|
+
* emitted for the success response.
|
|
1577
|
+
*/
|
|
1578
|
+
const hasResponseSchema = (verbOptions, context) => {
|
|
1579
|
+
if (context.output.override.zod.generateEachHttpStatus) return false;
|
|
1580
|
+
const { input, isArray } = parseResponseSchema(verbOptions, context);
|
|
1581
|
+
if (!isArray && input.functions.length === 0) return false;
|
|
1582
|
+
const unsupportedTypes = /* @__PURE__ */ new Set([
|
|
1583
|
+
"allOf",
|
|
1584
|
+
"date",
|
|
1585
|
+
"instanceof"
|
|
1586
|
+
]);
|
|
1587
|
+
const containsUnsupported = (value) => {
|
|
1588
|
+
if (Array.isArray(value)) return value.some(containsUnsupported);
|
|
1589
|
+
if (!isObject(value)) return false;
|
|
1590
|
+
if (Array.isArray(value.functions)) {
|
|
1591
|
+
const functions = value.functions;
|
|
1592
|
+
return functions[0] !== void 0 && unsupportedTypes.has(functions[0][0]) || functions.some(([, args]) => containsUnsupported(args));
|
|
1593
|
+
}
|
|
1594
|
+
return Object.values(value).some(containsUnsupported);
|
|
1595
|
+
};
|
|
1596
|
+
return !containsUnsupported(input);
|
|
1597
|
+
};
|
|
1504
1598
|
const parseParameters = ({ data, context, operationName, isZodV4, strict, generate, useReusableSchemas }) => {
|
|
1505
1599
|
if (!data) return {
|
|
1506
1600
|
headers: {
|
|
@@ -1824,6 +1918,6 @@ const zodClientBuilder = {
|
|
|
1824
1918
|
};
|
|
1825
1919
|
const builder = () => () => zodClientBuilder;
|
|
1826
1920
|
//#endregion
|
|
1827
|
-
export { assertZodTarget, builder, builder as default, dereference, generateFormDataZodSchema, generateZod, generateZodValidationSchemaDefinition, getZodDependencies, getZodImportSource, getZodTypeName, isZodVersionV4, parseParameters, parseZodValidationSchemaDefinition, predefinedZodFormats, renderZodExport, resolveIsZodV4 };
|
|
1921
|
+
export { assertZodTarget, builder, builder as default, dereference, generateFormDataZodSchema, generateZod, generateZodValidationSchemaDefinition, getZodDependencies, getZodImportSource, getZodTypeName, hasResponseSchema, isObjectResponseSchema, isZodVersionV4, parseParameters, parseZodValidationSchemaDefinition, predefinedZodFormats, renderZodExport, resolveIsZodV4 };
|
|
1828
1922
|
|
|
1829
1923
|
//# sourceMappingURL=index.mjs.map
|