@kubb/plugin-react-query 5.7.0-canary.20261025T201031 → 5.8.0-canary.20261025T213931

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -545,7 +545,7 @@ export declare const pluginReactQuery: import("kubb/kit").PluginFactory<PluginRe
545
545
  * `useFooSuspense`, `useFooInfinite`, ...) and its companion helpers
546
546
  * (`fooQueryKey`, `fooQueryOptions`).
547
547
  *
548
- * Functions and files use the built-in camelCase casing; hooks get the `use`
548
+ * Functions use safe camelCase identifiers; hooks get the `use`
549
549
  * prefix; suspense and infinite variants are suffixed with `Suspense`/`Infinite`.
550
550
  *
551
551
  * @example Resolve hook and helper names
package/dist/index.d.ts CHANGED
@@ -545,7 +545,7 @@ export declare const pluginReactQuery: import("kubb/kit").PluginFactory<PluginRe
545
545
  * `useFooSuspense`, `useFooInfinite`, ...) and its companion helpers
546
546
  * (`fooQueryKey`, `fooQueryOptions`).
547
547
  *
548
- * Functions and files use the built-in camelCase casing; hooks get the `use`
548
+ * Functions use safe camelCase identifiers; hooks get the `use`
549
549
  * prefix; suspense and infinite variants are suffixed with `Suspense`/`Infinite`.
550
550
  *
551
551
  * @example Resolve hook and helper names
package/dist/index.js CHANGED
@@ -166,6 +166,22 @@ function getOperationParameters(node) {
166
166
  operationParameterGroupsByNode.set(node, groups);
167
167
  return groups;
168
168
  }
