@kubb/plugin-zod 5.9.0 → 5.9.1

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.cts CHANGED
@@ -343,7 +343,8 @@ type ResolverZod = Resolver & {
343
343
  type CompileOptions = {
344
344
  /**
345
345
  * Throw an error if any part of the schema cannot be compiled into flat JavaScript,
346
- * preventing silent fallback to the standard interpreter.
346
+ * preventing silent fallback to the standard interpreter. A schema Zod refuses to
347
+ * compile, such as a coerced scalar or a `z.xor`, is left uncompiled.
347
348
  *
348
349
  * @default false
349
350
  */
@@ -513,6 +514,7 @@ declare global {
513
514
  typeName: string;
514
515
  type: string;
515
516
  zodPrinter: ReturnType<typeof printerZod> | ReturnType<typeof printerZodMini>;
517
+ zodDirectionalNodes: WeakMap<ast.SchemaNode, ast.SchemaNode | null>;
516
518
  }
517
519
  }
518
520
  }
@@ -571,5 +573,4 @@ export declare const pluginZod: import("@kubb/kit").PluginFactory<PluginZod>;
571
573
  * ```
572
574
  */
573
575
  export declare const resolverZod: ResolverZod;
574
- export { type CompileOptions, type PluginZod, type PrinterZodFactory, type PrinterZodMiniFactory, type PrinterZodMiniNodes, type PrinterZodMiniOptions, type PrinterZodNodes, type PrinterZodOptions, type ResolverZod, pluginZod as default };
575
- //# sourceMappingURL=index.d.cts.map
576
+ export { type CompileOptions, type PluginZod, type PrinterZodFactory, type PrinterZodMiniFactory, type PrinterZodMiniNodes, type PrinterZodMiniOptions, type PrinterZodNodes, type PrinterZodOptions, type ResolverZod, pluginZod as default };
package/dist/index.d.ts CHANGED
@@ -343,7 +343,8 @@ type ResolverZod = Resolver & {
343
343
  type CompileOptions = {
344
344
  /**
345
345
  * Throw an error if any part of the schema cannot be compiled into flat JavaScript,
346
- * preventing silent fallback to the standard interpreter.
346
+ * preventing silent fallback to the standard interpreter. A schema Zod refuses to
347
+ * compile, such as a coerced scalar or a `z.xor`, is left uncompiled.
347
348
  *
348
349
  * @default false
349
350
  */
@@ -513,6 +514,7 @@ declare global {
513
514
  typeName: string;
514
515
  type: string;
515
516
  zodPrinter: ReturnType<typeof printerZod> | ReturnType<typeof printerZodMini>;
517
+ zodDirectionalNodes: WeakMap<ast.SchemaNode, ast.SchemaNode | null>;
516
518
  }
517
519
  }
518
520
  }
@@ -571,5 +573,4 @@ export declare const pluginZod: import("@kubb/kit").PluginFactory<PluginZod>;
571
573
  * ```
572
574
  */
573
575
  export declare const resolverZod: ResolverZod;
