@kubb/plugin-vue-query 5.3.0-canary.20261012T190229 → 5.3.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.d.ts CHANGED
@@ -119,7 +119,51 @@ type Infinite = {
119
119
  * @default 0
120
120
  */
121
121
  initialPageParam?: unknown;
122
+ /**
123
+ * Whether `initialPageParam` was explicitly configured rather than defaulted.
124
+ * When omitted or false, the default previous page threshold remains 1 (legacy 1-based default).
125
+ */
126
+ hasExplicitInitialPageParam?: boolean;
127
+ /**
128
+ * Source of TanStack Query's `getNextPageParam`, inlined verbatim as a function expression. Use it
129
+ * when the next page has to be computed rather than read from a field. Takes precedence over
130
+ * `nextParam` and `cursorParam`.
131
+ *
132
+ * Note: Because functions are inlined verbatim into generated code via `.toString()`, they cannot
133
+ * reference local closures or external variables from the config file.
134
+ *
135
+ * @example
136
+ * `'(lastPage) => (lastPage.hasNext ? lastPage.number + 1 : undefined)'`
137
+ * // or with definePageParam:
138
+ * `definePageParam<MyResponse, number>((lastPage) => (lastPage.hasNext ? lastPage.number + 1 : undefined))`
139
+ */
140
+ getNextPageParam?: string | PageParamFn | null;
141
+ /**
142
+ * Source of TanStack Query's `getPreviousPageParam`, inlined verbatim as a function expression.
143
+ * Takes precedence over `previousParam` and `cursorParam`.
144
+ *
145
+ * Note: Because functions are inlined verbatim into generated code via `.toString()`, they cannot
146
+ * reference local closures or external variables from the config file.
147
+ *
148
+ * @example
149
+ * `'(firstPage) => (firstPage.number > 0 ? firstPage.number - 1 : undefined)'`
150
+ * // or with definePageParam:
151
+ * `definePageParam<MyResponse, number>((firstPage) => (firstPage.number > 0 ? firstPage.number - 1 : undefined))`
152
+ */
153
+ getPreviousPageParam?: string | PageParamFn | null;
122
154
  };
155
+ type PageParamFn<TPage = any, TParam = any> = (page: TPage, allPages: Array<TPage>, pageParam: TParam, allPageParams: Array<TParam>) => TParam | undefined | null;
156
+ //#endregion
157
+ //#region ../../internals/tanstack-query/src/utils.d.ts
158
+ /**
159
+ * Helper to define a typed page param function for `infinite.getNextPageParam` or
160
+ * `infinite.getPreviousPageParam`. Serializes the function to a string for inlining in generated code.
161
+ *
162
+ * Note: Because the function is inlined verbatim into the generated file via `.toString()`,
163
+ * it must be self-contained and cannot reference local closures or external variables from
164
+ * the config file.
165
+ */
166
+ export declare function definePageParam<TPage = any, TParam = any>(fn: PageParamFn<TPage, TParam>): string;
123
167
  //#endregion
124
168
  //#region src/types.d.ts
125
169
  /**
@@ -369,5 +413,5 @@ export declare const pluginVueQuery: import("kubb/kit").PluginFactory<PluginVueQ
369
413
  */
370
414
  export declare const resolverVueQuery: ResolverVueQuery;
371
415
  //#endregion
372
- export { type PluginVueQuery, type ResolverVueQuery, pluginVueQuery as default };
416
+ export { type PageParamFn, type PluginVueQuery, type ResolverVueQuery, pluginVueQuery as default };
373
417
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -322,8 +322,14 @@ function createGroupConfig(group) {
322
322
  };
323
323
  }
324
324
  //#endregion
325
+ //#region kubb-extension.json
326
+ var compatibility = {
327
+ "kubb": ">=5.8.0",
328
+ "node": ">=22"
329
+ };
330
+ //#endregion
325
331
  //#region package.json
326
- var version = "5.3.0-canary.20261012T190229";
332
+ var version = "5.3.1";
327
333
  //#endregion
328
334
  //#region ../../internals/tanstack-query/src/utils.ts
