@kubb/plugin-zod 5.3.0-canary.20260924T115534 → 5.3.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.ts CHANGED
@@ -328,6 +328,15 @@ type ResolverZod = Resolver & {
328
328
  options(node: ast.OperationNode): string;
329
329
  };
330
330
  };
331
+ type CompileOptions = {
332
+ /**
333
+ * Throw an error if any part of the schema cannot be compiled into flat JavaScript,
334
+ * preventing silent fallback to the standard interpreter.
335
+ *
336
+ * @default false
337
+ */
338
+ strict?: boolean;
339
+ };
331
340
  /**
332
341
  * Where the generated Zod schemas are written and how they are exported, plus the optional
333
342
  * `group` strategy. The `group` option organizes `output.mode: 'directory'` output into per-tag or per-path subdirectories.
@@ -398,6 +407,18 @@ type Options = OutputOptions & {
398
407
  * @default 'literal'
399
408
  */
400
409
  regexType?: 'literal' | 'constructor';
410
+ /**
411
+ * Wrap generated schemas with `z.compile(...)` to enable Zod's hyperoptimized
412
+ * fast-path validation logic.
413
+ *
414
+ * Set to `true` or pass `{ strict: true }` to enforce that schemas compile into
415
+ * flat JavaScript without silently degrading to the standard interpreter.
416
+ *
417
+ * @default false
418
+ * @note Only compatible with Zod v4.5.0 or above.
419
+ * @see https://zod.dev/blog/introducing-z-compile
420
+ */
421
+ compile?: boolean | CompileOptions;
401
422
  /**
402
423
  * Switch to Zod Mini's functional API for better tree-shaking. Also defaults
403
424
  * `importPath` to `'zod/mini'`.
@@ -453,6 +474,7 @@ type ResolvedOptions = {
453
474
  coercion: NonNullable<Options['coercion']>;
454
475
  guidType: NonNullable<Options['guidType']>;
455
476
  regexType: NonNullable<Options['regexType']>;
477
+ compile: NonNullable<Options['compile']>;
456
478
  mini: NonNullable<Options['mini']>;
457
479
  typeGuards: NonNullable<Options['typeGuards']>;
458
480
  printer: Options['printer'];
@@ -527,5 +549,5 @@ export declare const pluginZod: (options?: Options | undefined) => import("kubb/
527
549
  */
528
550
  export declare const resolverZod: ResolverZod;
529
551
  //#endregion
530
- export { type PluginZod, type PrinterZodFactory, type PrinterZodMiniFactory, type PrinterZodMiniNodes, type PrinterZodMiniOptions, type PrinterZodNodes, type PrinterZodOptions, type ResolverZod, pluginZod as default };
552
+ export { type CompileOptions, type PluginZod, type PrinterZodFactory, type PrinterZodMiniFactory, type PrinterZodMiniNodes, type PrinterZodMiniOptions, type PrinterZodNodes, type PrinterZodOptions, type ResolverZod, pluginZod as default };
531
553
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -734,71 +734,6 @@ function mapSchemaItems(node, transform) {
734
734
  }));
735
735
  }
736
736
  //#endregion
