@kubb/plugin-react-query 5.0.0-beta.3 → 5.0.0-beta.30

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.
Files changed (48) hide show
  1. package/README.md +34 -83
  2. package/dist/{components-DTGLu4UV.js → components-CDmg-RPi.js} +275 -255
  3. package/dist/components-CDmg-RPi.js.map +1 -0
  4. package/dist/{components-dAKJEn9b.cjs → components-MPBTffPl.cjs} +299 -255
  5. package/dist/components-MPBTffPl.cjs.map +1 -0
  6. package/dist/components.cjs +1 -1
  7. package/dist/components.d.ts +1 -75
  8. package/dist/components.js +1 -1
  9. package/dist/{generators-C_fbcjpG.js → generators-Bma51Uar.js} +301 -261
  10. package/dist/generators-Bma51Uar.js.map +1 -0
  11. package/dist/{generators-CWEQsdO9.cjs → generators-BtsWNz-6.cjs} +299 -259
  12. package/dist/generators-BtsWNz-6.cjs.map +1 -0
  13. package/dist/generators.cjs +1 -1
  14. package/dist/generators.d.ts +41 -1
  15. package/dist/generators.js +1 -1
  16. package/dist/index.cjs +143 -20
  17. package/dist/index.cjs.map +1 -1
  18. package/dist/index.d.ts +30 -1
  19. package/dist/index.js +143 -20
  20. package/dist/index.js.map +1 -1
  21. package/dist/types-DiZPLTXl.d.ts +400 -0
  22. package/extension.yaml +1507 -0
  23. package/package.json +16 -18
  24. package/src/components/InfiniteQuery.tsx +19 -13
  25. package/src/components/InfiniteQueryOptions.tsx +29 -47
  26. package/src/components/Mutation.tsx +35 -15
  27. package/src/components/MutationOptions.tsx +14 -13
  28. package/src/components/Query.tsx +9 -10
  29. package/src/components/QueryOptions.tsx +6 -27
  30. package/src/components/SuspenseInfiniteQuery.tsx +19 -13
  31. package/src/components/SuspenseInfiniteQueryOptions.tsx +29 -47
  32. package/src/components/SuspenseQuery.tsx +9 -10
  33. package/src/generators/customHookOptionsFileGenerator.tsx +18 -14
  34. package/src/generators/hookOptionsGenerator.tsx +36 -33
  35. package/src/generators/infiniteQueryGenerator.tsx +46 -64
  36. package/src/generators/mutationGenerator.tsx +42 -50
  37. package/src/generators/queryGenerator.tsx +43 -49
  38. package/src/generators/suspenseInfiniteQueryGenerator.tsx +41 -51
  39. package/src/generators/suspenseQueryGenerator.tsx +44 -62
  40. package/src/plugin.ts +42 -16
  41. package/src/resolvers/resolverReactQuery.ts +102 -6
  42. package/src/types.ts +199 -61
  43. package/src/utils.ts +10 -33
  44. package/dist/components-DTGLu4UV.js.map +0 -1
  45. package/dist/components-dAKJEn9b.cjs.map +0 -1
  46. package/dist/generators-CWEQsdO9.cjs.map +0 -1
  47. package/dist/generators-C_fbcjpG.js.map +0 -1
  48. package/dist/types-DfaFRSBf.d.ts +0 -284
@@ -1,30 +1,37 @@
1
1
  import "./chunk--u3MIqq1.js";
2
- import { a as Mutation, c as InfiniteQuery, d as transformName, f as QueryKey, i as Query, l as QueryOptions, n as SuspenseInfiniteQueryOptions, o as MutationOptions, p as MutationKey, r as SuspenseInfiniteQuery, s as InfiniteQueryOptions, t as SuspenseQuery, u as resolveOperationOverrides } from "./components-DTGLu4UV.js";
2
+ import { a as Mutation, c as InfiniteQuery, f as resolveOperationOverrides, g as MutationKey, h as resolveOperationTypeNames, i as Query, l as QueryOptions, m as getOperationParameters, n as SuspenseInfiniteQueryOptions, o as MutationOptions, p as resolveZodSchemaNames, r as SuspenseInfiniteQuery, s as InfiniteQueryOptions, t as SuspenseQuery, u as QueryKey } from "./components-CDmg-RPi.js";
3
3
  import path from "node:path";
4
- import { ast, defineGenerator } from "@kubb/core";
4
+ import { defineGenerator } from "@kubb/core";
5
5
  import { Client, pluginClientName } from "@kubb/plugin-client";
6
6
  import { pluginTsName } from "@kubb/plugin-ts";
7
7
  import { pluginZodName } from "@kubb/plugin-zod";
8
- import { File, Function, Type, jsxRenderer } from "@kubb/renderer-jsx";
8
+ import { File, Function, Type, jsxRendererSync } from "@kubb/renderer-jsx";
9
9
  import { Fragment, jsx, jsxs } from "@kubb/renderer-jsx/jsx-runtime";
10
10
  import fs from "node:fs";
11
11
  import { difference } from "remeda";
12
12
  //#region src/generators/customHookOptionsFileGenerator.tsx
