@kubb/plugin-vue-query 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 CHANGED
@@ -89,7 +89,7 @@ function toFilePath(name, caseLast = camelCase) {
89
89
  * JavaScript and Java reserved words.
90
90
  * @link https://github.com/jonschlinkert/reserved/blob/master/index.js
91
91
  */
92
- const reservedWords = new Set([
92
+ const reservedWords = /* @__PURE__ */ new Set([
93
93
  "abstract",
94
94
  "arguments",
95
95
  "boolean",
@@ -318,6 +318,23 @@ function caseParams(params, casing) {
318
318
  caseParamsCache.set(params, result);
319
319
  return result;
320
320
  }
321
+ /**
322
+ * Drops parameters that collapse to the same property identity once camelCased, keeping the first.
323
+ *
324
+ * Some specs declare the same parameter twice under different casings (for example AWS S3 lists both
325
+ * `max-uploads` and `MaxUploads`). Both resolve to one output property, so emitting both would yield
326
+ * an object type with a duplicate member, which TypeScript rejects. De-duplicate by the camelCased
327
+ * identity so the resulting group is collision-free regardless of the names each caller carries.
328
+ */
329
+ function dedupeByCasedName(params) {
330
+ const seen = /* @__PURE__ */ new Set();
331
+ return params.filter((param) => {
332
+ const key = camelCase(param.name);
333
+ if (seen.has(key)) return false;
334
+ seen.add(key);
335
+ return true;
336
+ });
337
+ }
321
338
  //#endregion
322
339
  //#region ../../internals/shared/src/operation.ts
323
340
  /**
@@ -356,11 +373,27 @@ function getContentTypeInfo(node) {
356
373
  hasFormData: contentTypes.some((ct) => ct === "multipart/form-data")
357
374
  };
358
375
  }
376
+ /**
377
+ * The request-body counterpart for the primary success response: the content types it documents and
378
+ * whether several are present, so the client can let a caller pick which one to accept.
379
+ */
380
+ function getResponseContentTypeInfo(node) {
381
+ const contentTypes = getPrimarySuccessResponse(node)?.content?.map((e) => e.contentType) ?? [];
382
+ const isMultipleContentTypes = contentTypes.length > 1;
383
+ return {
384
+ contentTypes,
385
+ isMultipleContentTypes,
386
+ contentTypeUnion: isMultipleContentTypes ? contentTypes.map((ct) => JSON.stringify(ct)).join(" | ") : "",
387
+ defaultContentType: contentTypes[0] ?? "application/json",
388
+ hasFormData: contentTypes.some((ct) => ct === "multipart/form-data")
389
+ };
390
+ }
359
391
  function buildRequestConfigType(node) {
360
- const { isMultipleContentTypes, contentTypeUnion } = getContentTypeInfo(node);
392
+ const request = getContentTypeInfo(node);
393
+ const response = getResponseContentTypeInfo(node);
361
394
  const configType = `Partial<Omit<RequestConfig, 'path' | 'query' | 'body' | 'headers' | 'url'>>`;
362
- const contentTypeProp = isMultipleContentTypes ? `contentType?: ${contentTypeUnion}` : null;
363
- return contentTypeProp ? `${configType} & { ${contentTypeProp} }` : configType;
395
+ const members = [request.isMultipleContentTypes ? `request?: ${request.contentTypeUnion}` : null, response.isMultipleContentTypes ? `response?: ${response.contentTypeUnion}` : null].filter(Boolean);
396
+ return members.length ? `${configType} & { contentType?: { ${members.join("; ")} } }` : configType;
364
397
  }
365
398
  /**
366
399
  * Builds the `client?:` option type shared by the generated query hooks (`useQuery`,
@@ -422,10 +455,10 @@ function buildOperationComments(node, options = {}) {
422
455
  function getOperationParameters(node, options = {}) {
423
456
  const params = caseParams(node.parameters, options.paramsCasing === "original" ? void 0 : "camelcase");
424
457
  return {
425
- path: params.filter((param) => param.in === "path"),
426
- query: params.filter((param) => param.in === "query"),
427
- header: params.filter((param) => param.in === "header"),
428
- cookie: params.filter((param) => param.in === "cookie")
458
+ path: dedupeByCasedName(params.filter((param) => param.in === "path")),
459
+ query: dedupeByCasedName(params.filter((param) => param.in === "query")),
460
+ header: dedupeByCasedName(params.filter((param) => param.in === "header")),
461
+ cookie: dedupeByCasedName(params.filter((param) => param.in === "cookie"))
429
462
  };
430
463
  }
431
464
  function getStatusCodeNumber(statusCode) {
@@ -440,6 +473,15 @@ function isErrorStatusCode(statusCode) {
440
473
  const code = getStatusCodeNumber(statusCode);
441
474
  return code !== null && code >= 400;
442
475
  }
476
+ function getSuccessResponses(responses) {
477
+ return responses.filter((response) => isSuccessStatusCode(response.statusCode));
478
+ }
479
+ function getOperationSuccessResponses(node) {
480
+ return getSuccessResponses(node.responses);
481
+ }
482
+ function getPrimarySuccessResponse(node) {
483
+ return getOperationSuccessResponses(node)[0] ?? null;
484
+ }
443
485
  function resolveErrorNames(node, resolver) {
444
486
  return node.responses.filter((response) => isErrorStatusCode(response.statusCode)).map((response) => resolver.resolveResponseStatusName(node, response.statusCode));
445
487
  }
@@ -513,14 +555,14 @@ function createGroupConfig(group) {
513
555
  };
514
556
  }
515
557
  //#endregion
516
- //#region ../../internals/client/src/builders/parser.ts
558
+ //#region ../../internals/client/src/builders/validatorOptions.ts
517
559
  /**
518
- * 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).
519
561
  */
520
- function isParserEnabled(parser) {
521
- if (!parser) return false;
522
- if (parser === "zod") return true;
523
- 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);
524
566
  }
525
567
  //#endregion
526
568
  //#region ../../internals/client/src/resolveClient.ts
@@ -655,6 +697,19 @@ const requestGroupOrder$1 = [
655
697
  "headers"
656
698
  ];
657
699
  /**
700
+ * Widens a request-group member type so a generated TanStack hook accepts either the value or a
701
+ * deferred value. Both plugins apply this through the `memberTypeWrapper` of `buildGroupedRequestParam`;
702
+ * they only differ in how the deferred form is later resolved.
703
+ *
704
+ * `maybeRefOrGetter` is used by vue-query, which keeps the ref/getter live and unwraps it lazily with
705
+ * `toValue` because vue-query keys are reactive. `maybeValueOrGetter` is used by react-query, which
706
+ * resolves the getter once at the hook boundary and forwards a plain value because React Query hashes
707
+ * keys structurally and cannot hold a function.
708
+ */
709
+ function maybeRefOrGetter(type) {
710
+ return `MaybeRefOrGetter<${type}>`;
711
+ }
712
+ /**
658
713
  * Builds the grouped `{ path, query, body, headers }` parameter that mirrors the client
659
714
  * function signature. Only the groups the operation carries are emitted, typed from the
660
715
  * operation's `RequestConfig`. `keys` narrows the emitted groups, used by the query key which
@@ -776,12 +831,6 @@ const queryKeyTransformer = ({ node }) => {
776
831
  };
777
832
  //#endregion
778
833
  //#region src/utils.ts
779
- /**
780
- * Wraps a type string in `MaybeRefOrGetter<…>` so a vue-query signature accepts refs or getters.
781
- */
782
- function maybeRefOrGetter(type) {
783
- return `MaybeRefOrGetter<${type}>`;
784
- }
785
834
  const requestGroupOrder = [
786
835
  "path",
787
836
  "query",
@@ -1225,7 +1274,7 @@ const infiniteQueryGenerator = (0, _kubb_core.defineGenerator)({
1225
1274
  operation(node, ctx) {
1226
1275
  if (!_kubb_core.ast.isHttpOperationNode(node)) return null;
1227
1276
  const { config, driver, resolver, root } = ctx;
1228
- const { output, query, mutation, infinite, parser, client, group } = ctx.options;
1277
+ const { output, query, mutation, infinite, validator, client, group, hooks } = ctx.options;
1229
1278
  const pluginTs = driver.getPlugin(_kubb_plugin_ts.pluginTsName);
1230
1279
  if (!pluginTs) return null;
1231
1280
  const tsResolver = driver.getResolver(_kubb_plugin_ts.pluginTsName);
@@ -1275,14 +1324,14 @@ const infiniteQueryGenerator = (0, _kubb_core.defineGenerator)({
1275
1324
  includeParams: false
1276
1325
  })
1277
1326
  ].filter((name) => Boolean(name));
1278
- const pluginZod = isParserEnabled(parser) ? driver.getPlugin(_kubb_plugin_zod.pluginZodName) : null;
1327
+ const pluginZod = isValidatorEnabled(validator) ? driver.getPlugin(_kubb_plugin_zod.pluginZodName) : null;
1279
1328
  const zodResolver = pluginZod ? driver.getResolver(_kubb_plugin_zod.pluginZodName) : null;
1280
1329
  const fileZod = zodResolver ? zodResolver.resolveFile(operationFileEntry(node, node.operationId), {
1281
1330
  root,
1282
1331
  output: pluginZod?.options?.output ?? output,
1283
1332
  group: pluginZod?.options?.group ?? void 0
1284
1333
  }) : null;
1285
- const zodSchemaNames = resolveZodSchemaNames(node, zodResolver, parser);
1334
+ const zodSchemaNames = resolveZodSchemaNames(node, zodResolver, validator);
1286
1335
  const calledClientName = contractOp.name;
1287
1336
  return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx.File, {
1288
1337
  baseName: meta.file.baseName,
@@ -1364,30 +1413,32 @@ const infiniteQueryGenerator = (0, _kubb_core.defineGenerator)({
1364
1413
  initialPageParam: infiniteOptions.initialPageParam,
1365
1414
  queryParam: infiniteOptions.queryParam
1366
1415
  }),
1367
- /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
1368
- name: ["useInfiniteQuery"],
1369
- path: importPath
1370
- }),
1371
- /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
1372
- name: [
1373
- "QueryKey",
1374
- "QueryClient",
1375
- "UseInfiniteQueryOptions",
1376
- "UseInfiniteQueryReturnType"
1377
- ],
1378
- path: importPath,
1379
- isTypeOnly: true
1380
- }),
1381
- /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(InfiniteQuery, {
1382
- name: queryName,
1383
- queryOptionsName,
1384
- queryKeyName,
1385
- queryKeyTypeName,
1386
- node,
1387
- tsResolver,
1388
- initialPageParam: infiniteOptions.initialPageParam,
1389
- queryParam: infiniteOptions.queryParam
1390
- })
1416
+ hooks && /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: [
1417
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
1418
+ name: ["useInfiniteQuery"],
1419
+ path: importPath
1420
+ }),
1421
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
1422
+ name: [
1423
+ "QueryKey",
1424
+ "QueryClient",
1425
+ "UseInfiniteQueryOptions",
1426
+ "UseInfiniteQueryReturnType"
1427
+ ],
1428
+ path: importPath,
1429
+ isTypeOnly: true
1430
+ }),
1431
+ /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(InfiniteQuery, {
1432
+ name: queryName,
1433
+ queryOptionsName,
1434
+ queryKeyName,
1435
+ queryKeyTypeName,
1436
+ node,
1437
+ tsResolver,
1438
+ initialPageParam: infiniteOptions.initialPageParam,
1439
+ queryParam: infiniteOptions.queryParam
1440
+ })
1441
+ ] })
1391
1442
  ]
