@kubb/plugin-vue-query 5.6.0 → 5.6.1

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.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { Diagnostics, Resolver, Url, addGenerator, ast, createResolver, defineExtension, defineGenerator, setMacros, setResolver, useConfig } from "kubb/kit";
2
2
  import path from "node:path";
3
3
  import { createFunctionParameter, createFunctionParameters, createObjectBindingPattern, createTypeLiteral, functionPrinter, pluginTsName } from "@kubb/plugin-ts";
4
+ import { pluginZodName } from "@kubb/plugin-zod";
4
5
  import { File, Function, Type, jsxRenderer } from "kubb/jsx";
5
6
  import { Fragment, jsx, jsxs } from "kubb/jsx/jsx-runtime";
6
7
  //#endregion
@@ -330,17 +331,256 @@ var compatibility = {
330
331
  };
331
332
  //#endregion
332
333
  //#region package.json
333
- var version = "5.6.0";
334
+ var version = "5.6.1";
335
+ //#endregion
336
+ //#region ../../internals/client/src/resolveOperationTypes.ts
337
+ /**
338
+ * A `plugin-ts` shaped resolver whose operation type names point at the types `pluginZod({ inferred })`
339
+ * exports next to each schema, so code written against `plugin-ts` names picks up the zod types.
340
+ */
341
+ function toZodTypeResolver(resolver) {
342
+ const type = (name) => resolver.schema.type(name);
343
+ return {
344
+ ...resolver,
345
+ file: resolver.file.bind(resolver),
346
+ param: {
347
+ name: (node, p) => type(resolver.param.name(node, p)),
348
+ path: (node, p) => type(resolver.param.path(node, p)),
349
+ query: (node, p) => type(resolver.param.query(node, p)),
350
+ headers: (node, p) => type(resolver.param.headers(node, p))
351
+ },
352
+ response: {
353
+ body: (node) => type(resolver.response.body(node)),
354
+ status: (node, statusCode) => type(resolver.response.status(node, statusCode)),
355
+ response: (node) => type(resolver.response.response(node)),
356
+ responses: (node) => type(resolver.response.responses(node)),
357
+ options: (node) => resolver.response.options(node)
358
+ }
359
+ };
360
+ }
361
+ /**
362
+ * Picks the plugin generated clients, query hooks, and MCP handlers take their operation types from.
363
+ *
364
+ * `pluginZod({ inferred: 'codec' })` wins, so a codec param takes its domain value. Otherwise `plugin-ts`
365
+ * wins when it is in the pipeline, and without it any `pluginZod({ inferred })`. Throws
366
+ * `KUBB_MISSING_DEPENDENCY` for `pluginName` when neither is available.
367
+ *
368
+ * @example
369
+ * ```ts
370
+ * const types = resolveOperationTypes(ctx.driver, ctx.plugin.name)
371
+ * types.response.options(node) // 'GetPetByIdOptions', or 'GetPetByIdOptionsSchemaType' from zod
372
+ * ```
373
+ */
374
+ function resolveOperationTypes(driver, pluginName) {
375
+ const pluginTs = driver.getPlugin(pluginTsName);
376
+ const pluginZod = driver.getPlugin(pluginZodName);
377
+ if (pluginTs && pluginZod?.options?.inferred !== "codec") {
378
+ const resolver = driver.getResolver(pluginTsName);
379
+ return {
380
+ response: resolver.response,
381
+ resolver,
382
+ output: pluginTs.options?.output,
383
+ group: pluginTs.options?.group ?? void 0
384
+ };
385
+ }
386
+ if (!pluginZod?.options?.inferred) throw new Diagnostics.Error({
387
+ code: Diagnostics.code.missingDependency,
388
+ severity: "error",
389
+ message: `Plugin "${pluginName}" has no source for operation types.`,
390
+ help: `Add \`pluginTs()\` before "${pluginName}", or add \`pluginZod({ inferred: true })\`.`,
391
+ location: { kind: "config" },
392
+ plugin: pluginName
393
+ });
394
+ const resolver = toZodTypeResolver(driver.getResolver(pluginZodName));
395
+ return {
396
+ response: resolver.response,
397
+ resolver,
398
+ output: pluginZod.options.output,
399
+ group: pluginZod.options.group ?? void 0
400
+ };
401
+ }
402
+ //#endregion
403
+ //#region ../../internals/client/src/resolveClient.ts
404
+ /**
405
+ * Resolves which client plugin a consumer (react-query, vue-query, swr, mcp) should call for an
406
+ * operation, shared so the selection rules and diagnostics stay in one place.
407
+ *
408
+ * Every client runtime lives in a dedicated client plugin, so a consumer always calls a registered
409
+ * contract client plugin (plugin-fetch, plugin-axios, or plugin-client) and never emits its own
410
+ * inline client:
411
+ *
412
+ * - `contract` — a registered contract client plugin owns the `<op>` functions and the consumer
413
+ * imports and calls them.
414
+ * - `error` — no client plugin is registered, several are registered without a selector, the
415
+ * requested one is missing, or `client` is not a known selector.
416
+ *
417
+ * The `client` string selects explicitly (`'fetch'` / `'axios'` / `'client'`); when it is unset a
418
+ * lone registered contract client plugin is picked up automatically.
419
+ */
420
+ const pluginFetchName = "plugin-fetch";
421
+ const pluginAxiosName = "plugin-axios";
422
+ const pluginClientName = "plugin-client";
423
+ const selectorToPlugin = {
424
+ fetch: pluginFetchName,
425
+ axios: pluginAxiosName,
426
+ client: pluginClientName
427
+ };
428
+ const contractPlugins = [
429
+ pluginFetchName,
430
+ pluginAxiosName,
431
+ pluginClientName
432
+ ];
433
+ /**
434
+ * Applies the `client` resolution rules. See the module comment for the strategy shape.
435
+ *
436
+ * @example
437
+ * ```ts
438
+ * resolveClient({ client: 'fetch', pluginNames: ['plugin-ts', 'plugin-fetch'] })
439
+ * // { kind: 'contract', pluginName: 'plugin-fetch' }
440
+ * ```
441
+ *
442
+ * @example
443
+ * ```ts
444
+ * resolveClient({ client: undefined, pluginNames: ['plugin-ts'] })
445
+ * // { kind: 'error', code: 'KUBB_MISSING_DEPENDENCY', message: 'No client plugin is registered.', help: 'Add …' }
446
+ * ```
447
+ */
448
+ function resolveClient(options) {
449
+ const { client, pluginNames } = options;
450
+ const has = (name) => pluginNames.includes(name);
451
+ if (client === "fetch" || client === "axios" || client === "client") {
452
+ const pluginName = selectorToPlugin[client];
453
+ if (!has(pluginName)) return {
454
+ kind: "error",
455
+ code: Diagnostics.code.missingDependency,
456
+ message: `\`client: '${client}'\` is set but \`@kubb/plugin-${client}\` is not registered in \`plugins\`.`,
457
+ help: `Add \`@kubb/plugin-${client}\` to \`plugins\`, or drop \`client\` to use a different client plugin.`
458
+ };
459
+ return {
460
+ kind: "contract",
461
+ pluginName
462
+ };
463
+ }
464
+ if (client !== void 0) return {
465
+ kind: "error",
466
+ code: Diagnostics.code.invalidPluginOptions,
467
+ message: `Option \`client\` is ${typeof client === "string" ? `'${client}'` : String(client)}, but it must be one of 'fetch', 'axios', 'client'.`,
468
+ help: "Set `client` to one of those values, or drop it to use the registered client plugin."
469
+ };
470
+ const registered = contractPlugins.filter(has);
471
+ if (registered.length === 1) return {
472
+ kind: "contract",
473
+ pluginName: registered[0]
474
+ };
475
+ if (registered.length > 1) return {
476
+ kind: "error",
477
+ code: Diagnostics.code.invalidPluginOptions,
478
+ message: `Multiple client plugins are registered (${registered.map((name) => `\`@kubb/${name}\``).join(", ")}) and \`client\` is not set.`,
479
+ help: "Set `client: 'fetch' | 'axios' | 'client'` to choose which client the hooks call, or register a single client plugin."
480
+ };
481
+ return {
482
+ kind: "error",
483
+ code: Diagnostics.code.missingDependency,
484
+ message: "No client plugin is registered.",
485
+ help: "Add `@kubb/plugin-fetch`, `@kubb/plugin-axios`, or `@kubb/plugin-client` to `plugins` so the generated code has an HTTP client to call."
486
+ };
487
+ }
488
+ /**
489
+ * Resolves the contract client during a consumer plugin's setup hook.
490
+ * It extracts the plugin names from the raw `plugins` config and applies {@link resolveClient}.
491
+ * On a misconfiguration it throws a config diagnostic tagged with `plugin`, so every consumer
492
+ * fails fast with the same message.
493
+ */
494
+ function resolveContractClient(options) {
495
+ const { plugin, client, plugins = [] } = options;
496
+ const resolved = resolveClient({
497
+ client,
498
+ pluginNames: plugins.map((plugin) => plugin.name).filter((name) => Boolean(name))
499
+ });
500
+ if (resolved.kind === "error") {
501
+ const { code, message, help } = resolved;
502
+ throw new Diagnostics.Error({
503
+ code,
504
+ severity: "error",
505
+ message,
506
+ help,
507
+ location: { kind: "config" },
508
+ plugin
509
+ });
510
+ }
511
+ return resolved;
512
+ }
513
+ //#endregion
514
+ //#region ../../internals/client/src/resolveClientOperation.ts
515
+ function isRelativeImport(importPath) {
516
+ return importPath.startsWith(".");
517
+ }
518
+ function resolveImportPath(options) {
519
+ const { importPath, operationFile } = options;
520
+ return isRelativeImport(importPath) ? path.resolve(path.dirname(operationFile), importPath) : importPath;
521
+ }
522
+ /**
523
+ * Resolves the contract client `<op>` a consumer (query hook, MCP handler) imports, by looking up
524
+ * the registered contract client plugin's resolver and output. Works for any contract client plugin
525
+ * (plugin-fetch, plugin-axios, or plugin-client). Returns `null` when no contract plugin is in play (the inline
526
+ * path), or when the client plugin's `exclude` / `include` leaves this operation out, since it then
527
+ * emits no `<op>` to import. plugin-fetch / plugin-axios inject `.kubb/client.ts` at the global
528
+ * output root, the same path consumers read `RequestConfig` / `ResponseErrorConfig` from.
529
+ * With plugin-client they come from the user's `importPath` module instead.
530
+ *
531
+ * The result is cached in the current node's `cache` (`ctx.cache`) under the client plugin's name,
532
+ * so several dependents reading the same client plugin for one operation in a single pass
533
+ * (react-query's query/mutation/infinite generators, vue-query, swr, the MCP handler, ...) share
534
+ * one computed result instead of each re-deriving the name and path.
535
+ *
536
+ * `returnType`, `output`, and `group` are the client plugin's options for this operation, after its
537
+ * `override` entries, the same resolution its own generator sees. A dependent's generated call body
538
+ * and import path therefore match the `<op>` actually emitted, even when an `override` changes it.
539
+ */
540
+ function resolveClientOperation(options) {
541
+ const { clientPlugin, driver, node, root, output, cache } = options;
542
+ if (!clientPlugin) return null;
543
+ return cache.ensureItem(`${clientPlugin.pluginName}:clientOperation`, () => {
544
+ const resolver = driver.getResolver(clientPlugin.pluginName);
545
+ const pluginOptions = driver.getPlugin(clientPlugin.pluginName)?.options ?? {};
546
+ const { exclude, include, override } = pluginOptions;
547
+ const operationOptions = Boolean(exclude?.length || include?.length || override?.length) && resolver.default ? resolver.default.options(node, {
548
+ options: pluginOptions,
549
+ exclude,
550
+ include,
551
+ override
552
+ }) : pluginOptions;
553
+ if (!operationOptions) return null;
554
+ const file = resolver.file({
555
+ ...operationFileEntry(node, node.operationId),
556
+ root,
557
+ output: operationOptions.output ?? output,
558
+ group: operationOptions.group ?? void 0
559
+ });
560
+ const { importPath } = operationOptions;
561
+ return {
562
+ name: resolver.name(node.operationId),
563
+ path: file.path,
564
+ clientPath: importPath === void 0 ? path.resolve(root, ".kubb/client.ts") : resolveImportPath({
565
+ importPath,
566
+ operationFile: file.path
567
+ }),
568
+ clientPathIsFile: importPath === void 0 || isRelativeImport(importPath),
569
+ returnType: operationOptions.returnType ?? "full"
570
+ };
571
+ });
572
+ }
334
573
  //#endregion