169
+ /**
170
+ * Builds the combined `{ body, path, query, headers }` options object schema for an operation,
171
+ * referencing the already-resolved body and grouped param names. Shared by `@kubb/plugin-ts`'s
172
+ * `Options` type and `@kubb/plugin-zod`'s inferred options schema, so both printers emit the same
173
+ * shape from the same inputs. `primitive: 'object'` is a no-op for the TS printer and tells the Zod
174
+ * printer to emit `z.object(…)` rather than a record.
175
+ */
176
+ function hasRequestContentTypeChoice(node) {
177
+ return (node.requestBody?.content ?? []).filter((entry) => entry.schema).length > 1;
178
+ }
179
+ /**
180
+ * Casts a call argument to the client's parameter type; a `'plain'` client is non-generic.
181
+ */
182
+ function castToClientOptions(callArg, clientName, returnType = "full") {
183
+ return `${callArg} as Parameters<typeof ${clientName}${returnType === "plain" ? "" : "<true>"}>[0]`;
184
+ }
169
185
  function getStatusCodeNumber(statusCode) {
170
186
  const code = Number(statusCode);
171
187
  return Number.isNaN(code) ? null : code;
@@ -277,6 +293,146 @@ function capitalize(text) {
277
293
  return `${text.charAt(0).toUpperCase()}${text.slice(1)}`;
278
294
  }
279
295
  //#endregion
296
+ //#region ../../internals/utils/src/reserved.ts
297
+ /**
298
+ * JavaScript and Java reserved words.
299
+ * @link https://github.com/jonschlinkert/reserved/blob/master/index.js
300
+ */
301
+ const reservedWords = /* @__PURE__ */ new Set([
302
+ "abstract",
303
+ "arguments",
304
+ "await",
305
+ "boolean",
306
+ "break",
307
+ "byte",
308
+ "case",
309
+ "catch",
310
+ "char",
311
+ "class",
312
+ "const",
313
+ "continue",
314
+ "debugger",
315
+ "default",
316
+ "delete",
317
+ "do",
318
+ "double",
319
+ "else",
320
+ "enum",
321
+ "eval",
322
+ "export",
323
+ "extends",
324
+ "false",
325
+ "final",
326
+ "finally",
327
+ "float",
328
+ "for",
329
+ "function",
330
+ "goto",
331
+ "if",
332
+ "implements",
333
+ "import",
334
+ "in",
335
+ "instanceof",
336
+ "int",
337
+ "interface",
338
+ "let",
339
+ "long",
340
+ "native",
341
+ "new",
342
+ "null",
343
+ "package",
344
+ "private",
345
+ "protected",
346
+ "public",
347
+ "return",
348
+ "short",
349
+ "static",
350
+ "super",
351
+ "switch",
352
+ "synchronized",
353
+ "this",
354
+ "throw",
355
+ "throws",
356
+ "transient",
357
+ "true",
358
+ "try",
359
+ "typeof",
360
+ "var",
361
+ "void",
362
+ "volatile",
363
+ "while",
364
+ "with",
365
+ "yield",
366
+ "Array",
367
+ "Date",
368
+ "hasOwnProperty",
369
+ "Infinity",
370
+ "isFinite",
371
+ "isNaN",
372
+ "isPrototypeOf",
373
+ "length",
374
+ "Math",
375
+ "name",
376
+ "NaN",
377
+ "Number",
378
+ "Object",
379
+ "prototype",
380
+ "String",
381
+ "toString",
382
+ "undefined",
383
+ "valueOf"
384
+ ]);
385
+ /**
386
+ * Returns `true` when `name` is a syntactically valid JavaScript variable name.
387
+ *
388
+ * @example
389
+ * ```ts
390
+ * isValidVarName('status') // true
391
+ * isValidVarName('class') // false (reserved word)
392
+ * isValidVarName('42foo') // false (starts with digit)
393
+ * ```
394
+ */
395
+ function isValidVarName(name) {
396
+ if (!name || reservedWords.has(name)) return false;
397
+ return isIdentifier(name);
398
+ }
399
+ /**
400
+ * Returns `name` when it's a syntactically valid JavaScript variable name,
401
+ * otherwise prefixes it with `_` so the result is a valid identifier.
402
+ *
403
+ * Useful for sanitizing OpenAPI schema names or operation IDs that start with
404
+ * a digit (e.g. `409`, `504AccountCancel`) before using them as exported
405
+ * variable, type, or function names.
406
+ *
407
+ * @example
408
+ * ```ts
409
+ * ensureValidVarName('409') // '_409'
410
+ * ensureValidVarName('504AccountCancel') // '_504AccountCancel'
411
+ * ensureValidVarName('Pet') // 'Pet'
412
+ * ensureValidVarName('class') // '_class'
413
+ * ```
414
+ */
415
+ function ensureValidVarName(name) {
416
+ if (!name || isValidVarName(name)) return name;
417
+ return `_${name}`;
418
+ }
419
+ /**
420
+ * Returns `true` when `name` is syntactically a valid identifier, ignoring reserved words.
421
+ *
422
+ * Reserved words and globals (`class`, `name`, `Date`, …) are valid as bare object-literal keys
423
+ * even though they are not valid variable names, so use this (not {@link isValidVarName}) when
424
+ * deciding whether an object key needs quoting.
425
+ *
426
+ * @example
427
+ * ```ts
428
+ * isIdentifier('name') // true
429
+ * isIdentifier('x-total')// false
430
+ * ```
431
+ */
432
+ function isIdentifier(name) {
433
+ return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
434
+ }
435
+ //#endregion
280
436
  //#region ../../internals/utils/src/strings.ts
281
437
  /**
282
438
  * Renders a dotted path or string array as an optional-chaining accessor expression rooted at
@@ -294,6 +450,11 @@ function getNestedAccessor(param, accessor) {
294
450
  return `${accessor}?.['${`${parts.join("']?.['")}']`}`;
295
451
  }
296
452
  //#endregion
453
+ //#region ../../internals/shared/src/resolver.ts
454
+ function resolveOperationName(name) {
455
+ return ensureValidVarName(camelCase(name));
456
+ }
457
+ //#endregion
297
458
  //#region ../../internals/shared/src/group.ts
298
459
  /**
299
460
  * Builds the `group` config a Kubb plugin passes to `ctx.setOptions`, applying the
@@ -332,7 +493,7 @@ var compatibility = {
332
493
  };
333
494
  //#endregion
334
495
  //#region package.json
335
- var version = "5.7.0-canary.20261025T201031";
496
+ var version = "5.8.0-canary.20261025T213931";
336
497
  //#endregion
337
498
  //#region ../../internals/client/src/resolveOperationTypes.ts
338
499
  /**
@@ -688,7 +849,7 @@ function maybeValueOrGetter(type) {
688
849
  * `MaybeRefOrGetter` per group.
689
850
  */
690
851
  function buildGroupedRequestParam(node, options) {
691
- const { resolver, keys = requestGroupOrder, memberTypeWrapper } = options;
852
+ const { resolver, keys = requestGroupOrder, memberTypeWrapper, withContentType = false } = options;
692
853
  const { groups, hasRequiredPath, hasRequiredQuery, hasRequiredHeader } = getRequestGroupOptionality(node);
693
854
  const names = keys.filter((key) => groups[key]);
694
855
  if (names.length === 0) return null;
@@ -700,6 +861,11 @@ function buildGroupedRequestParam(node, options) {
700
861
  };
701
862
  const isOptional = names.every((name) => !requiredByGroup[name]);
702
863
  const optionsName = resolver.response.options(node);
864
+ if (withContentType && hasRequestContentTypeChoice(node)) return createFunctionParameter({
865
+ name: "variables",
866
+ type: optionsName,
867
+ optional: false
868
+ });
703
869
  const omittedKeys = requestGroupOrder.filter((key) => !keys.includes(key));
704
870
  const optionsType = omittedKeys.length > 0 ? `Omit<${optionsName}, ${omittedKeys.map((key) => `'${key}'`).join(" | ")}>` : optionsName;
705
871
  if (memberTypeWrapper) {
@@ -757,14 +923,17 @@ function buildQueryOptionsParams(node, options) {
757
923
  * ```
758
924
  */
759
925
  function buildClientCall(node, options) {
760
- const { clientName, signal = false, unwrapName } = options;
926
+ const { clientName, signal = false, unwrapName, withContentType = false, returnType = "full" } = options;
761
927
  const { groups } = getRequestGroupOptionality(node);
762
- return `${clientName}({ ${[
928
+ const names = requestGroupOrder.filter((key) => groups[key]);
929
+ const args = [
763
930
  "...config",
764
- ...requestGroupOrder.filter((key) => groups[key]).map((name) => unwrapName ? `${name}: ${unwrapName(name)}` : name),
931
+ ...withContentType && hasRequestContentTypeChoice(node) ? ["...variables"] : names.map((name) => unwrapName ? `${name}: ${unwrapName(name)}` : name),
765
932
  signal ? "signal: config.signal ?? signal" : null,
766
933
  "throwOnError: true"
767
- ].filter((part) => part !== null).join(", ")} })`;
934
+ ].filter((part) => part !== null);
935
+ if (withContentType && hasRequestContentTypeChoice(node)) return `${clientName}(${castToClientOptions(`{ ${args.join(", ")} }`, clientName, returnType)})`;
936
+ return `${clientName}({ ${args.join(", ")} })`;
768
937
  }
769
938
  /**
770
939
  * Builds the query/mutation body that resolves a `buildClientCall` expression down to the bare
@@ -1843,14 +2012,19 @@ function MutationOptions({ name, clientName, node, tsResolver, mutationKeyName,
1843
2012
  const { TData, TError } = buildResponseTypes(node, tsResolver);
1844
2013
  const configParamsNode = buildMutationConfigParamsNode(node);
1845
2014
  const paramsSignature = declarationPrinter$1.print(configParamsNode) ?? "";
1846
- const groupedParam = buildGroupedRequestParam(node, { resolver: tsResolver });
2015
+ const groupedParam = buildGroupedRequestParam(node, {
2016
+ resolver: tsResolver,
2017
+ withContentType: true
2018
+ });
1847
2019
  const hasMutationParams = groupedParam !== null;
1848
2020
  const groupedParamsNode = createFunctionParameters({ params: groupedParam ? [groupedParam] : [] });
1849
2021
  const TRequest = hasMutationParams ? tsResolver.response.options(node) : "undefined";
1850
2022
  const argBindingStr = hasMutationParams ? callPrinter$1.print(groupedParamsNode) ?? "" : "_";
1851
2023
  const mutationFnBody = buildCallResultBody(buildClientCall(node, {
1852
2024
  clientName,
1853
- signal: false
2025
+ signal: false,
2026
+ withContentType: true,
2027
+ returnType
1854
2028
  }), { returnType });
1855
2029
  return /* @__PURE__ */ jsx(File.Source, {
1856
2030
  name,
@@ -2071,7 +2245,7 @@ const suspenseQueryGenerator = createQueryGenerator({
2071
2245
  * `useFooSuspense`, `useFooInfinite`, ...) and its companion helpers
2072
2246
  * (`fooQueryKey`, `fooQueryOptions`).
2073
2247
  *
2074
- * Functions and files use the built-in camelCase casing; hooks get the `use`
2248
+ * Functions use safe camelCase identifiers; hooks get the `use`
2075
2249
  * prefix; suspense and infinite variants are suffixed with `Suspense`/`Infinite`.
2076
2250
  *
2077
2251
  * @example Resolve hook and helper names
@@ -2086,6 +2260,7 @@ const suspenseQueryGenerator = createQueryGenerator({
2086
2260
  */
2087
2261
  const resolverReactQuery = createResolver({
2088
2262
  pluginName: "plugin-react-query",
2263
+ name: resolveOperationName,
2089
2264
  query: createQueryResolver(),
2090
2265
  suspenseQuery: createQueryResolver("Suspense"),
2091
2266
  infiniteQuery: createQueryResolver("Infinite"),