1392
1443
  });
1393
1444
  }
@@ -1405,7 +1456,7 @@ const mutationGenerator = (0, _kubb_core.defineGenerator)({
1405
1456
  operation(node, ctx) {
1406
1457
  if (!_kubb_core.ast.isHttpOperationNode(node)) return null;
1407
1458
  const { config, driver, resolver, root } = ctx;
1408
- const { output, query, mutation, parser, client, group } = ctx.options;
1459
+ const { output, query, mutation, validator, client, group, hooks } = ctx.options;
1409
1460
  const pluginTs = driver.getPlugin(_kubb_plugin_ts.pluginTsName);
1410
1461
  if (!pluginTs) return null;
1411
1462
  const tsResolver = driver.getResolver(_kubb_plugin_ts.pluginTsName);
@@ -1440,14 +1491,14 @@ const mutationGenerator = (0, _kubb_core.defineGenerator)({
1440
1491
  order: "body-response-first",
1441
1492
  includeParams: false
1442
1493
  })].filter((name) => Boolean(name));
1443
- const pluginZod = isParserEnabled(parser) ? driver.getPlugin(_kubb_plugin_zod.pluginZodName) : null;
1494
+ const pluginZod = isValidatorEnabled(validator) ? driver.getPlugin(_kubb_plugin_zod.pluginZodName) : null;
1444
1495
  const zodResolver = pluginZod ? driver.getResolver(_kubb_plugin_zod.pluginZodName) : null;
1445
1496
  const fileZod = zodResolver ? zodResolver.resolveFile(operationFileEntry(node, node.operationId), {
1446
1497
  root,
1447
1498
  output: pluginZod?.options?.output ?? output,
1448
1499
  group: pluginZod?.options?.group ?? void 0
1449
1500
  }) : null;
1450
- const zodSchemaNames = resolveZodSchemaNames(node, zodResolver, parser);
1501
+ const zodSchemaNames = resolveZodSchemaNames(node, zodResolver, validator);
1451
1502
  const calledClientName = contractOp.name;
1452
1503
  const groups = getRequestGroups(node);
1453
1504
  const hasRequestGroups = groups.path || groups.query || groups.body || groups.headers;
@@ -1508,7 +1559,7 @@ const mutationGenerator = (0, _kubb_core.defineGenerator)({
1508
1559
  node,
1509
1560
  transformer: ctx.options.mutationKey
1510
1561
  }),
1511
- mutation && /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: [
1562
+ mutation && hooks && /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: [
1512
1563
  /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
1513
1564
  name: ["useMutation"],
1514
1565
  path: importPath
@@ -1544,7 +1595,7 @@ const queryGenerator = (0, _kubb_core.defineGenerator)({
1544
1595
  operation(node, ctx) {
1545
1596
  if (!_kubb_core.ast.isHttpOperationNode(node)) return null;
1546
1597
  const { config, driver, resolver, root } = ctx;
1547
- const { output, query, mutation, parser, client, group } = ctx.options;
1598
+ const { output, query, mutation, validator, client, group, hooks } = ctx.options;
1548
1599
  const pluginTs = driver.getPlugin(_kubb_plugin_ts.pluginTsName);
1549
1600
  if (!pluginTs) return null;
1550
1601
  const tsResolver = driver.getResolver(_kubb_plugin_ts.pluginTsName);
@@ -1582,14 +1633,14 @@ const queryGenerator = (0, _kubb_core.defineGenerator)({
1582
1633
  order: "body-response-first",
1583
1634
  includeParams: false
1584
1635
  })].filter((name) => Boolean(name));
1585
- const pluginZod = isParserEnabled(parser) ? driver.getPlugin(_kubb_plugin_zod.pluginZodName) : null;
1636
+ const pluginZod = isValidatorEnabled(validator) ? driver.getPlugin(_kubb_plugin_zod.pluginZodName) : null;
1586
1637
  const zodResolver = pluginZod ? driver.getResolver(_kubb_plugin_zod.pluginZodName) : null;
1587
1638
  const fileZod = zodResolver ? zodResolver.resolveFile(operationFileEntry(node, node.operationId), {
1588
1639
  root,
1589
1640
  output: pluginZod?.options?.output ?? output,
1590
1641
  group: pluginZod?.options?.group ?? void 0
1591
1642
  }) : null;
1592
- const zodSchemaNames = resolveZodSchemaNames(node, zodResolver, parser);
1643
+ const zodSchemaNames = resolveZodSchemaNames(node, zodResolver, validator);
1593
1644
  const calledClientName = contractOp.name;
1594
1645
  return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx.File, {
1595
1646
  baseName: meta.file.baseName,
@@ -1661,7 +1712,7 @@ const queryGenerator = (0, _kubb_core.defineGenerator)({
1661
1712
  node,
1662
1713
  tsResolver
1663
1714
  }),
1664
- query && /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: [
1715
+ query && hooks && /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: [
1665
1716
  /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
1666
1717
  name: ["useQuery"],
1667
1718
  path: importPath
@@ -1797,7 +1848,7 @@ const pluginVueQuery = (0, _kubb_core.definePlugin)((options) => {
1797
1848
  const { output = {
1798
1849
  path: "hooks",
1799
1850
  barrel: { type: "named" }
1800
- }, group, exclude = [], include, override = [], parser = false, infinite = false, mutation = {}, query = {}, mutationKey = mutationKeyTransformer, queryKey = queryKeyTransformer, client, resolver: userResolver, macros: userMacros } = options;
1851
+ }, group, exclude = [], include, override = [], validator = false, infinite = false, mutation = {}, query = {}, mutationKey = mutationKeyTransformer, queryKey = queryKeyTransformer, hooks = false, client, resolver: userResolver, macros: userMacros } = options;
1801
1852
  const selectedGenerators = [
1802
1853
  queryGenerator,
1803
1854
  infiniteQueryGenerator,
@@ -1807,7 +1858,7 @@ const pluginVueQuery = (0, _kubb_core.definePlugin)((options) => {
1807
1858
  return {
1808
1859
  name: pluginVueQueryName,
1809
1860
  options,
1810
- dependencies: [_kubb_plugin_ts.pluginTsName, isParserEnabled(parser) ? _kubb_plugin_zod.pluginZodName : void 0].filter((dependency) => Boolean(dependency)),
1861
+ dependencies: [_kubb_plugin_ts.pluginTsName, isValidatorEnabled(validator) ? _kubb_plugin_zod.pluginZodName : void 0].filter((dependency) => Boolean(dependency)),
1811
1862
  hooks: { "kubb:plugin:setup"(ctx) {
1812
1863
  const resolver = userResolver ? {
1813
1864
  ...resolverVueQuery,
@@ -1850,7 +1901,8 @@ const pluginVueQuery = (0, _kubb_core.definePlugin)((options) => {
1850
1901
  previousParam: null,
1851
1902
  ...infinite
1852
1903
  } : false,
1853
- parser,
1904
+ hooks,
1905
+ validator,
1854
1906
  group: groupConfig,
1855
1907
  exclude,
1856
1908
  include,