574
- export { type CompileOptions, type PluginZod, type PrinterZodFactory, type PrinterZodMiniFactory, type PrinterZodMiniNodes, type PrinterZodMiniOptions, type PrinterZodNodes, type PrinterZodOptions, type ResolverZod, pluginZod as default };
575
- //# sourceMappingURL=index.d.ts.map
576
+ export { type CompileOptions, type PluginZod, type PrinterZodFactory, type PrinterZodMiniFactory, type PrinterZodMiniNodes, type PrinterZodMiniOptions, type PrinterZodNodes, type PrinterZodOptions, type ResolverZod, pluginZod as default };
package/dist/index.js CHANGED
@@ -767,78 +767,6 @@ function createCasedFile(caseLast) {
767
767
  function getCircularNames(ctx) {
768
768
  return ctx.memo("circularNames:set", () => ast.graph.getCircularNames(ctx.driver.inputNode?.schemas ?? []));
769
769
  }
770
- // src/components/Zod.tsx
771
- function Zod({ name, node, printer, inferTypeName, inferKind = "infer", typeGuards, isName, assertName, mini, cyclic, compile }) {
772
- const output = printer.print(node);
773
- const printerImports = printer.drainImports();
774
- if (!output) return;
775
- const needsAnnotation = cyclic && node.type !== "object";
776
- const isAlias = ast.ref.isAlias(node, printer.options.keysToOmit);
777
- const isCyclic = Boolean(cyclic || printer.options.cyclicSchemas && ast.graph.containsCircular(node, { circularSchemas: printer.options.cyclicSchemas }));
778
- const value = Boolean(compile) && !isAlias && !isCyclic ? typeof compile === "object" && compile.strict ? `z.compile(${output}, { strict: true })` : `z.compile(${output})` : output;
779
- const targetType = inferTypeName ?? `z.infer<typeof ${name}>`;
780
- const shouldGenerateIs = isName && (typeof typeGuards === "object" ? typeGuards.is ?? true : Boolean(typeGuards));
781
- const shouldGenerateAssert = assertName && (typeof typeGuards === "object" ? typeGuards.assert ?? true : Boolean(typeGuards));
782
- return /* @__PURE__ */ jsxs(Fragment, { children: [
783
- printerImports.map((imp) => /* @__PURE__ */ jsx(File.Import, {
784
- name: imp.name,
785
- path: imp.path,
786
- root: imp.root,
787
- isTypeOnly: imp.isTypeOnly,
788
- isNameSpace: imp.isNameSpace
789
- }, [
790
- name,
791
- imp.path,
792
- imp.name
793
- ].join("-"))),
794
- /* @__PURE__ */ jsx(File.Source, {
795
- name,
796
- isExportable: true,
797
- isIndexable: true,
798
- children: /* @__PURE__ */ jsx(Const, {
799
- export: true,
800
- name,
801
- type: needsAnnotation ? mini ? "z.ZodMiniType" : "z.ZodType" : void 0,
802
- children: value
803
- })
804
- }),
805
- inferTypeName && /* @__PURE__ */ jsx(File.Source, {
806
- name: inferTypeName,
807
- isExportable: true,
808
- isIndexable: true,
809
- isTypeOnly: true,
810
- children: /* @__PURE__ */ jsx(Type, {
811
- export: true,
812
- name: inferTypeName,
813
- children: `z.${inferKind}<typeof ${name}>`
814
- })
815
- }),
816
- shouldGenerateIs && /* @__PURE__ */ jsx(File.Source, {
817
- name: isName,
818
- isExportable: true,
819
- isIndexable: true,
820
- children: /* @__PURE__ */ jsx(Const, {
821
- export: true,
822
- name: isName,
823
- JSDoc: { comments: [`Type guard for {@link ${name}}`] },
824
- children: mini ? `(data: unknown): data is ${targetType} => z.validate(${name}, data)` : `(data: unknown): data is ${targetType} => ${name}.validate(data)`
825
- })
826
- }),
827
- shouldGenerateAssert && /* @__PURE__ */ jsx(File.Source, {
828
- name: assertName,
829
- isExportable: true,
830
- isIndexable: true,
831
- children: /* @__PURE__ */ jsx(Function, {
832
- export: true,
833
- name: assertName,
834
- params: "data: unknown",
835
- returnType: `asserts data is ${targetType}`,
836
- JSDoc: { comments: [`Asserter for {@link ${name}}`, "@throws {z.ZodError} If data is invalid"] },
837
- children: mini ? `if (!z.validate(${name}, data)) {\n z.parse(${name}, data)\n}` : `if (!${name}.validate(data)) {\n ${name}.parse(data)\n}`
838
- })
839
- })
840
- ] });
841
- }
842
770
  // src/utils.ts
843
771
  /**
844
772
  * Returns `true` when the given coercion option enables coercion for the specified type.
@@ -1331,6 +1259,40 @@ function hasCoercedDiscriminator({ member, propertyName, options }) {
1331
1259
  })?.coerce;
1332
1260
  });
1333
1261
  }
1262
+ /**
1263
+ * Whether `z.compile(schema, { strict: true })` throws for the node. Zod runs an unsupported schema below an object
1264
+ * property or an array, tuple or record item on its runtime parser, so only a coerced scalar or a `z.xor` that compiles
1265
+ * inline with the root throws: the node itself, or one reached through refs and union or intersection members.
1266
+ * `siblings` resolves a generated ref, which names another schema of the same file and carries no target.
1267
+ *
1268
+ * Mirrors the built-in handlers, so a type with a `printer.nodes` override is judged as if it printed the built-in output.
1269
+ */
1270
+ function throwsOnStrictCompile({ node, options, siblings, seen = /* @__PURE__ */ new Set() }) {
1271
+ if (!node || seen.has(node)) return false;
1272
+ seen.add(node);
1273
+ const throws = (child) => throwsOnStrictCompile({
1274
+ node: child,
1275
+ options,
1276
+ siblings,
1277
+ seen
1278
+ });
1279
+ switch (node.type) {
1280
+ case ast.schema.types.ref: return throws(node.schema ?? (node.ref || !node.name ? void 0 : siblings?.get(node.name)));
1281
+ case ast.schema.types.union:
1282
+ if (node.strategy === "one" && options.oneOfType === "xor") return true;
1283
+ return !!getLiteralUnion({
1284
+ node,
1285
+ options
1286
+ })?.coerce || (node.members ?? []).some(throws);
1287
+ case ast.schema.types.intersection: return (node.members ?? []).some(throws);
1288
+ case ast.schema.types.bigint: return true;
1289
+ case ast.schema.types.string: return shouldCoerce(options.coercion, "strings");
1290
+ case ast.schema.types.number:
1291
+ case ast.schema.types.integer: return shouldCoerce(options.coercion, "numbers");
1292
+ case ast.schema.types.date: return node.representation === "date" && options.direction !== "encode" && shouldCoerce(options.coercion, "dates");
1293
+ default: return false;
1294
+ }
1295
+ }
1334
1296
  function hasPlainDiscriminator({ member, propertyName }) {
1335
1297
  const schemas = ast.schema.findProperties({
1336
1298
  node: member,
@@ -1594,6 +1556,111 @@ function withInputChecks(nodes) {
1594
1556
  };
1595
1557
  return Object.fromEntries(Object.values(ast.schema.types).flatMap(wrapHandler));
1596
1558
  }
1559
+ // src/components/Zod.tsx
1560
+ /**
1561
+ * Whether the schema reaches a circular schema through its refs. `containsCircular` reads the refs the node holds,
1562
+ * while Zod refuses to compile a cycle anywhere below the root. A generated ref carries no target, so `siblings` resolves it.
1563
+ */
1564
+ function reachesCycle({ node, siblings, cyclicSchemas, seen = /* @__PURE__ */ new Set() }) {
1565
+ if (!cyclicSchemas?.size || seen.has(node)) return false;
1566
+ seen.add(node);
1567
+ return ast.schema.find(node, {
1568
+ followRefs: true,
1569
+ predicate(schema) {
1570
+ if (schema.type !== ast.schema.types.ref) return false;
1571
+ const name = ast.ref.getName(schema);
1572
+ if (name && cyclicSchemas.has(name)) return true;
1573
+ const sibling = schema.ref || !schema.name ? void 0 : siblings?.get(schema.name);
1574
+ return !!sibling && reachesCycle({
1575
+ node: sibling,
1576
+ siblings,
1577
+ cyclicSchemas,
1578
+ seen
1579
+ });
1580
+ }
1581
+ }) !== void 0;
1582
+ }
1583
+ function Zod({ name, node, printer, inferTypeName, inferKind = "infer", typeGuards, isName, assertName, mini, cyclic, compile, siblings }) {
1584
+ const output = printer.print(node);
1585
+ const printerImports = printer.drainImports();
1586
+ if (!output) return;
1587
+ const needsAnnotation = cyclic && node.type !== "object";
1588
+ const isAlias = ast.ref.isAlias(node, printer.options.keysToOmit);
1589
+ const isCyclic = Boolean(cyclic || printer.options.cyclicSchemas && ast.graph.containsCircular(node, { circularSchemas: printer.options.cyclicSchemas }));
1590
+ const isStrict = typeof compile === "object" && Boolean(compile.strict);
1591
+ const throwsOnCompile = isStrict && (throwsOnStrictCompile({
1592
+ node,
1593
+ options: printer.options,
1594
+ siblings
1595
+ }) || reachesCycle({
1596
+ node,
1597
+ siblings,
1598
+ cyclicSchemas: printer.options.cyclicSchemas
1599
+ }));
1600
+ const value = Boolean(compile) && !isAlias && !isCyclic && !throwsOnCompile ? isStrict ? `z.compile(${output}, { strict: true })` : `z.compile(${output})` : output;
1601
+ const targetType = inferTypeName ?? `z.infer<typeof ${name}>`;
1602
+ const shouldGenerateIs = isName && (typeof typeGuards === "object" ? typeGuards.is ?? true : Boolean(typeGuards));
1603
+ const shouldGenerateAssert = assertName && (typeof typeGuards === "object" ? typeGuards.assert ?? true : Boolean(typeGuards));
1604
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1605
+ printerImports.map((imp) => /* @__PURE__ */ jsx(File.Import, {
1606
+ name: imp.name,
1607
+ path: imp.path,
1608
+ root: imp.root,
1609
+ isTypeOnly: imp.isTypeOnly,
1610
+ isNameSpace: imp.isNameSpace
1611
+ }, [
1612
+ name,
1613
+ imp.path,
1614
+ imp.name
1615
+ ].join("-"))),
1616
+ /* @__PURE__ */ jsx(File.Source, {
1617
+ name,
1618
+ isExportable: true,
1619
+ isIndexable: true,
1620
+ children: /* @__PURE__ */ jsx(Const, {
1621
+ export: true,
1622
+ name,
1623
+ type: needsAnnotation ? mini ? "z.ZodMiniType" : "z.ZodType" : void 0,
1624
+ children: value
1625
+ })
1626
+ }),
1627
+ inferTypeName && /* @__PURE__ */ jsx(File.Source, {
1628
+ name: inferTypeName,
1629
+ isExportable: true,
1630
+ isIndexable: true,
1631
+ isTypeOnly: true,
1632
+ children: /* @__PURE__ */ jsx(Type, {
1633
+ export: true,
1634
+ name: inferTypeName,
1635
+ children: `z.${inferKind}<typeof ${name}>`
1636
+ })
1637
+ }),
1638
+ shouldGenerateIs && /* @__PURE__ */ jsx(File.Source, {
1639
+ name: isName,
1640
+ isExportable: true,
1641
+ isIndexable: true,
1642
+ children: /* @__PURE__ */ jsx(Const, {
1643
+ export: true,
1644
+ name: isName,
1645
+ JSDoc: { comments: [`Type guard for {@link ${name}}`] },
1646
+ children: mini ? `(data: unknown): data is ${targetType} => z.validate(${name}, data)` : `(data: unknown): data is ${targetType} => ${name}.validate(data)`
1647
+ })
1648
+ }),
1649
+ shouldGenerateAssert && /* @__PURE__ */ jsx(File.Source, {
1650
+ name: assertName,
1651
+ isExportable: true,
1652
+ isIndexable: true,
1653
+ children: /* @__PURE__ */ jsx(Function, {
1654
+ export: true,
1655
+ name: assertName,
1656
+ params: "data: unknown",
1657
+ returnType: `asserts data is ${targetType}`,
1658
+ JSDoc: { comments: [`Asserter for {@link ${name}}`, "@throws {z.ZodError} If data is invalid"] },
1659
+ children: mini ? `if (!z.validate(${name}, data)) {\n z.parse(${name}, data)\n}` : `if (!${name}.validate(data)) {\n ${name}.parse(data)\n}`
1660
+ })
1661
+ })
1662
+ ] });
1663
+ }
1597
1664
  // src/printers/printerZod.ts
