@kubb/plugin-vue-query 5.3.0-canary.20261012T190229 → 5.3.0

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
@@ -323,7 +323,7 @@ function createGroupConfig(group) {
323
323
  }
324
324
  //#endregion
325
325
  //#region package.json
326
- var version = "5.3.0-canary.20261012T190229";
326
+ var version = "5.3.0";
327
327
  //#endregion
328
328
  //#region ../../internals/tanstack-query/src/utils.ts
329
329
  /**
@@ -541,22 +541,61 @@ function classifyOperation(node, { query, mutation }) {
541
541
  };
542
542
  }
543
543
  /**
544
+ * Helper to define a typed page param function for `infinite.getNextPageParam` or
545
+ * `infinite.getPreviousPageParam`. Serializes the function to a string for inlining in generated code.
546
+ *
547
+ * Note: Because the function is inlined verbatim into the generated file via `.toString()`,
548
+ * it must be self-contained and cannot reference local closures or external variables from
549
+ * the config file.
550
+ */
551
+ function definePageParam(fn) {
552
+ return fn.toString();
553
+ }
554
+ /**
544
555
  * Applies the shared infinite-query defaults during plugin setup: a falsy value disables infinite
545
556
  * queries, and an object merges over `queryParam: 'id'` and `initialPageParam: 0` with the cursor
546
557
  * paths cleared.
547
558
  */
548
559
  function resolveInfiniteConfig(infinite) {
549
560
  if (!infinite) return false;
561
+ const hasExplicitInitialPageParam = infinite.hasExplicitInitialPageParam ?? infinite.initialPageParam !== void 0;
562
+ const getNextPageParam = infinite.getNextPageParam ? typeof infinite.getNextPageParam === "function" ? infinite.getNextPageParam.toString() : infinite.getNextPageParam : null;
563
+ const getPreviousPageParam = infinite.getPreviousPageParam ? typeof infinite.getPreviousPageParam === "function" ? infinite.getPreviousPageParam.toString() : infinite.getPreviousPageParam : null;
550
564
  return {
551
565
  queryParam: "id",
552
566
  initialPageParam: 0,
567
+ hasExplicitInitialPageParam,
553
568
  cursorParam: null,
554
569
  nextParam: null,
555
570
  previousParam: null,
556
- ...infinite
571
+ getNextPageParam,
572
+ getPreviousPageParam,
573
+ ...infinite,
574
+ ...getNextPageParam ? { getNextPageParam } : {},
575
+ ...getPreviousPageParam ? { getPreviousPageParam } : {}
557
576
  };
558
577
  }