335
574
  //#region ../../internals/tanstack-query/src/components/HookFile.tsx
336
575
  /**
337
- * Resolves what every TanStack hook file shares: its file, the `@kubb/plugin-ts` file and type names, banner and footer.
576
+ * Resolves what every TanStack hook file shares: its file, the operation types file and names (`@kubb/plugin-ts`, or
577
+ * `pluginZod({ inferred: 'codec' })`), banner and footer.
338
578
  */
339
579
  function resolveHookFile(node, ctx, options) {
340
580
  const { name, output, group, contractOp, keyTypeName, extraTypeNames = [] } = options;
341
581
  const { config, root, resolver } = ctx;
342
- const pluginTs = ctx.requirePlugin(pluginTsName);
343
- const tsResolver = ctx.driver.getResolver(pluginTsName);
582
+ const types = resolveOperationTypes(ctx.driver, resolver.pluginName);
583
+ const tsResolver = types.resolver;
344
584
  const file = resolver.file({
345
585
  ...operationFileEntry(node, name),
346
586
  root,
@@ -352,8 +592,8 @@ function resolveHookFile(node, ctx, options) {
352
592
  node,
353
593
  resolver: tsResolver,
354
594
  root,
355
- output: pluginTs.options?.output ?? output,
356
- group: pluginTs.options?.group
595
+ output: types.output ?? output,
596
+ group: types.group
357
597
  });
358
598
  const importedTypeNames = [
359
599
  tsResolver.response.options(node),
@@ -978,177 +1218,6 @@ function QueryKey({ name, node, tsResolver, typeName, transformer, variant = "qu
978
1218
  })] });
