@kubb/plugin-swr 5.0.0-beta.77 → 5.0.0-beta.79

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 CHANGED
@@ -92,7 +92,7 @@ function toFilePath(name, caseLast = camelCase) {
92
92
  * JavaScript and Java reserved words.
93
93
  * @link https://github.com/jonschlinkert/reserved/blob/master/index.js
94
94
  */
95
- const reservedWords = new Set([
95
+ const reservedWords = /* @__PURE__ */ new Set([
96
96
  "abstract",
97
97
  "arguments",
98
98
  "boolean",
@@ -321,6 +321,23 @@ function caseParams(params, casing) {
321
321
  caseParamsCache.set(params, result);
322
322
  return result;
323
323
  }
324
+ /**
325
+ * Drops parameters that collapse to the same property identity once camelCased, keeping the first.
326
+ *
327
+ * Some specs declare the same parameter twice under different casings (for example AWS S3 lists both
328
+ * `max-uploads` and `MaxUploads`). Both resolve to one output property, so emitting both would yield
329
+ * an object type with a duplicate member, which TypeScript rejects. De-duplicate by the camelCased
330
+ * identity so the resulting group is collision-free regardless of the names each caller carries.
331
+ */
332
+ function dedupeByCasedName(params) {
333
+ const seen = /* @__PURE__ */ new Set();
334
+ return params.filter((param) => {
335
+ const key = camelCase(param.name);
336
+ if (seen.has(key)) return false;
337
+ seen.add(key);
338
+ return true;
339
+ });
340
+ }
324
341
  //#endregion
325
342
  //#region ../../internals/shared/src/operation.ts
326
343
  /**
@@ -359,11 +376,27 @@ function getContentTypeInfo(node) {
359
376
  hasFormData: contentTypes.some((ct) => ct === "multipart/form-data")
360
377
  };
361
378
  }
379
+ /**
380
+ * The request-body counterpart for the primary success response: the content types it documents and
381
+ * whether several are present, so the client can let a caller pick which one to accept.
382
+ */
383
+ function getResponseContentTypeInfo(node) {
384
+ const contentTypes = getPrimarySuccessResponse(node)?.content?.map((e) => e.contentType) ?? [];
385
+ const isMultipleContentTypes = contentTypes.length > 1;
386
+ return {
387
+ contentTypes,
388
+ isMultipleContentTypes,
389
+ contentTypeUnion: isMultipleContentTypes ? contentTypes.map((ct) => JSON.stringify(ct)).join(" | ") : "",
390
+ defaultContentType: contentTypes[0] ?? "application/json",
391
+ hasFormData: contentTypes.some((ct) => ct === "multipart/form-data")
392
+ };
393
+ }
362
394
  function buildRequestConfigType(node) {
363
- const { isMultipleContentTypes, contentTypeUnion } = getContentTypeInfo(node);
395
+ const request = getContentTypeInfo(node);
396
+ const response = getResponseContentTypeInfo(node);
364
397
  const configType = `Partial<Omit<RequestConfig, 'path' | 'query' | 'body' | 'headers' | 'url'>>`;
365
- const contentTypeProp = isMultipleContentTypes ? `contentType?: ${contentTypeUnion}` : null;
366
- return contentTypeProp ? `${configType} & { ${contentTypeProp} }` : configType;
398
+ const members = [request.isMultipleContentTypes ? `request?: ${request.contentTypeUnion}` : null, response.isMultipleContentTypes ? `response?: ${response.contentTypeUnion}` : null].filter(Boolean);
399
+ return members.length ? `${configType} & { contentType?: { ${members.join("; ")} } }` : configType;
367
400
  }
368
401
  /**
369
402
  * Builds the `client?:` option type shared by the generated query hooks (`useQuery`,
@@ -425,20 +458,33 @@ function buildOperationComments(node, options = {}) {
425
458
  function getOperationParameters(node, options = {}) {
426
459
  const params = caseParams(node.parameters, options.paramsCasing === "original" ? void 0 : "camelcase");
427
460
  return {
428
- path: params.filter((param) => param.in === "path"),
429
- query: params.filter((param) => param.in === "query"),
430
- header: params.filter((param) => param.in === "header"),
431
- cookie: params.filter((param) => param.in === "cookie")
461
+ path: dedupeByCasedName(params.filter((param) => param.in === "path")),
462
+ query: dedupeByCasedName(params.filter((param) => param.in === "query")),
463
+ header: dedupeByCasedName(params.filter((param) => param.in === "header")),
464
+ cookie: dedupeByCasedName(params.filter((param) => param.in === "cookie"))
432
465
  };
433
466
  }
434
467
  function getStatusCodeNumber(statusCode) {
435
468
  const code = Number(statusCode);
436
469
  return Number.isNaN(code) ? null : code;
437
470
  }
471
+ function isSuccessStatusCode(statusCode) {
472
+ const code = getStatusCodeNumber(statusCode);
473
+ return code !== null && code >= 200 && code < 300;
474
+ }
438
475
  function isErrorStatusCode(statusCode) {
439
476
  const code = getStatusCodeNumber(statusCode);
440
477
  return code !== null && code >= 400;
441
478
  }
479
+ function getSuccessResponses(responses) {
480
+ return responses.filter((response) => isSuccessStatusCode(response.statusCode));
481
+ }
482
+ function getOperationSuccessResponses(node) {
483
+ return getSuccessResponses(node.responses);
484
+ }
485
+ function getPrimarySuccessResponse(node) {
486
+ return getOperationSuccessResponses(node)[0] ?? null;
487
+ }
442
488
  function resolveErrorNames(node, resolver) {
443
489
  return node.responses.filter((response) => isErrorStatusCode(response.statusCode)).map((response) => resolver.resolveResponseStatusName(node, response.statusCode));
444
490
  }
@@ -509,14 +555,14 @@ function createGroupConfig(group) {
509
555
  };
510
556
  }
511
557
  //#endregion
512
- //#region ../../internals/client/src/builders/parser.ts
558
+ //#region ../../internals/client/src/builders/validatorOptions.ts
513
559
  /**
514
- * Returns `true` when any direction of the parser uses zod (used for dependency checks).
560
+ * Returns `true` when any direction of the validator uses zod (used for dependency checks).
515
561
  */
516
- function isParserEnabled(parser) {
517
- if (!parser) return false;
518
- if (parser === "zod") return true;
519
- return Boolean(parser.request || parser.response);
562
+ function isValidatorEnabled(validator) {
563
+ if (!validator) return false;
564
+ if (validator === "zod") return true;
565
+ return Boolean(validator.request || validator.response);
520
566
  }
521
567
  //#endregion
522
568
  //#region ../../internals/client/src/resolveClient.ts
@@ -1046,7 +1092,7 @@ const mutationGenerator = (0, _kubb_core.defineGenerator)({
1046
1092
  operation(node, ctx) {
1047
1093
  if (!_kubb_core.ast.isHttpOperationNode(node)) return null;
1048
1094
  const { config, driver, resolver, root } = ctx;
1049
- const { output, query, mutation, parser, client, group } = ctx.options;
1095
+ const { output, query, mutation, validator, client, group } = ctx.options;
1050
1096
  const pluginTs = driver.getPlugin(_kubb_plugin_ts.pluginTsName);
1051
1097
  if (!pluginTs) return null;
1052
1098
  const tsResolver = driver.getResolver(_kubb_plugin_ts.pluginTsName);
@@ -1092,7 +1138,7 @@ const mutationGenerator = (0, _kubb_core.defineGenerator)({
1092
1138
  order: "body-response-first",
1093
1139
  includeParams: false
1094
1140
  })].filter((name) => Boolean(name));
1095
- const pluginZod = isParserEnabled(parser) ? driver.getPlugin(_kubb_plugin_zod.pluginZodName) : void 0;
1141
+ const pluginZod = isValidatorEnabled(validator) ? driver.getPlugin(_kubb_plugin_zod.pluginZodName) : void 0;
1096
1142
  const zodResolver = pluginZod ? driver.getResolver(_kubb_plugin_zod.pluginZodName) : void 0;
1097
1143
  const fileZod = zodResolver ? zodResolver.resolveFile({
1098
1144
  name: node.operationId,
@@ -1104,7 +1150,7 @@ const mutationGenerator = (0, _kubb_core.defineGenerator)({
1104
1150
  output: pluginZod?.options?.output ?? output,
1105
1151
  group: pluginZod?.options?.group
1106
1152
  }) : void 0;
1107
- const zodSchemaNames = resolveZodSchemaNames(node, zodResolver, parser);
1153
+ const zodSchemaNames = resolveZodSchemaNames(node, zodResolver, validator);
1108
1154
  const calledClientName = contractOp.name;
1109
1155
  return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx.File, {
1110
1156
  baseName: meta.file.baseName,
@@ -1187,7 +1233,7 @@ const queryGenerator = (0, _kubb_core.defineGenerator)({
1187
1233
  operation(node, ctx) {
1188
1234
  if (!_kubb_core.ast.isHttpOperationNode(node)) return null;
1189
1235
  const { config, driver, resolver, root } = ctx;
1190
- const { output, query, mutation, parser, client, group } = ctx.options;
1236
+ const { output, query, mutation, validator, client, group } = ctx.options;
1191
1237
  const pluginTs = driver.getPlugin(_kubb_plugin_ts.pluginTsName);
1192
1238
  if (!pluginTs) return null;
1193
1239
  const tsResolver = driver.getResolver(_kubb_plugin_ts.pluginTsName);
@@ -1235,7 +1281,7 @@ const queryGenerator = (0, _kubb_core.defineGenerator)({
1235
1281
  order: "body-response-first",
1236
1282
  includeParams: false
1237
1283
  })].filter((name) => Boolean(name));
1238
- const pluginZod = isParserEnabled(parser) ? driver.getPlugin(_kubb_plugin_zod.pluginZodName) : void 0;
1284
+ const pluginZod = isValidatorEnabled(validator) ? driver.getPlugin(_kubb_plugin_zod.pluginZodName) : void 0;
1239
1285
  const zodResolver = pluginZod ? driver.getResolver(_kubb_plugin_zod.pluginZodName) : void 0;
1240
1286
  const fileZod = zodResolver ? zodResolver.resolveFile({
1241
1287
  name: node.operationId,
@@ -1247,7 +1293,7 @@ const queryGenerator = (0, _kubb_core.defineGenerator)({
1247
1293
  output: pluginZod?.options?.output ?? output,
1248
1294
  group: pluginZod?.options?.group
1249
1295
  }) : void 0;
1250
- const zodSchemaNames = resolveZodSchemaNames(node, zodResolver, parser);
1296
+ const zodSchemaNames = resolveZodSchemaNames(node, zodResolver, validator);
1251
1297
  const calledClientName = contractOp.name;
1252
1298
  return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx.File, {
1253
1299
  baseName: meta.file.baseName,
@@ -1388,13 +1434,13 @@ const pluginSwr = (0, _kubb_core.definePlugin)((options) => {
1388
1434
  const { output = {
1389
1435
  path: "hooks",
1390
1436
  barrel: { type: "named" }
1391
- }, group, exclude = [], include, override = [], parser = false, mutation = {}, query = {}, mutationKey = mutationKeyTransformer, queryKey = queryKeyTransformer, client, resolver: userResolver, macros: userMacros } = options;
1437
+ }, group, exclude = [], include, override = [], validator = false, mutation = {}, query = {}, mutationKey = mutationKeyTransformer, queryKey = queryKeyTransformer, client, resolver: userResolver, macros: userMacros } = options;
1392
1438
  const selectedGenerators = [queryGenerator, mutationGenerator].filter((generator) => Boolean(generator));
1393
1439
  const groupConfig = createGroupConfig(group) ?? void 0;
1394
1440
  return {
1395
1441
  name: pluginSwrName,
1396
1442
  options,
1397
- dependencies: [_kubb_plugin_ts.pluginTsName, isParserEnabled(parser) ? _kubb_plugin_zod.pluginZodName : void 0].filter((dependency) => Boolean(dependency)),
1443
+ dependencies: [_kubb_plugin_ts.pluginTsName, isValidatorEnabled(validator) ? _kubb_plugin_zod.pluginZodName : void 0].filter((dependency) => Boolean(dependency)),
1398
1444
  hooks: { "kubb:plugin:setup"(ctx) {
1399
1445
  const resolver = userResolver ? {
1400
1446
  ...resolverSwr,
@@ -1429,7 +1475,7 @@ const pluginSwr = (0, _kubb_core.definePlugin)((options) => {
1429
1475
  ],
1430
1476
  ...mutation
1431
1477
  },
1432
- parser,
1478
+ validator,
1433
1479
  group: groupConfig,
1434
1480
  exclude,
1435
1481
  include,