1598
1665
  function strictOneOfMember(member, node, cyclicSchemas) {
1599
1666
  if (node.type === ast.schema.types.ref) {
@@ -1714,10 +1781,19 @@ function containsDirectionalNode({ node, printerOptions }) {
1714
1781
  node: schema,
1715
1782
  printerOptions
1716
1783
  }),
1717
- followRefs: true
1784
+ followRefs: true,
1785
+ cache: getDirectionalCache(printerOptions)
1718
1786
  }) !== void 0;
1719
1787
  }
1720
1788
  /**
1789
+ * The `find` cache for {@link containsDirectionalNode}, one per plugin per build and per option set
1790
+ * the probe reads. A `printer.nodes` override has no string key, so it searches without a cache.
1791
+ */
1792
+ function getDirectionalCache({ resolver, nodes, coercion, dateType }) {
1793
+ if (!resolver || nodes) return void 0;
1794
+ return resolver.memo(`zodDirectionalNodes:${shouldCoerce(coercion, "dates")}:${dateType}`, () => /* @__PURE__ */ new WeakMap());
1795
+ }
1796
+ /**
1721
1797
  * Names of the `$ref` schemas the generator should route to their input (encode) variant.
1722
1798
  */
1723
1799
  function collectDirectionalRefNames({ node, printerOptions }) {
@@ -2083,8 +2159,10 @@ const zodGenerator = defineGenerator({
2083
2159
  cyclicSchemas: getCircularNames(ctx),
2084
2160
  nodes: printer?.nodes
2085
2161
  };
2162
+ const siblings = /* @__PURE__ */ new Map();
2086
2163
  function renderSchemaEntry({ schema, name, keysToOmit, direction = "decode" }) {
2087
2164
  if (!schema) return null;
2165
+ siblings.set(name, schema);
2088
2166
  const directionalRefNames = direction === "encode" && !mini ? new Set(collectDirectionalRefNames({
2089
2167
  node: schema,
2090
2168
  printerOptions
@@ -2116,7 +2194,8 @@ const zodGenerator = defineGenerator({
2116
2194
  inferTypeName: inferred ? resolver.schema.type(name) : null,
2117
2195
  inferKind: aliasKind(inferred, direction),
2118
2196
  cyclic: false,
2119
- compile
2197
+ compile,
2198
+ siblings
2120
2199
  })] });
2121
2200
  }
2122
2201
  function buildContentTypeVariants(entries, baseName, decorate, direction) {
@@ -2297,7 +2376,7 @@ var compatibility = {
2297
2376
  "node": ">=22.22"
2298
2377
  };
2299
2378
  // package.json
2300
- var version = "5.9.0";
2379
+ var version = "5.9.1";
2301
2380
  // src/resolvers/resolverZod.ts
2302
2381
  /**
2303
2382
  * Default resolver used by `@kubb/plugin-zod`. Decides the names and file