@kubb/plugin-zod 5.0.0-beta.42 → 5.0.0-beta.64
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 +123 -182
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +18 -20
- package/dist/index.js +117 -176
- package/dist/index.js.map +1 -1
- package/package.json +7 -15
- package/extension.yaml +0 -970
- package/src/components/Operations.tsx +0 -78
- package/src/components/Zod.tsx +0 -42
- package/src/constants.ts +0 -5
- package/src/generators/zodGenerator.tsx +0 -366
- package/src/index.ts +0 -11
- package/src/plugin.ts +0 -97
- package/src/printers/printerZod.ts +0 -362
- package/src/printers/printerZodMini.ts +0 -292
- package/src/resolvers/resolverZod.ts +0 -69
- package/src/types.ts +0 -223
- package/src/utils.ts +0 -299
package/dist/index.cjs
CHANGED
|
@@ -10,6 +10,7 @@ var __name = (target, value) => __defProp(target, "name", {
|
|
|
10
10
|
});
|
|
11
11
|
//#endregion
|
|
12
12
|
let _kubb_core = require("@kubb/core");
|
|
13
|
+
let _kubb_ast_utils = require("@kubb/ast/utils");
|
|
13
14
|
let _kubb_renderer_jsx = require("@kubb/renderer-jsx");
|
|
14
15
|
let _kubb_renderer_jsx_jsx_runtime = require("@kubb/renderer-jsx/jsx-runtime");
|
|
15
16
|
//#region ../../internals/utils/src/casing.ts
|
|
@@ -23,117 +24,57 @@ let _kubb_renderer_jsx_jsx_runtime = require("@kubb/renderer-jsx/jsx-runtime");
|
|
|
23
24
|
function toCamelOrPascal(text, pascal) {
|
|
24
25
|
return text.trim().replace(/([a-z\d])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").replace(/(\d)([a-z])/g, "$1 $2").split(/[\s\-_./\\:]+/).filter(Boolean).map((word, i) => {
|
|
25
26
|
if (word.length > 1 && word === word.toUpperCase()) return word;
|
|
26
|
-
|
|
27
|
-
return word.charAt(0).toUpperCase() + word.slice(1);
|
|
27
|
+
return (i === 0 && !pascal ? word.charAt(0).toLowerCase() : word.charAt(0).toUpperCase()) + word.slice(1);
|
|
28
28
|
}).join("").replace(/[^a-zA-Z0-9]/g, "");
|
|
29
29
|
}
|
|
30
30
|
/**
|
|
31
|
-
* Splits `text` on `.` and applies `transformPart` to each segment.
|
|
32
|
-
* The last segment receives `isLast = true`, all earlier segments receive `false`.
|
|
33
|
-
* Segments are joined with `/` to form a file path.
|
|
34
|
-
*
|
|
35
|
-
* Only splits on dots followed by a letter so that version numbers
|
|
36
|
-
* embedded in operationIds (e.g. `v2025.0`) are kept intact.
|
|
37
|
-
*/
|
|
38
|
-
function applyToFileParts(text, transformPart) {
|
|
39
|
-
const parts = text.split(/\.(?=[a-zA-Z])/);
|
|
40
|
-
return parts.map((part, i) => transformPart(part, i === parts.length - 1)).join("/");
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
31
|
* Converts `text` to camelCase.
|
|
44
|
-
* When `isFile` is `true`, dot-separated segments are each cased independently and joined with `/`.
|
|
45
32
|
*
|
|
46
|
-
* @example
|
|
47
|
-
* camelCase('hello-world')
|
|
48
|
-
*
|
|
33
|
+
* @example Word boundaries
|
|
34
|
+
* `camelCase('hello-world') // 'helloWorld'`
|
|
35
|
+
*
|
|
36
|
+
* @example With a prefix
|
|
37
|
+
* `camelCase('tag', { prefix: 'create' }) // 'createTag'`
|
|
49
38
|
*/
|
|
50
|
-
function camelCase(text, {
|
|
51
|
-
if (isFile) return applyToFileParts(text, (part, isLast) => camelCase(part, isLast ? {
|
|
52
|
-
prefix,
|
|
53
|
-
suffix
|
|
54
|
-
} : {}));
|
|
39
|
+
function camelCase(text, { prefix = "", suffix = "" } = {}) {
|
|
55
40
|
return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false);
|
|
56
41
|
}
|
|
57
42
|
/**
|
|
58
43
|
* Converts `text` to PascalCase.
|
|
59
|
-
* When `isFile` is `true`, the last dot-separated segment is PascalCased and earlier segments are camelCased.
|
|
60
44
|
*
|
|
61
|
-
* @example
|
|
62
|
-
* pascalCase('hello-world')
|
|
63
|
-
*
|
|
45
|
+
* @example Word boundaries
|
|
46
|
+
* `pascalCase('hello-world') // 'HelloWorld'`
|
|
47
|
+
*
|
|
48
|
+
* @example With a suffix
|
|
49
|
+
* `pascalCase('tag', { suffix: 'schema' }) // 'TagSchema'`
|
|
64
50
|
*/
|
|
65
|
-
function pascalCase(text, {
|
|
66
|
-
if (isFile) return applyToFileParts(text, (part, isLast) => isLast ? pascalCase(part, {
|
|
67
|
-
prefix,
|
|
68
|
-
suffix
|
|
69
|
-
}) : camelCase(part));
|
|
51
|
+
function pascalCase(text, { prefix = "", suffix = "" } = {}) {
|
|
70
52
|
return toCamelOrPascal(`${prefix} ${text} ${suffix}`, true);
|
|
71
53
|
}
|
|
72
54
|
//#endregion
|
|
73
|
-
//#region ../../internals/utils/src/
|
|
55
|
+
//#region ../../internals/utils/src/fs.ts
|
|
74
56
|
/**
|
|
75
|
-
*
|
|
76
|
-
*
|
|
57
|
+
* Builds a nested file path from a dotted name. Splits on dots that precede a letter
|
|
58
|
+
* (so version numbers embedded in operationIds like `v2025.0` stay intact), camelCases
|
|
59
|
+
* every earlier segment, applies `caseLast` to the final segment, and joins with `/`.
|
|
77
60
|
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
|
|
82
|
-
function trimQuotes(text) {
|
|
83
|
-
if (text.length >= 2) {
|
|
84
|
-
const first = text[0];
|
|
85
|
-
const last = text[text.length - 1];
|
|
86
|
-
if (first === "\"" && last === "\"" || first === "'" && last === "'" || first === "`" && last === "`") return text.slice(1, -1);
|
|
87
|
-
}
|
|
88
|
-
return text;
|
|
89
|
-
}
|
|
90
|
-
//#endregion
|
|
91
|
-
//#region ../../internals/utils/src/object.ts
|
|
92
|
-
/**
|
|
93
|
-
* Serializes a primitive value to a JSON string literal, stripping any surrounding quote characters first.
|
|
61
|
+
* Empty segments are dropped before joining. They arise when the name starts with a dot
|
|
62
|
+
* followed by a letter (e.g. `..Schema` splits into `['..', 'Schema']` and `'..'` cases to
|
|
63
|
+
* an empty string). Without this a leading `/` would form, which `path.resolve` reads as an
|
|
64
|
+
* absolute path, letting generated files escape the configured output directory.
|
|
94
65
|
*
|
|
95
|
-
* @example
|
|
96
|
-
*
|
|
97
|
-
* stringify('"hello"') // '"hello"'
|
|
98
|
-
*/
|
|
99
|
-
function stringify(value) {
|
|
100
|
-
if (value === void 0 || value === null) return "\"\"";
|
|
101
|
-
return JSON.stringify(trimQuotes(value.toString()));
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* Converts a plain object into a multiline key-value string suitable for embedding in generated code.
|
|
105
|
-
* Nested objects are recursively stringified with indentation.
|
|
66
|
+
* @example Nested path from a dotted name
|
|
67
|
+
* `toFilePath('pet.petId') // 'pet/petId'`
|
|
106
68
|
*
|
|
107
|
-
* @example
|
|
108
|
-
*
|
|
109
|
-
* // 'foo: bar,\nnested: {\n a: 1\n }'
|
|
110
|
-
*/
|
|
111
|
-
function stringifyObject(value) {
|
|
112
|
-
return Object.entries(value).map(([key, val]) => {
|
|
113
|
-
if (val !== null && typeof val === "object") return `${key}: {\n ${stringifyObject(val)}\n }`;
|
|
114
|
-
return `${key}: ${val}`;
|
|
115
|
-
}).filter(Boolean).join(",\n");
|
|
116
|
-
}
|
|
117
|
-
//#endregion
|
|
118
|
-
//#region ../../internals/utils/src/regexp.ts
|
|
119
|
-
/**
|
|
120
|
-
* Converts a pattern string into a `new RegExp(...)` constructor call or a regex literal string.
|
|
121
|
-
* Inline flags expressed as `^(?im)` prefixes are extracted and applied to the resulting expression.
|
|
122
|
-
* Pass `null` as the second argument to emit a `/pattern/flags` literal instead.
|
|
69
|
+
* @example PascalCase the final segment
|
|
70
|
+
* `toFilePath('pet.Pet', pascalCase) // 'pet/Pet'`
|
|
123
71
|
*
|
|
124
|
-
* @example
|
|
125
|
-
*
|
|
126
|
-
* toRegExpString('^(?im)foo', null) // → '/foo/im'
|
|
72
|
+
* @example Suffix applied to the final segment only
|
|
73
|
+
* `toFilePath('tag.tag', (part) => camelCase(part, { suffix: 'schema' })) // 'tag/tagSchema'`
|
|
127
74
|
*/
|
|
128
|
-
function
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
const replacementTarget = match?.[1] ?? "";
|
|
132
|
-
const matchedFlags = match?.[2];
|
|
133
|
-
const cleaned = raw.replace(/^\\?\//, "").replace(/\\?\/$/, "").replace(replacementTarget, "");
|
|
134
|
-
const { source, flags } = new RegExp(cleaned, matchedFlags);
|
|
135
|
-
if (func === null) return `/${source}/${flags}`;
|
|
136
|
-
return `new ${func}(${JSON.stringify(source)}${flags ? `, ${JSON.stringify(flags)}` : ""})`;
|
|
75
|
+
function toFilePath(name, caseLast = camelCase) {
|
|
76
|
+
const parts = name.split(/\.(?=[a-zA-Z])/);
|
|
77
|
+
return parts.map((part, i) => i === parts.length - 1 ? caseLast(part) : camelCase(part)).filter(Boolean).join("/");
|
|
137
78
|
}
|
|
138
79
|
//#endregion
|
|
139
80
|
//#region ../../internals/utils/src/reserved.ts
|
|
@@ -315,26 +256,24 @@ function resolveContentTypeVariants(entries, baseName) {
|
|
|
315
256
|
* shared default naming so every plugin groups output consistently:
|
|
316
257
|
*
|
|
317
258
|
* - `path` groups use the second path segment (`/pet/findByStatus` → `pet`).
|
|
318
|
-
* - other groups use
|
|
259
|
+
* - other groups use the camelCased group (`pet store` → `petStore`).
|
|
319
260
|
*
|
|
320
261
|
* A user-provided `group.name` always wins over the default namer, so callers stay in
|
|
321
262
|
* control of their output folders. Returns `null` when grouping is disabled, matching the
|
|
322
263
|
* per-plugin convention.
|
|
323
264
|
*
|
|
324
265
|
* @param group - The user-supplied group option, or `undefined` to disable grouping.
|
|
325
|
-
* @param options.suffix - Appended to non-`path` group names, e.g. `'Controller'` or `'Requests'`.
|
|
326
266
|
*
|
|
327
267
|
* @example
|
|
328
268
|
* ```ts
|
|
329
|
-
* createGroupConfig(group
|
|
330
|
-
* createGroupConfig(group, { suffix: 'Requests' }) // plugin-cypress, plugin-mcp
|
|
269
|
+
* createGroupConfig(group) // shared across every plugin
|
|
331
270
|
* ```
|
|
332
271
|
*/
|
|
333
|
-
function createGroupConfig(group
|
|
272
|
+
function createGroupConfig(group) {
|
|
334
273
|
if (!group) return null;
|
|
335
274
|
const defaultName = (ctx) => {
|
|
336
275
|
if (group.type === "path") return `${ctx.group.split("/")[1]}`;
|
|
337
|
-
return
|
|
276
|
+
return camelCase(ctx.group);
|
|
338
277
|
};
|
|
339
278
|
return {
|
|
340
279
|
...group,
|
|
@@ -399,7 +338,7 @@ function Operations({ name, operations }) {
|
|
|
399
338
|
export: true,
|
|
400
339
|
name,
|
|
401
340
|
asConst: true,
|
|
402
|
-
children: `{${stringifyObject(operationsJSON)}}`
|
|
341
|
+
children: `{${(0, _kubb_ast_utils.stringifyObject)(operationsJSON)}}`
|
|
403
342
|
})
|
|
404
343
|
}),
|
|
405
344
|
/* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Source, {
|
|
@@ -410,7 +349,7 @@ function Operations({ name, operations }) {
|
|
|
410
349
|
export: true,
|
|
411
350
|
name: "paths",
|
|
412
351
|
asConst: true,
|
|
413
|
-
children: `{${stringifyObject(pathsJSON)}}`
|
|
352
|
+
children: `{${(0, _kubb_ast_utils.stringifyObject)(pathsJSON)}}`
|
|
414
353
|
})
|
|
415
354
|
})
|
|
416
355
|
] });
|
|
@@ -497,12 +436,12 @@ function containsCodec(node, seen = /* @__PURE__ */ new Set()) {
|
|
|
497
436
|
if (hasCodec(node)) return true;
|
|
498
437
|
if (node.type === "ref") {
|
|
499
438
|
if (!node.ref) return false;
|
|
500
|
-
const refName =
|
|
439
|
+
const refName = (0, _kubb_ast_utils.extractRefName)(node.ref);
|
|
501
440
|
if (refName) {
|
|
502
441
|
if (seen.has(refName)) return false;
|
|
503
442
|
seen.add(refName);
|
|
504
443
|
}
|
|
505
|
-
const resolved =
|
|
444
|
+
const resolved = (0, _kubb_ast_utils.syncSchemaRef)(node);
|
|
506
445
|
if (resolved.type === "ref") return false;
|
|
507
446
|
return containsCodec(resolved, seen);
|
|
508
447
|
}
|
|
@@ -514,6 +453,13 @@ function containsCodec(node, seen = /* @__PURE__ */ new Set()) {
|
|
|
514
453
|
return children.some((child) => containsCodec(child, seen));
|
|
515
454
|
}
|
|
516
455
|
/**
|
|
456
|
+
* Collects the names of `$ref` schemas that transitively contain a codec, so the generator can route
|
|
457
|
+
* them to their input (encode) variant.
|
|
458
|
+
*/
|
|
459
|
+
function collectCodecRefNames(node) {
|
|
460
|
+
return _kubb_core.ast.collect(node, { schema: (n) => n.type === "ref" && n.ref && containsCodec(n) ? (0, _kubb_ast_utils.extractRefName)(n.ref) ?? void 0 : void 0 });
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
517
463
|
* Collects all resolved schema names for an operation's parameters and responses
|
|
518
464
|
* into a single lookup object, useful for building imports and type references.
|
|
519
465
|
*/
|
|
@@ -548,7 +494,7 @@ function buildSchemaNames(node, { params, resolver }) {
|
|
|
548
494
|
* Objects become `{}`, primitives become their string representation, strings are quoted.
|
|
549
495
|
*/
|
|
550
496
|
function formatDefault(value) {
|
|
551
|
-
if (typeof value === "string") return stringify(value);
|
|
497
|
+
if (typeof value === "string") return (0, _kubb_ast_utils.stringify)(value);
|
|
552
498
|
if (typeof value === "object" && value !== null) return "{}";
|
|
553
499
|
return String(value ?? "");
|
|
554
500
|
}
|
|
@@ -557,7 +503,7 @@ function formatDefault(value) {
|
|
|
557
503
|
* Strings are quoted; numbers and booleans are emitted raw.
|
|
558
504
|
*/
|
|
559
505
|
function formatLiteral(v) {
|
|
560
|
-
if (typeof v === "string") return stringify(v);
|
|
506
|
+
if (typeof v === "string") return (0, _kubb_ast_utils.stringify)(v);
|
|
561
507
|
return String(v);
|
|
562
508
|
}
|
|
563
509
|
/**
|
|
@@ -581,7 +527,7 @@ function lengthConstraints({ min, max, pattern }) {
|
|
|
581
527
|
return [
|
|
582
528
|
min !== void 0 ? `.min(${min})` : "",
|
|
583
529
|
max !== void 0 ? `.max(${max})` : "",
|
|
584
|
-
pattern !== void 0 ? `.regex(${toRegExpString(pattern, null)})` : ""
|
|
530
|
+
pattern !== void 0 ? `.regex(${(0, _kubb_ast_utils.toRegExpString)(pattern, null)})` : ""
|
|
585
531
|
].join("");
|
|
586
532
|
}
|
|
587
533
|
/**
|
|
@@ -603,7 +549,7 @@ function lengthChecksMini({ min, max, pattern }) {
|
|
|
603
549
|
const checks = [];
|
|
604
550
|
if (min !== void 0) checks.push(`z.minLength(${min})`);
|
|
605
551
|
if (max !== void 0) checks.push(`z.maxLength(${max})`);
|
|
606
|
-
if (pattern !== void 0) checks.push(`z.regex(${toRegExpString(pattern, null)})`);
|
|
552
|
+
if (pattern !== void 0) checks.push(`z.regex(${(0, _kubb_ast_utils.toRegExpString)(pattern, null)})`);
|
|
607
553
|
return checks.length ? `.check(${checks.join(", ")})` : "";
|
|
608
554
|
}
|
|
609
555
|
/**
|
|
@@ -618,7 +564,7 @@ function applyModifiers({ value, nullable, optional, nullish, defaultValue, desc
|
|
|
618
564
|
return value;
|
|
619
565
|
})();
|
|
620
566
|
const withDefault = defaultValue !== void 0 ? `${withModifier}.default(${formatDefault(defaultValue)})` : withModifier;
|
|
621
|
-
return description ? `${withDefault}.describe(${stringify(description)})` : withDefault;
|
|
567
|
+
return description ? `${withDefault}.describe(${(0, _kubb_ast_utils.stringify)(description)})` : withDefault;
|
|
622
568
|
}
|
|
623
569
|
/**
|
|
624
570
|
* Apply nullable / optional / nullish modifiers using the functional `zod/mini` API
|
|
@@ -638,7 +584,7 @@ function strictOneOfMember$1(member, node) {
|
|
|
638
584
|
if (node.type === "object" && node.additionalProperties === void 0) return `${member}.strict()`;
|
|
639
585
|
if (node.type === "ref") {
|
|
640
586
|
if (member.startsWith("z.lazy(")) return member;
|
|
641
|
-
const schema =
|
|
587
|
+
const schema = (0, _kubb_ast_utils.syncSchemaRef)(node);
|
|
642
588
|
if (schema.type === "object" && (schema.additionalProperties === void 0 || schema.additionalProperties === false)) return `${member}.strict()`;
|
|
643
589
|
}
|
|
644
590
|
return member;
|
|
@@ -723,24 +669,24 @@ const printerZod = _kubb_core.ast.definePrinter((options) => {
|
|
|
723
669
|
},
|
|
724
670
|
ref(node) {
|
|
725
671
|
if (!node.name) return null;
|
|
726
|
-
const refName = node.ref ?
|
|
672
|
+
const refName = node.ref ? (0, _kubb_ast_utils.extractRefName)(node.ref) ?? node.name : node.name;
|
|
727
673
|
const useInputVariant = node.ref != null && this.options.direction === "input" && containsCodec(node);
|
|
728
674
|
const resolvedName = node.ref ? useInputVariant ? this.options.resolver?.resolveInputSchemaName(refName) ?? refName : this.options.resolver?.default(refName, "function") ?? refName : node.name;
|
|
729
675
|
if (node.ref && this.options.cyclicSchemas?.has(refName)) return `z.lazy(() => ${resolvedName})`;
|
|
730
676
|
return resolvedName;
|
|
731
677
|
},
|
|
732
678
|
object(node) {
|
|
733
|
-
const
|
|
734
|
-
|
|
735
|
-
const
|
|
736
|
-
const isNullable = meta.nullable;
|
|
737
|
-
const isOptional = schema.optional;
|
|
738
|
-
const isNullish = schema.nullish;
|
|
739
|
-
const hasSelfRef = this.options.cyclicSchemas != null && _kubb_core.ast.containsCircularRef(schema, { circularSchemas: this.options.cyclicSchemas });
|
|
679
|
+
const isCyclic = (schema) => this.options.cyclicSchemas != null && (0, _kubb_ast_utils.containsCircularRef)(schema, { circularSchemas: this.options.cyclicSchemas });
|
|
680
|
+
const objectBase = `z.object(${(0, _kubb_ast_utils.buildObject)((0, _kubb_ast_utils.mapSchemaProperties)(node, (schema) => {
|
|
681
|
+
const hasSelfRef = isCyclic(schema);
|
|
740
682
|
const savedCyclicSchemas = this.options.cyclicSchemas;
|
|
741
683
|
if (hasSelfRef) this.options.cyclicSchemas = void 0;
|
|
742
|
-
const baseOutput = this.transform(schema) ?? this.transform(_kubb_core.ast.createSchema({ type: "unknown" }));
|
|
684
|
+
const baseOutput = this.transform(schema) ?? this.transform(_kubb_core.ast.factory.createSchema({ type: "unknown" }));
|
|
743
685
|
if (hasSelfRef) this.options.cyclicSchemas = savedCyclicSchemas;
|
|
686
|
+
return baseOutput;
|
|
687
|
+
}).map(({ name: propName, property, output: baseOutput }) => {
|
|
688
|
+
const { schema } = property;
|
|
689
|
+
const meta = (0, _kubb_ast_utils.syncSchemaRef)(schema);
|
|
744
690
|
const wrappedOutput = this.options.wrapOutput ? this.options.wrapOutput({
|
|
745
691
|
output: baseOutput,
|
|
746
692
|
schema
|
|
@@ -748,42 +694,41 @@ const printerZod = _kubb_core.ast.definePrinter((options) => {
|
|
|
748
694
|
const descriptionToApply = schema.type !== "ref" && meta.type === "ref" ? void 0 : meta.description;
|
|
749
695
|
const value = applyModifiers({
|
|
750
696
|
value: wrappedOutput,
|
|
751
|
-
nullable:
|
|
752
|
-
optional:
|
|
753
|
-
nullish:
|
|
697
|
+
nullable: meta.nullable,
|
|
698
|
+
optional: schema.optional || property.required === false,
|
|
699
|
+
nullish: schema.nullish,
|
|
754
700
|
defaultValue: meta.default,
|
|
755
701
|
description: descriptionToApply
|
|
756
702
|
});
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
703
|
+
return isCyclic(schema) ? (0, _kubb_ast_utils.lazyGetter)({
|
|
704
|
+
name: propName,
|
|
705
|
+
body: value
|
|
706
|
+
}) : `${(0, _kubb_ast_utils.objectKey)(propName)}: ${value}`;
|
|
707
|
+
}))})`;
|
|
760
708
|
return (() => {
|
|
761
709
|
if (node.additionalProperties && node.additionalProperties !== true) {
|
|
762
710
|
const catchallType = this.transform(node.additionalProperties);
|
|
763
711
|
return catchallType ? `${objectBase}.catchall(${catchallType})` : objectBase;
|
|
764
712
|
}
|
|
765
|
-
if (node.additionalProperties === true) return `${objectBase}.catchall(${this.transform(_kubb_core.ast.createSchema({ type: "unknown" }))})`;
|
|
713
|
+
if (node.additionalProperties === true) return `${objectBase}.catchall(${this.transform(_kubb_core.ast.factory.createSchema({ type: "unknown" }))})`;
|
|
766
714
|
if (node.additionalProperties === false) return `${objectBase}.strict()`;
|
|
767
715
|
return objectBase;
|
|
768
716
|
})();
|
|
769
717
|
},
|
|
770
718
|
array(node) {
|
|
771
|
-
const base = `z.array(${(
|
|
719
|
+
const base = `z.array(${(0, _kubb_ast_utils.mapSchemaItems)(node, (item) => this.transform(item)).map(({ output }) => output).filter(Boolean).join(", ") || this.transform(_kubb_core.ast.factory.createSchema({ type: "unknown" }))})${lengthConstraints(node)}`;
|
|
772
720
|
return node.unique ? `${base}.refine(items => new Set(items).size === items.length, { message: "Array entries must be unique" })` : base;
|
|
773
721
|
},
|
|
774
722
|
tuple(node) {
|
|
775
|
-
return `z.tuple(
|
|
723
|
+
return `z.tuple(${(0, _kubb_ast_utils.buildList)((0, _kubb_ast_utils.mapSchemaItems)(node, (item) => this.transform(item)).map(({ output }) => output).filter(Boolean))})`;
|
|
776
724
|
},
|
|
777
725
|
union(node) {
|
|
778
726
|
const nodeMembers = node.members ?? [];
|
|
779
|
-
const members =
|
|
780
|
-
const member = this.transform(memberNode);
|
|
781
|
-
return member && node.strategy === "one" ? strictOneOfMember$1(member, memberNode) : member;
|
|
782
|
-
}).filter(Boolean);
|
|
727
|
+
const members = (0, _kubb_ast_utils.mapSchemaMembers)(node, (memberNode) => this.transform(memberNode)).map(({ schema, output }) => output && node.strategy === "one" ? strictOneOfMember$1(output, schema) : output).filter(Boolean);
|
|
783
728
|
if (members.length === 0) return "";
|
|
784
729
|
if (members.length === 1) return members[0];
|
|
785
|
-
if (node.discriminatorPropertyName && !nodeMembers.some((m) => m.type === "intersection")) return `z.discriminatedUnion(${stringify(node.discriminatorPropertyName)},
|
|
786
|
-
return `z.union(
|
|
730
|
+
if (node.discriminatorPropertyName && !nodeMembers.some((m) => m.type === "intersection")) return `z.discriminatedUnion(${(0, _kubb_ast_utils.stringify)(node.discriminatorPropertyName)}, ${(0, _kubb_ast_utils.buildList)(members)})`;
|
|
731
|
+
return `z.union(${(0, _kubb_ast_utils.buildList)(members)})`;
|
|
787
732
|
},
|
|
788
733
|
intersection(node) {
|
|
789
734
|
const members = node.members ?? [];
|
|
@@ -805,7 +750,7 @@ const printerZod = _kubb_core.ast.definePrinter((options) => {
|
|
|
805
750
|
const { keysToOmit } = this.options;
|
|
806
751
|
const transformed = this.transform(node);
|
|
807
752
|
if (!transformed) return null;
|
|
808
|
-
const meta =
|
|
753
|
+
const meta = (0, _kubb_ast_utils.syncSchemaRef)(node);
|
|
809
754
|
return applyModifiers({
|
|
810
755
|
value: (() => {
|
|
811
756
|
if (!keysToOmit?.length || meta.primitive !== "object" || meta.type === "union" && meta.discriminatorPropertyName) return transformed;
|
|
@@ -902,54 +847,53 @@ const printerZodMini = _kubb_core.ast.definePrinter((options) => {
|
|
|
902
847
|
},
|
|
903
848
|
ref(node) {
|
|
904
849
|
if (!node.name) return null;
|
|
905
|
-
const refName = node.ref ?
|
|
850
|
+
const refName = node.ref ? (0, _kubb_ast_utils.extractRefName)(node.ref) ?? node.name : node.name;
|
|
906
851
|
const resolvedName = node.ref ? this.options.resolver?.default(refName, "function") ?? refName : node.name;
|
|
907
852
|
if (node.ref && this.options.cyclicSchemas?.has(refName)) return `z.lazy(() => ${resolvedName})`;
|
|
908
853
|
return resolvedName;
|
|
909
854
|
},
|
|
910
855
|
object(node) {
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
const
|
|
914
|
-
const isNullable = meta.nullable;
|
|
915
|
-
const isOptional = schema.optional;
|
|
916
|
-
const isNullish = schema.nullish;
|
|
917
|
-
const hasSelfRef = this.options.cyclicSchemas != null && _kubb_core.ast.containsCircularRef(schema, { circularSchemas: this.options.cyclicSchemas });
|
|
856
|
+
const isCyclic = (schema) => this.options.cyclicSchemas != null && (0, _kubb_ast_utils.containsCircularRef)(schema, { circularSchemas: this.options.cyclicSchemas });
|
|
857
|
+
return `z.object(${(0, _kubb_ast_utils.buildObject)((0, _kubb_ast_utils.mapSchemaProperties)(node, (schema) => {
|
|
858
|
+
const hasSelfRef = isCyclic(schema);
|
|
918
859
|
const savedCyclicSchemas = this.options.cyclicSchemas;
|
|
919
860
|
if (hasSelfRef) this.options.cyclicSchemas = void 0;
|
|
920
|
-
const baseOutput = this.transform(schema) ?? this.transform(_kubb_core.ast.createSchema({ type: "unknown" }));
|
|
861
|
+
const baseOutput = this.transform(schema) ?? this.transform(_kubb_core.ast.factory.createSchema({ type: "unknown" }));
|
|
921
862
|
if (hasSelfRef) this.options.cyclicSchemas = savedCyclicSchemas;
|
|
863
|
+
return baseOutput;
|
|
864
|
+
}).map(({ name: propName, property, output: baseOutput }) => {
|
|
865
|
+
const { schema } = property;
|
|
866
|
+
const meta = (0, _kubb_ast_utils.syncSchemaRef)(schema);
|
|
922
867
|
const value = applyMiniModifiers({
|
|
923
868
|
value: this.options.wrapOutput ? this.options.wrapOutput({
|
|
924
869
|
output: baseOutput,
|
|
925
870
|
schema
|
|
926
871
|
}) || baseOutput : baseOutput,
|
|
927
|
-
nullable:
|
|
928
|
-
optional:
|
|
929
|
-
nullish:
|
|
872
|
+
nullable: meta.nullable,
|
|
873
|
+
optional: schema.optional || property.required === false,
|
|
874
|
+
nullish: schema.nullish,
|
|
930
875
|
defaultValue: meta.default
|
|
931
876
|
});
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
877
|
+
return isCyclic(schema) ? (0, _kubb_ast_utils.lazyGetter)({
|
|
878
|
+
name: propName,
|
|
879
|
+
body: value
|
|
880
|
+
}) : `${(0, _kubb_ast_utils.objectKey)(propName)}: ${value}`;
|
|
881
|
+
}))})`;
|
|
935
882
|
},
|
|
936
883
|
array(node) {
|
|
937
|
-
const base = `z.array(${(
|
|
884
|
+
const base = `z.array(${(0, _kubb_ast_utils.mapSchemaItems)(node, (item) => this.transform(item)).map(({ output }) => output).filter(Boolean).join(", ") || this.transform(_kubb_core.ast.factory.createSchema({ type: "unknown" }))})${lengthChecksMini(node)}`;
|
|
938
885
|
return node.unique ? `${base}.refine(items => new Set(items).size === items.length, { message: "Array entries must be unique" })` : base;
|
|
939
886
|
},
|
|
940
887
|
tuple(node) {
|
|
941
|
-
return `z.tuple(
|
|
888
|
+
return `z.tuple(${(0, _kubb_ast_utils.buildList)((0, _kubb_ast_utils.mapSchemaItems)(node, (item) => this.transform(item)).map(({ output }) => output).filter(Boolean))})`;
|
|
942
889
|
},
|
|
943
890
|
union(node) {
|
|
944
891
|
const nodeMembers = node.members ?? [];
|
|
945
|
-
const members =
|
|
946
|
-
const member = this.transform(memberNode);
|
|
947
|
-
return member && node.strategy === "one" ? strictOneOfMember(member, memberNode) : member;
|
|
948
|
-
}).filter(Boolean);
|
|
892
|
+
const members = (0, _kubb_ast_utils.mapSchemaMembers)(node, (memberNode) => this.transform(memberNode)).map(({ schema, output }) => output && node.strategy === "one" ? strictOneOfMember(output, schema) : output).filter(Boolean);
|
|
949
893
|
if (members.length === 0) return "";
|
|
950
894
|
if (members.length === 1) return members[0];
|
|
951
|
-
if (node.discriminatorPropertyName && !nodeMembers.some((m) => m.type === "intersection")) return `z.discriminatedUnion(${stringify(node.discriminatorPropertyName)},
|
|
952
|
-
return `z.union(
|
|
895
|
+
if (node.discriminatorPropertyName && !nodeMembers.some((m) => m.type === "intersection")) return `z.discriminatedUnion(${(0, _kubb_ast_utils.stringify)(node.discriminatorPropertyName)}, ${(0, _kubb_ast_utils.buildList)(members)})`;
|
|
896
|
+
return `z.union(${(0, _kubb_ast_utils.buildList)(members)})`;
|
|
953
897
|
},
|
|
954
898
|
intersection(node) {
|
|
955
899
|
const members = node.members ?? [];
|
|
@@ -971,7 +915,7 @@ const printerZodMini = _kubb_core.ast.definePrinter((options) => {
|
|
|
971
915
|
const { keysToOmit } = this.options;
|
|
972
916
|
const transformed = this.transform(node);
|
|
973
917
|
if (!transformed) return null;
|
|
974
|
-
const meta =
|
|
918
|
+
const meta = (0, _kubb_ast_utils.syncSchemaRef)(node);
|
|
975
919
|
return applyMiniModifiers({
|
|
976
920
|
value: (() => {
|
|
977
921
|
if (!keysToOmit?.length || meta.primitive !== "object" || meta.type === "union" && meta.discriminatorPropertyName) return transformed;
|
|
@@ -1047,17 +991,16 @@ function getMiniPrinter(resolver, params) {
|
|
|
1047
991
|
*/
|
|
1048
992
|
const zodGenerator = (0, _kubb_core.defineGenerator)({
|
|
1049
993
|
name: "zod",
|
|
1050
|
-
renderer: _kubb_renderer_jsx.
|
|
994
|
+
renderer: _kubb_renderer_jsx.jsxRenderer,
|
|
1051
995
|
schema(node, ctx) {
|
|
1052
996
|
const { adapter, config, resolver, root } = ctx;
|
|
1053
997
|
const { output, coercion, guidType, mini, wrapOutput, inferred, importPath, group, printer } = ctx.options;
|
|
1054
998
|
const dateType = adapter.options.dateType;
|
|
1055
999
|
if (!node.name) return;
|
|
1056
|
-
const mode = ctx.getMode(output);
|
|
1057
1000
|
const isZodImport = ZOD_NAMESPACE_IMPORTS.has(importPath);
|
|
1058
1001
|
const cyclicSchemas = new Set(ctx.meta.circularNames);
|
|
1059
1002
|
const hasCodec = !mini && containsCodec(node);
|
|
1060
|
-
const codecRefNames = new Set(hasCodec ?
|
|
1003
|
+
const codecRefNames = new Set(hasCodec ? collectCodecRefNames(node) : []);
|
|
1061
1004
|
const importEntries = adapter.getImports(node, (schemaName) => ({
|
|
1062
1005
|
name: resolver.resolveSchemaName(schemaName),
|
|
1063
1006
|
path: resolver.resolveFile({
|
|
@@ -1070,7 +1013,7 @@ const zodGenerator = (0, _kubb_core.defineGenerator)({
|
|
|
1070
1013
|
}).path
|
|
1071
1014
|
}));
|
|
1072
1015
|
const inputImportEntries = hasCodec ? [...codecRefNames].map((schemaName) => ({
|
|
1073
|
-
name: resolver.resolveInputSchemaName(schemaName),
|
|
1016
|
+
name: [resolver.resolveInputSchemaName(schemaName)],
|
|
1074
1017
|
path: resolver.resolveFile({
|
|
1075
1018
|
name: schemaName,
|
|
1076
1019
|
extname: ".ts"
|
|
@@ -1139,7 +1082,7 @@ const zodGenerator = (0, _kubb_core.defineGenerator)({
|
|
|
1139
1082
|
path: importPath,
|
|
1140
1083
|
isNameSpace: isZodImport
|
|
1141
1084
|
}),
|
|
1142
|
-
|
|
1085
|
+
imports.map((imp) => /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
|
|
1143
1086
|
root: meta.file.path,
|
|
1144
1087
|
path: imp.path,
|
|
1145
1088
|
name: imp.name
|
|
@@ -1168,9 +1111,8 @@ const zodGenerator = (0, _kubb_core.defineGenerator)({
|
|
|
1168
1111
|
const { adapter, config, resolver, root } = ctx;
|
|
1169
1112
|
const { output, coercion, guidType, mini, wrapOutput, inferred, importPath, group, paramsCasing, printer } = ctx.options;
|
|
1170
1113
|
const dateType = adapter.options.dateType;
|
|
1171
|
-
const mode = ctx.getMode(output);
|
|
1172
1114
|
const isZodImport = ZOD_NAMESPACE_IMPORTS.has(importPath);
|
|
1173
|
-
const params =
|
|
1115
|
+
const params = (0, _kubb_ast_utils.caseParams)(node.parameters, paramsCasing);
|
|
1174
1116
|
const meta = { file: resolver.resolveFile({
|
|
1175
1117
|
name: node.operationId,
|
|
1176
1118
|
extname: ".ts",
|
|
@@ -1185,7 +1127,7 @@ const zodGenerator = (0, _kubb_core.defineGenerator)({
|
|
|
1185
1127
|
function renderSchemaEntry({ schema, name, keysToOmit, direction = "output" }) {
|
|
1186
1128
|
if (!schema) return null;
|
|
1187
1129
|
const inferTypeName = inferred ? resolver.resolveTypeName(name) : null;
|
|
1188
|
-
const codecRefNames = direction === "input" && !mini ? new Set(
|
|
1130
|
+
const codecRefNames = direction === "input" && !mini ? new Set(collectCodecRefNames(schema)) : null;
|
|
1189
1131
|
const imports = adapter.getImports(schema, (schemaName) => ({
|
|
1190
1132
|
name: codecRefNames?.has(schemaName) ? resolver.resolveInputSchemaName(schemaName) : resolver.resolveSchemaName(schemaName),
|
|
1191
1133
|
path: resolver.resolveFile({
|
|
@@ -1227,7 +1169,7 @@ const zodGenerator = (0, _kubb_core.defineGenerator)({
|
|
|
1227
1169
|
cyclicSchemas,
|
|
1228
1170
|
nodes: printer?.nodes
|
|
1229
1171
|
})[direction];
|
|
1230
|
-
return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: [
|
|
1172
|
+
return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: [imports.map((imp) => /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
|
|
1231
1173
|
root: meta.file.path,
|
|
1232
1174
|
path: imp.path,
|
|
1233
1175
|
name: imp.name
|
|
@@ -1244,9 +1186,9 @@ const zodGenerator = (0, _kubb_core.defineGenerator)({
|
|
|
1244
1186
|
}
|
|
1245
1187
|
function buildContentTypeVariants(entries, baseName, decorate, direction) {
|
|
1246
1188
|
const variants = resolveContentTypeVariants(entries, baseName);
|
|
1247
|
-
const unionSchema = _kubb_core.ast.createSchema({
|
|
1189
|
+
const unionSchema = _kubb_core.ast.factory.createSchema({
|
|
1248
1190
|
type: "union",
|
|
1249
|
-
members: variants.map((variant) => _kubb_core.ast.createSchema({
|
|
1191
|
+
members: variants.map((variant) => _kubb_core.ast.factory.createSchema({
|
|
1250
1192
|
type: "ref",
|
|
1251
1193
|
name: variant.name
|
|
1252
1194
|
}))
|
|
@@ -1284,12 +1226,12 @@ const zodGenerator = (0, _kubb_core.defineGenerator)({
|
|
|
1284
1226
|
name: resolver.resolveSchemaName(schemaName),
|
|
1285
1227
|
path: ""
|
|
1286
1228
|
})).flatMap((imp) => Array.isArray(imp.name) ? imp.name : [imp.name]) : []))).has(responseUnionName)) return null;
|
|
1287
|
-
const members = responsesWithSchema.map((res) => _kubb_core.ast.createSchema({
|
|
1229
|
+
const members = responsesWithSchema.map((res) => _kubb_core.ast.factory.createSchema({
|
|
1288
1230
|
type: "ref",
|
|
1289
1231
|
name: resolver.resolveResponseStatusName(node, res.statusCode)
|
|
1290
1232
|
}));
|
|
1291
1233
|
return renderSchemaEntry({
|
|
1292
|
-
schema: members.length === 1 ? members[0] : _kubb_core.ast.createSchema({
|
|
1234
|
+
schema: members.length === 1 ? members[0] : _kubb_core.ast.factory.createSchema({
|
|
1293
1235
|
type: "union",
|
|
1294
1236
|
members
|
|
1295
1237
|
}),
|
|
@@ -1367,7 +1309,7 @@ const zodGenerator = (0, _kubb_core.defineGenerator)({
|
|
|
1367
1309
|
return {
|
|
1368
1310
|
node,
|
|
1369
1311
|
data: buildSchemaNames(node, {
|
|
1370
|
-
params:
|
|
1312
|
+
params: (0, _kubb_ast_utils.caseParams)(node.parameters, paramsCasing),
|
|
1371
1313
|
resolver
|
|
1372
1314
|
})
|
|
1373
1315
|
};
|
|
@@ -1435,14 +1377,16 @@ const zodGenerator = (0, _kubb_core.defineGenerator)({
|
|
|
1435
1377
|
/**
|
|
1436
1378
|
* Default resolver used by `@kubb/plugin-zod`. Decides the names and file
|
|
1437
1379
|
* paths for every generated Zod schema. Schemas use camelCase with a
|
|
1438
|
-
* `Schema` suffix (`listPetsSchema`); their inferred types use PascalCase
|
|
1380
|
+
* `Schema` suffix (`listPetsSchema`); their inferred types use PascalCase
|
|
1381
|
+
* with a `SchemaType` suffix (`PetSchemaType`), so the value and the type
|
|
1382
|
+
* never share an identifier even when the schema name is all-uppercase.
|
|
1439
1383
|
*
|
|
1440
1384
|
* @example Resolve schema and type names
|
|
1441
1385
|
* ```ts
|
|
1442
1386
|
* import { resolverZod } from '@kubb/plugin-zod'
|
|
1443
1387
|
*
|
|
1444
1388
|
* resolverZod.default('list pets', 'function') // 'listPetsSchema'
|
|
1445
|
-
* resolverZod.resolveSchemaTypeName('pet') // '
|
|
1389
|
+
* resolverZod.resolveSchemaTypeName('pet') // 'PetSchemaType'
|
|
1446
1390
|
* ```
|
|
1447
1391
|
*/
|
|
1448
1392
|
const resolverZod = (0, _kubb_core.defineResolver)(() => {
|
|
@@ -1450,17 +1394,14 @@ const resolverZod = (0, _kubb_core.defineResolver)(() => {
|
|
|
1450
1394
|
name: "default",
|
|
1451
1395
|
pluginName: "plugin-zod",
|
|
1452
1396
|
default(name, type) {
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
suffix: type ? "schema" : void 0
|
|
1456
|
-
});
|
|
1457
|
-
return type === "file" ? resolved : ensureValidVarName(resolved);
|
|
1397
|
+
if (type === "file") return toFilePath(name, (part) => camelCase(part, { suffix: "schema" }));
|
|
1398
|
+
return ensureValidVarName(camelCase(name, { suffix: type ? "schema" : void 0 }));
|
|
1458
1399
|
},
|
|
1459
1400
|
resolveSchemaName(name) {
|
|
1460
1401
|
return ensureValidVarName(camelCase(name, { suffix: "schema" }));
|
|
1461
1402
|
},
|
|
1462
1403
|
resolveSchemaTypeName(name) {
|
|
1463
|
-
return ensureValidVarName(pascalCase(name, { suffix: "schema" }));
|
|
1404
|
+
return ensureValidVarName(pascalCase(name, { suffix: "schema type" }));
|
|
1464
1405
|
},
|
|
1465
1406
|
resolveInputSchemaName(name) {
|
|
1466
1407
|
return this.resolveSchemaName(`${name} input`);
|
|
@@ -1469,7 +1410,7 @@ const resolverZod = (0, _kubb_core.defineResolver)(() => {
|
|
|
1469
1410
|
return this.resolveSchemaTypeName(`${name} input`);
|
|
1470
1411
|
},
|
|
1471
1412
|
resolveTypeName(name) {
|
|
1472
|
-
return ensureValidVarName(pascalCase(name));
|
|
1413
|
+
return ensureValidVarName(pascalCase(name, { suffix: "type" }));
|
|
1473
1414
|
},
|
|
1474
1415
|
resolvePathName(name, type) {
|
|
1475
1416
|
return this.default(name, type);
|
|
@@ -1535,9 +1476,9 @@ const pluginZodName = "plugin-zod";
|
|
|
1535
1476
|
const pluginZod = (0, _kubb_core.definePlugin)((options) => {
|
|
1536
1477
|
const { output = {
|
|
1537
1478
|
path: "zod",
|
|
1538
|
-
|
|
1539
|
-
}, group, exclude = [], include, override = [], typed = false, operations = false, mini = false, guidType = "uuid", importPath = mini ? "zod/mini" : "zod", coercion = false, inferred = false, wrapOutput = void 0, paramsCasing, printer, resolver: userResolver,
|
|
1540
|
-
const groupConfig = createGroupConfig(group
|
|
1479
|
+
barrel: { type: "named" }
|
|
1480
|
+
}, group, exclude = [], include, override = [], typed = false, operations = false, mini = false, guidType = "uuid", importPath = mini ? "zod/mini" : "zod", coercion = false, inferred = false, wrapOutput = void 0, paramsCasing, printer, resolver: userResolver, macros: userMacros, generators: userGenerators = [] } = options;
|
|
1481
|
+
const groupConfig = createGroupConfig(group);
|
|
1541
1482
|
return {
|
|
1542
1483
|
name: pluginZodName,
|
|
1543
1484
|
options,
|
|
@@ -1563,7 +1504,7 @@ const pluginZod = (0, _kubb_core.definePlugin)((options) => {
|
|
|
1563
1504
|
...resolverZod,
|
|
1564
1505
|
...userResolver
|
|
1565
1506
|
} : resolverZod);
|
|
1566
|
-
if (
|
|
1507
|
+
if (userMacros?.length) ctx.setMacros(userMacros);
|
|
1567
1508
|
ctx.addGenerator(zodGenerator);
|
|
1568
1509
|
for (const gen of userGenerators) ctx.addGenerator(gen);
|
|
1569
1510
|
} }
|