@kubb/plugin-zod 5.4.0-canary.20260925T211808 → 5.4.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.cjs +52 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +52 -6
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -811,13 +811,38 @@ function shouldCoerce(coercion, type) {
|
|
|
811
811
|
if (coercion === true) return true;
|
|
812
812
|
return !!coercion[type];
|
|
813
813
|
}
|
|
814
|
+
function hasPropertyNames(node) {
|
|
815
|
+
return "propertyNames" in node && Boolean(node.propertyNames);
|
|
816
|
+
}
|
|
817
|
+
/**
|
|
818
|
+
* Whether the schema node represents a closed or finite set of keys (e.g. enum, literal,
|
|
819
|
+
* or union of enums/literals).
|
|
820
|
+
*
|
|
821
|
+
* In Zod v4, passing a closed key schema to `z.record()` enforces exhaustiveness (all keys
|
|
822
|
+
* must exist in the input). OpenAPI 3.1 `propertyNames` only validates present keys without
|
|
823
|
+
* requiring all keys to exist, so closed key schemas use `z.partialRecord()` instead.
|
|
824
|
+
*/
|
|
825
|
+
function isClosedKeySchema(node) {
|
|
826
|
+
if (!node) return false;
|
|
827
|
+
const resolved = syncSchemaRef(node);
|
|
828
|
+
if (resolved.type === "enum") return true;
|
|
829
|
+
if (resolved.type === "union") {
|
|
830
|
+
const members = resolved.members ?? [];
|
|
831
|
+
return members.length > 0 && members.every(isClosedKeySchema);
|
|
832
|
+
}
|
|
833
|
+
return false;
|
|
834
|
+
}
|
|
814
835
|
/**
|
|
815
836
|
* Whether the node is a plain inline object whose shape can be lifted into an `.extend({ … })`
|
|
816
837
|
* argument. A catchall, `patternProperties`, or a nullable/optional wrapper cannot, so those stay
|
|
817
838
|
* on `.and(…)`.
|
|
818
839
|
*/
|
|
819
840
|
function isPlainInlineObject(node) {
|
|
820
|
-
|
|
841
|
+
if (node.type !== "object") return false;
|
|
842
|
+
if (node.nullable || node.optional || node.nullish) return false;
|
|
843
|
+
const hasAdditionalProperties = node.additionalProperties !== void 0;
|
|
844
|
+
const hasPatternProperties = Boolean(node.patternProperties);
|
|
845
|
+
return !hasAdditionalProperties && !hasPatternProperties && !hasPropertyNames(node);
|
|
821
846
|
}
|
|
822
847
|
/**
|
|
823
848
|
* Whether a node renders as a bare Zod object — one that accepts `.extend(…)` and can be a
|
|
@@ -828,7 +853,12 @@ function isPlainInlineObject(node) {
|
|
|
828
853
|
*/
|
|
829
854
|
function isObjectSchemaNode(node, cyclicSchemas) {
|
|
830
855
|
if (node.nullable || node.optional || node.nullish) return false;
|
|
831
|
-
if (node.type === "object")
|
|
856
|
+
if (node.type === "object") {
|
|
857
|
+
const hasProperties = Boolean(node.properties?.length);
|
|
858
|
+
const hasTypedAdditionalProperties = Boolean(node.additionalProperties && node.additionalProperties !== true);
|
|
859
|
+
const hasPatternProperties = Boolean(node.patternProperties);
|
|
860
|
+
return !(!hasProperties && (hasTypedAdditionalProperties || hasPatternProperties || hasPropertyNames(node)));
|
|
861
|
+
}
|
|
832
862
|
if (node.type === "ref") {
|
|
833
863
|
const refName = ast.resolveRefName(node);
|
|
834
864
|
if (refName && cyclicSchemas?.has(refName)) return false;
|
|
@@ -1202,6 +1232,7 @@ function containsDirectionalNode({ node, printerOptions, seen = /* @__PURE__ */
|
|
|
1202
1232
|
if ("items" in node && node.items) children.push(...node.items);
|
|
1203
1233
|
if ("members" in node && node.members) children.push(...node.members);
|
|
1204
1234
|
if ("additionalProperties" in node && node.additionalProperties && node.additionalProperties !== true) children.push(node.additionalProperties);
|
|
1235
|
+
if ("propertyNames" in node && node.propertyNames) children.push(node.propertyNames);
|
|
1205
1236
|
return children.some((child) => containsDirectionalNode({
|
|
1206
1237
|
node: child,
|
|
1207
1238
|
printerOptions,
|
|
@@ -1366,14 +1397,23 @@ const printerZod = ast.createPrinter((options) => {
|
|
|
1366
1397
|
object(node) {
|
|
1367
1398
|
const entries = node.properties ?? [];
|
|
1368
1399
|
const patterns = node.patternProperties ? Object.entries(node.patternProperties) : [];
|
|
1400
|
+
const propertyNamesNode = "propertyNames" in node ? node.propertyNames : void 0;
|
|
1401
|
+
const propertyNamesKeySchema = propertyNamesNode ? this.transform(propertyNamesNode) : null;
|
|
1369
1402
|
const isStrict = node.additionalProperties === false && patterns.length === 0;
|
|
1370
|
-
const
|
|
1403
|
+
const isLoose = node.additionalProperties === true;
|
|
1404
|
+
const objectBase = `${isStrict ? "z.strictObject" : isLoose ? "z.looseObject" : "z.object"}(${buildZodObjectShape(this, node)})`;
|
|
1371
1405
|
return (() => {
|
|
1406
|
+
const recordFn = isClosedKeySchema(propertyNamesNode) ? "z.partialRecord" : "z.record";
|
|
1372
1407
|
if (node.additionalProperties && node.additionalProperties !== true) {
|
|
1373
1408
|
const catchallType = this.transform(node.additionalProperties);
|
|
1409
|
+
if (entries.length === 0) return catchallType ? `${recordFn}(${propertyNamesKeySchema || "z.string()"}, ${catchallType})` : objectBase;
|
|
1374
1410
|
return catchallType ? `${objectBase}.catchall(${catchallType})` : objectBase;
|
|
1375
1411
|
}
|
|
1376
|
-
if (
|
|
1412
|
+
if (entries.length === 0 && patterns.length === 0 && propertyNamesKeySchema && !isStrict) {
|
|
1413
|
+
const unknownType = this.transform(ast.factory.createSchema({ type: "unknown" }));
|
|
1414
|
+
return `${recordFn}(${propertyNamesKeySchema}, ${unknownType})`;
|
|
1415
|
+
}
|
|
1416
|
+
if (node.additionalProperties === true) return objectBase;
|
|
1377
1417
|
if (isStrict) return objectBase;
|
|
1378
1418
|
if (patterns.length > 0) {
|
|
1379
1419
|
const values = patterns.map(([, valueSchema]) => {
|
|
@@ -1629,13 +1669,19 @@ const printerZodMini = ast.createPrinter((options) => {
|
|
|
1629
1669
|
object(node) {
|
|
1630
1670
|
const entries = node.properties ?? [];
|
|
1631
1671
|
const patterns = node.patternProperties ? Object.entries(node.patternProperties) : [];
|
|
1672
|
+
const propertyNamesNode = "propertyNames" in node ? node.propertyNames : void 0;
|
|
1673
|
+
const propertyNamesKeySchema = propertyNamesNode ? this.transform(propertyNamesNode) : null;
|
|
1632
1674
|
const isStrict = node.additionalProperties === false && patterns.length === 0;
|
|
1633
|
-
const
|
|
1675
|
+
const isLoose = node.additionalProperties === true;
|
|
1676
|
+
const objectBase = `${isStrict ? "z.strictObject" : isLoose ? "z.looseObject" : "z.object"}(${buildZodMiniObjectShape(this, node)})`;
|
|
1677
|
+
const recordFn = isClosedKeySchema(propertyNamesNode) ? "z.partialRecord" : "z.record";
|
|
1634
1678
|
if (node.additionalProperties && node.additionalProperties !== true) {
|
|
1635
1679
|
const catchallType = this.transform(node.additionalProperties);
|
|
1680
|
+
if (entries.length === 0) return catchallType ? `${recordFn}(${propertyNamesKeySchema || "z.string()"}, ${catchallType})` : objectBase;
|
|
1636
1681
|
return catchallType ? `z.catchall(${objectBase}, ${catchallType})` : objectBase;
|
|
1637
1682
|
}
|
|
1638
|
-
if (
|
|
1683
|
+
if (entries.length === 0 && patterns.length === 0 && propertyNamesKeySchema && !isStrict) return `${recordFn}(${propertyNamesKeySchema}, ${this.transform(ast.factory.createSchema({ type: "unknown" }))})`;
|
|
1684
|
+
if (node.additionalProperties === true) return objectBase;
|
|
1639
1685
|
if (isStrict) return objectBase;
|
|
1640
1686
|
if (patterns.length > 0) {
|
|
1641
1687
|
const values = patterns.map(([, valueSchema]) => {
|