@kubb/plugin-zod 5.2.0-canary.20260922T120902 → 5.2.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 CHANGED
@@ -745,31 +745,61 @@ function mapSchemaItems(node, transform) {
745
745
  }
746
746
  //#endregion
747
747
  //#region src/components/Zod.tsx
748
- function Zod({ name, node, printer, inferTypeName, cyclic }) {
748
+ function Zod({ name, node, printer, inferTypeName, typeGuards, isName, assertName, mini, cyclic }) {
749
749
  const output = printer.print(node);
750
750
  if (!output) return;
751
751
  const needsAnnotation = cyclic && node.type !== "object";
752
- return /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsxs)(kubb_jsx_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Source, {
753
- name,
754
- isExportable: true,
755
- isIndexable: true,
756
- children: /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.Const, {
757
- export: true,
752
+ const targetType = inferTypeName ?? `z.infer<typeof ${name}>`;
753
+ const shouldGenerateIs = isName && (typeof typeGuards === "object" ? typeGuards.is ?? true : Boolean(typeGuards));
754
+ const shouldGenerateAssert = assertName && (typeof typeGuards === "object" ? typeGuards.assert ?? true : Boolean(typeGuards));
755
+ return /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsxs)(kubb_jsx_jsx_runtime.Fragment, { children: [
756
+ /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Source, {
758
757
  name,
759
- type: needsAnnotation ? "z.ZodType" : void 0,
760
- children: output
761
- })
762
- }), inferTypeName && /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Source, {
763
- name: inferTypeName,
764
- isExportable: true,
765
- isIndexable: true,
766
- isTypeOnly: true,
767
- children: /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.Type, {
768
- export: true,
758
+ isExportable: true,
759
+ isIndexable: true,
760
+ children: /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.Const, {
761
+ export: true,
762
+ name,
763
+ type: needsAnnotation ? "z.ZodType" : void 0,
764
+ children: output
765
+ })
766
+ }),
767
+ inferTypeName && /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Source, {
769
768
  name: inferTypeName,
770
- children: `z.infer<typeof ${name}>`
769
+ isExportable: true,
770
+ isIndexable: true,
771
+ isTypeOnly: true,
772
+ children: /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.Type, {
773
+ export: true,
774
+ name: inferTypeName,
775
+ children: `z.infer<typeof ${name}>`
776
+ })
777
+ }),
778
+ shouldGenerateIs && /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Source, {
779
+ name: isName,
780
+ isExportable: true,
781
+ isIndexable: true,
782
+ children: /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.Const, {
783
+ export: true,
784
+ name: isName,
785
+ JSDoc: { comments: [`Type guard for {@link ${name}}`] },
786
+ children: mini ? `(data: unknown): data is ${targetType} => z.validate(${name}, data)` : `(data: unknown): data is ${targetType} => ${name}.validate(data)`
787
+ })
788
+ }),
789
+ shouldGenerateAssert && /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Source, {
790
+ name: assertName,
791
+ isExportable: true,
792
+ isIndexable: true,
793
+ children: /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.Function, {
794
+ export: true,
795
+ name: assertName,
796
+ params: "data: unknown",
797
+ returnType: `asserts data is ${targetType}`,
798
+ JSDoc: { comments: [`Asserter for {@link ${name}}`, "@throws {z.ZodError} If data is invalid"] },
799
+ children: mini ? `if (!z.validate(${name}, data)) {\n z.parse(${name}, data)\n}` : `if (!${name}.validate(data)) {\n ${name}.parse(data)\n}`
800
+ })
771
801
  })
772
- })] });
802
+ ] });
773
803
  }
774
804
  //#endregion
775
805
  //#region src/constants.ts
@@ -1044,8 +1074,20 @@ function buildGroupedParamsSchema({ params, optional }) {
1044
1074
  }
1045
1075
  //#endregion
1046
1076
  //#region src/printers/printerZod.ts