559
578
  /**
579
+ * Whether the infinite hook for `node` should be generated: the operation takes the configured
580
+ * `queryParam`.
581
+ */
582
+ function matchesInfinite(node, infinite) {
583
+ if (!infinite.queryParam) return false;
584
+ return getOperationParameters(node).query.some((param) => param.name.replace(/\?$/, "") === infinite.queryParam);
585
+ }
586
+ /**
587
+ * Warning for an infinite hook that falls back to the built-in page params on a response that
588
+ * isn't an array. Those params only stop on an empty array, so `hasNextPage` never turns false.
589
+ */
590
+ function getDefaultPageParamsWarning(node, infinite) {
591
+ if (!(infinite.getNextPageParam == null && infinite.getPreviousPageParam == null && infinite.nextParam == null && infinite.previousParam == null && !infinite.cursorParam)) return null;
592
+ const content = getPrimarySuccessResponse(node)?.content;
593
+ let resolved = (content?.find((item) => item.contentType?.includes("json")) ?? content?.[0])?.schema;
594
+ while (resolved?.type === "ref" || resolved?.type === "intersection" && resolved.members?.length === 1) resolved = resolved.type === "ref" ? resolved.schema : resolved.members?.[0];
595
+ if (!resolved || resolved.type === "array") return null;
596
+ 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.`;
597
+ }
598
+ /**
560
599
  * The request groups a query key is built from, matching `buildQueryKeyParams`. Headers are
561
600
  * deliberately absent: they do not identify a cache entry, so the key factory takes no parameter
562
601
  * for an operation that only carries headers.
@@ -570,7 +609,7 @@ const queryKeyGroupOrder = [
570
609
  //#region ../../internals/tanstack-query/src/components/InfiniteQueryOptions.tsx
571
610
  const declarationPrinter$7 = functionPrinter({ mode: "declaration" });
572
611
  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" }) {
612
+ function InfiniteQueryOptions$1({ name, clientName, initialPageParam, hasExplicitInitialPageParam, cursorParam, nextParam, previousParam, getNextPageParam, getPreviousPageParam, node, tsResolver, queryParam, queryKeyName, queryKeyType = "typeof queryKey", memberTypeWrapper, unwrapName, returnType = "full" }) {
574
613
  const { TData: queryFnDataType, TError: errorType } = buildResponseTypes(node, tsResolver);
575
614
  const { queryParamsTypeName, pageParamType } = resolvePageParamType(node, {
576
615
  resolver: tsResolver,
@@ -594,18 +633,25 @@ function InfiniteQueryOptions$1({ name, clientName, initialPageParam, cursorPara
594
633
  signal: true,
595
634
  unwrapName
596
635
  }), { 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"];
636
+ const initialPageParamLiteral = typeof initialPageParam === "string" || typeof initialPageParam === "object" && initialPageParam !== null ? JSON.stringify(initialPageParam) : String(initialPageParam === void 0 ? 0 : initialPageParam);
637
+ const serializedGetNextPageParam = typeof getNextPageParam === "function" ? getNextPageParam.toString() : getNextPageParam;
638
+ const getNextPageParamExpr = (() => {
639
+ if (serializedGetNextPageParam) return `getNextPageParam: ${serializedGetNextPageParam}`;
640
+ if (nextParam) return `getNextPageParam: (lastPage) => ${getNestedAccessor(nextParam, "lastPage")}`;
641
+ if (cursorParam) return `getNextPageParam: (lastPage) => lastPage['${cursorParam}']`;
642
+ return "getNextPageParam: (lastPage, _allPages, lastPageParam) => Array.isArray(lastPage) && lastPage.length === 0 ? undefined : lastPageParam + 1";
643
+ })();
644
+ const serializedGetPreviousPageParam = typeof getPreviousPageParam === "function" ? getPreviousPageParam.toString() : getPreviousPageParam;
645
+ const defaultPreviousThreshold = hasExplicitInitialPageParam ? initialPageParamLiteral : "1";
646
+ const getPreviousPageParamExpr = (() => {
647
+ if (serializedGetPreviousPageParam) return `getPreviousPageParam: ${serializedGetPreviousPageParam}`;
648
+ if (previousParam) return `getPreviousPageParam: (firstPage) => ${getNestedAccessor(previousParam, "firstPage")}`;
649
+ if (cursorParam) return `getPreviousPageParam: (firstPage) => firstPage['${cursorParam}']`;
650
+ if (serializedGetNextPageParam || nextParam) return null;
651
+ return `getPreviousPageParam: (_firstPage, _allPages, firstPageParam) => firstPageParam <= ${defaultPreviousThreshold} ? undefined : firstPageParam - 1`;
606
652
  })();
607
653
  const queryOptionsArr = [
608
- `initialPageParam: ${typeof initialPageParam === "string" ? JSON.stringify(initialPageParam) : initialPageParam}`,
654
+ `initialPageParam: ${initialPageParamLiteral}`,
609
655
  getNextPageParamExpr,
610
656
  getPreviousPageParamExpr
611
657
  ].filter(Boolean);
@@ -1195,21 +1241,28 @@ function Query({ name, queryKeyTypeName, queryOptionsName, queryKeyName, node, t
1195
1241
  const infiniteQueryGenerator = defineGenerator({
1196
1242
  name: "vue-query-infinite",
1197
1243
  renderer: jsxRenderer,
1244
+ match(node, ctx) {
1245
+ const operationNode = node;
1246
+ if (!ast.isHttpOperationNode(operationNode)) return false;
1247
+ const { query, mutation, infinite, hooks } = ctx.options;
1248
+ const { isQuery, isMutation } = classifyOperation(operationNode, {
1249
+ query,
1250
+ mutation
1251
+ });
1252
+ const infiniteOptions = infinite && typeof infinite === "object" ? infinite : null;
1253
+ if (!isQuery || isMutation || !infiniteOptions || !hooks) return false;
1254
+ return matchesInfinite(operationNode, infiniteOptions);
1255
+ },
1198
1256
  operation(node, ctx) {
1199
1257
  if (!ast.isHttpOperationNode(node)) return null;
1200
1258
  const { config, driver, resolver, root } = ctx;
1201
- const { output, query, mutation, infinite, client, group, hooks } = ctx.options;
1259
+ const { output, query, infinite, client, group } = ctx.options;
1260
+ const infiniteOptions = infinite && typeof infinite === "object" ? infinite : null;
1261
+ if (!infiniteOptions) return null;
1262
+ const pageParamsWarning = getDefaultPageParamsWarning(node, infiniteOptions);
1263
+ if (pageParamsWarning) ctx.warn(pageParamsWarning);
1202
1264
  const pluginTs = ctx.requirePlugin(pluginTsName);
1203
1265
  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
1266
  const importPath = query ? query.importPath : "@tanstack/vue-query";
1214
1267
  const contractOp = resolveClientOperation({
1215
1268
  clientPlugin: { pluginName: client.pluginName },
@@ -1328,7 +1381,10 @@ const infiniteQueryGenerator = defineGenerator({
1328
1381
  cursorParam: infiniteOptions.cursorParam,
1329
1382
  nextParam: infiniteOptions.nextParam,
1330
1383
  previousParam: infiniteOptions.previousParam,
1384
+ getNextPageParam: infiniteOptions.getNextPageParam,
1385
+ getPreviousPageParam: infiniteOptions.getPreviousPageParam,
1331
1386
  initialPageParam: infiniteOptions.initialPageParam,
1387
+ hasExplicitInitialPageParam: infiniteOptions.hasExplicitInitialPageParam,
1332
1388
  queryParam: infiniteOptions.queryParam,
1333
1389
  returnType: contractOp.returnType
1334
1390
  }),
@@ -1744,6 +1800,6 @@ const pluginVueQuery = definePlugin({
1744
1800
  }
1745
1801
  });
1746
1802
  //#endregion
1747
- export { pluginVueQuery as default, pluginVueQuery, pluginVueQueryName, resolverVueQuery };
1803
+ export { pluginVueQuery as default, pluginVueQuery, definePageParam, pluginVueQueryName, resolverVueQuery };
1748
1804
 
1749
1805
  //# sourceMappingURL=index.js.map