@orval/zod 8.33.0 → 8.35.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 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
- declare const parseParameters: ({ data, context, operationName, isZodV4, strict, generate, useReusableSchemas }: {
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, ZodMetaArgs, ZodParamsContext, ZodParamsInjection, ZodValidationSchemaDefinition, assertZodTarget, builder, builder as default, dereference, generateFormDataZodSchema, generateZod, generateZodValidationSchemaDefinition, getZodDependencies, getZodImportSource, getZodTypeName, isZodVersionV4, parseParameters, parseZodValidationSchemaDefinition, predefinedZodFormats, renderZodExport, resolveIsZodV4 };
225
+ export { type ZodExportBlock, builder as default };
219
226
  //# sourceMappingURL=index.d.mts.map
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { EnumGeneration, assertSafeNumericConstraint, buildDynamicScope, buildInlineDynamicScope, camel, compareVersions, createLogger, generateMutator, getDynamicAnchorName, getEnumImplementation, getEnumMembers, getEnumValueInfo, getFormDataFieldFileType, getNumberWord, getRefInfo, getRequiredKeys, hasEnumMetadata, isBoolean, isDynamicReference, isNumber, isObject, isString, jsStringEscape, jsStringLiteralEscape, pascal, resolveDynamicRef, resolveRef, safeNumericConstraint, stringify } from "@orval/core";
1
+ import { EnumGeneration, assertSafeNumericConstraint, buildDynamicScope, buildInlineDynamicScope, camel, compareVersions, createLogger, generateMutator, getDynamicAnchorName, getEnumImplementation, getEnumMembers, getEnumValueInfo, getFormDataFieldFileType, getNumberWord, getRefInfo, getRequiredKeys, hasEnumMetadata, isBoolean, isDynamicReference, isNumber, isObject, isSchemaNullable, isString, jsStringEscape, jsStringLiteralEscape, pascal, resolveDynamicRef, resolveRef, safeNumericConstraint, stringify } from "@orval/core";
2
2
  import jsesc from "jsesc";
3
3
  import { unique } from "remeda";
4
4
  //#region src/logger.ts
@@ -356,18 +356,12 @@ const generateZodValidationSchemaDefinition = (schema, context, name, strict, is
356
356
  functions: [],
357
357
  consts: []
358
358
  };
359
- const CHAINABLE_SIBLINGS = /* @__PURE__ */ new Set([
360
- "nullable",
361
- "default",
362
- "description"
363
- ]);
359
+ const CHAINABLE_SIBLINGS = /* @__PURE__ */ new Set(["default", "description"]);
364
360
  const isChainable = (k) => CHAINABLE_SIBLINGS.has(k);
365
361
  const applyChainableSiblings = (functions, consts, siblingSchema) => {
366
362
  const refRequired = rules?.required ?? false;
367
363
  const refHasDefault = siblingSchema.default !== void 0;
368
- if (!refRequired && siblingSchema.nullable) functions.push(["nullish", void 0]);
369
- else if (siblingSchema.nullable) functions.push(["nullable", void 0]);
370
- else if (!refRequired && !refHasDefault) functions.push(["optional", void 0]);
364
+ if (!refRequired && !refHasDefault) functions.push(["optional", void 0]);
371
365
  if (refHasDefault) {
372
366
  const registry = rules?.constNameRegistry ?? {};
373
367
  const counter = isNumber(registry[name]) ? registry[name] + 1 : 0;
@@ -450,13 +444,11 @@ const generateZodValidationSchemaDefinition = (schema, context, name, strict, is
450
444
  const type = resolveZodType(schema);
451
445
  const required = rules?.required ?? false;
452
446
  const hasDefault = schema.default !== void 0;
453
- const nullable = "nullable" in schema && schema.nullable || Array.isArray(schema.type) && schema.type.includes("null");
447
+ const nullable = Array.isArray(schema.type) && schema.type.includes("null");
454
448
  const min = schema.minimum ?? schema.minLength ?? schema.minItems;
455
449
  const max = schema.maximum ?? schema.maxLength ?? schema.maxItems;
456
- const exclusiveMinRaw = "exclusiveMinimum" in schema ? schema.exclusiveMinimum : void 0;
457
- const exclusiveMaxRaw = "exclusiveMaximum" in schema ? schema.exclusiveMaximum : void 0;
458
- const exclusiveMin = isBoolean(exclusiveMinRaw) ? exclusiveMinRaw ? min : void 0 : exclusiveMinRaw;
459
- const exclusiveMax = isBoolean(exclusiveMaxRaw) ? exclusiveMaxRaw ? max : void 0 : exclusiveMaxRaw;
450
+ const exclusiveMin = "exclusiveMinimum" in schema ? schema.exclusiveMinimum : void 0;
451
+ const exclusiveMax = "exclusiveMaximum" in schema ? schema.exclusiveMaximum : void 0;
460
452
  const multipleOf = schema.multipleOf;
461
453
  const matches = schema.pattern ?? void 0;
462
454
  const hasNonArrayEnum = !!schema.enum && type !== "array";
@@ -1441,8 +1433,11 @@ const generateFormDataZodSchema = (schema, context, name, strict, isZodV4, encod
1441
1433
  const fileType = resolvedPropSchema ? getFormDataFieldFileType(resolvedPropSchema, encoding?.[key]?.contentType) : void 0;
1442
1434
  if (fileType) {
1443
1435
  const isRequired = schema.required?.includes(key);
1436
+ const isNullable = !!resolvedPropSchema && isSchemaNullable(resolvedPropSchema);
1444
1437
  const fileFunctions = [fileType === "binary" ? ["instanceof", "Blob"] : ["fileOrString", void 0]];
1445
- if (!isRequired) fileFunctions.push(["optional", void 0]);
1438
+ if (!isRequired && isNullable) fileFunctions.push(["nullish", void 0]);
1439
+ else if (isNullable) fileFunctions.push(["nullable", void 0]);
1440
+ else if (!isRequired) fileFunctions.push(["optional", void 0]);
1446
1441
  propertyOverrides[key] = {
1447
1442
  functions: fileFunctions,
1448
1443
  consts: []
@@ -1537,6 +1532,64 @@ const getSingleResponse = (responses) => {
1537
1532
  const otherSuccess = Object.entries(responses).find(([code]) => code.startsWith("2") && code !== "204" && code !== "205")?.[1];
1538
1533
  return responses["200"] ?? responses["2XX"] ?? responses["2xx"] ?? otherSuccess ?? responses["204"] ?? responses["205"];
1539
1534
  };
1535
+ const parseResponseSchema = ({ verb, pathRoute, override }, context) => {
1536
+ const isZodV4 = resolveIsZodV4(context.output.override.zod.version, context.output.packageJson);
1537
+ return {
1538
+ isZodV4,
1539
+ ...parseBodyAndResponse({
1540
+ data: getSingleResponse(context.spec.paths?.[pathRoute]?.[verb]?.responses),
1541
+ context,
1542
+ name: "response",
1543
+ strict: override.zod.strict.response,
1544
+ generate: override.zod.generate.response,
1545
+ isZodV4,
1546
+ parseType: "response"
1547
+ })
1548
+ };
1549
+ };
1550
+ /** The success response is emitted as a plain `zod.object(...)`. */
1551
+ const isObjectResponseSchema = (verbOptions, context) => {
1552
+ if (context.output.override.zod.generateEachHttpStatus) return false;
1553
+ const { input, isArray, isZodV4 } = parseResponseSchema(verbOptions, context);
1554
+ const [root, ...modifiers] = input.functions;
1555
+ if (isArray || root === void 0) return false;
1556
+ if (verbOptions.override.zod.preprocess?.response || verbOptions.override.zod.useBrandedTypes && !isZodV4) return false;
1557
+ const objectRoots = /* @__PURE__ */ new Set([
1558
+ "object",
1559
+ "looseObject",
1560
+ "strictObject"
1561
+ ]);
1562
+ const objectModifiers = /* @__PURE__ */ new Set([
1563
+ "strict",
1564
+ "passthrough",
1565
+ "describe"
1566
+ ]);
1567
+ return objectRoots.has(root[0]) && modifiers.every(([fn]) => objectModifiers.has(fn));
1568
+ };
1569
+ /**
1570
+ * A `<Operation>Response` schema that can be converted to JSON Schema is
1571
+ * emitted for the success response.
1572
+ */
1573
+ const hasResponseSchema = (verbOptions, context) => {
1574
+ if (context.output.override.zod.generateEachHttpStatus) return false;
1575
+ const { input, isArray } = parseResponseSchema(verbOptions, context);
1576
+ if (!isArray && input.functions.length === 0) return false;
1577
+ const unsupportedTypes = /* @__PURE__ */ new Set([
1578
+ "allOf",
1579
+ "date",
1580
+ "instanceof"
1581
+ ]);
1582
+ const containsUnsupported = (value) => {
1583
+ if (Array.isArray(value)) return value.some(containsUnsupported);
1584
+ if (!isObject(value)) return false;
1585
+ if (Array.isArray(value.functions)) {
1586
+ const functions = value.functions;
1587
+ return functions[0] !== void 0 && unsupportedTypes.has(functions[0][0]) || functions.some(([, args]) => containsUnsupported(args));
1588
+ }
1589
+ return Object.values(value).some(containsUnsupported);
1590
+ };
1591
+ return !containsUnsupported(input);
1592
+ };
1540
1593
  const parseParameters = ({ data, context, operationName, isZodV4, strict, generate, useReusableSchemas }) => {
1541
1594
  if (!data) return {
1542
1595
  headers: {
@@ -1860,6 +1913,6 @@ const zodClientBuilder = {
1860
1913
  };
1861
1914
  const builder = () => () => zodClientBuilder;
1862
1915
  //#endregion
1863
- export { assertZodTarget, builder, builder as default, dereference, generateFormDataZodSchema, generateZod, generateZodValidationSchemaDefinition, getZodDependencies, getZodImportSource, getZodTypeName, isZodVersionV4, parseParameters, parseZodValidationSchemaDefinition, predefinedZodFormats, renderZodExport, resolveIsZodV4 };
1916
+ export { assertZodTarget, builder, builder as default, dereference, generateFormDataZodSchema, generateZod, generateZodValidationSchemaDefinition, getZodDependencies, getZodImportSource, getZodTypeName, hasResponseSchema, isObjectResponseSchema, isZodVersionV4, parseParameters, parseZodValidationSchemaDefinition, predefinedZodFormats, renderZodExport, resolveIsZodV4 };
1864
1917
 
1865
1918
  //# sourceMappingURL=index.mjs.map