979
1219
  }
980
1220
  //#endregion
981
- //#region ../../internals/client/src/resolveClient.ts
982
- /**
983
- * Resolves which client plugin a consumer (react-query, vue-query, swr, mcp) should call for an
984
- * operation, shared so the selection rules and diagnostics stay in one place.
985
- *
986
- * Every client runtime lives in a dedicated client plugin, so a consumer always calls a registered
987
- * contract client plugin (plugin-fetch, plugin-axios, or plugin-client) and never emits its own
988
- * inline client:
989
- *
990
- * - `contract` — a registered contract client plugin owns the `<op>` functions and the consumer
991
- * imports and calls them.
992
- * - `error` — no client plugin is registered, several are registered without a selector, the
993
- * requested one is missing, or `client` is not a known selector.
994
- *
995
- * The `client` string selects explicitly (`'fetch'` / `'axios'` / `'client'`); when it is unset a
996
- * lone registered contract client plugin is picked up automatically.
997
- */
998
- const pluginFetchName = "plugin-fetch";
999
- const pluginAxiosName = "plugin-axios";
1000
- const pluginClientName = "plugin-client";
1001
- const selectorToPlugin = {
1002
- fetch: pluginFetchName,
1003
- axios: pluginAxiosName,
1004
- client: pluginClientName
1005
- };
1006
- const contractPlugins = [
1007
- pluginFetchName,
1008
- pluginAxiosName,
1009
- pluginClientName
1010
- ];
1011
- /**
1012
- * Applies the `client` resolution rules. See the module comment for the strategy shape.
1013
- *
1014
- * @example
1015
- * ```ts
1016
- * resolveClient({ client: 'fetch', pluginNames: ['plugin-ts', 'plugin-fetch'] })
1017
- * // { kind: 'contract', pluginName: 'plugin-fetch' }
1018
- * ```
1019
- *
1020
- * @example
1021
- * ```ts
1022
- * resolveClient({ client: undefined, pluginNames: ['plugin-ts'] })
1023
- * // { kind: 'error', code: 'KUBB_MISSING_DEPENDENCY', message: 'No client plugin is registered.', help: 'Add …' }
1024
- * ```
1025
- */
1026
- function resolveClient(options) {
1027
- const { client, pluginNames } = options;
1028
- const has = (name) => pluginNames.includes(name);
1029
- if (client === "fetch" || client === "axios" || client === "client") {
1030
- const pluginName = selectorToPlugin[client];
1031
- if (!has(pluginName)) return {
1032
- kind: "error",
1033
- code: Diagnostics.code.missingDependency,
1034
- message: `\`client: '${client}'\` is set but \`@kubb/plugin-${client}\` is not registered in \`plugins\`.`,
1035
- help: `Add \`@kubb/plugin-${client}\` to \`plugins\`, or drop \`client\` to use a different client plugin.`
1036
- };
1037
- return {
1038
- kind: "contract",
1039
- pluginName
1040
- };
1041
- }
1042
- if (client !== void 0) return {
1043
- kind: "error",
1044
- code: Diagnostics.code.invalidPluginOptions,
1045
- message: `Option \`client\` is ${typeof client === "string" ? `'${client}'` : String(client)}, but it must be one of 'fetch', 'axios', 'client'.`,
1046
- help: "Set `client` to one of those values, or drop it to use the registered client plugin."
1047
- };
1048
- const registered = contractPlugins.filter(has);
1049
- if (registered.length === 1) return {
1050
- kind: "contract",
1051
- pluginName: registered[0]
1052
- };
1053
- if (registered.length > 1) return {
1054
- kind: "error",
1055
- code: Diagnostics.code.invalidPluginOptions,
1056
- message: `Multiple client plugins are registered (${registered.map((name) => `\`@kubb/${name}\``).join(", ")}) and \`client\` is not set.`,
1057
- help: "Set `client: 'fetch' | 'axios' | 'client'` to choose which client the hooks call, or register a single client plugin."
1058
- };
1059
- return {
1060
- kind: "error",
1061
- code: Diagnostics.code.missingDependency,
1062
- message: "No client plugin is registered.",
1063
- help: "Add `@kubb/plugin-fetch`, `@kubb/plugin-axios`, or `@kubb/plugin-client` to `plugins` so the generated code has an HTTP client to call."
1064
- };
1065
- }
1066
- /**
1067
- * Resolves the contract client during a consumer plugin's setup hook.
1068
- * It extracts the plugin names from the raw `plugins` config and applies {@link resolveClient}.
1069
- * On a misconfiguration it throws a config diagnostic tagged with `plugin`, so every consumer
1070
- * fails fast with the same message.
1071
- */
1072
- function resolveContractClient(options) {
1073
- const { plugin, client, plugins = [] } = options;
1074
- const resolved = resolveClient({
1075
- client,
1076
- pluginNames: plugins.map((plugin) => plugin.name).filter((name) => Boolean(name))
1077
- });
1078
- if (resolved.kind === "error") {
1079
- const { code, message, help } = resolved;
1080
- throw new Diagnostics.Error({
1081
- code,
1082
- severity: "error",
1083
- message,
1084
- help,
1085
- location: { kind: "config" },
1086
- plugin
1087
- });
1088
- }
1089
- return resolved;
1090
- }
1091
- //#endregion
1092
- //#region ../../internals/client/src/resolveClientOperation.ts
1093
- function isRelativeImport(importPath) {
1094
- return importPath.startsWith(".");
1095
- }
1096
- function resolveImportPath(options) {
1097
- const { importPath, operationFile } = options;
1098
- return isRelativeImport(importPath) ? path.resolve(path.dirname(operationFile), importPath) : importPath;
1099
- }
1100
- /**
1101
- * Resolves the contract client `<op>` a consumer (query hook, MCP handler) imports, by looking up
1102
- * the registered contract client plugin's resolver and output. Works for any contract client plugin
1103
- * (plugin-fetch, plugin-axios, or plugin-client). Returns `null` when no contract plugin is in play (the inline
1104
- * path), or when the client plugin's `exclude` / `include` leaves this operation out, since it then
1105
- * emits no `<op>` to import. plugin-fetch / plugin-axios inject `.kubb/client.ts` at the global
1106
- * output root, the same path consumers read `RequestConfig` / `ResponseErrorConfig` from.
1107
- * With plugin-client they come from the user's `importPath` module instead.
1108
- *
1109
- * The result is cached in the current node's `cache` (`ctx.cache`) under the client plugin's name,
1110
- * so several dependents reading the same client plugin for one operation in a single pass
1111
- * (react-query's query/mutation/infinite generators, vue-query, swr, the MCP handler, ...) share
1112
- * one computed result instead of each re-deriving the name and path.
1113
- *
1114
- * `returnType`, `output`, and `group` are the client plugin's options for this operation, after its
1115
- * `override` entries, the same resolution its own generator sees. A dependent's generated call body
1116
- * and import path therefore match the `<op>` actually emitted, even when an `override` changes it.
1117
- */
1118
- function resolveClientOperation(options) {
1119
- const { clientPlugin, driver, node, root, output, cache } = options;
1120
- if (!clientPlugin) return null;
1121
- return cache.ensureItem(`${clientPlugin.pluginName}:clientOperation`, () => {
1122
- const resolver = driver.getResolver(clientPlugin.pluginName);
1123
- const pluginOptions = driver.getPlugin(clientPlugin.pluginName)?.options ?? {};
1124
- const { exclude, include, override } = pluginOptions;
1125
- const operationOptions = Boolean(exclude?.length || include?.length || override?.length) && resolver.default ? resolver.default.options(node, {
1126
- options: pluginOptions,
1127
- exclude,
1128
- include,
1129
- override
1130
- }) : pluginOptions;
1131
- if (!operationOptions) return null;
1132
- const file = resolver.file({
1133
- ...operationFileEntry(node, node.operationId),
1134
- root,
1135
- output: operationOptions.output ?? output,
1136
- group: operationOptions.group ?? void 0
1137
- });
1138
- const { importPath } = operationOptions;
1139
- return {
1140
- name: resolver.name(node.operationId),
1141
- path: file.path,
1142
- clientPath: importPath === void 0 ? path.resolve(root, ".kubb/client.ts") : resolveImportPath({
1143
- importPath,
1144
- operationFile: file.path
1145
- }),
1146
- clientPathIsFile: importPath === void 0 || isRelativeImport(importPath),
1147
- returnType: operationOptions.returnType ?? "full"
1148
- };
1149
- });
1150
- }
1151
- //#endregion
1152
1221
  //#region src/components/QueryOptions.tsx
1153
1222
  const declarationPrinter$2 = functionPrinter({ mode: "declaration" });
1154
1223
  const callPrinter$2 = functionPrinter({ mode: "call" });
@@ -1328,7 +1397,7 @@ const infiniteQueryGenerator = defineGenerator({
1328
1397
  contractOp,
1329
1398
  keyTypeName: queryKeyTypeName,
1330
1399
  extraTypeNames: [resolvePageParamType(node, {
1331
- resolver: ctx.driver.getResolver(pluginTsName),
1400
+ resolver: resolveOperationTypes(ctx.driver, ctx.resolver.pluginName).resolver,
1332
1401
  initialPageParam: infiniteOptions.initialPageParam,
1333
1402
  queryParam: infiniteOptions.queryParam
1334
1403
  }).queryParamsTypeName]
@@ -1723,7 +1792,7 @@ const pluginVueQuery = defineExtension({
1723
1792
  version,
1724
1793
  compatibility
1725
1794
  },
1726
- dependencies: { [pluginTsName]: {} },
1795
+ dependencies: { [pluginTsName]: { optional: true } },
1727
1796
  setup(options) {
1728
1797
  const { output = {
1729
1798
  path: "hooks",