737
- //#region src/components/Zod.tsx
738
- function Zod({ name, node, printer, inferTypeName, typeGuards, isName, assertName, mini, cyclic }) {
739
- const output = printer.print(node);
740
- if (!output) return;
741
- const needsAnnotation = cyclic && node.type !== "object";
742
- const targetType = inferTypeName ?? `z.infer<typeof ${name}>`;
743
- const shouldGenerateIs = isName && (typeof typeGuards === "object" ? typeGuards.is ?? true : Boolean(typeGuards));
744
- const shouldGenerateAssert = assertName && (typeof typeGuards === "object" ? typeGuards.assert ?? true : Boolean(typeGuards));
745
- return /* @__PURE__ */ jsxs(Fragment, { children: [
746
- /* @__PURE__ */ jsx(File.Source, {
747
- name,
748
- isExportable: true,
749
- isIndexable: true,
750
- children: /* @__PURE__ */ jsx(Const, {
751
- export: true,
752
- name,
753
- type: needsAnnotation ? "z.ZodType" : void 0,
754
- children: output
755
- })
756
- }),
757
- inferTypeName && /* @__PURE__ */ jsx(File.Source, {
758
- name: inferTypeName,
759
- isExportable: true,
760
- isIndexable: true,
761
- isTypeOnly: true,
762
- children: /* @__PURE__ */ jsx(Type, {
763
- export: true,
764
- name: inferTypeName,
765
- children: `z.infer<typeof ${name}>`
766
- })
767
- }),
768
- shouldGenerateIs && /* @__PURE__ */ jsx(File.Source, {
769
- name: isName,
770
- isExportable: true,
771
- isIndexable: true,
772
- children: /* @__PURE__ */ jsx(Const, {
773
- export: true,
774
- name: isName,
775
- JSDoc: { comments: [`Type guard for {@link ${name}}`] },
776
- children: mini ? `(data: unknown): data is ${targetType} => z.validate(${name}, data)` : `(data: unknown): data is ${targetType} => ${name}.validate(data)`
777
- })
778
- }),
779
- shouldGenerateAssert && /* @__PURE__ */ jsx(File.Source, {
780
- name: assertName,
781
- isExportable: true,
782
- isIndexable: true,
783
- children: /* @__PURE__ */ jsx(Function, {
784
- export: true,
785
- name: assertName,
786
- params: "data: unknown",
787
- returnType: `asserts data is ${targetType}`,
788
- JSDoc: { comments: [`Asserter for {@link ${name}}`, "@throws {z.ZodError} If data is invalid"] },
789
- children: mini ? `if (!z.validate(${name}, data)) {\n z.parse(${name}, data)\n}` : `if (!${name}.validate(data)) {\n ${name}.parse(data)\n}`
790
- })
791
- })
792
- ] });
793
- }
794
- //#endregion
795
- //#region src/constants.ts
796
- /**
797
- * Import paths that use a namespace import (`import * as z from '...'`).
798
- * All other import paths use a named import (`import { z } from '...'`).
799
- */
800
- const ZOD_NAMESPACE_IMPORTS = /* @__PURE__ */ new Set(["zod", "zod/mini"]);
801
- //#endregion
802
737
  //#region src/utils.ts
