@kubb/plugin-zod 5.0.0-beta.22 → 5.0.0-beta.27
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 +176 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +77 -32
- package/dist/index.js +176 -28
- package/dist/index.js.map +1 -1
- package/extension.yaml +646 -185
- package/package.json +4 -4
- package/src/components/Operations.tsx +4 -4
- package/src/components/Zod.tsx +1 -1
- package/src/generators/zodGenerator.tsx +21 -9
- package/src/plugin.ts +21 -8
- package/src/resolvers/resolverZod.ts +15 -9
- package/src/types.ts +42 -21
- package/src/utils.ts +6 -6
package/dist/index.cjs
CHANGED
|
@@ -136,6 +136,129 @@ function toRegExpString(text, func = "RegExp") {
|
|
|
136
136
|
return `new ${func}(${JSON.stringify(source)}${flags ? `, ${JSON.stringify(flags)}` : ""})`;
|
|
137
137
|
}
|
|
138
138
|
//#endregion
|
|
139
|
+
//#region ../../internals/utils/src/reserved.ts
|
|
140
|
+
/**
|
|
141
|
+
* JavaScript and Java reserved words.
|
|
142
|
+
* @link https://github.com/jonschlinkert/reserved/blob/master/index.js
|
|
143
|
+
*/
|
|
144
|
+
const reservedWords = new Set([
|
|
145
|
+
"abstract",
|
|
146
|
+
"arguments",
|
|
147
|
+
"boolean",
|
|
148
|
+
"break",
|
|
149
|
+
"byte",
|
|
150
|
+
"case",
|
|
151
|
+
"catch",
|
|
152
|
+
"char",
|
|
153
|
+
"class",
|
|
154
|
+
"const",
|
|
155
|
+
"continue",
|
|
156
|
+
"debugger",
|
|
157
|
+
"default",
|
|
158
|
+
"delete",
|
|
159
|
+
"do",
|
|
160
|
+
"double",
|
|
161
|
+
"else",
|
|
162
|
+
"enum",
|
|
163
|
+
"eval",
|
|
164
|
+
"export",
|
|
165
|
+
"extends",
|
|
166
|
+
"false",
|
|
167
|
+
"final",
|
|
168
|
+
"finally",
|
|
169
|
+
"float",
|
|
170
|
+
"for",
|
|
171
|
+
"function",
|
|
172
|
+
"goto",
|
|
173
|
+
"if",
|
|
174
|
+
"implements",
|
|
175
|
+
"import",
|
|
176
|
+
"in",
|
|
177
|
+
"instanceof",
|
|
178
|
+
"int",
|
|
179
|
+
"interface",
|
|
180
|
+
"let",
|
|
181
|
+
"long",
|
|
182
|
+
"native",
|
|
183
|
+
"new",
|
|
184
|
+
"null",
|
|
185
|
+
"package",
|
|
186
|
+
"private",
|
|
187
|
+
"protected",
|
|
188
|
+
"public",
|
|
189
|
+
"return",
|
|
190
|
+
"short",
|
|
191
|
+
"static",
|
|
192
|
+
"super",
|
|
193
|
+
"switch",
|
|
194
|
+
"synchronized",
|
|
195
|
+
"this",
|
|
196
|
+
"throw",
|
|
197
|
+
"throws",
|
|
198
|
+
"transient",
|
|
199
|
+
"true",
|
|
200
|
+
"try",
|
|
201
|
+
"typeof",
|
|
202
|
+
"var",
|
|
203
|
+
"void",
|
|
204
|
+
"volatile",
|
|
205
|
+
"while",
|
|
206
|
+
"with",
|
|
207
|
+
"yield",
|
|
208
|
+
"Array",
|
|
209
|
+
"Date",
|
|
210
|
+
"hasOwnProperty",
|
|
211
|
+
"Infinity",
|
|
212
|
+
"isFinite",
|
|
213
|
+
"isNaN",
|
|
214
|
+
"isPrototypeOf",
|
|
215
|
+
"length",
|
|
216
|
+
"Math",
|
|
217
|
+
"name",
|
|
218
|
+
"NaN",
|
|
219
|
+
"Number",
|
|
220
|
+
"Object",
|
|
221
|
+
"prototype",
|
|
222
|
+
"String",
|
|
223
|
+
"toString",
|
|
224
|
+
"undefined",
|
|
225
|
+
"valueOf"
|
|
226
|
+
]);
|
|
227
|
+
/**
|
|
228
|
+
* Returns `true` when `name` is a syntactically valid JavaScript variable name.
|
|
229
|
+
*
|
|
230
|
+
* @example
|
|
231
|
+
* ```ts
|
|
232
|
+
* isValidVarName('status') // true
|
|
233
|
+
* isValidVarName('class') // false (reserved word)
|
|
234
|
+
* isValidVarName('42foo') // false (starts with digit)
|
|
235
|
+
* ```
|
|
236
|
+
*/
|
|
237
|
+
function isValidVarName(name) {
|
|
238
|
+
if (!name || reservedWords.has(name)) return false;
|
|
239
|
+
return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Returns `name` when it's a syntactically valid JavaScript variable name,
|
|
243
|
+
* otherwise prefixes it with `_` so the result is a valid identifier.
|
|
244
|
+
*
|
|
245
|
+
* Useful for sanitizing OpenAPI schema names or operation IDs that start with
|
|
246
|
+
* a digit (e.g. `409`, `504AccountCancel`) before using them as exported
|
|
247
|
+
* variable, type, or function names.
|
|
248
|
+
*
|
|
249
|
+
* @example
|
|
250
|
+
* ```ts
|
|
251
|
+
* ensureValidVarName('409') // '_409'
|
|
252
|
+
* ensureValidVarName('504AccountCancel') // '_504AccountCancel'
|
|
253
|
+
* ensureValidVarName('Pet') // 'Pet'
|
|
254
|
+
* ensureValidVarName('class') // '_class'
|
|
255
|
+
* ```
|
|
256
|
+
*/
|
|
257
|
+
function ensureValidVarName(name) {
|
|
258
|
+
if (!name || isValidVarName(name)) return name;
|
|
259
|
+
return `_${name}`;
|
|
260
|
+
}
|
|
261
|
+
//#endregion
|
|
139
262
|
//#region src/components/Operations.tsx
|
|
140
263
|
function Operations({ name, operations }) {
|
|
141
264
|
const operationsJSON = operations.reduce((prev, acc) => {
|
|
@@ -271,11 +394,11 @@ function buildSchemaNames(node, { params, resolver }) {
|
|
|
271
394
|
}
|
|
272
395
|
responses["default"] = resolver.resolveResponseName(node);
|
|
273
396
|
return {
|
|
274
|
-
request: node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) :
|
|
397
|
+
request: node.requestBody?.content?.[0]?.schema ? resolver.resolveDataName(node) : null,
|
|
275
398
|
parameters: {
|
|
276
|
-
path: pathParam ? resolver.resolvePathParamsName(node, pathParam) :
|
|
277
|
-
query: queryParam ? resolver.resolveQueryParamsName(node, queryParam) :
|
|
278
|
-
header: headerParam ? resolver.resolveHeaderParamsName(node, headerParam) :
|
|
399
|
+
path: pathParam ? resolver.resolvePathParamsName(node, pathParam) : null,
|
|
400
|
+
query: queryParam ? resolver.resolveQueryParamsName(node, queryParam) : null,
|
|
401
|
+
header: headerParam ? resolver.resolveHeaderParamsName(node, headerParam) : null
|
|
279
402
|
},
|
|
280
403
|
responses,
|
|
281
404
|
errors
|
|
@@ -727,6 +850,12 @@ const printerZodMini = _kubb_core.ast.definePrinter((options) => {
|
|
|
727
850
|
//#region src/generators/zodGenerator.tsx
|
|
728
851
|
const zodPrinterCache = /* @__PURE__ */ new WeakMap();
|
|
729
852
|
const zodMiniPrinterCache = /* @__PURE__ */ new WeakMap();
|
|
853
|
+
/**
|
|
854
|
+
* Built-in generator for `@kubb/plugin-zod`. Emits one Zod schema per
|
|
855
|
+
* schema in the spec plus per-operation request/response/parameter schemas.
|
|
856
|
+
* When `mini: true`, schemas use the Zod Mini functional API instead of
|
|
857
|
+
* chainable methods.
|
|
858
|
+
*/
|
|
730
859
|
const zodGenerator = (0, _kubb_core.defineGenerator)({
|
|
731
860
|
name: "zod",
|
|
732
861
|
renderer: _kubb_renderer_jsx.jsxRendererSync,
|
|
@@ -745,7 +874,7 @@ const zodGenerator = (0, _kubb_core.defineGenerator)({
|
|
|
745
874
|
}, {
|
|
746
875
|
root,
|
|
747
876
|
output,
|
|
748
|
-
group
|
|
877
|
+
group: group ?? void 0
|
|
749
878
|
}).path
|
|
750
879
|
}));
|
|
751
880
|
const meta = {
|
|
@@ -756,10 +885,10 @@ const zodGenerator = (0, _kubb_core.defineGenerator)({
|
|
|
756
885
|
}, {
|
|
757
886
|
root,
|
|
758
887
|
output,
|
|
759
|
-
group
|
|
888
|
+
group: group ?? void 0
|
|
760
889
|
})
|
|
761
890
|
};
|
|
762
|
-
const inferTypeName = inferred ? resolver.resolveSchemaTypeName(node.name) :
|
|
891
|
+
const inferTypeName = inferred ? resolver.resolveSchemaTypeName(node.name) : null;
|
|
763
892
|
const cyclicSchemas = new Set(ctx.meta.circularNames);
|
|
764
893
|
const schemaPrinter = mini ? getCachedMiniPrinter() : getCachedStdPrinter();
|
|
765
894
|
function getCachedStdPrinter() {
|
|
@@ -845,12 +974,12 @@ const zodGenerator = (0, _kubb_core.defineGenerator)({
|
|
|
845
974
|
}, {
|
|
846
975
|
root,
|
|
847
976
|
output,
|
|
848
|
-
group
|
|
977
|
+
group: group ?? void 0
|
|
849
978
|
}) };
|
|
850
979
|
const cyclicSchemas = new Set(ctx.meta.circularNames);
|
|
851
980
|
function renderSchemaEntry({ schema, name, keysToOmit }) {
|
|
852
981
|
if (!schema) return null;
|
|
853
|
-
const inferTypeName = inferred ? resolver.resolveTypeName(name) :
|
|
982
|
+
const inferTypeName = inferred ? resolver.resolveTypeName(name) : null;
|
|
854
983
|
const imports = adapter.getImports(schema, (schemaName) => ({
|
|
855
984
|
name: resolver.resolveSchemaName(schemaName),
|
|
856
985
|
path: resolver.resolveFile({
|
|
@@ -859,7 +988,7 @@ const zodGenerator = (0, _kubb_core.defineGenerator)({
|
|
|
859
988
|
}, {
|
|
860
989
|
root,
|
|
861
990
|
output,
|
|
862
|
-
group
|
|
991
|
+
group: group ?? void 0
|
|
863
992
|
}).path
|
|
864
993
|
}));
|
|
865
994
|
const cachedStd = zodPrinterCache.get(resolver);
|
|
@@ -982,7 +1111,7 @@ const zodGenerator = (0, _kubb_core.defineGenerator)({
|
|
|
982
1111
|
}, {
|
|
983
1112
|
root,
|
|
984
1113
|
output,
|
|
985
|
-
group
|
|
1114
|
+
group: group ?? void 0
|
|
986
1115
|
}) };
|
|
987
1116
|
const transformedOperations = nodes.map((node) => {
|
|
988
1117
|
return {
|
|
@@ -1007,7 +1136,7 @@ const zodGenerator = (0, _kubb_core.defineGenerator)({
|
|
|
1007
1136
|
}, {
|
|
1008
1137
|
root,
|
|
1009
1138
|
output,
|
|
1010
|
-
group
|
|
1139
|
+
group: group ?? void 0
|
|
1011
1140
|
});
|
|
1012
1141
|
return names.map((name) => /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
|
|
1013
1142
|
name: [name],
|
|
@@ -1046,31 +1175,37 @@ const zodGenerator = (0, _kubb_core.defineGenerator)({
|
|
|
1046
1175
|
//#endregion
|
|
1047
1176
|
//#region src/resolvers/resolverZod.ts
|
|
1048
1177
|
/**
|
|
1049
|
-
*
|
|
1178
|
+
* Default resolver used by `@kubb/plugin-zod`. Decides the names and file
|
|
1179
|
+
* paths for every generated Zod schema. Schemas use camelCase with a
|
|
1180
|
+
* `Schema` suffix (`listPetsSchema`); their inferred types use PascalCase.
|
|
1050
1181
|
*
|
|
1051
|
-
*
|
|
1182
|
+
* @example Resolve schema and type names
|
|
1183
|
+
* ```ts
|
|
1184
|
+
* import { resolverZod } from '@kubb/plugin-zod'
|
|
1052
1185
|
*
|
|
1053
|
-
*
|
|
1054
|
-
*
|
|
1186
|
+
* resolverZod.default('list pets', 'function') // 'listPetsSchema'
|
|
1187
|
+
* resolverZod.resolveSchemaTypeName('pet') // 'PetSchema'
|
|
1188
|
+
* ```
|
|
1055
1189
|
*/
|
|
1056
1190
|
const resolverZod = (0, _kubb_core.defineResolver)(() => {
|
|
1057
1191
|
return {
|
|
1058
1192
|
name: "default",
|
|
1059
1193
|
pluginName: "plugin-zod",
|
|
1060
1194
|
default(name, type) {
|
|
1061
|
-
|
|
1195
|
+
const resolved = camelCase(name, {
|
|
1062
1196
|
isFile: type === "file",
|
|
1063
1197
|
suffix: type ? "schema" : void 0
|
|
1064
1198
|
});
|
|
1199
|
+
return type === "file" ? resolved : ensureValidVarName(resolved);
|
|
1065
1200
|
},
|
|
1066
1201
|
resolveSchemaName(name) {
|
|
1067
|
-
return camelCase(name, { suffix: "schema" });
|
|
1202
|
+
return ensureValidVarName(camelCase(name, { suffix: "schema" }));
|
|
1068
1203
|
},
|
|
1069
1204
|
resolveSchemaTypeName(name) {
|
|
1070
|
-
return pascalCase(name, { suffix: "schema" });
|
|
1205
|
+
return ensureValidVarName(pascalCase(name, { suffix: "schema" }));
|
|
1071
1206
|
},
|
|
1072
1207
|
resolveTypeName(name) {
|
|
1073
|
-
return pascalCase(name);
|
|
1208
|
+
return ensureValidVarName(pascalCase(name));
|
|
1074
1209
|
},
|
|
1075
1210
|
resolvePathName(name, type) {
|
|
1076
1211
|
return this.default(name, type);
|
|
@@ -1104,19 +1239,32 @@ const resolverZod = (0, _kubb_core.defineResolver)(() => {
|
|
|
1104
1239
|
//#endregion
|
|
1105
1240
|
//#region src/plugin.ts
|
|
1106
1241
|
/**
|
|
1107
|
-
* Canonical plugin name for `@kubb/plugin-zod
|
|
1242
|
+
* Canonical plugin name for `@kubb/plugin-zod`. Used for driver lookups and
|
|
1243
|
+
* cross-plugin dependency references.
|
|
1108
1244
|
*/
|
|
1109
1245
|
const pluginZodName = "plugin-zod";
|
|
1110
1246
|
/**
|
|
1111
|
-
* Generates Zod
|
|
1112
|
-
*
|
|
1113
|
-
*
|
|
1247
|
+
* Generates Zod v4 schemas from an OpenAPI spec. Use them to validate API
|
|
1248
|
+
* responses at runtime, build form schemas, or feed back into router libraries
|
|
1249
|
+
* that consume Zod (tRPC, Hono, Elysia). Pair with `@kubb/plugin-client` and
|
|
1250
|
+
* set the client's `parser: 'zod'` to validate every response automatically.
|
|
1114
1251
|
*
|
|
1115
|
-
* @example
|
|
1252
|
+
* @example
|
|
1116
1253
|
* ```ts
|
|
1117
|
-
* import
|
|
1254
|
+
* import { defineConfig } from 'kubb'
|
|
1255
|
+
* import { pluginTs } from '@kubb/plugin-ts'
|
|
1256
|
+
* import { pluginZod } from '@kubb/plugin-zod'
|
|
1257
|
+
*
|
|
1118
1258
|
* export default defineConfig({
|
|
1119
|
-
*
|
|
1259
|
+
* input: { path: './petStore.yaml' },
|
|
1260
|
+
* output: { path: './src/gen' },
|
|
1261
|
+
* plugins: [
|
|
1262
|
+
* pluginTs(),
|
|
1263
|
+
* pluginZod({
|
|
1264
|
+
* output: { path: './zod' },
|
|
1265
|
+
* typed: true,
|
|
1266
|
+
* }),
|
|
1267
|
+
* ],
|
|
1120
1268
|
* })
|
|
1121
1269
|
* ```
|
|
1122
1270
|
*/
|
|
@@ -1131,7 +1279,7 @@ const pluginZod = (0, _kubb_core.definePlugin)((options) => {
|
|
|
1131
1279
|
if (group.type === "path") return `${ctx.group.split("/")[1]}`;
|
|
1132
1280
|
return `${camelCase(ctx.group)}Controller`;
|
|
1133
1281
|
}
|
|
1134
|
-
} :
|
|
1282
|
+
} : null;
|
|
1135
1283
|
return {
|
|
1136
1284
|
name: pluginZodName,
|
|
1137
1285
|
options,
|