@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.cjs +154 -75
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.js +154 -75
- package/dist/index.js.map +1 -1
- package/docs/guides/customization.md +7 -6
- package/docs/options.md +13 -7
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -771,78 +771,6 @@ function createCasedFile(caseLast) {
|
|
|
771
771
|
function getCircularNames(ctx) {
|
|
772
772
|
return ctx.memo("circularNames:set", () => _kubb_kit.ast.graph.getCircularNames(ctx.driver.inputNode?.schemas ?? []));
|
|
773
773
|
}
|
|
774
|
-
// src/components/Zod.tsx
|
|
775
|
-
function Zod({ name, node, printer, inferTypeName, inferKind = "infer", typeGuards, isName, assertName, mini, cyclic, compile }) {
|
|
776
|
-
const output = printer.print(node);
|
|
777
|
-
const printerImports = printer.drainImports();
|
|
778
|
-
if (!output) return;
|
|
779
|
-
const needsAnnotation = cyclic && node.type !== "object";
|
|
780
|
-
const isAlias = _kubb_kit.ast.ref.isAlias(node, printer.options.keysToOmit);
|
|
781
|
-
const isCyclic = Boolean(cyclic || printer.options.cyclicSchemas && _kubb_kit.ast.graph.containsCircular(node, { circularSchemas: printer.options.cyclicSchemas }));
|
|
782
|
-
const value = Boolean(compile) && !isAlias && !isCyclic ? typeof compile === "object" && compile.strict ? `z.compile(${output}, { strict: true })` : `z.compile(${output})` : output;
|
|
783
|
-
const targetType = inferTypeName ?? `z.infer<typeof ${name}>`;
|
|
784
|
-
const shouldGenerateIs = isName && (typeof typeGuards === "object" ? typeGuards.is ?? true : Boolean(typeGuards));
|
|
785
|
-
const shouldGenerateAssert = assertName && (typeof typeGuards === "object" ? typeGuards.assert ?? true : Boolean(typeGuards));
|
|
786
|
-
return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: [
|
|
787
|
-
printerImports.map((imp) => /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
|
|
788
|
-
name: imp.name,
|
|
789
|
-
path: imp.path,
|
|
790
|
-
root: imp.root,
|
|
791
|
-
isTypeOnly: imp.isTypeOnly,
|
|
792
|
-
isNameSpace: imp.isNameSpace
|
|
793
|
-
}, [
|
|
794
|
-
name,
|
|
795
|
-
imp.path,
|
|
796
|
-
imp.name
|
|
797
|
-
].join("-"))),
|
|
798
|
-
/* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Source, {
|
|
799
|
-
name,
|
|
800
|
-
isExportable: true,
|
|
801
|
-
isIndexable: true,
|
|
802
|
-
children: /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.Const, {
|
|
803
|
-
export: true,
|
|
804
|
-
name,
|
|
805
|
-
type: needsAnnotation ? mini ? "z.ZodMiniType" : "z.ZodType" : void 0,
|
|
806
|
-
children: value
|
|
807
|
-
})
|
|
808
|
-
}),
|
|
809
|
-
inferTypeName && /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Source, {
|
|
810
|
-
name: inferTypeName,
|
|
811
|
-
isExportable: true,
|
|
812
|
-
isIndexable: true,
|
|
813
|
-
isTypeOnly: true,
|
|
814
|
-
children: /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.Type, {
|
|
815
|
-
export: true,
|
|
816
|
-
name: inferTypeName,
|
|
817
|
-
children: `z.${inferKind}<typeof ${name}>`
|
|
818
|
-
})
|
|
819
|
-
}),
|
|
820
|
-
shouldGenerateIs && /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Source, {
|
|
821
|
-
name: isName,
|
|
822
|
-
isExportable: true,
|
|
823
|
-
isIndexable: true,
|
|
824
|
-
children: /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.Const, {
|
|
825
|
-
export: true,
|
|
826
|
-
name: isName,
|
|
827
|
-
JSDoc: { comments: [`Type guard for {@link ${name}}`] },
|
|
828
|
-
children: mini ? `(data: unknown): data is ${targetType} => z.validate(${name}, data)` : `(data: unknown): data is ${targetType} => ${name}.validate(data)`
|
|
829
|
-
})
|
|
830
|
-
}),
|
|
831
|
-
shouldGenerateAssert && /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Source, {
|
|
832
|
-
name: assertName,
|
|
833
|
-
isExportable: true,
|
|
834
|
-
isIndexable: true,
|
|
835
|
-
children: /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.Function, {
|
|
836
|
-
export: true,
|
|
837
|
-
name: assertName,
|
|
838
|
-
params: "data: unknown",
|
|
839
|
-
returnType: `asserts data is ${targetType}`,
|
|
840
|
-
JSDoc: { comments: [`Asserter for {@link ${name}}`, "@throws {z.ZodError} If data is invalid"] },
|
|
841
|
-
children: mini ? `if (!z.validate(${name}, data)) {\n z.parse(${name}, data)\n}` : `if (!${name}.validate(data)) {\n ${name}.parse(data)\n}`
|
|
842
|
-
})
|
|
843
|
-
})
|
|
844
|
-
] });
|
|
845
|
-
}
|
|
846
774
|
// src/utils.ts
|
|
847
775
|
/**
|
|
848
776
|
* Returns `true` when the given coercion option enables coercion for the specified type.
|
|
@@ -1335,6 +1263,40 @@ function hasCoercedDiscriminator({ member, propertyName, options }) {
|
|
|
1335
1263
|
})?.coerce;
|
|
1336
1264
|
});
|
|
1337
1265
|
}
|
|
1266
|
+
/**
|
|
1267
|
+
* Whether `z.compile(schema, { strict: true })` throws for the node. Zod runs an unsupported schema below an object
|
|
1268
|
+
* property or an array, tuple or record item on its runtime parser, so only a coerced scalar or a `z.xor` that compiles
|
|
1269
|
+
* inline with the root throws: the node itself, or one reached through refs and union or intersection members.
|
|
1270
|
+
* `siblings` resolves a generated ref, which names another schema of the same file and carries no target.
|
|
1271
|
+
*
|
|
1272
|
+
* Mirrors the built-in handlers, so a type with a `printer.nodes` override is judged as if it printed the built-in output.
|
|
1273
|
+
*/
|
|
1274
|
+
function throwsOnStrictCompile({ node, options, siblings, seen = /* @__PURE__ */ new Set() }) {
|
|
1275
|
+
if (!node || seen.has(node)) return false;
|
|
1276
|
+
seen.add(node);
|
|
1277
|
+
const throws = (child) => throwsOnStrictCompile({
|
|
1278
|
+
node: child,
|
|
1279
|
+
options,
|
|
1280
|
+
siblings,
|
|
1281
|
+
seen
|
|
1282
|
+
});
|
|
1283
|
+
switch (node.type) {
|
|
1284
|
+
case _kubb_kit.ast.schema.types.ref: return throws(node.schema ?? (node.ref || !node.name ? void 0 : siblings?.get(node.name)));
|
|
1285
|
+
case _kubb_kit.ast.schema.types.union:
|
|
1286
|
+
if (node.strategy === "one" && options.oneOfType === "xor") return true;
|
|
1287
|
+
return !!getLiteralUnion({
|
|
1288
|
+
node,
|
|
1289
|
+
options
|
|
1290
|
+
})?.coerce || (node.members ?? []).some(throws);
|
|
1291
|
+
case _kubb_kit.ast.schema.types.intersection: return (node.members ?? []).some(throws);
|
|
1292
|
+
case _kubb_kit.ast.schema.types.bigint: return true;
|
|
1293
|
+
case _kubb_kit.ast.schema.types.string: return shouldCoerce(options.coercion, "strings");
|
|
1294
|
+
case _kubb_kit.ast.schema.types.number:
|
|
1295
|
+
case _kubb_kit.ast.schema.types.integer: return shouldCoerce(options.coercion, "numbers");
|
|
1296
|
+
case _kubb_kit.ast.schema.types.date: return node.representation === "date" && options.direction !== "encode" && shouldCoerce(options.coercion, "dates");
|
|
1297
|
+
default: return false;
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1338
1300
|
function hasPlainDiscriminator({ member, propertyName }) {
|
|
1339
1301
|
const schemas = _kubb_kit.ast.schema.findProperties({
|
|
1340
1302
|
node: member,
|
|
@@ -1598,6 +1560,111 @@ function withInputChecks(nodes) {
|
|
|
1598
1560
|
};
|
|
1599
1561
|
return Object.fromEntries(Object.values(_kubb_kit.ast.schema.types).flatMap(wrapHandler));
|
|
1600
1562
|
}
|
|
1563
|
+
// src/components/Zod.tsx
|
|
1564
|
+
/**
|
|
1565
|
+
* Whether the schema reaches a circular schema through its refs. `containsCircular` reads the refs the node holds,
|
|
1566
|
+
* while Zod refuses to compile a cycle anywhere below the root. A generated ref carries no target, so `siblings` resolves it.
|
|
1567
|
+
*/
|
|
1568
|
+
function reachesCycle({ node, siblings, cyclicSchemas, seen = /* @__PURE__ */ new Set() }) {
|
|
1569
|
+
if (!cyclicSchemas?.size || seen.has(node)) return false;
|
|
1570
|
+
seen.add(node);
|
|
1571
|
+
return _kubb_kit.ast.schema.find(node, {
|
|
1572
|
+
followRefs: true,
|
|
1573
|
+
predicate(schema) {
|
|
1574
|
+
if (schema.type !== _kubb_kit.ast.schema.types.ref) return false;
|
|
1575
|
+
const name = _kubb_kit.ast.ref.getName(schema);
|
|
1576
|
+
if (name && cyclicSchemas.has(name)) return true;
|
|
1577
|
+
const sibling = schema.ref || !schema.name ? void 0 : siblings?.get(schema.name);
|
|
1578
|
+
return !!sibling && reachesCycle({
|
|
1579
|
+
node: sibling,
|
|
1580
|
+
siblings,
|
|
1581
|
+
cyclicSchemas,
|
|
1582
|
+
seen
|
|
1583
|
+
});
|
|
1584
|
+
}
|
|
1585
|
+
}) !== void 0;
|
|
1586
|
+
}
|
|
1587
|
+
function Zod({ name, node, printer, inferTypeName, inferKind = "infer", typeGuards, isName, assertName, mini, cyclic, compile, siblings }) {
|
|
1588
|
+
const output = printer.print(node);
|
|
1589
|
+
const printerImports = printer.drainImports();
|
|
1590
|
+
if (!output) return;
|
|
1591
|
+
const needsAnnotation = cyclic && node.type !== "object";
|
|
1592
|
+
const isAlias = _kubb_kit.ast.ref.isAlias(node, printer.options.keysToOmit);
|
|
1593
|
+
const isCyclic = Boolean(cyclic || printer.options.cyclicSchemas && _kubb_kit.ast.graph.containsCircular(node, { circularSchemas: printer.options.cyclicSchemas }));
|
|
1594
|
+
const isStrict = typeof compile === "object" && Boolean(compile.strict);
|
|
1595
|
+
const throwsOnCompile = isStrict && (throwsOnStrictCompile({
|
|
1596
|
+
node,
|
|
1597
|
+
options: printer.options,
|
|
1598
|
+
siblings
|
|
1599
|
+
}) || reachesCycle({
|
|
1600
|
+
node,
|
|
1601
|
+
siblings,
|
|
1602
|
+
cyclicSchemas: printer.options.cyclicSchemas
|
|
1603
|
+
}));
|
|
1604
|
+
const value = Boolean(compile) && !isAlias && !isCyclic && !throwsOnCompile ? isStrict ? `z.compile(${output}, { strict: true })` : `z.compile(${output})` : output;
|
|
1605
|
+
const targetType = inferTypeName ?? `z.infer<typeof ${name}>`;
|
|
1606
|
+
const shouldGenerateIs = isName && (typeof typeGuards === "object" ? typeGuards.is ?? true : Boolean(typeGuards));
|
|
1607
|
+
const shouldGenerateAssert = assertName && (typeof typeGuards === "object" ? typeGuards.assert ?? true : Boolean(typeGuards));
|
|
1608
|
+
return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: [
|
|
1609
|
+
printerImports.map((imp) => /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
|
|
1610
|
+
name: imp.name,
|
|
1611
|
+
path: imp.path,
|
|
1612
|
+
root: imp.root,
|
|
1613
|
+
isTypeOnly: imp.isTypeOnly,
|
|
1614
|
+
isNameSpace: imp.isNameSpace
|
|
1615
|
+
}, [
|
|
1616
|
+
name,
|
|
1617
|
+
imp.path,
|
|
1618
|
+
imp.name
|
|
1619
|
+
].join("-"))),
|
|
1620
|
+
/* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Source, {
|
|
1621
|
+
name,
|
|
1622
|
+
isExportable: true,
|
|
1623
|
+
isIndexable: true,
|
|
1624
|
+
children: /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.Const, {
|
|
1625
|
+
export: true,
|
|
1626
|
+
name,
|
|
1627
|
+
type: needsAnnotation ? mini ? "z.ZodMiniType" : "z.ZodType" : void 0,
|
|
1628
|
+
children: value
|
|
1629
|
+
})
|
|
1630
|
+
}),
|
|
1631
|
+
inferTypeName && /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Source, {
|
|
1632
|
+
name: inferTypeName,
|
|
1633
|
+
isExportable: true,
|
|
1634
|
+
isIndexable: true,
|
|
1635
|
+
isTypeOnly: true,
|
|
1636
|
+
children: /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.Type, {
|
|
1637
|
+
export: true,
|
|
1638
|
+
name: inferTypeName,
|
|
1639
|
+
children: `z.${inferKind}<typeof ${name}>`
|
|
1640
|
+
})
|
|
1641
|
+
}),
|
|
1642
|
+
shouldGenerateIs && /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Source, {
|
|
1643
|
+
name: isName,
|
|
1644
|
+
isExportable: true,
|
|
1645
|
+
isIndexable: true,
|
|
1646
|
+
children: /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.Const, {
|
|
1647
|
+
export: true,
|
|
1648
|
+
name: isName,
|
|
1649
|
+
JSDoc: { comments: [`Type guard for {@link ${name}}`] },
|
|
1650
|
+
children: mini ? `(data: unknown): data is ${targetType} => z.validate(${name}, data)` : `(data: unknown): data is ${targetType} => ${name}.validate(data)`
|
|
1651
|
+
})
|
|
1652
|
+
}),
|
|
1653
|
+
shouldGenerateAssert && /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Source, {
|
|
1654
|
+
name: assertName,
|
|
1655
|
+
isExportable: true,
|
|
1656
|
+
isIndexable: true,
|
|
1657
|
+
children: /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.Function, {
|
|
1658
|
+
export: true,
|
|
1659
|
+
name: assertName,
|
|
1660
|
+
params: "data: unknown",
|
|
1661
|
+
returnType: `asserts data is ${targetType}`,
|
|
1662
|
+
JSDoc: { comments: [`Asserter for {@link ${name}}`, "@throws {z.ZodError} If data is invalid"] },
|
|
1663
|
+
children: mini ? `if (!z.validate(${name}, data)) {\n z.parse(${name}, data)\n}` : `if (!${name}.validate(data)) {\n ${name}.parse(data)\n}`
|
|
1664
|
+
})
|
|
1665
|
+
})
|
|
1666
|
+
] });
|
|
1667
|
+
}
|
|
1601
1668
|
// src/printers/printerZod.ts
|
|
1602
1669
|
function strictOneOfMember(member, node, cyclicSchemas) {
|
|
1603
1670
|
if (node.type === _kubb_kit.ast.schema.types.ref) {
|
|
@@ -1718,10 +1785,19 @@ function containsDirectionalNode({ node, printerOptions }) {
|
|
|
1718
1785
|
node: schema,
|
|
1719
1786
|
printerOptions
|
|
1720
1787
|
}),
|
|
1721
|
-
followRefs: true
|
|
1788
|
+
followRefs: true,
|
|
1789
|
+
cache: getDirectionalCache(printerOptions)
|
|
1722
1790
|
}) !== void 0;
|
|
1723
1791
|
}
|
|
1724
1792
|
/**
|
|
1793
|
+
* The `find` cache for {@link containsDirectionalNode}, one per plugin per build and per option set
|
|
1794
|
+
* the probe reads. A `printer.nodes` override has no string key, so it searches without a cache.
|
|
1795
|
+
*/
|
|
1796
|
+
function getDirectionalCache({ resolver, nodes, coercion, dateType }) {
|
|
1797
|
+
if (!resolver || nodes) return void 0;
|
|
1798
|
+
return resolver.memo(`zodDirectionalNodes:${shouldCoerce(coercion, "dates")}:${dateType}`, () => /* @__PURE__ */ new WeakMap());
|
|
1799
|
+
}
|
|
1800
|
+
/**
|
|
1725
1801
|
* Names of the `$ref` schemas the generator should route to their input (encode) variant.
|
|
1726
1802
|
*/
|
|
1727
1803
|
function collectDirectionalRefNames({ node, printerOptions }) {
|
|
@@ -2087,8 +2163,10 @@ const zodGenerator = (0, _kubb_kit.defineGenerator)({
|
|
|
2087
2163
|
cyclicSchemas: getCircularNames(ctx),
|
|
2088
2164
|
nodes: printer?.nodes
|
|
2089
2165
|
};
|
|
2166
|
+
const siblings = /* @__PURE__ */ new Map();
|
|
2090
2167
|
function renderSchemaEntry({ schema, name, keysToOmit, direction = "decode" }) {
|
|
2091
2168
|
if (!schema) return null;
|
|
2169
|
+
siblings.set(name, schema);
|
|
2092
2170
|
const directionalRefNames = direction === "encode" && !mini ? new Set(collectDirectionalRefNames({
|
|
2093
2171
|
node: schema,
|
|
2094
2172
|
printerOptions
|
|
@@ -2120,7 +2198,8 @@ const zodGenerator = (0, _kubb_kit.defineGenerator)({
|
|
|
2120
2198
|
inferTypeName: inferred ? resolver.schema.type(name) : null,
|
|
2121
2199
|
inferKind: aliasKind(inferred, direction),
|
|
2122
2200
|
cyclic: false,
|
|
2123
|
-
compile
|
|
2201
|
+
compile,
|
|
2202
|
+
siblings
|
|
2124
2203
|
})] });
|
|
2125
2204
|
}
|
|
2126
2205
|
function buildContentTypeVariants(entries, baseName, decorate, direction) {
|
|
@@ -2301,7 +2380,7 @@ var compatibility = {
|
|
|
2301
2380
|
"node": ">=22.22"
|
|
2302
2381
|
};
|
|
2303
2382
|
// package.json
|
|
2304
|
-
var version = "5.9.
|
|
2383
|
+
var version = "5.9.1";
|
|
2305
2384
|
// src/resolvers/resolverZod.ts
|
|
2306
2385
|
/**
|
|
2307
2386
|
* Default resolver used by `@kubb/plugin-zod`. Decides the names and file
|