@kubb/plugin-swr 5.0.0-beta.77 → 5.0.0-beta.80
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 +69 -23
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.js +69 -23
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
package/dist/index.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ import { Exclude, Group, Include, Output, OutputOptions, Override, PluginFactory
|
|
|
10
10
|
* body and query parameters before the call; `response` validates the success response body and,
|
|
11
11
|
* on the non-throw path, the error body.
|
|
12
12
|
*/
|
|
13
|
-
type
|
|
13
|
+
type ValidatorOptions = false | 'zod' | {
|
|
14
14
|
request?: 'zod';
|
|
15
15
|
response?: 'zod';
|
|
16
16
|
};
|
|
@@ -82,7 +82,7 @@ type Options$1 = OutputOptions & {
|
|
|
82
82
|
*
|
|
83
83
|
* @default false
|
|
84
84
|
*/
|
|
85
|
-
|
|
85
|
+
validator?: ValidatorOptions;
|
|
86
86
|
/**
|
|
87
87
|
* Generates a class-based SDK instead of the standalone functions. Each tag client is an instance
|
|
88
88
|
* class whose constructor takes a client config and builds its own client, so every environment is
|
|
@@ -148,7 +148,7 @@ type ResolvedOptions$1 = {
|
|
|
148
148
|
override: Array<Override<ResolvedOptions$1>>;
|
|
149
149
|
group: Group | null;
|
|
150
150
|
baseURL: Options$1['baseURL'];
|
|
151
|
-
|
|
151
|
+
validator: NonNullable<Options$1['validator']>;
|
|
152
152
|
sdk: {
|
|
153
153
|
mode: Mode;
|
|
154
154
|
name: string | undefined;
|
|
@@ -321,7 +321,7 @@ type Options = OutputOptions & {
|
|
|
321
321
|
/**
|
|
322
322
|
* Parser to use for validating response data.
|
|
323
323
|
*/
|
|
324
|
-
|
|
324
|
+
validator?: Options$1['validator'];
|
|
325
325
|
/**
|
|
326
326
|
* Override naming conventions for function names and types.
|
|
327
327
|
*/
|
|
@@ -349,7 +349,7 @@ type ResolvedOptions = {
|
|
|
349
349
|
* The resolved contract client the generators import and call.
|
|
350
350
|
*/
|
|
351
351
|
client: ResolvedClient;
|
|
352
|
-
|
|
352
|
+
validator: NonNullable<Options['validator']>;
|
|
353
353
|
queryKey: QueryKey | undefined;
|
|
354
354
|
query: NonNullable<Required<Query>> | false;
|
|
355
355
|
mutationKey: MutationKey | undefined;
|
package/dist/index.js
CHANGED
|
@@ -62,7 +62,7 @@ function toFilePath(name, caseLast = camelCase) {
|
|
|
62
62
|
* JavaScript and Java reserved words.
|
|
63
63
|
* @link https://github.com/jonschlinkert/reserved/blob/master/index.js
|
|
64
64
|
*/
|
|
65
|
-
const reservedWords = new Set([
|
|
65
|
+
const reservedWords = /* @__PURE__ */ new Set([
|
|
66
66
|
"abstract",
|
|
67
67
|
"arguments",
|
|
68
68
|
"boolean",
|
|
@@ -291,6 +291,23 @@ function caseParams(params, casing) {
|
|
|
291
291
|
caseParamsCache.set(params, result);
|
|
292
292
|
return result;
|
|
293
293
|
}
|
|
294
|
+
/**
|
|
295
|
+
* Drops parameters that collapse to the same property identity once camelCased, keeping the first.
|
|
296
|
+
*
|
|
297
|
+
* Some specs declare the same parameter twice under different casings (for example AWS S3 lists both
|
|
298
|
+
* `max-uploads` and `MaxUploads`). Both resolve to one output property, so emitting both would yield
|
|
299
|
+
* an object type with a duplicate member, which TypeScript rejects. De-duplicate by the camelCased
|
|
300
|
+
* identity so the resulting group is collision-free regardless of the names each caller carries.
|
|
301
|
+
*/
|
|
302
|
+
function dedupeByCasedName(params) {
|
|
303
|
+
const seen = /* @__PURE__ */ new Set();
|
|
304
|
+
return params.filter((param) => {
|
|
305
|
+
const key = camelCase(param.name);
|
|
306
|
+
if (seen.has(key)) return false;
|
|
307
|
+
seen.add(key);
|
|
308
|
+
return true;
|
|
309
|
+
});
|
|
310
|
+
}
|
|
294
311
|
//#endregion
|
|
295
312
|
//#region ../../internals/shared/src/operation.ts
|
|
296
313
|
/**
|
|
@@ -329,11 +346,27 @@ function getContentTypeInfo(node) {
|
|
|
329
346
|
hasFormData: contentTypes.some((ct) => ct === "multipart/form-data")
|
|
330
347
|
};
|
|
331
348
|
}
|
|
349
|
+
/**
|
|
350
|
+
* The request-body counterpart for the primary success response: the content types it documents and
|
|
351
|
+
* whether several are present, so the client can let a caller pick which one to accept.
|
|
352
|
+
*/
|
|
353
|
+
function getResponseContentTypeInfo(node) {
|
|
354
|
+
const contentTypes = getPrimarySuccessResponse(node)?.content?.map((e) => e.contentType) ?? [];
|
|
355
|
+
const isMultipleContentTypes = contentTypes.length > 1;
|
|
356
|
+
return {
|
|
357
|
+
contentTypes,
|
|
358
|
+
isMultipleContentTypes,
|
|
359
|
+
contentTypeUnion: isMultipleContentTypes ? contentTypes.map((ct) => JSON.stringify(ct)).join(" | ") : "",
|
|
360
|
+
defaultContentType: contentTypes[0] ?? "application/json",
|
|
361
|
+
hasFormData: contentTypes.some((ct) => ct === "multipart/form-data")
|
|
362
|
+
};
|
|
363
|
+
}
|
|
332
364
|
function buildRequestConfigType(node) {
|
|
333
|
-
const
|
|
365
|
+
const request = getContentTypeInfo(node);
|
|
366
|
+
const response = getResponseContentTypeInfo(node);
|
|
334
367
|
const configType = `Partial<Omit<RequestConfig, 'path' | 'query' | 'body' | 'headers' | 'url'>>`;
|
|
335
|
-
const
|
|
336
|
-
return
|
|
368
|
+
const members = [request.isMultipleContentTypes ? `request?: ${request.contentTypeUnion}` : null, response.isMultipleContentTypes ? `response?: ${response.contentTypeUnion}` : null].filter(Boolean);
|
|
369
|
+
return members.length ? `${configType} & { contentType?: { ${members.join("; ")} } }` : configType;
|
|
337
370
|
}
|
|
338
371
|
/**
|
|
339
372
|
* Builds the `client?:` option type shared by the generated query hooks (`useQuery`,
|
|
@@ -395,20 +428,33 @@ function buildOperationComments(node, options = {}) {
|
|
|
395
428
|
function getOperationParameters(node, options = {}) {
|
|
396
429
|
const params = caseParams(node.parameters, options.paramsCasing === "original" ? void 0 : "camelcase");
|
|
397
430
|
return {
|
|
398
|
-
path: params.filter((param) => param.in === "path"),
|
|
399
|
-
query: params.filter((param) => param.in === "query"),
|
|
400
|
-
header: params.filter((param) => param.in === "header"),
|
|
401
|
-
cookie: params.filter((param) => param.in === "cookie")
|
|
431
|
+
path: dedupeByCasedName(params.filter((param) => param.in === "path")),
|
|
432
|
+
query: dedupeByCasedName(params.filter((param) => param.in === "query")),
|
|
433
|
+
header: dedupeByCasedName(params.filter((param) => param.in === "header")),
|
|
434
|
+
cookie: dedupeByCasedName(params.filter((param) => param.in === "cookie"))
|
|
402
435
|
};
|
|
403
436
|
}
|
|
404
437
|
function getStatusCodeNumber(statusCode) {
|
|
405
438
|
const code = Number(statusCode);
|
|
406
439
|
return Number.isNaN(code) ? null : code;
|
|
407
440
|
}
|
|
441
|
+
function isSuccessStatusCode(statusCode) {
|
|
442
|
+
const code = getStatusCodeNumber(statusCode);
|
|
443
|
+
return code !== null && code >= 200 && code < 300;
|
|
444
|
+
}
|
|
408
445
|
function isErrorStatusCode(statusCode) {
|
|
409
446
|
const code = getStatusCodeNumber(statusCode);
|
|
410
447
|
return code !== null && code >= 400;
|
|
411
448
|
}
|
|
449
|
+
function getSuccessResponses(responses) {
|
|
450
|
+
return responses.filter((response) => isSuccessStatusCode(response.statusCode));
|
|
451
|
+
}
|
|
452
|
+
function getOperationSuccessResponses(node) {
|
|
453
|
+
return getSuccessResponses(node.responses);
|
|
454
|
+
}
|
|
455
|
+
function getPrimarySuccessResponse(node) {
|
|
456
|
+
return getOperationSuccessResponses(node)[0] ?? null;
|
|
457
|
+
}
|
|
412
458
|
function resolveErrorNames(node, resolver) {
|
|
413
459
|
return node.responses.filter((response) => isErrorStatusCode(response.statusCode)).map((response) => resolver.resolveResponseStatusName(node, response.statusCode));
|
|
414
460
|
}
|
|
@@ -479,14 +525,14 @@ function createGroupConfig(group) {
|
|
|
479
525
|
};
|
|
480
526
|
}
|
|
481
527
|
//#endregion
|
|
482
|
-
//#region ../../internals/client/src/builders/
|
|
528
|
+
//#region ../../internals/client/src/builders/validatorOptions.ts
|
|
483
529
|
/**
|
|
484
|
-
* Returns `true` when any direction of the
|
|
530
|
+
* Returns `true` when any direction of the validator uses zod (used for dependency checks).
|
|
485
531
|
*/
|
|
486
|
-
function
|
|
487
|
-
if (!
|
|
488
|
-
if (
|
|
489
|
-
return Boolean(
|
|
532
|
+
function isValidatorEnabled(validator) {
|
|
533
|
+
if (!validator) return false;
|
|
534
|
+
if (validator === "zod") return true;
|
|
535
|
+
return Boolean(validator.request || validator.response);
|
|
490
536
|
}
|
|
491
537
|
//#endregion
|
|
492
538
|
//#region ../../internals/client/src/resolveClient.ts
|
|
@@ -1016,7 +1062,7 @@ const mutationGenerator = defineGenerator({
|
|
|
1016
1062
|
operation(node, ctx) {
|
|
1017
1063
|
if (!ast.isHttpOperationNode(node)) return null;
|
|
1018
1064
|
const { config, driver, resolver, root } = ctx;
|
|
1019
|
-
const { output, query, mutation,
|
|
1065
|
+
const { output, query, mutation, validator, client, group } = ctx.options;
|
|
1020
1066
|
const pluginTs = driver.getPlugin(pluginTsName);
|
|
1021
1067
|
if (!pluginTs) return null;
|
|
1022
1068
|
const tsResolver = driver.getResolver(pluginTsName);
|
|
@@ -1062,7 +1108,7 @@ const mutationGenerator = defineGenerator({
|
|
|
1062
1108
|
order: "body-response-first",
|
|
1063
1109
|
includeParams: false
|
|
1064
1110
|
})].filter((name) => Boolean(name));
|
|
1065
|
-
const pluginZod =
|
|
1111
|
+
const pluginZod = isValidatorEnabled(validator) ? driver.getPlugin(pluginZodName) : void 0;
|
|
1066
1112
|
const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : void 0;
|
|
1067
1113
|
const fileZod = zodResolver ? zodResolver.resolveFile({
|
|
1068
1114
|
name: node.operationId,
|
|
@@ -1074,7 +1120,7 @@ const mutationGenerator = defineGenerator({
|
|
|
1074
1120
|
output: pluginZod?.options?.output ?? output,
|
|
1075
1121
|
group: pluginZod?.options?.group
|
|
1076
1122
|
}) : void 0;
|
|
1077
|
-
const zodSchemaNames = resolveZodSchemaNames(node, zodResolver,
|
|
1123
|
+
const zodSchemaNames = resolveZodSchemaNames(node, zodResolver, validator);
|
|
1078
1124
|
const calledClientName = contractOp.name;
|
|
1079
1125
|
return /* @__PURE__ */ jsxs(File, {
|
|
1080
1126
|
baseName: meta.file.baseName,
|
|
@@ -1157,7 +1203,7 @@ const queryGenerator = defineGenerator({
|
|
|
1157
1203
|
operation(node, ctx) {
|
|
1158
1204
|
if (!ast.isHttpOperationNode(node)) return null;
|
|
1159
1205
|
const { config, driver, resolver, root } = ctx;
|
|
1160
|
-
const { output, query, mutation,
|
|
1206
|
+
const { output, query, mutation, validator, client, group } = ctx.options;
|
|
1161
1207
|
const pluginTs = driver.getPlugin(pluginTsName);
|
|
1162
1208
|
if (!pluginTs) return null;
|
|
1163
1209
|
const tsResolver = driver.getResolver(pluginTsName);
|
|
@@ -1205,7 +1251,7 @@ const queryGenerator = defineGenerator({
|
|
|
1205
1251
|
order: "body-response-first",
|
|
1206
1252
|
includeParams: false
|
|
1207
1253
|
})].filter((name) => Boolean(name));
|
|
1208
|
-
const pluginZod =
|
|
1254
|
+
const pluginZod = isValidatorEnabled(validator) ? driver.getPlugin(pluginZodName) : void 0;
|
|
1209
1255
|
const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : void 0;
|
|
1210
1256
|
const fileZod = zodResolver ? zodResolver.resolveFile({
|
|
1211
1257
|
name: node.operationId,
|
|
@@ -1217,7 +1263,7 @@ const queryGenerator = defineGenerator({
|
|
|
1217
1263
|
output: pluginZod?.options?.output ?? output,
|
|
1218
1264
|
group: pluginZod?.options?.group
|
|
1219
1265
|
}) : void 0;
|
|
1220
|
-
const zodSchemaNames = resolveZodSchemaNames(node, zodResolver,
|
|
1266
|
+
const zodSchemaNames = resolveZodSchemaNames(node, zodResolver, validator);
|
|
1221
1267
|
const calledClientName = contractOp.name;
|
|
1222
1268
|
return /* @__PURE__ */ jsxs(File, {
|
|
1223
1269
|
baseName: meta.file.baseName,
|
|
@@ -1358,13 +1404,13 @@ const pluginSwr = definePlugin((options) => {
|
|
|
1358
1404
|
const { output = {
|
|
1359
1405
|
path: "hooks",
|
|
1360
1406
|
barrel: { type: "named" }
|
|
1361
|
-
}, group, exclude = [], include, override = [],
|
|
1407
|
+
}, group, exclude = [], include, override = [], validator = false, mutation = {}, query = {}, mutationKey = mutationKeyTransformer, queryKey = queryKeyTransformer, client, resolver: userResolver, macros: userMacros } = options;
|
|
1362
1408
|
const selectedGenerators = [queryGenerator, mutationGenerator].filter((generator) => Boolean(generator));
|
|
1363
1409
|
const groupConfig = createGroupConfig(group) ?? void 0;
|
|
1364
1410
|
return {
|
|
1365
1411
|
name: pluginSwrName,
|
|
1366
1412
|
options,
|
|
1367
|
-
dependencies: [pluginTsName,
|
|
1413
|
+
dependencies: [pluginTsName, isValidatorEnabled(validator) ? pluginZodName : void 0].filter((dependency) => Boolean(dependency)),
|
|
1368
1414
|
hooks: { "kubb:plugin:setup"(ctx) {
|
|
1369
1415
|
const resolver = userResolver ? {
|
|
1370
1416
|
...resolverSwr,
|
|
@@ -1399,7 +1445,7 @@ const pluginSwr = definePlugin((options) => {
|
|
|
1399
1445
|
],
|
|
1400
1446
|
...mutation
|
|
1401
1447
|
},
|
|
1402
|
-
|
|
1448
|
+
validator,
|
|
1403
1449
|
group: groupConfig,
|
|
1404
1450
|
exclude,
|
|
1405
1451
|
include,
|