@kubb/plugin-react-query 5.0.0-beta.76 → 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.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 ParserOptions = false | 'zod' | {
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
- parser?: ParserOptions;
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
- parser: NonNullable<Options$1['parser']>;
151
+ validator: NonNullable<Options$1['validator']>;
152
152
  sdk: {
153
153
  mode: Mode;
154
154
  name: string | undefined;
@@ -470,7 +470,7 @@ type Options = OutputOptions & {
470
470
  * - `'client'` — no validation. Trusts the API.
471
471
  * - `'zod'` — pipes responses through schemas from `@kubb/plugin-zod`.
472
472
  */
473
- parser?: Options$1['parser'];
473
+ validator?: Options$1['validator'];
474
474
  /**
475
475
  * Override how hook names and file paths are built. Methods you omit fall
476
476
  * back to the default `resolverReactQuery`.
@@ -499,7 +499,7 @@ type ResolvedOptions = {
499
499
  * The resolved contract client the generators import and call.
500
500
  */
501
501
  client: ResolvedClient;
502
- parser: NonNullable<Options['parser']>;
502
+ validator: NonNullable<Options['validator']>;
503
503
  /**
504
504
  * Only used for infinite
505
505
  */
package/dist/index.js CHANGED
@@ -64,7 +64,7 @@ function toFilePath(name, caseLast = camelCase) {
64
64
  * JavaScript and Java reserved words.
65
65
  * @link https://github.com/jonschlinkert/reserved/blob/master/index.js
66
66
  */
67
- const reservedWords = new Set([
67
+ const reservedWords = /* @__PURE__ */ new Set([
68
68
  "abstract",
69
69
  "arguments",
70
70
  "boolean",
@@ -293,6 +293,23 @@ function caseParams(params, casing) {
293
293
  caseParamsCache.set(params, result);
294
294
  return result;
295
295
  }
296
+ /**
297
+ * Drops parameters that collapse to the same property identity once camelCased, keeping the first.
298
+ *
299
+ * Some specs declare the same parameter twice under different casings (for example AWS S3 lists both
300
+ * `max-uploads` and `MaxUploads`). Both resolve to one output property, so emitting both would yield
301
+ * an object type with a duplicate member, which TypeScript rejects. De-duplicate by the camelCased
302
+ * identity so the resulting group is collision-free regardless of the names each caller carries.
303
+ */
304
+ function dedupeByCasedName(params) {
305
+ const seen = /* @__PURE__ */ new Set();
306
+ return params.filter((param) => {
307
+ const key = camelCase(param.name);
308
+ if (seen.has(key)) return false;
309
+ seen.add(key);
310
+ return true;
311
+ });
312
+ }
296
313
  //#endregion
297
314
  //#region ../../internals/shared/src/operation.ts
298
315
  /**
@@ -331,11 +348,27 @@ function getContentTypeInfo(node) {
331
348
  hasFormData: contentTypes.some((ct) => ct === "multipart/form-data")
332
349
  };
333
350
  }
351
+ /**
352
+ * The request-body counterpart for the primary success response: the content types it documents and
353
+ * whether several are present, so the client can let a caller pick which one to accept.
354
+ */
355
+ function getResponseContentTypeInfo(node) {
356
+ const contentTypes = getPrimarySuccessResponse(node)?.content?.map((e) => e.contentType) ?? [];
357
+ const isMultipleContentTypes = contentTypes.length > 1;
358
+ return {
359
+ contentTypes,
360
+ isMultipleContentTypes,
361
+ contentTypeUnion: isMultipleContentTypes ? contentTypes.map((ct) => JSON.stringify(ct)).join(" | ") : "",
362
+ defaultContentType: contentTypes[0] ?? "application/json",
363
+ hasFormData: contentTypes.some((ct) => ct === "multipart/form-data")
364
+ };
365
+ }
334
366
  function buildRequestConfigType(node) {
335
- const { isMultipleContentTypes, contentTypeUnion } = getContentTypeInfo(node);
367
+ const request = getContentTypeInfo(node);
368
+ const response = getResponseContentTypeInfo(node);
336
369
  const configType = `Partial<Omit<RequestConfig, 'path' | 'query' | 'body' | 'headers' | 'url'>>`;
337
- const contentTypeProp = isMultipleContentTypes ? `contentType?: ${contentTypeUnion}` : null;
338
- return contentTypeProp ? `${configType} & { ${contentTypeProp} }` : configType;
370
+ const members = [request.isMultipleContentTypes ? `request?: ${request.contentTypeUnion}` : null, response.isMultipleContentTypes ? `response?: ${response.contentTypeUnion}` : null].filter(Boolean);
371
+ return members.length ? `${configType} & { contentType?: { ${members.join("; ")} } }` : configType;
339
372
  }
340
373
  /**
341
374
  * Builds the `client?:` option type shared by the generated query hooks (`useQuery`,
@@ -397,10 +430,10 @@ function buildOperationComments(node, options = {}) {
397
430
  function getOperationParameters(node, options = {}) {
398
431
  const params = caseParams(node.parameters, options.paramsCasing === "original" ? void 0 : "camelcase");
399
432
  return {
400
- path: params.filter((param) => param.in === "path"),
401
- query: params.filter((param) => param.in === "query"),
402
- header: params.filter((param) => param.in === "header"),
403
- cookie: params.filter((param) => param.in === "cookie")
433
+ path: dedupeByCasedName(params.filter((param) => param.in === "path")),
434
+ query: dedupeByCasedName(params.filter((param) => param.in === "query")),
435
+ header: dedupeByCasedName(params.filter((param) => param.in === "header")),
436
+ cookie: dedupeByCasedName(params.filter((param) => param.in === "cookie"))
404
437
  };
405
438
  }
406
439
  function getStatusCodeNumber(statusCode) {
@@ -415,6 +448,15 @@ function isErrorStatusCode(statusCode) {
415
448
  const code = getStatusCodeNumber(statusCode);
416
449
  return code !== null && code >= 400;
417
450
  }
451
+ function getSuccessResponses(responses) {
452
+ return responses.filter((response) => isSuccessStatusCode(response.statusCode));
453
+ }
454
+ function getOperationSuccessResponses(node) {
455
+ return getSuccessResponses(node.responses);
456
+ }
457
+ function getPrimarySuccessResponse(node) {
458
+ return getOperationSuccessResponses(node)[0] ?? null;
459
+ }
418
460
  function resolveErrorNames(node, resolver) {
419
461
  return node.responses.filter((response) => isErrorStatusCode(response.statusCode)).map((response) => resolver.resolveResponseStatusName(node, response.statusCode));
420
462
  }
@@ -488,14 +530,14 @@ function createGroupConfig(group) {
488
530
  };
489
531
  }
490
532
  //#endregion
491
- //#region ../../internals/client/src/builders/parser.ts
533
+ //#region ../../internals/client/src/builders/validatorOptions.ts
492
534
  /**
493
- * Returns `true` when any direction of the parser uses zod (used for dependency checks).
535
+ * Returns `true` when any direction of the validator uses zod (used for dependency checks).
494
536
  */
495
- function isParserEnabled(parser) {
496
- if (!parser) return false;
497
- if (parser === "zod") return true;
498
- return Boolean(parser.request || parser.response);
537
+ function isValidatorEnabled(validator) {
538
+ if (!validator) return false;
539
+ if (validator === "zod") return true;
540
+ return Boolean(validator.request || validator.response);
499
541
  }
500
542
  //#endregion
501
543
  //#region ../../internals/client/src/resolveClient.ts
@@ -1743,7 +1785,7 @@ const infiniteQueryGenerator = defineGenerator({
1743
1785
  operation(node, ctx) {
1744
1786
  if (!ast.isHttpOperationNode(node)) return null;
1745
1787
  const { config, driver, resolver, root } = ctx;
1746
- const { output, query, mutation, infinite, parser, client, group, customOptions } = ctx.options;
1788
+ const { output, query, mutation, infinite, validator, client, group, customOptions } = ctx.options;
1747
1789
  const pluginTs = driver.getPlugin(pluginTsName);
1748
1790
  if (!pluginTs) return null;
1749
1791
  const tsResolver = driver.getResolver(pluginTsName);
@@ -1793,14 +1835,14 @@ const infiniteQueryGenerator = defineGenerator({
1793
1835
  includeParams: false
1794
1836
  })
1795
1837
  ].filter((name) => Boolean(name));
1796
- const pluginZod = isParserEnabled(parser) ? driver.getPlugin(pluginZodName) : null;
1838
+ const pluginZod = isValidatorEnabled(validator) ? driver.getPlugin(pluginZodName) : null;
1797
1839
  const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : null;
1798
1840
  const fileZod = zodResolver ? zodResolver.resolveFile(operationFileEntry(node, node.operationId), {
1799
1841
  root,
1800
1842
  output: pluginZod?.options?.output ?? output,
1801
1843
  group: pluginZod?.options?.group ?? void 0
1802
1844
  }) : null;
1803
- const zodSchemaNames = resolveZodSchemaNames(node, zodResolver, parser);
1845
+ const zodSchemaNames = resolveZodSchemaNames(node, zodResolver, validator);
1804
1846
  const calledClientName = contractOp.name;
1805
1847
  return /* @__PURE__ */ jsxs(File, {
1806
1848
  baseName: meta.file.baseName,
@@ -1919,7 +1961,7 @@ const mutationGenerator = defineGenerator({
1919
1961
  operation(node, ctx) {
1920
1962
  if (!ast.isHttpOperationNode(node)) return null;
1921
1963
  const { config, driver, resolver, root } = ctx;
1922
- const { output, query, mutation, parser, client, group, customOptions } = ctx.options;
1964
+ const { output, query, mutation, validator, client, group, customOptions } = ctx.options;
1923
1965
  const pluginTs = driver.getPlugin(pluginTsName);
1924
1966
  if (!pluginTs) return null;
1925
1967
  const tsResolver = driver.getResolver(pluginTsName);
@@ -1955,14 +1997,14 @@ const mutationGenerator = defineGenerator({
1955
1997
  order: "body-response-first",
1956
1998
  includeParams: false
1957
1999
  })].filter((name) => Boolean(name));
1958
- const pluginZod = isParserEnabled(parser) ? driver.getPlugin(pluginZodName) : null;
2000
+ const pluginZod = isValidatorEnabled(validator) ? driver.getPlugin(pluginZodName) : null;
1959
2001
  const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : null;
1960
2002
  const fileZod = zodResolver ? zodResolver.resolveFile(operationFileEntry(node, node.operationId), {
1961
2003
  root,
1962
2004
  output: pluginZod?.options?.output ?? output,
1963
2005
  group: pluginZod?.options?.group ?? void 0
1964
2006
  }) : null;
1965
- const zodSchemaNames = resolveZodSchemaNames(node, zodResolver, parser);
2007
+ const zodSchemaNames = resolveZodSchemaNames(node, zodResolver, validator);
1966
2008
  const calledClientName = contractOp.name;
1967
2009
  return /* @__PURE__ */ jsxs(File, {
1968
2010
  baseName: meta.file.baseName,
@@ -2068,7 +2110,7 @@ const queryGenerator = defineGenerator({
2068
2110
  operation(node, ctx) {
2069
2111
  if (!ast.isHttpOperationNode(node)) return null;
2070
2112
  const { config, driver, resolver, root } = ctx;
2071
- const { output, query, mutation, parser, client, group, customOptions } = ctx.options;
2113
+ const { output, query, mutation, validator, client, group, customOptions } = ctx.options;
2072
2114
  const pluginTs = driver.getPlugin(pluginTsName);
2073
2115
  if (!pluginTs) return null;
2074
2116
  const tsResolver = driver.getResolver(pluginTsName);
@@ -2106,14 +2148,14 @@ const queryGenerator = defineGenerator({
2106
2148
  order: "body-response-first",
2107
2149
  includeParams: false
2108
2150
  })].filter((name) => Boolean(name));
2109
- const pluginZod = isParserEnabled(parser) ? driver.getPlugin(pluginZodName) : null;
2151
+ const pluginZod = isValidatorEnabled(validator) ? driver.getPlugin(pluginZodName) : null;
2110
2152
  const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : null;
2111
2153
  const fileZod = zodResolver ? zodResolver.resolveFile(operationFileEntry(node, node.operationId), {
2112
2154
  root,
2113
2155
  output: pluginZod?.options?.output ?? output,
2114
2156
  group: pluginZod?.options?.group ?? void 0
2115
2157
  }) : null;
2116
- const zodSchemaNames = resolveZodSchemaNames(node, zodResolver, parser);
2158
+ const zodSchemaNames = resolveZodSchemaNames(node, zodResolver, validator);
2117
2159
  const calledClientName = contractOp.name;
2118
2160
  return /* @__PURE__ */ jsxs(File, {
2119
2161
  baseName: meta.file.baseName,
@@ -2223,7 +2265,7 @@ const suspenseInfiniteQueryGenerator = defineGenerator({
2223
2265
  operation(node, ctx) {
2224
2266
  if (!ast.isHttpOperationNode(node)) return null;
2225
2267
  const { config, driver, resolver, root } = ctx;
2226
- const { output, query, mutation, infinite, suspense, parser, client, group, customOptions } = ctx.options;
2268
+ const { output, query, mutation, infinite, suspense, validator, client, group, customOptions } = ctx.options;
2227
2269
  const pluginTs = driver.getPlugin(pluginTsName);
2228
2270
  if (!pluginTs) return null;
2229
2271
  const tsResolver = driver.getResolver(pluginTsName);
@@ -2273,14 +2315,14 @@ const suspenseInfiniteQueryGenerator = defineGenerator({
2273
2315
  includeParams: false
2274
2316
  })
2275
2317
  ].filter((name) => Boolean(name));
2276
- const pluginZod = isParserEnabled(parser) ? driver.getPlugin(pluginZodName) : null;
2318
+ const pluginZod = isValidatorEnabled(validator) ? driver.getPlugin(pluginZodName) : null;
2277
2319
  const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : null;
2278
2320
  const fileZod = zodResolver ? zodResolver.resolveFile(operationFileEntry(node, node.operationId), {
2279
2321
  root,
2280
2322
  output: pluginZod?.options?.output ?? output,
2281
2323
  group: pluginZod?.options?.group ?? void 0
2282
2324
  }) : null;
2283
- const zodSchemaNames = resolveZodSchemaNames(node, zodResolver, parser);
2325
+ const zodSchemaNames = resolveZodSchemaNames(node, zodResolver, validator);
2284
2326
  const calledClientName = contractOp.name;
2285
2327
  return /* @__PURE__ */ jsxs(File, {
2286
2328
  baseName: meta.file.baseName,
@@ -2400,7 +2442,7 @@ const suspenseQueryGenerator = defineGenerator({
2400
2442
  operation(node, ctx) {
2401
2443
  if (!ast.isHttpOperationNode(node)) return null;
2402
2444
  const { config, driver, resolver, root } = ctx;
2403
- const { output, query, mutation, suspense, parser, client, group, customOptions } = ctx.options;
2445
+ const { output, query, mutation, suspense, validator, client, group, customOptions } = ctx.options;
2404
2446
  const pluginTs = driver.getPlugin(pluginTsName);
2405
2447
  if (!pluginTs) return null;
2406
2448
  const tsResolver = driver.getResolver(pluginTsName);
@@ -2438,14 +2480,14 @@ const suspenseQueryGenerator = defineGenerator({
2438
2480
  order: "body-response-first",
2439
2481
  includeParams: false
2440
2482
  })].filter((name) => Boolean(name));
2441
- const pluginZod = isParserEnabled(parser) ? driver.getPlugin(pluginZodName) : null;
2483
+ const pluginZod = isValidatorEnabled(validator) ? driver.getPlugin(pluginZodName) : null;
2442
2484
  const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : null;
2443
2485
  const fileZod = zodResolver ? zodResolver.resolveFile(operationFileEntry(node, node.operationId), {
2444
2486
  root,
2445
2487
  output: pluginZod?.options?.output ?? output,
2446
2488
  group: pluginZod?.options?.group ?? void 0
2447
2489
  }) : null;
2448
- const zodSchemaNames = resolveZodSchemaNames(node, zodResolver, parser);
2490
+ const zodSchemaNames = resolveZodSchemaNames(node, zodResolver, validator);
2449
2491
  const calledClientName = contractOp.name;
2450
2492
  return /* @__PURE__ */ jsxs(File, {
2451
2493
  baseName: meta.file.baseName,
@@ -2692,7 +2734,7 @@ const pluginReactQuery = definePlugin((options) => {
2692
2734
  const { output = {
2693
2735
  path: "hooks",
2694
2736
  barrel: { type: "named" }
2695
- }, group, exclude = [], include, override = [], parser = false, suspense = {}, infinite = false, mutation = {}, query = {}, mutationKey = mutationKeyTransformer, queryKey = queryKeyTransformer, customOptions, client, resolver: userResolver, macros: userMacros } = options;
2737
+ }, group, exclude = [], include, override = [], validator = false, suspense = {}, infinite = false, mutation = {}, query = {}, mutationKey = mutationKeyTransformer, queryKey = queryKeyTransformer, customOptions, client, resolver: userResolver, macros: userMacros } = options;
2696
2738
  const selectedGenerators = [
2697
2739
  queryGenerator,
2698
2740
  suspenseQueryGenerator,
@@ -2706,7 +2748,7 @@ const pluginReactQuery = definePlugin((options) => {
2706
2748
  return {
2707
2749
  name: pluginReactQueryName,
2708
2750
  options,
2709
- dependencies: [pluginTsName, isParserEnabled(parser) ? pluginZodName : void 0].filter((dependency) => Boolean(dependency)),
2751
+ dependencies: [pluginTsName, isValidatorEnabled(validator) ? pluginZodName : void 0].filter((dependency) => Boolean(dependency)),
2710
2752
  hooks: { "kubb:plugin:setup"(ctx) {
2711
2753
  const resolver = userResolver ? {
2712
2754
  ...resolverReactQuery,
@@ -2754,7 +2796,7 @@ const pluginReactQuery = definePlugin((options) => {
2754
2796
  name: "useCustomHookOptions",
2755
2797
  ...customOptions
2756
2798
  } : null,
2757
- parser,
2799
+ validator,
2758
2800
  group: groupConfig,
2759
2801
  exclude,
2760
2802
  include,