@kubb/plugin-zod 5.2.0 → 5.2.2

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
@@ -367,7 +367,9 @@ type Options = OutputOptions & {
367
367
  *
368
368
  * `dates` applies to fields typed as `Date` (adapter `dateType: 'date'`): they
369
369
  * validate with `z.coerce.date()` instead of the string-to-Date codec. Fields
370
- * kept as ISO strings (`z.iso.date()`, `z.iso.datetime()`) are never coerced.
370
+ * kept as ISO strings (`z.iso.date()`, `z.iso.datetime()`) are never coerced,
371
+ * and neither are `format: time` fields, since `new Date()` cannot parse a bare
372
+ * `HH:mm:ss` value.
371
373
  *
372
374
  * `bigint` fields (`format: int64`) always coerce, regardless of this option:
373
375
  * `JSON.parse` hands back a `number`, which a plain `z.bigint()` rejects.
package/dist/index.js CHANGED
@@ -1064,8 +1064,20 @@ function buildGroupedParamsSchema({ params, optional }) {
1064
1064
  }
1065
1065
  //#endregion
1066
1066
  //#region src/printers/printerZod.ts
1067
- function strictOneOfMember$1(member, node, cyclicSchemas) {
1068
- if (node.type === "object" && node.additionalProperties === void 0) return `${member}.strict()`;
1067
+ /**
1068
+ * A `oneOf` member that is an inline object is exhaustive, so it prints as a strict object.
1069
+ * Marking the node lets `object()` build `z.strictObject(...)` itself; appending `.strict()` to the
1070
+ * printed member instead would read `.shape` eagerly and run a self-reference's deferred getter
1071
+ * inside the temporal dead zone.
1072
+ */
1073
+ function strictOneOfNode$1(node) {
1074
+ return node.type === "object" && node.additionalProperties === void 0 ? {
1075
+ ...node,
1076
+ additionalProperties: false
1077
+ } : node;
1078
+ }
1079
+ __name(strictOneOfNode$1, "strictOneOfNode");
1080
+ function strictOneOfMember(member, node, cyclicSchemas) {
1069
1081
  if (node.type === "ref") {
1070
1082
  if (member.startsWith("z.lazy(")) return member;
1071
1083
  const refName = ast.resolveRefName(node);
@@ -1076,7 +1088,6 @@ function strictOneOfMember$1(member, node, cyclicSchemas) {
1076
1088
  }
1077
1089
  return member;
1078
1090
  }
1079
- __name(strictOneOfMember$1, "strictOneOfMember");
1080
1091
  function getMemberConstraint({ member, regexType }) {
1081
1092
  if (member.primitive === "string") return lengthConstraints({
1082
1093
  ...ast.narrowSchema(member, "string") ?? {},
@@ -1207,10 +1218,12 @@ function collectDirectionalRefNames({ node, printerOptions }) {
1207
1218
  * Handlers that never recurse into children, so {@link variesByDirection} can call one directly
1208
1219
  * to probe both directions without building a printer.
1209
1220
  *
1210
- * `date` is the built-in two-way conversion, decoding `string → Date` on responses and encoding
1211
- * back on requests, keeping `date` and `date-time` precision apart. Only `representation: 'date'`
1212
- * fields convert; ISO-string fields print `z.iso.date()` either way. A `printer.nodes.date`
1213
- * override replaces the whole handler, direction branch included.
1221
+ * `date` and `time` are the built-in two-way conversions, decoding `string → Date` on responses
1222
+ * and encoding back on requests. `date` keeps `date` and `date-time` precision apart. `time` has
1223
+ * no date component, so it decodes onto `1970-01-01` UTC and encodes back to `HH:mm:ss`, dropping
1224
+ * fractional seconds. Only `representation: 'date'` fields convert; ISO-string fields print the
1225
+ * matching `z.iso.*()` either way. A `printer.nodes.date` or `printer.nodes.time` override
1226
+ * replaces the whole handler, direction branch included.
1214
1227
  */
1215
1228
  const scalarNodes = {
1216
1229
  any: () => "z.any()",
@@ -1282,7 +1295,8 @@ const scalarNodes = {
1282
1295
  },
1283
1296
  time(node) {
1284
1297
  if (node.representation === "string") return "z.iso.time()";
1285
- return shouldCoerce(this.options.coercion, "dates") ? "z.coerce.date()" : "z.date()";
1298
+ if (this.options.direction === "encode") return "z.date().transform((value) => value.toISOString().slice(11, 19))";
1299
+ return "z.iso.time().transform((value) => new Date(`1970-01-01T${value}Z`))";
1286
1300
  },
1287
1301
  uuid(node) {
1288
1302
  return `${this.options.guidType === "guid" ? "z.guid()" : "z.uuid()"}${lengthConstraints({
@@ -1348,15 +1362,16 @@ const printerZod = ast.createPrinter((options) => {
1348
1362
  },
1349
1363
  object(node) {
1350
1364
  const entries = node.properties ?? [];
1351
- const objectBase = `z.object(${buildZodObjectShape(this, node)})`;
1365
+ const patterns = node.patternProperties ? Object.entries(node.patternProperties) : [];
1366
+ const isStrict = node.additionalProperties === false && patterns.length === 0;
1367
+ const objectBase = `${isStrict ? "z.strictObject" : "z.object"}(${buildZodObjectShape(this, node)})`;
1352
1368
  return (() => {
1353
- const patterns = node.patternProperties ? Object.entries(node.patternProperties) : [];
1354
1369
  if (node.additionalProperties && node.additionalProperties !== true) {
1355
1370
  const catchallType = this.transform(node.additionalProperties);
1356
1371
  return catchallType ? `${objectBase}.catchall(${catchallType})` : objectBase;
1357
1372
  }
1358
1373
  if (node.additionalProperties === true) return `${objectBase}.catchall(${this.transform(ast.factory.createSchema({ type: "unknown" }))})`;
1359
- if (node.additionalProperties === false && patterns.length === 0) return `${objectBase}.strict()`;
1374
+ if (isStrict) return objectBase;
1360
1375
  if (patterns.length > 0) {
1361
1376
  const values = patterns.map(([, valueSchema]) => {
1362
1377
  const valueType = this.transform(valueSchema) ?? this.transform(ast.factory.createSchema({ type: "unknown" }));
@@ -1385,7 +1400,7 @@ const printerZod = ast.createPrinter((options) => {
1385
1400
  },
1386
1401
  union(node) {
1387
1402
  const nodeMembers = node.members ?? [];
1388
- const members = mapSchemaMembers(node, (memberNode) => this.transform(memberNode)).map(({ schema, output }) => output && node.strategy === "one" ? strictOneOfMember$1(output, schema, cyclicSchemaNames) : output).filter(Boolean);
1403
+ 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);
1389
1404
  if (members.length === 0) return "";
1390
1405
  if (members.length === 1) return members[0];
1391
1406
  const allDiscriminable = nodeMembers.every((m) => isObjectSchemaNode(m, cyclicSchemaNames));
@@ -1439,9 +1454,15 @@ const printerZod = ast.createPrinter((options) => {
1439
1454
  });
1440
1455
  //#endregion
1441
1456
  //#region src/printers/printerZodMini.ts
1442
- function strictOneOfMember(member, node) {
1443
- if (node.type === "object" && (node.additionalProperties === void 0 || node.additionalProperties === false)) return member.replace(/^z\.object\(/, "z.strictObject(");
1444
- return member;
1457
+ /**
1458
+ * A `oneOf` member that is an inline object is exhaustive, so it prints as a strict object.
1459
+ * Marking the node lets `object()` build `z.strictObject(...)` itself, with no rewrite afterwards.
1460
+ */
1461
+ function strictOneOfNode(node) {
1462
+ return node.type === "object" && node.additionalProperties === void 0 ? {
1463
+ ...node,
1464
+ additionalProperties: false
1465
+ } : node;
1445
1466
  }
1446
1467
  function getMemberConstraintMini({ member, regexType }) {
1447
1468
  if (member.primitive === "string") return lengthChecksMini({
@@ -1604,14 +1625,15 @@ const printerZodMini = ast.createPrinter((options) => {
1604
1625
  },
1605
1626
  object(node) {
1606
1627
  const entries = node.properties ?? [];
1607
- const objectBase = `z.object(${buildZodMiniObjectShape(this, node)})`;
1608
1628
  const patterns = node.patternProperties ? Object.entries(node.patternProperties) : [];
1629
+ const isStrict = node.additionalProperties === false && patterns.length === 0;
1630
+ const objectBase = `${isStrict ? "z.strictObject" : "z.object"}(${buildZodMiniObjectShape(this, node)})`;
1609
1631
  if (node.additionalProperties && node.additionalProperties !== true) {
1610
1632
  const catchallType = this.transform(node.additionalProperties);
1611
1633
  return catchallType ? `z.catchall(${objectBase}, ${catchallType})` : objectBase;
1612
1634
  }
1613
1635
  if (node.additionalProperties === true) return `z.catchall(${objectBase}, ${this.transform(ast.factory.createSchema({ type: "unknown" }))})`;
1614
- if (node.additionalProperties === false && patterns.length === 0) return objectBase.replace(/^z\.object\(/, "z.strictObject(");
1636
+ if (isStrict) return objectBase;
1615
1637
  if (patterns.length > 0) {
1616
1638
  const values = patterns.map(([, valueSchema]) => {
1617
1639
  const valueType = this.transform(valueSchema) ?? this.transform(ast.factory.createSchema({ type: "unknown" }));
@@ -1639,7 +1661,7 @@ const printerZodMini = ast.createPrinter((options) => {
1639
1661
  },
1640
1662
  union(node) {
1641
1663
  const nodeMembers = node.members ?? [];
1642
- const members = mapSchemaMembers(node, (memberNode) => this.transform(memberNode)).map(({ schema, output }) => output && node.strategy === "one" ? strictOneOfMember(output, schema) : output).filter(Boolean);
1664
+ const members = mapSchemaMembers(node, (memberNode) => this.transform(node.strategy === "one" ? strictOneOfNode(memberNode) : memberNode)).map(({ output }) => output).filter(Boolean);
1643
1665
  if (members.length === 0) return "";
1644
1666
  if (members.length === 1) return members[0];
1645
1667
  const allDiscriminable = nodeMembers.every((m) => isObjectSchemaNode(m, cyclicSchemaNames));