@kubb/plugin-zod 5.7.2 → 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 +425 -185
- 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 +425 -185
- 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
|
*/
|
|
@@ -833,11 +922,12 @@ function isClosedKeySchema(node) {
|
|
|
833
922
|
}
|
|
834
923
|
/**
|
|
835
924
|
* Whether the node is a plain inline object whose shape can be lifted into an `.extend({ … })`
|
|
836
|
-
* argument.
|
|
925
|
+
* argument. Property counts, a catchall, `patternProperties`, or a nullable/optional wrapper cannot, so those stay
|
|
837
926
|
* on `.and(…)`.
|
|
838
927
|
*/
|
|
839
928
|
function isPlainInlineObject(node) {
|
|
840
929
|
if (node.type !== "object") return false;
|
|
930
|
+
if (node.minProperties !== void 0 || node.maxProperties !== void 0) return false;
|
|
841
931
|
if (node.nullable || node.optional || node.nullish) return false;
|
|
842
932
|
const hasAdditionalProperties = node.additionalProperties !== void 0;
|
|
843
933
|
const hasPatternProperties = Boolean(node.patternProperties);
|
|
@@ -848,11 +938,12 @@ function isPlainInlineObject(node) {
|
|
|
848
938
|
* `z.discriminatedUnion` option. Covers object nodes, `$ref`s that resolve to (or are still
|
|
849
939
|
* unresolved) objects, single-member unions of an object, and object-composable `allOf`.
|
|
850
940
|
*
|
|
851
|
-
*
|
|
941
|
+
* Property counts render as a pipe. A ref into `cyclicSchemas` renders as `z.lazy(…)`.
|
|
852
942
|
*/
|
|
853
943
|
function isObjectSchemaNode(node, cyclicSchemas) {
|
|
854
944
|
if (node.nullable || node.optional || node.nullish) return false;
|
|
855
945
|
if (node.type === "object") {
|
|
946
|
+
if (node.minProperties !== void 0 || node.maxProperties !== void 0) return false;
|
|
856
947
|
const hasProperties = Boolean(node.properties?.length);
|
|
857
948
|
const hasTypedAdditionalProperties = Boolean(node.additionalProperties && node.additionalProperties !== true);
|
|
858
949
|
const hasPatternProperties = Boolean(node.patternProperties);
|
|
@@ -880,6 +971,49 @@ function isObjectComposableIntersection(node, cyclicSchemas) {
|
|
|
880
971
|
const [first, ...rest] = node.members ?? [];
|
|
881
972
|
return !!first && isObjectSchemaNode(first, cyclicSchemas) && rest.every(isPlainInlineObject);
|
|
882
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
|
+
}
|
|
883
1017
|
/**
|
|
884
1018
|
* Format a default value as a code-level literal.
|
|
885
1019
|
* Arrays and objects keep their contents as a JSON literal, primitives become their string
|
|
@@ -926,11 +1060,20 @@ function defaultLiteral(node, value) {
|
|
|
926
1060
|
*/
|
|
927
1061
|
function buildEnum(values) {
|
|
928
1062
|
if (values.every((v) => typeof v === "string")) return `z.enum([${values.map((v) => formatDefault(v)).join(", ")}])`;
|
|
929
|
-
const literals = values.map((
|
|
1063
|
+
const literals = values.map((value) => buildLiteral(value));
|
|
930
1064
|
if (literals.length === 1) return literals[0];
|
|
931
1065
|
return `z.union([${literals.join(", ")}])`;
|
|
932
1066
|
}
|
|
933
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
|
+
/**
|
|
934
1077
|
* Digit pattern for a `type: 'string'` schema that carries an integer `format`, the way ProtoJSON
|
|
935
1078
|
* encodes 64-bit integers. Returns `undefined` for every other format, and a `pattern` from the
|
|
936
1079
|
* spec takes precedence over this fallback.
|
|
@@ -1013,6 +1156,17 @@ function lengthChecksMini({ min, max, pattern, regexType }) {
|
|
|
1013
1156
|
return checks.length ? `.check(${checks.join(", ")})` : "";
|
|
1014
1157
|
}
|
|
1015
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
|
+
/**
|
|
1016
1170
|
* Apply nullable / optional / nullish modifiers, an optional `.describe()` call, and an
|
|
1017
1171
|
* optional `.meta({ examples })` call to a schema value string using the chainable Zod v4 API.
|
|
1018
1172
|
*/
|
|
@@ -1102,7 +1256,7 @@ function getMemberConstraint({ member, regexType, lengths, numbers }) {
|
|
|
1102
1256
|
/**
|
|
1103
1257
|
* Builds the `{ key: value, … }` shape shared by the `z.object(...)` and `.extend(...)` renderings.
|
|
1104
1258
|
*/
|
|
1105
|
-
function buildObjectShape(ctx, node,
|
|
1259
|
+
function buildObjectShape(ctx, node, renderProperty) {
|
|
1106
1260
|
const objectNode = kubb_kit.ast.narrowSchema(node, "object");
|
|
1107
1261
|
if (!objectNode) return "{}";
|
|
1108
1262
|
const isCyclic = (schema) => ctx.options.cyclicSchemas != null && (0, kubb_kit.containsCircularRef)(schema, { circularSchemas: ctx.options.cyclicSchemas });
|
|
@@ -1113,18 +1267,16 @@ function buildObjectShape(ctx, node, modify) {
|
|
|
1113
1267
|
const baseOutput = ctx.transform(schema) ?? ctx.transform(kubb_kit.ast.factory.createSchema({ type: "unknown" }));
|
|
1114
1268
|
if (hasSelfRef) ctx.options.cyclicSchemas = savedCyclicSchemas;
|
|
1115
1269
|
return baseOutput;
|
|
1116
|
-
}).map(({ name
|
|
1270
|
+
}).map(({ name, property, output: value }) => {
|
|
1117
1271
|
const { schema } = property;
|
|
1118
|
-
|
|
1119
|
-
|
|
1272
|
+
return renderProperty({
|
|
1273
|
+
name,
|
|
1274
|
+
value,
|
|
1120
1275
|
schema,
|
|
1121
1276
|
required: property.required,
|
|
1122
|
-
meta: (0, kubb_kit.syncSchemaRef)(schema)
|
|
1277
|
+
meta: (0, kubb_kit.syncSchemaRef)(schema),
|
|
1278
|
+
cyclic: isCyclic(schema)
|
|
1123
1279
|
});
|
|
1124
|
-
return isCyclic(schema) ? lazyGetter({
|
|
1125
|
-
name: propName,
|
|
1126
|
-
body: value
|
|
1127
|
-
}) : `${objectKey(propName)}: ${value}`;
|
|
1128
1280
|
}));
|
|
1129
1281
|
}
|
|
1130
1282
|
/**
|
|
@@ -1139,22 +1291,28 @@ function printWithOmit(ctx, node, modify, mini = false) {
|
|
|
1139
1291
|
if (!keysToOmit?.length || meta.primitive !== "object" || meta.type === "union" && meta.discriminatorPropertyName) return transformed;
|
|
1140
1292
|
const unwrap = omitUnwrapChain(node, mini ? "._zod.def.innerType" : ".unwrap()");
|
|
1141
1293
|
const mask = `{ ${keysToOmit.map((k) => `"${k}": true`).join(", ")} }`;
|
|
1142
|
-
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
|
+
};
|
|
1143
1302
|
const lazyMatch = transformed.match(/^z\.lazy\(\(\)\s*=>\s*(.+)\)$/);
|
|
1144
1303
|
if (lazyMatch) return `z.lazy(() => ${omit(lazyMatch[1])})`;
|
|
1145
1304
|
return omit(transformed);
|
|
1146
1305
|
})(), meta);
|
|
1147
1306
|
}
|
|
1148
|
-
|
|
1149
|
-
//#region src/printers/printerZod.ts
|
|
1307
|
+
// src/printers/printerZod.ts
|
|
1150
1308
|
function strictOneOfMember(member, node, cyclicSchemas) {
|
|
1151
|
-
if (node.type ===
|
|
1309
|
+
if (node.type === kubb_kit.ast.schemaTypes.ref) {
|
|
1152
1310
|
if (member.startsWith("z.lazy(")) return member;
|
|
1153
1311
|
const refName = kubb_kit.ast.resolveRefName(node);
|
|
1154
1312
|
if (refName && cyclicSchemas?.has(refName)) return member;
|
|
1155
1313
|
const schema = (0, kubb_kit.syncSchemaRef)(node);
|
|
1156
1314
|
if (schema.nullable || schema.optional || node.nullable || node.optional) return member;
|
|
1157
|
-
if (schema.type ===
|
|
1315
|
+
if (schema.type === kubb_kit.ast.schemaTypes.object && (schema.additionalProperties === void 0 || schema.additionalProperties === false)) return `${member}.strict()`;
|
|
1158
1316
|
}
|
|
1159
1317
|
return member;
|
|
1160
1318
|
}
|
|
@@ -1162,28 +1320,70 @@ function strictOneOfMember(member, node, cyclicSchemas) {
|
|
|
1162
1320
|
* Builds the `{ key: value, … }` shape for an object node with the chainable modifiers.
|
|
1163
1321
|
*/
|
|
1164
1322
|
function buildZodObjectShape(ctx, node) {
|
|
1165
|
-
return buildObjectShape(ctx, node, ({ value, schema, required, meta }) =>
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
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;
|
|
1175
1375
|
}
|
|
1176
1376
|
/**
|
|
1177
1377
|
* Types the direction probe skips. They delegate to their children rather than reading
|
|
1178
1378
|
* `direction` themselves, so {@link containsDirectionalNode} walks into the children instead.
|
|
1179
1379
|
*/
|
|
1180
1380
|
const CONTAINER_TYPES = /* @__PURE__ */ new Set([
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
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
|
|
1187
1387
|
]);
|
|
1188
1388
|
/**
|
|
1189
1389
|
* Runs the node's effective handler (a `printer.nodes` override, else the built-in) once per
|
|
@@ -1215,7 +1415,7 @@ function variesByDirection({ node, printerOptions }) {
|
|
|
1215
1415
|
*/
|
|
1216
1416
|
function containsDirectionalNode({ node, printerOptions, seen = /* @__PURE__ */ new Set() }) {
|
|
1217
1417
|
if (!node) return false;
|
|
1218
|
-
if (node.type ===
|
|
1418
|
+
if (node.type === kubb_kit.ast.schemaTypes.ref) {
|
|
1219
1419
|
if (!node.ref) return false;
|
|
1220
1420
|
const refName = (0, kubb_kit.extractRefName)(node.ref);
|
|
1221
1421
|
if (refName) {
|
|
@@ -1223,7 +1423,7 @@ function containsDirectionalNode({ node, printerOptions, seen = /* @__PURE__ */
|
|
|
1223
1423
|
seen.add(refName);
|
|
1224
1424
|
}
|
|
1225
1425
|
const resolved = (0, kubb_kit.syncSchemaRef)(node);
|
|
1226
|
-
if (resolved.type ===
|
|
1426
|
+
if (resolved.type === kubb_kit.ast.schemaTypes.ref) return false;
|
|
1227
1427
|
return containsDirectionalNode({
|
|
1228
1428
|
node: resolved,
|
|
1229
1429
|
printerOptions,
|
|
@@ -1239,7 +1439,7 @@ function containsDirectionalNode({ node, printerOptions, seen = /* @__PURE__ */
|
|
|
1239
1439
|
if ("items" in node && node.items) children.push(...node.items);
|
|
1240
1440
|
if ("members" in node && node.members) children.push(...node.members);
|
|
1241
1441
|
if ("additionalProperties" in node && node.additionalProperties && node.additionalProperties !== true) children.push(node.additionalProperties);
|
|
1242
|
-
const propertyNames = node.type ===
|
|
1442
|
+
const propertyNames = node.type === kubb_kit.ast.schemaTypes.object ? node.propertyNames : void 0;
|
|
1243
1443
|
if (propertyNames) children.push(propertyNames);
|
|
1244
1444
|
return children.some((child) => containsDirectionalNode({
|
|
1245
1445
|
node: child,
|
|
@@ -1251,7 +1451,7 @@ function containsDirectionalNode({ node, printerOptions, seen = /* @__PURE__ */
|
|
|
1251
1451
|
* Names of the `$ref` schemas the generator should route to their input (encode) variant.
|
|
1252
1452
|
*/
|
|
1253
1453
|
function collectDirectionalRefNames({ node, printerOptions }) {
|
|
1254
|
-
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({
|
|
1255
1455
|
node: n,
|
|
1256
1456
|
printerOptions
|
|
1257
1457
|
}) ? kubb_kit.ast.resolveRefName(n) ?? void 0 : void 0 });
|
|
@@ -1343,7 +1543,7 @@ const scalarNodes = {
|
|
|
1343
1543
|
enum(node) {
|
|
1344
1544
|
const nonNullValues = (node.namedEnumValues?.map((v) => v.value) ?? node.enumValues ?? []).filter((v) => v !== null);
|
|
1345
1545
|
if (node.namedEnumValues?.length) {
|
|
1346
|
-
const literals = nonNullValues.map((v) =>
|
|
1546
|
+
const literals = nonNullValues.map((v) => buildLiteral(v));
|
|
1347
1547
|
if (literals.length === 1) return literals[0];
|
|
1348
1548
|
return `z.union([${literals.join(", ")}])`;
|
|
1349
1549
|
}
|
|
@@ -1364,6 +1564,7 @@ const scalarNodes = {
|
|
|
1364
1564
|
*/
|
|
1365
1565
|
const printerZod = kubb_kit.ast.createPrinter((options) => {
|
|
1366
1566
|
const cyclicSchemaNames = options.cyclicSchemas;
|
|
1567
|
+
const unionsWithSiblings = /* @__PURE__ */ new WeakSet();
|
|
1367
1568
|
return {
|
|
1368
1569
|
name: "zod",
|
|
1369
1570
|
options,
|
|
@@ -1389,37 +1590,40 @@ const printerZod = kubb_kit.ast.createPrinter((options) => {
|
|
|
1389
1590
|
const isStrict = node.additionalProperties === false && patterns.length === 0;
|
|
1390
1591
|
const isLoose = node.additionalProperties === true;
|
|
1391
1592
|
const objectBase = `${isStrict ? "z.strictObject" : isLoose ? "z.looseObject" : "z.object"}(${buildZodObjectShape(this, node)})`;
|
|
1392
|
-
return (
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
const
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
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
|
+
});
|
|
1420
1624
|
},
|
|
1421
1625
|
array(node) {
|
|
1422
|
-
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({
|
|
1423
1627
|
...node,
|
|
1424
1628
|
regexType: this.options.regexType
|
|
1425
1629
|
})}`;
|
|
@@ -1432,7 +1636,7 @@ const printerZod = kubb_kit.ast.createPrinter((options) => {
|
|
|
1432
1636
|
const nodeMembers = node.members ?? [];
|
|
1433
1637
|
const isDiscriminated = !!node.discriminatorPropertyName && nodeMembers.every((m) => isObjectSchemaNode(m, cyclicSchemaNames));
|
|
1434
1638
|
const isXor = node.strategy === "one" && !isDiscriminated && this.options.oneOfType === "xor";
|
|
1435
|
-
const isStrict = node.strategy === "one" && !isXor;
|
|
1639
|
+
const isStrict = node.strategy === "one" && !isXor && !unionsWithSiblings.has(node);
|
|
1436
1640
|
const members = mapSchemaMembers(node, (memberNode) => this.transform(isStrict ? strictOneOfNode(memberNode) : memberNode)).map(({ schema, output }) => output && isStrict ? strictOneOfMember(output, schema, cyclicSchemaNames) : output).filter(Boolean);
|
|
1437
1641
|
if (members.length === 0) return "";
|
|
1438
1642
|
if (members.length === 1) return members[0];
|
|
@@ -1443,11 +1647,21 @@ const printerZod = kubb_kit.ast.createPrinter((options) => {
|
|
|
1443
1647
|
intersection(node) {
|
|
1444
1648
|
const members = node.members ?? [];
|
|
1445
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
|
+
};
|
|
1446
1660
|
const [first, ...rest] = members;
|
|
1447
1661
|
if (!first) return "";
|
|
1448
|
-
const firstBase =
|
|
1662
|
+
const firstBase = transform(first);
|
|
1449
1663
|
if (!firstBase) return "";
|
|
1450
|
-
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);
|
|
1451
1665
|
return rest.reduce((acc, member) => {
|
|
1452
1666
|
const constraint = getMemberConstraint({
|
|
1453
1667
|
member,
|
|
@@ -1456,7 +1670,7 @@ const printerZod = kubb_kit.ast.createPrinter((options) => {
|
|
|
1456
1670
|
numbers: numberConstraints
|
|
1457
1671
|
});
|
|
1458
1672
|
if (constraint) return acc + constraint;
|
|
1459
|
-
const transformed =
|
|
1673
|
+
const transformed = transform(member);
|
|
1460
1674
|
return transformed ? `${acc}.and(${transformed})` : acc;
|
|
1461
1675
|
}, firstBase);
|
|
1462
1676
|
}
|
|
@@ -1476,20 +1690,25 @@ const printerZod = kubb_kit.ast.createPrinter((options) => {
|
|
|
1476
1690
|
}
|
|
1477
1691
|
};
|
|
1478
1692
|
});
|
|
1479
|
-
|
|
1480
|
-
//#region src/printers/printerZodMini.ts
|
|
1693
|
+
// src/printers/printerZodMini.ts
|
|
1481
1694
|
/**
|
|
1482
1695
|
* Builds the `{ key: value, … }` shape for an object node with the functional `zod/mini` modifiers.
|
|
1483
1696
|
*/
|
|
1484
1697
|
function buildZodMiniObjectShape(ctx, node) {
|
|
1485
|
-
return buildObjectShape(ctx, node, ({ value, schema, required, meta }) =>
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
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
|
+
});
|
|
1493
1712
|
}
|
|
1494
1713
|
/**
|
|
1495
1714
|
* Zod v4 Mini printer built with `definePrinter`.
|
|
@@ -1505,6 +1724,7 @@ function buildZodMiniObjectShape(ctx, node) {
|
|
|
1505
1724
|
*/
|
|
1506
1725
|
const printerZodMini = kubb_kit.ast.createPrinter((options) => {
|
|
1507
1726
|
const cyclicSchemaNames = options.cyclicSchemas;
|
|
1727
|
+
const unionsWithSiblings = /* @__PURE__ */ new WeakSet();
|
|
1508
1728
|
return {
|
|
1509
1729
|
name: "zod-mini",
|
|
1510
1730
|
options,
|
|
@@ -1577,7 +1797,7 @@ const printerZodMini = kubb_kit.ast.createPrinter((options) => {
|
|
|
1577
1797
|
enum(node) {
|
|
1578
1798
|
const nonNullValues = (node.namedEnumValues?.map((v) => v.value) ?? node.enumValues ?? []).filter((v) => v !== null);
|
|
1579
1799
|
if (node.namedEnumValues?.length) {
|
|
1580
|
-
const literals = nonNullValues.map((v) =>
|
|
1800
|
+
const literals = nonNullValues.map((v) => buildLiteral(v));
|
|
1581
1801
|
if (literals.length === 1) return literals[0];
|
|
1582
1802
|
return `z.union([${literals.join(", ")}])`;
|
|
1583
1803
|
}
|
|
@@ -1599,32 +1819,40 @@ const printerZodMini = kubb_kit.ast.createPrinter((options) => {
|
|
|
1599
1819
|
const isStrict = node.additionalProperties === false && patterns.length === 0;
|
|
1600
1820
|
const isLoose = node.additionalProperties === true;
|
|
1601
1821
|
const objectBase = `${isStrict ? "z.strictObject" : isLoose ? "z.looseObject" : "z.object"}(${buildZodMiniObjectShape(this, node)})`;
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
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
|
+
});
|
|
1625
1853
|
},
|
|
1626
1854
|
array(node) {
|
|
1627
|
-
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({
|
|
1628
1856
|
...node,
|
|
1629
1857
|
regexType: this.options.regexType
|
|
1630
1858
|
})}`;
|
|
@@ -1637,7 +1865,7 @@ const printerZodMini = kubb_kit.ast.createPrinter((options) => {
|
|
|
1637
1865
|
const nodeMembers = node.members ?? [];
|
|
1638
1866
|
const isDiscriminated = !!node.discriminatorPropertyName && nodeMembers.every((m) => isObjectSchemaNode(m, cyclicSchemaNames));
|
|
1639
1867
|
const isXor = node.strategy === "one" && !isDiscriminated && this.options.oneOfType === "xor";
|
|
1640
|
-
const isStrict = node.strategy === "one" && !isXor;
|
|
1868
|
+
const isStrict = node.strategy === "one" && !isXor && !unionsWithSiblings.has(node);
|
|
1641
1869
|
const members = mapSchemaMembers(node, (memberNode) => this.transform(isStrict ? strictOneOfNode(memberNode) : memberNode)).map(({ output }) => output).filter(Boolean);
|
|
1642
1870
|
if (members.length === 0) return "";
|
|
1643
1871
|
if (members.length === 1) return members[0];
|
|
@@ -1648,11 +1876,21 @@ const printerZodMini = kubb_kit.ast.createPrinter((options) => {
|
|
|
1648
1876
|
intersection(node) {
|
|
1649
1877
|
const members = node.members ?? [];
|
|
1650
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
|
+
};
|
|
1651
1889
|
const [first, ...rest] = members;
|
|
1652
1890
|
if (!first) return "";
|
|
1653
|
-
const firstBase =
|
|
1891
|
+
const firstBase = transform(first);
|
|
1654
1892
|
if (!firstBase) return "";
|
|
1655
|
-
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);
|
|
1656
1894
|
return rest.reduce((acc, member) => {
|
|
1657
1895
|
const constraint = getMemberConstraint({
|
|
1658
1896
|
member,
|
|
@@ -1661,7 +1899,7 @@ const printerZodMini = kubb_kit.ast.createPrinter((options) => {
|
|
|
1661
1899
|
numbers: numberChecksMini
|
|
1662
1900
|
});
|
|
1663
1901
|
if (constraint) return acc + constraint;
|
|
1664
|
-
const transformed =
|
|
1902
|
+
const transformed = transform(member);
|
|
1665
1903
|
return transformed ? `z.intersection(${acc}, ${transformed})` : acc;
|
|
1666
1904
|
}, firstBase);
|
|
1667
1905
|
}
|
|
@@ -1679,8 +1917,7 @@ const printerZodMini = kubb_kit.ast.createPrinter((options) => {
|
|
|
1679
1917
|
}
|
|
1680
1918
|
};
|
|
1681
1919
|
});
|
|
1682
|
-
|
|
1683
|
-
//#region src/generators/zodGenerator.tsx
|
|
1920
|
+
// src/generators/zodGenerator.tsx
|
|
1684
1921
|
/**
|
|
1685
1922
|
* The helper an inferred alias is printed with. `'codec'` reads a request (encode) schema from its
|
|
1686
1923
|
* input and a response (decode) schema from its output; `true` keeps `z.infer` for both.
|
|
@@ -2141,17 +2378,14 @@ const zodGenerator = (0, kubb_kit.defineGenerator)({
|
|
|
2141
2378
|
});
|
|
2142
2379
|
}
|
|
2143
2380
|
});
|
|
2144
|
-
|
|
2145
|
-
//#region kubb-extension.json
|
|
2381
|
+
// kubb-extension.json
|
|
2146
2382
|
var compatibility = {
|
|
2147
|
-
"kubb": ">=5.
|
|
2383
|
+
"kubb": ">=5.14.6",
|
|
2148
2384
|
"node": ">=22.22"
|
|
2149
2385
|
};
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
//#endregion
|
|
2154
|
-
//#region src/resolvers/resolverZod.ts
|
|
2386
|
+
// package.json
|
|
2387
|
+
var version = "5.7.3";
|
|
2388
|
+
// src/resolvers/resolverZod.ts
|
|
2155
2389
|
/**
|
|
2156
2390
|
* Default resolver used by `@kubb/plugin-zod`. Decides the names and file
|
|
2157
2391
|
* paths for every generated Zod schema. Schemas use camelCase with a
|
|
@@ -2197,15 +2431,22 @@ const resolverZod = (0, kubb_kit.createResolver)({
|
|
|
2197
2431
|
response: {
|
|
2198
2432
|
...createOperationResponseResolver(),
|
|
2199
2433
|
error(node) {
|
|
2200
|
-
|
|
2434
|
+
const name = this.name(`${node.operationId} Error`);
|
|
2435
|
+
return this.resolveName({
|
|
2436
|
+
key: operationKey(node, "response", "error"),
|
|
2437
|
+
name
|
|
2438
|
+
});
|
|
2201
2439
|
},
|
|
2202
2440
|
options(node) {
|
|
2203
|
-
|
|
2441
|
+
const name = this.schema.type(this.name(`${node.operationId} Options`));
|
|
2442
|
+
return this.resolveName({
|
|
2443
|
+
key: operationKey(node, "response", "options"),
|
|
2444
|
+
name
|
|
2445
|
+
});
|
|
2204
2446
|
}
|
|
2205
2447
|
}
|
|
2206
2448
|
});
|
|
2207
|
-
|
|
2208
|
-
//#region src/plugin.ts
|
|
2449
|
+
// src/plugin.ts
|
|
2209
2450
|
/**
|
|
2210
2451
|
* Canonical plugin name for `@kubb/plugin-zod`. Used for driver lookups and
|
|
2211
2452
|
* cross-plugin dependency references.
|
|
@@ -2271,7 +2512,6 @@ const pluginZod = (0, kubb_kit.defineExtension)({
|
|
|
2271
2512
|
};
|
|
2272
2513
|
}
|
|
2273
2514
|
});
|
|
2274
|
-
//#endregion
|
|
2275
2515
|
exports.default = pluginZod;
|
|
2276
2516
|
exports.pluginZod = pluginZod;
|
|
2277
2517
|
exports.pluginZodName = pluginZodName;
|