@kubb/plugin-zod 5.0.0-beta.3 → 5.0.0-beta.30
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/README.md +25 -5
- package/dist/index.cjs +390 -177
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +79 -34
- package/dist/index.js +386 -179
- package/dist/index.js.map +1 -1
- package/extension.yaml +966 -0
- package/package.json +9 -13
- package/src/components/Operations.tsx +4 -4
- package/src/components/Zod.tsx +1 -1
- package/src/generators/zodGenerator.tsx +77 -32
- package/src/plugin.ts +21 -8
- package/src/printers/printerZod.ts +67 -63
- package/src/printers/printerZodMini.ts +46 -49
- package/src/resolvers/resolverZod.ts +25 -19
- package/src/types.ts +42 -21
- package/src/utils.ts +20 -36
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import "./chunk--u3MIqq1.js";
|
|
1
|
+
import { t as __name } from "./chunk--u3MIqq1.js";
|
|
2
2
|
import { ast, defineGenerator, definePlugin, defineResolver } from "@kubb/core";
|
|
3
|
-
import { Const, File, Type,
|
|
3
|
+
import { Const, File, Type, jsxRendererSync } from "@kubb/renderer-jsx";
|
|
4
4
|
import { Fragment, jsx, jsxs } from "@kubb/renderer-jsx/jsx-runtime";
|
|
5
5
|
//#region ../../internals/utils/src/casing.ts
|
|
6
6
|
/**
|
|
@@ -126,6 +126,129 @@ function toRegExpString(text, func = "RegExp") {
|
|
|
126
126
|
return `new ${func}(${JSON.stringify(source)}${flags ? `, ${JSON.stringify(flags)}` : ""})`;
|
|
127
127
|
}
|
|
128
128
|
//#endregion
|
|
129
|
+
//#region ../../internals/utils/src/reserved.ts
|
|
130
|
+
/**
|
|
131
|
+
* JavaScript and Java reserved words.
|
|
132
|
+
* @link https://github.com/jonschlinkert/reserved/blob/master/index.js
|
|
133
|
+
*/
|
|
134
|
+
const reservedWords = new Set([
|
|
135
|
+
"abstract",
|
|
136
|
+
"arguments",
|
|
137
|
+
"boolean",
|
|
138
|
+
"break",
|
|
139
|
+
"byte",
|
|
140
|
+
"case",
|
|
141
|
+
"catch",
|
|
142
|
+
"char",
|
|
143
|
+
"class",
|
|
144
|
+
"const",
|
|
145
|
+
"continue",
|
|
146
|
+
"debugger",
|
|
147
|
+
"default",
|
|
148
|
+
"delete",
|
|
149
|
+
"do",
|
|
150
|
+
"double",
|
|
151
|
+
"else",
|
|
152
|
+
"enum",
|
|
153
|
+
"eval",
|
|
154
|
+
"export",
|
|
155
|
+
"extends",
|
|
156
|
+
"false",
|
|
157
|
+
"final",
|
|
158
|
+
"finally",
|
|
159
|
+
"float",
|
|
160
|
+
"for",
|
|
161
|
+
"function",
|
|
162
|
+
"goto",
|
|
163
|
+
"if",
|
|
164
|
+
"implements",
|
|
165
|
+
"import",
|
|
166
|
+
"in",
|
|
167
|
+
"instanceof",
|
|
168
|
+
"int",
|
|
169
|
+
"interface",
|
|
170
|
+
"let",
|
|
171
|
+
"long",
|
|
172
|
+
"native",
|
|
173
|
+
"new",
|
|
174
|
+
"null",
|
|
175
|
+
"package",
|
|
176
|
+
"private",
|
|
177
|
+
"protected",
|
|
178
|
+
"public",
|
|
179
|
+
"return",
|
|
180
|
+
"short",
|
|
181
|
+
"static",
|
|
182
|
+
"super",
|
|
183
|
+
"switch",
|
|
184
|
+
"synchronized",
|
|
185
|
+
"this",
|
|
186
|
+
"throw",
|
|
187
|
+
"throws",
|
|
188
|
+
"transient",
|
|
189
|
+
"true",
|
|
190
|
+
"try",
|
|
191
|
+
"typeof",
|
|
192
|
+
"var",
|
|
193
|
+
"void",
|
|
194
|
+
"volatile",
|
|
195
|
+
"while",
|
|
196
|
+
"with",
|
|
197
|
+
"yield",
|
|
198
|
+
"Array",
|
|
199
|
+
"Date",
|
|
200
|
+
"hasOwnProperty",
|
|
201
|
+
"Infinity",
|
|
202
|
+
"isFinite",
|
|
203
|
+
"isNaN",
|
|
204
|
+
"isPrototypeOf",
|
|
205
|
+
"length",
|
|
206
|
+
"Math",
|
|
207
|
+
"name",
|
|
208
|
+
"NaN",
|
|
209
|
+
"Number",
|
|
210
|
+
"Object",
|
|
211
|
+
"prototype",
|
|
212
|
+
"String",
|
|
213
|
+
"toString",
|
|
214
|
+
"undefined",
|
|
215
|
+
"valueOf"
|
|
216
|
+
]);
|
|
217
|
+
/**
|
|
218
|
+
* Returns `true` when `name` is a syntactically valid JavaScript variable name.
|
|
219
|
+
*
|
|
220
|
+
* @example
|
|
221
|
+
* ```ts
|
|
222
|
+
* isValidVarName('status') // true
|
|
223
|
+
* isValidVarName('class') // false (reserved word)
|
|
224
|
+
* isValidVarName('42foo') // false (starts with digit)
|
|
225
|
+
* ```
|
|
226
|
+
*/
|
|
227
|
+
function isValidVarName(name) {
|
|
228
|
+
if (!name || reservedWords.has(name)) return false;
|
|
229
|
+
return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Returns `name` when it's a syntactically valid JavaScript variable name,
|
|
233
|
+
* otherwise prefixes it with `_` so the result is a valid identifier.
|
|
234
|
+
*
|
|
235
|
+
* Useful for sanitizing OpenAPI schema names or operation IDs that start with
|
|
236
|
+
* a digit (e.g. `409`, `504AccountCancel`) before using them as exported
|
|
237
|
+
* variable, type, or function names.
|
|
238
|
+
*
|
|
239
|
+
* @example
|
|
240
|
+
* ```ts
|
|
241
|
+
* ensureValidVarName('409') // '_409'
|
|
242
|
+
* ensureValidVarName('504AccountCancel') // '_504AccountCancel'
|
|
243
|
+
* ensureValidVarName('Pet') // 'Pet'
|
|
244
|
+
* ensureValidVarName('class') // '_class'
|
|
245
|
+
* ```
|
|
246
|
+
*/
|
|
247
|
+
function ensureValidVarName(name) {
|
|
248
|
+
if (!name || isValidVarName(name)) return name;
|
|
249
|
+
return `_${name}`;
|
|
250
|
+
}
|
|
251
|
+
//#endregion
|
|
129
252
|
//#region src/components/Operations.tsx
|
|
130
253
|
function Operations({ name, operations }) {
|
|
131
254
|
const operationsJSON = operations.reduce((prev, acc) => {
|
|
@@ -261,11 +384,11 @@ function buildSchemaNames(node, { params, resolver }) {
|
|
|
261
384
|
}
|
|
262
385
|
responses["default"] = resolver.resolveResponseName(node);
|
|
263
386
|
return {
|
|
264
|
-
request: node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) :
|
|
387
|
+
request: node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) : null,
|
|
265
388
|
parameters: {
|
|
266
|
-
path: pathParam ? resolver.resolvePathParamsName(node, pathParam) :
|
|
267
|
-
query: queryParam ? resolver.resolveQueryParamsName(node, queryParam) :
|
|
268
|
-
header: headerParam ? resolver.resolveHeaderParamsName(node, headerParam) :
|
|
389
|
+
path: pathParam ? resolver.resolvePathParamsName(node, pathParam) : null,
|
|
390
|
+
query: queryParam ? resolver.resolveQueryParamsName(node, queryParam) : null,
|
|
391
|
+
header: headerParam ? resolver.resolveHeaderParamsName(node, headerParam) : null
|
|
269
392
|
},
|
|
270
393
|
responses,
|
|
271
394
|
errors
|
|
@@ -339,30 +462,44 @@ function lengthChecksMini({ min, max, pattern }) {
|
|
|
339
462
|
* to a schema value string using the chainable Zod v4 API.
|
|
340
463
|
*/
|
|
341
464
|
function applyModifiers({ value, nullable, optional, nullish, defaultValue, description }) {
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
465
|
+
const withModifier = (() => {
|
|
466
|
+
if (nullish || nullable && optional) return `${value}.nullish()`;
|
|
467
|
+
if (optional) return `${value}.optional()`;
|
|
468
|
+
if (nullable) return `${value}.nullable()`;
|
|
469
|
+
return value;
|
|
470
|
+
})();
|
|
471
|
+
const withDefault = defaultValue !== void 0 ? `${withModifier}.default(${formatDefault(defaultValue)})` : withModifier;
|
|
472
|
+
return description ? `${withDefault}.describe(${stringify(description)})` : withDefault;
|
|
349
473
|
}
|
|
350
474
|
/**
|
|
351
475
|
* Apply nullable / optional / nullish modifiers using the functional `zod/mini` API
|
|
352
476
|
* (`z.nullable()`, `z.optional()`, `z.nullish()`).
|
|
353
477
|
*/
|
|
354
478
|
function applyMiniModifiers({ value, nullable, optional, nullish, defaultValue }) {
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
}
|
|
361
|
-
if (defaultValue !== void 0) result = `z._default(${result}, ${formatDefault(defaultValue)})`;
|
|
362
|
-
return result;
|
|
479
|
+
const withModifier = (() => {
|
|
480
|
+
if (nullish) return `z.nullish(${value})`;
|
|
481
|
+
const withNullable = nullable ? `z.nullable(${value})` : value;
|
|
482
|
+
return optional ? `z.optional(${withNullable})` : withNullable;
|
|
483
|
+
})();
|
|
484
|
+
return defaultValue !== void 0 ? `z._default(${withModifier}, ${formatDefault(defaultValue)})` : withModifier;
|
|
363
485
|
}
|
|
364
486
|
//#endregion
|
|
365
487
|
//#region src/printers/printerZod.ts
|
|
488
|
+
function strictOneOfMember$1(member, node) {
|
|
489
|
+
if (node.type === "object" && node.additionalProperties === void 0) return `${member}.strict()`;
|
|
490
|
+
if (node.type === "ref") {
|
|
491
|
+
if (member.startsWith("z.lazy(")) return member;
|
|
492
|
+
const schema = ast.syncSchemaRef(node);
|
|
493
|
+
if (schema.type === "object" && (schema.additionalProperties === void 0 || schema.additionalProperties === false)) return `${member}.strict()`;
|
|
494
|
+
}
|
|
495
|
+
return member;
|
|
496
|
+
}
|
|
497
|
+
__name(strictOneOfMember$1, "strictOneOfMember");
|
|
498
|
+
function getMemberConstraint(member) {
|
|
499
|
+
if (member.primitive === "string") return lengthConstraints(ast.narrowSchema(member, "string") ?? {}) || void 0;
|
|
500
|
+
if (member.primitive === "number" || member.primitive === "integer") return numberConstraints(ast.narrowSchema(member, "number") ?? ast.narrowSchema(member, "integer") ?? {}) || void 0;
|
|
501
|
+
if (member.primitive === "array") return lengthConstraints(ast.narrowSchema(member, "array") ?? {}) || void 0;
|
|
502
|
+
}
|
|
366
503
|
/**
|
|
367
504
|
* Zod v4 printer built with `definePrinter`.
|
|
368
505
|
*
|
|
@@ -435,29 +572,29 @@ const printerZod = ast.definePrinter((options) => {
|
|
|
435
572
|
return `z.enum([${nonNullValues.map(formatLiteral).join(", ")}])`;
|
|
436
573
|
},
|
|
437
574
|
ref(node) {
|
|
438
|
-
if (!node.name) return
|
|
575
|
+
if (!node.name) return null;
|
|
439
576
|
const refName = node.ref ? ast.extractRefName(node.ref) ?? node.name : node.name;
|
|
440
577
|
const resolvedName = node.ref ? this.options.resolver?.default(refName, "function") ?? refName : node.name;
|
|
441
578
|
if (node.ref && this.options.cyclicSchemas?.has(refName)) return `z.lazy(() => ${resolvedName})`;
|
|
442
579
|
return resolvedName;
|
|
443
580
|
},
|
|
444
581
|
object(node) {
|
|
445
|
-
|
|
582
|
+
const objectBase = `z.object({\n ${node.properties.map((prop) => {
|
|
446
583
|
const { name: propName, schema } = prop;
|
|
447
584
|
const meta = ast.syncSchemaRef(schema);
|
|
448
585
|
const isNullable = meta.nullable;
|
|
449
586
|
const isOptional = schema.optional;
|
|
450
587
|
const isNullish = schema.nullish;
|
|
451
588
|
const hasSelfRef = this.options.cyclicSchemas != null && ast.containsCircularRef(schema, { circularSchemas: this.options.cyclicSchemas });
|
|
589
|
+
const savedCyclicSchemas = this.options.cyclicSchemas;
|
|
452
590
|
if (hasSelfRef) this.options.cyclicSchemas = void 0;
|
|
453
591
|
const baseOutput = this.transform(schema) ?? this.transform(ast.createSchema({ type: "unknown" }));
|
|
454
|
-
if (hasSelfRef) this.options.cyclicSchemas =
|
|
592
|
+
if (hasSelfRef) this.options.cyclicSchemas = savedCyclicSchemas;
|
|
455
593
|
const wrappedOutput = this.options.wrapOutput ? this.options.wrapOutput({
|
|
456
594
|
output: baseOutput,
|
|
457
595
|
schema
|
|
458
596
|
}) || baseOutput : baseOutput;
|
|
459
|
-
|
|
460
|
-
if (schema.type !== "ref" && meta.type === "ref") descriptionToApply = void 0;
|
|
597
|
+
const descriptionToApply = schema.type !== "ref" && meta.type === "ref" ? void 0 : meta.description;
|
|
461
598
|
const value = applyModifiers({
|
|
462
599
|
value: wrappedOutput,
|
|
463
600
|
nullable: isNullable,
|
|
@@ -469,24 +606,29 @@ const printerZod = ast.definePrinter((options) => {
|
|
|
469
606
|
if (hasSelfRef) return `get "${propName}"() { return ${value} }`;
|
|
470
607
|
return `"${propName}": ${value}`;
|
|
471
608
|
}).join(",\n ")}\n })`;
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
609
|
+
return (() => {
|
|
610
|
+
if (node.additionalProperties && node.additionalProperties !== true) {
|
|
611
|
+
const catchallType = this.transform(node.additionalProperties);
|
|
612
|
+
return catchallType ? `${objectBase}.catchall(${catchallType})` : objectBase;
|
|
613
|
+
}
|
|
614
|
+
if (node.additionalProperties === true) return `${objectBase}.catchall(${this.transform(ast.createSchema({ type: "unknown" }))})`;
|
|
615
|
+
if (node.additionalProperties === false) return `${objectBase}.strict()`;
|
|
616
|
+
return objectBase;
|
|
617
|
+
})();
|
|
478
618
|
},
|
|
479
619
|
array(node) {
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
return result;
|
|
620
|
+
const base = `z.array(${(node.items ?? []).map((item) => this.transform(item)).filter(Boolean).join(", ") || this.transform(ast.createSchema({ type: "unknown" }))})${lengthConstraints(node)}`;
|
|
621
|
+
return node.unique ? `${base}.refine(items => new Set(items).size === items.length, { message: "Array entries must be unique" })` : base;
|
|
483
622
|
},
|
|
484
623
|
tuple(node) {
|
|
485
624
|
return `z.tuple([${(node.items ?? []).map((item) => this.transform(item)).filter(Boolean).join(", ")}])`;
|
|
486
625
|
},
|
|
487
626
|
union(node) {
|
|
488
627
|
const nodeMembers = node.members ?? [];
|
|
489
|
-
const members = nodeMembers.map((
|
|
628
|
+
const members = nodeMembers.map((memberNode) => {
|
|
629
|
+
const member = this.transform(memberNode);
|
|
630
|
+
return member && node.strategy === "one" ? strictOneOfMember$1(member, memberNode) : member;
|
|
631
|
+
}).filter(Boolean);
|
|
490
632
|
if (members.length === 0) return "";
|
|
491
633
|
if (members.length === 1) return members[0];
|
|
492
634
|
if (node.discriminatorPropertyName && !nodeMembers.some((m) => m.type === "intersection")) return `z.discriminatedUnion(${stringify(node.discriminatorPropertyName)}, [${members.join(", ")}])`;
|
|
@@ -497,47 +639,29 @@ const printerZod = ast.definePrinter((options) => {
|
|
|
497
639
|
if (members.length === 0) return "";
|
|
498
640
|
const [first, ...rest] = members;
|
|
499
641
|
if (!first) return "";
|
|
500
|
-
|
|
501
|
-
if (!
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
if (c) {
|
|
506
|
-
base += c;
|
|
507
|
-
continue;
|
|
508
|
-
}
|
|
509
|
-
} else if (member.primitive === "number" || member.primitive === "integer") {
|
|
510
|
-
const c = numberConstraints(ast.narrowSchema(member, "number") ?? ast.narrowSchema(member, "integer") ?? {});
|
|
511
|
-
if (c) {
|
|
512
|
-
base += c;
|
|
513
|
-
continue;
|
|
514
|
-
}
|
|
515
|
-
} else if (member.primitive === "array") {
|
|
516
|
-
const c = lengthConstraints(ast.narrowSchema(member, "array") ?? {});
|
|
517
|
-
if (c) {
|
|
518
|
-
base += c;
|
|
519
|
-
continue;
|
|
520
|
-
}
|
|
521
|
-
}
|
|
642
|
+
const firstBase = this.transform(first);
|
|
643
|
+
if (!firstBase) return "";
|
|
644
|
+
return rest.reduce((acc, member) => {
|
|
645
|
+
const constraint = getMemberConstraint(member);
|
|
646
|
+
if (constraint) return acc + constraint;
|
|
522
647
|
const transformed = this.transform(member);
|
|
523
|
-
|
|
524
|
-
}
|
|
525
|
-
return base;
|
|
648
|
+
return transformed ? `${acc}.and(${transformed})` : acc;
|
|
649
|
+
}, firstBase);
|
|
526
650
|
},
|
|
527
651
|
...options.nodes
|
|
528
652
|
},
|
|
529
653
|
print(node) {
|
|
530
654
|
const { keysToOmit } = this.options;
|
|
531
|
-
|
|
532
|
-
if (!
|
|
655
|
+
const transformed = this.transform(node);
|
|
656
|
+
if (!transformed) return null;
|
|
533
657
|
const meta = ast.syncSchemaRef(node);
|
|
534
|
-
if (keysToOmit?.length && meta.primitive === "object" && !(meta.type === "union" && meta.discriminatorPropertyName)) {
|
|
535
|
-
const lazyMatch = base.match(/^z\.lazy\(\(\)\s*=>\s*(.+)\)$/);
|
|
536
|
-
if (lazyMatch) base = `z.lazy(() => ${lazyMatch[1]}.omit({ ${keysToOmit.map((k) => `"${k}": true`).join(", ")} }))`;
|
|
537
|
-
else base = `${base}.omit({ ${keysToOmit.map((k) => `"${k}": true`).join(", ")} })`;
|
|
538
|
-
}
|
|
539
658
|
return applyModifiers({
|
|
540
|
-
value:
|
|
659
|
+
value: (() => {
|
|
660
|
+
if (!keysToOmit?.length || meta.primitive !== "object" || meta.type === "union" && meta.discriminatorPropertyName) return transformed;
|
|
661
|
+
const lazyMatch = transformed.match(/^z\.lazy\(\(\)\s*=>\s*(.+)\)$/);
|
|
662
|
+
if (lazyMatch) return `z.lazy(() => ${lazyMatch[1]}.omit({ ${keysToOmit.map((k) => `"${k}": true`).join(", ")} }))`;
|
|
663
|
+
return `${transformed}.omit({ ${keysToOmit.map((k) => `"${k}": true`).join(", ")} })`;
|
|
664
|
+
})(),
|
|
541
665
|
nullable: meta.nullable,
|
|
542
666
|
optional: meta.optional,
|
|
543
667
|
nullish: meta.nullish,
|
|
@@ -549,6 +673,15 @@ const printerZod = ast.definePrinter((options) => {
|
|
|
549
673
|
});
|
|
550
674
|
//#endregion
|
|
551
675
|
//#region src/printers/printerZodMini.ts
|
|
676
|
+
function strictOneOfMember(member, node) {
|
|
677
|
+
if (node.type === "object" && (node.additionalProperties === void 0 || node.additionalProperties === false)) return member.replace(/^z\.object\(/, "z.strictObject(");
|
|
678
|
+
return member;
|
|
679
|
+
}
|
|
680
|
+
function getMemberConstraintMini(member) {
|
|
681
|
+
if (member.primitive === "string") return lengthChecksMini(ast.narrowSchema(member, "string") ?? {}) || void 0;
|
|
682
|
+
if (member.primitive === "number" || member.primitive === "integer") return numberChecksMini(ast.narrowSchema(member, "number") ?? ast.narrowSchema(member, "integer") ?? {}) || void 0;
|
|
683
|
+
if (member.primitive === "array") return lengthChecksMini(ast.narrowSchema(member, "array") ?? {}) || void 0;
|
|
684
|
+
}
|
|
552
685
|
/**
|
|
553
686
|
* Zod v4 **Mini** printer built with `definePrinter`.
|
|
554
687
|
*
|
|
@@ -617,7 +750,7 @@ const printerZodMini = ast.definePrinter((options) => {
|
|
|
617
750
|
return `z.enum([${nonNullValues.map(formatLiteral).join(", ")}])`;
|
|
618
751
|
},
|
|
619
752
|
ref(node) {
|
|
620
|
-
if (!node.name) return
|
|
753
|
+
if (!node.name) return null;
|
|
621
754
|
const refName = node.ref ? ast.extractRefName(node.ref) ?? node.name : node.name;
|
|
622
755
|
const resolvedName = node.ref ? this.options.resolver?.default(refName, "function") ?? refName : node.name;
|
|
623
756
|
if (node.ref && this.options.cyclicSchemas?.has(refName)) return `z.lazy(() => ${resolvedName})`;
|
|
@@ -631,9 +764,10 @@ const printerZodMini = ast.definePrinter((options) => {
|
|
|
631
764
|
const isOptional = schema.optional;
|
|
632
765
|
const isNullish = schema.nullish;
|
|
633
766
|
const hasSelfRef = this.options.cyclicSchemas != null && ast.containsCircularRef(schema, { circularSchemas: this.options.cyclicSchemas });
|
|
767
|
+
const savedCyclicSchemas = this.options.cyclicSchemas;
|
|
634
768
|
if (hasSelfRef) this.options.cyclicSchemas = void 0;
|
|
635
769
|
const baseOutput = this.transform(schema) ?? this.transform(ast.createSchema({ type: "unknown" }));
|
|
636
|
-
if (hasSelfRef) this.options.cyclicSchemas =
|
|
770
|
+
if (hasSelfRef) this.options.cyclicSchemas = savedCyclicSchemas;
|
|
637
771
|
const value = applyMiniModifiers({
|
|
638
772
|
value: this.options.wrapOutput ? this.options.wrapOutput({
|
|
639
773
|
output: baseOutput,
|
|
@@ -649,16 +783,18 @@ const printerZodMini = ast.definePrinter((options) => {
|
|
|
649
783
|
}).join(",\n ")}\n })`;
|
|
650
784
|
},
|
|
651
785
|
array(node) {
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
return result;
|
|
786
|
+
const base = `z.array(${(node.items ?? []).map((item) => this.transform(item)).filter(Boolean).join(", ") || this.transform(ast.createSchema({ type: "unknown" }))})${lengthChecksMini(node)}`;
|
|
787
|
+
return node.unique ? `${base}.refine(items => new Set(items).size === items.length, { message: "Array entries must be unique" })` : base;
|
|
655
788
|
},
|
|
656
789
|
tuple(node) {
|
|
657
790
|
return `z.tuple([${(node.items ?? []).map((item) => this.transform(item)).filter(Boolean).join(", ")}])`;
|
|
658
791
|
},
|
|
659
792
|
union(node) {
|
|
660
793
|
const nodeMembers = node.members ?? [];
|
|
661
|
-
const members = nodeMembers.map((
|
|
794
|
+
const members = nodeMembers.map((memberNode) => {
|
|
795
|
+
const member = this.transform(memberNode);
|
|
796
|
+
return member && node.strategy === "one" ? strictOneOfMember(member, memberNode) : member;
|
|
797
|
+
}).filter(Boolean);
|
|
662
798
|
if (members.length === 0) return "";
|
|
663
799
|
if (members.length === 1) return members[0];
|
|
664
800
|
if (node.discriminatorPropertyName && !nodeMembers.some((m) => m.type === "intersection")) return `z.discriminatedUnion(${stringify(node.discriminatorPropertyName)}, [${members.join(", ")}])`;
|
|
@@ -669,47 +805,29 @@ const printerZodMini = ast.definePrinter((options) => {
|
|
|
669
805
|
if (members.length === 0) return "";
|
|
670
806
|
const [first, ...rest] = members;
|
|
671
807
|
if (!first) return "";
|
|
672
|
-
|
|
673
|
-
if (!
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
if (c) {
|
|
678
|
-
base += c;
|
|
679
|
-
continue;
|
|
680
|
-
}
|
|
681
|
-
} else if (member.primitive === "number" || member.primitive === "integer") {
|
|
682
|
-
const c = numberChecksMini(ast.narrowSchema(member, "number") ?? ast.narrowSchema(member, "integer") ?? {});
|
|
683
|
-
if (c) {
|
|
684
|
-
base += c;
|
|
685
|
-
continue;
|
|
686
|
-
}
|
|
687
|
-
} else if (member.primitive === "array") {
|
|
688
|
-
const c = lengthChecksMini(ast.narrowSchema(member, "array") ?? {});
|
|
689
|
-
if (c) {
|
|
690
|
-
base += c;
|
|
691
|
-
continue;
|
|
692
|
-
}
|
|
693
|
-
}
|
|
808
|
+
const firstBase = this.transform(first);
|
|
809
|
+
if (!firstBase) return "";
|
|
810
|
+
return rest.reduce((acc, member) => {
|
|
811
|
+
const constraint = getMemberConstraintMini(member);
|
|
812
|
+
if (constraint) return acc + constraint;
|
|
694
813
|
const transformed = this.transform(member);
|
|
695
|
-
|
|
696
|
-
}
|
|
697
|
-
return base;
|
|
814
|
+
return transformed ? `z.intersection(${acc}, ${transformed})` : acc;
|
|
815
|
+
}, firstBase);
|
|
698
816
|
},
|
|
699
817
|
...options.nodes
|
|
700
818
|
},
|
|
701
819
|
print(node) {
|
|
702
820
|
const { keysToOmit } = this.options;
|
|
703
|
-
|
|
704
|
-
if (!
|
|
821
|
+
const transformed = this.transform(node);
|
|
822
|
+
if (!transformed) return null;
|
|
705
823
|
const meta = ast.syncSchemaRef(node);
|
|
706
|
-
if (keysToOmit?.length && meta.primitive === "object" && !(meta.type === "union" && meta.discriminatorPropertyName)) {
|
|
707
|
-
const lazyMatch = base.match(/^z\.lazy\(\(\)\s*=>\s*(.+)\)$/);
|
|
708
|
-
if (lazyMatch) base = `z.lazy(() => ${lazyMatch[1]}.omit({ ${keysToOmit.map((k) => `"${k}": true`).join(", ")} }))`;
|
|
709
|
-
else base = `${base}.omit({ ${keysToOmit.map((k) => `"${k}": true`).join(", ")} })`;
|
|
710
|
-
}
|
|
711
824
|
return applyMiniModifiers({
|
|
712
|
-
value:
|
|
825
|
+
value: (() => {
|
|
826
|
+
if (!keysToOmit?.length || meta.primitive !== "object" || meta.type === "union" && meta.discriminatorPropertyName) return transformed;
|
|
827
|
+
const lazyMatch = transformed.match(/^z\.lazy\(\(\)\s*=>\s*(.+)\)$/);
|
|
828
|
+
if (lazyMatch) return `z.lazy(() => ${lazyMatch[1]}.omit({ ${keysToOmit.map((k) => `"${k}": true`).join(", ")} }))`;
|
|
829
|
+
return `${transformed}.omit({ ${keysToOmit.map((k) => `"${k}": true`).join(", ")} })`;
|
|
830
|
+
})(),
|
|
713
831
|
nullable: meta.nullable,
|
|
714
832
|
optional: meta.optional,
|
|
715
833
|
nullish: meta.nullish,
|
|
@@ -720,9 +838,17 @@ const printerZodMini = ast.definePrinter((options) => {
|
|
|
720
838
|
});
|
|
721
839
|
//#endregion
|
|
722
840
|
//#region src/generators/zodGenerator.tsx
|
|
841
|
+
const zodPrinterCache = /* @__PURE__ */ new WeakMap();
|
|
842
|
+
const zodMiniPrinterCache = /* @__PURE__ */ new WeakMap();
|
|
843
|
+
/**
|
|
844
|
+
* Built-in generator for `@kubb/plugin-zod`. Emits one Zod schema per
|
|
845
|
+
* schema in the spec plus per-operation request/response/parameter schemas.
|
|
846
|
+
* When `mini: true`, schemas use the Zod Mini functional API instead of
|
|
847
|
+
* chainable methods.
|
|
848
|
+
*/
|
|
723
849
|
const zodGenerator = defineGenerator({
|
|
724
850
|
name: "zod",
|
|
725
|
-
renderer:
|
|
851
|
+
renderer: jsxRendererSync,
|
|
726
852
|
schema(node, ctx) {
|
|
727
853
|
const { adapter, config, resolver, root } = ctx;
|
|
728
854
|
const { output, coercion, guidType, mini, wrapOutput, inferred, importPath, group, printer } = ctx.options;
|
|
@@ -738,7 +864,7 @@ const zodGenerator = defineGenerator({
|
|
|
738
864
|
}, {
|
|
739
865
|
root,
|
|
740
866
|
output,
|
|
741
|
-
group
|
|
867
|
+
group: group ?? void 0
|
|
742
868
|
}).path
|
|
743
869
|
}));
|
|
744
870
|
const meta = {
|
|
@@ -749,37 +875,67 @@ const zodGenerator = defineGenerator({
|
|
|
749
875
|
}, {
|
|
750
876
|
root,
|
|
751
877
|
output,
|
|
752
|
-
group
|
|
878
|
+
group: group ?? void 0
|
|
753
879
|
})
|
|
754
880
|
};
|
|
755
|
-
const inferTypeName = inferred ? resolver.resolveSchemaTypeName(node.name) :
|
|
756
|
-
const cyclicSchemas =
|
|
757
|
-
const schemaPrinter = mini ?
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
881
|
+
const inferTypeName = inferred ? resolver.resolveSchemaTypeName(node.name) : null;
|
|
882
|
+
const cyclicSchemas = new Set(ctx.meta.circularNames);
|
|
883
|
+
const schemaPrinter = mini ? getCachedMiniPrinter() : getCachedStdPrinter();
|
|
884
|
+
function getCachedStdPrinter() {
|
|
885
|
+
const cached = zodPrinterCache.get(resolver);
|
|
886
|
+
if (cached && cached.coercion === coercion && cached.guidType === guidType && cached.dateType === dateType) return cached.printer;
|
|
887
|
+
const p = printerZod({
|
|
888
|
+
coercion,
|
|
889
|
+
guidType,
|
|
890
|
+
dateType,
|
|
891
|
+
wrapOutput,
|
|
892
|
+
resolver,
|
|
893
|
+
cyclicSchemas,
|
|
894
|
+
nodes: printer?.nodes
|
|
895
|
+
});
|
|
896
|
+
zodPrinterCache.set(resolver, {
|
|
897
|
+
printer: p,
|
|
898
|
+
coercion,
|
|
899
|
+
guidType,
|
|
900
|
+
dateType
|
|
901
|
+
});
|
|
902
|
+
return p;
|
|
903
|
+
}
|
|
904
|
+
function getCachedMiniPrinter() {
|
|
905
|
+
const cached = zodMiniPrinterCache.get(resolver);
|
|
906
|
+
if (cached && cached.guidType === guidType) return cached.printer;
|
|
907
|
+
const p = printerZodMini({
|
|
908
|
+
guidType,
|
|
909
|
+
wrapOutput,
|
|
910
|
+
resolver,
|
|
911
|
+
cyclicSchemas,
|
|
912
|
+
nodes: printer?.nodes
|
|
913
|
+
});
|
|
914
|
+
zodMiniPrinterCache.set(resolver, {
|
|
915
|
+
printer: p,
|
|
916
|
+
guidType
|
|
917
|
+
});
|
|
918
|
+
return p;
|
|
919
|
+
}
|
|
772
920
|
return /* @__PURE__ */ jsxs(File, {
|
|
773
921
|
baseName: meta.file.baseName,
|
|
774
922
|
path: meta.file.path,
|
|
775
923
|
meta: meta.file.meta,
|
|
776
|
-
banner: resolver.resolveBanner(
|
|
924
|
+
banner: resolver.resolveBanner(ctx.meta, {
|
|
777
925
|
output,
|
|
778
|
-
config
|
|
926
|
+
config,
|
|
927
|
+
file: {
|
|
928
|
+
path: meta.file.path,
|
|
929
|
+
baseName: meta.file.baseName
|
|
930
|
+
}
|
|
779
931
|
}),
|
|
780
|
-
footer: resolver.resolveFooter(
|
|
932
|
+
footer: resolver.resolveFooter(ctx.meta, {
|
|
781
933
|
output,
|
|
782
|
-
config
|
|
934
|
+
config,
|
|
935
|
+
file: {
|
|
936
|
+
path: meta.file.path,
|
|
937
|
+
baseName: meta.file.baseName
|
|
938
|
+
}
|
|
783
939
|
}),
|
|
784
940
|
children: [
|
|
785
941
|
/* @__PURE__ */ jsx(File.Import, {
|
|
@@ -816,12 +972,12 @@ const zodGenerator = defineGenerator({
|
|
|
816
972
|
}, {
|
|
817
973
|
root,
|
|
818
974
|
output,
|
|
819
|
-
group
|
|
975
|
+
group: group ?? void 0
|
|
820
976
|
}) };
|
|
821
|
-
const cyclicSchemas =
|
|
977
|
+
const cyclicSchemas = new Set(ctx.meta.circularNames);
|
|
822
978
|
function renderSchemaEntry({ schema, name, keysToOmit }) {
|
|
823
979
|
if (!schema) return null;
|
|
824
|
-
const inferTypeName = inferred ? resolver.resolveTypeName(name) :
|
|
980
|
+
const inferTypeName = inferred ? resolver.resolveTypeName(name) : null;
|
|
825
981
|
const imports = adapter.getImports(schema, (schemaName) => ({
|
|
826
982
|
name: resolver.resolveSchemaName(schemaName),
|
|
827
983
|
path: resolver.resolveFile({
|
|
@@ -830,17 +986,25 @@ const zodGenerator = defineGenerator({
|
|
|
830
986
|
}, {
|
|
831
987
|
root,
|
|
832
988
|
output,
|
|
833
|
-
group
|
|
989
|
+
group: group ?? void 0
|
|
834
990
|
}).path
|
|
835
991
|
}));
|
|
836
|
-
const
|
|
992
|
+
const cachedStd = zodPrinterCache.get(resolver);
|
|
993
|
+
const cachedMini = zodMiniPrinterCache.get(resolver);
|
|
994
|
+
const schemaPrinter = mini ? keysToOmit?.length ? printerZodMini({
|
|
837
995
|
guidType,
|
|
838
996
|
wrapOutput,
|
|
839
997
|
resolver,
|
|
840
998
|
keysToOmit,
|
|
841
999
|
cyclicSchemas,
|
|
842
1000
|
nodes: printer?.nodes
|
|
843
|
-
}) :
|
|
1001
|
+
}) : cachedMini?.guidType === guidType ? cachedMini.printer : printerZodMini({
|
|
1002
|
+
guidType,
|
|
1003
|
+
wrapOutput,
|
|
1004
|
+
resolver,
|
|
1005
|
+
cyclicSchemas,
|
|
1006
|
+
nodes: printer?.nodes
|
|
1007
|
+
}) : keysToOmit?.length ? printerZod({
|
|
844
1008
|
coercion,
|
|
845
1009
|
guidType,
|
|
846
1010
|
dateType,
|
|
@@ -849,6 +1013,14 @@ const zodGenerator = defineGenerator({
|
|
|
849
1013
|
keysToOmit,
|
|
850
1014
|
cyclicSchemas,
|
|
851
1015
|
nodes: printer?.nodes
|
|
1016
|
+
}) : cachedStd?.coercion === coercion && cachedStd?.guidType === guidType && cachedStd?.dateType === dateType ? cachedStd.printer : printerZod({
|
|
1017
|
+
coercion,
|
|
1018
|
+
guidType,
|
|
1019
|
+
dateType,
|
|
1020
|
+
wrapOutput,
|
|
1021
|
+
resolver,
|
|
1022
|
+
cyclicSchemas,
|
|
1023
|
+
nodes: printer?.nodes
|
|
852
1024
|
});
|
|
853
1025
|
return /* @__PURE__ */ jsxs(Fragment, { children: [mode === "split" && imports.map((imp) => /* @__PURE__ */ jsx(File.Import, {
|
|
854
1026
|
root: meta.file.path,
|
|
@@ -870,14 +1042,14 @@ const zodGenerator = defineGenerator({
|
|
|
870
1042
|
name: resolver.resolveParamName(node, param)
|
|
871
1043
|
}));
|
|
872
1044
|
const responseSchemas = node.responses.map((res) => renderSchemaEntry({
|
|
873
|
-
schema: res.schema,
|
|
1045
|
+
schema: res.content?.[0]?.schema ?? null,
|
|
874
1046
|
name: resolver.resolveResponseStatusName(node, res.statusCode),
|
|
875
|
-
keysToOmit: res.keysToOmit
|
|
1047
|
+
keysToOmit: res.content?.[0]?.keysToOmit
|
|
876
1048
|
}));
|
|
877
|
-
const responsesWithSchema = node.responses.filter((res) => res.schema);
|
|
1049
|
+
const responsesWithSchema = node.responses.filter((res) => res.content?.[0]?.schema);
|
|
878
1050
|
const responseUnionSchema = responsesWithSchema.length > 0 ? (() => {
|
|
879
1051
|
const responseUnionName = resolver.resolveResponseName(node);
|
|
880
|
-
if (new Set(responsesWithSchema.flatMap((res) => res.schema ? adapter.getImports(res.schema, (schemaName) => ({
|
|
1052
|
+
if (new Set(responsesWithSchema.flatMap((res) => res.content?.[0]?.schema ? adapter.getImports(res.content[0].schema, (schemaName) => ({
|
|
881
1053
|
name: resolver.resolveSchemaName(schemaName),
|
|
882
1054
|
path: ""
|
|
883
1055
|
})).flatMap((imp) => Array.isArray(imp.name) ? imp.name : [imp.name]) : [])).has(responseUnionName)) return null;
|
|
@@ -905,13 +1077,21 @@ const zodGenerator = defineGenerator({
|
|
|
905
1077
|
baseName: meta.file.baseName,
|
|
906
1078
|
path: meta.file.path,
|
|
907
1079
|
meta: meta.file.meta,
|
|
908
|
-
banner: resolver.resolveBanner(
|
|
1080
|
+
banner: resolver.resolveBanner(ctx.meta, {
|
|
909
1081
|
output,
|
|
910
|
-
config
|
|
1082
|
+
config,
|
|
1083
|
+
file: {
|
|
1084
|
+
path: meta.file.path,
|
|
1085
|
+
baseName: meta.file.baseName
|
|
1086
|
+
}
|
|
911
1087
|
}),
|
|
912
|
-
footer: resolver.resolveFooter(
|
|
1088
|
+
footer: resolver.resolveFooter(ctx.meta, {
|
|
913
1089
|
output,
|
|
914
|
-
config
|
|
1090
|
+
config,
|
|
1091
|
+
file: {
|
|
1092
|
+
path: meta.file.path,
|
|
1093
|
+
baseName: meta.file.baseName
|
|
1094
|
+
}
|
|
915
1095
|
}),
|
|
916
1096
|
children: [
|
|
917
1097
|
/* @__PURE__ */ jsx(File.Import, {
|
|
@@ -927,7 +1107,7 @@ const zodGenerator = defineGenerator({
|
|
|
927
1107
|
});
|
|
928
1108
|
},
|
|
929
1109
|
operations(nodes, ctx) {
|
|
930
|
-
const {
|
|
1110
|
+
const { config, resolver, root } = ctx;
|
|
931
1111
|
const { output, importPath, group, operations, paramsCasing } = ctx.options;
|
|
932
1112
|
if (!operations) return;
|
|
933
1113
|
const isZodImport = ZOD_NAMESPACE_IMPORTS.has(importPath);
|
|
@@ -937,7 +1117,7 @@ const zodGenerator = defineGenerator({
|
|
|
937
1117
|
}, {
|
|
938
1118
|
root,
|
|
939
1119
|
output,
|
|
940
|
-
group
|
|
1120
|
+
group: group ?? void 0
|
|
941
1121
|
}) };
|
|
942
1122
|
const transformedOperations = nodes.map((node) => {
|
|
943
1123
|
return {
|
|
@@ -962,7 +1142,7 @@ const zodGenerator = defineGenerator({
|
|
|
962
1142
|
}, {
|
|
963
1143
|
root,
|
|
964
1144
|
output,
|
|
965
|
-
group
|
|
1145
|
+
group: group ?? void 0
|
|
966
1146
|
});
|
|
967
1147
|
return names.map((name) => /* @__PURE__ */ jsx(File.Import, {
|
|
968
1148
|
name: [name],
|
|
@@ -974,13 +1154,21 @@ const zodGenerator = defineGenerator({
|
|
|
974
1154
|
baseName: meta.file.baseName,
|
|
975
1155
|
path: meta.file.path,
|
|
976
1156
|
meta: meta.file.meta,
|
|
977
|
-
banner: resolver.resolveBanner(
|
|
1157
|
+
banner: resolver.resolveBanner(ctx.meta, {
|
|
978
1158
|
output,
|
|
979
|
-
config
|
|
1159
|
+
config,
|
|
1160
|
+
file: {
|
|
1161
|
+
path: meta.file.path,
|
|
1162
|
+
baseName: meta.file.baseName
|
|
1163
|
+
}
|
|
980
1164
|
}),
|
|
981
|
-
footer: resolver.resolveFooter(
|
|
1165
|
+
footer: resolver.resolveFooter(ctx.meta, {
|
|
982
1166
|
output,
|
|
983
|
-
config
|
|
1167
|
+
config,
|
|
1168
|
+
file: {
|
|
1169
|
+
path: meta.file.path,
|
|
1170
|
+
baseName: meta.file.baseName
|
|
1171
|
+
}
|
|
984
1172
|
}),
|
|
985
1173
|
children: [
|
|
986
1174
|
/* @__PURE__ */ jsx(File.Import, {
|
|
@@ -1001,77 +1189,96 @@ const zodGenerator = defineGenerator({
|
|
|
1001
1189
|
//#endregion
|
|
1002
1190
|
//#region src/resolvers/resolverZod.ts
|
|
1003
1191
|
/**
|
|
1004
|
-
*
|
|
1192
|
+
* Default resolver used by `@kubb/plugin-zod`. Decides the names and file
|
|
1193
|
+
* paths for every generated Zod schema. Schemas use camelCase with a
|
|
1194
|
+
* `Schema` suffix (`listPetsSchema`); their inferred types use PascalCase.
|
|
1005
1195
|
*
|
|
1006
|
-
*
|
|
1196
|
+
* @example Resolve schema and type names
|
|
1197
|
+
* ```ts
|
|
1198
|
+
* import { resolverZod } from '@kubb/plugin-zod'
|
|
1007
1199
|
*
|
|
1008
|
-
*
|
|
1009
|
-
*
|
|
1200
|
+
* resolverZod.default('list pets', 'function') // 'listPetsSchema'
|
|
1201
|
+
* resolverZod.resolveSchemaTypeName('pet') // 'PetSchema'
|
|
1202
|
+
* ```
|
|
1010
1203
|
*/
|
|
1011
|
-
const resolverZod = defineResolver((
|
|
1204
|
+
const resolverZod = defineResolver(() => {
|
|
1012
1205
|
return {
|
|
1013
1206
|
name: "default",
|
|
1014
1207
|
pluginName: "plugin-zod",
|
|
1015
1208
|
default(name, type) {
|
|
1016
|
-
|
|
1209
|
+
const resolved = camelCase(name, {
|
|
1017
1210
|
isFile: type === "file",
|
|
1018
1211
|
suffix: type ? "schema" : void 0
|
|
1019
1212
|
});
|
|
1213
|
+
return type === "file" ? resolved : ensureValidVarName(resolved);
|
|
1020
1214
|
},
|
|
1021
1215
|
resolveSchemaName(name) {
|
|
1022
|
-
return camelCase(name, { suffix: "schema" });
|
|
1216
|
+
return ensureValidVarName(camelCase(name, { suffix: "schema" }));
|
|
1023
1217
|
},
|
|
1024
1218
|
resolveSchemaTypeName(name) {
|
|
1025
|
-
return pascalCase(name, { suffix: "schema" });
|
|
1219
|
+
return ensureValidVarName(pascalCase(name, { suffix: "schema" }));
|
|
1026
1220
|
},
|
|
1027
1221
|
resolveTypeName(name) {
|
|
1028
|
-
return pascalCase(name);
|
|
1222
|
+
return ensureValidVarName(pascalCase(name));
|
|
1029
1223
|
},
|
|
1030
1224
|
resolvePathName(name, type) {
|
|
1031
|
-
return
|
|
1225
|
+
return this.default(name, type);
|
|
1032
1226
|
},
|
|
1033
1227
|
resolveParamName(node, param) {
|
|
1034
|
-
return
|
|
1228
|
+
return this.resolveSchemaName(`${node.operationId} ${param.in} ${param.name}`);
|
|
1035
1229
|
},
|
|
1036
1230
|
resolveResponseStatusName(node, statusCode) {
|
|
1037
|
-
return
|
|
1231
|
+
return this.resolveSchemaName(`${node.operationId} Status ${statusCode}`);
|
|
1038
1232
|
},
|
|
1039
1233
|
resolveDataName(node) {
|
|
1040
|
-
return
|
|
1234
|
+
return this.resolveSchemaName(`${node.operationId} Data`);
|
|
1041
1235
|
},
|
|
1042
1236
|
resolveResponsesName(node) {
|
|
1043
|
-
return
|
|
1237
|
+
return this.resolveSchemaName(`${node.operationId} Responses`);
|
|
1044
1238
|
},
|
|
1045
1239
|
resolveResponseName(node) {
|
|
1046
|
-
return
|
|
1240
|
+
return this.resolveSchemaName(`${node.operationId} Response`);
|
|
1047
1241
|
},
|
|
1048
1242
|
resolvePathParamsName(node, param) {
|
|
1049
|
-
return
|
|
1243
|
+
return this.resolveParamName(node, param);
|
|
1050
1244
|
},
|
|
1051
1245
|
resolveQueryParamsName(node, param) {
|
|
1052
|
-
return
|
|
1246
|
+
return this.resolveParamName(node, param);
|
|
1053
1247
|
},
|
|
1054
1248
|
resolveHeaderParamsName(node, param) {
|
|
1055
|
-
return
|
|
1249
|
+
return this.resolveParamName(node, param);
|
|
1056
1250
|
}
|
|
1057
1251
|
};
|
|
1058
1252
|
});
|
|
1059
1253
|
//#endregion
|
|
1060
1254
|
//#region src/plugin.ts
|
|
1061
1255
|
/**
|
|
1062
|
-
* Canonical plugin name for `@kubb/plugin-zod
|
|
1256
|
+
* Canonical plugin name for `@kubb/plugin-zod`. Used for driver lookups and
|
|
1257
|
+
* cross-plugin dependency references.
|
|
1063
1258
|
*/
|
|
1064
1259
|
const pluginZodName = "plugin-zod";
|
|
1065
1260
|
/**
|
|
1066
|
-
* Generates Zod
|
|
1067
|
-
*
|
|
1068
|
-
*
|
|
1261
|
+
* Generates Zod v4 schemas from an OpenAPI spec. Use them to validate API
|
|
1262
|
+
* responses at runtime, build form schemas, or feed back into router libraries
|
|
1263
|
+
* that consume Zod (tRPC, Hono, Elysia). Pair with `@kubb/plugin-client` and
|
|
1264
|
+
* set the client's `parser: 'zod'` to validate every response automatically.
|
|
1069
1265
|
*
|
|
1070
|
-
* @example
|
|
1266
|
+
* @example
|
|
1071
1267
|
* ```ts
|
|
1072
|
-
* import
|
|
1268
|
+
* import { defineConfig } from 'kubb'
|
|
1269
|
+
* import { pluginTs } from '@kubb/plugin-ts'
|
|
1270
|
+
* import { pluginZod } from '@kubb/plugin-zod'
|
|
1271
|
+
*
|
|
1073
1272
|
* export default defineConfig({
|
|
1074
|
-
*
|
|
1273
|
+
* input: { path: './petStore.yaml' },
|
|
1274
|
+
* output: { path: './src/gen' },
|
|
1275
|
+
* plugins: [
|
|
1276
|
+
* pluginTs(),
|
|
1277
|
+
* pluginZod({
|
|
1278
|
+
* output: { path: './zod' },
|
|
1279
|
+
* typed: true,
|
|
1280
|
+
* }),
|
|
1281
|
+
* ],
|
|
1075
1282
|
* })
|
|
1076
1283
|
* ```
|
|
1077
1284
|
*/
|
|
@@ -1086,7 +1293,7 @@ const pluginZod = definePlugin((options) => {
|
|
|
1086
1293
|
if (group.type === "path") return `${ctx.group.split("/")[1]}`;
|
|
1087
1294
|
return `${camelCase(ctx.group)}Controller`;
|
|
1088
1295
|
}
|
|
1089
|
-
} :
|
|
1296
|
+
} : null;
|
|
1090
1297
|
return {
|
|
1091
1298
|
name: pluginZodName,
|
|
1092
1299
|
options,
|