13
+ /**
14
+ * Scaffolds the user-editable `useCustomHookOptions` file when
15
+ * `pluginReactQuery({ customOptions: { ... } })` is configured. The file is
16
+ * only created when it does not already exist, so user edits persist across
17
+ * regeneration.
18
+ */
13
19
  const customHookOptionsFileGenerator = defineGenerator({
14
20
  name: "react-query-custom-hook-options-file",
15
- renderer: jsxRenderer,
21
+ renderer: jsxRendererSync,
16
22
  operations(nodes, ctx) {
17
23
  const { resolver, config, root } = ctx;
18
- const { output, customOptions, query, group, transformers } = ctx.options;
24
+ const { output, customOptions, query, group } = ctx.options;
19
25
  if (!customOptions) return null;
20
26
  const override = output.override ?? config.output.override ?? false;
21
27
  const { importPath, name } = customOptions;
28
+ const hookOptionsName = resolver.resolveHookOptionsName();
29
+ const customHookOptionsName = resolver.resolveCustomHookOptionsName();
22
30
  const reactQueryImportPath = query ? query.importPath : "@tanstack/react-query";
23
- const capitalize = (s) => s.charAt(0).toUpperCase() + s.slice(1);
24
31
  let hookFilePath;
25
32
  const firstNode = nodes[0];
26
33
  if (firstNode) {
27
- const hookName = transformName(`use${capitalize(resolver.resolveName(firstNode.operationId))}`, "function", transformers);
34
+ const hookName = resolver.resolveQueryName(firstNode);
28
35
  hookFilePath = resolver.resolveFile({
29
36
  name: hookName,
30
37
  extname: ".ts",
@@ -33,7 +40,7 @@ const customHookOptionsFileGenerator = defineGenerator({
33
40
  }, {
34
41
  root,
35
42
  output,
36
- group
43
+ group: group ?? void 0
37
44
  }).path;
38
45
  } else hookFilePath = path.resolve(root, "index.ts");
39
46
  const ensureExtension = (filePath, extname) => {
@@ -62,7 +69,7 @@ const customHookOptionsFileGenerator = defineGenerator({
62
69
  path: reactQueryImportPath
63
70
  }),
64
71
  /* @__PURE__ */ jsx(File.Import, {
65
- name: ["HookOptions"],
72
+ name: [hookOptionsName],
66
73
  root: file.path,
67
74
  path: path.resolve(root, "./index.ts")
68
75
  }),
@@ -71,9 +78,9 @@ const customHookOptionsFileGenerator = defineGenerator({
71
78
  isExportable: true,
72
79
  isIndexable: true,
73
80
  children: [/* @__PURE__ */ jsx(Function, {
74
- name: "getCustomHookOptions",
81
+ name: customHookOptionsName,
75
82
  params: "{ queryClient }: { queryClient: QueryClient }",
76
- returnType: "Partial<HookOptions>",
83
+ returnType: `Partial<${hookOptionsName}>`,
77
84
  children: `return {
78
85
  // TODO: Define custom hook options here
79
86
  // Example:
@@ -85,12 +92,12 @@ const customHookOptionsFileGenerator = defineGenerator({
85
92
  }`
86
93
  }), /* @__PURE__ */ jsx(Function, {
87
94
  name,
88
- generics: "T extends keyof HookOptions",
95
+ generics: `T extends keyof ${hookOptionsName}`,
89
96
  params: "{ hookName, operationId }: { hookName: T, operationId: string }",
90
- returnType: "HookOptions[T]",
97
+ returnType: `${hookOptionsName}[T]`,
91
98
  export: true,
92
99
  children: `const queryClient = useQueryClient()
93
- const customOptions = getCustomHookOptions({ queryClient })
100
+ const customOptions = ${customHookOptionsName}({ queryClient })
94
101
  return customOptions[hookName] ?? {}`
95
102
  })]
96
103
  })
@@ -100,43 +107,48 @@ const customHookOptionsFileGenerator = defineGenerator({
100
107
  });
101
108
  //#endregion
102
109
  //#region src/generators/hookOptionsGenerator.tsx
110
+ /**
111
+ * Emits the `HookOptions` type used by `customOptions`. Enabled when
112
+ * `pluginReactQuery({ customOptions: { ... } })`. The generated type lists
113
+ * every hook keyed by name so user-supplied options stay in sync with the
114
+ * generated hooks at compile time.
115
+ */
103
116
  const hookOptionsGenerator = defineGenerator({
104
117
  name: "react-query-hook-options",
105
- renderer: jsxRenderer,
118
+ renderer: jsxRendererSync,
106
119
  operations(nodes, ctx) {
107
- const { resolver, config, root, adapter } = ctx;
108
- const { output, customOptions, query, mutation, suspense, infinite, group, transformers, override } = ctx.options;
120
+ const { resolver, config, root } = ctx;
121
+ const { output, customOptions, query, mutation, suspense, infinite, group, override } = ctx.options;
109
122
  if (!customOptions) return null;
123
+ const name = resolver.resolveHookOptionsName();
110
124
  const resolvedFile = resolver.resolveFile({
111
- name: "HookOptions",
125
+ name,
112
126
  extname: ".ts"
113
127
  }, {
114
128
  root,
115
129
  output,
116
- group
130
+ group: group ?? void 0
117
131
  });
118
132
  const hookOptionsFile = {
119
133
  ...resolvedFile,
120
- baseName: "HookOptions.ts",
121
- path: resolvedFile.path.replace(/hookOptions\.ts$/, "HookOptions.ts")
134
+ baseName: `${name}.ts`,
135
+ path: resolvedFile.path.replace(/[^/\\]+\.ts$/, `${name}.ts`)
122
136
  };
123
- const capitalize = (s) => s.charAt(0).toUpperCase() + s.slice(1);
124
137
  const imports = [];
125
138
  const hookOptions = {};
126
139
  for (const node of nodes) {
127
- const baseName = resolver.resolveName(node.operationId);
128
140
  const opOverrides = resolveOperationOverrides(node, override);
129
141
  const nodeQuery = "query" in opOverrides ? opOverrides.query : query;
130
142
  const nodeMutation = "mutation" in opOverrides ? opOverrides.mutation : mutation;
131
143
  const nodeInfinite = "infinite" in opOverrides ? opOverrides.infinite : infinite;
132
- const nodeInfiniteOptions = nodeInfinite && typeof nodeInfinite === "object" ? nodeInfinite : void 0;
144
+ const nodeInfiniteOptions = nodeInfinite && typeof nodeInfinite === "object" ? nodeInfinite : null;
133
145
  const isQueryOp = nodeQuery === false ? !!query && query.methods.some((m) => node.method.toLowerCase() === m.toLowerCase()) : !!nodeQuery && nodeQuery.methods.some((m) => node.method.toLowerCase() === m.toLowerCase());
134
146
  const isMutationOp = nodeMutation !== false && !isQueryOp && difference(nodeMutation ? nodeMutation.methods : [], nodeQuery ? nodeQuery.methods : []).some((m) => node.method.toLowerCase() === m.toLowerCase());
135
147
  const isSuspenseOp = !!suspense;
136
148
  const isInfiniteOp = !!nodeInfiniteOptions;
137
149
  if (isQueryOp) {
138
- const queryOptionsName = transformName(`${baseName}QueryOptions`, "function", transformers);
139
- const queryHookName = transformName(`use${capitalize(baseName)}`, "function", transformers);
150
+ const queryOptionsName = resolver.resolveQueryOptionsName(node);
151
+ const queryHookName = resolver.resolveQueryName(node);
140
152
  const queryHookFile = resolver.resolveFile({
141
153
  name: queryHookName,
142
154
  extname: ".ts",
@@ -145,7 +157,7 @@ const hookOptionsGenerator = defineGenerator({
145
157
  }, {
146
158
  root,
147
159
  output,
148
- group
160
+ group: group ?? void 0
149
161
  });
150
162
  imports.push(/* @__PURE__ */ jsx(File.Import, {
151
163
  name: [queryOptionsName],
@@ -154,8 +166,8 @@ const hookOptionsGenerator = defineGenerator({
154
166
  }));
155
167
  hookOptions[queryHookName] = `Partial<ReturnType<typeof ${queryOptionsName}>>`;
156
168
  if (isSuspenseOp) {
157
- const suspenseOptionsName = transformName(`${baseName}SuspenseQueryOptions`, "function", transformers);
158
- const suspenseHookName = transformName(`use${capitalize(baseName)}Suspense`, "function", transformers);
169
+ const suspenseOptionsName = resolver.resolveSuspenseQueryOptionsName(node);
170
+ const suspenseHookName = resolver.resolveSuspenseQueryName(node);
159
171
  const suspenseHookFile = resolver.resolveFile({
160
172
  name: suspenseHookName,
161
173
  extname: ".ts",
@@ -164,7 +176,7 @@ const hookOptionsGenerator = defineGenerator({
164
176
  }, {
165
177
  root,
166
178
  output,
167
- group
179
+ group: group ?? void 0
168
180
  });
169
181
  imports.push(/* @__PURE__ */ jsx(File.Import, {
170
182
  name: [suspenseOptionsName],
@@ -175,10 +187,10 @@ const hookOptionsGenerator = defineGenerator({
175
187
  }
176
188
  if (isInfiniteOp) {
177
189
  const normalizeKey = (key) => key.replace(/\?$/, "");
178
- const queryParamKeys = node.parameters.filter((p) => p.in === "query").map((p) => p.name);
190
+ const queryParamKeys = getOperationParameters(node).query.map((p) => p.name);
179
191
  if (nodeInfiniteOptions.queryParam ? queryParamKeys.some((k) => normalizeKey(k) === nodeInfiniteOptions.queryParam) : false) {
180
- const infiniteOptionsName = transformName(`${baseName}InfiniteQueryOptions`, "function", transformers);
181
- const infiniteHookName = transformName(`use${capitalize(baseName)}Infinite`, "function", transformers);
192
+ const infiniteOptionsName = resolver.resolveInfiniteQueryOptionsName(node);
193
+ const infiniteHookName = resolver.resolveInfiniteQueryName(node);
182
194
  const infiniteHookFile = resolver.resolveFile({
183
195
  name: infiniteHookName,
184
196
  extname: ".ts",
@@ -187,7 +199,7 @@ const hookOptionsGenerator = defineGenerator({
187
199
  }, {
188
200
  root,
189
201
  output,
190
- group
202
+ group: group ?? void 0
191
203
  });
192
204
  imports.push(/* @__PURE__ */ jsx(File.Import, {
193
205
  name: [infiniteOptionsName],
@@ -196,8 +208,8 @@ const hookOptionsGenerator = defineGenerator({
196
208
  }));
197
209
  hookOptions[infiniteHookName] = `Partial<ReturnType<typeof ${infiniteOptionsName}>>`;
198
210
  if (isSuspenseOp) {
199
- const suspenseInfiniteOptionsName = transformName(`${baseName}SuspenseInfiniteQueryOptions`, "function", transformers);
200
- const suspenseInfiniteHookName = transformName(`use${capitalize(baseName)}SuspenseInfinite`, "function", transformers);
211
+ const suspenseInfiniteOptionsName = resolver.resolveSuspenseInfiniteQueryOptionsName(node);
212
+ const suspenseInfiniteHookName = resolver.resolveSuspenseInfiniteQueryName(node);
201
213
  const suspenseInfiniteHookFile = resolver.resolveFile({
202
214
  name: suspenseInfiniteHookName,
203
215
  extname: ".ts",
@@ -206,7 +218,7 @@ const hookOptionsGenerator = defineGenerator({
206
218
  }, {
207
219
  root,
208
220
  output,
209
- group
221
+ group: group ?? void 0
210
222
  });
211
223
  imports.push(/* @__PURE__ */ jsx(File.Import, {
212
224
  name: [suspenseInfiniteOptionsName],
@@ -219,8 +231,8 @@ const hookOptionsGenerator = defineGenerator({
219
231
  }
220
232
  }
221
233
  if (isMutationOp) {
222
- const mutationOptionsName = transformName(`${baseName}MutationOptions`, "function", transformers);
223
- const mutationHookName = transformName(`use${capitalize(baseName)}`, "function", transformers);
234
+ const mutationOptionsName = resolver.resolveMutationOptionsName(node);
235
+ const mutationHookName = resolver.resolveMutationName(node);
224
236
  const mutationHookFile = resolver.resolveFile({
225
237
  name: mutationHookName,
226
238
  extname: ".ts",
@@ -229,7 +241,7 @@ const hookOptionsGenerator = defineGenerator({
229
241
  }, {
230
242
  root,
231
243
  output,
232
- group
244
+ group: group ?? void 0
233
245
  });
234
246
  imports.push(/* @__PURE__ */ jsx(File.Import, {
235
247
  name: [mutationOptionsName],
@@ -239,18 +251,25 @@ const hookOptionsGenerator = defineGenerator({
239
251
  hookOptions[mutationHookName] = `Partial<ReturnType<typeof ${mutationOptionsName}>>`;
240
252
  }
241
253
  }
242
- const name = "HookOptions";
243
254
  return /* @__PURE__ */ jsxs(File, {
244
255
  baseName: hookOptionsFile.baseName,
245
256
  path: hookOptionsFile.path,
246
257
  meta: hookOptionsFile.meta,
247
- banner: resolver.resolveBanner(adapter.inputNode, {
258
+ banner: resolver.resolveBanner(ctx.meta, {
248
259
  output,
249
- config
260
+ config,
261
+ file: {
262
+ path: hookOptionsFile.path,
263
+ baseName: hookOptionsFile.baseName
264
+ }
250
265
  }),
251
- footer: resolver.resolveFooter(adapter.inputNode, {
266
+ footer: resolver.resolveFooter(ctx.meta, {
252
267
  output,
253
- config
268
+ config,
269
+ file: {
270
+ path: hookOptionsFile.path,
271
+ baseName: hookOptionsFile.baseName
272
+ }
254
273
  }),
255
274
  children: [imports, /* @__PURE__ */ jsx(File.Source, {
256
275
  name,
@@ -268,32 +287,36 @@ const hookOptionsGenerator = defineGenerator({
268
287
  });
269
288
  //#endregion
270
289
  //#region src/generators/infiniteQueryGenerator.tsx
290
+ /**
291
+ * Built-in generator for `useInfiniteQuery` hooks. Enabled when
292
+ * `pluginReactQuery({ infinite: { ... } })`. Emits one `useFooInfiniteQuery`
293
+ * hook per query operation, wiring the configured `nextParam` /
294
+ * `previousParam` paths into TanStack Query's cursor-based pagination.
295
+ */
271
296
  const infiniteQueryGenerator = defineGenerator({
272
297
  name: "react-infinite-query",
273
- renderer: jsxRenderer,
298
+ renderer: jsxRendererSync,
274
299
  operation(node, ctx) {
275
- const { adapter, config, driver, resolver, root } = ctx;
276
- const { output, query, mutation, infinite, paramsCasing, paramsType, pathParamsType, parser, client: clientOptions, group, transformers, customOptions } = ctx.options;
300
+ const { config, driver, resolver, root } = ctx;
301
+ const { output, query, mutation, infinite, paramsCasing, paramsType, pathParamsType, parser, client: clientOptions, group, customOptions } = ctx.options;
277
302
  const pluginTs = driver.getPlugin(pluginTsName);
278
303
  if (!pluginTs) return null;
279
304
  const tsResolver = driver.getResolver(pluginTsName);
280
305
  const isQuery = query === false || !!query && query.methods.some((method) => node.method.toLowerCase() === method.toLowerCase());
281
306
  const isMutation = mutation !== false && !isQuery && difference(mutation ? mutation.methods : [], query ? query.methods : []).some((method) => node.method.toLowerCase() === method.toLowerCase());
282
- const infiniteOptions = infinite && typeof infinite === "object" ? infinite : void 0;
307
+ const infiniteOptions = infinite && typeof infinite === "object" ? infinite : null;
283
308
  if (!isQuery || isMutation || !infiniteOptions) return null;
284
309
  const normalizeKey = (key) => key.replace(/\?$/, "");
285
- const queryParamKeys = node.parameters.filter((p) => p.in === "query").map((p) => p.name);
310
+ const queryParamKeys = getOperationParameters(node).query.map((p) => p.name);
286
311
  const hasQueryParam = infiniteOptions.queryParam ? queryParamKeys.some((k) => normalizeKey(k) === infiniteOptions.queryParam) : false;
287
312
  const hasCursorParam = !infiniteOptions.cursorParam || true;
288
313
  if (!hasQueryParam || !hasCursorParam) return null;
289
314
  const importPath = query ? query.importPath : "@tanstack/react-query";
290
- const baseName = resolver.resolveName(node.operationId);
291
- const capitalize = (s) => s.charAt(0).toUpperCase() + s.slice(1);
292
- const queryName = transformName(`use${capitalize(baseName)}Infinite`, "function", transformers);
293
- const queryOptionsName = transformName(`${baseName}InfiniteQueryOptions`, "function", transformers);
294
- const queryKeyName = transformName(`${baseName}InfiniteQueryKey`, "const", transformers);
295
- const queryKeyTypeName = transformName(`${capitalize(baseName)}InfiniteQueryKey`, "type", transformers);
296
- const clientBaseName = transformName(`${baseName}Infinite`, "function", transformers);
315
+ const queryName = resolver.resolveInfiniteQueryName(node);
316
+ const queryOptionsName = resolver.resolveInfiniteQueryOptionsName(node);
317
+ const queryKeyName = resolver.resolveInfiniteQueryKeyName(node);
318
+ const queryKeyTypeName = resolver.resolveInfiniteQueryKeyTypeName(node);
319
+ const clientBaseName = resolver.resolveInfiniteClientName(node);
297
320
  const meta = {
298
321
  file: resolver.resolveFile({
299
322
  name: queryName,
@@ -303,7 +326,7 @@ const infiniteQueryGenerator = defineGenerator({
303
326
  }, {
304
327
  root,
305
328
  output,
306
- group
329
+ group: group ?? void 0
307
330
  }),
308
331
  fileTs: tsResolver.resolveFile({
309
332
  name: node.operationId,
@@ -313,23 +336,16 @@ const infiniteQueryGenerator = defineGenerator({
313
336
  }, {
314
337
  root,
315
338
  output: pluginTs.options?.output ?? output,
316
- group: pluginTs.options?.group
339
+ group: pluginTs.options?.group ?? void 0
317
340
  })
318
341
  };
319
- const casedParams = ast.caseParams(node.parameters, paramsCasing);
320
- const pathParams = casedParams.filter((p) => p.in === "path");
321
- const queryParams = casedParams.filter((p) => p.in === "query");
322
- const headerParams = casedParams.filter((p) => p.in === "header");
323
- const importedTypeNames = [
324
- node.requestBody?.content?.[0]?.schema ? tsResolver.resolveDataName(node) : void 0,
325
- tsResolver.resolveResponseName(node),
326
- ...pathParams.map((p) => tsResolver.resolvePathParamsName(node, p)),
327
- ...queryParams.map((p) => tsResolver.resolveQueryParamsName(node, p)),
328
- ...headerParams.map((p) => tsResolver.resolveHeaderParamsName(node, p)),
329
- ...node.responses.map((res) => tsResolver.resolveResponseStatusName(node, res.statusCode))
330
- ].filter((name) => !!name && name !== queryKeyTypeName);
331
- const pluginZod = parser === "zod" ? driver.getPlugin(pluginZodName) : void 0;
332
- const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : void 0;
342
+ const importedTypeNames = resolveOperationTypeNames(node, tsResolver, {
343
+ paramsCasing,
344
+ exclude: [queryKeyTypeName],
345
+ order: "body-response-first"
346
+ });
347
+ const pluginZod = parser === "zod" ? driver.getPlugin(pluginZodName) : null;
348
+ const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : null;
333
349
  const fileZod = zodResolver ? zodResolver.resolveFile({
334
350
  name: node.operationId,
335
351
  extname: ".ts",
@@ -338,12 +354,12 @@ const infiniteQueryGenerator = defineGenerator({
338
354
  }, {
339
355
  root,
340
356
  output: pluginZod?.options?.output ?? output,
341
- group: pluginZod?.options?.group
342
- }) : void 0;
343
- const zodSchemaNames = zodResolver && parser === "zod" ? [zodResolver.resolveResponseName?.(node), node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : void 0].filter(Boolean) : [];
357
+ group: pluginZod?.options?.group ?? void 0
358
+ }) : null;
359
+ const zodSchemaNames = resolveZodSchemaNames(node, zodResolver);
344
360
  const clientPlugin = driver.getPlugin(pluginClientName);
345
361
  const shouldUseClientPlugin = clientPlugin?.name === pluginClientName && clientOptions.clientType !== "class";
346
- const clientResolver = shouldUseClientPlugin ? driver.getResolver(pluginClientName) : void 0;
362
+ const clientResolver = shouldUseClientPlugin ? driver.getResolver(pluginClientName) : null;
347
363
  const clientFile = shouldUseClientPlugin ? clientResolver?.resolveFile({
348
364
  name: node.operationId,
349
365
  extname: ".ts",
@@ -352,30 +368,38 @@ const infiniteQueryGenerator = defineGenerator({
352
368
  }, {
353
369
  root,
354
370
  output: clientPlugin?.options?.output ?? output,
355
- group: clientPlugin?.options?.group
356
- }) : void 0;
371
+ group: clientPlugin?.options?.group ?? void 0
372
+ }) : null;
357
373
  const resolvedClientName = shouldUseClientPlugin ? clientResolver?.resolveName(node.operationId) ?? clientBaseName : clientBaseName;
358
374
  return /* @__PURE__ */ jsxs(File, {
359
375
  baseName: meta.file.baseName,
360
376
  path: meta.file.path,
361
377
  meta: meta.file.meta,
362
- banner: resolver.resolveBanner(adapter.inputNode, {
378
+ banner: resolver.resolveBanner(ctx.meta, {
363
379
  output,
364
- config
380
+ config,
381
+ file: {
382
+ path: meta.file.path,
383
+ baseName: meta.file.baseName
384
+ }
365
385
  }),
366
- footer: resolver.resolveFooter(adapter.inputNode, {
386
+ footer: resolver.resolveFooter(ctx.meta, {
367
387
  output,
368
- config
388
+ config,
389
+ file: {
390
+ path: meta.file.path,
391
+ baseName: meta.file.baseName
392
+ }
369
393
  }),
370
394
  children: [
371
- parser === "zod" && fileZod && zodSchemaNames.length > 0 && /* @__PURE__ */ jsx(File.Import, {
395
+ fileZod && zodSchemaNames.length > 0 && /* @__PURE__ */ jsx(File.Import, {
372
396
  name: zodSchemaNames,
373
397
  root: meta.file.path,
374
398
  path: fileZod.path
375
399
  }),
376
400
  clientOptions.importPath ? /* @__PURE__ */ jsxs(Fragment, { children: [
377
401
  !shouldUseClientPlugin && /* @__PURE__ */ jsx(File.Import, {
378
- name: "fetch",
402
+ name: "client",
379
403
  path: clientOptions.importPath
380
404
  }),
381
405
  /* @__PURE__ */ jsx(File.Import, {
@@ -394,9 +418,9 @@ const infiniteQueryGenerator = defineGenerator({
394
418
  })
395
419
  ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
396
420
  !shouldUseClientPlugin && /* @__PURE__ */ jsx(File.Import, {
397
- name: ["fetch"],
421
+ name: ["client"],
398
422
  root: meta.file.path,
399
- path: path.resolve(root, ".kubb/fetch.ts")
423
+ path: path.resolve(root, ".kubb/client.ts")
400
424
  }),
401
425
  /* @__PURE__ */ jsx(File.Import, {
402
426
  name: [
@@ -405,13 +429,13 @@ const infiniteQueryGenerator = defineGenerator({
405
429
  "ResponseErrorConfig"
406
430
  ],
407
431
  root: meta.file.path,
408
- path: path.resolve(root, ".kubb/fetch.ts"),
432
+ path: path.resolve(root, ".kubb/client.ts"),
409
433
  isTypeOnly: true
410
434
  }),
411
435
  clientOptions.dataReturnType === "full" && /* @__PURE__ */ jsx(File.Import, {
412
436
  name: ["ResponseConfig"],
413
437
  root: meta.file.path,
414
- path: path.resolve(root, ".kubb/fetch.ts"),
438
+ path: path.resolve(root, ".kubb/client.ts"),
415
439
  isTypeOnly: true
416
440
  })
417
441
  ] }),
@@ -516,25 +540,28 @@ const infiniteQueryGenerator = defineGenerator({
516
540
  });
517
541
  //#endregion
518
542
  //#region src/generators/mutationGenerator.tsx
543
+ /**
544
+ * Built-in generator for `useMutation` hooks. Emits one `useFooMutation` hook
545
+ * per POST/PUT/DELETE operation (configurable via `mutation.methods`) plus
546
+ * the matching `fooMutationKey` / `fooMutationOptions` helpers.
547
+ */
519
548
  const mutationGenerator = defineGenerator({
520
549
  name: "react-query-mutation",
521
- renderer: jsxRenderer,
550
+ renderer: jsxRendererSync,
522
551
  operation(node, ctx) {
523
- const { adapter, config, driver, resolver, root } = ctx;
524
- const { output, query, mutation, paramsCasing, paramsType, pathParamsType, parser, client: clientOptions, group, transformers, customOptions } = ctx.options;
552
+ const { config, driver, resolver, root } = ctx;
553
+ const { output, query, mutation, paramsCasing, paramsType, pathParamsType, parser, client: clientOptions, group, customOptions } = ctx.options;
525
554
  const pluginTs = driver.getPlugin(pluginTsName);
526
555
  if (!pluginTs) return null;
527
556
  const tsResolver = driver.getResolver(pluginTsName);
528
557
  const isQuery = query === false || !!query && query.methods.some((method) => node.method.toLowerCase() === method.toLowerCase());
529
558
  if (!(mutation !== false && !isQuery && difference(mutation ? mutation.methods : [], query ? query.methods : []).some((method) => node.method.toLowerCase() === method.toLowerCase()))) return null;
530
559
  const importPath = mutation ? mutation.importPath : "@tanstack/react-query";
531
- const baseName = resolver.resolveName(node.operationId);
532
- const capitalize = (s) => s.charAt(0).toUpperCase() + s.slice(1);
533
- const mutationHookName = transformName(`use${capitalize(baseName)}`, "function", transformers);
534
- const mutationTypeName = transformName(`${capitalize(baseName)}`, "type", transformers);
535
- const mutationOptionsName = transformName(`${baseName}MutationOptions`, "function", transformers);
536
- const mutationKeyName = transformName(`${baseName}MutationKey`, "const", transformers);
537
- const clientName = transformName(baseName, "function", transformers);
560
+ const mutationHookName = resolver.resolveMutationName(node);
561
+ const mutationTypeName = resolver.resolveMutationTypeName(node);
562
+ const mutationOptionsName = resolver.resolveMutationOptionsName(node);
563
+ const mutationKeyName = resolver.resolveMutationKeyName(node);
564
+ const clientName = resolver.resolveClientName(node);
538
565
  const meta = {
539
566
  file: resolver.resolveFile({
540
567
  name: mutationHookName,
@@ -544,7 +571,7 @@ const mutationGenerator = defineGenerator({
544
571
  }, {
545
572
  root,
546
573
  output,
547
- group
574
+ group: group ?? void 0
548
575
  }),
549
576
  fileTs: tsResolver.resolveFile({
550
577
  name: node.operationId,
@@ -554,23 +581,15 @@ const mutationGenerator = defineGenerator({
554
581
  }, {
555
582
  root,
556
583
  output: pluginTs.options?.output ?? output,
557
- group: pluginTs.options?.group
584
+ group: pluginTs.options?.group ?? void 0
558
585
  })
559
586
  };
560
- const casedParams = ast.caseParams(node.parameters, paramsCasing);
561
- const pathParams = casedParams.filter((p) => p.in === "path");
562
- const queryParams = casedParams.filter((p) => p.in === "query");
563
- const headerParams = casedParams.filter((p) => p.in === "header");
564
- const importedTypeNames = [
565
- node.requestBody?.content?.[0]?.schema ? tsResolver.resolveDataName(node) : void 0,
566
- tsResolver.resolveResponseName(node),
567
- ...pathParams.map((p) => tsResolver.resolvePathParamsName(node, p)),
568
- ...queryParams.map((p) => tsResolver.resolveQueryParamsName(node, p)),
569
- ...headerParams.map((p) => tsResolver.resolveHeaderParamsName(node, p)),
570
- ...node.responses.map((res) => tsResolver.resolveResponseStatusName(node, res.statusCode))
571
- ].filter((name) => !!name);
572
- const pluginZod = parser === "zod" ? driver.getPlugin(pluginZodName) : void 0;
573
- const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : void 0;
587
+ const importedTypeNames = resolveOperationTypeNames(node, tsResolver, {
588
+ paramsCasing,
589
+ order: "body-response-first"
590
+ });
591
+ const pluginZod = parser === "zod" ? driver.getPlugin(pluginZodName) : null;
592
+ const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : null;
574
593
  const fileZod = zodResolver ? zodResolver.resolveFile({
575
594
  name: node.operationId,
576
595
  extname: ".ts",
@@ -579,12 +598,12 @@ const mutationGenerator = defineGenerator({
579
598
  }, {
580
599
  root,
581
600
  output: pluginZod?.options?.output ?? output,
582
- group: pluginZod?.options?.group
583
- }) : void 0;
584
- const zodSchemaNames = zodResolver && parser === "zod" ? [zodResolver.resolveResponseName?.(node), node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : void 0].filter(Boolean) : [];
601
+ group: pluginZod?.options?.group ?? void 0
602
+ }) : null;
603
+ const zodSchemaNames = resolveZodSchemaNames(node, zodResolver);
585
604
  const clientPlugin = driver.getPlugin(pluginClientName);
586
605
  const shouldUseClientPlugin = clientPlugin?.name === pluginClientName && clientOptions.clientType !== "class";
587
- const clientResolver = shouldUseClientPlugin ? driver.getResolver(pluginClientName) : void 0;
606
+ const clientResolver = shouldUseClientPlugin ? driver.getResolver(pluginClientName) : null;
588
607
  const clientFile = shouldUseClientPlugin ? clientResolver?.resolveFile({
589
608
  name: node.operationId,
590
609
  extname: ".ts",
@@ -593,30 +612,38 @@ const mutationGenerator = defineGenerator({
593
612
  }, {
594
613
  root,
595
614
  output: clientPlugin?.options?.output ?? output,
596
- group: clientPlugin?.options?.group
597
- }) : void 0;
615
+ group: clientPlugin?.options?.group ?? void 0
616
+ }) : null;
598
617
  const resolvedClientName = shouldUseClientPlugin ? clientResolver?.resolveName(node.operationId) ?? clientName : clientName;
599
618
  return /* @__PURE__ */ jsxs(File, {
600
619
  baseName: meta.file.baseName,
601
620
  path: meta.file.path,
602
621
  meta: meta.file.meta,
603
- banner: resolver.resolveBanner(adapter.inputNode, {
622
+ banner: resolver.resolveBanner(ctx.meta, {
604
623
  output,
605
- config
624
+ config,
625
+ file: {
626
+ path: meta.file.path,
627
+ baseName: meta.file.baseName
628
+ }
606
629
  }),
607
- footer: resolver.resolveFooter(adapter.inputNode, {
630
+ footer: resolver.resolveFooter(ctx.meta, {
608
631
  output,
609
- config
632
+ config,
633
+ file: {
634
+ path: meta.file.path,
635
+ baseName: meta.file.baseName
636
+ }
610
637
  }),
611
638
  children: [
612
- parser === "zod" && fileZod && zodSchemaNames.length > 0 && /* @__PURE__ */ jsx(File.Import, {
639
+ fileZod && zodSchemaNames.length > 0 && /* @__PURE__ */ jsx(File.Import, {
613
640
  name: zodSchemaNames,
614
641
  root: meta.file.path,
615
642
  path: fileZod.path
616
643
  }),
617
644
  clientOptions.importPath ? /* @__PURE__ */ jsxs(Fragment, { children: [
618
645
  !shouldUseClientPlugin && /* @__PURE__ */ jsx(File.Import, {
619
- name: "fetch",
646
+ name: "client",
620
647
  path: clientOptions.importPath
621
648
  }),
622
649
  /* @__PURE__ */ jsx(File.Import, {
@@ -635,9 +662,9 @@ const mutationGenerator = defineGenerator({
635
662
  })
636
663
  ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
637
664
  !shouldUseClientPlugin && /* @__PURE__ */ jsx(File.Import, {
638
- name: ["fetch"],
665
+ name: ["client"],
639
666
  root: meta.file.path,
640
- path: path.resolve(root, ".kubb/fetch.ts")
667
+ path: path.resolve(root, ".kubb/client.ts")
641
668
  }),
642
669
  /* @__PURE__ */ jsx(File.Import, {
643
670
  name: [
@@ -646,13 +673,13 @@ const mutationGenerator = defineGenerator({
646
673
  "ResponseErrorConfig"
647
674
  ],
648
675
  root: meta.file.path,
649
- path: path.resolve(root, ".kubb/fetch.ts"),
676
+ path: path.resolve(root, ".kubb/client.ts"),
650
677
  isTypeOnly: true
651
678
  }),
652
679
  clientOptions.dataReturnType === "full" && /* @__PURE__ */ jsx(File.Import, {
653
680
  name: ["ResponseConfig"],
654
681
  root: meta.file.path,
655
- path: path.resolve(root, ".kubb/fetch.ts"),
682
+ path: path.resolve(root, ".kubb/client.ts"),
656
683
  isTypeOnly: true
657
684
  })
658
685
  ] }),
@@ -661,7 +688,7 @@ const mutationGenerator = defineGenerator({
661
688
  root: meta.file.path,
662
689
  path: clientFile.path
663
690
  }),
664
- !shouldUseClientPlugin && /* @__PURE__ */ jsx(File.Import, {
691
+ !shouldUseClientPlugin && node.requestBody?.content?.some((e) => e.contentType === "multipart/form-data") && /* @__PURE__ */ jsx(File.Import, {
665
692
  name: ["buildFormData"],
666
693
  root: meta.file.path,
667
694
  path: path.resolve(root, ".kubb/config.ts")
@@ -743,12 +770,17 @@ const mutationGenerator = defineGenerator({
743
770
  });
744
771
  //#endregion
745
772
  //#region src/generators/queryGenerator.tsx
773
+ /**
774
+ * Built-in generator for `useQuery` hooks. Emits one `useFooQuery` hook per
775
+ * GET operation (configurable via `query.methods`) plus the matching
776
+ * `fooQueryKey` / `fooQueryOptions` helpers.
777
+ */
746
778
  const queryGenerator = defineGenerator({
747
779
  name: "react-query",
748
- renderer: jsxRenderer,
780
+ renderer: jsxRendererSync,
749
781
  operation(node, ctx) {
750
- const { adapter, config, driver, resolver, root } = ctx;
751
- const { output, query, mutation, paramsCasing, paramsType, pathParamsType, parser, client: clientOptions, group, transformers, customOptions } = ctx.options;
782
+ const { config, driver, resolver, root } = ctx;
783
+ const { output, query, mutation, paramsCasing, paramsType, pathParamsType, parser, client: clientOptions, group, customOptions } = ctx.options;
752
784
  const pluginTs = driver.getPlugin(pluginTsName);
753
785
  if (!pluginTs) return null;
754
786
  const tsResolver = driver.getResolver(pluginTsName);
@@ -756,13 +788,11 @@ const queryGenerator = defineGenerator({
756
788
  const isMutation = mutation !== false && !isQuery && difference(mutation ? mutation.methods : [], query ? query.methods : []).some((method) => node.method.toLowerCase() === method.toLowerCase());
757
789
  if (!isQuery || isMutation) return null;
758
790
  const importPath = query ? query.importPath : "@tanstack/react-query";
759
- const baseName = resolver.resolveName(node.operationId);
760
- const capitalize = (s) => s.charAt(0).toUpperCase() + s.slice(1);
761
- const queryName = transformName(`use${capitalize(baseName)}`, "function", transformers);
762
- const queryOptionsName = transformName(`${baseName}QueryOptions`, "function", transformers);
763
- const queryKeyName = transformName(`${baseName}QueryKey`, "const", transformers);
764
- const queryKeyTypeName = transformName(`${capitalize(baseName)}QueryKey`, "type", transformers);
765
- const clientName = transformName(baseName, "function", transformers);
791
+ const queryName = resolver.resolveQueryName(node);
792
+ const queryOptionsName = resolver.resolveQueryOptionsName(node);
793
+ const queryKeyName = resolver.resolveQueryKeyName(node);
794
+ const queryKeyTypeName = resolver.resolveQueryKeyTypeName(node);
795
+ const clientName = resolver.resolveClientName(node);
766
796
  const meta = {
767
797
  file: resolver.resolveFile({
768
798
  name: queryName,
@@ -772,7 +802,7 @@ const queryGenerator = defineGenerator({
772
802
  }, {
773
803
  root,
774
804
  output,
775
- group
805
+ group: group ?? void 0
776
806
  }),
777
807
  fileTs: tsResolver.resolveFile({
778
808
  name: node.operationId,
@@ -782,23 +812,16 @@ const queryGenerator = defineGenerator({
782
812
  }, {
783
813
  root,
784
814
  output: pluginTs.options?.output ?? output,
785
- group: pluginTs.options?.group
815
+ group: pluginTs.options?.group ?? void 0
786
816
  })
787
817
  };
788
- const casedParams = ast.caseParams(node.parameters, paramsCasing);
789
- const pathParams = casedParams.filter((p) => p.in === "path");
790
- const queryParams = casedParams.filter((p) => p.in === "query");
791
- const headerParams = casedParams.filter((p) => p.in === "header");
792
- const importedTypeNames = [
793
- node.requestBody?.content?.[0]?.schema ? tsResolver.resolveDataName(node) : void 0,
794
- tsResolver.resolveResponseName(node),
795
- ...pathParams.map((p) => tsResolver.resolvePathParamsName(node, p)),
796
- ...queryParams.map((p) => tsResolver.resolveQueryParamsName(node, p)),
797
- ...headerParams.map((p) => tsResolver.resolveHeaderParamsName(node, p)),
798
- ...node.responses.map((res) => tsResolver.resolveResponseStatusName(node, res.statusCode))
799
- ].filter((name) => !!name && name !== queryKeyTypeName);
800
- const pluginZod = parser === "zod" ? driver.getPlugin(pluginZodName) : void 0;
801
- const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : void 0;
818
+ const importedTypeNames = resolveOperationTypeNames(node, tsResolver, {
819
+ paramsCasing,
820
+ exclude: [queryKeyTypeName],
821
+ order: "body-response-first"
822
+ });
823
+ const pluginZod = parser === "zod" ? driver.getPlugin(pluginZodName) : null;
824
+ const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : null;
802
825
  const fileZod = zodResolver ? zodResolver.resolveFile({
803
826
  name: node.operationId,
804
827
  extname: ".ts",
@@ -807,12 +830,12 @@ const queryGenerator = defineGenerator({
807
830
  }, {
808
831
  root,
809
832
  output: pluginZod?.options?.output ?? output,
810
- group: pluginZod?.options?.group
811
- }) : void 0;
812
- const zodSchemaNames = zodResolver && parser === "zod" ? [zodResolver.resolveResponseName?.(node), node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : void 0].filter(Boolean) : [];
833
+ group: pluginZod?.options?.group ?? void 0
834
+ }) : null;
835
+ const zodSchemaNames = resolveZodSchemaNames(node, zodResolver);
813
836
  const clientPlugin = driver.getPlugin(pluginClientName);
814
837
  const shouldUseClientPlugin = clientPlugin?.name === pluginClientName && clientOptions.clientType !== "class";
815
- const clientResolver = shouldUseClientPlugin ? driver.getResolver(pluginClientName) : void 0;
838
+ const clientResolver = shouldUseClientPlugin ? driver.getResolver(pluginClientName) : null;
816
839
  const clientFile = shouldUseClientPlugin ? clientResolver?.resolveFile({
817
840
  name: node.operationId,
818
841
  extname: ".ts",
@@ -821,30 +844,38 @@ const queryGenerator = defineGenerator({
821
844
  }, {
822
845
  root,
823
846
  output: clientPlugin?.options?.output ?? output,
824
- group: clientPlugin?.options?.group
825
- }) : void 0;
847
+ group: clientPlugin?.options?.group ?? void 0
848
+ }) : null;
826
849
  const resolvedClientName = shouldUseClientPlugin ? clientResolver?.resolveName(node.operationId) ?? clientName : clientName;
827
850
  return /* @__PURE__ */ jsxs(File, {
828
851
  baseName: meta.file.baseName,
829
852
  path: meta.file.path,
830
853
  meta: meta.file.meta,
831
- banner: resolver.resolveBanner(adapter.inputNode, {
854
+ banner: resolver.resolveBanner(ctx.meta, {
832
855
  output,
833
- config
856
+ config,
857
+ file: {
858
+ path: meta.file.path,
859
+ baseName: meta.file.baseName
860
+ }
834
861
  }),
835
- footer: resolver.resolveFooter(adapter.inputNode, {
862
+ footer: resolver.resolveFooter(ctx.meta, {
836
863
  output,
837
- config
864
+ config,
865
+ file: {
866
+ path: meta.file.path,
867
+ baseName: meta.file.baseName
868
+ }
838
869
  }),
839
870
  children: [
840
- parser === "zod" && fileZod && zodSchemaNames.length > 0 && /* @__PURE__ */ jsx(File.Import, {
871
+ fileZod && zodSchemaNames.length > 0 && /* @__PURE__ */ jsx(File.Import, {
841
872
  name: zodSchemaNames,
842
873
  root: meta.file.path,
843
874
  path: fileZod.path
844
875
  }),
845
876
  clientOptions.importPath ? /* @__PURE__ */ jsxs(Fragment, { children: [
846
877
  !shouldUseClientPlugin && /* @__PURE__ */ jsx(File.Import, {
847
- name: "fetch",
878
+ name: "client",
848
879
  path: clientOptions.importPath
849
880
  }),
850
881
  /* @__PURE__ */ jsx(File.Import, {
@@ -863,9 +894,9 @@ const queryGenerator = defineGenerator({
863
894
  })
864
895
  ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
865
896
  !shouldUseClientPlugin && /* @__PURE__ */ jsx(File.Import, {
866
- name: ["fetch"],
897
+ name: ["client"],
867
898
  root: meta.file.path,
868
- path: path.resolve(root, ".kubb/fetch.ts")
899
+ path: path.resolve(root, ".kubb/client.ts")
869
900
  }),
870
901
  /* @__PURE__ */ jsx(File.Import, {
871
902
  name: [
@@ -874,13 +905,13 @@ const queryGenerator = defineGenerator({
874
905
  "ResponseErrorConfig"
875
906
  ],
876
907
  root: meta.file.path,
877
- path: path.resolve(root, ".kubb/fetch.ts"),
908
+ path: path.resolve(root, ".kubb/client.ts"),
878
909
  isTypeOnly: true
879
910
  }),
880
911
  clientOptions.dataReturnType === "full" && /* @__PURE__ */ jsx(File.Import, {
881
912
  name: ["ResponseConfig"],
882
913
  root: meta.file.path,
883
- path: path.resolve(root, ".kubb/fetch.ts"),
914
+ path: path.resolve(root, ".kubb/client.ts"),
884
915
  isTypeOnly: true
885
916
  })
886
917
  ] }),
@@ -975,33 +1006,37 @@ const queryGenerator = defineGenerator({
975
1006
  });
976
1007
  //#endregion
977
1008
  //#region src/generators/suspenseInfiniteQueryGenerator.tsx
1009
+ /**
1010
+ * Built-in generator for `useSuspenseInfiniteQuery` hooks. Enabled when both
1011
+ * `suspense` and `infinite` are configured. Combines suspense semantics with
1012
+ * cursor-based pagination — handlers throw promises while loading and pull
1013
+ * additional pages on demand.
1014
+ */
978
1015
  const suspenseInfiniteQueryGenerator = defineGenerator({
979
1016
  name: "react-suspense-infinite-query",
980
- renderer: jsxRenderer,
1017
+ renderer: jsxRendererSync,
981
1018
  operation(node, ctx) {
982
- const { adapter, config, driver, resolver, root } = ctx;
983
- const { output, query, mutation, infinite, suspense, paramsCasing, paramsType, pathParamsType, parser, client: clientOptions, group, transformers, customOptions } = ctx.options;
1019
+ const { config, driver, resolver, root } = ctx;
1020
+ const { output, query, mutation, infinite, suspense, paramsCasing, paramsType, pathParamsType, parser, client: clientOptions, group, customOptions } = ctx.options;
984
1021
  const pluginTs = driver.getPlugin(pluginTsName);
985
1022
  if (!pluginTs) return null;
986
1023
  const tsResolver = driver.getResolver(pluginTsName);
987
1024
  const isQuery = query === false || !!query && query.methods.some((method) => node.method.toLowerCase() === method.toLowerCase());
988
1025
  const isMutation = mutation !== false && !isQuery && difference(mutation ? mutation.methods : [], query ? query.methods : []).some((method) => node.method.toLowerCase() === method.toLowerCase());
989
1026
  const isSuspense = !!suspense;
990
- const infiniteOptions = infinite && typeof infinite === "object" ? infinite : void 0;
1027
+ const infiniteOptions = infinite && typeof infinite === "object" ? infinite : null;
991
1028
  if (!isQuery || isMutation || !isSuspense || !infiniteOptions) return null;
992
1029
  const normalizeKey = (key) => key.replace(/\?$/, "");
993
- const queryParamKeys = node.parameters.filter((p) => p.in === "query").map((p) => p.name);
1030
+ const queryParamKeys = getOperationParameters(node).query.map((p) => p.name);
994
1031
  const hasQueryParam = infiniteOptions.queryParam ? queryParamKeys.some((k) => normalizeKey(k) === infiniteOptions.queryParam) : false;
995
1032
  const hasCursorParam = !infiniteOptions.cursorParam || true;
996
1033
  if (!hasQueryParam || !hasCursorParam) return null;
997
1034
  const importPath = query ? query.importPath : "@tanstack/react-query";
998
- const baseName = resolver.resolveName(node.operationId);
999
- const capitalize = (s) => s.charAt(0).toUpperCase() + s.slice(1);
1000
- const queryName = transformName(`use${capitalize(baseName)}SuspenseInfinite`, "function", transformers);
1001
- const queryOptionsName = transformName(`${baseName}SuspenseInfiniteQueryOptions`, "function", transformers);
1002
- const queryKeyName = transformName(`${baseName}SuspenseInfiniteQueryKey`, "const", transformers);
1003
- const queryKeyTypeName = transformName(`${capitalize(baseName)}SuspenseInfiniteQueryKey`, "type", transformers);
1004
- const clientBaseName = transformName(`${baseName}SuspenseInfinite`, "function", transformers);
1035
+ const queryName = resolver.resolveSuspenseInfiniteQueryName(node);
1036
+ const queryOptionsName = resolver.resolveSuspenseInfiniteQueryOptionsName(node);
1037
+ const queryKeyName = resolver.resolveSuspenseInfiniteQueryKeyName(node);
1038
+ const queryKeyTypeName = resolver.resolveSuspenseInfiniteQueryKeyTypeName(node);
1039
+ const clientBaseName = resolver.resolveSuspenseInfiniteClientName(node);
1005
1040
  const meta = {
1006
1041
  file: resolver.resolveFile({
1007
1042
  name: queryName,
@@ -1011,7 +1046,7 @@ const suspenseInfiniteQueryGenerator = defineGenerator({
1011
1046
  }, {
1012
1047
  root,
1013
1048
  output,
1014
- group
1049
+ group: group ?? void 0
1015
1050
  }),
1016
1051
  fileTs: tsResolver.resolveFile({
1017
1052
  name: node.operationId,
@@ -1021,23 +1056,15 @@ const suspenseInfiniteQueryGenerator = defineGenerator({
1021
1056
  }, {
1022
1057
  root,
1023
1058
  output: pluginTs.options?.output ?? output,
1024
- group: pluginTs.options?.group
1059
+ group: pluginTs.options?.group ?? void 0
1025
1060
  })
1026
1061
  };
1027
- const casedParams = ast.caseParams(node.parameters, paramsCasing);
1028
- const pathParams = casedParams.filter((p) => p.in === "path");
1029
- const queryParams = casedParams.filter((p) => p.in === "query");
1030
- const headerParams = casedParams.filter((p) => p.in === "header");
1031
- const importedTypeNames = [
1032
- node.requestBody?.content?.[0]?.schema ? tsResolver.resolveDataName(node) : void 0,
1033
- tsResolver.resolveResponseName(node),
1034
- ...pathParams.map((p) => tsResolver.resolvePathParamsName(node, p)),
1035
- ...queryParams.map((p) => tsResolver.resolveQueryParamsName(node, p)),
1036
- ...headerParams.map((p) => tsResolver.resolveHeaderParamsName(node, p)),
1037
- ...node.responses.map((res) => tsResolver.resolveResponseStatusName(node, res.statusCode))
1038
- ].filter(Boolean);
1039
- const pluginZod = parser === "zod" ? driver.getPlugin(pluginZodName) : void 0;
1040
- const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : void 0;
1062
+ const importedTypeNames = resolveOperationTypeNames(node, tsResolver, {
1063
+ paramsCasing,
1064
+ order: "body-response-first"
1065
+ });
1066
+ const pluginZod = parser === "zod" ? driver.getPlugin(pluginZodName) : null;
1067
+ const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : null;
1041
1068
  const fileZod = zodResolver ? zodResolver.resolveFile({
1042
1069
  name: node.operationId,
1043
1070
  extname: ".ts",
@@ -1046,12 +1073,12 @@ const suspenseInfiniteQueryGenerator = defineGenerator({
1046
1073
  }, {
1047
1074
  root,
1048
1075
  output: pluginZod?.options?.output ?? output,
1049
- group: pluginZod?.options?.group
1050
- }) : void 0;
1051
- const zodSchemaNames = zodResolver && parser === "zod" ? [zodResolver.resolveResponseName?.(node), node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : void 0].filter(Boolean) : [];
1076
+ group: pluginZod?.options?.group ?? void 0
1077
+ }) : null;
1078
+ const zodSchemaNames = resolveZodSchemaNames(node, zodResolver);
1052
1079
  const clientPlugin = driver.getPlugin(pluginClientName);
1053
1080
  const shouldUseClientPlugin = clientPlugin?.name === pluginClientName && clientOptions.clientType !== "class";
1054
- const clientResolver = shouldUseClientPlugin ? driver.getResolver(pluginClientName) : void 0;
1081
+ const clientResolver = shouldUseClientPlugin ? driver.getResolver(pluginClientName) : null;
1055
1082
  const clientFile = shouldUseClientPlugin ? clientResolver?.resolveFile({
1056
1083
  name: node.operationId,
1057
1084
  extname: ".ts",
@@ -1060,30 +1087,38 @@ const suspenseInfiniteQueryGenerator = defineGenerator({
1060
1087
  }, {
1061
1088
  root,
1062
1089
  output: clientPlugin?.options?.output ?? output,
1063
- group: clientPlugin?.options?.group
1064
- }) : void 0;
1090
+ group: clientPlugin?.options?.group ?? void 0
1091
+ }) : null;
1065
1092
  const resolvedClientName = shouldUseClientPlugin ? clientResolver?.resolveName(node.operationId) ?? clientBaseName : clientBaseName;
1066
1093
  return /* @__PURE__ */ jsxs(File, {
1067
1094
  baseName: meta.file.baseName,
1068
1095
  path: meta.file.path,
1069
1096
  meta: meta.file.meta,
1070
- banner: resolver.resolveBanner(adapter.inputNode, {
1097
+ banner: resolver.resolveBanner(ctx.meta, {
1071
1098
  output,
1072
- config
1099
+ config,
1100
+ file: {
1101
+ path: meta.file.path,
1102
+ baseName: meta.file.baseName
1103
+ }
1073
1104
  }),
1074
- footer: resolver.resolveFooter(adapter.inputNode, {
1105
+ footer: resolver.resolveFooter(ctx.meta, {
1075
1106
  output,
1076
- config
1107
+ config,
1108
+ file: {
1109
+ path: meta.file.path,
1110
+ baseName: meta.file.baseName
1111
+ }
1077
1112
  }),
1078
1113
  children: [
1079
- parser === "zod" && fileZod && zodSchemaNames.length > 0 && /* @__PURE__ */ jsx(File.Import, {
1114
+ fileZod && zodSchemaNames.length > 0 && /* @__PURE__ */ jsx(File.Import, {
1080
1115
  name: zodSchemaNames,
1081
1116
  root: meta.file.path,
1082
1117
  path: fileZod.path
1083
1118
  }),
1084
1119
  clientOptions.importPath ? /* @__PURE__ */ jsxs(Fragment, { children: [
1085
1120
  !shouldUseClientPlugin && /* @__PURE__ */ jsx(File.Import, {
1086
- name: "fetch",
1121
+ name: "client",
1087
1122
  path: clientOptions.importPath
1088
1123
  }),
1089
1124
  /* @__PURE__ */ jsx(File.Import, {
@@ -1102,9 +1137,9 @@ const suspenseInfiniteQueryGenerator = defineGenerator({
1102
1137
  })
1103
1138
  ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
1104
1139
  !shouldUseClientPlugin && /* @__PURE__ */ jsx(File.Import, {
1105
- name: ["fetch"],
1140
+ name: ["client"],
1106
1141
  root: meta.file.path,
1107
- path: path.resolve(root, ".kubb/fetch.ts")
1142
+ path: path.resolve(root, ".kubb/client.ts")
1108
1143
  }),
1109
1144
  /* @__PURE__ */ jsx(File.Import, {
1110
1145
  name: [
@@ -1113,13 +1148,13 @@ const suspenseInfiniteQueryGenerator = defineGenerator({
1113
1148
  "ResponseErrorConfig"
1114
1149
  ],
1115
1150
  root: meta.file.path,
1116
- path: path.resolve(root, ".kubb/fetch.ts"),
1151
+ path: path.resolve(root, ".kubb/client.ts"),
1117
1152
  isTypeOnly: true
1118
1153
  }),
1119
1154
  clientOptions.dataReturnType === "full" && /* @__PURE__ */ jsx(File.Import, {
1120
1155
  name: ["ResponseConfig"],
1121
1156
  root: meta.file.path,
1122
- path: path.resolve(root, ".kubb/fetch.ts"),
1157
+ path: path.resolve(root, ".kubb/client.ts"),
1123
1158
  isTypeOnly: true
1124
1159
  })
1125
1160
  ] }),
@@ -1224,12 +1259,18 @@ const suspenseInfiniteQueryGenerator = defineGenerator({
1224
1259
  });
1225
1260
  //#endregion
1226
1261
  //#region src/generators/suspenseQueryGenerator.tsx
1262
+ /**
1263
+ * Built-in generator for `useSuspenseQuery` hooks. Enabled when
1264
+ * `pluginReactQuery({ suspense: {} })`. Emits one `useFooSuspenseQuery` hook
1265
+ * per query operation. Suspense queries throw promises while loading and
1266
+ * require a `<Suspense>` boundary in the React tree. TanStack Query v5+ only.
1267
+ */
1227
1268
  const suspenseQueryGenerator = defineGenerator({
1228
1269
  name: "react-suspense-query",
1229
- renderer: jsxRenderer,
1270
+ renderer: jsxRendererSync,
1230
1271
  operation(node, ctx) {
1231
- const { adapter, config, driver, resolver, root } = ctx;
1232
- const { output, query, mutation, suspense, paramsCasing, paramsType, pathParamsType, parser, client: clientOptions, group, transformers, customOptions } = ctx.options;
1272
+ const { config, driver, resolver, root } = ctx;
1273
+ const { output, query, mutation, suspense, paramsCasing, paramsType, pathParamsType, parser, client: clientOptions, group, customOptions } = ctx.options;
1233
1274
  const pluginTs = driver.getPlugin(pluginTsName);
1234
1275
  if (!pluginTs) return null;
1235
1276
  const tsResolver = driver.getResolver(pluginTsName);
@@ -1237,13 +1278,11 @@ const suspenseQueryGenerator = defineGenerator({
1237
1278
  const isMutation = mutation !== false && !isQuery && difference(mutation ? mutation.methods : [], query ? query.methods : []).some((method) => node.method.toLowerCase() === method.toLowerCase());
1238
1279
  if (!isQuery || isMutation || !!!suspense) return null;
1239
1280
  const importPath = query ? query.importPath : "@tanstack/react-query";
1240
- const baseName = resolver.resolveName(node.operationId);
1241
- const capitalize = (s) => s.charAt(0).toUpperCase() + s.slice(1);
1242
- const queryName = transformName(`use${capitalize(baseName)}Suspense`, "function", transformers);
1243
- const queryOptionsName = transformName(`${baseName}SuspenseQueryOptions`, "function", transformers);
1244
- const queryKeyName = transformName(`${baseName}SuspenseQueryKey`, "const", transformers);
1245
- const queryKeyTypeName = transformName(`${capitalize(baseName)}SuspenseQueryKey`, "type", transformers);
1246
- const clientName = transformName(`${baseName}Suspense`, "function", transformers);
1281
+ const queryName = resolver.resolveSuspenseQueryName(node);
1282
+ const queryOptionsName = resolver.resolveSuspenseQueryOptionsName(node);
1283
+ const queryKeyName = resolver.resolveSuspenseQueryKeyName(node);
1284
+ const queryKeyTypeName = resolver.resolveSuspenseQueryKeyTypeName(node);
1285
+ const clientName = resolver.resolveSuspenseClientName(node);
1247
1286
  const meta = {
1248
1287
  file: resolver.resolveFile({
1249
1288
  name: queryName,
@@ -1253,7 +1292,7 @@ const suspenseQueryGenerator = defineGenerator({
1253
1292
  }, {
1254
1293
  root,
1255
1294
  output,
1256
- group
1295
+ group: group ?? void 0
1257
1296
  }),
1258
1297
  fileTs: tsResolver.resolveFile({
1259
1298
  name: node.operationId,
@@ -1263,23 +1302,16 @@ const suspenseQueryGenerator = defineGenerator({
1263
1302
  }, {
1264
1303
  root,
1265
1304
  output: pluginTs.options?.output ?? output,
1266
- group: pluginTs.options?.group
1305
+ group: pluginTs.options?.group ?? void 0
1267
1306
  })
1268
1307
  };
1269
- const casedParams = ast.caseParams(node.parameters, paramsCasing);
1270
- const pathParams = casedParams.filter((p) => p.in === "path");
1271
- const queryParams = casedParams.filter((p) => p.in === "query");
1272
- const headerParams = casedParams.filter((p) => p.in === "header");
1273
- const importedTypeNames = [
1274
- node.requestBody?.content?.[0]?.schema ? tsResolver.resolveDataName(node) : void 0,
1275
- tsResolver.resolveResponseName(node),
1276
- ...pathParams.map((p) => tsResolver.resolvePathParamsName(node, p)),
1277
- ...queryParams.map((p) => tsResolver.resolveQueryParamsName(node, p)),
1278
- ...headerParams.map((p) => tsResolver.resolveHeaderParamsName(node, p)),
1279
- ...node.responses.map((res) => tsResolver.resolveResponseStatusName(node, res.statusCode))
1280
- ].filter((name) => !!name && name !== queryKeyTypeName);
1281
- const pluginZod = parser === "zod" ? driver.getPlugin(pluginZodName) : void 0;
1282
- const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : void 0;
1308
+ const importedTypeNames = resolveOperationTypeNames(node, tsResolver, {
1309
+ paramsCasing,
1310
+ exclude: [queryKeyTypeName],
1311
+ order: "body-response-first"
1312
+ });
1313
+ const pluginZod = parser === "zod" ? driver.getPlugin(pluginZodName) : null;
1314
+ const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : null;
1283
1315
  const fileZod = zodResolver ? zodResolver.resolveFile({
1284
1316
  name: node.operationId,
1285
1317
  extname: ".ts",
@@ -1288,12 +1320,12 @@ const suspenseQueryGenerator = defineGenerator({
1288
1320
  }, {
1289
1321
  root,
1290
1322
  output: pluginZod?.options?.output ?? output,
1291
- group: pluginZod?.options?.group
1292
- }) : void 0;
1293
- const zodSchemaNames = zodResolver && parser === "zod" ? [zodResolver.resolveResponseName?.(node), node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName?.(node) : void 0].filter(Boolean) : [];
1323
+ group: pluginZod?.options?.group ?? void 0
1324
+ }) : null;
1325
+ const zodSchemaNames = resolveZodSchemaNames(node, zodResolver);
1294
1326
  const clientPlugin = driver.getPlugin(pluginClientName);
1295
1327
  const shouldUseClientPlugin = clientPlugin?.name === pluginClientName && clientOptions.clientType !== "class";
1296
- const clientResolver = shouldUseClientPlugin ? driver.getResolver(pluginClientName) : void 0;
1328
+ const clientResolver = shouldUseClientPlugin ? driver.getResolver(pluginClientName) : null;
1297
1329
  const clientFile = shouldUseClientPlugin ? clientResolver?.resolveFile({
1298
1330
  name: node.operationId,
1299
1331
  extname: ".ts",
@@ -1302,30 +1334,38 @@ const suspenseQueryGenerator = defineGenerator({
1302
1334
  }, {
1303
1335
  root,
1304
1336
  output: clientPlugin?.options?.output ?? output,
1305
- group: clientPlugin?.options?.group
1306
- }) : void 0;
1337
+ group: clientPlugin?.options?.group ?? void 0
1338
+ }) : null;
1307
1339
  const resolvedClientName = shouldUseClientPlugin ? clientResolver?.resolveName(node.operationId) ?? clientName : clientName;
1308
1340
  return /* @__PURE__ */ jsxs(File, {
1309
1341
  baseName: meta.file.baseName,
1310
1342
  path: meta.file.path,
1311
1343
  meta: meta.file.meta,
1312
- banner: resolver.resolveBanner(adapter.inputNode, {
1344
+ banner: resolver.resolveBanner(ctx.meta, {
1313
1345
  output,
1314
- config
1346
+ config,
1347
+ file: {
1348
+ path: meta.file.path,
1349
+ baseName: meta.file.baseName
1350
+ }
1315
1351
  }),
1316
- footer: resolver.resolveFooter(adapter.inputNode, {
1352
+ footer: resolver.resolveFooter(ctx.meta, {
1317
1353
  output,
1318
- config
1354
+ config,
1355
+ file: {
1356
+ path: meta.file.path,
1357
+ baseName: meta.file.baseName
1358
+ }
1319
1359
  }),
1320
1360
  children: [
1321
- parser === "zod" && fileZod && zodSchemaNames.length > 0 && /* @__PURE__ */ jsx(File.Import, {
1361
+ fileZod && zodSchemaNames.length > 0 && /* @__PURE__ */ jsx(File.Import, {
1322
1362
  name: zodSchemaNames,
1323
1363
  root: meta.file.path,
1324
1364
  path: fileZod.path
1325
1365
  }),
1326
1366
  clientOptions.importPath ? /* @__PURE__ */ jsxs(Fragment, { children: [
1327
1367
  !shouldUseClientPlugin && /* @__PURE__ */ jsx(File.Import, {
1328
- name: "fetch",
1368
+ name: "client",
1329
1369
  path: clientOptions.importPath
1330
1370
  }),
1331
1371
  /* @__PURE__ */ jsx(File.Import, {
@@ -1344,9 +1384,9 @@ const suspenseQueryGenerator = defineGenerator({
1344
1384
  })
1345
1385
  ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
1346
1386
  !shouldUseClientPlugin && /* @__PURE__ */ jsx(File.Import, {
1347
- name: ["fetch"],
1387
+ name: ["client"],
1348
1388
  root: meta.file.path,
1349
- path: path.resolve(root, ".kubb/fetch.ts")
1389
+ path: path.resolve(root, ".kubb/client.ts")
1350
1390
  }),
1351
1391
  /* @__PURE__ */ jsx(File.Import, {
1352
1392
  name: [
@@ -1355,13 +1395,13 @@ const suspenseQueryGenerator = defineGenerator({
1355
1395
  "ResponseErrorConfig"
1356
1396
  ],
1357
1397
  root: meta.file.path,
1358
- path: path.resolve(root, ".kubb/fetch.ts"),
1398
+ path: path.resolve(root, ".kubb/client.ts"),
1359
1399
  isTypeOnly: true
1360
1400
  }),
1361
1401
  clientOptions.dataReturnType === "full" && /* @__PURE__ */ jsx(File.Import, {
1362
1402
  name: ["ResponseConfig"],
1363
1403
  root: meta.file.path,
1364
- path: path.resolve(root, ".kubb/fetch.ts"),
1404
+ path: path.resolve(root, ".kubb/client.ts"),
1365
1405
  isTypeOnly: true
1366
1406
  })
1367
1407
  ] }),
@@ -1457,4 +1497,4 @@ const suspenseQueryGenerator = defineGenerator({
1457
1497
  //#endregion
1458
1498
  export { infiniteQueryGenerator as a, mutationGenerator as i, suspenseInfiniteQueryGenerator as n, hookOptionsGenerator as o, queryGenerator as r, customHookOptionsFileGenerator as s, suspenseQueryGenerator as t };
1459
1499
 
1460
- //# sourceMappingURL=generators-C_fbcjpG.js.map
1500
+ //# sourceMappingURL=generators-Bma51Uar.js.map