803
738
  /**
804
739
  * Returns `true` when the given coercion option enables coercion for the specified type.
@@ -817,6 +752,16 @@ function isPlainInlineObject(node) {
817
752
  return node.type === "object" && !node.nullable && !node.optional && !node.nullish && node.additionalProperties === void 0 && !node.patternProperties;
818
753
  }
819
754
  /**
755
+ * Whether the node is a bare reference schema (a `$ref` with no modifiers, descriptions, or omit keys).
756
+ * Bare references resolve directly to another schema variable and should not be re-wrapped in `z.compile(...)`.
757
+ */
758
+ function isBareRef(node, keysToOmit) {
759
+ const ref = ast.narrowSchema(node, "ref");
760
+ if (!ref) return false;
761
+ const meta = syncSchemaRef(ref);
762
+ return !meta.nullable && !meta.optional && !meta.nullish && meta.default === void 0 && !meta.description && !meta.examples?.length && !keysToOmit?.length;
763
+ }
764
+ /**
820
765
  * Whether a node renders as a bare Zod object — one that accepts `.extend(…)` and can be a
821
766
  * `z.discriminatedUnion` option. Covers object nodes, `$ref`s that resolve to (or are still
822
767
  * unresolved) objects, single-member unions of an object, and object-composable `allOf`.
@@ -1063,6 +1008,74 @@ function buildGroupedParamsSchema({ params, optional }) {
1063
1008
  });
1064
1009
  }
1065
1010
  //#endregion
1011
+ //#region src/components/Zod.tsx
1012
+ function Zod({ name, node, printer, inferTypeName, typeGuards, isName, assertName, mini, cyclic, compile }) {
1013
+ const output = printer.print(node);
1014
+ if (!output) return;
1015
+ const needsAnnotation = cyclic && node.type !== "object";
1016
+ const isBare = isBareRef(node, printer.options.keysToOmit);
1017
+ const isCyclic = Boolean(cyclic || printer.options.cyclicSchemas && containsCircularRef(node, { circularSchemas: printer.options.cyclicSchemas }));
1018
+ const value = Boolean(compile) && !isBare && !isCyclic ? typeof compile === "object" && compile.strict ? `z.compile(${output}, { strict: true })` : `z.compile(${output})` : output;
1019
+ const targetType = inferTypeName ?? `z.infer<typeof ${name}>`;
1020
+ const shouldGenerateIs = isName && (typeof typeGuards === "object" ? typeGuards.is ?? true : Boolean(typeGuards));
1021
+ const shouldGenerateAssert = assertName && (typeof typeGuards === "object" ? typeGuards.assert ?? true : Boolean(typeGuards));
1022
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1023
+ /* @__PURE__ */ jsx(File.Source, {
1024
+ name,
1025
+ isExportable: true,
1026
+ isIndexable: true,
1027
+ children: /* @__PURE__ */ jsx(Const, {
1028
+ export: true,
1029
+ name,
1030
+ type: needsAnnotation ? "z.ZodType" : void 0,
1031
+ children: value
1032
+ })
1033
+ }),
1034
+ inferTypeName && /* @__PURE__ */ jsx(File.Source, {
1035
+ name: inferTypeName,
1036
+ isExportable: true,
1037
+ isIndexable: true,
1038
+ isTypeOnly: true,
1039
+ children: /* @__PURE__ */ jsx(Type, {
1040
+ export: true,
1041
+ name: inferTypeName,
1042
+ children: `z.infer<typeof ${name}>`
1043
+ })
1044
+ }),
1045
+ shouldGenerateIs && /* @__PURE__ */ jsx(File.Source, {
1046
+ name: isName,
1047
+ isExportable: true,
1048
+ isIndexable: true,
1049
+ children: /* @__PURE__ */ jsx(Const, {
1050
+ export: true,
1051
+ name: isName,
1052
+ JSDoc: { comments: [`Type guard for {@link ${name}}`] },
1053
+ children: mini ? `(data: unknown): data is ${targetType} => z.validate(${name}, data)` : `(data: unknown): data is ${targetType} => ${name}.validate(data)`
1054
+ })
1055
+ }),
1056
+ shouldGenerateAssert && /* @__PURE__ */ jsx(File.Source, {
1057
+ name: assertName,
1058
+ isExportable: true,
1059
+ isIndexable: true,
1060
+ children: /* @__PURE__ */ jsx(Function, {
1061
+ export: true,
1062
+ name: assertName,
1063
+ params: "data: unknown",
1064
+ returnType: `asserts data is ${targetType}`,
1065
+ JSDoc: { comments: [`Asserter for {@link ${name}}`, "@throws {z.ZodError} If data is invalid"] },
1066
+ children: mini ? `if (!z.validate(${name}, data)) {\n z.parse(${name}, data)\n}` : `if (!${name}.validate(data)) {\n ${name}.parse(data)\n}`
1067
+ })
1068
+ })
1069
+ ] });
1070
+ }
1071
+ //#endregion
1072
+ //#region src/constants.ts
1073
+ /**
1074
+ * Import paths that use a namespace import (`import * as z from '...'`).
1075
+ * All other import paths use a named import (`import { z } from '...'`).
1076
+ */
1077
+ const ZOD_NAMESPACE_IMPORTS = /* @__PURE__ */ new Set(["zod", "zod/mini"]);
1078
+ //#endregion
1066
1079
  //#region src/printers/printerZod.ts