1047
- function strictOneOfMember$1(member, node, cyclicSchemas) {
1048
- if (node.type === "object" && node.additionalProperties === void 0) return `${member}.strict()`;
1077
+ /**
1078
+ * A `oneOf` member that is an inline object is exhaustive, so it prints as a strict object.
1079
+ * Marking the node lets `object()` build `z.strictObject(...)` itself; appending `.strict()` to the
1080
+ * printed member instead would read `.shape` eagerly and run a self-reference's deferred getter
1081
+ * inside the temporal dead zone.
1082
+ */
1083
+ function strictOneOfNode$1(node) {
1084
+ return node.type === "object" && node.additionalProperties === void 0 ? {
1085
+ ...node,
1086
+ additionalProperties: false
1087
+ } : node;
1088
+ }
1089
+ __name(strictOneOfNode$1, "strictOneOfNode");
1090
+ function strictOneOfMember(member, node, cyclicSchemas) {
1049
1091
  if (node.type === "ref") {
1050
1092
  if (member.startsWith("z.lazy(")) return member;
1051
1093
  const refName = kubb_kit.ast.resolveRefName(node);
@@ -1056,7 +1098,6 @@ function strictOneOfMember$1(member, node, cyclicSchemas) {
1056
1098
  }
1057
1099
  return member;
1058
1100
  }
1059
- __name(strictOneOfMember$1, "strictOneOfMember");
1060
1101
  function getMemberConstraint({ member, regexType }) {
1061
1102
  if (member.primitive === "string") return lengthConstraints({
1062
1103
  ...kubb_kit.ast.narrowSchema(member, "string") ?? {},
@@ -1200,6 +1241,32 @@ const scalarNodes = {
1200
1241
  boolean: () => "z.boolean()",
1201
1242
  null: () => "z.null()",
1202
1243
  string(node) {
1244
+ if (!shouldCoerce(this.options.coercion, "strings")) {
1245
+ if (node.format === "byte" || node.format === "base64") return `z.base64()${lengthConstraints({
1246
+ ...node,
1247
+ regexType: this.options.regexType
1248
+ })}`;
1249
+ if (node.format === "base64url") return `z.base64url()${lengthConstraints({
1250
+ ...node,
1251
+ regexType: this.options.regexType
1252
+ })}`;
1253
+ if (node.format === "jwt") return `z.jwt()${lengthConstraints({
1254
+ ...node,
1255
+ regexType: this.options.regexType
1256
+ })}`;
1257
+ if (node.format === "ulid") return `z.ulid()${lengthConstraints({
1258
+ ...node,
1259
+ regexType: this.options.regexType
1260
+ })}`;
1261
+ if (node.format === "iban") return `z.iban()${lengthConstraints({
1262
+ ...node,
1263
+ regexType: this.options.regexType
1264
+ })}`;
1265
+ if (node.format === "duration") return `z.iso.duration()${lengthConstraints({
1266
+ ...node,
1267
+ regexType: this.options.regexType
1268
+ })}`;
1269
+ }
1203
1270
  const base = shouldCoerce(this.options.coercion, "strings") ? "z.coerce.string()" : "z.string()";
1204
1271
  const pattern = node.pattern ?? integerFormatPattern(node.format);
1205
1272
  return `${base}${lengthConstraints({
@@ -1212,6 +1279,10 @@ const scalarNodes = {
1212
1279
  return `${shouldCoerce(this.options.coercion, "numbers") ? "z.coerce.number()" : "z.number()"}${numberConstraints(node)}`;
1213
1280
  },
1214
1281
  integer(node) {
1282
+ if (!shouldCoerce(this.options.coercion, "numbers")) {
1283
+ if (node.format === "int32") return `z.int32()${numberConstraints(node)}`;
1284
+ if (node.format === "uint32") return `z.uint32()${numberConstraints(node)}`;
1285
+ }
1215
1286
  return `${shouldCoerce(this.options.coercion, "numbers") ? "z.coerce.number().int()" : "z.int()"}${numberConstraints(node)}`;
1216
1287
  },
1217
1288
  bigint() {
@@ -1298,15 +1369,16 @@ const printerZod = kubb_kit.ast.createPrinter((options) => {
1298
1369
  },
1299
1370
  object(node) {
1300
1371
  const entries = node.properties ?? [];
1301
- const objectBase = `z.object(${buildZodObjectShape(this, node)})`;
1372
+ const patterns = node.patternProperties ? Object.entries(node.patternProperties) : [];
1373
+ const isStrict = node.additionalProperties === false && patterns.length === 0;
1374
+ const objectBase = `${isStrict ? "z.strictObject" : "z.object"}(${buildZodObjectShape(this, node)})`;
1302
1375
  return (() => {
1303
- const patterns = node.patternProperties ? Object.entries(node.patternProperties) : [];
1304
1376
  if (node.additionalProperties && node.additionalProperties !== true) {
1305
1377
  const catchallType = this.transform(node.additionalProperties);
1306
1378
  return catchallType ? `${objectBase}.catchall(${catchallType})` : objectBase;
1307
1379
  }
1308
1380
  if (node.additionalProperties === true) return `${objectBase}.catchall(${this.transform(kubb_kit.ast.factory.createSchema({ type: "unknown" }))})`;
1309
- if (node.additionalProperties === false && patterns.length === 0) return `${objectBase}.strict()`;
1381
+ if (isStrict) return objectBase;
1310
1382
  if (patterns.length > 0) {
1311
1383
  const values = patterns.map(([, valueSchema]) => {
1312
1384
  const valueType = this.transform(valueSchema) ?? this.transform(kubb_kit.ast.factory.createSchema({ type: "unknown" }));
@@ -1335,7 +1407,7 @@ const printerZod = kubb_kit.ast.createPrinter((options) => {
1335
1407
  },
1336
1408
  union(node) {
1337
1409
  const nodeMembers = node.members ?? [];
1338
- const members = mapSchemaMembers(node, (memberNode) => this.transform(memberNode)).map(({ schema, output }) => output && node.strategy === "one" ? strictOneOfMember$1(output, schema, cyclicSchemaNames) : output).filter(Boolean);
1410
+ const members = mapSchemaMembers(node, (memberNode) => this.transform(node.strategy === "one" ? strictOneOfNode$1(memberNode) : memberNode)).map(({ schema, output }) => output && node.strategy === "one" ? strictOneOfMember(output, schema, cyclicSchemaNames) : output).filter(Boolean);
1339
1411
  if (members.length === 0) return "";
1340
1412
  if (members.length === 1) return members[0];
1341
1413
  const allDiscriminable = nodeMembers.every((m) => isObjectSchemaNode(m, cyclicSchemaNames));
@@ -1389,9 +1461,15 @@ const printerZod = kubb_kit.ast.createPrinter((options) => {
1389
1461
  });
1390
1462
  //#endregion
1391
1463
  //#region src/printers/printerZodMini.ts
1392
- function strictOneOfMember(member, node) {
1393
- if (node.type === "object" && (node.additionalProperties === void 0 || node.additionalProperties === false)) return member.replace(/^z\.object\(/, "z.strictObject(");
1394
- return member;
1464
+ /**
1465
+ * A `oneOf` member that is an inline object is exhaustive, so it prints as a strict object.
1466
+ * Marking the node lets `object()` build `z.strictObject(...)` itself, with no rewrite afterwards.
1467
+ */
1468
+ function strictOneOfNode(node) {
1469
+ return node.type === "object" && node.additionalProperties === void 0 ? {
1470
+ ...node,
1471
+ additionalProperties: false
1472
+ } : node;
1395
1473
  }
1396
1474
  function getMemberConstraintMini({ member, regexType }) {
1397
1475
  if (member.primitive === "string") return lengthChecksMini({
@@ -1461,6 +1539,30 @@ const printerZodMini = kubb_kit.ast.createPrinter((options) => {
1461
1539
  boolean: () => "z.boolean()",
1462
1540
  null: () => "z.null()",
1463
1541
  string(node) {
1542
+ if (node.format === "byte" || node.format === "base64") return `z.base64()${lengthChecksMini({
1543
+ ...node,
1544
+ regexType: this.options.regexType
1545
+ })}`;
1546
+ if (node.format === "base64url") return `z.base64url()${lengthChecksMini({
1547
+ ...node,
1548
+ regexType: this.options.regexType
1549
+ })}`;
1550
+ if (node.format === "jwt") return `z.jwt()${lengthChecksMini({
1551
+ ...node,
1552
+ regexType: this.options.regexType
1553
+ })}`;
1554
+ if (node.format === "ulid") return `z.ulid()${lengthChecksMini({
1555
+ ...node,
1556
+ regexType: this.options.regexType
1557
+ })}`;
1558
+ if (node.format === "iban") return `z.iban()${lengthChecksMini({
1559
+ ...node,
1560
+ regexType: this.options.regexType
1561
+ })}`;
1562
+ if (node.format === "duration") return `z.iso.duration()${lengthChecksMini({
1563
+ ...node,
1564
+ regexType: this.options.regexType
1565
+ })}`;
1464
1566
  const pattern = node.pattern ?? integerFormatPattern(node.format);
1465
1567
  return `z.string()${lengthChecksMini({
1466
1568
  ...node,
@@ -1472,6 +1574,8 @@ const printerZodMini = kubb_kit.ast.createPrinter((options) => {
1472
1574
  return `z.number()${numberChecksMini(node)}`;
1473
1575
  },
1474
1576
  integer(node) {
1577
+ if (node.format === "int32") return `z.int32()${numberChecksMini(node)}`;
1578
+ if (node.format === "uint32") return `z.uint32()${numberChecksMini(node)}`;
1475
1579
  return `z.int()${numberChecksMini(node)}`;
1476
1580
  },
1477
1581
  bigint(node) {
@@ -1528,14 +1632,15 @@ const printerZodMini = kubb_kit.ast.createPrinter((options) => {
1528
1632
  },
1529
1633
  object(node) {
1530
1634
  const entries = node.properties ?? [];
1531
- const objectBase = `z.object(${buildZodMiniObjectShape(this, node)})`;
1532
1635
  const patterns = node.patternProperties ? Object.entries(node.patternProperties) : [];
1636
+ const isStrict = node.additionalProperties === false && patterns.length === 0;
1637
+ const objectBase = `${isStrict ? "z.strictObject" : "z.object"}(${buildZodMiniObjectShape(this, node)})`;
1533
1638
  if (node.additionalProperties && node.additionalProperties !== true) {
1534
1639
  const catchallType = this.transform(node.additionalProperties);
1535
1640
  return catchallType ? `z.catchall(${objectBase}, ${catchallType})` : objectBase;
1536
1641
  }
1537
1642
  if (node.additionalProperties === true) return `z.catchall(${objectBase}, ${this.transform(kubb_kit.ast.factory.createSchema({ type: "unknown" }))})`;
1538
- if (node.additionalProperties === false && patterns.length === 0) return objectBase.replace(/^z\.object\(/, "z.strictObject(");
1643
+ if (isStrict) return objectBase;
1539
1644
  if (patterns.length > 0) {
1540
1645
  const values = patterns.map(([, valueSchema]) => {
1541
1646
  const valueType = this.transform(valueSchema) ?? this.transform(kubb_kit.ast.factory.createSchema({ type: "unknown" }));
@@ -1563,7 +1668,7 @@ const printerZodMini = kubb_kit.ast.createPrinter((options) => {
1563
1668
  },
1564
1669
  union(node) {
1565
1670
  const nodeMembers = node.members ?? [];
1566
- const members = mapSchemaMembers(node, (memberNode) => this.transform(memberNode)).map(({ schema, output }) => output && node.strategy === "one" ? strictOneOfMember(output, schema) : output).filter(Boolean);
1671
+ const members = mapSchemaMembers(node, (memberNode) => this.transform(node.strategy === "one" ? strictOneOfNode(memberNode) : memberNode)).map(({ output }) => output).filter(Boolean);
1567
1672
  if (members.length === 0) return "";
1568
1673
  if (members.length === 1) return members[0];
1569
1674
  const allDiscriminable = nodeMembers.every((m) => isObjectSchemaNode(m, cyclicSchemaNames));
@@ -1677,7 +1782,7 @@ const zodGenerator = (0, kubb_kit.defineGenerator)({
1677
1782
  renderer: kubb_jsx.jsxRenderer,
1678
1783
  schema(node, ctx) {
1679
1784
  const { adapter, config, resolver, root } = ctx;
1680
- const { output, coercion, guidType, regexType, mini, inferred, importPath, group, printer } = ctx.options;
1785
+ const { output, coercion, guidType, regexType, mini, inferred, typeGuards, importPath, group, printer } = ctx.options;
1681
1786
  const dateType = getOasAdapter(adapter).options.dateType;
1682
1787
  if (!node.name) return;
1683
1788
  const isZodImport = ZOD_NAMESPACE_IMPORTS.has(importPath);
@@ -1733,6 +1838,8 @@ const zodGenerator = (0, kubb_kit.defineGenerator)({
1733
1838
  })
1734
1839
  };
1735
1840
  const inferTypeName = inferred ? resolver.schema.typeName(node.name) : null;
1841
+ const isName = typeGuards ? resolver.schema.isName(node.name) : null;
1842
+ const assertName = typeGuards ? resolver.schema.assertName(node.name) : null;
1736
1843
  const stdPrinters = mini ? null : getStdPrinters(resolver, {
1737
1844
  coercion,
1738
1845
  guidType,
@@ -1787,6 +1894,10 @@ const zodGenerator = (0, kubb_kit.defineGenerator)({
1787
1894
  node,
1788
1895
  printer: schemaPrinter,
1789
1896
  inferTypeName,
1897
+ typeGuards,
1898
+ isName,
1899
+ assertName,
1900
+ mini,
1790
1901
  cyclic: cyclicSchemas.has(node.name)
1791
1902
  }),
1792
1903
  hasDirectionalNode && stdPrinters && /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(Zod, {
@@ -1794,6 +1905,10 @@ const zodGenerator = (0, kubb_kit.defineGenerator)({
1794
1905
  node,
1795
1906
  printer: stdPrinters.encode,
1796
1907
  inferTypeName: inferred ? resolver.schema.inputTypeName(node.name) : null,
1908
+ typeGuards,
1909
+ isName: typeGuards ? resolver.schema.isName(resolver.schema.inputName(node.name)) : null,
1910
+ assertName: typeGuards ? resolver.schema.assertName(resolver.schema.inputName(node.name)) : null,
1911
+ mini,
1797
1912
  cyclic: cyclicSchemas.has(node.name)
1798
1913
  })
1799
1914
  ]
@@ -2072,6 +2187,12 @@ const resolverZod = (0, kubb_kit.createResolver)({
2072
2187
  },
2073
2188
  inputTypeName(name) {
2074
2189
  return this.schema.typeName(`${name} input`);
2190
+ },
2191
+ isName(name) {
2192
+ return ensureValidVarName(camelCase(name, { prefix: "is" }));
2193
+ },
2194
+ assertName(name) {
2195
+ return ensureValidVarName(camelCase(name, { prefix: "assert" }));
2075
2196
  }
2076
2197
  },
2077
2198
  param: createOperationParamResolver(),
@@ -2122,7 +2243,7 @@ const pluginZod = (0, kubb_kit.definePlugin)((options) => {
2122
2243
  const { output = {
2123
2244
  path: "zod",
2124
2245
  barrel: { type: "named" }
2125
- }, group, exclude = [], include, override = [], mini = false, guidType = "uuid", regexType = "literal", importPath = mini ? "zod/mini" : "zod", coercion = false, inferred = false, printer, resolver: userResolver, macros: userMacros } = options;
2246
+ }, 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;
2126
2247
  const groupConfig = createGroupConfig(group);
2127
2248
  return {
2128
2249
  name: pluginZodName,
@@ -2140,6 +2261,7 @@ const pluginZod = (0, kubb_kit.definePlugin)((options) => {
2140
2261
  guidType,
2141
2262
  regexType,
2142
2263
  mini,
2264
+ typeGuards,
2143
2265
  printer
2144
2266
  });
2145
2267
  ctx.setResolver(userResolver ? kubb_kit.Resolver.merge(resolverZod, userResolver) : resolverZod);