@kubb/plugin-zod 5.7.1 → 5.7.3
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 +429 -192
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +0 -12
- package/dist/index.d.ts +0 -12
- package/dist/index.js +429 -192
- package/dist/index.js.map +1 -1
- package/kubb-extension.json +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -2,11 +2,10 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
//#endregion
|
|
6
5
|
let kubb_kit = require("kubb/kit");
|
|
7
6
|
let kubb_jsx = require("kubb/jsx");
|
|
8
7
|
let kubb_jsx_jsx_runtime = require("kubb/jsx/jsx-runtime");
|
|
9
|
-
|
|
8
|
+
// ../../internals/shared/src/operation.ts
|
|
10
9
|
/**
|
|
11
10
|
* Maps a content type to the PascalCase suffix used to name per-content-type variants
|
|
12
11
|
* (e.g. `application/json` → `Json`, `application/xml` → `Xml`, `multipart/form-data` → `FormData`).
|
|
@@ -89,7 +88,10 @@ function getOperationParameters(node) {
|
|
|
89
88
|
* shape from the same inputs. `primitive: 'object'` is a no-op for the TS printer and tells the Zod
|
|
90
89
|
* printer to emit `z.object(…)` rather than a record.
|
|
91
90
|
*/
|
|
92
|
-
function
|
|
91
|
+
function hasRequestContentTypeChoice(node) {
|
|
92
|
+
return (node.requestBody?.content ?? []).filter((entry) => entry.schema).length > 1;
|
|
93
|
+
}
|
|
94
|
+
function buildOptionsSchema(node, resolver, { pairContentTypes = false } = {}) {
|
|
93
95
|
const { path, query, header } = getOperationParameters(node);
|
|
94
96
|
const hasBody = Boolean(node.requestBody?.content?.[0]?.schema);
|
|
95
97
|
const createNever = () => kubb_kit.ast.factory.createSchema({
|
|
@@ -114,29 +116,57 @@ function buildOptionsSchema(node, resolver) {
|
|
|
114
116
|
resolve: resolver.param.headers
|
|
115
117
|
}
|
|
116
118
|
];
|
|
117
|
-
|
|
119
|
+
const createOptions = (body, extra = []) => kubb_kit.ast.factory.createSchema({
|
|
118
120
|
type: "object",
|
|
119
121
|
primitive: "object",
|
|
120
122
|
deprecated: node.deprecated,
|
|
121
|
-
properties: [
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
})
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
})
|
|
138
|
-
})
|
|
139
|
-
|
|
123
|
+
properties: [
|
|
124
|
+
kubb_kit.ast.factory.createProperty({
|
|
125
|
+
name: "body",
|
|
126
|
+
required: hasBody,
|
|
127
|
+
schema: body
|
|
128
|
+
}),
|
|
129
|
+
...groups.map(({ name, params, resolve }) => {
|
|
130
|
+
const required = params.some((param) => param.required);
|
|
131
|
+
return kubb_kit.ast.factory.createProperty({
|
|
132
|
+
name,
|
|
133
|
+
required,
|
|
134
|
+
schema: params.length > 0 ? kubb_kit.ast.factory.createSchema({
|
|
135
|
+
type: "ref",
|
|
136
|
+
name: resolve.call(resolver.param, node, params[0]),
|
|
137
|
+
optional: !required
|
|
138
|
+
}) : createNever()
|
|
139
|
+
});
|
|
140
|
+
}),
|
|
141
|
+
...extra
|
|
142
|
+
]
|
|
143
|
+
});
|
|
144
|
+
const variants = pairContentTypes && hasRequestContentTypeChoice(node) ? resolveContentTypeVariants(node.requestBody?.content ?? [], resolver.response.body(node)) : [];
|
|
145
|
+
if (variants.length < 2) return createOptions(hasBody ? kubb_kit.ast.factory.createSchema({
|
|
146
|
+
type: "ref",
|
|
147
|
+
name: resolver.response.body(node)
|
|
148
|
+
}) : createNever());
|
|
149
|
+
return kubb_kit.ast.factory.createSchema({
|
|
150
|
+
type: "union",
|
|
151
|
+
members: variants.map((variant, index) => createOptions(kubb_kit.ast.factory.createSchema({
|
|
152
|
+
type: "ref",
|
|
153
|
+
name: variant.name
|
|
154
|
+
}), [kubb_kit.ast.factory.createProperty({
|
|
155
|
+
name: "contentType",
|
|
156
|
+
required: index > 0,
|
|
157
|
+
schema: kubb_kit.ast.factory.createSchema({
|
|
158
|
+
type: "object",
|
|
159
|
+
primitive: "object",
|
|
160
|
+
properties: [kubb_kit.ast.factory.createProperty({
|
|
161
|
+
name: "request",
|
|
162
|
+
required: true,
|
|
163
|
+
schema: kubb_kit.ast.factory.createSchema({
|
|
164
|
+
type: "enum",
|
|
165
|
+
enumValues: [variant.contentType]
|
|
166
|
+
})
|
|
167
|
+
})]
|
|
168
|
+
})
|
|
169
|
+
})]))
|
|
140
170
|
});
|
|
141
171
|
}
|
|
142
172
|
/**
|
|
@@ -206,8 +236,7 @@ function isSuccessStatusCode(statusCode) {
|
|
|
206
236
|
function getSuccessResponses(responses) {
|
|
207
237
|
return responses.filter((response) => isSuccessStatusCode(response.statusCode));
|
|
208
238
|
}
|
|
209
|
-
|
|
210
|
-
//#region ../../internals/shared/src/adapter.ts
|
|
239
|
+
// ../../internals/shared/src/adapter.ts
|
|
211
240
|
/**
|
|
212
241
|
* Narrows the generic `Adapter` from a generator context to the OpenAPI adapter,
|
|
213
242
|
* so OAS-only options (`dateType`, `enums`) and the parsed `document` are typed.
|
|
@@ -230,8 +259,7 @@ function getOasAdapter(adapter) {
|
|
|
230
259
|
});
|
|
231
260
|
return adapter;
|
|
232
261
|
}
|
|
233
|
-
|
|
234
|
-
//#region ../../internals/utils/src/casing.ts
|
|
262
|
+
// ../../internals/utils/src/casing.ts
|
|
235
263
|
/**
|
|
236
264
|
* Shared implementation for camelCase and PascalCase conversion.
|
|
237
265
|
* Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)
|
|
@@ -280,8 +308,7 @@ function camelCase(text, { prefix = "", suffix = "" } = {}) {
|
|
|
280
308
|
function pascalCase(text, { prefix = "", suffix = "" } = {}) {
|
|
281
309
|
return toCamelOrPascal(`${prefix} ${text} ${suffix}`, true);
|
|
282
310
|
}
|
|
283
|
-
|
|
284
|
-
//#region ../../internals/utils/src/reserved.ts
|
|
311
|
+
// ../../internals/utils/src/reserved.ts
|
|
285
312
|
/**
|
|
286
313
|
* JavaScript and Java reserved words.
|
|
287
314
|
* @link https://github.com/jonschlinkert/reserved/blob/master/index.js
|
|
@@ -289,6 +316,7 @@ function pascalCase(text, { prefix = "", suffix = "" } = {}) {
|
|
|
289
316
|
const reservedWords = /* @__PURE__ */ new Set([
|
|
290
317
|
"abstract",
|
|
291
318
|
"arguments",
|
|
319
|
+
"await",
|
|
292
320
|
"boolean",
|
|
293
321
|
"break",
|
|
294
322
|
"byte",
|
|
@@ -419,8 +447,7 @@ function ensureValidVarName(name) {
|
|
|
419
447
|
function isIdentifier(name) {
|
|
420
448
|
return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
|
|
421
449
|
}
|
|
422
|
-
|
|
423
|
-
//#region ../../internals/utils/src/strings.ts
|
|
450
|
+
// ../../internals/utils/src/strings.ts
|
|
424
451
|
/**
|
|
425
452
|
* Wraps a value in single quotes for emitting a single-quoted JavaScript string literal, escaping
|
|
426
453
|
* any backslash or single quote in the content.
|
|
@@ -469,6 +496,34 @@ function stringify(value) {
|
|
|
469
496
|
if (value === void 0 || value === null) return "''";
|
|
470
497
|
return `'${JSON.stringify(trimQuotes(value.toString())).slice(1, -1).replace(/\\"/g, "\"").replace(/'/g, "\\'")}'`;
|
|
471
498
|
}
|
|
499
|
+
const NEEDS_UNICODE = /(?<!\\)(?:\\\\)*\\[pPu]\{|[\u{10000}-\u{10FFFF}]/u;
|
|
500
|
+
const KEPT_ESCAPE = /[A-Za-z0-9^$\\.*+?()[\]{}|/]/;
|
|
501
|
+
/**
|
|
502
|
+
* Drops the backslash from escapes that the `u` flag rejects: an escaped punctuation character that is
|
|
503
|
+
* not a syntax character, and `\-` outside a class. Both match the same character without the backslash.
|
|
504
|
+
*/
|
|
505
|
+
function dropIdentityEscapes(pattern) {
|
|
506
|
+
let inClass = false;
|
|
507
|
+
return pattern.replace(/\\(.)|[[\]]/gs, (match, escaped) => {
|
|
508
|
+
if (escaped === void 0) {
|
|
509
|
+
inClass = match === "[";
|
|
510
|
+
return match;
|
|
511
|
+
}
|
|
512
|
+
return KEPT_ESCAPE.test(escaped) || escaped === "-" && inClass ? match : escaped;
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
/**
|
|
516
|
+
* Builds the `RegExp` for a pattern, adding the `u` flag when it uses `\p{...}`, `\P{...}` or `\u{...}`, or
|
|
517
|
+
* holds a character outside the BMP. A pattern that is not valid under `u` keeps the flags it came with.
|
|
518
|
+
*/
|
|
519
|
+
function toRegExp(pattern, flags) {
|
|
520
|
+
if (flags?.includes("u") || !NEEDS_UNICODE.test(pattern)) return new RegExp(pattern, flags);
|
|
521
|
+
try {
|
|
522
|
+
return new RegExp(dropIdentityEscapes(pattern), `${flags ?? ""}u`);
|
|
523
|
+
} catch {
|
|
524
|
+
return new RegExp(pattern, flags);
|
|
525
|
+
}
|
|
526
|
+
}
|
|
472
527
|
/**
|
|
473
528
|
* Converts a pattern string into a `new RegExp(...)` constructor call or a regex literal string.
|
|
474
529
|
* Inline flags expressed as a `^(?im)` prefix are extracted and applied to the resulting expression.
|
|
@@ -485,13 +540,11 @@ function toRegExpString(text, func = "RegExp") {
|
|
|
485
540
|
const match = raw.match(/^\^(\(\?([igmsuy]+)\))/i);
|
|
486
541
|
const replacementTarget = match?.[1] ?? "";
|
|
487
542
|
const matchedFlags = match?.[2];
|
|
488
|
-
const
|
|
489
|
-
const { source, flags } = new RegExp(cleaned, matchedFlags);
|
|
543
|
+
const { source, flags } = toRegExp(raw.replace(/^\\?\//, "").replace(/\\?\/$/, "").replace(replacementTarget, ""), matchedFlags);
|
|
490
544
|
if (func === null) return `/${source}/${flags}`;
|
|
491
545
|
return `new ${func}(${JSON.stringify(source)}${flags ? `, ${JSON.stringify(flags)}` : ""})`;
|
|
492
546
|
}
|
|
493
|
-
|
|
494
|
-
//#region ../../internals/utils/src/codegen.ts
|
|
547
|
+
// ../../internals/utils/src/codegen.ts
|
|
495
548
|
const INDENT = " ";
|
|
496
549
|
/**
|
|
497
550
|
* Indents every non-empty line of `text` by one indent level, leaving blank lines empty.
|
|
@@ -560,8 +613,7 @@ function buildList(items, brackets = ["[", "]"]) {
|
|
|
560
613
|
function lazyGetter({ name, body }) {
|
|
561
614
|
return `get ${objectKey(name)}() { return ${body} }`;
|
|
562
615
|
}
|
|
563
|
-
|
|
564
|
-
//#region ../../internals/utils/src/fs.ts
|
|
616
|
+
// ../../internals/utils/src/fs.ts
|
|
565
617
|
/**
|
|
566
618
|
* Builds a nested file path from a dotted name. Splits on dots that precede a letter
|
|
567
619
|
* (so version numbers embedded in operationIds like `v2025.0` stay intact), camelCases
|
|
@@ -585,17 +637,24 @@ function toFilePath(name, caseLast = camelCase) {
|
|
|
585
637
|
const parts = name.split(/\.(?=[a-zA-Z])/);
|
|
586
638
|
return parts.map((part, i) => i === parts.length - 1 ? caseLast(part) : camelCase(part)).filter(Boolean).join("/");
|
|
587
639
|
}
|
|
588
|
-
|
|
589
|
-
//#region ../../internals/shared/src/resolver.ts
|
|
640
|
+
// ../../internals/shared/src/resolver.ts
|
|
590
641
|
/**
|
|
591
|
-
*
|
|
592
|
-
*
|
|
642
|
+
* Builds the allocation key for a declaration an operation owns. `scope` names which declaration
|
|
643
|
+
* it is, so two of them never share an allocation even when a custom resolver gives both the same
|
|
644
|
+
* name. Leave `scope` empty for the operation's own declaration.
|
|
593
645
|
*
|
|
594
646
|
* @example
|
|
595
|
-
*
|
|
647
|
+
* ```ts
|
|
648
|
+
* resolver.resolveName({ key: operationKey(node, 'response', 'status', 404), name })
|
|
649
|
+
* ```
|
|
596
650
|
*/
|
|
597
|
-
function
|
|
598
|
-
return
|
|
651
|
+
function operationKey(node, ...scope) {
|
|
652
|
+
return [
|
|
653
|
+
"operation",
|
|
654
|
+
node.method,
|
|
655
|
+
node.path,
|
|
656
|
+
...scope.map(String)
|
|
657
|
+
];
|
|
599
658
|
}
|
|
600
659
|
/**
|
|
601
660
|
* Builds the shared `param` namespace. Spread the result into `createResolver`
|
|
@@ -608,15 +667,33 @@ function operationParamName(node, param) {
|
|
|
608
667
|
*/
|
|
609
668
|
function createOperationParamResolver() {
|
|
610
669
|
return {
|
|
611
|
-
name
|
|
670
|
+
name(node, param) {
|
|
671
|
+
const name = this.name(`${node.operationId} ${param.in} ${param.name}`);
|
|
672
|
+
return this.resolveName({
|
|
673
|
+
key: operationKey(node, "param", "name", param.in, param.name),
|
|
674
|
+
name
|
|
675
|
+
});
|
|
676
|
+
},
|
|
612
677
|
path(node) {
|
|
613
|
-
|
|
678
|
+
const name = this.name(`${node.operationId} Path`);
|
|
679
|
+
return this.resolveName({
|
|
680
|
+
key: operationKey(node, "param", "path"),
|
|
681
|
+
name
|
|
682
|
+
});
|
|
614
683
|
},
|
|
615
684
|
query(node) {
|
|
616
|
-
|
|
685
|
+
const name = this.name(`${node.operationId} Query`);
|
|
686
|
+
return this.resolveName({
|
|
687
|
+
key: operationKey(node, "param", "query"),
|
|
688
|
+
name
|
|
689
|
+
});
|
|
617
690
|
},
|
|
618
691
|
headers(node) {
|
|
619
|
-
|
|
692
|
+
const name = this.name(`${node.operationId} Headers`);
|
|
693
|
+
return this.resolveName({
|
|
694
|
+
key: operationKey(node, "param", "headers"),
|
|
695
|
+
name
|
|
696
|
+
});
|
|
620
697
|
}
|
|
621
698
|
};
|
|
622
699
|
}
|
|
@@ -633,16 +710,32 @@ function createOperationParamResolver() {
|
|
|
633
710
|
function createOperationResponseResolver() {
|
|
634
711
|
return {
|
|
635
712
|
status(node, statusCode) {
|
|
636
|
-
|
|
713
|
+
const name = this.name(`${node.operationId} Status ${statusCode}`);
|
|
714
|
+
return this.resolveName({
|
|
715
|
+
key: operationKey(node, "response", "status", statusCode),
|
|
716
|
+
name
|
|
717
|
+
});
|
|
637
718
|
},
|
|
638
719
|
body(node) {
|
|
639
|
-
|
|
720
|
+
const name = this.name(`${node.operationId} Body`);
|
|
721
|
+
return this.resolveName({
|
|
722
|
+
key: operationKey(node, "response", "body"),
|
|
723
|
+
name
|
|
724
|
+
});
|
|
640
725
|
},
|
|
641
726
|
responses(node) {
|
|
642
|
-
|
|
727
|
+
const name = this.name(`${node.operationId} Responses`);
|
|
728
|
+
return this.resolveName({
|
|
729
|
+
key: operationKey(node, "response", "responses"),
|
|
730
|
+
name
|
|
731
|
+
});
|
|
643
732
|
},
|
|
644
733
|
response(node) {
|
|
645
|
-
|
|
734
|
+
const name = this.name(`${node.operationId} Response`);
|
|
735
|
+
return this.resolveName({
|
|
736
|
+
key: operationKey(node, "response", "response"),
|
|
737
|
+
name
|
|
738
|
+
});
|
|
646
739
|
}
|
|
647
740
|
};
|
|
648
741
|
}
|
|
@@ -660,8 +753,7 @@ function createCasedFile(caseLast) {
|
|
|
660
753
|
return `${toFilePath(name, caseLast)}${extname}`;
|
|
661
754
|
} };
|
|
662
755
|
}
|
|
663
|
-
|
|
664
|
-
//#region ../../internals/shared/src/group.ts
|
|
756
|
+
// ../../internals/shared/src/group.ts
|
|
665
757
|
/**
|
|
666
758
|
* Builds the `group` config a Kubb plugin passes to `ctx.setOptions`, applying the
|
|
667
759
|
* shared default naming so every plugin groups output consistently:
|
|
@@ -691,8 +783,7 @@ function createGroupConfig(group) {
|
|
|
691
783
|
name: group.name ? group.name : defaultName
|
|
692
784
|
};
|
|
693
785
|
}
|
|
694
|
-
|
|
695
|
-
//#region ../../internals/shared/src/schemaTraversal.ts
|
|
786
|
+
// ../../internals/shared/src/schemaTraversal.ts
|
|
696
787
|
/**
|
|
697
788
|
* Maps each property of an object schema to its transformed output. Pairs every result with the
|
|
698
789
|
* original property so the printer keeps full control over modifiers, getters, and key syntax.
|
|
@@ -730,8 +821,7 @@ function mapSchemaItems(node, transform) {
|
|
|
730
821
|
output: transform(schema)
|
|
731
822
|
}));
|
|
732
823
|
}
|
|
733
|
-
|
|
734
|
-
//#region src/components/Zod.tsx
|
|
824
|
+
// src/components/Zod.tsx
|
|
735
825
|
function Zod({ name, node, printer, inferTypeName, inferKind = "infer", typeGuards, isName, assertName, mini, cyclic, compile }) {
|
|
736
826
|
const output = printer.print(node);
|
|
737
827
|
const printerImports = printer.drainImports();
|
|
@@ -803,8 +893,7 @@ function Zod({ name, node, printer, inferTypeName, inferKind = "infer", typeGuar
|
|
|
803
893
|
})
|
|
804
894
|
] });
|
|
805
895
|
}
|
|
806
|
-
|
|
807
|
-
//#region src/utils.ts
|
|
896
|
+
// src/utils.ts
|
|
808
897
|
/**
|
|
809
898
|
* Returns `true` when the given coercion option enables coercion for the specified type.
|
|
810
899
|
*/
|
|
@@ -813,9 +902,6 @@ function shouldCoerce(coercion, type) {
|
|
|
813
902
|
if (coercion === true) return true;
|
|
814
903
|
return !!coercion[type];
|
|
815
904
|
}
|
|
816
|
-
function propertyNamesOf(node) {
|
|
817
|
-
return "propertyNames" in node ? node.propertyNames : void 0;
|
|
818
|
-
}
|
|
819
905
|
/**
|
|
820
906
|
* Whether the schema node represents a closed or finite set of keys (e.g. enum, literal,
|
|
821
907
|
* or union of enums/literals).
|
|
@@ -836,30 +922,32 @@ function isClosedKeySchema(node) {
|
|
|
836
922
|
}
|
|
837
923
|
/**
|
|
838
924
|
* Whether the node is a plain inline object whose shape can be lifted into an `.extend({ … })`
|
|
839
|
-
* argument.
|
|
925
|
+
* argument. Property counts, a catchall, `patternProperties`, or a nullable/optional wrapper cannot, so those stay
|
|
840
926
|
* on `.and(…)`.
|
|
841
927
|
*/
|
|
842
928
|
function isPlainInlineObject(node) {
|
|
843
929
|
if (node.type !== "object") return false;
|
|
930
|
+
if (node.minProperties !== void 0 || node.maxProperties !== void 0) return false;
|
|
844
931
|
if (node.nullable || node.optional || node.nullish) return false;
|
|
845
932
|
const hasAdditionalProperties = node.additionalProperties !== void 0;
|
|
846
933
|
const hasPatternProperties = Boolean(node.patternProperties);
|
|
847
|
-
return !hasAdditionalProperties && !hasPatternProperties && !
|
|
934
|
+
return !hasAdditionalProperties && !hasPatternProperties && !node.propertyNames;
|
|
848
935
|
}
|
|
849
936
|
/**
|
|
850
937
|
* Whether a node renders as a bare Zod object — one that accepts `.extend(…)` and can be a
|
|
851
938
|
* `z.discriminatedUnion` option. Covers object nodes, `$ref`s that resolve to (or are still
|
|
852
939
|
* unresolved) objects, single-member unions of an object, and object-composable `allOf`.
|
|
853
940
|
*
|
|
854
|
-
*
|
|
941
|
+
* Property counts render as a pipe. A ref into `cyclicSchemas` renders as `z.lazy(…)`.
|
|
855
942
|
*/
|
|
856
943
|
function isObjectSchemaNode(node, cyclicSchemas) {
|
|
857
944
|
if (node.nullable || node.optional || node.nullish) return false;
|
|
858
945
|
if (node.type === "object") {
|
|
946
|
+
if (node.minProperties !== void 0 || node.maxProperties !== void 0) return false;
|
|
859
947
|
const hasProperties = Boolean(node.properties?.length);
|
|
860
948
|
const hasTypedAdditionalProperties = Boolean(node.additionalProperties && node.additionalProperties !== true);
|
|
861
949
|
const hasPatternProperties = Boolean(node.patternProperties);
|
|
862
|
-
return !(!hasProperties && (hasTypedAdditionalProperties || hasPatternProperties ||
|
|
950
|
+
return !(!hasProperties && (hasTypedAdditionalProperties || hasPatternProperties || node.propertyNames));
|
|
863
951
|
}
|
|
864
952
|
if (node.type === "ref") {
|
|
865
953
|
const refName = kubb_kit.ast.resolveRefName(node);
|
|
@@ -883,6 +971,49 @@ function isObjectComposableIntersection(node, cyclicSchemas) {
|
|
|
883
971
|
const [first, ...rest] = node.members ?? [];
|
|
884
972
|
return !!first && isObjectSchemaNode(first, cyclicSchemas) && rest.every(isPlainInlineObject);
|
|
885
973
|
}
|
|
974
|
+
function preserveRequiredProperties(members) {
|
|
975
|
+
const hasRequiredProperty = ({ node, propertyName, seen = /* @__PURE__ */ new Set() }) => {
|
|
976
|
+
if (seen.has(node)) return false;
|
|
977
|
+
seen.add(node);
|
|
978
|
+
const resolved = (0, kubb_kit.syncSchemaRef)(node);
|
|
979
|
+
const composition = kubb_kit.ast.narrowSchema(resolved, kubb_kit.ast.schemaTypes.intersection) ?? kubb_kit.ast.narrowSchema(resolved, kubb_kit.ast.schemaTypes.union);
|
|
980
|
+
if (composition) {
|
|
981
|
+
if (composition.type === kubb_kit.ast.schemaTypes.union && composition.members?.length !== 1) return false;
|
|
982
|
+
return composition.members?.some((child) => hasRequiredProperty({
|
|
983
|
+
node: child,
|
|
984
|
+
propertyName,
|
|
985
|
+
seen
|
|
986
|
+
})) ?? false;
|
|
987
|
+
}
|
|
988
|
+
return kubb_kit.ast.resolveSchemaProperties({
|
|
989
|
+
node: resolved,
|
|
990
|
+
propertyName
|
|
991
|
+
}).some((property) => property.required !== false && !property.schema.optional && !property.schema.nullish);
|
|
992
|
+
};
|
|
993
|
+
return members.map((member, index) => {
|
|
994
|
+
const object = kubb_kit.ast.narrowSchema(member, kubb_kit.ast.schemaTypes.object);
|
|
995
|
+
if (!object || index === 0) return member;
|
|
996
|
+
return {
|
|
997
|
+
...object,
|
|
998
|
+
properties: object.properties.map((property) => {
|
|
999
|
+
if (!members.slice(0, index).some((base) => hasRequiredProperty({
|
|
1000
|
+
node: base,
|
|
1001
|
+
propertyName: property.name
|
|
1002
|
+
}))) return property;
|
|
1003
|
+
return {
|
|
1004
|
+
...property,
|
|
1005
|
+
required: true,
|
|
1006
|
+
schema: {
|
|
1007
|
+
...property.schema,
|
|
1008
|
+
optional: false,
|
|
1009
|
+
nullish: false,
|
|
1010
|
+
nullable: property.schema.nullable || property.schema.nullish
|
|
1011
|
+
}
|
|
1012
|
+
};
|
|
1013
|
+
})
|
|
1014
|
+
};
|
|
1015
|
+
});
|
|
1016
|
+
}
|
|
886
1017
|
/**
|
|
887
1018
|
* Format a default value as a code-level literal.
|
|
888
1019
|
* Arrays and objects keep their contents as a JSON literal, primitives become their string
|
|
@@ -929,11 +1060,20 @@ function defaultLiteral(node, value) {
|
|
|
929
1060
|
*/
|
|
930
1061
|
function buildEnum(values) {
|
|
931
1062
|
if (values.every((v) => typeof v === "string")) return `z.enum([${values.map((v) => formatDefault(v)).join(", ")}])`;
|
|
932
|
-
const literals = values.map((
|
|
1063
|
+
const literals = values.map((value) => buildLiteral(value));
|
|
933
1064
|
if (literals.length === 1) return literals[0];
|
|
934
1065
|
return `z.union([${literals.join(", ")}])`;
|
|
935
1066
|
}
|
|
936
1067
|
/**
|
|
1068
|
+
* Preserves the structure of JSON const values in both Zod APIs.
|
|
1069
|
+
*/
|
|
1070
|
+
function buildLiteral(value) {
|
|
1071
|
+
if (value === null) return "z.null()";
|
|
1072
|
+
if (Array.isArray(value)) return `z.tuple([${value.map((item) => buildLiteral(item)).join(", ")}])`;
|
|
1073
|
+
if (typeof value === "object") return `z.strictObject({${Object.entries(value).map(([name, item]) => `${JSON.stringify(name)}: ${buildLiteral(item)}`).join(", ")}})`;
|
|
1074
|
+
return `z.literal(${formatDefault(value)})`;
|
|
1075
|
+
}
|
|
1076
|
+
/**
|
|
937
1077
|
* Digit pattern for a `type: 'string'` schema that carries an integer `format`, the way ProtoJSON
|
|
938
1078
|
* encodes 64-bit integers. Returns `undefined` for every other format, and a `pattern` from the
|
|
939
1079
|
* spec takes precedence over this fallback.
|
|
@@ -1016,6 +1156,17 @@ function lengthChecksMini({ min, max, pattern, regexType }) {
|
|
|
1016
1156
|
return checks.length ? `.check(${checks.join(", ")})` : "";
|
|
1017
1157
|
}
|
|
1018
1158
|
/**
|
|
1159
|
+
* Checks property counts before object parsing strips unknown keys or inserts defaults.
|
|
1160
|
+
*/
|
|
1161
|
+
function objectConstraints({ value, node }) {
|
|
1162
|
+
if (node.type !== "object") return value;
|
|
1163
|
+
const checks = [];
|
|
1164
|
+
const skip = "typeof value !== \"object\" || value === null || Array.isArray(value)";
|
|
1165
|
+
if (node.minProperties !== void 0) checks.push(`z.refine(value => ${skip} || Object.keys(value).length >= ${node.minProperties}, { message: "Object must have at least ${node.minProperties} properties" })`);
|
|
1166
|
+
if (node.maxProperties !== void 0) checks.push(`z.refine(value => ${skip} || Object.keys(value).length <= ${node.maxProperties}, { message: "Object must have at most ${node.maxProperties} properties" })`);
|
|
1167
|
+
return checks.length ? `z.pipe(z.unknown().check(${checks.join(", ")}), ${value})` : value;
|
|
1168
|
+
}
|
|
1169
|
+
/**
|
|
1019
1170
|
* Apply nullable / optional / nullish modifiers, an optional `.describe()` call, and an
|
|
1020
1171
|
* optional `.meta({ examples })` call to a schema value string using the chainable Zod v4 API.
|
|
1021
1172
|
*/
|
|
@@ -1105,7 +1256,7 @@ function getMemberConstraint({ member, regexType, lengths, numbers }) {
|
|
|
1105
1256
|
/**
|
|
1106
1257
|
* Builds the `{ key: value, … }` shape shared by the `z.object(...)` and `.extend(...)` renderings.
|
|
1107
1258
|
*/
|
|
1108
|
-
function buildObjectShape(ctx, node,
|
|
1259
|
+
function buildObjectShape(ctx, node, renderProperty) {
|
|
1109
1260
|
const objectNode = kubb_kit.ast.narrowSchema(node, "object");
|
|
1110
1261
|
if (!objectNode) return "{}";
|
|
1111
1262
|
const isCyclic = (schema) => ctx.options.cyclicSchemas != null && (0, kubb_kit.containsCircularRef)(schema, { circularSchemas: ctx.options.cyclicSchemas });
|
|
@@ -1116,18 +1267,16 @@ function buildObjectShape(ctx, node, modify) {
|
|
|
1116
1267
|
const baseOutput = ctx.transform(schema) ?? ctx.transform(kubb_kit.ast.factory.createSchema({ type: "unknown" }));
|
|
1117
1268
|
if (hasSelfRef) ctx.options.cyclicSchemas = savedCyclicSchemas;
|
|
1118
1269
|
return baseOutput;
|
|
1119
|
-
}).map(({ name
|
|
1270
|
+
}).map(({ name, property, output: value }) => {
|
|
1120
1271
|
const { schema } = property;
|
|
1121
|
-
|
|
1122
|
-
|
|
1272
|
+
return renderProperty({
|
|
1273
|
+
name,
|
|
1274
|
+
value,
|
|
1123
1275
|
schema,
|
|
1124
1276
|
required: property.required,
|
|
1125
|
-
meta: (0, kubb_kit.syncSchemaRef)(schema)
|
|
1277
|
+
meta: (0, kubb_kit.syncSchemaRef)(schema),
|
|
1278
|
+
cyclic: isCyclic(schema)
|
|
1126
1279
|
});
|
|
1127
|
-
return isCyclic(schema) ? lazyGetter({
|
|
1128
|
-
name: propName,
|
|
1129
|
-
body: value
|
|
1130
|
-
}) : `${objectKey(propName)}: ${value}`;
|
|
1131
1280
|
}));
|
|
1132
1281
|
}
|
|
1133
1282
|
/**
|
|
@@ -1142,22 +1291,28 @@ function printWithOmit(ctx, node, modify, mini = false) {
|
|
|
1142
1291
|
if (!keysToOmit?.length || meta.primitive !== "object" || meta.type === "union" && meta.discriminatorPropertyName) return transformed;
|
|
1143
1292
|
const unwrap = omitUnwrapChain(node, mini ? "._zod.def.innerType" : ".unwrap()");
|
|
1144
1293
|
const mask = `{ ${keysToOmit.map((k) => `"${k}": true`).join(", ")} }`;
|
|
1145
|
-
const omit = (target) =>
|
|
1294
|
+
const omit = (target) => {
|
|
1295
|
+
const inner = `${target}${unwrap}`;
|
|
1296
|
+
const hasObjectConstraints = meta.type === "object" && (meta.minProperties !== void 0 || meta.maxProperties !== void 0);
|
|
1297
|
+
const pipe = mini ? `${inner}._zod.def` : inner;
|
|
1298
|
+
const object = hasObjectConstraints ? `${pipe}.out` : inner;
|
|
1299
|
+
const omitted = mini ? `z.omit(${object}, ${mask})` : `${object}.omit(${mask})`;
|
|
1300
|
+
return hasObjectConstraints ? `z.pipe(${pipe}.in, ${omitted})` : omitted;
|
|
1301
|
+
};
|
|
1146
1302
|
const lazyMatch = transformed.match(/^z\.lazy\(\(\)\s*=>\s*(.+)\)$/);
|
|
1147
1303
|
if (lazyMatch) return `z.lazy(() => ${omit(lazyMatch[1])})`;
|
|
1148
1304
|
return omit(transformed);
|
|
1149
1305
|
})(), meta);
|
|
1150
1306
|
}
|
|
1151
|
-
|
|
1152
|
-
//#region src/printers/printerZod.ts
|
|
1307
|
+
// src/printers/printerZod.ts
|
|
1153
1308
|
function strictOneOfMember(member, node, cyclicSchemas) {
|
|
1154
|
-
if (node.type ===
|
|
1309
|
+
if (node.type === kubb_kit.ast.schemaTypes.ref) {
|
|
1155
1310
|
if (member.startsWith("z.lazy(")) return member;
|
|
1156
1311
|
const refName = kubb_kit.ast.resolveRefName(node);
|
|
1157
1312
|
if (refName && cyclicSchemas?.has(refName)) return member;
|
|
1158
1313
|
const schema = (0, kubb_kit.syncSchemaRef)(node);
|
|
1159
1314
|
if (schema.nullable || schema.optional || node.nullable || node.optional) return member;
|
|
1160
|
-
if (schema.type ===
|
|
1315
|
+
if (schema.type === kubb_kit.ast.schemaTypes.object && (schema.additionalProperties === void 0 || schema.additionalProperties === false)) return `${member}.strict()`;
|
|
1161
1316
|
}
|
|
1162
1317
|
return member;
|
|
1163
1318
|
}
|
|
@@ -1165,28 +1320,70 @@ function strictOneOfMember(member, node, cyclicSchemas) {
|
|
|
1165
1320
|
* Builds the `{ key: value, … }` shape for an object node with the chainable modifiers.
|
|
1166
1321
|
*/
|
|
1167
1322
|
function buildZodObjectShape(ctx, node) {
|
|
1168
|
-
return buildObjectShape(ctx, node, ({ value, schema, required, meta }) =>
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1323
|
+
return buildObjectShape(ctx, node, ({ name, value, schema, required, meta, cyclic }) => {
|
|
1324
|
+
const body = applyModifiers({
|
|
1325
|
+
value,
|
|
1326
|
+
schema,
|
|
1327
|
+
nullable: meta.nullable,
|
|
1328
|
+
optional: schema.optional || required === false,
|
|
1329
|
+
nullish: schema.nullish,
|
|
1330
|
+
defaultValue: meta.default,
|
|
1331
|
+
description: schema.type !== kubb_kit.ast.schemaTypes.ref && meta.type === kubb_kit.ast.schemaTypes.ref ? void 0 : meta.description,
|
|
1332
|
+
examples: meta.examples
|
|
1333
|
+
});
|
|
1334
|
+
if (!cyclic) return `${objectKey(name)}: ${body}`;
|
|
1335
|
+
const returnType = recursiveGetterType({
|
|
1336
|
+
ctx,
|
|
1337
|
+
schema,
|
|
1338
|
+
required
|
|
1339
|
+
});
|
|
1340
|
+
return returnType ? `get ${objectKey(name)}(): ${returnType} { return ${body} }` : lazyGetter({
|
|
1341
|
+
name,
|
|
1342
|
+
body
|
|
1343
|
+
});
|
|
1344
|
+
});
|
|
1345
|
+
}
|
|
1346
|
+
/**
|
|
1347
|
+
* Breaks getter inference cycles without widening recursive refs and arrays to `z.ZodType`.
|
|
1348
|
+
*/
|
|
1349
|
+
function recursiveGetterType({ ctx, schema, required }) {
|
|
1350
|
+
function baseType(schema) {
|
|
1351
|
+
if (ctx.options.nodes?.[schema.type]) return void 0;
|
|
1352
|
+
if (schema.type === kubb_kit.ast.schemaTypes.ref) {
|
|
1353
|
+
const saved = ctx.options.cyclicSchemas;
|
|
1354
|
+
ctx.options.cyclicSchemas = void 0;
|
|
1355
|
+
const name = ctx.transform(schema);
|
|
1356
|
+
ctx.options.cyclicSchemas = saved;
|
|
1357
|
+
return name ? `typeof ${name}` : void 0;
|
|
1358
|
+
}
|
|
1359
|
+
if (schema.type === kubb_kit.ast.schemaTypes.array && schema.items?.length === 1) {
|
|
1360
|
+
const item = baseType(schema.items[0]);
|
|
1361
|
+
return item ? `z.ZodArray<${item}>` : void 0;
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
const base = baseType(schema);
|
|
1365
|
+
if (!base) return void 0;
|
|
1366
|
+
const meta = (0, kubb_kit.syncSchemaRef)(schema);
|
|
1367
|
+
const optional = schema.optional || required === false;
|
|
1368
|
+
const wrapped = (() => {
|
|
1369
|
+
if (schema.nullish || meta.nullable && optional) return `z.ZodOptional<z.ZodNullable<${base}>>`;
|
|
1370
|
+
if (optional) return `z.ZodOptional<${base}>`;
|
|
1371
|
+
if (meta.nullable) return `z.ZodNullable<${base}>`;
|
|
1372
|
+
return base;
|
|
1373
|
+
})();
|
|
1374
|
+
return meta.default !== void 0 && defaultLiteral(schema, meta.default) !== null ? `z.ZodDefault<${wrapped}>` : wrapped;
|
|
1178
1375
|
}
|
|
1179
1376
|
/**
|
|
1180
1377
|
* Types the direction probe skips. They delegate to their children rather than reading
|
|
1181
1378
|
* `direction` themselves, so {@link containsDirectionalNode} walks into the children instead.
|
|
1182
1379
|
*/
|
|
1183
1380
|
const CONTAINER_TYPES = /* @__PURE__ */ new Set([
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1381
|
+
kubb_kit.ast.schemaTypes.object,
|
|
1382
|
+
kubb_kit.ast.schemaTypes.array,
|
|
1383
|
+
kubb_kit.ast.schemaTypes.tuple,
|
|
1384
|
+
kubb_kit.ast.schemaTypes.union,
|
|
1385
|
+
kubb_kit.ast.schemaTypes.intersection,
|
|
1386
|
+
kubb_kit.ast.schemaTypes.ref
|
|
1190
1387
|
]);
|
|
1191
1388
|
/**
|
|
1192
1389
|
* Runs the node's effective handler (a `printer.nodes` override, else the built-in) once per
|
|
@@ -1218,7 +1415,7 @@ function variesByDirection({ node, printerOptions }) {
|
|
|
1218
1415
|
*/
|
|
1219
1416
|
function containsDirectionalNode({ node, printerOptions, seen = /* @__PURE__ */ new Set() }) {
|
|
1220
1417
|
if (!node) return false;
|
|
1221
|
-
if (node.type ===
|
|
1418
|
+
if (node.type === kubb_kit.ast.schemaTypes.ref) {
|
|
1222
1419
|
if (!node.ref) return false;
|
|
1223
1420
|
const refName = (0, kubb_kit.extractRefName)(node.ref);
|
|
1224
1421
|
if (refName) {
|
|
@@ -1226,7 +1423,7 @@ function containsDirectionalNode({ node, printerOptions, seen = /* @__PURE__ */
|
|
|
1226
1423
|
seen.add(refName);
|
|
1227
1424
|
}
|
|
1228
1425
|
const resolved = (0, kubb_kit.syncSchemaRef)(node);
|
|
1229
|
-
if (resolved.type ===
|
|
1426
|
+
if (resolved.type === kubb_kit.ast.schemaTypes.ref) return false;
|
|
1230
1427
|
return containsDirectionalNode({
|
|
1231
1428
|
node: resolved,
|
|
1232
1429
|
printerOptions,
|
|
@@ -1242,7 +1439,7 @@ function containsDirectionalNode({ node, printerOptions, seen = /* @__PURE__ */
|
|
|
1242
1439
|
if ("items" in node && node.items) children.push(...node.items);
|
|
1243
1440
|
if ("members" in node && node.members) children.push(...node.members);
|
|
1244
1441
|
if ("additionalProperties" in node && node.additionalProperties && node.additionalProperties !== true) children.push(node.additionalProperties);
|
|
1245
|
-
const propertyNames =
|
|
1442
|
+
const propertyNames = node.type === kubb_kit.ast.schemaTypes.object ? node.propertyNames : void 0;
|
|
1246
1443
|
if (propertyNames) children.push(propertyNames);
|
|
1247
1444
|
return children.some((child) => containsDirectionalNode({
|
|
1248
1445
|
node: child,
|
|
@@ -1254,7 +1451,7 @@ function containsDirectionalNode({ node, printerOptions, seen = /* @__PURE__ */
|
|
|
1254
1451
|
* Names of the `$ref` schemas the generator should route to their input (encode) variant.
|
|
1255
1452
|
*/
|
|
1256
1453
|
function collectDirectionalRefNames({ node, printerOptions }) {
|
|
1257
|
-
return kubb_kit.ast.collectSync(node, { schema: (n) => n.type ===
|
|
1454
|
+
return kubb_kit.ast.collectSync(node, { schema: (n) => n.type === kubb_kit.ast.schemaTypes.ref && n.ref && containsDirectionalNode({
|
|
1258
1455
|
node: n,
|
|
1259
1456
|
printerOptions
|
|
1260
1457
|
}) ? kubb_kit.ast.resolveRefName(n) ?? void 0 : void 0 });
|
|
@@ -1346,7 +1543,7 @@ const scalarNodes = {
|
|
|
1346
1543
|
enum(node) {
|
|
1347
1544
|
const nonNullValues = (node.namedEnumValues?.map((v) => v.value) ?? node.enumValues ?? []).filter((v) => v !== null);
|
|
1348
1545
|
if (node.namedEnumValues?.length) {
|
|
1349
|
-
const literals = nonNullValues.map((v) =>
|
|
1546
|
+
const literals = nonNullValues.map((v) => buildLiteral(v));
|
|
1350
1547
|
if (literals.length === 1) return literals[0];
|
|
1351
1548
|
return `z.union([${literals.join(", ")}])`;
|
|
1352
1549
|
}
|
|
@@ -1367,6 +1564,7 @@ const scalarNodes = {
|
|
|
1367
1564
|
*/
|
|
1368
1565
|
const printerZod = kubb_kit.ast.createPrinter((options) => {
|
|
1369
1566
|
const cyclicSchemaNames = options.cyclicSchemas;
|
|
1567
|
+
const unionsWithSiblings = /* @__PURE__ */ new WeakSet();
|
|
1370
1568
|
return {
|
|
1371
1569
|
name: "zod",
|
|
1372
1570
|
options,
|
|
@@ -1387,42 +1585,45 @@ const printerZod = kubb_kit.ast.createPrinter((options) => {
|
|
|
1387
1585
|
object(node) {
|
|
1388
1586
|
const entries = node.properties ?? [];
|
|
1389
1587
|
const patterns = node.patternProperties ? Object.entries(node.patternProperties) : [];
|
|
1390
|
-
const propertyNamesNode =
|
|
1588
|
+
const propertyNamesNode = node.propertyNames;
|
|
1391
1589
|
const propertyNamesKeySchema = propertyNamesNode ? this.transform(propertyNamesNode) : null;
|
|
1392
1590
|
const isStrict = node.additionalProperties === false && patterns.length === 0;
|
|
1393
1591
|
const isLoose = node.additionalProperties === true;
|
|
1394
1592
|
const objectBase = `${isStrict ? "z.strictObject" : isLoose ? "z.looseObject" : "z.object"}(${buildZodObjectShape(this, node)})`;
|
|
1395
|
-
return (
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
const
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1593
|
+
return objectConstraints({
|
|
1594
|
+
value: (() => {
|
|
1595
|
+
const recordFn = isClosedKeySchema(propertyNamesNode) ? "z.partialRecord" : "z.record";
|
|
1596
|
+
if (node.additionalProperties && node.additionalProperties !== true) {
|
|
1597
|
+
const catchallType = this.transform(node.additionalProperties);
|
|
1598
|
+
if (entries.length === 0) return catchallType ? `${recordFn}(${propertyNamesKeySchema || "z.string()"}, ${catchallType})` : objectBase;
|
|
1599
|
+
return catchallType ? `${objectBase}.catchall(${catchallType})` : objectBase;
|
|
1600
|
+
}
|
|
1601
|
+
if (entries.length === 0 && patterns.length === 0 && propertyNamesKeySchema && !isStrict) {
|
|
1602
|
+
const unknownType = this.transform(kubb_kit.ast.factory.createSchema({ type: kubb_kit.ast.schemaTypes.unknown }));
|
|
1603
|
+
return `${recordFn}(${propertyNamesKeySchema}, ${unknownType})`;
|
|
1604
|
+
}
|
|
1605
|
+
if (node.additionalProperties === true) return objectBase;
|
|
1606
|
+
if (isStrict) return objectBase;
|
|
1607
|
+
if (patterns.length > 0) {
|
|
1608
|
+
const values = patterns.map(([, valueSchema]) => {
|
|
1609
|
+
const valueType = this.transform(valueSchema) ?? this.transform(kubb_kit.ast.factory.createSchema({ type: kubb_kit.ast.schemaTypes.unknown }));
|
|
1610
|
+
return valueSchema.nullable ? `${valueType}.nullable()` : valueType;
|
|
1611
|
+
});
|
|
1612
|
+
const distinct = [...new Set(values)];
|
|
1613
|
+
const value = distinct.length === 1 ? distinct[0] : `z.union([${distinct.join(", ")}])`;
|
|
1614
|
+
if (entries.length > 0) return `${objectBase}.catchall(${value})`;
|
|
1615
|
+
return `z.record(${patternKeySchema({
|
|
1616
|
+
patterns: patterns.map(([pattern]) => pattern),
|
|
1617
|
+
regexType: this.options.regexType
|
|
1618
|
+
})}, ${value})`;
|
|
1619
|
+
}
|
|
1620
|
+
return objectBase;
|
|
1621
|
+
})(),
|
|
1622
|
+
node
|
|
1623
|
+
});
|
|
1423
1624
|
},
|
|
1424
1625
|
array(node) {
|
|
1425
|
-
const base = `z.array(${mapSchemaItems(node, (item) => this.transform(item)).map(({ output }) => output).filter(Boolean).join(", ") || this.transform(kubb_kit.ast.factory.createSchema({ type:
|
|
1626
|
+
const base = `z.array(${mapSchemaItems(node, (item) => this.transform(item)).map(({ output }) => output).filter(Boolean).join(", ") || this.transform(kubb_kit.ast.factory.createSchema({ type: kubb_kit.ast.schemaTypes.unknown }))})${lengthConstraints({
|
|
1426
1627
|
...node,
|
|
1427
1628
|
regexType: this.options.regexType
|
|
1428
1629
|
})}`;
|
|
@@ -1435,7 +1636,7 @@ const printerZod = kubb_kit.ast.createPrinter((options) => {
|
|
|
1435
1636
|
const nodeMembers = node.members ?? [];
|
|
1436
1637
|
const isDiscriminated = !!node.discriminatorPropertyName && nodeMembers.every((m) => isObjectSchemaNode(m, cyclicSchemaNames));
|
|
1437
1638
|
const isXor = node.strategy === "one" && !isDiscriminated && this.options.oneOfType === "xor";
|
|
1438
|
-
const isStrict = node.strategy === "one" && !isXor;
|
|
1639
|
+
const isStrict = node.strategy === "one" && !isXor && !unionsWithSiblings.has(node);
|
|
1439
1640
|
const members = mapSchemaMembers(node, (memberNode) => this.transform(isStrict ? strictOneOfNode(memberNode) : memberNode)).map(({ schema, output }) => output && isStrict ? strictOneOfMember(output, schema, cyclicSchemaNames) : output).filter(Boolean);
|
|
1440
1641
|
if (members.length === 0) return "";
|
|
1441
1642
|
if (members.length === 1) return members[0];
|
|
@@ -1446,11 +1647,21 @@ const printerZod = kubb_kit.ast.createPrinter((options) => {
|
|
|
1446
1647
|
intersection(node) {
|
|
1447
1648
|
const members = node.members ?? [];
|
|
1448
1649
|
if (members.length === 0) return "";
|
|
1650
|
+
const hasSiblingProperties = members.some((member) => member.type === kubb_kit.ast.schemaTypes.object && member.properties.length > 0);
|
|
1651
|
+
const transform = (member) => {
|
|
1652
|
+
if (!hasSiblingProperties) return this.transform(member);
|
|
1653
|
+
unionsWithSiblings.add(member);
|
|
1654
|
+
try {
|
|
1655
|
+
return this.transform(member);
|
|
1656
|
+
} finally {
|
|
1657
|
+
unionsWithSiblings.delete(member);
|
|
1658
|
+
}
|
|
1659
|
+
};
|
|
1449
1660
|
const [first, ...rest] = members;
|
|
1450
1661
|
if (!first) return "";
|
|
1451
|
-
const firstBase =
|
|
1662
|
+
const firstBase = transform(first);
|
|
1452
1663
|
if (!firstBase) return "";
|
|
1453
|
-
if (rest.length > 0 && isObjectComposableIntersection(node, cyclicSchemaNames)) return
|
|
1664
|
+
if (rest.length > 0 && isObjectComposableIntersection(node, cyclicSchemaNames)) return preserveRequiredProperties(members).slice(1).reduce((acc, member) => `${acc}.extend(${buildZodObjectShape(this, member)})`, firstBase);
|
|
1454
1665
|
return rest.reduce((acc, member) => {
|
|
1455
1666
|
const constraint = getMemberConstraint({
|
|
1456
1667
|
member,
|
|
@@ -1459,7 +1670,7 @@ const printerZod = kubb_kit.ast.createPrinter((options) => {
|
|
|
1459
1670
|
numbers: numberConstraints
|
|
1460
1671
|
});
|
|
1461
1672
|
if (constraint) return acc + constraint;
|
|
1462
|
-
const transformed =
|
|
1673
|
+
const transformed = transform(member);
|
|
1463
1674
|
return transformed ? `${acc}.and(${transformed})` : acc;
|
|
1464
1675
|
}, firstBase);
|
|
1465
1676
|
}
|
|
@@ -1479,20 +1690,25 @@ const printerZod = kubb_kit.ast.createPrinter((options) => {
|
|
|
1479
1690
|
}
|
|
1480
1691
|
};
|
|
1481
1692
|
});
|
|
1482
|
-
|
|
1483
|
-
//#region src/printers/printerZodMini.ts
|
|
1693
|
+
// src/printers/printerZodMini.ts
|
|
1484
1694
|
/**
|
|
1485
1695
|
* Builds the `{ key: value, … }` shape for an object node with the functional `zod/mini` modifiers.
|
|
1486
1696
|
*/
|
|
1487
1697
|
function buildZodMiniObjectShape(ctx, node) {
|
|
1488
|
-
return buildObjectShape(ctx, node, ({ value, schema, required, meta }) =>
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1698
|
+
return buildObjectShape(ctx, node, ({ name, value, schema, required, meta, cyclic }) => {
|
|
1699
|
+
const body = applyMiniModifiers({
|
|
1700
|
+
value,
|
|
1701
|
+
schema,
|
|
1702
|
+
nullable: meta.nullable,
|
|
1703
|
+
optional: schema.optional || required === false,
|
|
1704
|
+
nullish: schema.nullish,
|
|
1705
|
+
defaultValue: meta.default
|
|
1706
|
+
});
|
|
1707
|
+
return cyclic ? lazyGetter({
|
|
1708
|
+
name,
|
|
1709
|
+
body
|
|
1710
|
+
}) : `${objectKey(name)}: ${body}`;
|
|
1711
|
+
});
|
|
1496
1712
|
}
|
|
1497
1713
|
/**
|
|
1498
1714
|
* Zod v4 Mini printer built with `definePrinter`.
|
|
@@ -1508,6 +1724,7 @@ function buildZodMiniObjectShape(ctx, node) {
|
|
|
1508
1724
|
*/
|
|
1509
1725
|
const printerZodMini = kubb_kit.ast.createPrinter((options) => {
|
|
1510
1726
|
const cyclicSchemaNames = options.cyclicSchemas;
|
|
1727
|
+
const unionsWithSiblings = /* @__PURE__ */ new WeakSet();
|
|
1511
1728
|
return {
|
|
1512
1729
|
name: "zod-mini",
|
|
1513
1730
|
options,
|
|
@@ -1580,7 +1797,7 @@ const printerZodMini = kubb_kit.ast.createPrinter((options) => {
|
|
|
1580
1797
|
enum(node) {
|
|
1581
1798
|
const nonNullValues = (node.namedEnumValues?.map((v) => v.value) ?? node.enumValues ?? []).filter((v) => v !== null);
|
|
1582
1799
|
if (node.namedEnumValues?.length) {
|
|
1583
|
-
const literals = nonNullValues.map((v) =>
|
|
1800
|
+
const literals = nonNullValues.map((v) => buildLiteral(v));
|
|
1584
1801
|
if (literals.length === 1) return literals[0];
|
|
1585
1802
|
return `z.union([${literals.join(", ")}])`;
|
|
1586
1803
|
}
|
|
@@ -1597,37 +1814,45 @@ const printerZodMini = kubb_kit.ast.createPrinter((options) => {
|
|
|
1597
1814
|
object(node) {
|
|
1598
1815
|
const entries = node.properties ?? [];
|
|
1599
1816
|
const patterns = node.patternProperties ? Object.entries(node.patternProperties) : [];
|
|
1600
|
-
const propertyNamesNode =
|
|
1817
|
+
const propertyNamesNode = node.propertyNames;
|
|
1601
1818
|
const propertyNamesKeySchema = propertyNamesNode ? this.transform(propertyNamesNode) : null;
|
|
1602
1819
|
const isStrict = node.additionalProperties === false && patterns.length === 0;
|
|
1603
1820
|
const isLoose = node.additionalProperties === true;
|
|
1604
1821
|
const objectBase = `${isStrict ? "z.strictObject" : isLoose ? "z.looseObject" : "z.object"}(${buildZodMiniObjectShape(this, node)})`;
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1822
|
+
return objectConstraints({
|
|
1823
|
+
value: (() => {
|
|
1824
|
+
const recordFn = isClosedKeySchema(propertyNamesNode) ? "z.partialRecord" : "z.record";
|
|
1825
|
+
if (node.additionalProperties && node.additionalProperties !== true) {
|
|
1826
|
+
const catchallType = this.transform(node.additionalProperties);
|
|
1827
|
+
if (entries.length === 0) return catchallType ? `${recordFn}(${propertyNamesKeySchema || "z.string()"}, ${catchallType})` : objectBase;
|
|
1828
|
+
return catchallType ? `z.catchall(${objectBase}, ${catchallType})` : objectBase;
|
|
1829
|
+
}
|
|
1830
|
+
if (entries.length === 0 && patterns.length === 0 && propertyNamesKeySchema && !isStrict) {
|
|
1831
|
+
const unknownType = this.transform(kubb_kit.ast.factory.createSchema({ type: kubb_kit.ast.schemaTypes.unknown }));
|
|
1832
|
+
return `${recordFn}(${propertyNamesKeySchema}, ${unknownType})`;
|
|
1833
|
+
}
|
|
1834
|
+
if (node.additionalProperties === true) return objectBase;
|
|
1835
|
+
if (isStrict) return objectBase;
|
|
1836
|
+
if (patterns.length > 0) {
|
|
1837
|
+
const values = patterns.map(([, valueSchema]) => {
|
|
1838
|
+
const valueType = this.transform(valueSchema) ?? this.transform(kubb_kit.ast.factory.createSchema({ type: kubb_kit.ast.schemaTypes.unknown }));
|
|
1839
|
+
return valueSchema.nullable ? `z.nullable(${valueType})` : valueType;
|
|
1840
|
+
});
|
|
1841
|
+
const distinct = [...new Set(values)];
|
|
1842
|
+
const value = distinct.length === 1 ? distinct[0] : `z.union([${distinct.join(", ")}])`;
|
|
1843
|
+
if (entries.length > 0) return `z.catchall(${objectBase}, ${value})`;
|
|
1844
|
+
return `z.record(${patternKeySchemaMini({
|
|
1845
|
+
patterns: patterns.map(([pattern]) => pattern),
|
|
1846
|
+
regexType: this.options.regexType
|
|
1847
|
+
})}, ${value})`;
|
|
1848
|
+
}
|
|
1849
|
+
return objectBase;
|
|
1850
|
+
})(),
|
|
1851
|
+
node
|
|
1852
|
+
});
|
|
1628
1853
|
},
|
|
1629
1854
|
array(node) {
|
|
1630
|
-
const base = `z.array(${mapSchemaItems(node, (item) => this.transform(item)).map(({ output }) => output).filter(Boolean).join(", ") || this.transform(kubb_kit.ast.factory.createSchema({ type:
|
|
1855
|
+
const base = `z.array(${mapSchemaItems(node, (item) => this.transform(item)).map(({ output }) => output).filter(Boolean).join(", ") || this.transform(kubb_kit.ast.factory.createSchema({ type: kubb_kit.ast.schemaTypes.unknown }))})${lengthChecksMini({
|
|
1631
1856
|
...node,
|
|
1632
1857
|
regexType: this.options.regexType
|
|
1633
1858
|
})}`;
|
|
@@ -1640,7 +1865,7 @@ const printerZodMini = kubb_kit.ast.createPrinter((options) => {
|
|
|
1640
1865
|
const nodeMembers = node.members ?? [];
|
|
1641
1866
|
const isDiscriminated = !!node.discriminatorPropertyName && nodeMembers.every((m) => isObjectSchemaNode(m, cyclicSchemaNames));
|
|
1642
1867
|
const isXor = node.strategy === "one" && !isDiscriminated && this.options.oneOfType === "xor";
|
|
1643
|
-
const isStrict = node.strategy === "one" && !isXor;
|
|
1868
|
+
const isStrict = node.strategy === "one" && !isXor && !unionsWithSiblings.has(node);
|
|
1644
1869
|
const members = mapSchemaMembers(node, (memberNode) => this.transform(isStrict ? strictOneOfNode(memberNode) : memberNode)).map(({ output }) => output).filter(Boolean);
|
|
1645
1870
|
if (members.length === 0) return "";
|
|
1646
1871
|
if (members.length === 1) return members[0];
|
|
@@ -1651,11 +1876,21 @@ const printerZodMini = kubb_kit.ast.createPrinter((options) => {
|
|
|
1651
1876
|
intersection(node) {
|
|
1652
1877
|
const members = node.members ?? [];
|
|
1653
1878
|
if (members.length === 0) return "";
|
|
1879
|
+
const hasSiblingProperties = members.some((member) => member.type === kubb_kit.ast.schemaTypes.object && member.properties.length > 0);
|
|
1880
|
+
const transform = (member) => {
|
|
1881
|
+
if (!hasSiblingProperties) return this.transform(member);
|
|
1882
|
+
unionsWithSiblings.add(member);
|
|
1883
|
+
try {
|
|
1884
|
+
return this.transform(member);
|
|
1885
|
+
} finally {
|
|
1886
|
+
unionsWithSiblings.delete(member);
|
|
1887
|
+
}
|
|
1888
|
+
};
|
|
1654
1889
|
const [first, ...rest] = members;
|
|
1655
1890
|
if (!first) return "";
|
|
1656
|
-
const firstBase =
|
|
1891
|
+
const firstBase = transform(first);
|
|
1657
1892
|
if (!firstBase) return "";
|
|
1658
|
-
if (rest.length > 0 && isObjectComposableIntersection(node, cyclicSchemaNames)) return
|
|
1893
|
+
if (rest.length > 0 && isObjectComposableIntersection(node, cyclicSchemaNames)) return preserveRequiredProperties(members).slice(1).reduce((acc, member) => `z.extend(${acc}, ${buildZodMiniObjectShape(this, member)})`, firstBase);
|
|
1659
1894
|
return rest.reduce((acc, member) => {
|
|
1660
1895
|
const constraint = getMemberConstraint({
|
|
1661
1896
|
member,
|
|
@@ -1664,7 +1899,7 @@ const printerZodMini = kubb_kit.ast.createPrinter((options) => {
|
|
|
1664
1899
|
numbers: numberChecksMini
|
|
1665
1900
|
});
|
|
1666
1901
|
if (constraint) return acc + constraint;
|
|
1667
|
-
const transformed =
|
|
1902
|
+
const transformed = transform(member);
|
|
1668
1903
|
return transformed ? `z.intersection(${acc}, ${transformed})` : acc;
|
|
1669
1904
|
}, firstBase);
|
|
1670
1905
|
}
|
|
@@ -1682,8 +1917,7 @@ const printerZodMini = kubb_kit.ast.createPrinter((options) => {
|
|
|
1682
1917
|
}
|
|
1683
1918
|
};
|
|
1684
1919
|
});
|
|
1685
|
-
|
|
1686
|
-
//#region src/generators/zodGenerator.tsx
|
|
1920
|
+
// src/generators/zodGenerator.tsx
|
|
1687
1921
|
/**
|
|
1688
1922
|
* The helper an inferred alias is printed with. `'codec'` reads a request (encode) schema from its
|
|
1689
1923
|
* input and a response (decode) schema from its output; `true` keeps `z.infer` for both.
|
|
@@ -2144,17 +2378,14 @@ const zodGenerator = (0, kubb_kit.defineGenerator)({
|
|
|
2144
2378
|
});
|
|
2145
2379
|
}
|
|
2146
2380
|
});
|
|
2147
|
-
|
|
2148
|
-
//#region kubb-extension.json
|
|
2381
|
+
// kubb-extension.json
|
|
2149
2382
|
var compatibility = {
|
|
2150
|
-
"kubb": ">=5.
|
|
2383
|
+
"kubb": ">=5.14.6",
|
|
2151
2384
|
"node": ">=22.22"
|
|
2152
2385
|
};
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
//#endregion
|
|
2157
|
-
//#region src/resolvers/resolverZod.ts
|
|
2386
|
+
// package.json
|
|
2387
|
+
var version = "5.7.3";
|
|
2388
|
+
// src/resolvers/resolverZod.ts
|
|
2158
2389
|
/**
|
|
2159
2390
|
* Default resolver used by `@kubb/plugin-zod`. Decides the names and file
|
|
2160
2391
|
* paths for every generated Zod schema. Schemas use camelCase with a
|
|
@@ -2200,15 +2431,22 @@ const resolverZod = (0, kubb_kit.createResolver)({
|
|
|
2200
2431
|
response: {
|
|
2201
2432
|
...createOperationResponseResolver(),
|
|
2202
2433
|
error(node) {
|
|
2203
|
-
|
|
2434
|
+
const name = this.name(`${node.operationId} Error`);
|
|
2435
|
+
return this.resolveName({
|
|
2436
|
+
key: operationKey(node, "response", "error"),
|
|
2437
|
+
name
|
|
2438
|
+
});
|
|
2204
2439
|
},
|
|
2205
2440
|
options(node) {
|
|
2206
|
-
|
|
2441
|
+
const name = this.schema.type(this.name(`${node.operationId} Options`));
|
|
2442
|
+
return this.resolveName({
|
|
2443
|
+
key: operationKey(node, "response", "options"),
|
|
2444
|
+
name
|
|
2445
|
+
});
|
|
2207
2446
|
}
|
|
2208
2447
|
}
|
|
2209
2448
|
});
|
|
2210
|
-
|
|
2211
|
-
//#region src/plugin.ts
|
|
2449
|
+
// src/plugin.ts
|
|
2212
2450
|
/**
|
|
2213
2451
|
* Canonical plugin name for `@kubb/plugin-zod`. Used for driver lookups and
|
|
2214
2452
|
* cross-plugin dependency references.
|
|
@@ -2274,7 +2512,6 @@ const pluginZod = (0, kubb_kit.defineExtension)({
|
|
|
2274
2512
|
};
|
|
2275
2513
|
}
|
|
2276
2514
|
});
|
|
2277
|
-
//#endregion
|
|
2278
2515
|
exports.default = pluginZod;
|
|
2279
2516
|
exports.pluginZod = pluginZod;
|
|
2280
2517
|
exports.pluginZodName = pluginZodName;
|