1067
1080
  /**
1068
1081
  * A `oneOf` member that is an inline object is exhaustive, so it prints as a strict object.
@@ -1775,7 +1788,7 @@ const zodGenerator = defineGenerator({
1775
1788
  renderer: jsxRenderer,
1776
1789
  schema(node, ctx) {
1777
1790
  const { adapter, config, resolver, root } = ctx;
1778
- const { output, coercion, guidType, regexType, mini, inferred, typeGuards, importPath, group, printer } = ctx.options;
1791
+ const { output, coercion, guidType, regexType, compile, mini, inferred, typeGuards, importPath, group, printer } = ctx.options;
1779
1792
  const dateType = getOasAdapter(adapter).options.dateType;
1780
1793
  if (!node.name) return;
1781
1794
  const isZodImport = ZOD_NAMESPACE_IMPORTS.has(importPath);
@@ -1891,7 +1904,8 @@ const zodGenerator = defineGenerator({
1891
1904
  isName,
1892
1905
  assertName,
1893
1906
  mini,
1894
- cyclic: cyclicSchemas.has(node.name)
1907
+ cyclic: cyclicSchemas.has(node.name),
1908
+ compile
1895
1909
  }),
1896
1910
  hasDirectionalNode && stdPrinters && /* @__PURE__ */ jsx(Zod, {
1897
1911
  name: resolver.schema.inputName(node.name),
@@ -1902,7 +1916,8 @@ const zodGenerator = defineGenerator({
1902
1916
  isName: typeGuards ? resolver.schema.isName(resolver.schema.inputName(node.name)) : null,
1903
1917
  assertName: typeGuards ? resolver.schema.assertName(resolver.schema.inputName(node.name)) : null,
1904
1918
  mini,
1905
- cyclic: cyclicSchemas.has(node.name)
1919
+ cyclic: cyclicSchemas.has(node.name),
1920
+ compile
1906
1921
  })
1907
1922
  ]
1908
1923
  });
@@ -1910,7 +1925,7 @@ const zodGenerator = defineGenerator({
1910
1925
  operation(node, ctx) {
1911
1926
  if (!ast.isHttpOperationNode(node)) return null;
1912
1927
  const { adapter, config, resolver, root } = ctx;
1913
- const { output, coercion, guidType, regexType, mini, inferred, importPath, group, printer } = ctx.options;
1928
+ const { output, coercion, guidType, regexType, compile, mini, inferred, importPath, group, printer } = ctx.options;
1914
1929
  const dateType = getOasAdapter(adapter).options.dateType;
1915
1930
  const isZodImport = ZOD_NAMESPACE_IMPORTS.has(importPath);
1916
1931
  const meta = { file: resolver.file({
@@ -1989,7 +2004,8 @@ const zodGenerator = defineGenerator({
1989
2004
  node: schema,
1990
2005
  printer: schemaPrinter,
1991
2006
  inferTypeName,
1992
- cyclic: false
2007
+ cyclic: false,
2008
+ compile
1993
2009
  })] });
1994
2010
  }
1995
2011
  function buildContentTypeVariants(entries, baseName, decorate, direction) {
@@ -2236,7 +2252,7 @@ const pluginZod = definePlugin((options) => {
2236
2252
  const { output = {
2237
2253
  path: "zod",
2238
2254
  barrel: { type: "named" }
2239
- }, group, exclude = [], include, override = [], mini = false, guidType = "uuid", regexType = "literal", importPath = mini ? "zod/mini" : "zod", coercion = false, inferred = false, typeGuards = false, printer, resolver: userResolver, macros: userMacros } = options;
2255
+ }, group, exclude = [], include, override = [], compile = false, mini = false, guidType = "uuid", regexType = "literal", importPath = mini ? "zod/mini" : "zod", coercion = false, inferred = false, typeGuards = false, printer, resolver: userResolver, macros: userMacros } = options;
2240
2256
  const groupConfig = createGroupConfig(group);
2241
2257
  return {
2242
2258
  name: pluginZodName,
@@ -2253,6 +2269,7 @@ const pluginZod = definePlugin((options) => {
2253
2269
  inferred,
2254
2270
  guidType,
2255
2271
  regexType,
2272
+ compile,
2256
2273
  mini,
2257
2274
  typeGuards,
2258
2275
  printer