@kubb/plugin-zod 5.0.0-alpha.23 → 5.0.0-alpha.25
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 +1673 -88
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +317 -2
- package/dist/index.js +1646 -88
- package/dist/index.js.map +1 -1
- package/package.json +5 -33
- package/src/components/Operations.tsx +22 -15
- package/src/components/Zod.tsx +18 -118
- package/src/components/ZodMini.tsx +41 -0
- package/src/constants.ts +5 -0
- package/src/generators/zodGenerator.tsx +165 -158
- package/src/generators/zodGeneratorLegacy.tsx +401 -0
- package/src/index.ts +11 -1
- package/src/plugin.ts +105 -129
- package/src/presets.ts +25 -0
- package/src/printers/printerZod.ts +271 -0
- package/src/printers/printerZodMini.ts +246 -0
- package/src/resolvers/resolverZod.ts +71 -0
- package/src/resolvers/resolverZodLegacy.ts +60 -0
- package/src/types.ts +121 -92
- package/src/utils.ts +248 -0
- package/dist/components-DW4Q2yVq.js +0 -868
- package/dist/components-DW4Q2yVq.js.map +0 -1
- package/dist/components-qFUGs0vU.cjs +0 -916
- package/dist/components-qFUGs0vU.cjs.map +0 -1
- package/dist/components.cjs +0 -4
- package/dist/components.d.ts +0 -56
- package/dist/components.js +0 -2
- package/dist/generators-C9BCTLXg.cjs +0 -301
- package/dist/generators-C9BCTLXg.cjs.map +0 -1
- package/dist/generators-maqx12yN.js +0 -290
- package/dist/generators-maqx12yN.js.map +0 -1
- package/dist/generators.cjs +0 -4
- package/dist/generators.d.ts +0 -12
- package/dist/generators.js +0 -2
- package/dist/templates/ToZod.source.cjs +0 -7
- package/dist/templates/ToZod.source.cjs.map +0 -1
- package/dist/templates/ToZod.source.d.ts +0 -7
- package/dist/templates/ToZod.source.js +0 -6
- package/dist/templates/ToZod.source.js.map +0 -1
- package/dist/types-CClg-ikj.d.ts +0 -172
- package/src/components/index.ts +0 -2
- package/src/generators/index.ts +0 -2
- package/src/generators/operationsGenerator.tsx +0 -50
- package/src/parser.ts +0 -952
- package/src/templates/ToZod.source.ts +0 -4
- package/templates/ToZod.ts +0 -61
package/dist/index.cjs
CHANGED
|
@@ -1,12 +1,32 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
//#region \0rolldown/runtime.js
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
11
|
+
key = keys[i];
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
13
|
+
get: ((k) => from[k]).bind(null, key),
|
|
14
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
20
|
+
value: mod,
|
|
21
|
+
enumerable: true
|
|
22
|
+
}) : target, mod));
|
|
23
|
+
//#endregion
|
|
5
24
|
let node_path = require("node:path");
|
|
6
|
-
node_path =
|
|
25
|
+
node_path = __toESM(node_path);
|
|
26
|
+
let _kubb_ast = require("@kubb/ast");
|
|
7
27
|
let _kubb_core = require("@kubb/core");
|
|
8
|
-
let
|
|
9
|
-
let
|
|
28
|
+
let _kubb_react_fabric = require("@kubb/react-fabric");
|
|
29
|
+
let _kubb_react_fabric_jsx_runtime = require("@kubb/react-fabric/jsx-runtime");
|
|
10
30
|
//#region ../../internals/utils/src/casing.ts
|
|
11
31
|
/**
|
|
12
32
|
* Shared implementation for camelCase and PascalCase conversion.
|
|
@@ -65,105 +85,1664 @@ function pascalCase(text, { isFile, prefix = "", suffix = "" } = {}) {
|
|
|
65
85
|
return toCamelOrPascal(`${prefix} ${text} ${suffix}`, true);
|
|
66
86
|
}
|
|
67
87
|
//#endregion
|
|
88
|
+
//#region ../../internals/utils/src/string.ts
|
|
89
|
+
/**
|
|
90
|
+
* Strips a single matching pair of `"..."`, `'...'`, or `` `...` `` from both ends of `text`.
|
|
91
|
+
* Returns the string unchanged when no balanced quote pair is found.
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* trimQuotes('"hello"') // 'hello'
|
|
95
|
+
* trimQuotes('hello') // 'hello'
|
|
96
|
+
*/
|
|
97
|
+
function trimQuotes(text) {
|
|
98
|
+
if (text.length >= 2) {
|
|
99
|
+
const first = text[0];
|
|
100
|
+
const last = text[text.length - 1];
|
|
101
|
+
if (first === "\"" && last === "\"" || first === "'" && last === "'" || first === "`" && last === "`") return text.slice(1, -1);
|
|
102
|
+
}
|
|
103
|
+
return text;
|
|
104
|
+
}
|
|
105
|
+
//#endregion
|
|
106
|
+
//#region ../../internals/utils/src/object.ts
|
|
107
|
+
/**
|
|
108
|
+
* Serializes a primitive value to a JSON string literal, stripping any surrounding quote characters first.
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* stringify('hello') // '"hello"'
|
|
112
|
+
* stringify('"hello"') // '"hello"'
|
|
113
|
+
*/
|
|
114
|
+
function stringify(value) {
|
|
115
|
+
if (value === void 0 || value === null) return "\"\"";
|
|
116
|
+
return JSON.stringify(trimQuotes(value.toString()));
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Converts a plain object into a multiline key-value string suitable for embedding in generated code.
|
|
120
|
+
* Nested objects are recursively stringified with indentation.
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* stringifyObject({ foo: 'bar', nested: { a: 1 } })
|
|
124
|
+
* // 'foo: bar,\nnested: {\n a: 1\n }'
|
|
125
|
+
*/
|
|
126
|
+
function stringifyObject(value) {
|
|
127
|
+
return Object.entries(value).map(([key, val]) => {
|
|
128
|
+
if (val !== null && typeof val === "object") return `${key}: {\n ${stringifyObject(val)}\n }`;
|
|
129
|
+
return `${key}: ${val}`;
|
|
130
|
+
}).filter(Boolean).join(",\n");
|
|
131
|
+
}
|
|
132
|
+
//#endregion
|
|
133
|
+
//#region ../../internals/utils/src/regexp.ts
|
|
134
|
+
/**
|
|
135
|
+
* Converts a pattern string into a `new RegExp(...)` constructor call or a regex literal string.
|
|
136
|
+
* Inline flags expressed as `^(?im)` prefixes are extracted and applied to the resulting expression.
|
|
137
|
+
* Pass `null` as the second argument to emit a `/pattern/flags` literal instead.
|
|
138
|
+
*
|
|
139
|
+
* @example
|
|
140
|
+
* toRegExpString('^(?im)foo') // → 'new RegExp("foo", "im")'
|
|
141
|
+
* toRegExpString('^(?im)foo', null) // → '/foo/im'
|
|
142
|
+
*/
|
|
143
|
+
function toRegExpString(text, func = "RegExp") {
|
|
144
|
+
const raw = trimQuotes(text);
|
|
145
|
+
const match = raw.match(/^\^(\(\?([igmsuy]+)\))/i);
|
|
146
|
+
const replacementTarget = match?.[1] ?? "";
|
|
147
|
+
const matchedFlags = match?.[2];
|
|
148
|
+
const cleaned = raw.replace(/^\\?\//, "").replace(/\\?\/$/, "").replace(replacementTarget, "");
|
|
149
|
+
const { source, flags } = new RegExp(cleaned, matchedFlags);
|
|
150
|
+
if (func === null) return `/${source}/${flags}`;
|
|
151
|
+
return `new ${func}(${JSON.stringify(source)}${flags ? `, ${JSON.stringify(flags)}` : ""})`;
|
|
152
|
+
}
|
|
153
|
+
//#endregion
|
|
154
|
+
//#region src/components/Operations.tsx
|
|
155
|
+
function Operations({ name, operations }) {
|
|
156
|
+
const operationsJSON = operations.reduce((prev, acc) => {
|
|
157
|
+
prev[`"${acc.node.operationId}"`] = acc.data;
|
|
158
|
+
return prev;
|
|
159
|
+
}, {});
|
|
160
|
+
const pathsJSON = operations.reduce((prev, acc) => {
|
|
161
|
+
prev[`"${acc.node.path}"`] = {
|
|
162
|
+
...prev[`"${acc.node.path}"`] ?? {},
|
|
163
|
+
[acc.node.method]: `operations["${acc.node.operationId}"]`
|
|
164
|
+
};
|
|
165
|
+
return prev;
|
|
166
|
+
}, {});
|
|
167
|
+
return /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsxs)(_kubb_react_fabric_jsx_runtime.Fragment, { children: [
|
|
168
|
+
/* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(_kubb_react_fabric.File.Source, {
|
|
169
|
+
name: "OperationSchema",
|
|
170
|
+
isExportable: true,
|
|
171
|
+
isIndexable: true,
|
|
172
|
+
children: /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(_kubb_react_fabric.Type, {
|
|
173
|
+
name: "OperationSchema",
|
|
174
|
+
export: true,
|
|
175
|
+
children: `{
|
|
176
|
+
readonly request: z.ZodTypeAny | undefined;
|
|
177
|
+
readonly parameters: {
|
|
178
|
+
readonly path: z.ZodTypeAny | undefined;
|
|
179
|
+
readonly query: z.ZodTypeAny | undefined;
|
|
180
|
+
readonly header: z.ZodTypeAny | undefined;
|
|
181
|
+
};
|
|
182
|
+
readonly responses: {
|
|
183
|
+
readonly [status: number]: z.ZodTypeAny;
|
|
184
|
+
readonly default: z.ZodTypeAny;
|
|
185
|
+
};
|
|
186
|
+
readonly errors: {
|
|
187
|
+
readonly [status: number]: z.ZodTypeAny;
|
|
188
|
+
};
|
|
189
|
+
}`
|
|
190
|
+
})
|
|
191
|
+
}),
|
|
192
|
+
/* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(_kubb_react_fabric.File.Source, {
|
|
193
|
+
name: "OperationsMap",
|
|
194
|
+
isExportable: true,
|
|
195
|
+
isIndexable: true,
|
|
196
|
+
children: /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(_kubb_react_fabric.Type, {
|
|
197
|
+
name: "OperationsMap",
|
|
198
|
+
export: true,
|
|
199
|
+
children: "Record<string, OperationSchema>"
|
|
200
|
+
})
|
|
201
|
+
}),
|
|
202
|
+
/* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(_kubb_react_fabric.File.Source, {
|
|
203
|
+
name,
|
|
204
|
+
isExportable: true,
|
|
205
|
+
isIndexable: true,
|
|
206
|
+
children: /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(_kubb_react_fabric.Const, {
|
|
207
|
+
export: true,
|
|
208
|
+
name,
|
|
209
|
+
asConst: true,
|
|
210
|
+
children: `{${stringifyObject(operationsJSON)}}`
|
|
211
|
+
})
|
|
212
|
+
}),
|
|
213
|
+
/* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(_kubb_react_fabric.File.Source, {
|
|
214
|
+
name: "paths",
|
|
215
|
+
isExportable: true,
|
|
216
|
+
isIndexable: true,
|
|
217
|
+
children: /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(_kubb_react_fabric.Const, {
|
|
218
|
+
export: true,
|
|
219
|
+
name: "paths",
|
|
220
|
+
asConst: true,
|
|
221
|
+
children: `{${stringifyObject(pathsJSON)}}`
|
|
222
|
+
})
|
|
223
|
+
})
|
|
224
|
+
] });
|
|
225
|
+
}
|
|
226
|
+
//#endregion
|
|
227
|
+
//#region src/utils.ts
|
|
228
|
+
/**
|
|
229
|
+
* Returns `true` when the given coercion option enables coercion for the specified type.
|
|
230
|
+
*/
|
|
231
|
+
function shouldCoerce(coercion, type) {
|
|
232
|
+
if (coercion === void 0 || coercion === false) return false;
|
|
233
|
+
if (coercion === true) return true;
|
|
234
|
+
return !!coercion[type];
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Collects all resolved schema names for an operation's parameters and responses
|
|
238
|
+
* into a single lookup object, useful for building imports and type references.
|
|
239
|
+
*/
|
|
240
|
+
function buildSchemaNames(node, { params, resolver }) {
|
|
241
|
+
const pathParam = params.find((p) => p.in === "path");
|
|
242
|
+
const queryParam = params.find((p) => p.in === "query");
|
|
243
|
+
const headerParam = params.find((p) => p.in === "header");
|
|
244
|
+
const responses = {};
|
|
245
|
+
const errors = {};
|
|
246
|
+
for (const res of node.responses) {
|
|
247
|
+
const name = resolver.resolveResponseStatusName(node, res.statusCode);
|
|
248
|
+
const statusNum = Number(res.statusCode);
|
|
249
|
+
if (!Number.isNaN(statusNum)) {
|
|
250
|
+
responses[statusNum] = name;
|
|
251
|
+
if (statusNum >= 400) errors[statusNum] = name;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
responses["default"] = resolver.resolveResponseName(node);
|
|
255
|
+
return {
|
|
256
|
+
request: node.requestBody?.schema ? resolver.resolveDataName(node) : void 0,
|
|
257
|
+
parameters: {
|
|
258
|
+
path: pathParam ? resolver.resolvePathParamsName(node, pathParam) : void 0,
|
|
259
|
+
query: queryParam ? resolver.resolveQueryParamsName(node, queryParam) : void 0,
|
|
260
|
+
header: headerParam ? resolver.resolveHeaderParamsName(node, headerParam) : void 0
|
|
261
|
+
},
|
|
262
|
+
responses,
|
|
263
|
+
errors
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Format a default value as a code-level literal.
|
|
268
|
+
* Objects become `{}`, primitives become their string representation, strings are quoted.
|
|
269
|
+
*/
|
|
270
|
+
function formatDefault(value) {
|
|
271
|
+
if (typeof value === "string") return stringify(value);
|
|
272
|
+
if (typeof value === "object" && value !== null) return "{}";
|
|
273
|
+
return String(value ?? "");
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Format a primitive enum/literal value.
|
|
277
|
+
* Strings are quoted; numbers and booleans are emitted raw.
|
|
278
|
+
*/
|
|
279
|
+
function formatLiteral(v) {
|
|
280
|
+
if (typeof v === "string") return stringify(v);
|
|
281
|
+
return String(v);
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Build `.min()` / `.max()` / `.gt()` / `.lt()` constraint chains for numbers
|
|
285
|
+
* using the standard chainable Zod v4 API.
|
|
286
|
+
*/
|
|
287
|
+
function numberConstraints({ min, max, exclusiveMinimum, exclusiveMaximum, multipleOf }) {
|
|
288
|
+
return [
|
|
289
|
+
min !== void 0 ? `.min(${min})` : "",
|
|
290
|
+
max !== void 0 ? `.max(${max})` : "",
|
|
291
|
+
exclusiveMinimum !== void 0 ? `.gt(${exclusiveMinimum})` : "",
|
|
292
|
+
exclusiveMaximum !== void 0 ? `.lt(${exclusiveMaximum})` : "",
|
|
293
|
+
multipleOf !== void 0 ? `.multipleOf(${multipleOf})` : ""
|
|
294
|
+
].join("");
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Build `.min()` / `.max()` / `.regex()` chains for strings/arrays
|
|
298
|
+
* using the standard chainable Zod v4 API.
|
|
299
|
+
*/
|
|
300
|
+
function lengthConstraints({ min, max, pattern }) {
|
|
301
|
+
return [
|
|
302
|
+
min !== void 0 ? `.min(${min})` : "",
|
|
303
|
+
max !== void 0 ? `.max(${max})` : "",
|
|
304
|
+
pattern !== void 0 ? `.regex(${toRegExpString(pattern, null)})` : ""
|
|
305
|
+
].join("");
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Build `.check(z.minimum(), z.maximum())` for `zod/mini` numeric constraints.
|
|
309
|
+
*/
|
|
310
|
+
function numberChecksMini({ min, max, exclusiveMinimum, exclusiveMaximum, multipleOf }) {
|
|
311
|
+
const checks = [];
|
|
312
|
+
if (min !== void 0) checks.push(`z.minimum(${min})`);
|
|
313
|
+
if (max !== void 0) checks.push(`z.maximum(${max})`);
|
|
314
|
+
if (exclusiveMinimum !== void 0) checks.push(`z.minimum(${exclusiveMinimum}, { exclusive: true })`);
|
|
315
|
+
if (exclusiveMaximum !== void 0) checks.push(`z.maximum(${exclusiveMaximum}, { exclusive: true })`);
|
|
316
|
+
if (multipleOf !== void 0) checks.push(`z.multipleOf(${multipleOf})`);
|
|
317
|
+
return checks.length ? `.check(${checks.join(", ")})` : "";
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Build `.check(z.minLength(), z.maxLength(), z.regex())` for `zod/mini` length constraints.
|
|
321
|
+
*/
|
|
322
|
+
function lengthChecksMini({ min, max, pattern }) {
|
|
323
|
+
const checks = [];
|
|
324
|
+
if (min !== void 0) checks.push(`z.minLength(${min})`);
|
|
325
|
+
if (max !== void 0) checks.push(`z.maxLength(${max})`);
|
|
326
|
+
if (pattern !== void 0) checks.push(`z.regex(${toRegExpString(pattern, null)})`);
|
|
327
|
+
return checks.length ? `.check(${checks.join(", ")})` : "";
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Apply nullable / optional / nullish modifiers and an optional `.describe()` call
|
|
331
|
+
* to a schema value string using the chainable Zod v4 API.
|
|
332
|
+
*/
|
|
333
|
+
function applyModifiers({ value, nullable, optional, nullish, defaultValue, description }) {
|
|
334
|
+
let result = value;
|
|
335
|
+
if (nullish || nullable && optional) result = `${result}.nullish()`;
|
|
336
|
+
else if (optional) result = `${result}.optional()`;
|
|
337
|
+
else if (nullable) result = `${result}.nullable()`;
|
|
338
|
+
if (defaultValue !== void 0) result = `${result}.default(${formatDefault(defaultValue)})`;
|
|
339
|
+
if (description) result = `${result}.describe(${stringify(description)})`;
|
|
340
|
+
return result;
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Apply nullable / optional / nullish modifiers using the functional `zod/mini` API
|
|
344
|
+
* (`z.nullable()`, `z.optional()`, `z.nullish()`).
|
|
345
|
+
*/
|
|
346
|
+
function applyMiniModifiers({ value, nullable, optional, nullish, defaultValue }) {
|
|
347
|
+
let result = value;
|
|
348
|
+
if (nullish) result = `z.nullish(${result})`;
|
|
349
|
+
else {
|
|
350
|
+
if (nullable) result = `z.nullable(${result})`;
|
|
351
|
+
if (optional) result = `z.optional(${result})`;
|
|
352
|
+
}
|
|
353
|
+
if (defaultValue !== void 0) result = `z._default(${result}, ${formatDefault(defaultValue)})`;
|
|
354
|
+
return result;
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Returns true when the schema tree contains a self-referential `$ref`
|
|
358
|
+
* whose resolved name matches `schemaName`.
|
|
359
|
+
*
|
|
360
|
+
* A `visited` set prevents infinite recursion on circular schema graphs.
|
|
361
|
+
*/
|
|
362
|
+
function containsSelfRef(node, { schemaName, resolver, visited = /* @__PURE__ */ new Set() }) {
|
|
363
|
+
if (visited.has(node)) return false;
|
|
364
|
+
visited.add(node);
|
|
365
|
+
if (node.type === "ref" && node.ref) {
|
|
366
|
+
const rawName = (0, _kubb_ast.extractRefName)(node.ref) ?? node.name;
|
|
367
|
+
return (rawName ? resolver?.default(rawName, "function") ?? rawName : node.name) === schemaName;
|
|
368
|
+
}
|
|
369
|
+
if (node.type === "object") {
|
|
370
|
+
if (node.properties?.some((p) => containsSelfRef(p.schema, {
|
|
371
|
+
schemaName,
|
|
372
|
+
resolver,
|
|
373
|
+
visited
|
|
374
|
+
}))) return true;
|
|
375
|
+
if (node.additionalProperties && node.additionalProperties !== true) return containsSelfRef(node.additionalProperties, {
|
|
376
|
+
schemaName,
|
|
377
|
+
resolver,
|
|
378
|
+
visited
|
|
379
|
+
});
|
|
380
|
+
return false;
|
|
381
|
+
}
|
|
382
|
+
if (node.type === "array" || node.type === "tuple") return node.items?.some((item) => containsSelfRef(item, {
|
|
383
|
+
schemaName,
|
|
384
|
+
resolver,
|
|
385
|
+
visited
|
|
386
|
+
})) ?? false;
|
|
387
|
+
if (node.type === "union" || node.type === "intersection") return node.members?.some((m) => containsSelfRef(m, {
|
|
388
|
+
schemaName,
|
|
389
|
+
resolver,
|
|
390
|
+
visited
|
|
391
|
+
})) ?? false;
|
|
392
|
+
return false;
|
|
393
|
+
}
|
|
394
|
+
//#endregion
|
|
395
|
+
//#region src/printers/printerZod.ts
|
|
396
|
+
/**
|
|
397
|
+
* Zod v4 printer built with `definePrinter`.
|
|
398
|
+
*
|
|
399
|
+
* Converts a `SchemaNode` AST into a **standard** Zod v4 code string
|
|
400
|
+
* using the chainable method API (`.optional()`, `.nullable()`, etc.).
|
|
401
|
+
*
|
|
402
|
+
* For the `zod/mini` functional API, see {@link printerZodMini}.
|
|
403
|
+
*
|
|
404
|
+
* @example
|
|
405
|
+
* ```ts
|
|
406
|
+
* const printer = printerZod({ coercion: false })
|
|
407
|
+
* const code = printer.print(stringSchemaNode) // "z.string()"
|
|
408
|
+
* ```
|
|
409
|
+
*/
|
|
410
|
+
const printerZod = (0, _kubb_core.definePrinter)((options) => {
|
|
411
|
+
return {
|
|
412
|
+
name: "zod",
|
|
413
|
+
options,
|
|
414
|
+
nodes: {
|
|
415
|
+
any: () => "z.any()",
|
|
416
|
+
unknown: () => "z.unknown()",
|
|
417
|
+
void: () => "z.void()",
|
|
418
|
+
never: () => "z.never()",
|
|
419
|
+
boolean: () => "z.boolean()",
|
|
420
|
+
null: () => "z.null()",
|
|
421
|
+
string(node) {
|
|
422
|
+
return `${shouldCoerce(this.options.coercion, "strings") ? "z.coerce.string()" : "z.string()"}${lengthConstraints(node)}`;
|
|
423
|
+
},
|
|
424
|
+
number(node) {
|
|
425
|
+
return `${shouldCoerce(this.options.coercion, "numbers") ? "z.coerce.number()" : "z.number()"}${numberConstraints(node)}`;
|
|
426
|
+
},
|
|
427
|
+
integer(node) {
|
|
428
|
+
return `${shouldCoerce(this.options.coercion, "numbers") ? "z.coerce.number().int()" : "z.int()"}${numberConstraints(node)}`;
|
|
429
|
+
},
|
|
430
|
+
bigint() {
|
|
431
|
+
return shouldCoerce(this.options.coercion, "numbers") ? "z.coerce.bigint()" : "z.bigint()";
|
|
432
|
+
},
|
|
433
|
+
date(node) {
|
|
434
|
+
if (node.representation === "string") return "z.iso.date()";
|
|
435
|
+
return shouldCoerce(this.options.coercion, "dates") ? "z.coerce.date()" : "z.date()";
|
|
436
|
+
},
|
|
437
|
+
datetime(node) {
|
|
438
|
+
if (node.offset) return "z.iso.datetime({ offset: true })";
|
|
439
|
+
if (node.local) return "z.iso.datetime({ local: true })";
|
|
440
|
+
return "z.iso.datetime()";
|
|
441
|
+
},
|
|
442
|
+
time(node) {
|
|
443
|
+
if (node.representation === "string") return "z.iso.time()";
|
|
444
|
+
return shouldCoerce(this.options.coercion, "dates") ? "z.coerce.date()" : "z.date()";
|
|
445
|
+
},
|
|
446
|
+
uuid(node) {
|
|
447
|
+
return `${this.options.guidType === "guid" ? "z.guid()" : "z.uuid()"}${lengthConstraints(node)}`;
|
|
448
|
+
},
|
|
449
|
+
email(node) {
|
|
450
|
+
return `z.email()${lengthConstraints(node)}`;
|
|
451
|
+
},
|
|
452
|
+
url(node) {
|
|
453
|
+
return `z.url()${lengthConstraints(node)}`;
|
|
454
|
+
},
|
|
455
|
+
ipv4: () => "z.ipv4()",
|
|
456
|
+
ipv6: () => "z.ipv6()",
|
|
457
|
+
blob: () => "z.instanceof(File)",
|
|
458
|
+
enum(node) {
|
|
459
|
+
const nonNullValues = (node.namedEnumValues?.map((v) => v.value) ?? node.enumValues ?? []).filter((v) => v !== null);
|
|
460
|
+
if (node.namedEnumValues?.length) {
|
|
461
|
+
const literals = nonNullValues.map((v) => `z.literal(${formatLiteral(v)})`);
|
|
462
|
+
if (literals.length === 1) return literals[0];
|
|
463
|
+
return `z.union([${literals.join(", ")}])`;
|
|
464
|
+
}
|
|
465
|
+
return `z.enum([${nonNullValues.map(formatLiteral).join(", ")}])`;
|
|
466
|
+
},
|
|
467
|
+
ref(node) {
|
|
468
|
+
if (!node.name) return void 0;
|
|
469
|
+
const refName = node.ref ? (0, _kubb_ast.extractRefName)(node.ref) ?? node.name : node.name;
|
|
470
|
+
const resolvedName = node.ref ? this.options.resolver?.default(refName, "function") ?? refName : node.name;
|
|
471
|
+
if (node.ref && this.options.schemaName != null && resolvedName === this.options.schemaName) return `z.lazy(() => ${resolvedName})`;
|
|
472
|
+
return resolvedName;
|
|
473
|
+
},
|
|
474
|
+
object(node) {
|
|
475
|
+
let result = `z.object({\n ${node.properties.map((prop) => {
|
|
476
|
+
const { name: propName, schema } = prop;
|
|
477
|
+
const meta = (0, _kubb_ast.syncSchemaRef)(schema);
|
|
478
|
+
const isNullable = meta.nullable;
|
|
479
|
+
const isOptional = schema.optional;
|
|
480
|
+
const isNullish = schema.nullish;
|
|
481
|
+
const hasSelfRef = this.options.schemaName != null && containsSelfRef(schema, {
|
|
482
|
+
schemaName: this.options.schemaName,
|
|
483
|
+
resolver: this.options.resolver
|
|
484
|
+
});
|
|
485
|
+
const baseOutput = this.transform(schema) ?? this.transform((0, _kubb_ast.createSchema)({ type: "unknown" }));
|
|
486
|
+
const resolvedOutput = hasSelfRef ? baseOutput.replaceAll(`z.lazy(() => ${this.options.schemaName})`, this.options.schemaName) : baseOutput;
|
|
487
|
+
const value = applyModifiers({
|
|
488
|
+
value: this.options.wrapOutput ? this.options.wrapOutput({
|
|
489
|
+
output: resolvedOutput,
|
|
490
|
+
schema
|
|
491
|
+
}) || resolvedOutput : resolvedOutput,
|
|
492
|
+
nullable: isNullable,
|
|
493
|
+
optional: isOptional,
|
|
494
|
+
nullish: isNullish,
|
|
495
|
+
defaultValue: meta.default,
|
|
496
|
+
description: meta.description
|
|
497
|
+
});
|
|
498
|
+
if (hasSelfRef) return `get "${propName}"() { return ${value} }`;
|
|
499
|
+
return `"${propName}": ${value}`;
|
|
500
|
+
}).join(",\n ")}\n })`;
|
|
501
|
+
if (node.additionalProperties && node.additionalProperties !== true) {
|
|
502
|
+
const catchallType = this.transform(node.additionalProperties);
|
|
503
|
+
if (catchallType) result += `.catchall(${catchallType})`;
|
|
504
|
+
} else if (node.additionalProperties === true) result += `.catchall(${this.transform((0, _kubb_ast.createSchema)({ type: "unknown" }))})`;
|
|
505
|
+
else if (node.additionalProperties === false) result += ".strict()";
|
|
506
|
+
return result;
|
|
507
|
+
},
|
|
508
|
+
array(node) {
|
|
509
|
+
let result = `z.array(${(node.items ?? []).map((item) => this.transform(item)).filter(Boolean).join(", ") || this.transform((0, _kubb_ast.createSchema)({ type: "unknown" }))})${lengthConstraints(node)}`;
|
|
510
|
+
if (node.unique) result += `.refine(items => new Set(items).size === items.length, { message: "Array entries must be unique" })`;
|
|
511
|
+
return result;
|
|
512
|
+
},
|
|
513
|
+
tuple(node) {
|
|
514
|
+
return `z.tuple([${(node.items ?? []).map((item) => this.transform(item)).filter(Boolean).join(", ")}])`;
|
|
515
|
+
},
|
|
516
|
+
union(node) {
|
|
517
|
+
const nodeMembers = node.members ?? [];
|
|
518
|
+
const members = nodeMembers.map((m) => this.transform(m)).filter(Boolean);
|
|
519
|
+
if (members.length === 0) return "";
|
|
520
|
+
if (members.length === 1) return members[0];
|
|
521
|
+
if (node.discriminatorPropertyName && !nodeMembers.some((m) => m.type === "intersection")) return `z.discriminatedUnion(${stringify(node.discriminatorPropertyName)}, [${members.join(", ")}])`;
|
|
522
|
+
return `z.union([${members.join(", ")}])`;
|
|
523
|
+
},
|
|
524
|
+
intersection(node) {
|
|
525
|
+
const members = node.members ?? [];
|
|
526
|
+
if (members.length === 0) return "";
|
|
527
|
+
const [first, ...rest] = members;
|
|
528
|
+
if (!first) return "";
|
|
529
|
+
let base = this.transform(first);
|
|
530
|
+
if (!base) return "";
|
|
531
|
+
for (const member of rest) {
|
|
532
|
+
if (member.primitive === "string") {
|
|
533
|
+
const c = lengthConstraints((0, _kubb_ast.narrowSchema)(member, "string") ?? {});
|
|
534
|
+
if (c) {
|
|
535
|
+
base += c;
|
|
536
|
+
continue;
|
|
537
|
+
}
|
|
538
|
+
} else if (member.primitive === "number" || member.primitive === "integer") {
|
|
539
|
+
const c = numberConstraints((0, _kubb_ast.narrowSchema)(member, "number") ?? (0, _kubb_ast.narrowSchema)(member, "integer") ?? {});
|
|
540
|
+
if (c) {
|
|
541
|
+
base += c;
|
|
542
|
+
continue;
|
|
543
|
+
}
|
|
544
|
+
} else if (member.primitive === "array") {
|
|
545
|
+
const c = lengthConstraints((0, _kubb_ast.narrowSchema)(member, "array") ?? {});
|
|
546
|
+
if (c) {
|
|
547
|
+
base += c;
|
|
548
|
+
continue;
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
const transformed = this.transform(member);
|
|
552
|
+
if (transformed) base = `${base}.and(${transformed})`;
|
|
553
|
+
}
|
|
554
|
+
return base;
|
|
555
|
+
}
|
|
556
|
+
},
|
|
557
|
+
print(node) {
|
|
558
|
+
const { keysToOmit } = this.options;
|
|
559
|
+
let base = this.transform(node);
|
|
560
|
+
if (!base) return null;
|
|
561
|
+
const meta = (0, _kubb_ast.syncSchemaRef)(node);
|
|
562
|
+
if (keysToOmit?.length && meta.primitive === "object" && !(meta.type === "union" && meta.discriminatorPropertyName)) base = `${base}.omit({ ${keysToOmit.map((k) => `"${k}": true`).join(", ")} })`;
|
|
563
|
+
return applyModifiers({
|
|
564
|
+
value: base,
|
|
565
|
+
nullable: meta.nullable,
|
|
566
|
+
optional: meta.optional,
|
|
567
|
+
nullish: meta.nullish,
|
|
568
|
+
defaultValue: meta.default,
|
|
569
|
+
description: meta.description
|
|
570
|
+
});
|
|
571
|
+
}
|
|
572
|
+
};
|
|
573
|
+
});
|
|
574
|
+
//#endregion
|
|
575
|
+
//#region src/components/Zod.tsx
|
|
576
|
+
function Zod({ name, node, coercion, guidType, wrapOutput, inferTypeName, resolver, keysToOmit }) {
|
|
577
|
+
const output = printerZod({
|
|
578
|
+
coercion,
|
|
579
|
+
guidType,
|
|
580
|
+
wrapOutput,
|
|
581
|
+
resolver,
|
|
582
|
+
schemaName: name,
|
|
583
|
+
keysToOmit
|
|
584
|
+
}).print(node);
|
|
585
|
+
if (!output) return;
|
|
586
|
+
return /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsxs)(_kubb_react_fabric_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(_kubb_react_fabric.File.Source, {
|
|
587
|
+
name,
|
|
588
|
+
isExportable: true,
|
|
589
|
+
isIndexable: true,
|
|
590
|
+
children: /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(_kubb_react_fabric.Const, {
|
|
591
|
+
export: true,
|
|
592
|
+
name,
|
|
593
|
+
children: output
|
|
594
|
+
})
|
|
595
|
+
}), inferTypeName && /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(_kubb_react_fabric.File.Source, {
|
|
596
|
+
name: inferTypeName,
|
|
597
|
+
isExportable: true,
|
|
598
|
+
isIndexable: true,
|
|
599
|
+
isTypeOnly: true,
|
|
600
|
+
children: /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(_kubb_react_fabric.Type, {
|
|
601
|
+
export: true,
|
|
602
|
+
name: inferTypeName,
|
|
603
|
+
children: `z.infer<typeof ${name}>`
|
|
604
|
+
})
|
|
605
|
+
})] });
|
|
606
|
+
}
|
|
607
|
+
//#endregion
|
|
608
|
+
//#region src/printers/printerZodMini.ts
|
|
609
|
+
/**
|
|
610
|
+
* Zod v4 **Mini** printer built with `definePrinter`.
|
|
611
|
+
*
|
|
612
|
+
* Converts a `SchemaNode` AST into a Zod v4 Mini code string using the
|
|
613
|
+
* functional API (`z.optional(z.string())`) for better tree-shaking.
|
|
614
|
+
*
|
|
615
|
+
* For the standard chainable API, see {@link printerZod}.
|
|
616
|
+
*
|
|
617
|
+
* @example
|
|
618
|
+
* ```ts
|
|
619
|
+
* const printer = printerZodMini({})
|
|
620
|
+
* const code = printer.print(optionalStringNode) // "z.optional(z.string())"
|
|
621
|
+
* ```
|
|
622
|
+
*/
|
|
623
|
+
const printerZodMini = (0, _kubb_core.definePrinter)((options) => {
|
|
624
|
+
return {
|
|
625
|
+
name: "zod-mini",
|
|
626
|
+
options,
|
|
627
|
+
nodes: {
|
|
628
|
+
any: () => "z.any()",
|
|
629
|
+
unknown: () => "z.unknown()",
|
|
630
|
+
void: () => "z.void()",
|
|
631
|
+
never: () => "z.never()",
|
|
632
|
+
boolean: () => "z.boolean()",
|
|
633
|
+
null: () => "z.null()",
|
|
634
|
+
string(node) {
|
|
635
|
+
return `z.string()${lengthChecksMini(node)}`;
|
|
636
|
+
},
|
|
637
|
+
number(node) {
|
|
638
|
+
return `z.number()${numberChecksMini(node)}`;
|
|
639
|
+
},
|
|
640
|
+
integer(node) {
|
|
641
|
+
return `z.int()${numberChecksMini(node)}`;
|
|
642
|
+
},
|
|
643
|
+
bigint(node) {
|
|
644
|
+
return `z.bigint()${numberChecksMini(node)}`;
|
|
645
|
+
},
|
|
646
|
+
date(node) {
|
|
647
|
+
if (node.representation === "string") return "z.iso.date()";
|
|
648
|
+
return "z.date()";
|
|
649
|
+
},
|
|
650
|
+
datetime() {
|
|
651
|
+
return "z.string()";
|
|
652
|
+
},
|
|
653
|
+
time(node) {
|
|
654
|
+
if (node.representation === "string") return "z.iso.time()";
|
|
655
|
+
return "z.date()";
|
|
656
|
+
},
|
|
657
|
+
uuid(node) {
|
|
658
|
+
return `${this.options.guidType === "guid" ? "z.guid()" : "z.uuid()"}${lengthChecksMini(node)}`;
|
|
659
|
+
},
|
|
660
|
+
email(node) {
|
|
661
|
+
return `z.email()${lengthChecksMini(node)}`;
|
|
662
|
+
},
|
|
663
|
+
url(node) {
|
|
664
|
+
return `z.url()${lengthChecksMini(node)}`;
|
|
665
|
+
},
|
|
666
|
+
ipv4: () => "z.ipv4()",
|
|
667
|
+
ipv6: () => "z.ipv6()",
|
|
668
|
+
blob: () => "z.instanceof(File)",
|
|
669
|
+
enum(node) {
|
|
670
|
+
const nonNullValues = (node.namedEnumValues?.map((v) => v.value) ?? node.enumValues ?? []).filter((v) => v !== null);
|
|
671
|
+
if (node.namedEnumValues?.length) {
|
|
672
|
+
const literals = nonNullValues.map((v) => `z.literal(${formatLiteral(v)})`);
|
|
673
|
+
if (literals.length === 1) return literals[0];
|
|
674
|
+
return `z.union([${literals.join(", ")}])`;
|
|
675
|
+
}
|
|
676
|
+
return `z.enum([${nonNullValues.map(formatLiteral).join(", ")}])`;
|
|
677
|
+
},
|
|
678
|
+
ref(node) {
|
|
679
|
+
if (!node.name) return void 0;
|
|
680
|
+
const refName = node.ref ? (0, _kubb_ast.extractRefName)(node.ref) ?? node.name : node.name;
|
|
681
|
+
const resolvedName = node.ref ? this.options.resolver?.default(refName, "function") ?? refName : node.name;
|
|
682
|
+
if (node.ref && this.options.schemaName != null && resolvedName === this.options.schemaName) return `z.lazy(() => ${resolvedName})`;
|
|
683
|
+
return resolvedName;
|
|
684
|
+
},
|
|
685
|
+
object(node) {
|
|
686
|
+
return `z.object({\n ${node.properties.map((prop) => {
|
|
687
|
+
const { name: propName, schema } = prop;
|
|
688
|
+
const meta = (0, _kubb_ast.syncSchemaRef)(schema);
|
|
689
|
+
const isNullable = meta.nullable;
|
|
690
|
+
const isOptional = schema.optional;
|
|
691
|
+
const isNullish = schema.nullish;
|
|
692
|
+
const hasSelfRef = this.options.schemaName != null && containsSelfRef(schema, {
|
|
693
|
+
schemaName: this.options.schemaName,
|
|
694
|
+
resolver: this.options.resolver
|
|
695
|
+
});
|
|
696
|
+
const baseOutput = this.transform(schema) ?? this.transform((0, _kubb_ast.createSchema)({ type: "unknown" }));
|
|
697
|
+
const resolvedOutput = hasSelfRef ? baseOutput.replaceAll(`z.lazy(() => ${this.options.schemaName})`, this.options.schemaName) : baseOutput;
|
|
698
|
+
const value = applyMiniModifiers({
|
|
699
|
+
value: this.options.wrapOutput ? this.options.wrapOutput({
|
|
700
|
+
output: resolvedOutput,
|
|
701
|
+
schema
|
|
702
|
+
}) || resolvedOutput : resolvedOutput,
|
|
703
|
+
nullable: isNullable,
|
|
704
|
+
optional: isOptional,
|
|
705
|
+
nullish: isNullish,
|
|
706
|
+
defaultValue: meta.default
|
|
707
|
+
});
|
|
708
|
+
if (hasSelfRef) return `get "${propName}"() { return ${value} }`;
|
|
709
|
+
return `"${propName}": ${value}`;
|
|
710
|
+
}).join(",\n ")}\n })`;
|
|
711
|
+
},
|
|
712
|
+
array(node) {
|
|
713
|
+
let result = `z.array(${(node.items ?? []).map((item) => this.transform(item)).filter(Boolean).join(", ") || this.transform((0, _kubb_ast.createSchema)({ type: "unknown" }))})${lengthChecksMini(node)}`;
|
|
714
|
+
if (node.unique) result += `.refine(items => new Set(items).size === items.length, { message: "Array entries must be unique" })`;
|
|
715
|
+
return result;
|
|
716
|
+
},
|
|
717
|
+
tuple(node) {
|
|
718
|
+
return `z.tuple([${(node.items ?? []).map((item) => this.transform(item)).filter(Boolean).join(", ")}])`;
|
|
719
|
+
},
|
|
720
|
+
union(node) {
|
|
721
|
+
const nodeMembers = node.members ?? [];
|
|
722
|
+
const members = nodeMembers.map((m) => this.transform(m)).filter(Boolean);
|
|
723
|
+
if (members.length === 0) return "";
|
|
724
|
+
if (members.length === 1) return members[0];
|
|
725
|
+
if (node.discriminatorPropertyName && !nodeMembers.some((m) => m.type === "intersection")) return `z.discriminatedUnion(${stringify(node.discriminatorPropertyName)}, [${members.join(", ")}])`;
|
|
726
|
+
return `z.union([${members.join(", ")}])`;
|
|
727
|
+
},
|
|
728
|
+
intersection(node) {
|
|
729
|
+
const members = node.members ?? [];
|
|
730
|
+
if (members.length === 0) return "";
|
|
731
|
+
const [first, ...rest] = members;
|
|
732
|
+
if (!first) return "";
|
|
733
|
+
let base = this.transform(first);
|
|
734
|
+
if (!base) return "";
|
|
735
|
+
for (const member of rest) {
|
|
736
|
+
if (member.primitive === "string") {
|
|
737
|
+
const c = lengthChecksMini((0, _kubb_ast.narrowSchema)(member, "string") ?? {});
|
|
738
|
+
if (c) {
|
|
739
|
+
base += c;
|
|
740
|
+
continue;
|
|
741
|
+
}
|
|
742
|
+
} else if (member.primitive === "number" || member.primitive === "integer") {
|
|
743
|
+
const c = numberChecksMini((0, _kubb_ast.narrowSchema)(member, "number") ?? (0, _kubb_ast.narrowSchema)(member, "integer") ?? {});
|
|
744
|
+
if (c) {
|
|
745
|
+
base += c;
|
|
746
|
+
continue;
|
|
747
|
+
}
|
|
748
|
+
} else if (member.primitive === "array") {
|
|
749
|
+
const c = lengthChecksMini((0, _kubb_ast.narrowSchema)(member, "array") ?? {});
|
|
750
|
+
if (c) {
|
|
751
|
+
base += c;
|
|
752
|
+
continue;
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
const transformed = this.transform(member);
|
|
756
|
+
if (transformed) base = `z.intersection(${base}, ${transformed})`;
|
|
757
|
+
}
|
|
758
|
+
return base;
|
|
759
|
+
}
|
|
760
|
+
},
|
|
761
|
+
print(node) {
|
|
762
|
+
const { keysToOmit } = this.options;
|
|
763
|
+
let base = this.transform(node);
|
|
764
|
+
if (!base) return null;
|
|
765
|
+
const meta = (0, _kubb_ast.syncSchemaRef)(node);
|
|
766
|
+
if (keysToOmit?.length && meta.primitive === "object" && !(meta.type === "union" && meta.discriminatorPropertyName)) base = `${base}.omit({ ${keysToOmit.map((k) => `"${k}": true`).join(", ")} })`;
|
|
767
|
+
return applyMiniModifiers({
|
|
768
|
+
value: base,
|
|
769
|
+
nullable: meta.nullable,
|
|
770
|
+
optional: meta.optional,
|
|
771
|
+
nullish: meta.nullish,
|
|
772
|
+
defaultValue: meta.default
|
|
773
|
+
});
|
|
774
|
+
}
|
|
775
|
+
};
|
|
776
|
+
});
|
|
777
|
+
//#endregion
|
|
778
|
+
//#region src/components/ZodMini.tsx
|
|
779
|
+
function ZodMini({ name, node, guidType, wrapOutput, inferTypeName, resolver, keysToOmit }) {
|
|
780
|
+
const output = printerZodMini({
|
|
781
|
+
guidType,
|
|
782
|
+
wrapOutput,
|
|
783
|
+
resolver,
|
|
784
|
+
schemaName: name,
|
|
785
|
+
keysToOmit
|
|
786
|
+
}).print(node);
|
|
787
|
+
if (!output) return;
|
|
788
|
+
return /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsxs)(_kubb_react_fabric_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(_kubb_react_fabric.File.Source, {
|
|
789
|
+
name,
|
|
790
|
+
isExportable: true,
|
|
791
|
+
isIndexable: true,
|
|
792
|
+
children: /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(_kubb_react_fabric.Const, {
|
|
793
|
+
export: true,
|
|
794
|
+
name,
|
|
795
|
+
children: output
|
|
796
|
+
})
|
|
797
|
+
}), inferTypeName && /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(_kubb_react_fabric.File.Source, {
|
|
798
|
+
name: inferTypeName,
|
|
799
|
+
isExportable: true,
|
|
800
|
+
isIndexable: true,
|
|
801
|
+
isTypeOnly: true,
|
|
802
|
+
children: /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(_kubb_react_fabric.Type, {
|
|
803
|
+
export: true,
|
|
804
|
+
name: inferTypeName,
|
|
805
|
+
children: `z.infer<typeof ${name}>`
|
|
806
|
+
})
|
|
807
|
+
})] });
|
|
808
|
+
}
|
|
809
|
+
//#endregion
|
|
810
|
+
//#region src/constants.ts
|
|
811
|
+
/**
|
|
812
|
+
* Import paths that use a namespace import (`import * as z from '...'`).
|
|
813
|
+
* All other import paths use a named import (`import { z } from '...'`).
|
|
814
|
+
*/
|
|
815
|
+
const ZOD_NAMESPACE_IMPORTS = new Set(["zod", "zod/mini"]);
|
|
816
|
+
//#endregion
|
|
817
|
+
//#region src/generators/zodGenerator.tsx
|
|
818
|
+
const zodGenerator = (0, _kubb_core.defineGenerator)({
|
|
819
|
+
name: "zod",
|
|
820
|
+
type: "react",
|
|
821
|
+
Schema({ node, adapter, options, config, resolver }) {
|
|
822
|
+
const { output, coercion, guidType, mini, wrapOutput, inferred, importPath, group, transformers = [] } = options;
|
|
823
|
+
const transformedNode = (0, _kubb_ast.transform)(node, (0, _kubb_ast.composeTransformers)(...transformers));
|
|
824
|
+
if (!transformedNode.name) return;
|
|
825
|
+
const root = node_path.default.resolve(config.root, config.output.path);
|
|
826
|
+
const mode = (0, _kubb_core.getMode)(node_path.default.resolve(root, output.path));
|
|
827
|
+
const isZodImport = ZOD_NAMESPACE_IMPORTS.has(importPath);
|
|
828
|
+
const imports = adapter.getImports(transformedNode, (schemaName) => ({
|
|
829
|
+
name: resolver.default(schemaName, "function"),
|
|
830
|
+
path: resolver.resolveFile({
|
|
831
|
+
name: schemaName,
|
|
832
|
+
extname: ".ts"
|
|
833
|
+
}, {
|
|
834
|
+
root,
|
|
835
|
+
output,
|
|
836
|
+
group
|
|
837
|
+
}).path
|
|
838
|
+
}));
|
|
839
|
+
const inferTypeName = inferred ? resolver.resolveInferName(resolver.resolveName(transformedNode.name)) : void 0;
|
|
840
|
+
const meta = {
|
|
841
|
+
name: resolver.default(transformedNode.name, "function"),
|
|
842
|
+
file: resolver.resolveFile({
|
|
843
|
+
name: transformedNode.name,
|
|
844
|
+
extname: ".ts"
|
|
845
|
+
}, {
|
|
846
|
+
root,
|
|
847
|
+
output,
|
|
848
|
+
group
|
|
849
|
+
})
|
|
850
|
+
};
|
|
851
|
+
return /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsxs)(_kubb_react_fabric.File, {
|
|
852
|
+
baseName: meta.file.baseName,
|
|
853
|
+
path: meta.file.path,
|
|
854
|
+
meta: meta.file.meta,
|
|
855
|
+
banner: resolver.resolveBanner(adapter.rootNode, {
|
|
856
|
+
output,
|
|
857
|
+
config
|
|
858
|
+
}),
|
|
859
|
+
footer: resolver.resolveFooter(adapter.rootNode, {
|
|
860
|
+
output,
|
|
861
|
+
config
|
|
862
|
+
}),
|
|
863
|
+
children: [
|
|
864
|
+
/* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(_kubb_react_fabric.File.Import, {
|
|
865
|
+
name: isZodImport ? "z" : ["z"],
|
|
866
|
+
path: importPath,
|
|
867
|
+
isNameSpace: isZodImport
|
|
868
|
+
}),
|
|
869
|
+
mode === "split" && imports.map((imp) => /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(_kubb_react_fabric.File.Import, {
|
|
870
|
+
root: meta.file.path,
|
|
871
|
+
path: imp.path,
|
|
872
|
+
name: imp.name
|
|
873
|
+
}, [transformedNode.name, imp.path].join("-"))),
|
|
874
|
+
mini ? /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(ZodMini, {
|
|
875
|
+
name: meta.name,
|
|
876
|
+
node: transformedNode,
|
|
877
|
+
guidType,
|
|
878
|
+
wrapOutput,
|
|
879
|
+
inferTypeName,
|
|
880
|
+
resolver
|
|
881
|
+
}) : /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(Zod, {
|
|
882
|
+
name: meta.name,
|
|
883
|
+
node: transformedNode,
|
|
884
|
+
coercion,
|
|
885
|
+
guidType,
|
|
886
|
+
wrapOutput,
|
|
887
|
+
inferTypeName,
|
|
888
|
+
resolver
|
|
889
|
+
})
|
|
890
|
+
]
|
|
891
|
+
});
|
|
892
|
+
},
|
|
893
|
+
Operation({ node, adapter, options, config, resolver }) {
|
|
894
|
+
const { output, coercion, guidType, mini, wrapOutput, inferred, importPath, group, paramsCasing, transformers } = options;
|
|
895
|
+
const transformedNode = (0, _kubb_ast.transform)(node, (0, _kubb_ast.composeTransformers)(...transformers));
|
|
896
|
+
const root = node_path.default.resolve(config.root, config.output.path);
|
|
897
|
+
const mode = (0, _kubb_core.getMode)(node_path.default.resolve(root, output.path));
|
|
898
|
+
const isZodImport = ZOD_NAMESPACE_IMPORTS.has(importPath);
|
|
899
|
+
const params = (0, _kubb_ast.caseParams)(transformedNode.parameters, paramsCasing);
|
|
900
|
+
const meta = { file: resolver.resolveFile({
|
|
901
|
+
name: transformedNode.operationId,
|
|
902
|
+
extname: ".ts",
|
|
903
|
+
tag: transformedNode.tags[0] ?? "default",
|
|
904
|
+
path: transformedNode.path
|
|
905
|
+
}, {
|
|
906
|
+
root,
|
|
907
|
+
output,
|
|
908
|
+
group
|
|
909
|
+
}) };
|
|
910
|
+
function renderSchemaEntry({ schema, name, keysToOmit }) {
|
|
911
|
+
if (!schema) return null;
|
|
912
|
+
const inferTypeName = inferred ? resolver.resolveInferName(name) : void 0;
|
|
913
|
+
const imports = adapter.getImports(schema, (schemaName) => ({
|
|
914
|
+
name: resolver.default(schemaName, "function"),
|
|
915
|
+
path: resolver.resolveFile({
|
|
916
|
+
name: schemaName,
|
|
917
|
+
extname: ".ts"
|
|
918
|
+
}, {
|
|
919
|
+
root,
|
|
920
|
+
output,
|
|
921
|
+
group
|
|
922
|
+
}).path
|
|
923
|
+
}));
|
|
924
|
+
return /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsxs)(_kubb_react_fabric_jsx_runtime.Fragment, { children: [mode === "split" && imports.map((imp) => /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(_kubb_react_fabric.File.Import, {
|
|
925
|
+
root: meta.file.path,
|
|
926
|
+
path: imp.path,
|
|
927
|
+
name: imp.name
|
|
928
|
+
}, [
|
|
929
|
+
name,
|
|
930
|
+
imp.path,
|
|
931
|
+
imp.name
|
|
932
|
+
].join("-"))), mini ? /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(ZodMini, {
|
|
933
|
+
name,
|
|
934
|
+
node: schema,
|
|
935
|
+
guidType,
|
|
936
|
+
wrapOutput,
|
|
937
|
+
inferTypeName,
|
|
938
|
+
resolver,
|
|
939
|
+
keysToOmit
|
|
940
|
+
}) : /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(Zod, {
|
|
941
|
+
name,
|
|
942
|
+
node: schema,
|
|
943
|
+
coercion,
|
|
944
|
+
guidType,
|
|
945
|
+
wrapOutput,
|
|
946
|
+
inferTypeName,
|
|
947
|
+
resolver,
|
|
948
|
+
keysToOmit
|
|
949
|
+
})] });
|
|
950
|
+
}
|
|
951
|
+
const paramSchemas = params.map((param) => renderSchemaEntry({
|
|
952
|
+
schema: param.schema,
|
|
953
|
+
name: resolver.resolveParamName(node, param)
|
|
954
|
+
}));
|
|
955
|
+
const responseSchemas = transformedNode.responses.map((res) => renderSchemaEntry({
|
|
956
|
+
schema: res.schema,
|
|
957
|
+
name: resolver.resolveResponseStatusName(transformedNode, res.statusCode),
|
|
958
|
+
keysToOmit: res.keysToOmit
|
|
959
|
+
}));
|
|
960
|
+
const requestSchema = transformedNode.requestBody?.schema ? renderSchemaEntry({
|
|
961
|
+
schema: {
|
|
962
|
+
...transformedNode.requestBody.schema,
|
|
963
|
+
description: transformedNode.requestBody.description ?? transformedNode.requestBody.schema.description
|
|
964
|
+
},
|
|
965
|
+
name: resolver.resolveDataName(transformedNode),
|
|
966
|
+
keysToOmit: transformedNode.requestBody.keysToOmit
|
|
967
|
+
}) : null;
|
|
968
|
+
return /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsxs)(_kubb_react_fabric.File, {
|
|
969
|
+
baseName: meta.file.baseName,
|
|
970
|
+
path: meta.file.path,
|
|
971
|
+
meta: meta.file.meta,
|
|
972
|
+
banner: resolver.resolveBanner(adapter.rootNode, {
|
|
973
|
+
output,
|
|
974
|
+
config
|
|
975
|
+
}),
|
|
976
|
+
footer: resolver.resolveFooter(adapter.rootNode, {
|
|
977
|
+
output,
|
|
978
|
+
config
|
|
979
|
+
}),
|
|
980
|
+
children: [
|
|
981
|
+
/* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(_kubb_react_fabric.File.Import, {
|
|
982
|
+
name: isZodImport ? "z" : ["z"],
|
|
983
|
+
path: importPath,
|
|
984
|
+
isNameSpace: isZodImport
|
|
985
|
+
}),
|
|
986
|
+
paramSchemas,
|
|
987
|
+
responseSchemas,
|
|
988
|
+
requestSchema
|
|
989
|
+
]
|
|
990
|
+
});
|
|
991
|
+
},
|
|
992
|
+
Operations({ nodes, adapter, options, config, resolver }) {
|
|
993
|
+
const { output, importPath, group, operations, paramsCasing, transformers } = options;
|
|
994
|
+
if (!operations) return;
|
|
995
|
+
const root = node_path.default.resolve(config.root, config.output.path);
|
|
996
|
+
const isZodImport = ZOD_NAMESPACE_IMPORTS.has(importPath);
|
|
997
|
+
const meta = { file: resolver.resolveFile({
|
|
998
|
+
name: "operations",
|
|
999
|
+
extname: ".ts"
|
|
1000
|
+
}, {
|
|
1001
|
+
root,
|
|
1002
|
+
output,
|
|
1003
|
+
group
|
|
1004
|
+
}) };
|
|
1005
|
+
const transformedOperations = nodes.map((node) => {
|
|
1006
|
+
const transformedNode = (0, _kubb_ast.transform)(node, (0, _kubb_ast.composeTransformers)(...transformers));
|
|
1007
|
+
return {
|
|
1008
|
+
node: transformedNode,
|
|
1009
|
+
data: buildSchemaNames(transformedNode, {
|
|
1010
|
+
params: (0, _kubb_ast.caseParams)(transformedNode.parameters, paramsCasing),
|
|
1011
|
+
resolver
|
|
1012
|
+
})
|
|
1013
|
+
};
|
|
1014
|
+
});
|
|
1015
|
+
const imports = transformedOperations.flatMap(({ node, data }) => {
|
|
1016
|
+
const names = [
|
|
1017
|
+
data.request,
|
|
1018
|
+
...Object.values(data.responses),
|
|
1019
|
+
...Object.values(data.parameters)
|
|
1020
|
+
].filter(Boolean);
|
|
1021
|
+
const opFile = resolver.resolveFile({
|
|
1022
|
+
name: node.operationId,
|
|
1023
|
+
extname: ".ts",
|
|
1024
|
+
tag: node.tags[0] ?? "default",
|
|
1025
|
+
path: node.path
|
|
1026
|
+
}, {
|
|
1027
|
+
root,
|
|
1028
|
+
output,
|
|
1029
|
+
group
|
|
1030
|
+
});
|
|
1031
|
+
return names.map((name) => /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(_kubb_react_fabric.File.Import, {
|
|
1032
|
+
name: [name],
|
|
1033
|
+
root: meta.file.path,
|
|
1034
|
+
path: opFile.path
|
|
1035
|
+
}, [name, opFile.path].join("-")));
|
|
1036
|
+
});
|
|
1037
|
+
return /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsxs)(_kubb_react_fabric.File, {
|
|
1038
|
+
baseName: meta.file.baseName,
|
|
1039
|
+
path: meta.file.path,
|
|
1040
|
+
meta: meta.file.meta,
|
|
1041
|
+
banner: resolver.resolveBanner(adapter.rootNode, {
|
|
1042
|
+
output,
|
|
1043
|
+
config
|
|
1044
|
+
}),
|
|
1045
|
+
footer: resolver.resolveFooter(adapter.rootNode, {
|
|
1046
|
+
output,
|
|
1047
|
+
config
|
|
1048
|
+
}),
|
|
1049
|
+
children: [
|
|
1050
|
+
/* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(_kubb_react_fabric.File.Import, {
|
|
1051
|
+
isTypeOnly: true,
|
|
1052
|
+
name: isZodImport ? "z" : ["z"],
|
|
1053
|
+
path: importPath,
|
|
1054
|
+
isNameSpace: isZodImport
|
|
1055
|
+
}),
|
|
1056
|
+
imports,
|
|
1057
|
+
/* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(Operations, {
|
|
1058
|
+
name: "operations",
|
|
1059
|
+
operations: transformedOperations
|
|
1060
|
+
})
|
|
1061
|
+
]
|
|
1062
|
+
});
|
|
1063
|
+
}
|
|
1064
|
+
});
|
|
1065
|
+
//#endregion
|
|
1066
|
+
//#region src/generators/zodGeneratorLegacy.tsx
|
|
1067
|
+
function buildGroupedParamsSchema({ params, optional }) {
|
|
1068
|
+
return (0, _kubb_ast.createSchema)({
|
|
1069
|
+
type: "object",
|
|
1070
|
+
optional,
|
|
1071
|
+
primitive: "object",
|
|
1072
|
+
properties: params.map((param) => {
|
|
1073
|
+
return (0, _kubb_ast.createProperty)({
|
|
1074
|
+
name: param.name,
|
|
1075
|
+
required: param.required,
|
|
1076
|
+
schema: param.schema
|
|
1077
|
+
});
|
|
1078
|
+
})
|
|
1079
|
+
});
|
|
1080
|
+
}
|
|
1081
|
+
function buildLegacyResponsesSchemaNode(node, { resolver }) {
|
|
1082
|
+
const isGet = node.method.toLowerCase() === "get";
|
|
1083
|
+
const successResponses = node.responses.filter((res) => {
|
|
1084
|
+
const code = Number(res.statusCode);
|
|
1085
|
+
return !Number.isNaN(code) && code >= 200 && code < 300;
|
|
1086
|
+
});
|
|
1087
|
+
const errorResponses = node.responses.filter((res) => res.statusCode === "default" || Number(res.statusCode) >= 400);
|
|
1088
|
+
const responseSchema = successResponses.length > 0 ? successResponses.length === 1 ? (0, _kubb_ast.createSchema)({
|
|
1089
|
+
type: "ref",
|
|
1090
|
+
name: resolver.resolveResponseStatusName(node, successResponses[0].statusCode)
|
|
1091
|
+
}) : (0, _kubb_ast.createSchema)({
|
|
1092
|
+
type: "union",
|
|
1093
|
+
members: successResponses.map((res) => (0, _kubb_ast.createSchema)({
|
|
1094
|
+
type: "ref",
|
|
1095
|
+
name: resolver.resolveResponseStatusName(node, res.statusCode)
|
|
1096
|
+
}))
|
|
1097
|
+
}) : (0, _kubb_ast.createSchema)({ type: "any" });
|
|
1098
|
+
const errorsSchema = errorResponses.length > 0 ? errorResponses.length === 1 ? (0, _kubb_ast.createSchema)({
|
|
1099
|
+
type: "ref",
|
|
1100
|
+
name: resolver.resolveResponseStatusName(node, errorResponses[0].statusCode)
|
|
1101
|
+
}) : (0, _kubb_ast.createSchema)({
|
|
1102
|
+
type: "union",
|
|
1103
|
+
members: errorResponses.map((res) => (0, _kubb_ast.createSchema)({
|
|
1104
|
+
type: "ref",
|
|
1105
|
+
name: resolver.resolveResponseStatusName(node, res.statusCode)
|
|
1106
|
+
}))
|
|
1107
|
+
}) : (0, _kubb_ast.createSchema)({ type: "any" });
|
|
1108
|
+
const properties = [(0, _kubb_ast.createProperty)({
|
|
1109
|
+
name: "Response",
|
|
1110
|
+
required: true,
|
|
1111
|
+
schema: responseSchema
|
|
1112
|
+
})];
|
|
1113
|
+
if (!isGet && node.requestBody?.schema) properties.push((0, _kubb_ast.createProperty)({
|
|
1114
|
+
name: "Request",
|
|
1115
|
+
required: true,
|
|
1116
|
+
schema: (0, _kubb_ast.createSchema)({
|
|
1117
|
+
type: "ref",
|
|
1118
|
+
name: resolver.resolveDataName(node)
|
|
1119
|
+
})
|
|
1120
|
+
}));
|
|
1121
|
+
const queryParam = node.parameters.find((p) => p.in === "query");
|
|
1122
|
+
if (queryParam) properties.push((0, _kubb_ast.createProperty)({
|
|
1123
|
+
name: "QueryParams",
|
|
1124
|
+
required: true,
|
|
1125
|
+
schema: (0, _kubb_ast.createSchema)({
|
|
1126
|
+
type: "ref",
|
|
1127
|
+
name: resolver.resolveQueryParamsName(node, queryParam)
|
|
1128
|
+
})
|
|
1129
|
+
}));
|
|
1130
|
+
const pathParam = node.parameters.find((p) => p.in === "path");
|
|
1131
|
+
if (pathParam) properties.push((0, _kubb_ast.createProperty)({
|
|
1132
|
+
name: "PathParams",
|
|
1133
|
+
required: true,
|
|
1134
|
+
schema: (0, _kubb_ast.createSchema)({
|
|
1135
|
+
type: "ref",
|
|
1136
|
+
name: resolver.resolvePathParamsName(node, pathParam)
|
|
1137
|
+
})
|
|
1138
|
+
}));
|
|
1139
|
+
const headerParam = node.parameters.find((p) => p.in === "header");
|
|
1140
|
+
if (headerParam) properties.push((0, _kubb_ast.createProperty)({
|
|
1141
|
+
name: "HeaderParams",
|
|
1142
|
+
required: true,
|
|
1143
|
+
schema: (0, _kubb_ast.createSchema)({
|
|
1144
|
+
type: "ref",
|
|
1145
|
+
name: resolver.resolveHeaderParamsName(node, headerParam)
|
|
1146
|
+
})
|
|
1147
|
+
}));
|
|
1148
|
+
properties.push((0, _kubb_ast.createProperty)({
|
|
1149
|
+
name: "Errors",
|
|
1150
|
+
required: true,
|
|
1151
|
+
schema: errorsSchema
|
|
1152
|
+
}));
|
|
1153
|
+
return (0, _kubb_ast.createSchema)({
|
|
1154
|
+
type: "object",
|
|
1155
|
+
primitive: "object",
|
|
1156
|
+
properties
|
|
1157
|
+
});
|
|
1158
|
+
}
|
|
1159
|
+
function buildLegacyResponseUnionSchemaNode(node, { resolver }) {
|
|
1160
|
+
const successResponses = node.responses.filter((res) => {
|
|
1161
|
+
const code = Number(res.statusCode);
|
|
1162
|
+
return !Number.isNaN(code) && code >= 200 && code < 300;
|
|
1163
|
+
});
|
|
1164
|
+
if (successResponses.length === 0) return (0, _kubb_ast.createSchema)({ type: "any" });
|
|
1165
|
+
if (successResponses.length === 1) return (0, _kubb_ast.createSchema)({
|
|
1166
|
+
type: "ref",
|
|
1167
|
+
name: resolver.resolveResponseStatusName(node, successResponses[0].statusCode)
|
|
1168
|
+
});
|
|
1169
|
+
return (0, _kubb_ast.createSchema)({
|
|
1170
|
+
type: "union",
|
|
1171
|
+
members: successResponses.map((res) => (0, _kubb_ast.createSchema)({
|
|
1172
|
+
type: "ref",
|
|
1173
|
+
name: resolver.resolveResponseStatusName(node, res.statusCode)
|
|
1174
|
+
}))
|
|
1175
|
+
});
|
|
1176
|
+
}
|
|
1177
|
+
function buildLegacySchemaNames(node, params, resolver) {
|
|
1178
|
+
const pathParam = params.find((p) => p.in === "path");
|
|
1179
|
+
const queryParam = params.find((p) => p.in === "query");
|
|
1180
|
+
const headerParam = params.find((p) => p.in === "header");
|
|
1181
|
+
const responses = {};
|
|
1182
|
+
const errors = {};
|
|
1183
|
+
for (const res of node.responses) {
|
|
1184
|
+
const name = resolver.resolveResponseStatusName(node, res.statusCode);
|
|
1185
|
+
const statusNum = Number(res.statusCode);
|
|
1186
|
+
if (!Number.isNaN(statusNum)) {
|
|
1187
|
+
responses[statusNum] = name;
|
|
1188
|
+
if (statusNum >= 400) errors[statusNum] = name;
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
responses["default"] = resolver.resolveResponseName(node);
|
|
1192
|
+
return {
|
|
1193
|
+
request: node.requestBody?.schema ? resolver.resolveDataName(node) : void 0,
|
|
1194
|
+
parameters: {
|
|
1195
|
+
path: pathParam ? resolver.resolvePathParamsName(node, pathParam) : void 0,
|
|
1196
|
+
query: queryParam ? resolver.resolveQueryParamsName(node, queryParam) : void 0,
|
|
1197
|
+
header: headerParam ? resolver.resolveHeaderParamsName(node, headerParam) : void 0
|
|
1198
|
+
},
|
|
1199
|
+
responses,
|
|
1200
|
+
errors
|
|
1201
|
+
};
|
|
1202
|
+
}
|
|
1203
|
+
const zodGeneratorLegacy = (0, _kubb_core.defineGenerator)({
|
|
1204
|
+
name: "zod-legacy",
|
|
1205
|
+
type: "react",
|
|
1206
|
+
Schema({ node, adapter, options, config, resolver }) {
|
|
1207
|
+
const { output, coercion, guidType, mini, wrapOutput, inferred, importPath, group, transformers = [] } = options;
|
|
1208
|
+
const transformedNode = (0, _kubb_ast.transform)(node, (0, _kubb_ast.composeTransformers)(...transformers));
|
|
1209
|
+
if (!transformedNode.name) return;
|
|
1210
|
+
const root = node_path.default.resolve(config.root, config.output.path);
|
|
1211
|
+
const mode = (0, _kubb_core.getMode)(node_path.default.resolve(root, output.path));
|
|
1212
|
+
const isZodImport = ZOD_NAMESPACE_IMPORTS.has(importPath);
|
|
1213
|
+
const imports = adapter.getImports(transformedNode, (schemaName) => ({
|
|
1214
|
+
name: resolver.default(schemaName, "function"),
|
|
1215
|
+
path: resolver.resolveFile({
|
|
1216
|
+
name: schemaName,
|
|
1217
|
+
extname: ".ts"
|
|
1218
|
+
}, {
|
|
1219
|
+
root,
|
|
1220
|
+
output,
|
|
1221
|
+
group
|
|
1222
|
+
}).path
|
|
1223
|
+
}));
|
|
1224
|
+
const inferTypeName = inferred ? resolver.resolveInferName(resolver.resolveName(transformedNode.name)) : void 0;
|
|
1225
|
+
const meta = {
|
|
1226
|
+
name: resolver.default(transformedNode.name, "function"),
|
|
1227
|
+
file: resolver.resolveFile({
|
|
1228
|
+
name: transformedNode.name,
|
|
1229
|
+
extname: ".ts"
|
|
1230
|
+
}, {
|
|
1231
|
+
root,
|
|
1232
|
+
output,
|
|
1233
|
+
group
|
|
1234
|
+
})
|
|
1235
|
+
};
|
|
1236
|
+
return /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsxs)(_kubb_react_fabric.File, {
|
|
1237
|
+
baseName: meta.file.baseName,
|
|
1238
|
+
path: meta.file.path,
|
|
1239
|
+
meta: meta.file.meta,
|
|
1240
|
+
banner: resolver.resolveBanner(adapter.rootNode, {
|
|
1241
|
+
output,
|
|
1242
|
+
config
|
|
1243
|
+
}),
|
|
1244
|
+
footer: resolver.resolveFooter(adapter.rootNode, {
|
|
1245
|
+
output,
|
|
1246
|
+
config
|
|
1247
|
+
}),
|
|
1248
|
+
children: [
|
|
1249
|
+
/* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(_kubb_react_fabric.File.Import, {
|
|
1250
|
+
name: isZodImport ? "z" : ["z"],
|
|
1251
|
+
path: importPath,
|
|
1252
|
+
isNameSpace: isZodImport
|
|
1253
|
+
}),
|
|
1254
|
+
mode === "split" && imports.map((imp) => /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(_kubb_react_fabric.File.Import, {
|
|
1255
|
+
root: meta.file.path,
|
|
1256
|
+
path: imp.path,
|
|
1257
|
+
name: imp.name
|
|
1258
|
+
}, [transformedNode.name, imp.path].join("-"))),
|
|
1259
|
+
mini ? /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(ZodMini, {
|
|
1260
|
+
name: meta.name,
|
|
1261
|
+
node: transformedNode,
|
|
1262
|
+
guidType,
|
|
1263
|
+
wrapOutput,
|
|
1264
|
+
inferTypeName,
|
|
1265
|
+
resolver
|
|
1266
|
+
}) : /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(Zod, {
|
|
1267
|
+
name: meta.name,
|
|
1268
|
+
node: transformedNode,
|
|
1269
|
+
coercion,
|
|
1270
|
+
guidType,
|
|
1271
|
+
wrapOutput,
|
|
1272
|
+
inferTypeName,
|
|
1273
|
+
resolver
|
|
1274
|
+
})
|
|
1275
|
+
]
|
|
1276
|
+
});
|
|
1277
|
+
},
|
|
1278
|
+
Operation({ node, adapter, options, config, resolver }) {
|
|
1279
|
+
const { output, coercion, guidType, mini, wrapOutput, inferred, importPath, group, paramsCasing, transformers } = options;
|
|
1280
|
+
const transformedNode = (0, _kubb_ast.transform)(node, (0, _kubb_ast.composeTransformers)(...transformers));
|
|
1281
|
+
const root = node_path.default.resolve(config.root, config.output.path);
|
|
1282
|
+
const mode = (0, _kubb_core.getMode)(node_path.default.resolve(root, output.path));
|
|
1283
|
+
const isZodImport = ZOD_NAMESPACE_IMPORTS.has(importPath);
|
|
1284
|
+
const params = (0, _kubb_ast.caseParams)(transformedNode.parameters, paramsCasing);
|
|
1285
|
+
const meta = { file: resolver.resolveFile({
|
|
1286
|
+
name: transformedNode.operationId,
|
|
1287
|
+
extname: ".ts",
|
|
1288
|
+
tag: transformedNode.tags[0] ?? "default",
|
|
1289
|
+
path: transformedNode.path
|
|
1290
|
+
}, {
|
|
1291
|
+
root,
|
|
1292
|
+
output,
|
|
1293
|
+
group
|
|
1294
|
+
}) };
|
|
1295
|
+
function renderSchemaEntry({ schema, name, keysToOmit }) {
|
|
1296
|
+
if (!schema) return null;
|
|
1297
|
+
const inferTypeName = inferred ? resolver.resolveInferName(name) : void 0;
|
|
1298
|
+
const imports = adapter.getImports(schema, (schemaName) => ({
|
|
1299
|
+
name: resolver.default(schemaName, "function"),
|
|
1300
|
+
path: resolver.resolveFile({
|
|
1301
|
+
name: schemaName,
|
|
1302
|
+
extname: ".ts"
|
|
1303
|
+
}, {
|
|
1304
|
+
root,
|
|
1305
|
+
output,
|
|
1306
|
+
group
|
|
1307
|
+
}).path
|
|
1308
|
+
}));
|
|
1309
|
+
return /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsxs)(_kubb_react_fabric_jsx_runtime.Fragment, { children: [mode === "split" && imports.map((imp) => /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(_kubb_react_fabric.File.Import, {
|
|
1310
|
+
root: meta.file.path,
|
|
1311
|
+
path: imp.path,
|
|
1312
|
+
name: imp.name
|
|
1313
|
+
}, [
|
|
1314
|
+
name,
|
|
1315
|
+
imp.path,
|
|
1316
|
+
imp.name
|
|
1317
|
+
].join("-"))), mini ? /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(ZodMini, {
|
|
1318
|
+
name,
|
|
1319
|
+
node: schema,
|
|
1320
|
+
guidType,
|
|
1321
|
+
wrapOutput,
|
|
1322
|
+
inferTypeName,
|
|
1323
|
+
resolver,
|
|
1324
|
+
keysToOmit
|
|
1325
|
+
}) : /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(Zod, {
|
|
1326
|
+
name,
|
|
1327
|
+
node: schema,
|
|
1328
|
+
coercion,
|
|
1329
|
+
guidType,
|
|
1330
|
+
wrapOutput,
|
|
1331
|
+
inferTypeName,
|
|
1332
|
+
resolver,
|
|
1333
|
+
keysToOmit
|
|
1334
|
+
})] });
|
|
1335
|
+
}
|
|
1336
|
+
const pathParams = params.filter((p) => p.in === "path");
|
|
1337
|
+
const queryParams = params.filter((p) => p.in === "query");
|
|
1338
|
+
const headerParams = params.filter((p) => p.in === "header");
|
|
1339
|
+
const responseSchemas = transformedNode.responses.map((res) => {
|
|
1340
|
+
const responseName = resolver.resolveResponseStatusName(transformedNode, res.statusCode);
|
|
1341
|
+
return renderSchemaEntry({
|
|
1342
|
+
schema: {
|
|
1343
|
+
...res.schema,
|
|
1344
|
+
description: res.description ?? res.schema.description
|
|
1345
|
+
},
|
|
1346
|
+
name: responseName,
|
|
1347
|
+
keysToOmit: res.keysToOmit
|
|
1348
|
+
});
|
|
1349
|
+
});
|
|
1350
|
+
const requestSchema = transformedNode.requestBody?.schema ? renderSchemaEntry({
|
|
1351
|
+
schema: {
|
|
1352
|
+
...transformedNode.requestBody.schema,
|
|
1353
|
+
description: transformedNode.requestBody.description ?? transformedNode.requestBody.schema.description
|
|
1354
|
+
},
|
|
1355
|
+
name: resolver.resolveDataName(transformedNode),
|
|
1356
|
+
keysToOmit: transformedNode.requestBody.keysToOmit
|
|
1357
|
+
}) : null;
|
|
1358
|
+
const legacyParamTypes = [
|
|
1359
|
+
pathParams.length > 0 ? renderSchemaEntry({
|
|
1360
|
+
schema: buildGroupedParamsSchema({
|
|
1361
|
+
params: pathParams,
|
|
1362
|
+
optional: pathParams.every((p) => !p.required)
|
|
1363
|
+
}),
|
|
1364
|
+
name: resolver.resolvePathParamsName(transformedNode, pathParams[0])
|
|
1365
|
+
}) : null,
|
|
1366
|
+
queryParams.length > 0 ? renderSchemaEntry({
|
|
1367
|
+
schema: buildGroupedParamsSchema({
|
|
1368
|
+
params: queryParams,
|
|
1369
|
+
optional: queryParams.every((p) => !p.required)
|
|
1370
|
+
}),
|
|
1371
|
+
name: resolver.resolveQueryParamsName(transformedNode, queryParams[0])
|
|
1372
|
+
}) : null,
|
|
1373
|
+
headerParams.length > 0 ? renderSchemaEntry({
|
|
1374
|
+
schema: buildGroupedParamsSchema({
|
|
1375
|
+
params: headerParams,
|
|
1376
|
+
optional: headerParams.every((p) => !p.required)
|
|
1377
|
+
}),
|
|
1378
|
+
name: resolver.resolveHeaderParamsName(transformedNode, headerParams[0])
|
|
1379
|
+
}) : null
|
|
1380
|
+
];
|
|
1381
|
+
const legacyResponsesSchema = renderSchemaEntry({
|
|
1382
|
+
schema: buildLegacyResponsesSchemaNode(transformedNode, { resolver }),
|
|
1383
|
+
name: resolver.resolveResponsesName(transformedNode)
|
|
1384
|
+
});
|
|
1385
|
+
const legacyResponseSchema = renderSchemaEntry({
|
|
1386
|
+
schema: buildLegacyResponseUnionSchemaNode(transformedNode, { resolver }),
|
|
1387
|
+
name: resolver.resolveResponseName(transformedNode)
|
|
1388
|
+
});
|
|
1389
|
+
return /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsxs)(_kubb_react_fabric.File, {
|
|
1390
|
+
baseName: meta.file.baseName,
|
|
1391
|
+
path: meta.file.path,
|
|
1392
|
+
meta: meta.file.meta,
|
|
1393
|
+
banner: resolver.resolveBanner(adapter.rootNode, {
|
|
1394
|
+
output,
|
|
1395
|
+
config
|
|
1396
|
+
}),
|
|
1397
|
+
footer: resolver.resolveFooter(adapter.rootNode, {
|
|
1398
|
+
output,
|
|
1399
|
+
config
|
|
1400
|
+
}),
|
|
1401
|
+
children: [
|
|
1402
|
+
/* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(_kubb_react_fabric.File.Import, {
|
|
1403
|
+
name: isZodImport ? "z" : ["z"],
|
|
1404
|
+
path: importPath,
|
|
1405
|
+
isNameSpace: isZodImport
|
|
1406
|
+
}),
|
|
1407
|
+
legacyParamTypes,
|
|
1408
|
+
responseSchemas,
|
|
1409
|
+
requestSchema,
|
|
1410
|
+
legacyResponseSchema,
|
|
1411
|
+
legacyResponsesSchema
|
|
1412
|
+
]
|
|
1413
|
+
});
|
|
1414
|
+
},
|
|
1415
|
+
Operations({ nodes, adapter, options, config, resolver }) {
|
|
1416
|
+
const { output, importPath, group, operations, paramsCasing, transformers } = options;
|
|
1417
|
+
if (!operations) return;
|
|
1418
|
+
const root = node_path.default.resolve(config.root, config.output.path);
|
|
1419
|
+
const isZodImport = ZOD_NAMESPACE_IMPORTS.has(importPath);
|
|
1420
|
+
const meta = { file: resolver.resolveFile({
|
|
1421
|
+
name: "operations",
|
|
1422
|
+
extname: ".ts"
|
|
1423
|
+
}, {
|
|
1424
|
+
root,
|
|
1425
|
+
output,
|
|
1426
|
+
group
|
|
1427
|
+
}) };
|
|
1428
|
+
const transformedOperations = nodes.map((node) => {
|
|
1429
|
+
const transformedNode = (0, _kubb_ast.transform)(node, (0, _kubb_ast.composeTransformers)(...transformers));
|
|
1430
|
+
return {
|
|
1431
|
+
node: transformedNode,
|
|
1432
|
+
data: buildLegacySchemaNames(transformedNode, (0, _kubb_ast.caseParams)(transformedNode.parameters, paramsCasing), resolver)
|
|
1433
|
+
};
|
|
1434
|
+
});
|
|
1435
|
+
const imports = transformedOperations.flatMap(({ node, data }) => {
|
|
1436
|
+
const names = [
|
|
1437
|
+
data.request,
|
|
1438
|
+
...Object.values(data.responses),
|
|
1439
|
+
...Object.values(data.parameters)
|
|
1440
|
+
].filter(Boolean);
|
|
1441
|
+
const opFile = resolver.resolveFile({
|
|
1442
|
+
name: node.operationId,
|
|
1443
|
+
extname: ".ts",
|
|
1444
|
+
tag: node.tags[0] ?? "default",
|
|
1445
|
+
path: node.path
|
|
1446
|
+
}, {
|
|
1447
|
+
root,
|
|
1448
|
+
output,
|
|
1449
|
+
group
|
|
1450
|
+
});
|
|
1451
|
+
return names.map((name) => /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(_kubb_react_fabric.File.Import, {
|
|
1452
|
+
name: [name],
|
|
1453
|
+
root: meta.file.path,
|
|
1454
|
+
path: opFile.path
|
|
1455
|
+
}, [name, opFile.path].join("-")));
|
|
1456
|
+
});
|
|
1457
|
+
return /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsxs)(_kubb_react_fabric.File, {
|
|
1458
|
+
baseName: meta.file.baseName,
|
|
1459
|
+
path: meta.file.path,
|
|
1460
|
+
meta: meta.file.meta,
|
|
1461
|
+
banner: resolver.resolveBanner(adapter.rootNode, {
|
|
1462
|
+
output,
|
|
1463
|
+
config
|
|
1464
|
+
}),
|
|
1465
|
+
footer: resolver.resolveFooter(adapter.rootNode, {
|
|
1466
|
+
output,
|
|
1467
|
+
config
|
|
1468
|
+
}),
|
|
1469
|
+
children: [
|
|
1470
|
+
/* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(_kubb_react_fabric.File.Import, {
|
|
1471
|
+
isTypeOnly: true,
|
|
1472
|
+
name: isZodImport ? "z" : ["z"],
|
|
1473
|
+
path: importPath,
|
|
1474
|
+
isNameSpace: isZodImport
|
|
1475
|
+
}),
|
|
1476
|
+
imports,
|
|
1477
|
+
/* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(Operations, {
|
|
1478
|
+
name: "operations",
|
|
1479
|
+
operations: transformedOperations
|
|
1480
|
+
})
|
|
1481
|
+
]
|
|
1482
|
+
});
|
|
1483
|
+
}
|
|
1484
|
+
});
|
|
1485
|
+
//#endregion
|
|
1486
|
+
//#region src/resolvers/resolverZod.ts
|
|
1487
|
+
function toSchemaName(name, type) {
|
|
1488
|
+
const resolved = camelCase(name, {
|
|
1489
|
+
suffix: type ? "schema" : void 0,
|
|
1490
|
+
isFile: type === "file"
|
|
1491
|
+
});
|
|
1492
|
+
if (type === "type") return pascalCase(resolved);
|
|
1493
|
+
return resolved;
|
|
1494
|
+
}
|
|
1495
|
+
/**
|
|
1496
|
+
* Default resolver for `@kubb/plugin-zod`.
|
|
1497
|
+
*
|
|
1498
|
+
* Uses `camelCase` naming with a `Schema` suffix for function/type/const names.
|
|
1499
|
+
*
|
|
1500
|
+
* @example
|
|
1501
|
+
* ```ts
|
|
1502
|
+
* resolverZod.default('list pets', 'function') // → 'listPetsSchema'
|
|
1503
|
+
* resolverZod.default('Pet', 'file') // → 'pet'
|
|
1504
|
+
* resolverZod.resolveName('list pets') // → 'listPetsSchema'
|
|
1505
|
+
* ```
|
|
1506
|
+
*/
|
|
1507
|
+
const resolverZod = (0, _kubb_core.defineResolver)(() => {
|
|
1508
|
+
return {
|
|
1509
|
+
name: "default",
|
|
1510
|
+
pluginName: "plugin-zod",
|
|
1511
|
+
default(name, type) {
|
|
1512
|
+
return toSchemaName(name, type);
|
|
1513
|
+
},
|
|
1514
|
+
resolveName(name) {
|
|
1515
|
+
return this.default(name, "function");
|
|
1516
|
+
},
|
|
1517
|
+
resolveInferName(name) {
|
|
1518
|
+
return pascalCase(name);
|
|
1519
|
+
},
|
|
1520
|
+
resolvePathName(name, type) {
|
|
1521
|
+
return this.default(name, type);
|
|
1522
|
+
},
|
|
1523
|
+
resolveParamName(node, param) {
|
|
1524
|
+
return this.resolveName(`${node.operationId} ${param.in} ${param.name}`);
|
|
1525
|
+
},
|
|
1526
|
+
resolveResponseStatusName(node, statusCode) {
|
|
1527
|
+
return this.resolveName(`${node.operationId} Status ${statusCode}`);
|
|
1528
|
+
},
|
|
1529
|
+
resolveDataName(node) {
|
|
1530
|
+
return this.resolveName(`${node.operationId} Data`);
|
|
1531
|
+
},
|
|
1532
|
+
resolveResponsesName(node) {
|
|
1533
|
+
return this.resolveName(`${node.operationId} Responses`);
|
|
1534
|
+
},
|
|
1535
|
+
resolveResponseName(node) {
|
|
1536
|
+
return this.resolveName(`${node.operationId} Response`);
|
|
1537
|
+
},
|
|
1538
|
+
resolvePathParamsName(node, param) {
|
|
1539
|
+
return this.resolveParamName(node, param);
|
|
1540
|
+
},
|
|
1541
|
+
resolveQueryParamsName(node, param) {
|
|
1542
|
+
return this.resolveParamName(node, param);
|
|
1543
|
+
},
|
|
1544
|
+
resolveHeaderParamsName(node, param) {
|
|
1545
|
+
return this.resolveParamName(node, param);
|
|
1546
|
+
}
|
|
1547
|
+
};
|
|
1548
|
+
});
|
|
1549
|
+
//#endregion
|
|
1550
|
+
//#region src/resolvers/resolverZodLegacy.ts
|
|
1551
|
+
/**
|
|
1552
|
+
* Legacy resolver for `@kubb/plugin-zod` that reproduces the naming conventions
|
|
1553
|
+
* used in Kubb v4. Enable via `compatibilityPreset: 'kubbV4'`
|
|
1554
|
+
* (or by composing this resolver manually).
|
|
1555
|
+
*
|
|
1556
|
+
* Key differences from the default resolver:
|
|
1557
|
+
* - Response status types: `<operationId><StatusCode>Schema` (e.g. `createPets201Schema`) instead of `<operationId>Status201Schema`
|
|
1558
|
+
* - Default/error responses: `<operationId>ErrorSchema` instead of `<operationId>StatusDefaultSchema`
|
|
1559
|
+
* - Request body: `<operationId>MutationRequestSchema` (non-GET) / `<operationId>QueryRequestSchema` (GET)
|
|
1560
|
+
* - Combined responses type: `<operationId>MutationSchema` / `<operationId>QuerySchema`
|
|
1561
|
+
* - Response union: `<operationId>MutationResponseSchema` / `<operationId>QueryResponseSchema`
|
|
1562
|
+
*
|
|
1563
|
+
* @example
|
|
1564
|
+
* ```ts
|
|
1565
|
+
* import { resolverZodLegacy } from '@kubb/plugin-zod'
|
|
1566
|
+
*
|
|
1567
|
+
* resolverZodLegacy.resolveResponseStatusName(node, 201) // → 'createPets201Schema'
|
|
1568
|
+
* resolverZodLegacy.resolveResponseStatusName(node, 'default') // → 'createPetsErrorSchema'
|
|
1569
|
+
* resolverZodLegacy.resolveDataName(node) // → 'createPetsMutationRequestSchema' (POST)
|
|
1570
|
+
* resolverZodLegacy.resolveResponsesName(node) // → 'createPetsMutationSchema' (POST)
|
|
1571
|
+
* resolverZodLegacy.resolveResponseName(node) // → 'createPetsMutationResponseSchema' (POST)
|
|
1572
|
+
* ```
|
|
1573
|
+
*/
|
|
1574
|
+
const resolverZodLegacy = (0, _kubb_core.defineResolver)(() => {
|
|
1575
|
+
return {
|
|
1576
|
+
...resolverZod,
|
|
1577
|
+
pluginName: "plugin-zod",
|
|
1578
|
+
resolveResponseStatusName(node, statusCode) {
|
|
1579
|
+
if (statusCode === "default") return this.resolveName(`${node.operationId} Error`);
|
|
1580
|
+
return this.resolveName(`${node.operationId} ${statusCode}`);
|
|
1581
|
+
},
|
|
1582
|
+
resolveDataName(node) {
|
|
1583
|
+
const suffix = node.method === "GET" ? "QueryRequest" : "MutationRequest";
|
|
1584
|
+
return this.resolveName(`${node.operationId} ${suffix}`);
|
|
1585
|
+
},
|
|
1586
|
+
resolveResponsesName(node) {
|
|
1587
|
+
const suffix = node.method === "GET" ? "Query" : "Mutation";
|
|
1588
|
+
return this.resolveName(`${node.operationId} ${suffix}`);
|
|
1589
|
+
},
|
|
1590
|
+
resolveResponseName(node) {
|
|
1591
|
+
const suffix = node.method === "GET" ? "QueryResponse" : "MutationResponse";
|
|
1592
|
+
return this.resolveName(`${node.operationId} ${suffix}`);
|
|
1593
|
+
},
|
|
1594
|
+
resolvePathParamsName(node, _param) {
|
|
1595
|
+
return this.resolveName(`${node.operationId} PathParams`);
|
|
1596
|
+
},
|
|
1597
|
+
resolveQueryParamsName(node, _param) {
|
|
1598
|
+
return this.resolveName(`${node.operationId} QueryParams`);
|
|
1599
|
+
},
|
|
1600
|
+
resolveHeaderParamsName(node, _param) {
|
|
1601
|
+
return this.resolveName(`${node.operationId} HeaderParams`);
|
|
1602
|
+
}
|
|
1603
|
+
};
|
|
1604
|
+
});
|
|
1605
|
+
//#endregion
|
|
1606
|
+
//#region src/presets.ts
|
|
1607
|
+
/**
|
|
1608
|
+
* Built-in preset registry for `@kubb/plugin-zod`.
|
|
1609
|
+
*
|
|
1610
|
+
* - `default` — uses `resolverZod` and `zodGenerator` (current naming conventions).
|
|
1611
|
+
* - `kubbV4` — uses `resolverZodLegacy` and `zodGeneratorLegacy` (Kubb v4 naming conventions).
|
|
1612
|
+
*/
|
|
1613
|
+
const presets = (0, _kubb_core.definePresets)({
|
|
1614
|
+
default: {
|
|
1615
|
+
name: "default",
|
|
1616
|
+
resolvers: [resolverZod],
|
|
1617
|
+
generators: [zodGenerator]
|
|
1618
|
+
},
|
|
1619
|
+
kubbV4: {
|
|
1620
|
+
name: "kubbV4",
|
|
1621
|
+
resolvers: [resolverZodLegacy],
|
|
1622
|
+
generators: [zodGeneratorLegacy]
|
|
1623
|
+
}
|
|
1624
|
+
});
|
|
1625
|
+
//#endregion
|
|
68
1626
|
//#region src/plugin.ts
|
|
1627
|
+
/**
|
|
1628
|
+
* Canonical plugin name for `@kubb/plugin-zod`, used to identify the plugin in driver lookups and warnings.
|
|
1629
|
+
*/
|
|
69
1630
|
const pluginZodName = "plugin-zod";
|
|
1631
|
+
/**
|
|
1632
|
+
* The `@kubb/plugin-zod` plugin factory.
|
|
1633
|
+
*
|
|
1634
|
+
* Generates Zod validation schemas from an OpenAPI/AST `RootNode`.
|
|
1635
|
+
* Walks schemas and operations, delegates rendering to the active generators,
|
|
1636
|
+
* and writes barrel files based on `output.barrelType`.
|
|
1637
|
+
*
|
|
1638
|
+
* @example
|
|
1639
|
+
* ```ts
|
|
1640
|
+
* import { pluginZod } from '@kubb/plugin-zod'
|
|
1641
|
+
*
|
|
1642
|
+
* export default defineConfig({
|
|
1643
|
+
* plugins: [pluginZod({ output: { path: 'zod' } })],
|
|
1644
|
+
* })
|
|
1645
|
+
* ```
|
|
1646
|
+
*/
|
|
70
1647
|
const pluginZod = (0, _kubb_core.createPlugin)((options) => {
|
|
71
1648
|
const { output = {
|
|
72
1649
|
path: "zod",
|
|
73
1650
|
barrelType: "named"
|
|
74
|
-
}, group, exclude = [], include, override = [],
|
|
1651
|
+
}, group, exclude = [], include, override = [], dateType = "string", typed = false, operations = false, mini = false, guidType = "uuid", importPath = mini ? "zod/mini" : "zod", coercion = false, inferred = false, wrapOutput = void 0, paramsCasing, compatibilityPreset = "default", resolvers: userResolvers = [], transformers: userTransformers = [], generators: userGenerators = [] } = options;
|
|
1652
|
+
const preset = (0, _kubb_core.getPreset)({
|
|
1653
|
+
preset: compatibilityPreset,
|
|
1654
|
+
presets,
|
|
1655
|
+
resolvers: userResolvers,
|
|
1656
|
+
transformers: userTransformers,
|
|
1657
|
+
generators: userGenerators
|
|
1658
|
+
});
|
|
1659
|
+
let resolveNameWarning = false;
|
|
1660
|
+
let resolvePathWarning = false;
|
|
75
1661
|
return {
|
|
76
1662
|
name: pluginZodName,
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
1663
|
+
get resolver() {
|
|
1664
|
+
return preset.resolver;
|
|
1665
|
+
},
|
|
1666
|
+
get options() {
|
|
1667
|
+
return {
|
|
1668
|
+
output,
|
|
1669
|
+
group: group ? {
|
|
1670
|
+
...group,
|
|
1671
|
+
name: (ctx) => {
|
|
1672
|
+
if (group.type === "path") return `${ctx.group.split("/")[1]}`;
|
|
1673
|
+
return `${camelCase(ctx.group)}Controller`;
|
|
1674
|
+
}
|
|
1675
|
+
} : void 0,
|
|
1676
|
+
dateType,
|
|
1677
|
+
typed,
|
|
1678
|
+
importPath,
|
|
1679
|
+
coercion,
|
|
1680
|
+
operations,
|
|
1681
|
+
inferred,
|
|
1682
|
+
guidType,
|
|
1683
|
+
mini,
|
|
1684
|
+
wrapOutput,
|
|
1685
|
+
paramsCasing,
|
|
1686
|
+
transformers: preset.transformers
|
|
1687
|
+
};
|
|
1688
|
+
},
|
|
101
1689
|
resolvePath(baseName, pathMode, options) {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
* when output is a file then we will always append to the same file(output file), see fileManager.addOrAppend
|
|
106
|
-
* Other plugins then need to call addOrAppend instead of just add from the fileManager class
|
|
107
|
-
*/
|
|
108
|
-
return node_path.default.resolve(root, output.path);
|
|
109
|
-
if (group && (options?.group?.path || options?.group?.tag)) {
|
|
110
|
-
const groupName = group?.name ? group.name : (ctx) => {
|
|
111
|
-
if (group?.type === "path") return `${ctx.group.split("/")[1]}`;
|
|
112
|
-
return `${camelCase(ctx.group)}Controller`;
|
|
113
|
-
};
|
|
114
|
-
return node_path.default.resolve(root, output.path, groupName({ group: group.type === "path" ? options.group.path : options.group.tag }), baseName);
|
|
1690
|
+
if (!resolvePathWarning) {
|
|
1691
|
+
this.events.emit("warn", "Do not use resolvePath for pluginZod, use resolverZod.resolvePath instead");
|
|
1692
|
+
resolvePathWarning = true;
|
|
115
1693
|
}
|
|
116
|
-
return
|
|
1694
|
+
return this.plugin.resolver.resolvePath({
|
|
1695
|
+
baseName,
|
|
1696
|
+
pathMode,
|
|
1697
|
+
tag: options?.group?.tag,
|
|
1698
|
+
path: options?.group?.path
|
|
1699
|
+
}, {
|
|
1700
|
+
root: node_path.default.resolve(this.config.root, this.config.output.path),
|
|
1701
|
+
output,
|
|
1702
|
+
group: this.plugin.options.group
|
|
1703
|
+
});
|
|
117
1704
|
},
|
|
118
1705
|
resolveName(name, type) {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
if (type) return transformers?.name?.(resolvedName, type) || resolvedName;
|
|
125
|
-
return resolvedName;
|
|
1706
|
+
if (!resolveNameWarning) {
|
|
1707
|
+
this.events.emit("warn", "Do not use resolveName for pluginZod, use resolverZod.default instead");
|
|
1708
|
+
resolveNameWarning = true;
|
|
1709
|
+
}
|
|
1710
|
+
return this.plugin.resolver.default(name, type);
|
|
126
1711
|
},
|
|
127
1712
|
async install() {
|
|
128
|
-
const
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
}],
|
|
138
|
-
imports: [],
|
|
139
|
-
exports: []
|
|
140
|
-
});
|
|
141
|
-
const schemaFiles = await new _kubb_plugin_oas.SchemaGenerator(this.plugin.options, {
|
|
142
|
-
fabric: this.fabric,
|
|
143
|
-
oas,
|
|
144
|
-
driver: this.driver,
|
|
145
|
-
events: this.events,
|
|
146
|
-
plugin: this.plugin,
|
|
147
|
-
contentType,
|
|
148
|
-
include: void 0,
|
|
149
|
-
override,
|
|
150
|
-
mode,
|
|
151
|
-
output: output.path
|
|
152
|
-
}).build(...generators);
|
|
153
|
-
await this.upsertFile(...schemaFiles);
|
|
154
|
-
const operationFiles = await new _kubb_plugin_oas.OperationGenerator(this.plugin.options, {
|
|
155
|
-
fabric: this.fabric,
|
|
156
|
-
oas,
|
|
157
|
-
driver: this.driver,
|
|
158
|
-
events: this.events,
|
|
159
|
-
plugin: this.plugin,
|
|
160
|
-
contentType,
|
|
1713
|
+
const { config, fabric, plugin, adapter, rootNode, driver, openInStudio, resolver } = this;
|
|
1714
|
+
const root = node_path.default.resolve(config.root, config.output.path);
|
|
1715
|
+
if (!adapter) throw new Error(`[${pluginZodName}] No adapter found. Add an OAS adapter (e.g. pluginOas()) before this plugin in your Kubb config.`);
|
|
1716
|
+
await openInStudio({ ast: true });
|
|
1717
|
+
const collectedOperations = [];
|
|
1718
|
+
const generatorContext = {
|
|
1719
|
+
generators: preset.generators,
|
|
1720
|
+
plugin,
|
|
1721
|
+
resolver,
|
|
161
1722
|
exclude,
|
|
162
1723
|
include,
|
|
163
1724
|
override,
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
1725
|
+
fabric,
|
|
1726
|
+
adapter,
|
|
1727
|
+
config,
|
|
1728
|
+
driver
|
|
1729
|
+
};
|
|
1730
|
+
await (0, _kubb_ast.walk)(rootNode, {
|
|
1731
|
+
depth: "shallow",
|
|
1732
|
+
async schema(schemaNode) {
|
|
1733
|
+
await (0, _kubb_core.runGeneratorSchema)(schemaNode, generatorContext);
|
|
1734
|
+
},
|
|
1735
|
+
async operation(operationNode) {
|
|
1736
|
+
if (resolver.resolveOptions(operationNode, {
|
|
1737
|
+
options: plugin.options,
|
|
1738
|
+
exclude,
|
|
1739
|
+
include,
|
|
1740
|
+
override
|
|
1741
|
+
}) !== null) collectedOperations.push(operationNode);
|
|
1742
|
+
await (0, _kubb_core.runGeneratorOperation)(operationNode, generatorContext);
|
|
1743
|
+
}
|
|
1744
|
+
});
|
|
1745
|
+
await (0, _kubb_core.runGeneratorOperations)(collectedOperations, generatorContext);
|
|
167
1746
|
const barrelFiles = await (0, _kubb_core.getBarrelFiles)(this.fabric.files, {
|
|
168
1747
|
type: output.barrelType ?? "named",
|
|
169
1748
|
root,
|
|
@@ -177,5 +1756,11 @@ const pluginZod = (0, _kubb_core.createPlugin)((options) => {
|
|
|
177
1756
|
//#endregion
|
|
178
1757
|
exports.pluginZod = pluginZod;
|
|
179
1758
|
exports.pluginZodName = pluginZodName;
|
|
1759
|
+
exports.printerZod = printerZod;
|
|
1760
|
+
exports.printerZodMini = printerZodMini;
|
|
1761
|
+
exports.resolverZod = resolverZod;
|
|
1762
|
+
exports.resolverZodLegacy = resolverZodLegacy;
|
|
1763
|
+
exports.zodGenerator = zodGenerator;
|
|
1764
|
+
exports.zodGeneratorLegacy = zodGeneratorLegacy;
|
|
180
1765
|
|
|
181
1766
|
//# sourceMappingURL=index.cjs.map
|