@kubb/plugin-react-query 5.10.0-canary.20261109T201601 → 5.10.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.cjs +607 -570
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -9
- package/dist/index.d.ts +9 -9
- package/dist/index.js +606 -569
- package/dist/index.js.map +1 -1
- package/docs/guides/calling-operations.md +9 -7
- package/docs/options.md +38 -20
- package/docs/overview.md +5 -3
- package/kubb-extension.json +9 -6
- package/package.json +10 -9
package/dist/index.cjs
CHANGED
|
@@ -26,12 +26,295 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
26
26
|
let _kubb_kit = require("@kubb/kit");
|
|
27
27
|
let node_path = require("node:path");
|
|
28
28
|
node_path = __toESM(node_path, 1);
|
|
29
|
-
let _kubb_plugin_zod = require("@kubb/plugin-zod");
|
|
30
|
-
let _kubb_renderer_jsx = require("@kubb/renderer-jsx");
|
|
31
29
|
let _kubb_plugin_ts = require("@kubb/plugin-ts");
|
|
30
|
+
let _kubb_renderer_jsx = require("@kubb/renderer-jsx");
|
|
32
31
|
let _kubb_renderer_jsx_jsx_runtime = require("@kubb/renderer-jsx/jsx-runtime");
|
|
33
32
|
let node_fs = require("node:fs");
|
|
34
33
|
node_fs = __toESM(node_fs, 1);
|
|
34
|
+
// kubb-extension.json
|
|
35
|
+
var compatibility = {
|
|
36
|
+
"kubb": ">=5.18.4",
|
|
37
|
+
"node": ">=22.22"
|
|
38
|
+
};
|
|
39
|
+
// package.json
|
|
40
|
+
var version = "5.10.1";
|
|
41
|
+
// ../../internals/client/src/resolveClient.ts
|
|
42
|
+
/**
|
|
43
|
+
* Resolves which client plugin a consumer (react-query, vue-query, swr, mcp) should call for an
|
|
44
|
+
* operation, shared so the selection rules and diagnostics stay in one place.
|
|
45
|
+
*
|
|
46
|
+
* Every client runtime lives in a dedicated client plugin, so a consumer always calls a registered
|
|
47
|
+
* contract client plugin (plugin-fetch, plugin-axios, or plugin-client) and never emits its own
|
|
48
|
+
* inline client:
|
|
49
|
+
*
|
|
50
|
+
* - `contract` — a registered contract client plugin owns the `<op>` functions and the consumer
|
|
51
|
+
* imports and calls them.
|
|
52
|
+
* - `error` — no client plugin is registered, several are registered without a selector, the
|
|
53
|
+
* requested one is missing, or `client` is not a known selector.
|
|
54
|
+
*
|
|
55
|
+
* The `client` string selects explicitly (`'fetch'` / `'axios'` / `'client'`); when it is unset a
|
|
56
|
+
* lone registered contract client plugin is picked up automatically.
|
|
57
|
+
*/
|
|
58
|
+
const pluginFetchName = "plugin-fetch";
|
|
59
|
+
const pluginAxiosName = "plugin-axios";
|
|
60
|
+
const pluginClientName = "plugin-client";
|
|
61
|
+
const selectorToPlugin = {
|
|
62
|
+
fetch: pluginFetchName,
|
|
63
|
+
axios: pluginAxiosName,
|
|
64
|
+
client: pluginClientName
|
|
65
|
+
};
|
|
66
|
+
const contractPlugins = [
|
|
67
|
+
pluginFetchName,
|
|
68
|
+
pluginAxiosName,
|
|
69
|
+
pluginClientName
|
|
70
|
+
];
|
|
71
|
+
/**
|
|
72
|
+
* Applies the `client` resolution rules. See the module comment for the strategy shape.
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```ts
|
|
76
|
+
* resolveClient({ client: 'fetch', pluginNames: ['plugin-ts', 'plugin-fetch'] })
|
|
77
|
+
* // { kind: 'contract', pluginName: 'plugin-fetch' }
|
|
78
|
+
* ```
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```ts
|
|
82
|
+
* resolveClient({ client: undefined, pluginNames: ['plugin-ts'] })
|
|
83
|
+
* // { kind: 'error', code: 'KUBB_MISSING_DEPENDENCY', message: 'No client plugin is registered.', help: 'Add …' }
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
function resolveClient(options) {
|
|
87
|
+
const { client, pluginNames } = options;
|
|
88
|
+
const has = (name) => pluginNames.includes(name);
|
|
89
|
+
if (client === "fetch" || client === "axios" || client === "client") {
|
|
90
|
+
const pluginName = selectorToPlugin[client];
|
|
91
|
+
if (!has(pluginName)) return {
|
|
92
|
+
kind: "error",
|
|
93
|
+
code: _kubb_kit.Diagnostics.code.missingDependency,
|
|
94
|
+
message: `\`client: '${client}'\` is set but \`@kubb/plugin-${client}\` is not registered in \`plugins\`.`,
|
|
95
|
+
help: `Add \`@kubb/plugin-${client}\` to \`plugins\`, or drop \`client\` to use a different client plugin.`
|
|
96
|
+
};
|
|
97
|
+
return {
|
|
98
|
+
kind: "contract",
|
|
99
|
+
pluginName
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
if (client !== void 0) return {
|
|
103
|
+
kind: "error",
|
|
104
|
+
code: _kubb_kit.Diagnostics.code.invalidPluginOptions,
|
|
105
|
+
message: `Option \`client\` is ${typeof client === "string" ? `'${client}'` : String(client)}, but it must be one of 'fetch', 'axios', 'client'.`,
|
|
106
|
+
help: "Set `client` to one of those values, or drop it to use the registered client plugin."
|
|
107
|
+
};
|
|
108
|
+
const registered = contractPlugins.filter(has);
|
|
109
|
+
if (registered.length === 1) return {
|
|
110
|
+
kind: "contract",
|
|
111
|
+
pluginName: registered[0]
|
|
112
|
+
};
|
|
113
|
+
if (registered.length > 1) return {
|
|
114
|
+
kind: "error",
|
|
115
|
+
code: _kubb_kit.Diagnostics.code.invalidPluginOptions,
|
|
116
|
+
message: `Multiple client plugins are registered (${registered.map((name) => `\`@kubb/${name}\``).join(", ")}) and \`client\` is not set.`,
|
|
117
|
+
help: "Set `client: 'fetch' | 'axios' | 'client'` to choose which client the hooks call, or register a single client plugin."
|
|
118
|
+
};
|
|
119
|
+
return {
|
|
120
|
+
kind: "error",
|
|
121
|
+
code: _kubb_kit.Diagnostics.code.missingDependency,
|
|
122
|
+
message: "No client plugin is registered.",
|
|
123
|
+
help: "Add `@kubb/plugin-fetch`, `@kubb/plugin-axios`, or `@kubb/plugin-client` to `plugins` so the generated code has an HTTP client to call."
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Resolves the contract client during a consumer plugin's setup hook.
|
|
128
|
+
* It extracts the plugin names from the raw `plugins` config and applies {@link resolveClient}.
|
|
129
|
+
* On a misconfiguration it throws a config diagnostic tagged with `plugin`, so every consumer
|
|
130
|
+
* fails fast with the same message.
|
|
131
|
+
*/
|
|
132
|
+
function resolveContractClient(options) {
|
|
133
|
+
const { plugin, client, plugins = [] } = options;
|
|
134
|
+
const resolved = resolveClient({
|
|
135
|
+
client,
|
|
136
|
+
pluginNames: plugins.map((plugin) => plugin.name).filter((name) => Boolean(name))
|
|
137
|
+
});
|
|
138
|
+
if (resolved.kind === "error") {
|
|
139
|
+
const { code, message, help } = resolved;
|
|
140
|
+
throw new _kubb_kit.Diagnostics.Error({
|
|
141
|
+
code,
|
|
142
|
+
severity: "error",
|
|
143
|
+
message,
|
|
144
|
+
help,
|
|
145
|
+
location: { kind: "config" },
|
|
146
|
+
plugin
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
return resolved;
|
|
150
|
+
}
|
|
151
|
+
// ../../internals/utils/src/reserved.ts
|
|
152
|
+
/**
|
|
153
|
+
* JavaScript and Java reserved words.
|
|
154
|
+
* @link https://github.com/jonschlinkert/reserved/blob/master/index.js
|
|
155
|
+
*/
|
|
156
|
+
const reservedWords = /* @__PURE__ */ new Set([
|
|
157
|
+
"abstract",
|
|
158
|
+
"arguments",
|
|
159
|
+
"await",
|
|
160
|
+
"boolean",
|
|
161
|
+
"break",
|
|
162
|
+
"byte",
|
|
163
|
+
"case",
|
|
164
|
+
"catch",
|
|
165
|
+
"char",
|
|
166
|
+
"class",
|
|
167
|
+
"const",
|
|
168
|
+
"continue",
|
|
169
|
+
"debugger",
|
|
170
|
+
"default",
|
|
171
|
+
"delete",
|
|
172
|
+
"do",
|
|
173
|
+
"double",
|
|
174
|
+
"else",
|
|
175
|
+
"enum",
|
|
176
|
+
"eval",
|
|
177
|
+
"export",
|
|
178
|
+
"extends",
|
|
179
|
+
"false",
|
|
180
|
+
"final",
|
|
181
|
+
"finally",
|
|
182
|
+
"float",
|
|
183
|
+
"for",
|
|
184
|
+
"function",
|
|
185
|
+
"goto",
|
|
186
|
+
"if",
|
|
187
|
+
"implements",
|
|
188
|
+
"import",
|
|
189
|
+
"in",
|
|
190
|
+
"instanceof",
|
|
191
|
+
"int",
|
|
192
|
+
"interface",
|
|
193
|
+
"let",
|
|
194
|
+
"long",
|
|
195
|
+
"native",
|
|
196
|
+
"new",
|
|
197
|
+
"null",
|
|
198
|
+
"package",
|
|
199
|
+
"private",
|
|
200
|
+
"protected",
|
|
201
|
+
"public",
|
|
202
|
+
"return",
|
|
203
|
+
"short",
|
|
204
|
+
"static",
|
|
205
|
+
"super",
|
|
206
|
+
"switch",
|
|
207
|
+
"synchronized",
|
|
208
|
+
"this",
|
|
209
|
+
"throw",
|
|
210
|
+
"throws",
|
|
211
|
+
"transient",
|
|
212
|
+
"true",
|
|
213
|
+
"try",
|
|
214
|
+
"typeof",
|
|
215
|
+
"var",
|
|
216
|
+
"void",
|
|
217
|
+
"volatile",
|
|
218
|
+
"while",
|
|
219
|
+
"with",
|
|
220
|
+
"yield",
|
|
221
|
+
"Array",
|
|
222
|
+
"Date",
|
|
223
|
+
"hasOwnProperty",
|
|
224
|
+
"Infinity",
|
|
225
|
+
"isFinite",
|
|
226
|
+
"isNaN",
|
|
227
|
+
"isPrototypeOf",
|
|
228
|
+
"length",
|
|
229
|
+
"Math",
|
|
230
|
+
"name",
|
|
231
|
+
"NaN",
|
|
232
|
+
"Number",
|
|
233
|
+
"Object",
|
|
234
|
+
"prototype",
|
|
235
|
+
"String",
|
|
236
|
+
"toString",
|
|
237
|
+
"undefined",
|
|
238
|
+
"valueOf"
|
|
239
|
+
]);
|
|
240
|
+
/**
|
|
241
|
+
* Returns `true` when `name` is a syntactically valid JavaScript variable name.
|
|
242
|
+
*
|
|
243
|
+
* @example
|
|
244
|
+
* ```ts
|
|
245
|
+
* isValidVarName('status') // true
|
|
246
|
+
* isValidVarName('class') // false (reserved word)
|
|
247
|
+
* isValidVarName('42foo') // false (starts with digit)
|
|
248
|
+
* ```
|
|
249
|
+
*/
|
|
250
|
+
function isValidVarName(name) {
|
|
251
|
+
if (!name || reservedWords.has(name)) return false;
|
|
252
|
+
return isIdentifier(name);
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Returns `name` when it's a syntactically valid JavaScript variable name,
|
|
256
|
+
* otherwise prefixes it with `_` so the result is a valid identifier.
|
|
257
|
+
*
|
|
258
|
+
* Useful for sanitizing OpenAPI schema names or operation IDs that start with
|
|
259
|
+
* a digit (e.g. `409`, `504AccountCancel`) before using them as exported
|
|
260
|
+
* variable, type, or function names.
|
|
261
|
+
*
|
|
262
|
+
* @example
|
|
263
|
+
* ```ts
|
|
264
|
+
* ensureValidVarName('409') // '_409'
|
|
265
|
+
* ensureValidVarName('504AccountCancel') // '_504AccountCancel'
|
|
266
|
+
* ensureValidVarName('Pet') // 'Pet'
|
|
267
|
+
* ensureValidVarName('class') // '_class'
|
|
268
|
+
* ```
|
|
269
|
+
*/
|
|
270
|
+
function ensureValidVarName(name) {
|
|
271
|
+
if (!name || isValidVarName(name)) return name;
|
|
272
|
+
return `_${name}`;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Returns `true` when `name` is syntactically a valid identifier, ignoring reserved words.
|
|
276
|
+
*
|
|
277
|
+
* Reserved words and globals (`class`, `name`, `Date`, …) are valid as bare object-literal keys
|
|
278
|
+
* even though they are not valid variable names, so use this (not {@link isValidVarName}) when
|
|
279
|
+
* deciding whether an object key needs quoting.
|
|
280
|
+
*
|
|
281
|
+
* @example
|
|
282
|
+
* ```ts
|
|
283
|
+
* isIdentifier('name') // true
|
|
284
|
+
* isIdentifier('x-total')// false
|
|
285
|
+
* ```
|
|
286
|
+
*/
|
|
287
|
+
function isIdentifier(name) {
|
|
288
|
+
return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
|
|
289
|
+
}
|
|
290
|
+
// ../../internals/utils/src/strings.ts
|
|
291
|
+
/**
|
|
292
|
+
* Renders a dotted path or string array as an optional-chaining accessor expression rooted at
|
|
293
|
+
* `accessor`. Returns `null` for an empty path.
|
|
294
|
+
*
|
|
295
|
+
* @example
|
|
296
|
+
* ```ts
|
|
297
|
+
* getNestedAccessor('pagination.next.id', 'lastPage')
|
|
298
|
+
* // "lastPage?.['pagination']?.['next']?.['id']"
|
|
299
|
+
* ```
|
|
300
|
+
*/
|
|
301
|
+
function getNestedAccessor(param, accessor) {
|
|
302
|
+
const parts = Array.isArray(param) ? param : param.split(".");
|
|
303
|
+
if (parts.length === 0 || parts.length === 1 && parts[0] === "") return null;
|
|
304
|
+
return `${accessor}?.['${`${parts.join("']?.['")}']`}`;
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Escapes an `@` at the start of a line, so a multi-line description can't start a new JSDoc tag.
|
|
308
|
+
* Editors render `\@` as `@` in hovers.
|
|
309
|
+
*
|
|
310
|
+
* @example
|
|
311
|
+
* ```ts
|
|
312
|
+
* jsDocEscape('intro\n@example value') // 'intro\n\\@example value'
|
|
313
|
+
* ```
|
|
314
|
+
*/
|
|
315
|
+
function jsDocEscape(input) {
|
|
316
|
+
return `${input}`.replace(/^(\s*)@/gm, "$1\\@");
|
|
317
|
+
}
|
|
35
318
|
// ../../internals/shared/src/operation.ts
|
|
36
319
|
/**
|
|
37
320
|
* Builds the `ResolverFileParams` every operation generator passes to
|
|
@@ -53,29 +336,55 @@ function operationFileEntry(node, name, extname = ".ts") {
|
|
|
53
336
|
};
|
|
54
337
|
}
|
|
55
338
|
/**
|
|
56
|
-
* Resolves a
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
339
|
+
* Resolves the file a schema-emitting plugin (`plugin-ts`, `plugin-zod`, `plugin-faker`) writes
|
|
340
|
+
* `node` to, cached in `ctx.memo` under the resolver's plugin name and the
|
|
341
|
+
* operation. The plugin itself and every plugin that imports from it call this, so they all get
|
|
342
|
+
* the same path.
|
|
60
343
|
*
|
|
61
|
-
*
|
|
344
|
+
* When that path matches the file of a component schema in `ctx.driver.inputNode`, ignoring case, the file name
|
|
345
|
+
* gets an `Operation` suffix: operation `point` goes to `PointOperation.ts` next to schema `Point.ts`.
|
|
346
|
+
* Otherwise the two merge into one file, or overwrite each other on a case-insensitive file system.
|
|
347
|
+
* Only the file name changes. The declarations keep their names.
|
|
348
|
+
*
|
|
349
|
+
* @example Resolve `plugin-ts`'s file for the current operation
|
|
62
350
|
* ```ts
|
|
63
|
-
* const fileTs =
|
|
351
|
+
* const fileTs = resolveOperationFile({ ctx, node, resolver: tsResolver, root, output })
|
|
64
352
|
* ```
|
|
65
353
|
*/
|
|
66
|
-
function
|
|
67
|
-
const {
|
|
68
|
-
|
|
69
|
-
|
|
354
|
+
function resolveOperationFile(options) {
|
|
355
|
+
const { ctx, node, resolver, root, output } = options;
|
|
356
|
+
const { memo } = ctx;
|
|
357
|
+
const location = {
|
|
70
358
|
root,
|
|
71
359
|
output,
|
|
72
|
-
group: group ?? void 0
|
|
73
|
-
}
|
|
360
|
+
group: options.group ?? void 0
|
|
361
|
+
};
|
|
362
|
+
return memo(`${resolver.pluginName}:operationFile:${node.operationId}`, () => {
|
|
363
|
+
const schemaPaths = memo(`${resolver.pluginName}:schemaFilePaths`, () => new Set((ctx.driver.inputNode?.schemas ?? []).flatMap((schema) => schema.name ? [resolver.file({
|
|
364
|
+
name: schema.name,
|
|
365
|
+
extname: ".ts",
|
|
366
|
+
...location
|
|
367
|
+
}).path.toLowerCase()] : [])));
|
|
368
|
+
let file = resolver.file({
|
|
369
|
+
...operationFileEntry(node, node.operationId),
|
|
370
|
+
...location
|
|
371
|
+
});
|
|
372
|
+
for (let name = `${node.operationId}Operation`; schemaPaths.has(file.path.toLowerCase()); name += "Operation") {
|
|
373
|
+
const next = resolver.file({
|
|
374
|
+
...operationFileEntry(node, name),
|
|
375
|
+
...location
|
|
376
|
+
});
|
|
377
|
+
if (next.path === file.path) break;
|
|
378
|
+
file = next;
|
|
379
|
+
}
|
|
380
|
+
return file;
|
|
381
|
+
});
|
|
74
382
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
383
|
+
/**
|
|
384
|
+
* The operation's method and path as plain text, such as `` `GET /pet/{petId}` ``. A path is not a valid `{@link}` target.
|
|
385
|
+
*/
|
|
386
|
+
function getOperationRequestLine(node) {
|
|
387
|
+
return _kubb_kit.ast.http.isOperation(node) && node.path ? `\`${node.method.toUpperCase()} ${node.path}\`` : null;
|
|
79
388
|
}
|
|
80
389
|
/**
|
|
81
390
|
* Derives the shared `ContentTypeInfo` shape from a list of content types, tracking whether several
|
|
@@ -99,18 +408,7 @@ function getContentTypeInfo(node) {
|
|
|
99
408
|
* whether several are present, so the client can let a caller pick which one to accept.
|
|
100
409
|
*/
|
|
101
410
|
function getResponseContentTypeInfo(node) {
|
|
102
|
-
return buildContentTypeInfo(
|
|
103
|
-
}
|
|
104
|
-
function baseContentType(contentType) {
|
|
105
|
-
return contentType.split(";")[0].trim().toLowerCase();
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* Whether a content entry is a sequence of JSON values the adapter marks as a stream, such as `application/jsonl`,
|
|
109
|
-
* `application/x-ndjson`, `application/json-seq`, or any media type with an OpenAPI 3.2 `itemSchema`.
|
|
110
|
-
*/
|
|
111
|
-
function isJsonLines(entry) {
|
|
112
|
-
const baseType = baseContentType(entry.contentType);
|
|
113
|
-
return Boolean(entry.stream) && baseType !== "text/event-stream" && !baseType.startsWith("multipart/");
|
|
411
|
+
return buildContentTypeInfo(_kubb_kit.ast.http.responses.findPrimary(node)?.content?.map((e) => e.contentType) ?? []);
|
|
114
412
|
}
|
|
115
413
|
/**
|
|
116
414
|
* How an operation streams its primary success response item by item, when that response declares one content type:
|
|
@@ -122,11 +420,19 @@ function isJsonLines(entry) {
|
|
|
122
420
|
* call with its query hooks.
|
|
123
421
|
*/
|
|
124
422
|
function getEventStream(node) {
|
|
125
|
-
const content =
|
|
423
|
+
const content = _kubb_kit.ast.http.responses.findPrimary(node)?.content ?? [];
|
|
126
424
|
if (content.length !== 1) return null;
|
|
127
425
|
const entry = content[0];
|
|
128
|
-
|
|
129
|
-
|
|
426
|
+
const framing = getStreamFraming(entry);
|
|
427
|
+
if (framing === "events") return entry.stream?.shape ?? "data";
|
|
428
|
+
return framing === "lines" ? "line" : null;
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* How a content entry is framed as a stream: `'events'` for Server-Sent Events, `'lines'` for JSON Lines.
|
|
432
|
+
*/
|
|
433
|
+
function getStreamFraming(entry) {
|
|
434
|
+
if (_kubb_kit.ast.mediaType.getBase(entry) === "text/event-stream") return "events";
|
|
435
|
+
return entry.stream && _kubb_kit.ast.mediaType.isStream(entry) ? "lines" : void 0;
|
|
130
436
|
}
|
|
131
437
|
/**
|
|
132
438
|
* Whether an operation streams its primary success response, as Server-Sent Events or JSON Lines. The client generator uses
|
|
@@ -136,20 +442,42 @@ function isEventStream(node) {
|
|
|
136
442
|
return getEventStream(node) !== null;
|
|
137
443
|
}
|
|
138
444
|
/**
|
|
445
|
+
* Whether a success response offers a stream media type next to other content types. The client returns that variant's
|
|
446
|
+
* body as a `ReadableStream`, so the stream runtime is registered and a hook's data type includes the stream.
|
|
447
|
+
*/
|
|
448
|
+
function hasStreamVariant(node) {
|
|
449
|
+
return _kubb_kit.ast.http.responses.filterSuccess(node).some((response) => {
|
|
450
|
+
const variants = (response.content ?? []).filter((entry) => entry.schema);
|
|
451
|
+
return variants.length > 1 && variants.some((entry) => _kubb_kit.ast.mediaType.isStream(entry));
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
/**
|
|
139
455
|
* Builds the `client?:` option type shared by the generated query hooks (`useQuery`,
|
|
140
|
-
* `useInfiniteQuery`, `useSWR`, ...)
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
*
|
|
456
|
+
* `useInfiniteQuery`, `useSWR`, ...): `RequestConfig` minus what the
|
|
457
|
+
* hook fills in, which is every request group and `throwOnError`. Unlike {@link buildRequestConfigType},
|
|
458
|
+
* it never narrows `contentType`: query hooks wrap GET operations, which carry no request body to select
|
|
459
|
+
* a content type for.
|
|
144
460
|
*/
|
|
145
|
-
function buildClientOptionType(
|
|
146
|
-
return `Partial<Omit<RequestConfig,
|
|
461
|
+
function buildClientOptionType(options = {}) {
|
|
462
|
+
return `Partial<Omit<RequestConfig, ${[
|
|
463
|
+
...requestGroupOrder,
|
|
464
|
+
"url",
|
|
465
|
+
...options.omit ?? [],
|
|
466
|
+
"throwOnError"
|
|
467
|
+
].map((key) => `'${key}'`).join(" | ")}>>`;
|
|
147
468
|
}
|
|
469
|
+
/**
|
|
470
|
+
* The `client?:` option type of a mutation hook. When the operation has a request content type choice,
|
|
471
|
+
* the mutation variables carry `contentType`, so the config leaves it out. Otherwise the ambiguous side is
|
|
472
|
+
* narrowed to the operation's media types; a single-type side has nothing to pick, so it stays baked in the
|
|
473
|
+
* generated call.
|
|
474
|
+
*/
|
|
148
475
|
function buildRequestConfigType(node) {
|
|
476
|
+
if (hasRequestContentTypeChoice(node)) return buildClientOptionType({ omit: ["contentType"] });
|
|
149
477
|
const request = getContentTypeInfo(node);
|
|
150
478
|
const response = getResponseContentTypeInfo(node);
|
|
151
479
|
const members = [request.isMultipleContentTypes ? `request?: ${request.contentTypeUnion}` : null, response.isMultipleContentTypes ? `response?: ${response.contentTypeUnion}` : null].filter(Boolean);
|
|
152
|
-
const base = buildClientOptionType(
|
|
480
|
+
const base = buildClientOptionType();
|
|
153
481
|
return members.length ? `${base} & { contentType?: { ${members.join("; ")} } }` : base;
|
|
154
482
|
}
|
|
155
483
|
/** The grouped request options, in the order generated signatures and calls list them. */
|
|
@@ -164,11 +492,11 @@ const requestGroupOrder = [
|
|
|
164
492
|
* Which of the grouped request options an operation carries.
|
|
165
493
|
*/
|
|
166
494
|
function getRequestGroups(node) {
|
|
167
|
-
const { path, query, header, cookie } =
|
|
495
|
+
const { path, query, header, cookie } = _kubb_kit.ast.http.groupParameters(node);
|
|
168
496
|
return {
|
|
169
497
|
path: path.length > 0,
|
|
170
498
|
query: query.length > 0,
|
|
171
|
-
body: Boolean(
|
|
499
|
+
body: Boolean(_kubb_kit.ast.http.requestBody.getSchema(node)),
|
|
172
500
|
headers: header.length > 0,
|
|
173
501
|
cookies: cookie.length > 0
|
|
174
502
|
};
|
|
@@ -180,7 +508,7 @@ function getRequestGroups(node) {
|
|
|
180
508
|
*/
|
|
181
509
|
function getRequestGroupOptionality(node) {
|
|
182
510
|
const groups = getRequestGroups(node);
|
|
183
|
-
const { path, query, header } =
|
|
511
|
+
const { path, query, header } = _kubb_kit.ast.http.groupParameters(node);
|
|
184
512
|
const hasRequiredPath = path.some((param) => param.required);
|
|
185
513
|
const hasRequiredQuery = query.some((param) => param.required);
|
|
186
514
|
const hasRequiredHeader = header.some((param) => param.required);
|
|
@@ -193,104 +521,28 @@ function getRequestGroupOptionality(node) {
|
|
|
193
521
|
};
|
|
194
522
|
}
|
|
195
523
|
function buildOperationComments(node, options = {}) {
|
|
196
|
-
const {
|
|
197
|
-
const
|
|
198
|
-
|
|
199
|
-
node.description && `@description ${node.description}`,
|
|
200
|
-
node.summary && `@summary ${node.summary}`,
|
|
201
|
-
linkComment,
|
|
202
|
-
node.deprecated && "@deprecated"
|
|
203
|
-
] : [
|
|
524
|
+
const { splitLines = false } = options;
|
|
525
|
+
const filteredComments = [
|
|
526
|
+
getOperationRequestLine(node),
|
|
204
527
|
node.description && `@description ${node.description}`,
|
|
205
528
|
node.summary && `@summary ${node.summary}`,
|
|
206
529
|
node.deprecated && "@deprecated",
|
|
207
|
-
|
|
208
|
-
]
|
|
530
|
+
node.externalDocs && `@see ${jsDocEscape([node.externalDocs.url, node.externalDocs.description].filter(Boolean).join(" "))}`
|
|
531
|
+
].filter((comment) => Boolean(comment));
|
|
209
532
|
if (!splitLines) return filteredComments;
|
|
210
533
|
return filteredComments.flatMap((text) => text.split(/\r?\n/).map((line) => line.trim())).filter((comment) => Boolean(comment));
|
|
211
534
|
}
|
|
212
|
-
const operationParameterGroupsByNode = /* @__PURE__ */ new WeakMap();
|
|
213
|
-
/**
|
|
214
|
-
* An OpenAPI 3.2 `querystring` parameter is the whole query string, so a form-encoded object becomes one query parameter
|
|
215
|
-
* per property, typed and serialized like any other.
|
|
216
|
-
* Another content type, such as JSON, stays one parameter named after it, and the runtime sends its value as the whole query string.
|
|
217
|
-
*/
|
|
218
|
-
function spreadQuerystring(param) {
|
|
219
|
-
const schema = param.schema.type === "ref" ? param.schema.schema : param.schema;
|
|
220
|
-
const formEncoded = !param.contentType || param.contentType.split(";")[0].trim().toLowerCase() === "application/x-www-form-urlencoded";
|
|
221
|
-
if (schema?.type !== "object" || !formEncoded) return [param];
|
|
222
|
-
return schema.properties.map((property) => _kubb_kit.ast.factory.createParameter({
|
|
223
|
-
name: property.name,
|
|
224
|
-
in: "query",
|
|
225
|
-
schema: property.schema,
|
|
226
|
-
required: param.required && property.required
|
|
227
|
-
}));
|
|
228
|
-
}
|
|
229
|
-
/**
|
|
230
|
-
* Groups an operation's parameters by location (`path`/`query`/`header`/`cookie`), deduping each
|
|
231
|
-
* group by name. Every plugin generator visiting the same `OperationNode` shares one AST instance
|
|
232
|
-
* (see `KubbDriver`), so the result is cached per node to avoid re-filtering and re-deduping the
|
|
233
|
-
* same parameters once per plugin.
|
|
234
|
-
*/
|
|
235
|
-
function getOperationParameters(node) {
|
|
236
|
-
const cached = operationParameterGroupsByNode.get(node);
|
|
237
|
-
if (cached) return cached;
|
|
238
|
-
const dedupe = (params) => {
|
|
239
|
-
const seen = /* @__PURE__ */ new Set();
|
|
240
|
-
return params.filter((param) => {
|
|
241
|
-
if (seen.has(param.name)) return false;
|
|
242
|
-
seen.add(param.name);
|
|
243
|
-
return true;
|
|
244
|
-
});
|
|
245
|
-
};
|
|
246
|
-
const group = (location) => dedupe(node.parameters.filter((param) => param.in === location));
|
|
247
|
-
const groups = {
|
|
248
|
-
path: group("path"),
|
|
249
|
-
query: dedupe([...group("query"), ...group("querystring").flatMap(spreadQuerystring)]),
|
|
250
|
-
header: group("header"),
|
|
251
|
-
cookie: group("cookie")
|
|
252
|
-
};
|
|
253
|
-
operationParameterGroupsByNode.set(node, groups);
|
|
254
|
-
return groups;
|
|
255
|
-
}
|
|
256
535
|
/**
|
|
257
536
|
* Whether the operation declares more than one request media type with a schema, so a caller must pick one on `contentType`.
|
|
258
537
|
*/
|
|
259
538
|
function hasRequestContentTypeChoice(node) {
|
|
260
539
|
return (node.requestBody?.content ?? []).filter((entry) => entry.schema).length > 1;
|
|
261
540
|
}
|
|
262
|
-
/**
|
|
263
|
-
* Casts a call argument to the client's parameter type; a `'plain'` client is non-generic.
|
|
264
|
-
*/
|
|
265
|
-
function castToClientOptions(callArg, clientName, returnType = "full") {
|
|
266
|
-
return `${callArg} as Parameters<typeof ${clientName}${returnType === "plain" ? "" : "<true>"}>[0]`;
|
|
267
|
-
}
|
|
268
|
-
function getStatusCodeNumber(statusCode) {
|
|
269
|
-
const code = Number(statusCode);
|
|
270
|
-
return Number.isNaN(code) ? null : code;
|
|
271
|
-
}
|
|
272
|
-
function isSuccessStatusCode(statusCode) {
|
|
273
|
-
const code = getStatusCodeNumber(statusCode);
|
|
274
|
-
return code !== null && code >= 200 && code < 300;
|
|
275
|
-
}
|
|
276
|
-
function isErrorStatusCode(statusCode) {
|
|
277
|
-
const code = getStatusCodeNumber(statusCode);
|
|
278
|
-
return code !== null && code >= 400;
|
|
279
|
-
}
|
|
280
|
-
function getSuccessResponses(responses) {
|
|
281
|
-
return responses.filter((response) => isSuccessStatusCode(response.statusCode));
|
|
282
|
-
}
|
|
283
|
-
function getOperationSuccessResponses(node) {
|
|
284
|
-
return getSuccessResponses(node.responses);
|
|
285
|
-
}
|
|
286
|
-
function getPrimarySuccessResponse(node) {
|
|
287
|
-
return getOperationSuccessResponses(node)[0] ?? null;
|
|
288
|
-
}
|
|
289
541
|
function resolveErrorNames(node, resolver) {
|
|
290
|
-
return
|
|
542
|
+
return _kubb_kit.ast.http.responses.filterError(node).map((response) => resolver.response.status(node, response.statusCode));
|
|
291
543
|
}
|
|
292
544
|
function resolveSuccessNames(node, resolver) {
|
|
293
|
-
return
|
|
545
|
+
return _kubb_kit.ast.http.responses.filterSuccess(node).map((response) => resolver.response.status(node, response.statusCode));
|
|
294
546
|
}
|
|
295
547
|
function resolveStatusCodeNames(node, resolver) {
|
|
296
548
|
return node.responses.map((response) => resolver.response.status(node, response.statusCode));
|
|
@@ -302,7 +554,7 @@ function resolveStatusCodeNames(node, resolver) {
|
|
|
302
554
|
function resolveOperationTypeNames(node, resolver, options = {}) {
|
|
303
555
|
const key = `${node.operationId}\0${options.order ?? ""}\0${options.responseStatusNames ?? ""}\0${options.includeParams === false ? "noparams" : ""}\0${(options.exclude ?? []).join(",")}`;
|
|
304
556
|
return resolver.memo(`operationTypeNames:${key}`, () => {
|
|
305
|
-
const { path, query, header, cookie } =
|
|
557
|
+
const { path, query, header, cookie } = _kubb_kit.ast.http.groupParameters(node);
|
|
306
558
|
const responseStatusNames = options.responseStatusNames === "error" ? resolveErrorNames(node, resolver) : options.responseStatusNames === false ? [] : resolveStatusCodeNames(node, resolver);
|
|
307
559
|
const exclude = new Set(options.exclude ?? []);
|
|
308
560
|
const paramNames = options.includeParams === false ? [] : [
|
|
@@ -311,7 +563,7 @@ function resolveOperationTypeNames(node, resolver, options = {}) {
|
|
|
311
563
|
...header.map((param) => resolver.param.headers(node, param)),
|
|
312
564
|
...cookie.map((param) => resolver.param.cookies(node, param))
|
|
313
565
|
];
|
|
314
|
-
const bodyAndResponseNames = [
|
|
566
|
+
const bodyAndResponseNames = [_kubb_kit.ast.http.requestBody.getSchema(node) ? resolver.response.body(node) : null, resolver.response.response(node)];
|
|
315
567
|
return (options.order === "body-response-first" ? [
|
|
316
568
|
...bodyAndResponseNames,
|
|
317
569
|
...paramNames,
|
|
@@ -323,235 +575,139 @@ function resolveOperationTypeNames(node, resolver, options = {}) {
|
|
|
323
575
|
]).filter((name) => Boolean(name) && !exclude.has(name));
|
|
324
576
|
});
|
|
325
577
|
}
|
|
326
|
-
// ../../internals/
|
|
327
|
-
/**
|
|
328
|
-
* Uppercases only the first character of `text`, leaving the rest untouched.
|
|
329
|
-
* Unlike `pascalCase` it never re-splits word boundaries or strips characters.
|
|
330
|
-
*
|
|
331
|
-
* @example
|
|
332
|
-
* `capitalize('getPetById') // 'GetPetById'`
|
|
333
|
-
*/
|
|
334
|
-
function capitalize(text) {
|
|
335
|
-
return `${text.charAt(0).toUpperCase()}${text.slice(1)}`;
|
|
336
|
-
}
|
|
337
|
-
// ../../internals/utils/src/reserved.ts
|
|
338
|
-
/**
|
|
339
|
-
* JavaScript and Java reserved words.
|
|
340
|
-
* @link https://github.com/jonschlinkert/reserved/blob/master/index.js
|
|
341
|
-
*/
|
|
342
|
-
const reservedWords = /* @__PURE__ */ new Set([
|
|
343
|
-
"abstract",
|
|
344
|
-
"arguments",
|
|
345
|
-
"await",
|
|
346
|
-
"boolean",
|
|
347
|
-
"break",
|
|
348
|
-
"byte",
|
|
349
|
-
"case",
|
|
350
|
-
"catch",
|
|
351
|
-
"char",
|
|
352
|
-
"class",
|
|
353
|
-
"const",
|
|
354
|
-
"continue",
|
|
355
|
-
"debugger",
|
|
356
|
-
"default",
|
|
357
|
-
"delete",
|
|
358
|
-
"do",
|
|
359
|
-
"double",
|
|
360
|
-
"else",
|
|
361
|
-
"enum",
|
|
362
|
-
"eval",
|
|
363
|
-
"export",
|
|
364
|
-
"extends",
|
|
365
|
-
"false",
|
|
366
|
-
"final",
|
|
367
|
-
"finally",
|
|
368
|
-
"float",
|
|
369
|
-
"for",
|
|
370
|
-
"function",
|
|
371
|
-
"goto",
|
|
372
|
-
"if",
|
|
373
|
-
"implements",
|
|
374
|
-
"import",
|
|
375
|
-
"in",
|
|
376
|
-
"instanceof",
|
|
377
|
-
"int",
|
|
378
|
-
"interface",
|
|
379
|
-
"let",
|
|
380
|
-
"long",
|
|
381
|
-
"native",
|
|
382
|
-
"new",
|
|
383
|
-
"null",
|
|
384
|
-
"package",
|
|
385
|
-
"private",
|
|
386
|
-
"protected",
|
|
387
|
-
"public",
|
|
388
|
-
"return",
|
|
389
|
-
"short",
|
|
390
|
-
"static",
|
|
391
|
-
"super",
|
|
392
|
-
"switch",
|
|
393
|
-
"synchronized",
|
|
394
|
-
"this",
|
|
395
|
-
"throw",
|
|
396
|
-
"throws",
|
|
397
|
-
"transient",
|
|
398
|
-
"true",
|
|
399
|
-
"try",
|
|
400
|
-
"typeof",
|
|
401
|
-
"var",
|
|
402
|
-
"void",
|
|
403
|
-
"volatile",
|
|
404
|
-
"while",
|
|
405
|
-
"with",
|
|
406
|
-
"yield",
|
|
407
|
-
"Array",
|
|
408
|
-
"Date",
|
|
409
|
-
"hasOwnProperty",
|
|
410
|
-
"Infinity",
|
|
411
|
-
"isFinite",
|
|
412
|
-
"isNaN",
|
|
413
|
-
"isPrototypeOf",
|
|
414
|
-
"length",
|
|
415
|
-
"Math",
|
|
416
|
-
"name",
|
|
417
|
-
"NaN",
|
|
418
|
-
"Number",
|
|
419
|
-
"Object",
|
|
420
|
-
"prototype",
|
|
421
|
-
"String",
|
|
422
|
-
"toString",
|
|
423
|
-
"undefined",
|
|
424
|
-
"valueOf"
|
|
425
|
-
]);
|
|
578
|
+
// ../../internals/shared/src/resolver.ts
|
|
426
579
|
/**
|
|
427
|
-
*
|
|
428
|
-
*
|
|
429
|
-
* @example
|
|
430
|
-
* ```ts
|
|
431
|
-
* isValidVarName('status') // true
|
|
432
|
-
* isValidVarName('class') // false (reserved word)
|
|
433
|
-
* isValidVarName('42foo') // false (starts with digit)
|
|
434
|
-
* ```
|
|
580
|
+
* The shared top-level `name` of the operation plugins, computed once per operation name and build.
|
|
435
581
|
*/
|
|
436
|
-
function
|
|
437
|
-
|
|
438
|
-
return isIdentifier(name);
|
|
582
|
+
function resolveOperationName(name) {
|
|
583
|
+
return this.memo(`operation:${name}`, () => ensureValidVarName(_kubb_kit.casing.camel(name)));
|
|
439
584
|
}
|
|
440
585
|
/**
|
|
441
|
-
*
|
|
442
|
-
*
|
|
586
|
+
* Builds the allocation key for a declaration an operation owns. `scope` names which declaration
|
|
587
|
+
* it is, so two of them never share an allocation even when a custom resolver gives both the same
|
|
588
|
+
* name. Leave `scope` empty for the operation's own declaration.
|
|
443
589
|
*
|
|
444
|
-
*
|
|
445
|
-
*
|
|
446
|
-
* variable, type, or function names.
|
|
590
|
+
* The key starts from the operation's input `pointer`, which macros keep, so a plugin whose macro
|
|
591
|
+
* rewrites the method or path still resolves another plugin's names for the same operation.
|
|
447
592
|
*
|
|
448
593
|
* @example
|
|
449
594
|
* ```ts
|
|
450
|
-
*
|
|
451
|
-
* ensureValidVarName('504AccountCancel') // '_504AccountCancel'
|
|
452
|
-
* ensureValidVarName('Pet') // 'Pet'
|
|
453
|
-
* ensureValidVarName('class') // '_class'
|
|
595
|
+
* resolver.resolveName({ key: operationKey(node, 'response', 'status', 404), name })
|
|
454
596
|
* ```
|
|
455
597
|
*/
|
|
456
|
-
function
|
|
457
|
-
|
|
458
|
-
|
|
598
|
+
function operationKey(node, ...scope) {
|
|
599
|
+
return [
|
|
600
|
+
"operation",
|
|
601
|
+
...node.pointer ? [node.pointer] : [node.method, node.path],
|
|
602
|
+
...scope.map(String)
|
|
603
|
+
];
|
|
604
|
+
}
|
|
605
|
+
// ../../internals/client/src/resolveClientOperation.ts
|
|
606
|
+
function isRelativeImport(importPath) {
|
|
607
|
+
return importPath.startsWith(".");
|
|
608
|
+
}
|
|
609
|
+
function resolveImportPath(options) {
|
|
610
|
+
const { importPath, operationFile } = options;
|
|
611
|
+
return isRelativeImport(importPath) ? node_path.default.resolve(node_path.default.dirname(operationFile), importPath) : importPath;
|
|
459
612
|
}
|
|
460
613
|
/**
|
|
461
|
-
*
|
|
614
|
+
* Resolves the contract client `<op>` a consumer (query hook, MCP handler) imports, by looking up
|
|
615
|
+
* the registered contract client plugin's resolver and output. Works for any contract client plugin
|
|
616
|
+
* (plugin-fetch, plugin-axios, or plugin-client). Returns `null` when no contract plugin is in play (the inline
|
|
617
|
+
* path), or when the client plugin's `exclude` / `include` leaves this operation out, since it then
|
|
618
|
+
* emits no `<op>` to import. plugin-fetch / plugin-axios inject `.kubb/client.ts` at the global
|
|
619
|
+
* output root, the same path consumers read `RequestConfig` / `ResponseErrorConfig` from.
|
|
620
|
+
* With plugin-client they come from the user's `importPath` module instead.
|
|
462
621
|
*
|
|
463
|
-
*
|
|
464
|
-
*
|
|
465
|
-
*
|
|
622
|
+
* The result is cached in `memo` (the build's `ctx.memo`) under the client plugin's name and the operation,
|
|
623
|
+
* so several dependents reading the same client plugin for one operation in a single pass
|
|
624
|
+
* (react-query's query/mutation/infinite generators, vue-query, swr, the MCP handler, ...) share
|
|
625
|
+
* one computed result instead of each re-deriving the name and path.
|
|
466
626
|
*
|
|
467
|
-
*
|
|
468
|
-
*
|
|
469
|
-
*
|
|
470
|
-
* isIdentifier('x-total')// false
|
|
471
|
-
* ```
|
|
627
|
+
* `returnType`, `output`, and `group` are the client plugin's options for this operation, after its
|
|
628
|
+
* `override` entries, the same resolution its own generator sees. A dependent's generated call body
|
|
629
|
+
* and import path therefore match the `<op>` actually emitted, even when an `override` changes it.
|
|
472
630
|
*/
|
|
473
|
-
function
|
|
474
|
-
|
|
631
|
+
function resolveClientOperation(options) {
|
|
632
|
+
const { clientPlugin, driver, node, root, output, memo } = options;
|
|
633
|
+
if (!clientPlugin) return null;
|
|
634
|
+
return memo(`${clientPlugin.pluginName}:clientOperation:${node.operationId}`, () => {
|
|
635
|
+
const resolver = driver.getResolver(clientPlugin.pluginName);
|
|
636
|
+
const pluginOptions = driver.getPlugin(clientPlugin.pluginName)?.options ?? {};
|
|
637
|
+
const { exclude, include, override } = pluginOptions;
|
|
638
|
+
const operationOptions = Boolean(exclude?.length || include?.length || override?.length) && resolver.default ? resolver.default.options(node, {
|
|
639
|
+
options: pluginOptions,
|
|
640
|
+
exclude,
|
|
641
|
+
include,
|
|
642
|
+
override
|
|
643
|
+
}) : pluginOptions;
|
|
644
|
+
if (!operationOptions) return null;
|
|
645
|
+
const file = resolver.file({
|
|
646
|
+
...operationFileEntry(node, node.operationId),
|
|
647
|
+
root,
|
|
648
|
+
output: operationOptions.output ?? output,
|
|
649
|
+
group: operationOptions.group ?? void 0
|
|
650
|
+
});
|
|
651
|
+
const { importPath } = operationOptions;
|
|
652
|
+
const name = resolver.name(node.operationId);
|
|
653
|
+
return {
|
|
654
|
+
name: resolver.resolveName({
|
|
655
|
+
key: operationKey(node),
|
|
656
|
+
name
|
|
657
|
+
}),
|
|
658
|
+
path: file.path,
|
|
659
|
+
clientPath: importPath === void 0 ? node_path.default.resolve(root, ".kubb/client.ts") : resolveImportPath({
|
|
660
|
+
importPath,
|
|
661
|
+
operationFile: file.path
|
|
662
|
+
}),
|
|
663
|
+
clientPathIsFile: importPath === void 0 || isRelativeImport(importPath),
|
|
664
|
+
returnType: operationOptions.returnType ?? "full",
|
|
665
|
+
typedHeaders: importPath === void 0
|
|
666
|
+
};
|
|
667
|
+
});
|
|
668
|
+
}
|
|
669
|
+
// ../../internals/client/src/resolveOperationTypes.ts
|
|
670
|
+
const pluginZodName = "plugin-zod";
|
|
671
|
+
function getResponseHeadersEntries({ node, types }) {
|
|
672
|
+
const resolve = types.response.headers;
|
|
673
|
+
if (!resolve) return [];
|
|
674
|
+
return node.responses.filter((response) => response.headers?.length).map((response) => [response.statusCode, resolve.call(types.response, node, response.statusCode)]);
|
|
475
675
|
}
|
|
476
|
-
// ../../internals/utils/src/strings.ts
|
|
477
676
|
/**
|
|
478
|
-
*
|
|
479
|
-
* `accessor`. Returns `null` for an empty path.
|
|
480
|
-
*
|
|
481
|
-
* @example
|
|
482
|
-
* ```ts
|
|
483
|
-
* getNestedAccessor('pagination.next.id', 'lastPage')
|
|
484
|
-
* // "lastPage?.['pagination']?.['next']?.['id']"
|
|
485
|
-
* ```
|
|
677
|
+
* The headers type argument of `RequestResult`, such as `{ '200': LoginUserStatus200Headers }`, or `null` when no response declares headers.
|
|
486
678
|
*/
|
|
487
|
-
function
|
|
488
|
-
const
|
|
489
|
-
|
|
490
|
-
|
|
679
|
+
function buildResponseHeadersType({ node, types }) {
|
|
680
|
+
const entries = getResponseHeadersEntries({
|
|
681
|
+
node,
|
|
682
|
+
types
|
|
683
|
+
}).map(([statusCode, name]) => `'${statusCode}': ${name}`);
|
|
684
|
+
return entries.length ? `{ ${entries.join("; ")} }` : null;
|
|
491
685
|
}
|
|
492
|
-
// ../../internals/shared/src/resolver.ts
|
|
493
686
|
/**
|
|
494
|
-
*
|
|
687
|
+
* A runtime result type, such as `RequestResult`, in its `WithHeaders` form when `headers` is set.
|
|
495
688
|
*/
|
|
496
|
-
function
|
|
497
|
-
return
|
|
689
|
+
function resultTypeName(name, headers) {
|
|
690
|
+
return headers ? `${name}WithHeaders` : name;
|
|
498
691
|
}
|
|
499
692
|
/**
|
|
500
|
-
*
|
|
501
|
-
* it is, so two of them never share an allocation even when a custom resolver gives both the same
|
|
502
|
-
* name. Leave `scope` empty for the operation's own declaration.
|
|
503
|
-
*
|
|
504
|
-
* @example
|
|
505
|
-
* ```ts
|
|
506
|
-
* resolver.resolveName({ key: operationKey(node, 'response', 'status', 404), name })
|
|
507
|
-
* ```
|
|
693
|
+
* A runtime result type with its arguments, such as `RequestResultWithHeaders<Responses, Headers, ThrowOnError>`.
|
|
508
694
|
*/
|
|
509
|
-
function
|
|
510
|
-
return [
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
];
|
|
695
|
+
function buildResultTypeRef(name, responses, headers, rest = []) {
|
|
696
|
+
return `${resultTypeName(name, headers !== null)}<${[
|
|
697
|
+
responses,
|
|
698
|
+
headers,
|
|
699
|
+
...rest
|
|
700
|
+
].filter(Boolean).join(", ")}>`;
|
|
516
701
|
}
|
|
517
|
-
// ../../internals/shared/src/group.ts
|
|
518
702
|
/**
|
|
519
|
-
*
|
|
520
|
-
* shared default naming so every plugin groups output consistently:
|
|
521
|
-
*
|
|
522
|
-
* - `path` groups use the second path segment (`/pet/findByStatus` → `pet`).
|
|
523
|
-
* - other groups use the camelCased group (`pet store` → `petStore`).
|
|
524
|
-
*
|
|
525
|
-
* A user-provided `group.name` always wins over the default namer, so callers stay in
|
|
526
|
-
* control of their output folders. Returns `null` when grouping is disabled, matching the
|
|
527
|
-
* per-plugin convention.
|
|
528
|
-
*
|
|
529
|
-
* @param group - The user-supplied group option, or `undefined` to disable grouping.
|
|
530
|
-
*
|
|
531
|
-
* @example
|
|
532
|
-
* ```ts
|
|
533
|
-
* createGroupConfig(group) // shared across every plugin
|
|
534
|
-
* ```
|
|
703
|
+
* The names of the headers types `buildResponseHeadersType` references, for the file's imports.
|
|
535
704
|
*/
|
|
536
|
-
function
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
};
|
|
542
|
-
return {
|
|
543
|
-
...group,
|
|
544
|
-
name: group.name ? group.name : defaultName
|
|
545
|
-
};
|
|
705
|
+
function getResponseHeadersTypeNames({ node, types }) {
|
|
706
|
+
return getResponseHeadersEntries({
|
|
707
|
+
node,
|
|
708
|
+
types
|
|
709
|
+
}).map(([, name]) => name);
|
|
546
710
|
}
|
|
547
|
-
// kubb-extension.json
|
|
548
|
-
var compatibility = {
|
|
549
|
-
"kubb": ">=5.16.0",
|
|
550
|
-
"node": ">=22.22"
|
|
551
|
-
};
|
|
552
|
-
// package.json
|
|
553
|
-
var version = "5.10.0-canary.20261109T201601";
|
|
554
|
-
// ../../internals/client/src/resolveOperationTypes.ts
|
|
555
711
|
/**
|
|
556
712
|
* A `plugin-ts` shaped resolver whose operation type names point at the types `pluginZod({ inferred })`
|
|
557
713
|
* exports next to each schema, so code written against `plugin-ts` names picks up the zod types.
|
|
@@ -574,6 +730,7 @@ function toZodTypeResolver(resolver) {
|
|
|
574
730
|
status: (node, statusCode) => type(resolver.response.status(node, statusCode)),
|
|
575
731
|
response: (node) => type(resolver.response.response(node)),
|
|
576
732
|
responses: (node) => type(resolver.response.responses(node)),
|
|
733
|
+
headers: (node, statusCode) => type(resolver.response.headers(node, statusCode)),
|
|
577
734
|
options: (node) => resolver.response.options(node)
|
|
578
735
|
}
|
|
579
736
|
};
|
|
@@ -594,7 +751,7 @@ function toZodTypeResolver(resolver) {
|
|
|
594
751
|
function resolveOperationTypes(driver, pluginName) {
|
|
595
752
|
return driver.memo(`operationTypes:${pluginName}`, () => {
|
|
596
753
|
const pluginTs = driver.getPlugin(_kubb_plugin_ts.pluginTsName);
|
|
597
|
-
const pluginZod = driver.getPlugin(
|
|
754
|
+
const pluginZod = driver.getPlugin(pluginZodName);
|
|
598
755
|
if (pluginTs && pluginZod?.options?.inferred !== "codec") {
|
|
599
756
|
const resolver = driver.getResolver(_kubb_plugin_ts.pluginTsName);
|
|
600
757
|
return {
|
|
@@ -612,7 +769,7 @@ function resolveOperationTypes(driver, pluginName) {
|
|
|
612
769
|
location: { kind: "config" },
|
|
613
770
|
plugin: pluginName
|
|
614
771
|
});
|
|
615
|
-
const resolver = toZodTypeResolver(driver.getResolver(
|
|
772
|
+
const resolver = toZodTypeResolver(driver.getResolver(pluginZodName));
|
|
616
773
|
return {
|
|
617
774
|
response: resolver.response,
|
|
618
775
|
resolver,
|
|
@@ -621,179 +778,6 @@ function resolveOperationTypes(driver, pluginName) {
|
|
|
621
778
|
};
|
|
622
779
|
});
|
|
623
780
|
}
|
|
624
|
-
// ../../internals/client/src/resolveClient.ts
|
|
625
|
-
/**
|
|
626
|
-
* Resolves which client plugin a consumer (react-query, vue-query, swr, mcp) should call for an
|
|
627
|
-
* operation, shared so the selection rules and diagnostics stay in one place.
|
|
628
|
-
*
|
|
629
|
-
* Every client runtime lives in a dedicated client plugin, so a consumer always calls a registered
|
|
630
|
-
* contract client plugin (plugin-fetch, plugin-axios, or plugin-client) and never emits its own
|
|
631
|
-
* inline client:
|
|
632
|
-
*
|
|
633
|
-
* - `contract` — a registered contract client plugin owns the `<op>` functions and the consumer
|
|
634
|
-
* imports and calls them.
|
|
635
|
-
* - `error` — no client plugin is registered, several are registered without a selector, the
|
|
636
|
-
* requested one is missing, or `client` is not a known selector.
|
|
637
|
-
*
|
|
638
|
-
* The `client` string selects explicitly (`'fetch'` / `'axios'` / `'client'`); when it is unset a
|
|
639
|
-
* lone registered contract client plugin is picked up automatically.
|
|
640
|
-
*/
|
|
641
|
-
const pluginFetchName = "plugin-fetch";
|
|
642
|
-
const pluginAxiosName = "plugin-axios";
|
|
643
|
-
const pluginClientName = "plugin-client";
|
|
644
|
-
const selectorToPlugin = {
|
|
645
|
-
fetch: pluginFetchName,
|
|
646
|
-
axios: pluginAxiosName,
|
|
647
|
-
client: pluginClientName
|
|
648
|
-
};
|
|
649
|
-
const contractPlugins = [
|
|
650
|
-
pluginFetchName,
|
|
651
|
-
pluginAxiosName,
|
|
652
|
-
pluginClientName
|
|
653
|
-
];
|
|
654
|
-
/**
|
|
655
|
-
* Applies the `client` resolution rules. See the module comment for the strategy shape.
|
|
656
|
-
*
|
|
657
|
-
* @example
|
|
658
|
-
* ```ts
|
|
659
|
-
* resolveClient({ client: 'fetch', pluginNames: ['plugin-ts', 'plugin-fetch'] })
|
|
660
|
-
* // { kind: 'contract', pluginName: 'plugin-fetch' }
|
|
661
|
-
* ```
|
|
662
|
-
*
|
|
663
|
-
* @example
|
|
664
|
-
* ```ts
|
|
665
|
-
* resolveClient({ client: undefined, pluginNames: ['plugin-ts'] })
|
|
666
|
-
* // { kind: 'error', code: 'KUBB_MISSING_DEPENDENCY', message: 'No client plugin is registered.', help: 'Add …' }
|
|
667
|
-
* ```
|
|
668
|
-
*/
|
|
669
|
-
function resolveClient(options) {
|
|
670
|
-
const { client, pluginNames } = options;
|
|
671
|
-
const has = (name) => pluginNames.includes(name);
|
|
672
|
-
if (client === "fetch" || client === "axios" || client === "client") {
|
|
673
|
-
const pluginName = selectorToPlugin[client];
|
|
674
|
-
if (!has(pluginName)) return {
|
|
675
|
-
kind: "error",
|
|
676
|
-
code: _kubb_kit.Diagnostics.code.missingDependency,
|
|
677
|
-
message: `\`client: '${client}'\` is set but \`@kubb/plugin-${client}\` is not registered in \`plugins\`.`,
|
|
678
|
-
help: `Add \`@kubb/plugin-${client}\` to \`plugins\`, or drop \`client\` to use a different client plugin.`
|
|
679
|
-
};
|
|
680
|
-
return {
|
|
681
|
-
kind: "contract",
|
|
682
|
-
pluginName
|
|
683
|
-
};
|
|
684
|
-
}
|
|
685
|
-
if (client !== void 0) return {
|
|
686
|
-
kind: "error",
|
|
687
|
-
code: _kubb_kit.Diagnostics.code.invalidPluginOptions,
|
|
688
|
-
message: `Option \`client\` is ${typeof client === "string" ? `'${client}'` : String(client)}, but it must be one of 'fetch', 'axios', 'client'.`,
|
|
689
|
-
help: "Set `client` to one of those values, or drop it to use the registered client plugin."
|
|
690
|
-
};
|
|
691
|
-
const registered = contractPlugins.filter(has);
|
|
692
|
-
if (registered.length === 1) return {
|
|
693
|
-
kind: "contract",
|
|
694
|
-
pluginName: registered[0]
|
|
695
|
-
};
|
|
696
|
-
if (registered.length > 1) return {
|
|
697
|
-
kind: "error",
|
|
698
|
-
code: _kubb_kit.Diagnostics.code.invalidPluginOptions,
|
|
699
|
-
message: `Multiple client plugins are registered (${registered.map((name) => `\`@kubb/${name}\``).join(", ")}) and \`client\` is not set.`,
|
|
700
|
-
help: "Set `client: 'fetch' | 'axios' | 'client'` to choose which client the hooks call, or register a single client plugin."
|
|
701
|
-
};
|
|
702
|
-
return {
|
|
703
|
-
kind: "error",
|
|
704
|
-
code: _kubb_kit.Diagnostics.code.missingDependency,
|
|
705
|
-
message: "No client plugin is registered.",
|
|
706
|
-
help: "Add `@kubb/plugin-fetch`, `@kubb/plugin-axios`, or `@kubb/plugin-client` to `plugins` so the generated code has an HTTP client to call."
|
|
707
|
-
};
|
|
708
|
-
}
|
|
709
|
-
/**
|
|
710
|
-
* Resolves the contract client during a consumer plugin's setup hook.
|
|
711
|
-
* It extracts the plugin names from the raw `plugins` config and applies {@link resolveClient}.
|
|
712
|
-
* On a misconfiguration it throws a config diagnostic tagged with `plugin`, so every consumer
|
|
713
|
-
* fails fast with the same message.
|
|
714
|
-
*/
|
|
715
|
-
function resolveContractClient(options) {
|
|
716
|
-
const { plugin, client, plugins = [] } = options;
|
|
717
|
-
const resolved = resolveClient({
|
|
718
|
-
client,
|
|
719
|
-
pluginNames: plugins.map((plugin) => plugin.name).filter((name) => Boolean(name))
|
|
720
|
-
});
|
|
721
|
-
if (resolved.kind === "error") {
|
|
722
|
-
const { code, message, help } = resolved;
|
|
723
|
-
throw new _kubb_kit.Diagnostics.Error({
|
|
724
|
-
code,
|
|
725
|
-
severity: "error",
|
|
726
|
-
message,
|
|
727
|
-
help,
|
|
728
|
-
location: { kind: "config" },
|
|
729
|
-
plugin
|
|
730
|
-
});
|
|
731
|
-
}
|
|
732
|
-
return resolved;
|
|
733
|
-
}
|
|
734
|
-
// ../../internals/client/src/resolveClientOperation.ts
|
|
735
|
-
function isRelativeImport(importPath) {
|
|
736
|
-
return importPath.startsWith(".");
|
|
737
|
-
}
|
|
738
|
-
function resolveImportPath(options) {
|
|
739
|
-
const { importPath, operationFile } = options;
|
|
740
|
-
return isRelativeImport(importPath) ? node_path.default.resolve(node_path.default.dirname(operationFile), importPath) : importPath;
|
|
741
|
-
}
|
|
742
|
-
/**
|
|
743
|
-
* Resolves the contract client `<op>` a consumer (query hook, MCP handler) imports, by looking up
|
|
744
|
-
* the registered contract client plugin's resolver and output. Works for any contract client plugin
|
|
745
|
-
* (plugin-fetch, plugin-axios, or plugin-client). Returns `null` when no contract plugin is in play (the inline
|
|
746
|
-
* path), or when the client plugin's `exclude` / `include` leaves this operation out, since it then
|
|
747
|
-
* emits no `<op>` to import. plugin-fetch / plugin-axios inject `.kubb/client.ts` at the global
|
|
748
|
-
* output root, the same path consumers read `RequestConfig` / `ResponseErrorConfig` from.
|
|
749
|
-
* With plugin-client they come from the user's `importPath` module instead.
|
|
750
|
-
*
|
|
751
|
-
* The result is cached in `memo` (the build's `ctx.memo`) under the client plugin's name and the operation,
|
|
752
|
-
* so several dependents reading the same client plugin for one operation in a single pass
|
|
753
|
-
* (react-query's query/mutation/infinite generators, vue-query, swr, the MCP handler, ...) share
|
|
754
|
-
* one computed result instead of each re-deriving the name and path.
|
|
755
|
-
*
|
|
756
|
-
* `returnType`, `output`, and `group` are the client plugin's options for this operation, after its
|
|
757
|
-
* `override` entries, the same resolution its own generator sees. A dependent's generated call body
|
|
758
|
-
* and import path therefore match the `<op>` actually emitted, even when an `override` changes it.
|
|
759
|
-
*/
|
|
760
|
-
function resolveClientOperation(options) {
|
|
761
|
-
const { clientPlugin, driver, node, root, output, memo } = options;
|
|
762
|
-
if (!clientPlugin) return null;
|
|
763
|
-
return memo(`${clientPlugin.pluginName}:clientOperation:${node.operationId}`, () => {
|
|
764
|
-
const resolver = driver.getResolver(clientPlugin.pluginName);
|
|
765
|
-
const pluginOptions = driver.getPlugin(clientPlugin.pluginName)?.options ?? {};
|
|
766
|
-
const { exclude, include, override } = pluginOptions;
|
|
767
|
-
const operationOptions = Boolean(exclude?.length || include?.length || override?.length) && resolver.default ? resolver.default.options(node, {
|
|
768
|
-
options: pluginOptions,
|
|
769
|
-
exclude,
|
|
770
|
-
include,
|
|
771
|
-
override
|
|
772
|
-
}) : pluginOptions;
|
|
773
|
-
if (!operationOptions) return null;
|
|
774
|
-
const file = resolver.file({
|
|
775
|
-
...operationFileEntry(node, node.operationId),
|
|
776
|
-
root,
|
|
777
|
-
output: operationOptions.output ?? output,
|
|
778
|
-
group: operationOptions.group ?? void 0
|
|
779
|
-
});
|
|
780
|
-
const { importPath } = operationOptions;
|
|
781
|
-
const name = resolver.name(node.operationId);
|
|
782
|
-
return {
|
|
783
|
-
name: resolver.resolveName({
|
|
784
|
-
key: operationKey(node),
|
|
785
|
-
name
|
|
786
|
-
}),
|
|
787
|
-
path: file.path,
|
|
788
|
-
clientPath: importPath === void 0 ? node_path.default.resolve(root, ".kubb/client.ts") : resolveImportPath({
|
|
789
|
-
importPath,
|
|
790
|
-
operationFile: file.path
|
|
791
|
-
}),
|
|
792
|
-
clientPathIsFile: importPath === void 0 || isRelativeImport(importPath),
|
|
793
|
-
returnType: operationOptions.returnType ?? "full"
|
|
794
|
-
};
|
|
795
|
-
});
|
|
796
|
-
}
|
|
797
781
|
// ../../internals/tanstack-query/src/components/HookFile.tsx
|
|
798
782
|
/**
|
|
799
783
|
* Resolves what every TanStack hook file shares: its file, the operation types file and names (`@kubb/plugin-ts`, or
|
|
@@ -812,14 +796,18 @@ function resolveHookFile(node, ctx, options) {
|
|
|
812
796
|
});
|
|
813
797
|
const types = resolveOperationTypes(ctx.driver, resolver.pluginName);
|
|
814
798
|
const tsResolver = types.resolver;
|
|
799
|
+
const headerTypeNames = returnType === "data" || !contractOp.typedHeaders ? [] : getResponseHeadersTypeNames({
|
|
800
|
+
node,
|
|
801
|
+
types: tsResolver
|
|
802
|
+
});
|
|
815
803
|
const file = resolver.file({
|
|
816
804
|
...operationFileEntry(node, name),
|
|
817
805
|
root,
|
|
818
806
|
output,
|
|
819
807
|
group: group ?? void 0
|
|
820
808
|
});
|
|
821
|
-
const fileTs =
|
|
822
|
-
|
|
809
|
+
const fileTs = resolveOperationFile({
|
|
810
|
+
ctx,
|
|
823
811
|
node,
|
|
824
812
|
resolver: tsResolver,
|
|
825
813
|
root,
|
|
@@ -829,6 +817,7 @@ function resolveHookFile(node, ctx, options) {
|
|
|
829
817
|
const importedTypeNames = [
|
|
830
818
|
tsResolver.response.options(node),
|
|
831
819
|
tsResolver.response.responses(node),
|
|
820
|
+
...headerTypeNames,
|
|
832
821
|
...extraTypeNames,
|
|
833
822
|
...resolveOperationTypeNames(node, tsResolver, {
|
|
834
823
|
exclude: [keyTypeName, returnType !== "data" ? tsResolver.response.response(node) : null].filter((name) => Boolean(name)),
|
|
@@ -846,6 +835,7 @@ function resolveHookFile(node, ctx, options) {
|
|
|
846
835
|
tsResolver,
|
|
847
836
|
contractOp,
|
|
848
837
|
importedTypeNames,
|
|
838
|
+
resultTypeName: headerTypeNames.length ? "RequestResultWithHeaders" : "RequestResult",
|
|
849
839
|
returnType,
|
|
850
840
|
banner: resolver.default.banner(ctx.meta, {
|
|
851
841
|
output,
|
|
@@ -863,7 +853,7 @@ function resolveHookFile(node, ctx, options) {
|
|
|
863
853
|
* The `<File>` shell shared by the TanStack hook generators; renders `children` after the imports.
|
|
864
854
|
*/
|
|
865
855
|
function HookFile({ hook, imports, children }) {
|
|
866
|
-
const { file, fileTs, contractOp, importedTypeNames, banner, footer } = hook;
|
|
856
|
+
const { file, fileTs, contractOp, importedTypeNames, resultTypeName, banner, footer } = hook;
|
|
867
857
|
return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx.File, {
|
|
868
858
|
baseName: file.baseName,
|
|
869
859
|
path: file.path,
|
|
@@ -880,7 +870,7 @@ function HookFile({ hook, imports, children }) {
|
|
|
880
870
|
name: [
|
|
881
871
|
"RequestConfig",
|
|
882
872
|
"ResponseErrorConfig",
|
|
883
|
-
|
|
873
|
+
resultTypeName
|
|
884
874
|
],
|
|
885
875
|
root: contractOp.clientPathIsFile ? file.path : void 0,
|
|
886
876
|
path: contractOp.clientPath,
|
|
@@ -956,8 +946,8 @@ function buildGroupedRequestParam(node, options) {
|
|
|
956
946
|
/**
|
|
957
947
|
* Builds the shared `({ path, query, body, headers, cookies }, config = {})` parameter list for a
|
|
958
948
|
* TanStack query-options function. The leading parameter mirrors the client signature, and the
|
|
959
|
-
* trailing `config` is
|
|
960
|
-
*
|
|
949
|
+
* trailing `config` is the client's `Options` minus the request groups and `throwOnError`, which the
|
|
950
|
+
* hook passes itself. Framework plugins wrap the result when needed, for example vue-query applies `MaybeRefOrGetter`.
|
|
961
951
|
*/
|
|
962
952
|
function buildQueryOptionsParams(node, options) {
|
|
963
953
|
const { resolver, memberTypeWrapper } = options;
|
|
@@ -967,7 +957,7 @@ function buildQueryOptionsParams(node, options) {
|
|
|
967
957
|
});
|
|
968
958
|
const configParam = (0, _kubb_plugin_ts.createFunctionParameter)({
|
|
969
959
|
name: "config",
|
|
970
|
-
type: buildClientOptionType(
|
|
960
|
+
type: buildClientOptionType(),
|
|
971
961
|
default: "{}"
|
|
972
962
|
});
|
|
973
963
|
return (0, _kubb_plugin_ts.createFunctionParameters)({ params: [groupedParam, configParam].filter((param) => param !== null) });
|
|
@@ -979,26 +969,30 @@ function buildQueryOptionsParams(node, options) {
|
|
|
979
969
|
* can't flip the query's error semantics. Queries thread the TanStack `signal`; mutations omit it.
|
|
980
970
|
*
|
|
981
971
|
* When `unwrapName` is set, each request group is passed as an explicit member unwrapped through it,
|
|
982
|
-
* used by vue-query to resolve refs and getters with `toValue(...)` at call time.
|
|
972
|
+
* used by vue-query to resolve refs and getters with `toValue(...)` at call time. `pageParam` names the
|
|
973
|
+
* query parameter an infinite query sets from TanStack's `pageParam`.
|
|
983
974
|
*
|
|
984
975
|
* @example
|
|
985
976
|
* ```ts
|
|
986
977
|
* buildClientCall(node, { clientName: 'getPetById', signal: true })
|
|
987
|
-
* // getPetById({
|
|
978
|
+
* // getPetById({ ...config, path, signal: config.signal ?? signal, throwOnError: true })
|
|
988
979
|
* ```
|
|
989
980
|
*/
|
|
990
981
|
function buildClientCall(node, options) {
|
|
991
|
-
const { clientName, signal = false, unwrapName, withContentType = false,
|
|
982
|
+
const { clientName, signal = false, unwrapName, withContentType = false, pageParam } = options;
|
|
992
983
|
const { groups } = getRequestGroupOptionality(node);
|
|
993
984
|
const names = requestGroupOrder.filter((key) => groups[key]);
|
|
994
|
-
const
|
|
985
|
+
const member = (name) => {
|
|
986
|
+
const value = unwrapName ? unwrapName(name) : name;
|
|
987
|
+
if (name === "query" && pageParam) return `query: { ...${value}, ${JSON.stringify(pageParam)}: pageParam }`;
|
|
988
|
+
return unwrapName ? `${name}: ${value}` : name;
|
|
989
|
+
};
|
|
990
|
+
return `${clientName}({ ${[
|
|
995
991
|
"...config",
|
|
996
|
-
...withContentType && hasRequestContentTypeChoice(node) ? ["...variables"] : names.map(
|
|
992
|
+
...withContentType && hasRequestContentTypeChoice(node) ? ["...variables"] : names.map(member),
|
|
997
993
|
signal ? "signal: config.signal ?? signal" : null,
|
|
998
994
|
"throwOnError: true"
|
|
999
|
-
].filter((part) => part !== null)
|
|
1000
|
-
if (withContentType && hasRequestContentTypeChoice(node)) return `${clientName}(${castToClientOptions(`{ ${args.join(", ")} }`, clientName, returnType)})`;
|
|
1001
|
-
return `${clientName}({ ${args.join(", ")} })`;
|
|
995
|
+
].filter((part) => part !== null).join(", ")} })`;
|
|
1002
996
|
}
|
|
1003
997
|
/**
|
|
1004
998
|
* Builds the query/mutation body that resolves a `buildClientCall` expression down to the bare
|
|
@@ -1021,19 +1015,28 @@ function buildCallResultBody(call, options = {}) {
|
|
|
1021
1015
|
if (clientReturnType === "plain") return `return (await ${call}).data`;
|
|
1022
1016
|
return `return ${call}.unwrap()`;
|
|
1023
1017
|
}
|
|
1018
|
+
function buildResultType(node, resolver, typedHeaders) {
|
|
1019
|
+
const headers = typedHeaders ? buildResponseHeadersType({
|
|
1020
|
+
node,
|
|
1021
|
+
types: resolver
|
|
1022
|
+
}) : null;
|
|
1023
|
+
return buildResultTypeRef("RequestResult", resolver.response.responses(node), headers, ["true"]);
|
|
1024
|
+
}
|
|
1024
1025
|
/**
|
|
1025
1026
|
* Builds the `TData` / `TError` type expressions shared by every generated hook, joining the resolved
|
|
1026
1027
|
* success responses into `TData` and wrapping the error responses in `ResponseErrorConfig<...>`.
|
|
1027
|
-
* With `returnType` `'full'`, `TData` is the client's `RequestResult` over the operation's responses record
|
|
1028
|
+
* With `returnType` `'full'`, `TData` is the client's `RequestResult` over the operation's responses record, with the
|
|
1029
|
+
* response headers the operation declares.
|
|
1028
1030
|
*/
|
|
1029
1031
|
function buildResponseTypes(node, resolver, options = {}) {
|
|
1030
|
-
const { returnType = "data" } = options;
|
|
1031
|
-
return resolver.memo(`responseTypes:${returnType}:${node.method}\0${node.path}`, () => {
|
|
1032
|
+
const { returnType = "data", typedHeaders = true } = options;
|
|
1033
|
+
return resolver.memo(`responseTypes:${returnType}:${typedHeaders}:${node.method}\0${node.path}`, () => {
|
|
1032
1034
|
const successNames = resolveSuccessNames(node, resolver);
|
|
1033
|
-
const
|
|
1035
|
+
const bodyName = successNames.length > 0 ? successNames.join(" | ") : resolver.response.response(node);
|
|
1036
|
+
const responseName = hasStreamVariant(node) ? `${bodyName} | ReadableStream<Uint8Array>` : bodyName;
|
|
1034
1037
|
const errorNames = resolveErrorNames(node, resolver);
|
|
1035
1038
|
return {
|
|
1036
|
-
TData: returnType
|
|
1039
|
+
TData: returnType === "data" ? responseName : buildResultType(node, resolver, typedHeaders),
|
|
1037
1040
|
TError: `ResponseErrorConfig<${errorNames.length > 0 ? errorNames.join(" | ") : "Error"}>`
|
|
1038
1041
|
};
|
|
1039
1042
|
});
|
|
@@ -1052,7 +1055,7 @@ function resolveFallbackPageParamType(initialPageParam) {
|
|
|
1052
1055
|
* so callers can reuse it when rewriting the paginated request.
|
|
1053
1056
|
*/
|
|
1054
1057
|
function resolvePageParamType(node, { resolver, initialPageParam, queryParam }) {
|
|
1055
|
-
const firstQueryParam =
|
|
1058
|
+
const firstQueryParam = _kubb_kit.ast.http.groupParameters(node).query[0];
|
|
1056
1059
|
const groupName = firstQueryParam ? resolver.param.query(node, firstQueryParam) : null;
|
|
1057
1060
|
const queryParamsTypeName = groupName !== (firstQueryParam ? resolver.param.name(node, firstQueryParam) : null) ? groupName : null;
|
|
1058
1061
|
const queryParamType = queryParam && queryParamsTypeName ? `${queryParamsTypeName}['${queryParam}']` : null;
|
|
@@ -1155,7 +1158,7 @@ function resolveInfiniteConfig(infinite) {
|
|
|
1155
1158
|
*/
|
|
1156
1159
|
function matchesInfinite(node, infinite) {
|
|
1157
1160
|
if (!infinite.queryParam) return false;
|
|
1158
|
-
return
|
|
1161
|
+
return _kubb_kit.ast.http.groupParameters(node).query.some((param) => param.name.replace(/\?$/, "") === infinite.queryParam);
|
|
1159
1162
|
}
|
|
1160
1163
|
/**
|
|
1161
1164
|
* Warning for an infinite hook that falls back to the built-in page params on a response that
|
|
@@ -1163,8 +1166,8 @@ function matchesInfinite(node, infinite) {
|
|
|
1163
1166
|
*/
|
|
1164
1167
|
function getDefaultPageParamsWarning(node, infinite) {
|
|
1165
1168
|
if (!(infinite.getNextPageParam == null && infinite.getPreviousPageParam == null && infinite.nextParam == null && infinite.previousParam == null && !infinite.cursorParam)) return null;
|
|
1166
|
-
const content =
|
|
1167
|
-
let resolved = (content?.find((item) =>
|
|
1169
|
+
const content = _kubb_kit.ast.http.responses.findPrimary(node)?.content;
|
|
1170
|
+
let resolved = (content?.find((item) => _kubb_kit.ast.mediaType.isJson(item)) ?? content?.[0])?.schema;
|
|
1168
1171
|
while (resolved?.type === "ref" || resolved?.type === "intersection" && resolved.members?.length === 1) resolved = resolved.type === "ref" ? resolved.schema : resolved.members?.[0];
|
|
1169
1172
|
if (!resolved || resolved.type === "array") return null;
|
|
1170
1173
|
return `${node.operationId}: the default infinite page params expect an array response and never end for this one. Set \`infinite.getNextPageParam\` (or \`nextParam\`) to read the next page from the response.`;
|
|
@@ -1247,9 +1250,15 @@ function buildHookParams(node, options) {
|
|
|
1247
1250
|
}
|
|
1248
1251
|
/**
|
|
1249
1252
|
* The `TRequest` type argument of a mutation hook: the options type when the operation takes a request, else `undefined`.
|
|
1253
|
+
* When the variables carry the request media type and the response has several, `contentType` can pick the
|
|
1254
|
+
* response one too, as `{ request, response }`.
|
|
1250
1255
|
*/
|
|
1251
1256
|
function resolveMutationRequestType(node, resolver) {
|
|
1252
|
-
|
|
1257
|
+
if (!buildGroupedRequestParam(node, { resolver })) return "undefined";
|
|
1258
|
+
const optionsName = resolver.response.options(node);
|
|
1259
|
+
const response = getResponseContentTypeInfo(node);
|
|
1260
|
+
if (!hasRequestContentTypeChoice(node) || !response.isMultipleContentTypes) return optionsName;
|
|
1261
|
+
return `${/^[\w$]+$/.test(optionsName) ? optionsName : `(${optionsName})`} & { contentType?: string | { response?: ${response.contentTypeUnion} } }`;
|
|
1253
1262
|
}
|
|
1254
1263
|
/**
|
|
1255
1264
|
* Builds the object literal that unwraps each request group's getter before it reaches `queryKey`/`queryOptions`; `null` without a request group.
|
|
@@ -1263,8 +1272,11 @@ function buildResolvedRequestParams(node) {
|
|
|
1263
1272
|
// ../../internals/tanstack-query/src/components/InfiniteQueryOptions.tsx
|
|
1264
1273
|
const declarationPrinter$6 = (0, _kubb_plugin_ts.functionPrinter)({ mode: "declaration" });
|
|
1265
1274
|
const callPrinter$3 = (0, _kubb_plugin_ts.functionPrinter)({ mode: "call" });
|
|
1266
|
-
function InfiniteQueryOptions({ name, clientName, initialPageParam, hasExplicitInitialPageParam, cursorParam, nextParam, previousParam, getNextPageParam, getPreviousPageParam, node, tsResolver, queryParam, queryKeyName, queryKeyType = "typeof queryKey", memberTypeWrapper, unwrapName, clientReturnType, returnType }) {
|
|
1267
|
-
const { TData: queryFnDataType, TError: errorType } = buildResponseTypes(node, tsResolver, {
|
|
1275
|
+
function InfiniteQueryOptions({ name, clientName, initialPageParam, hasExplicitInitialPageParam, cursorParam, nextParam, previousParam, getNextPageParam, getPreviousPageParam, node, tsResolver, queryParam, queryKeyName, queryKeyType = "typeof queryKey", memberTypeWrapper, unwrapName, clientReturnType, returnType, typedHeaders }) {
|
|
1276
|
+
const { TData: queryFnDataType, TError: errorType } = buildResponseTypes(node, tsResolver, {
|
|
1277
|
+
returnType,
|
|
1278
|
+
typedHeaders
|
|
1279
|
+
});
|
|
1268
1280
|
const dataSuffix = returnType === "data" ? "" : ".data";
|
|
1269
1281
|
const { queryParamsTypeName, pageParamType } = resolvePageParamType(node, {
|
|
1270
1282
|
resolver: tsResolver,
|
|
@@ -1283,10 +1295,12 @@ function InfiniteQueryOptions({ name, clientName, initialPageParam, hasExplicitI
|
|
|
1283
1295
|
memberTypeWrapper
|
|
1284
1296
|
});
|
|
1285
1297
|
const paramsSignature = declarationPrinter$6.print(paramsNode) ?? "";
|
|
1298
|
+
const pageParam = queryParam && queryParamsTypeName ? queryParam : void 0;
|
|
1286
1299
|
const queryFnBody = buildCallResultBody(buildClientCall(node, {
|
|
1287
1300
|
clientName,
|
|
1288
1301
|
signal: true,
|
|
1289
|
-
unwrapName
|
|
1302
|
+
unwrapName,
|
|
1303
|
+
pageParam
|
|
1290
1304
|
}), {
|
|
1291
1305
|
clientReturnType,
|
|
1292
1306
|
returnType
|
|
@@ -1313,12 +1327,7 @@ function InfiniteQueryOptions({ name, clientName, initialPageParam, hasExplicitI
|
|
|
1313
1327
|
getNextPageParamExpr,
|
|
1314
1328
|
getPreviousPageParamExpr
|
|
1315
1329
|
].filter(Boolean);
|
|
1316
|
-
const
|
|
1317
|
-
...(query ?? {}),
|
|
1318
|
-
['${queryParam}']: pageParam as unknown as ${queryParamsTypeName}['${queryParam}'],
|
|
1319
|
-
} as ${queryParamsTypeName}` : "";
|
|
1320
|
-
const queryFnArgs = infiniteOverrideParams ? "{ signal, pageParam }" : "{ signal }";
|
|
1321
|
-
const queryFnStatements = infiniteOverrideParams ? `${infiniteOverrideParams}\n ${queryFnBody}` : queryFnBody;
|
|
1330
|
+
const queryFnArgs = pageParam ? "{ signal, pageParam }" : "{ signal }";
|
|
1322
1331
|
return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Source, {
|
|
1323
1332
|
name,
|
|
1324
1333
|
isExportable: true,
|
|
@@ -1332,7 +1341,7 @@ const queryKey = ${queryKeyName}(${queryKeyParamsCall})
|
|
|
1332
1341
|
return infiniteQueryOptions<${queryFnDataType}, ${errorType}, InfiniteData<${queryFnDataType}>, ${queryKeyType}, ${pageParamType}>({
|
|
1333
1342
|
queryKey,
|
|
1334
1343
|
queryFn: async (${queryFnArgs}) => {
|
|
1335
|
-
${
|
|
1344
|
+
${queryFnBody}
|
|
1336
1345
|
},
|
|
1337
1346
|
${queryOptionsArr.join(",\n ")}
|
|
1338
1347
|
})
|
|
@@ -1403,7 +1412,7 @@ function MutationKey({ name, node, transformer, typeName }) {
|
|
|
1403
1412
|
function createQueryResolver(variant = "") {
|
|
1404
1413
|
return {
|
|
1405
1414
|
name(node) {
|
|
1406
|
-
const name = `use${capitalize(this.name(node.operationId))}${variant}`;
|
|
1415
|
+
const name = `use${_kubb_kit.casing.capitalize(this.name(node.operationId))}${variant}`;
|
|
1407
1416
|
return this.resolveName({
|
|
1408
1417
|
key: operationKey(node, "query", variant, "name"),
|
|
1409
1418
|
name
|
|
@@ -1424,7 +1433,7 @@ function createQueryResolver(variant = "") {
|
|
|
1424
1433
|
});
|
|
1425
1434
|
},
|
|
1426
1435
|
keyTypeName(node) {
|
|
1427
|
-
const name = `${capitalize(this.name(node.operationId))}${variant}QueryKey`;
|
|
1436
|
+
const name = `${_kubb_kit.casing.capitalize(this.name(node.operationId))}${variant}QueryKey`;
|
|
1428
1437
|
return this.resolveName({
|
|
1429
1438
|
key: operationKey(node, "query", variant, "keyTypeName"),
|
|
1430
1439
|
name
|
|
@@ -1445,7 +1454,7 @@ function createQueryResolver(variant = "") {
|
|
|
1445
1454
|
function createMutationResolver() {
|
|
1446
1455
|
return {
|
|
1447
1456
|
name(node) {
|
|
1448
|
-
const name = `use${capitalize(this.name(node.operationId))}`;
|
|
1457
|
+
const name = `use${_kubb_kit.casing.capitalize(this.name(node.operationId))}`;
|
|
1449
1458
|
return this.resolveName({
|
|
1450
1459
|
key: operationKey(node, "mutation", "name"),
|
|
1451
1460
|
name
|
|
@@ -1474,14 +1483,14 @@ const declarationPrinter$4 = (0, _kubb_plugin_ts.functionPrinter)({ mode: "decla
|
|
|
1474
1483
|
*/
|
|
1475
1484
|
const queryKeyTransformer = ({ node, variant }) => {
|
|
1476
1485
|
if (!node.path) return [];
|
|
1477
|
-
const { path, query } =
|
|
1486
|
+
const { path, query } = _kubb_kit.ast.http.groupParameters(node);
|
|
1478
1487
|
const isInfinite = variant === "infiniteQuery" || variant === "suspenseInfiniteQuery";
|
|
1479
1488
|
const urlFields = [`url: '${_kubb_kit.Url.toPath(node.path)}'`];
|
|
1480
1489
|
if (path.length > 0) urlFields.push("params: path");
|
|
1481
1490
|
if (isInfinite) urlFields.push("infinite: true");
|
|
1482
1491
|
const result = [`{ ${urlFields.join(", ")} }`];
|
|
1483
1492
|
if (query.length > 0) result.push("...(query ? [query] : [])");
|
|
1484
|
-
if (
|
|
1493
|
+
if (_kubb_kit.ast.http.requestBody.getSchema(node)) result.push("...(body !== undefined ? [body] : [])");
|
|
1485
1494
|
return result;
|
|
1486
1495
|
};
|
|
1487
1496
|
function QueryKey({ name, node, tsResolver, typeName, transformer, variant = "query", memberTypeWrapper, exportType }) {
|
|
@@ -1565,6 +1574,13 @@ const customHookOptionsFileGenerator = (0, _kubb_kit.defineGenerator)({
|
|
|
1565
1574
|
const relativeToOutput = node_path.default.relative(outputDir, file.path);
|
|
1566
1575
|
if (relativeToOutput === ".." || relativeToOutput.startsWith(`..${node_path.default.sep}`) || node_path.default.isAbsolute(relativeToOutput)) return null;
|
|
1567
1576
|
if (node_fs.default.existsSync(file.path)) return null;
|
|
1577
|
+
const hookOptionsPath = resolver.file({
|
|
1578
|
+
name: hookOptionsName,
|
|
1579
|
+
extname: ".ts",
|
|
1580
|
+
root,
|
|
1581
|
+
output,
|
|
1582
|
+
group: group ?? void 0
|
|
1583
|
+
}).path.replace(/[^/\\]+\.ts$/, `${hookOptionsName}.ts`);
|
|
1568
1584
|
return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx.File, {
|
|
1569
1585
|
baseName: file.baseName,
|
|
1570
1586
|
path: file.path,
|
|
@@ -1581,7 +1597,8 @@ const customHookOptionsFileGenerator = (0, _kubb_kit.defineGenerator)({
|
|
|
1581
1597
|
/* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
|
|
1582
1598
|
name: [hookOptionsName],
|
|
1583
1599
|
root: file.path,
|
|
1584
|
-
path:
|
|
1600
|
+
path: hookOptionsPath,
|
|
1601
|
+
isTypeOnly: true
|
|
1585
1602
|
}),
|
|
1586
1603
|
/* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx.File.Source, {
|
|
1587
1604
|
name,
|
|
@@ -1645,7 +1662,7 @@ const hookOptionsGenerator = (0, _kubb_kit.defineGenerator)({
|
|
|
1645
1662
|
const imports = [];
|
|
1646
1663
|
const hookOptions = {};
|
|
1647
1664
|
for (const node of nodes) {
|
|
1648
|
-
if (!_kubb_kit.ast.
|
|
1665
|
+
if (!_kubb_kit.ast.http.isOperation(node)) continue;
|
|
1649
1666
|
const opOverrides = resolveOperationOverrides(node, override);
|
|
1650
1667
|
const nodeQuery = "query" in opOverrides ? opOverrides.query : query;
|
|
1651
1668
|
const nodeMutation = "mutation" in opOverrides ? opOverrides.mutation : mutation;
|
|
@@ -1768,8 +1785,11 @@ function buildHookTypes({ node, tsResolver, infinite, suspense, TData, TError, q
|
|
|
1768
1785
|
resultType: `${resultTypeName}<TData, ${TError}> & { queryKey: TQueryKey }`
|
|
1769
1786
|
};
|
|
1770
1787
|
}
|
|
1771
|
-
function Query({ name, queryKeyTypeName, queryOptionsName, queryKeyName, node, tsResolver, customOptions, suspense, infinite, returnType }) {
|
|
1772
|
-
const { TData, TError } = buildResponseTypes(node, tsResolver, {
|
|
1788
|
+
function Query({ name, queryKeyTypeName, queryOptionsName, queryKeyName, node, tsResolver, customOptions, suspense, infinite, returnType, typedHeaders }) {
|
|
1789
|
+
const { TData, TError } = buildResponseTypes(node, tsResolver, {
|
|
1790
|
+
returnType,
|
|
1791
|
+
typedHeaders
|
|
1792
|
+
});
|
|
1773
1793
|
const prefix = suspense ? "UseSuspense" : "Use";
|
|
1774
1794
|
const hookName = `${suspense ? "useSuspense" : "use"}${infinite ? "InfiniteQuery" : "Query"}`;
|
|
1775
1795
|
const observerOptionsName = OBSERVER_OPTIONS_NAMES[infinite ? "infinite" : "plain"][suspense ? "suspense" : "standard"];
|
|
@@ -1793,7 +1813,7 @@ function Query({ name, queryKeyTypeName, queryOptionsName, queryKeyName, node, t
|
|
|
1793
1813
|
memberTypeWrapper: maybeValueOrGetter,
|
|
1794
1814
|
optionsType: `{
|
|
1795
1815
|
query?: Partial<${observerOptionsType}> & { client?: QueryClient },
|
|
1796
|
-
client?: ${buildClientOptionType(
|
|
1816
|
+
client?: ${buildClientOptionType()}
|
|
1797
1817
|
}`
|
|
1798
1818
|
});
|
|
1799
1819
|
const paramsSignature = declarationPrinter$3.print(paramsNode) ?? "";
|
|
@@ -1829,8 +1849,11 @@ function Query({ name, queryKeyTypeName, queryOptionsName, queryKeyName, node, t
|
|
|
1829
1849
|
// src/components/QueryOptions.tsx
|
|
1830
1850
|
const declarationPrinter$2 = (0, _kubb_plugin_ts.functionPrinter)({ mode: "declaration" });
|
|
1831
1851
|
const callPrinter$2 = (0, _kubb_plugin_ts.functionPrinter)({ mode: "call" });
|
|
1832
|
-
function QueryOptions({ name, clientName, node, tsResolver, queryKeyName, clientReturnType, returnType }) {
|
|
1833
|
-
const { TData, TError } = buildResponseTypes(node, tsResolver, {
|
|
1852
|
+
function QueryOptions({ name, clientName, node, tsResolver, queryKeyName, clientReturnType, returnType, typedHeaders }) {
|
|
1853
|
+
const { TData, TError } = buildResponseTypes(node, tsResolver, {
|
|
1854
|
+
returnType,
|
|
1855
|
+
typedHeaders
|
|
1856
|
+
});
|
|
1834
1857
|
const queryKeyParamsNode = buildQueryKeyParams(node, { resolver: tsResolver });
|
|
1835
1858
|
const queryKeyParamsCall = callPrinter$2.print(queryKeyParamsNode) ?? "";
|
|
1836
1859
|
const paramsNode = buildQueryOptionsParams(node, { resolver: tsResolver });
|
|
@@ -1883,7 +1906,7 @@ function createQueryGenerator({ name, variant }) {
|
|
|
1883
1906
|
renderer: _kubb_renderer_jsx.jsxRenderer,
|
|
1884
1907
|
match(node, ctx) {
|
|
1885
1908
|
const operationNode = node;
|
|
1886
|
-
if (!_kubb_kit.ast.
|
|
1909
|
+
if (!_kubb_kit.ast.http.isOperation(operationNode)) return false;
|
|
1887
1910
|
const { query, mutation, infinite: infiniteConfig, suspense: suspenseConfig, hooks } = ctx.options;
|
|
1888
1911
|
const { isQuery, isMutation } = classifyOperation(operationNode, {
|
|
1889
1912
|
query,
|
|
@@ -1898,7 +1921,7 @@ function createQueryGenerator({ name, variant }) {
|
|
|
1898
1921
|
return !!infiniteOptions && matchesInfinite(operationNode, infiniteOptions);
|
|
1899
1922
|
},
|
|
1900
1923
|
operation(node, ctx) {
|
|
1901
|
-
if (!_kubb_kit.ast.
|
|
1924
|
+
if (!_kubb_kit.ast.http.isOperation(node)) return null;
|
|
1902
1925
|
const { driver, resolver, root } = ctx;
|
|
1903
1926
|
const { output, query, infinite: infiniteConfig, client, group, customOptions, hooks } = ctx.options;
|
|
1904
1927
|
const infiniteOptions = infinite && infiniteConfig && typeof infiniteConfig === "object" ? infiniteConfig : null;
|
|
@@ -1976,7 +1999,8 @@ function createQueryGenerator({ name, variant }) {
|
|
|
1976
1999
|
hasExplicitInitialPageParam: infiniteOptions.hasExplicitInitialPageParam,
|
|
1977
2000
|
queryParam: infiniteOptions.queryParam,
|
|
1978
2001
|
clientReturnType: contractOp.returnType,
|
|
1979
|
-
returnType: hook.returnType
|
|
2002
|
+
returnType: hook.returnType,
|
|
2003
|
+
typedHeaders: hook.contractOp.typedHeaders
|
|
1980
2004
|
})
|
|
1981
2005
|
] }) : /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
|
|
1982
2006
|
name: ["queryOptions"],
|
|
@@ -1988,7 +2012,8 @@ function createQueryGenerator({ name, variant }) {
|
|
|
1988
2012
|
node,
|
|
1989
2013
|
tsResolver: hook.tsResolver,
|
|
1990
2014
|
clientReturnType: contractOp.returnType,
|
|
1991
|
-
returnType: hook.returnType
|
|
2015
|
+
returnType: hook.returnType,
|
|
2016
|
+
typedHeaders: hook.contractOp.typedHeaders
|
|
1992
2017
|
})] }),
|
|
1993
2018
|
(variant !== "query" || query && hooks) && /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: [
|
|
1994
2019
|
/* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
|
|
@@ -2013,6 +2038,7 @@ function createQueryGenerator({ name, variant }) {
|
|
|
2013
2038
|
tsResolver: hook.tsResolver,
|
|
2014
2039
|
customOptions,
|
|
2015
2040
|
returnType: hook.returnType,
|
|
2041
|
+
typedHeaders: hook.contractOp.typedHeaders,
|
|
2016
2042
|
suspense,
|
|
2017
2043
|
infinite: infiniteOptions ? {
|
|
2018
2044
|
initialPageParam: infiniteOptions.initialPageParam,
|
|
@@ -2047,8 +2073,11 @@ function buildMutationConfigParamsNode(node) {
|
|
|
2047
2073
|
default: "{}"
|
|
2048
2074
|
})] });
|
|
2049
2075
|
}
|
|
2050
|
-
function MutationOptions({ name, clientName, node, tsResolver, mutationKeyName, clientReturnType, returnType }) {
|
|
2051
|
-
const { TData, TError } = buildResponseTypes(node, tsResolver, {
|
|
2076
|
+
function MutationOptions({ name, clientName, node, tsResolver, mutationKeyName, clientReturnType, returnType, typedHeaders }) {
|
|
2077
|
+
const { TData, TError } = buildResponseTypes(node, tsResolver, {
|
|
2078
|
+
returnType,
|
|
2079
|
+
typedHeaders
|
|
2080
|
+
});
|
|
2052
2081
|
const configParamsNode = buildMutationConfigParamsNode(node);
|
|
2053
2082
|
const paramsSignature = declarationPrinter$1.print(configParamsNode) ?? "";
|
|
2054
2083
|
const groupedParam = buildGroupedRequestParam(node, {
|
|
@@ -2057,13 +2086,12 @@ function MutationOptions({ name, clientName, node, tsResolver, mutationKeyName,
|
|
|
2057
2086
|
});
|
|
2058
2087
|
const hasMutationParams = groupedParam !== null;
|
|
2059
2088
|
const groupedParamsNode = (0, _kubb_plugin_ts.createFunctionParameters)({ params: groupedParam ? [groupedParam] : [] });
|
|
2060
|
-
const TRequest =
|
|
2089
|
+
const TRequest = resolveMutationRequestType(node, tsResolver);
|
|
2061
2090
|
const argBindingStr = hasMutationParams ? callPrinter$1.print(groupedParamsNode) ?? "" : "_";
|
|
2062
2091
|
const mutationFnBody = buildCallResultBody(buildClientCall(node, {
|
|
2063
2092
|
clientName,
|
|
2064
2093
|
signal: false,
|
|
2065
|
-
withContentType: true
|
|
2066
|
-
returnType: clientReturnType
|
|
2094
|
+
withContentType: true
|
|
2067
2095
|
}), {
|
|
2068
2096
|
clientReturnType,
|
|
2069
2097
|
returnType
|
|
@@ -2093,8 +2121,11 @@ function MutationOptions({ name, clientName, node, tsResolver, mutationKeyName,
|
|
|
2093
2121
|
const declarationPrinter = (0, _kubb_plugin_ts.functionPrinter)({ mode: "declaration" });
|
|
2094
2122
|
const callPrinter = (0, _kubb_plugin_ts.functionPrinter)({ mode: "call" });
|
|
2095
2123
|
function buildMutationParamsNode(node, options) {
|
|
2096
|
-
const { resolver, returnType } = options;
|
|
2097
|
-
const { TData, TError } = buildResponseTypes(node, resolver, {
|
|
2124
|
+
const { resolver, returnType, typedHeaders } = options;
|
|
2125
|
+
const { TData, TError } = buildResponseTypes(node, resolver, {
|
|
2126
|
+
returnType,
|
|
2127
|
+
typedHeaders
|
|
2128
|
+
});
|
|
2098
2129
|
return buildHookParams(node, {
|
|
2099
2130
|
resolver,
|
|
2100
2131
|
withRequest: false,
|
|
@@ -2109,8 +2140,11 @@ function buildMutationParamsNode(node, options) {
|
|
|
2109
2140
|
}`
|
|
2110
2141
|
});
|
|
2111
2142
|
}
|
|
2112
|
-
function Mutation({ name, mutationOptionsName, node, tsResolver, mutationKeyName, customOptions, returnType }) {
|
|
2113
|
-
const { TData, TError } = buildResponseTypes(node, tsResolver, {
|
|
2143
|
+
function Mutation({ name, mutationOptionsName, node, tsResolver, mutationKeyName, customOptions, returnType, typedHeaders }) {
|
|
2144
|
+
const { TData, TError } = buildResponseTypes(node, tsResolver, {
|
|
2145
|
+
returnType,
|
|
2146
|
+
typedHeaders
|
|
2147
|
+
});
|
|
2114
2148
|
const generics = [
|
|
2115
2149
|
TData,
|
|
2116
2150
|
TError,
|
|
@@ -2122,7 +2156,8 @@ function Mutation({ name, mutationOptionsName, node, tsResolver, mutationKeyName
|
|
|
2122
2156
|
const mutationOptionsParamsCall = callPrinter.print(mutationOptionsConfigNode) ?? "";
|
|
2123
2157
|
const paramsNode = buildMutationParamsNode(node, {
|
|
2124
2158
|
resolver: tsResolver,
|
|
2125
|
-
returnType
|
|
2159
|
+
returnType,
|
|
2160
|
+
typedHeaders
|
|
2126
2161
|
});
|
|
2127
2162
|
const paramsSignature = declarationPrinter.print(paramsNode) ?? "";
|
|
2128
2163
|
return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Source, {
|
|
@@ -2162,7 +2197,7 @@ const mutationGenerator = (0, _kubb_kit.defineGenerator)({
|
|
|
2162
2197
|
renderer: _kubb_renderer_jsx.jsxRenderer,
|
|
2163
2198
|
match(node, ctx) {
|
|
2164
2199
|
const operationNode = node;
|
|
2165
|
-
if (!_kubb_kit.ast.
|
|
2200
|
+
if (!_kubb_kit.ast.http.isOperation(operationNode)) return false;
|
|
2166
2201
|
const { query, mutation } = ctx.options;
|
|
2167
2202
|
return classifyOperation(operationNode, {
|
|
2168
2203
|
query,
|
|
@@ -2170,7 +2205,7 @@ const mutationGenerator = (0, _kubb_kit.defineGenerator)({
|
|
|
2170
2205
|
}).isMutation;
|
|
2171
2206
|
},
|
|
2172
2207
|
operation(node, ctx) {
|
|
2173
|
-
if (!_kubb_kit.ast.
|
|
2208
|
+
if (!_kubb_kit.ast.http.isOperation(node)) return null;
|
|
2174
2209
|
const { driver, resolver, root } = ctx;
|
|
2175
2210
|
const { output, mutation, client, group, customOptions, hooks } = ctx.options;
|
|
2176
2211
|
const importPath = mutation ? mutation.importPath : "@tanstack/react-query";
|
|
@@ -2217,7 +2252,8 @@ const mutationGenerator = (0, _kubb_kit.defineGenerator)({
|
|
|
2217
2252
|
node,
|
|
2218
2253
|
tsResolver,
|
|
2219
2254
|
clientReturnType: contractOp.returnType,
|
|
2220
|
-
returnType: hook.returnType
|
|
2255
|
+
returnType: hook.returnType,
|
|
2256
|
+
typedHeaders: hook.contractOp.typedHeaders
|
|
2221
2257
|
}),
|
|
2222
2258
|
mutation && hooks && /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: [
|
|
2223
2259
|
/* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Import, {
|
|
@@ -2240,7 +2276,8 @@ const mutationGenerator = (0, _kubb_kit.defineGenerator)({
|
|
|
2240
2276
|
node,
|
|
2241
2277
|
tsResolver,
|
|
2242
2278
|
customOptions,
|
|
2243
|
-
returnType: hook.returnType
|
|
2279
|
+
returnType: hook.returnType,
|
|
2280
|
+
typedHeaders: hook.contractOp.typedHeaders
|
|
2244
2281
|
})
|
|
2245
2282
|
] })
|
|
2246
2283
|
]
|
|
@@ -2399,7 +2436,7 @@ const pluginReactQuery = (0, _kubb_kit.defineExtension)({
|
|
|
2399
2436
|
...customOptions
|
|
2400
2437
|
} : null,
|
|
2401
2438
|
hooks,
|
|
2402
|
-
group:
|
|
2439
|
+
group: group ?? null,
|
|
2403
2440
|
exclude,
|
|
2404
2441
|
include,
|
|
2405
2442
|
override,
|