@kubb/plugin-zod 5.0.0-beta.42 → 5.0.0-beta.56
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 +75 -139
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +16 -18
- package/dist/index.js +69 -133
- package/dist/index.js.map +1 -1
- package/package.json +9 -16
- package/src/components/Operations.tsx +1 -1
- package/src/generators/zodGenerator.tsx +12 -11
- package/src/plugin.ts +2 -2
- package/src/printers/printerZod.ts +45 -47
- package/src/printers/printerZodMini.ts +39 -41
- package/src/resolvers/resolverZod.ts +9 -7
- package/src/types.ts +12 -16
- package/src/utils.ts +2 -2
- package/extension.yaml +0 -970
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,7 +436,7 @@ 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);
|
|
@@ -548,7 +487,7 @@ function buildSchemaNames(node, { params, resolver }) {
|
|
|
548
487
|
* Objects become `{}`, primitives become their string representation, strings are quoted.
|
|
549
488
|
*/
|
|
550
489
|
function formatDefault(value) {
|
|
551
|
-
if (typeof value === "string") return stringify(value);
|
|
490
|
+
if (typeof value === "string") return (0, _kubb_ast_utils.stringify)(value);
|
|
552
491
|
if (typeof value === "object" && value !== null) return "{}";
|
|
553
492
|
return String(value ?? "");
|
|
554
493
|
}
|
|
@@ -557,7 +496,7 @@ function formatDefault(value) {
|
|
|
557
496
|
* Strings are quoted; numbers and booleans are emitted raw.
|
|
558
497
|
*/
|
|
559
498
|
function formatLiteral(v) {
|
|
560
|
-
if (typeof v === "string") return stringify(v);
|
|
499
|
+
if (typeof v === "string") return (0, _kubb_ast_utils.stringify)(v);
|
|
561
500
|
return String(v);
|
|
562
501
|
}
|
|
563
502
|
/**
|
|
@@ -581,7 +520,7 @@ function lengthConstraints({ min, max, pattern }) {
|
|
|
581
520
|
return [
|
|
582
521
|
min !== void 0 ? `.min(${min})` : "",
|
|
583
522
|
max !== void 0 ? `.max(${max})` : "",
|
|
584
|
-
pattern !== void 0 ? `.regex(${toRegExpString(pattern, null)})` : ""
|
|
523
|
+
pattern !== void 0 ? `.regex(${(0, _kubb_ast_utils.toRegExpString)(pattern, null)})` : ""
|
|
585
524
|
].join("");
|
|
586
525
|
}
|
|
587
526
|
/**
|
|
@@ -603,7 +542,7 @@ function lengthChecksMini({ min, max, pattern }) {
|
|
|
603
542
|
const checks = [];
|
|
604
543
|
if (min !== void 0) checks.push(`z.minLength(${min})`);
|
|
605
544
|
if (max !== void 0) checks.push(`z.maxLength(${max})`);
|
|
606
|
-
if (pattern !== void 0) checks.push(`z.regex(${toRegExpString(pattern, null)})`);
|
|
545
|
+
if (pattern !== void 0) checks.push(`z.regex(${(0, _kubb_ast_utils.toRegExpString)(pattern, null)})`);
|
|
607
546
|
return checks.length ? `.check(${checks.join(", ")})` : "";
|
|
608
547
|
}
|
|
609
548
|
/**
|
|
@@ -618,7 +557,7 @@ function applyModifiers({ value, nullable, optional, nullish, defaultValue, desc
|
|
|
618
557
|
return value;
|
|
619
558
|
})();
|
|
620
559
|
const withDefault = defaultValue !== void 0 ? `${withModifier}.default(${formatDefault(defaultValue)})` : withModifier;
|
|
621
|
-
return description ? `${withDefault}.describe(${stringify(description)})` : withDefault;
|
|
560
|
+
return description ? `${withDefault}.describe(${(0, _kubb_ast_utils.stringify)(description)})` : withDefault;
|
|
622
561
|
}
|
|
623
562
|
/**
|
|
624
563
|
* Apply nullable / optional / nullish modifiers using the functional `zod/mini` API
|
|
@@ -723,14 +662,14 @@ const printerZod = _kubb_core.ast.definePrinter((options) => {
|
|
|
723
662
|
},
|
|
724
663
|
ref(node) {
|
|
725
664
|
if (!node.name) return null;
|
|
726
|
-
const refName = node.ref ?
|
|
665
|
+
const refName = node.ref ? (0, _kubb_ast_utils.extractRefName)(node.ref) ?? node.name : node.name;
|
|
727
666
|
const useInputVariant = node.ref != null && this.options.direction === "input" && containsCodec(node);
|
|
728
667
|
const resolvedName = node.ref ? useInputVariant ? this.options.resolver?.resolveInputSchemaName(refName) ?? refName : this.options.resolver?.default(refName, "function") ?? refName : node.name;
|
|
729
668
|
if (node.ref && this.options.cyclicSchemas?.has(refName)) return `z.lazy(() => ${resolvedName})`;
|
|
730
669
|
return resolvedName;
|
|
731
670
|
},
|
|
732
671
|
object(node) {
|
|
733
|
-
const objectBase = `z.object(
|
|
672
|
+
const objectBase = `z.object(${(0, _kubb_ast_utils.buildObject)(node.properties.map((prop) => {
|
|
734
673
|
const { name: propName, schema } = prop;
|
|
735
674
|
const meta = _kubb_core.ast.syncSchemaRef(schema);
|
|
736
675
|
const isNullable = meta.nullable;
|
|
@@ -754,9 +693,9 @@ const printerZod = _kubb_core.ast.definePrinter((options) => {
|
|
|
754
693
|
defaultValue: meta.default,
|
|
755
694
|
description: descriptionToApply
|
|
756
695
|
});
|
|
757
|
-
if (hasSelfRef) return `get
|
|
758
|
-
return
|
|
759
|
-
})
|
|
696
|
+
if (hasSelfRef) return `get ${(0, _kubb_ast_utils.objectKey)(propName)}() { return ${value} }`;
|
|
697
|
+
return `${(0, _kubb_ast_utils.objectKey)(propName)}: ${value}`;
|
|
698
|
+
}))})`;
|
|
760
699
|
return (() => {
|
|
761
700
|
if (node.additionalProperties && node.additionalProperties !== true) {
|
|
762
701
|
const catchallType = this.transform(node.additionalProperties);
|
|
@@ -772,7 +711,7 @@ const printerZod = _kubb_core.ast.definePrinter((options) => {
|
|
|
772
711
|
return node.unique ? `${base}.refine(items => new Set(items).size === items.length, { message: "Array entries must be unique" })` : base;
|
|
773
712
|
},
|
|
774
713
|
tuple(node) {
|
|
775
|
-
return `z.tuple(
|
|
714
|
+
return `z.tuple(${(0, _kubb_ast_utils.buildList)((node.items ?? []).map((item) => this.transform(item)).filter(Boolean))})`;
|
|
776
715
|
},
|
|
777
716
|
union(node) {
|
|
778
717
|
const nodeMembers = node.members ?? [];
|
|
@@ -782,8 +721,8 @@ const printerZod = _kubb_core.ast.definePrinter((options) => {
|
|
|
782
721
|
}).filter(Boolean);
|
|
783
722
|
if (members.length === 0) return "";
|
|
784
723
|
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(
|
|
724
|
+
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)})`;
|
|
725
|
+
return `z.union(${(0, _kubb_ast_utils.buildList)(members)})`;
|
|
787
726
|
},
|
|
788
727
|
intersection(node) {
|
|
789
728
|
const members = node.members ?? [];
|
|
@@ -902,13 +841,13 @@ const printerZodMini = _kubb_core.ast.definePrinter((options) => {
|
|
|
902
841
|
},
|
|
903
842
|
ref(node) {
|
|
904
843
|
if (!node.name) return null;
|
|
905
|
-
const refName = node.ref ?
|
|
844
|
+
const refName = node.ref ? (0, _kubb_ast_utils.extractRefName)(node.ref) ?? node.name : node.name;
|
|
906
845
|
const resolvedName = node.ref ? this.options.resolver?.default(refName, "function") ?? refName : node.name;
|
|
907
846
|
if (node.ref && this.options.cyclicSchemas?.has(refName)) return `z.lazy(() => ${resolvedName})`;
|
|
908
847
|
return resolvedName;
|
|
909
848
|
},
|
|
910
849
|
object(node) {
|
|
911
|
-
return `z.object(
|
|
850
|
+
return `z.object(${(0, _kubb_ast_utils.buildObject)(node.properties.map((prop) => {
|
|
912
851
|
const { name: propName, schema } = prop;
|
|
913
852
|
const meta = _kubb_core.ast.syncSchemaRef(schema);
|
|
914
853
|
const isNullable = meta.nullable;
|
|
@@ -929,16 +868,16 @@ const printerZodMini = _kubb_core.ast.definePrinter((options) => {
|
|
|
929
868
|
nullish: isNullish,
|
|
930
869
|
defaultValue: meta.default
|
|
931
870
|
});
|
|
932
|
-
if (hasSelfRef) return `get
|
|
933
|
-
return
|
|
934
|
-
})
|
|
871
|
+
if (hasSelfRef) return `get ${(0, _kubb_ast_utils.objectKey)(propName)}() { return ${value} }`;
|
|
872
|
+
return `${(0, _kubb_ast_utils.objectKey)(propName)}: ${value}`;
|
|
873
|
+
}))})`;
|
|
935
874
|
},
|
|
936
875
|
array(node) {
|
|
937
876
|
const base = `z.array(${(node.items ?? []).map((item) => this.transform(item)).filter(Boolean).join(", ") || this.transform(_kubb_core.ast.createSchema({ type: "unknown" }))})${lengthChecksMini(node)}`;
|
|
938
877
|
return node.unique ? `${base}.refine(items => new Set(items).size === items.length, { message: "Array entries must be unique" })` : base;
|
|
939
878
|
},
|
|
940
879
|
tuple(node) {
|
|
941
|
-
return `z.tuple(
|
|
880
|
+
return `z.tuple(${(0, _kubb_ast_utils.buildList)((node.items ?? []).map((item) => this.transform(item)).filter(Boolean))})`;
|
|
942
881
|
},
|
|
943
882
|
union(node) {
|
|
944
883
|
const nodeMembers = node.members ?? [];
|
|
@@ -948,8 +887,8 @@ const printerZodMini = _kubb_core.ast.definePrinter((options) => {
|
|
|
948
887
|
}).filter(Boolean);
|
|
949
888
|
if (members.length === 0) return "";
|
|
950
889
|
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(
|
|
890
|
+
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)})`;
|
|
891
|
+
return `z.union(${(0, _kubb_ast_utils.buildList)(members)})`;
|
|
953
892
|
},
|
|
954
893
|
intersection(node) {
|
|
955
894
|
const members = node.members ?? [];
|
|
@@ -1047,17 +986,16 @@ function getMiniPrinter(resolver, params) {
|
|
|
1047
986
|
*/
|
|
1048
987
|
const zodGenerator = (0, _kubb_core.defineGenerator)({
|
|
1049
988
|
name: "zod",
|
|
1050
|
-
renderer: _kubb_renderer_jsx.
|
|
989
|
+
renderer: _kubb_renderer_jsx.jsxRenderer,
|
|
1051
990
|
schema(node, ctx) {
|
|
1052
991
|
const { adapter, config, resolver, root } = ctx;
|
|
1053
992
|
const { output, coercion, guidType, mini, wrapOutput, inferred, importPath, group, printer } = ctx.options;
|
|
1054
993
|
const dateType = adapter.options.dateType;
|
|
1055
994
|
if (!node.name) return;
|
|
1056
|
-
const mode = ctx.getMode(output);
|
|
1057
995
|
const isZodImport = ZOD_NAMESPACE_IMPORTS.has(importPath);
|
|
1058
996
|
const cyclicSchemas = new Set(ctx.meta.circularNames);
|
|
1059
997
|
const hasCodec = !mini && containsCodec(node);
|
|
1060
|
-
const codecRefNames = new Set(hasCodec ? _kubb_core.ast.collect(node, { schema: (n) => n.type === "ref" && n.ref && containsCodec(n) ?
|
|
998
|
+
const codecRefNames = new Set(hasCodec ? _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 }) : []);
|
|
1061
999
|
const importEntries = adapter.getImports(node, (schemaName) => ({
|
|
1062
1000
|
name: resolver.resolveSchemaName(schemaName),
|
|
1063
1001
|
path: resolver.resolveFile({
|
|
@@ -1070,7 +1008,7 @@ const zodGenerator = (0, _kubb_core.defineGenerator)({
|
|
|
1070
1008
|
}).path
|
|
1071
1009
|
}));
|
|
1072
1010
|
const inputImportEntries = hasCodec ? [...codecRefNames].map((schemaName) => ({
|
|
1073
|
-
name: resolver.resolveInputSchemaName(schemaName),
|
|
1011
|
+
name: [resolver.resolveInputSchemaName(schemaName)],
|
|
1074
1012
|
path: resolver.resolveFile({
|
|
1075
1013
|
name: schemaName,
|
|
1076
1014
|
extname: ".ts"
|
|
@@ -1139,7 +1077,7 @@ const zodGenerator = (0, _kubb_core.defineGenerator)({
|
|
|
1139
1077
|
path: importPath,
|
|
1140
1078
|
isNameSpace: isZodImport
|
|
1141
1079
|
}),
|
|
1142
|
-
|
|
1080
|
+
imports.map((imp) => /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
|
|
1143
1081
|
root: meta.file.path,
|
|
1144
1082
|
path: imp.path,
|
|
1145
1083
|
name: imp.name
|
|
@@ -1168,7 +1106,6 @@ const zodGenerator = (0, _kubb_core.defineGenerator)({
|
|
|
1168
1106
|
const { adapter, config, resolver, root } = ctx;
|
|
1169
1107
|
const { output, coercion, guidType, mini, wrapOutput, inferred, importPath, group, paramsCasing, printer } = ctx.options;
|
|
1170
1108
|
const dateType = adapter.options.dateType;
|
|
1171
|
-
const mode = ctx.getMode(output);
|
|
1172
1109
|
const isZodImport = ZOD_NAMESPACE_IMPORTS.has(importPath);
|
|
1173
1110
|
const params = _kubb_core.ast.caseParams(node.parameters, paramsCasing);
|
|
1174
1111
|
const meta = { file: resolver.resolveFile({
|
|
@@ -1185,7 +1122,7 @@ const zodGenerator = (0, _kubb_core.defineGenerator)({
|
|
|
1185
1122
|
function renderSchemaEntry({ schema, name, keysToOmit, direction = "output" }) {
|
|
1186
1123
|
if (!schema) return null;
|
|
1187
1124
|
const inferTypeName = inferred ? resolver.resolveTypeName(name) : null;
|
|
1188
|
-
const codecRefNames = direction === "input" && !mini ? new Set(_kubb_core.ast.collect(schema, { schema: (n) => n.type === "ref" && n.ref && containsCodec(n) ?
|
|
1125
|
+
const codecRefNames = direction === "input" && !mini ? new Set(_kubb_core.ast.collect(schema, { schema: (n) => n.type === "ref" && n.ref && containsCodec(n) ? (0, _kubb_ast_utils.extractRefName)(n.ref) ?? void 0 : void 0 })) : null;
|
|
1189
1126
|
const imports = adapter.getImports(schema, (schemaName) => ({
|
|
1190
1127
|
name: codecRefNames?.has(schemaName) ? resolver.resolveInputSchemaName(schemaName) : resolver.resolveSchemaName(schemaName),
|
|
1191
1128
|
path: resolver.resolveFile({
|
|
@@ -1227,7 +1164,7 @@ const zodGenerator = (0, _kubb_core.defineGenerator)({
|
|
|
1227
1164
|
cyclicSchemas,
|
|
1228
1165
|
nodes: printer?.nodes
|
|
1229
1166
|
})[direction];
|
|
1230
|
-
return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: [
|
|
1167
|
+
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
1168
|
root: meta.file.path,
|
|
1232
1169
|
path: imp.path,
|
|
1233
1170
|
name: imp.name
|
|
@@ -1435,14 +1372,16 @@ const zodGenerator = (0, _kubb_core.defineGenerator)({
|
|
|
1435
1372
|
/**
|
|
1436
1373
|
* Default resolver used by `@kubb/plugin-zod`. Decides the names and file
|
|
1437
1374
|
* paths for every generated Zod schema. Schemas use camelCase with a
|
|
1438
|
-
* `Schema` suffix (`listPetsSchema`); their inferred types use PascalCase
|
|
1375
|
+
* `Schema` suffix (`listPetsSchema`); their inferred types use PascalCase
|
|
1376
|
+
* with a `SchemaType` suffix (`PetSchemaType`), so the value and the type
|
|
1377
|
+
* never share an identifier even when the schema name is all-uppercase.
|
|
1439
1378
|
*
|
|
1440
1379
|
* @example Resolve schema and type names
|
|
1441
1380
|
* ```ts
|
|
1442
1381
|
* import { resolverZod } from '@kubb/plugin-zod'
|
|
1443
1382
|
*
|
|
1444
1383
|
* resolverZod.default('list pets', 'function') // 'listPetsSchema'
|
|
1445
|
-
* resolverZod.resolveSchemaTypeName('pet') // '
|
|
1384
|
+
* resolverZod.resolveSchemaTypeName('pet') // 'PetSchemaType'
|
|
1446
1385
|
* ```
|
|
1447
1386
|
*/
|
|
1448
1387
|
const resolverZod = (0, _kubb_core.defineResolver)(() => {
|
|
@@ -1450,17 +1389,14 @@ const resolverZod = (0, _kubb_core.defineResolver)(() => {
|
|
|
1450
1389
|
name: "default",
|
|
1451
1390
|
pluginName: "plugin-zod",
|
|
1452
1391
|
default(name, type) {
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
suffix: type ? "schema" : void 0
|
|
1456
|
-
});
|
|
1457
|
-
return type === "file" ? resolved : ensureValidVarName(resolved);
|
|
1392
|
+
if (type === "file") return toFilePath(name, (part) => camelCase(part, { suffix: "schema" }));
|
|
1393
|
+
return ensureValidVarName(camelCase(name, { suffix: type ? "schema" : void 0 }));
|
|
1458
1394
|
},
|
|
1459
1395
|
resolveSchemaName(name) {
|
|
1460
1396
|
return ensureValidVarName(camelCase(name, { suffix: "schema" }));
|
|
1461
1397
|
},
|
|
1462
1398
|
resolveSchemaTypeName(name) {
|
|
1463
|
-
return ensureValidVarName(pascalCase(name, { suffix: "schema" }));
|
|
1399
|
+
return ensureValidVarName(pascalCase(name, { suffix: "schema type" }));
|
|
1464
1400
|
},
|
|
1465
1401
|
resolveInputSchemaName(name) {
|
|
1466
1402
|
return this.resolveSchemaName(`${name} input`);
|
|
@@ -1469,7 +1405,7 @@ const resolverZod = (0, _kubb_core.defineResolver)(() => {
|
|
|
1469
1405
|
return this.resolveSchemaTypeName(`${name} input`);
|
|
1470
1406
|
},
|
|
1471
1407
|
resolveTypeName(name) {
|
|
1472
|
-
return ensureValidVarName(pascalCase(name));
|
|
1408
|
+
return ensureValidVarName(pascalCase(name, { suffix: "type" }));
|
|
1473
1409
|
},
|
|
1474
1410
|
resolvePathName(name, type) {
|
|
1475
1411
|
return this.default(name, type);
|
|
@@ -1535,9 +1471,9 @@ const pluginZodName = "plugin-zod";
|
|
|
1535
1471
|
const pluginZod = (0, _kubb_core.definePlugin)((options) => {
|
|
1536
1472
|
const { output = {
|
|
1537
1473
|
path: "zod",
|
|
1538
|
-
|
|
1474
|
+
barrel: { type: "named" }
|
|
1539
1475
|
}, 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, transformer: userTransformer, generators: userGenerators = [] } = options;
|
|
1540
|
-
const groupConfig = createGroupConfig(group
|
|
1476
|
+
const groupConfig = createGroupConfig(group);
|
|
1541
1477
|
return {
|
|
1542
1478
|
name: pluginZodName,
|
|
1543
1479
|
options,
|