329
335
  /**
@@ -541,22 +547,61 @@ function classifyOperation(node, { query, mutation }) {
541
547
  };
542
548
  }
543
549
  /**
550
+ * Helper to define a typed page param function for `infinite.getNextPageParam` or
551
+ * `infinite.getPreviousPageParam`. Serializes the function to a string for inlining in generated code.
552
+ *
553
+ * Note: Because the function is inlined verbatim into the generated file via `.toString()`,
554
+ * it must be self-contained and cannot reference local closures or external variables from
555
+ * the config file.
556
+ */
557
+ function definePageParam(fn) {
558
+ return fn.toString();
559
+ }
560
+ /**
544
561
  * Applies the shared infinite-query defaults during plugin setup: a falsy value disables infinite
545
562
  * queries, and an object merges over `queryParam: 'id'` and `initialPageParam: 0` with the cursor
546
563
  * paths cleared.
547
564
  */
548
565
  function resolveInfiniteConfig(infinite) {
549
566
  if (!infinite) return false;
567
+ const hasExplicitInitialPageParam = infinite.hasExplicitInitialPageParam ?? infinite.initialPageParam !== void 0;
568
+ const getNextPageParam = infinite.getNextPageParam ? typeof infinite.getNextPageParam === "function" ? infinite.getNextPageParam.toString() : infinite.getNextPageParam : null;
569
+ const getPreviousPageParam = infinite.getPreviousPageParam ? typeof infinite.getPreviousPageParam === "function" ? infinite.getPreviousPageParam.toString() : infinite.getPreviousPageParam : null;
550
570
  return {
551
571
  queryParam: "id",
552
572
  initialPageParam: 0,
573
+ hasExplicitInitialPageParam,
553
574
  cursorParam: null,
554
575
  nextParam: null,
555
576
  previousParam: null,
556
- ...infinite
577
+ getNextPageParam,
578
+ getPreviousPageParam,
579
+ ...infinite,
580
+ ...getNextPageParam ? { getNextPageParam } : {},
581
+ ...getPreviousPageParam ? { getPreviousPageParam } : {}
557
582
  };
558
583
  }
