@kubb/plugin-zod 5.0.0-beta.75 → 5.0.0-beta.77
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 +87 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +8 -0
- package/dist/index.js +87 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -282,6 +282,14 @@ type ResolverZod = Resolver & OperationParamsResolver & {
|
|
|
282
282
|
* `resolver.resolveResponseName(node) // → 'listPetsResponseSchema'`
|
|
283
283
|
*/
|
|
284
284
|
resolveResponseName(this: ResolverZod, node: ast.OperationNode): string;
|
|
285
|
+
/**
|
|
286
|
+
* Resolves the name for the union of an operation's error (non-2xx) responses. Generated clients
|
|
287
|
+
* validate the error body against this on the non-throw path.
|
|
288
|
+
*
|
|
289
|
+
* @example Error union names
|
|
290
|
+
* `resolver.resolveErrorName(node) // → 'listPetsErrorSchema'`
|
|
291
|
+
*/
|
|
292
|
+
resolveErrorName(this: ResolverZod, node: ast.OperationNode): string;
|
|
285
293
|
/**
|
|
286
294
|
* Resolves the name for an operation's grouped path parameters type.
|
|
287
295
|
*
|
package/dist/index.js
CHANGED
|
@@ -432,6 +432,28 @@ function regexFunc(regexType) {
|
|
|
432
432
|
return regexType === "constructor" ? "RegExp" : null;
|
|
433
433
|
}
|
|
434
434
|
/**
|
|
435
|
+
* Builds a Zod record key schema that enforces the `patternProperties` regexes a plain
|
|
436
|
+
* `.catchall()` would drop. Several patterns combine into one alternation (`(^a)|(^b)`).
|
|
437
|
+
*/
|
|
438
|
+
function patternKeySchema({ patterns, regexType }) {
|
|
439
|
+
return `z.string().regex(${patternKeySource({
|
|
440
|
+
patterns,
|
|
441
|
+
regexType
|
|
442
|
+
})})`;
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* `zod/mini` variant of {@link patternKeySchema}, wrapping the regex in `.check(z.regex(...))`.
|
|
446
|
+
*/
|
|
447
|
+
function patternKeySchemaMini({ patterns, regexType }) {
|
|
448
|
+
return `z.string().check(z.regex(${patternKeySource({
|
|
449
|
+
patterns,
|
|
450
|
+
regexType
|
|
451
|
+
})}))`;
|
|
452
|
+
}
|
|
453
|
+
function patternKeySource({ patterns, regexType }) {
|
|
454
|
+
return toRegExpString(patterns.length === 1 ? patterns[0] : patterns.map((pattern) => `(${pattern})`).join("|"), regexFunc(regexType));
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
435
457
|
* Build `.min()` / `.max()` / `.gt()` / `.lt()` constraint chains for numbers
|
|
436
458
|
* using the standard chainable Zod v4 API.
|
|
437
459
|
*/
|
|
@@ -621,7 +643,7 @@ const printerZod = ast.createPrinter((options) => {
|
|
|
621
643
|
},
|
|
622
644
|
object(node) {
|
|
623
645
|
const isCyclic = (schema) => this.options.cyclicSchemas != null && containsCircularRef(schema, { circularSchemas: this.options.cyclicSchemas });
|
|
624
|
-
const
|
|
646
|
+
const entries = mapSchemaProperties(node, (schema) => {
|
|
625
647
|
const hasSelfRef = isCyclic(schema);
|
|
626
648
|
const savedCyclicSchemas = this.options.cyclicSchemas;
|
|
627
649
|
if (hasSelfRef) this.options.cyclicSchemas = void 0;
|
|
@@ -649,14 +671,29 @@ const printerZod = ast.createPrinter((options) => {
|
|
|
649
671
|
name: propName,
|
|
650
672
|
body: value
|
|
651
673
|
}) : `${objectKey(propName)}: ${value}`;
|
|
652
|
-
})
|
|
674
|
+
});
|
|
675
|
+
const objectBase = `z.object(${buildObject(entries)})`;
|
|
653
676
|
return (() => {
|
|
677
|
+
const patterns = node.patternProperties ? Object.entries(node.patternProperties) : [];
|
|
654
678
|
if (node.additionalProperties && node.additionalProperties !== true) {
|
|
655
679
|
const catchallType = this.transform(node.additionalProperties);
|
|
656
680
|
return catchallType ? `${objectBase}.catchall(${catchallType})` : objectBase;
|
|
657
681
|
}
|
|
658
682
|
if (node.additionalProperties === true) return `${objectBase}.catchall(${this.transform(ast.factory.createSchema({ type: "unknown" }))})`;
|
|
659
|
-
if (node.additionalProperties === false) return `${objectBase}.strict()`;
|
|
683
|
+
if (node.additionalProperties === false && patterns.length === 0) return `${objectBase}.strict()`;
|
|
684
|
+
if (patterns.length > 0) {
|
|
685
|
+
const values = patterns.map(([, valueSchema]) => {
|
|
686
|
+
const valueType = this.transform(valueSchema) ?? this.transform(ast.factory.createSchema({ type: "unknown" }));
|
|
687
|
+
return valueSchema.nullable ? `${valueType}.nullable()` : valueType;
|
|
688
|
+
});
|
|
689
|
+
const distinct = [...new Set(values)];
|
|
690
|
+
const value = distinct.length === 1 ? distinct[0] : `z.union([${distinct.join(", ")}])`;
|
|
691
|
+
if (entries.length > 0) return `${objectBase}.catchall(${value})`;
|
|
692
|
+
return `z.record(${patternKeySchema({
|
|
693
|
+
patterns: patterns.map(([pattern]) => pattern),
|
|
694
|
+
regexType: this.options.regexType
|
|
695
|
+
})}, ${value})`;
|
|
696
|
+
}
|
|
660
697
|
return objectBase;
|
|
661
698
|
})();
|
|
662
699
|
},
|
|
@@ -824,7 +861,7 @@ const printerZodMini = ast.createPrinter((options) => {
|
|
|
824
861
|
},
|
|
825
862
|
object(node) {
|
|
826
863
|
const isCyclic = (schema) => this.options.cyclicSchemas != null && containsCircularRef(schema, { circularSchemas: this.options.cyclicSchemas });
|
|
827
|
-
|
|
864
|
+
const entries = mapSchemaProperties(node, (schema) => {
|
|
828
865
|
const hasSelfRef = isCyclic(schema);
|
|
829
866
|
const savedCyclicSchemas = this.options.cyclicSchemas;
|
|
830
867
|
if (hasSelfRef) this.options.cyclicSchemas = void 0;
|
|
@@ -848,7 +885,29 @@ const printerZodMini = ast.createPrinter((options) => {
|
|
|
848
885
|
name: propName,
|
|
849
886
|
body: value
|
|
850
887
|
}) : `${objectKey(propName)}: ${value}`;
|
|
851
|
-
})
|
|
888
|
+
});
|
|
889
|
+
const objectBase = `z.object(${buildObject(entries)})`;
|
|
890
|
+
const patterns = node.patternProperties ? Object.entries(node.patternProperties) : [];
|
|
891
|
+
if (node.additionalProperties && node.additionalProperties !== true) {
|
|
892
|
+
const catchallType = this.transform(node.additionalProperties);
|
|
893
|
+
return catchallType ? `z.catchall(${objectBase}, ${catchallType})` : objectBase;
|
|
894
|
+
}
|
|
895
|
+
if (node.additionalProperties === true) return `z.catchall(${objectBase}, ${this.transform(ast.factory.createSchema({ type: "unknown" }))})`;
|
|
896
|
+
if (node.additionalProperties === false && patterns.length === 0) return objectBase.replace(/^z\.object\(/, "z.strictObject(");
|
|
897
|
+
if (patterns.length > 0) {
|
|
898
|
+
const values = patterns.map(([, valueSchema]) => {
|
|
899
|
+
const valueType = this.transform(valueSchema) ?? this.transform(ast.factory.createSchema({ type: "unknown" }));
|
|
900
|
+
return valueSchema.nullable ? `z.nullable(${valueType})` : valueType;
|
|
901
|
+
});
|
|
902
|
+
const distinct = [...new Set(values)];
|
|
903
|
+
const value = distinct.length === 1 ? distinct[0] : `z.union([${distinct.join(", ")}])`;
|
|
904
|
+
if (entries.length > 0) return `z.catchall(${objectBase}, ${value})`;
|
|
905
|
+
return `z.record(${patternKeySchemaMini({
|
|
906
|
+
patterns: patterns.map(([pattern]) => pattern),
|
|
907
|
+
regexType: this.options.regexType
|
|
908
|
+
})}, ${value})`;
|
|
909
|
+
}
|
|
910
|
+
return objectBase;
|
|
852
911
|
},
|
|
853
912
|
array(node) {
|
|
854
913
|
const base = `z.array(${mapSchemaItems(node, (item) => this.transform(item)).map(({ output }) => output).filter(Boolean).join(", ") || this.transform(ast.factory.createSchema({ type: "unknown" }))})${lengthChecksMini({
|
|
@@ -1227,6 +1286,25 @@ const zodGenerator = defineGenerator({
|
|
|
1227
1286
|
name: responseUnionName
|
|
1228
1287
|
});
|
|
1229
1288
|
})() : null;
|
|
1289
|
+
const errorResponsesWithSchema = responsesWithSchema.filter((res) => !isSuccessStatusCode(res.statusCode));
|
|
1290
|
+
const errorUnionSchema = errorResponsesWithSchema.length > 0 ? (() => {
|
|
1291
|
+
const errorUnionName = resolver.resolveErrorName(node);
|
|
1292
|
+
if (new Set(errorResponsesWithSchema.flatMap((res) => (res.content ?? []).flatMap((entry) => entry.schema ? adapter.getImports(entry.schema, (schemaName) => ({
|
|
1293
|
+
name: resolver.resolveSchemaName(schemaName),
|
|
1294
|
+
path: ""
|
|
1295
|
+
})).flatMap((imp) => Array.isArray(imp.name) ? imp.name : [imp.name]) : []))).has(errorUnionName)) return null;
|
|
1296
|
+
const members = errorResponsesWithSchema.map((res) => ast.factory.createSchema({
|
|
1297
|
+
type: "ref",
|
|
1298
|
+
name: resolver.resolveResponseStatusName(node, res.statusCode)
|
|
1299
|
+
}));
|
|
1300
|
+
return renderSchemaEntry({
|
|
1301
|
+
schema: members.length === 1 ? members[0] : ast.factory.createSchema({
|
|
1302
|
+
type: "union",
|
|
1303
|
+
members
|
|
1304
|
+
}),
|
|
1305
|
+
name: errorUnionName
|
|
1306
|
+
});
|
|
1307
|
+
})() : null;
|
|
1230
1308
|
const requestBodyContent = node.requestBody?.content ?? [];
|
|
1231
1309
|
const requestSchema = (() => {
|
|
1232
1310
|
if (requestBodyContent.length === 0) return null;
|
|
@@ -1277,6 +1355,7 @@ const zodGenerator = defineGenerator({
|
|
|
1277
1355
|
paramSchemas,
|
|
1278
1356
|
responseSchemas,
|
|
1279
1357
|
responseUnionSchema,
|
|
1358
|
+
errorUnionSchema,
|
|
1280
1359
|
requestSchema
|
|
1281
1360
|
]
|
|
1282
1361
|
});
|
|
@@ -1340,6 +1419,9 @@ const resolverZod = defineResolver(() => {
|
|
|
1340
1419
|
resolveResponseName(node) {
|
|
1341
1420
|
return this.resolveSchemaName(`${node.operationId} Response`);
|
|
1342
1421
|
},
|
|
1422
|
+
resolveErrorName(node) {
|
|
1423
|
+
return this.resolveSchemaName(`${node.operationId} Error`);
|
|
1424
|
+
},
|
|
1343
1425
|
resolvePathParamsName(node, param) {
|
|
1344
1426
|
return this.resolveParamName(node, param);
|
|
1345
1427
|
},
|