559
584
  /**
585
+ * Whether the infinite hook for `node` should be generated: the operation takes the configured
586
+ * `queryParam`.
587
+ */
588
+ function matchesInfinite(node, infinite) {
589
+ if (!infinite.queryParam) return false;
590
+ return getOperationParameters(node).query.some((param) => param.name.replace(/\?$/, "") === infinite.queryParam);
591
+ }
592
+ /**
593
+ * Warning for an infinite hook that falls back to the built-in page params on a response that
594
+ * isn't an array. Those params only stop on an empty array, so `hasNextPage` never turns false.
595
+ */
596
+ function getDefaultPageParamsWarning(node, infinite) {
597
+ if (!(infinite.getNextPageParam == null && infinite.getPreviousPageParam == null && infinite.nextParam == null && infinite.previousParam == null && !infinite.cursorParam)) return null;
598
+ const content = getPrimarySuccessResponse(node)?.content;
599
+ let resolved = (content?.find((item) => item.contentType?.includes("json")) ?? content?.[0])?.schema;
600
+ while (resolved?.type === "ref" || resolved?.type === "intersection" && resolved.members?.length === 1) resolved = resolved.type === "ref" ? resolved.schema : resolved.members?.[0];
601
+ if (!resolved || resolved.type === "array") return null;
602
+ 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.`;
603
+ }
604
+ /**
560
605
  * The request groups a query key is built from, matching `buildQueryKeyParams`. Headers are
561
606
  * deliberately absent: they do not identify a cache entry, so the key factory takes no parameter
562
607
  * for an operation that only carries headers.
@@ -570,7 +615,7 @@ const queryKeyGroupOrder = [
570
615
  //#region ../../internals/tanstack-query/src/components/InfiniteQueryOptions.tsx
571
616
  const declarationPrinter$7 = functionPrinter({ mode: "declaration" });
572
617
  const callPrinter$4 = functionPrinter({ mode: "call" });
573
- function InfiniteQueryOptions$1({ name, clientName, initialPageParam, cursorParam, nextParam, previousParam, node, tsResolver, queryParam, queryKeyName, queryKeyType = "typeof queryKey", memberTypeWrapper, unwrapName, returnType = "full" }) {
618
+ function InfiniteQueryOptions$1({ name, clientName, initialPageParam, hasExplicitInitialPageParam, cursorParam, nextParam, previousParam, getNextPageParam, getPreviousPageParam, node, tsResolver, queryParam, queryKeyName, queryKeyType = "typeof queryKey", memberTypeWrapper, unwrapName, returnType = "full" }) {
574
619
  const { TData: queryFnDataType, TError: errorType } = buildResponseTypes(node, tsResolver);
575
620
  const { queryParamsTypeName, pageParamType } = resolvePageParamType(node, {
576
621
  resolver: tsResolver,
@@ -594,18 +639,25 @@ function InfiniteQueryOptions$1({ name, clientName, initialPageParam, cursorPara
594
639
  signal: true,
595
640
  unwrapName
596
641
  }), { returnType });
597
- const hasNewParams = nextParam != null || previousParam != null;
598
- const [getNextPageParamExpr, getPreviousPageParamExpr] = (() => {
599
- if (hasNewParams) {
600
- const nextAccessor = nextParam ? getNestedAccessor(nextParam, "lastPage") : null;
601
- const prevAccessor = previousParam ? getNestedAccessor(previousParam, "firstPage") : null;
602
- return [nextAccessor ? `getNextPageParam: (lastPage) => ${nextAccessor}` : null, prevAccessor ? `getPreviousPageParam: (firstPage) => ${prevAccessor}` : null];
603
- }
604
- if (cursorParam) return [`getNextPageParam: (lastPage) => lastPage['${cursorParam}']`, `getPreviousPageParam: (firstPage) => firstPage['${cursorParam}']`];
605
- return ["getNextPageParam: (lastPage, _allPages, lastPageParam) => Array.isArray(lastPage) && lastPage.length === 0 ? undefined : lastPageParam + 1", "getPreviousPageParam: (_firstPage, _allPages, firstPageParam) => firstPageParam <= 1 ? undefined : firstPageParam - 1"];
642
+ const initialPageParamLiteral = typeof initialPageParam === "string" || typeof initialPageParam === "object" && initialPageParam !== null ? JSON.stringify(initialPageParam) : String(initialPageParam === void 0 ? 0 : initialPageParam);
643
+ const serializedGetNextPageParam = typeof getNextPageParam === "function" ? getNextPageParam.toString() : getNextPageParam;
644
+ const getNextPageParamExpr = (() => {
645
+ if (serializedGetNextPageParam) return `getNextPageParam: ${serializedGetNextPageParam}`;
646
+ if (nextParam) return `getNextPageParam: (lastPage) => ${getNestedAccessor(nextParam, "lastPage")}`;
647
+ if (cursorParam) return `getNextPageParam: (lastPage) => lastPage['${cursorParam}']`;
648
+ return "getNextPageParam: (lastPage, _allPages, lastPageParam) => Array.isArray(lastPage) && lastPage.length === 0 ? undefined : lastPageParam + 1";
649
+ })();
650
+ const serializedGetPreviousPageParam = typeof getPreviousPageParam === "function" ? getPreviousPageParam.toString() : getPreviousPageParam;
651
+ const defaultPreviousThreshold = hasExplicitInitialPageParam ? initialPageParamLiteral : "1";
652
+ const getPreviousPageParamExpr = (() => {
653
+ if (serializedGetPreviousPageParam) return `getPreviousPageParam: ${serializedGetPreviousPageParam}`;
654
+ if (previousParam) return `getPreviousPageParam: (firstPage) => ${getNestedAccessor(previousParam, "firstPage")}`;
655
+ if (cursorParam) return `getPreviousPageParam: (firstPage) => firstPage['${cursorParam}']`;
656
+ if (serializedGetNextPageParam || nextParam) return null;
657
+ return `getPreviousPageParam: (_firstPage, _allPages, firstPageParam) => firstPageParam <= ${defaultPreviousThreshold} ? undefined : firstPageParam - 1`;
606
658
  })();
607
659
  const queryOptionsArr = [
608
- `initialPageParam: ${typeof initialPageParam === "string" ? JSON.stringify(initialPageParam) : initialPageParam}`,
660
+ `initialPageParam: ${initialPageParamLiteral}`,
609
661
  getNextPageParamExpr,
610
662
  getPreviousPageParamExpr
611
663
  ].filter(Boolean);
@@ -1195,21 +1247,28 @@ function Query({ name, queryKeyTypeName, queryOptionsName, queryKeyName, node, t
1195
1247
  const infiniteQueryGenerator = defineGenerator({
1196
1248
  name: "vue-query-infinite",
1197
1249
  renderer: jsxRenderer,
1250
+ match(node, ctx) {
1251
+ const operationNode = node;
1252
+ if (!ast.isHttpOperationNode(operationNode)) return false;
1253
+ const { query, mutation, infinite, hooks } = ctx.options;
1254
+ const { isQuery, isMutation } = classifyOperation(operationNode, {
1255
+ query,
1256
+ mutation
1257
+ });
1258
+ const infiniteOptions = infinite && typeof infinite === "object" ? infinite : null;
1259
+ if (!isQuery || isMutation || !infiniteOptions || !hooks) return false;
1260
+ return matchesInfinite(operationNode, infiniteOptions);
1261
+ },
1198
1262
  operation(node, ctx) {
1199
1263
  if (!ast.isHttpOperationNode(node)) return null;
1200
1264
  const { config, driver, resolver, root } = ctx;
1201
- const { output, query, mutation, infinite, client, group, hooks } = ctx.options;
1265
+ const { output, query, infinite, client, group } = ctx.options;
1266
+ const infiniteOptions = infinite && typeof infinite === "object" ? infinite : null;
1267
+ if (!infiniteOptions) return null;
1268
+ const pageParamsWarning = getDefaultPageParamsWarning(node, infiniteOptions);
1269
+ if (pageParamsWarning) ctx.warn(pageParamsWarning);
1202
1270
  const pluginTs = ctx.requirePlugin(pluginTsName);
1203
1271
  const tsResolver = driver.getResolver(pluginTsName);
1204
- const { isQuery, isMutation } = classifyOperation(node, {
1205
- query,
1206
- mutation
1207
- });
1208
- const infiniteOptions = infinite && typeof infinite === "object" ? infinite : null;
1209
- if (!isQuery || isMutation || !infiniteOptions || !hooks) return null;
1210
- const normalizeKey = (key) => key.replace(/\?$/, "");
1211
- const queryParamKeys = getOperationParameters(node).query.map((p) => p.name);
1212
- if (!(infiniteOptions.queryParam ? queryParamKeys.some((k) => normalizeKey(k) === infiniteOptions.queryParam) : false)) return null;
1213
1272
  const importPath = query ? query.importPath : "@tanstack/vue-query";
1214
1273
  const contractOp = resolveClientOperation({
1215
1274
  clientPlugin: { pluginName: client.pluginName },
@@ -1328,7 +1387,10 @@ const infiniteQueryGenerator = defineGenerator({
1328
1387
  cursorParam: infiniteOptions.cursorParam,
1329
1388
  nextParam: infiniteOptions.nextParam,
1330
1389
  previousParam: infiniteOptions.previousParam,
1390
+ getNextPageParam: infiniteOptions.getNextPageParam,
1391
+ getPreviousPageParam: infiniteOptions.getPreviousPageParam,
1331
1392
  initialPageParam: infiniteOptions.initialPageParam,
1393
+ hasExplicitInitialPageParam: infiniteOptions.hasExplicitInitialPageParam,
1332
1394
  queryParam: infiniteOptions.queryParam,
1333
1395
  returnType: contractOp.returnType
1334
1396
  }),
@@ -1711,7 +1773,7 @@ const pluginVueQuery = definePlugin({
1711
1773
  meta: {
1712
1774
  name: pluginVueQueryName,
1713
1775
  version,
1714
- compatibility: { kubb: ">=5.8.0" }
1776
+ compatibility
1715
1777
  },
1716
1778
  dependencies: { [pluginTsName]: {} },
1717
1779
  setup(options) {
@@ -1744,6 +1806,6 @@ const pluginVueQuery = definePlugin({
1744
1806
  }
1745
1807
  });
1746
1808
  //#endregion
1747
- export { pluginVueQuery as default, pluginVueQuery, pluginVueQueryName, resolverVueQuery };
1809
+ export { pluginVueQuery as default, pluginVueQuery, definePageParam, pluginVueQueryName, resolverVueQuery };
1748
1810
 
1749
1811
  //# sourceMappingURL=index.js.map