@kubb/plugin-react-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/OVERVIEW.md +20 -0
- package/dist/index.cjs +83 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +45 -1
- package/dist/index.js +83 -21
- package/dist/index.js.map +1 -1
- package/kubb-extension.json +218 -0
- package/package.json +12 -9
package/OVERVIEW.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# React Query
|
|
2
|
+
|
|
3
|
+
Generates TanStack Query helpers for React from your OpenAPI spec. By default you get `queryOptions` and `mutationOptions` factories with their cache keys. Set `hooks: true` to also get `useQuery`, `useSuspenseQuery`, `useInfiniteQuery`, and `useMutation` hooks.
|
|
4
|
+
|
|
5
|
+
The plugin ships no HTTP client. Each helper calls a function generated by a client plugin.
|
|
6
|
+
|
|
7
|
+
## Setup
|
|
8
|
+
|
|
9
|
+
- Add `@kubb/plugin-ts` and a client plugin: `@kubb/plugin-fetch` or `@kubb/plugin-axios`.
|
|
10
|
+
- Install `@tanstack/react-query` v5 or higher in the app that uses the generated code.
|
|
11
|
+
- Configure validation on the client plugin, not here.
|
|
12
|
+
|
|
13
|
+
## Options worth knowing
|
|
14
|
+
|
|
15
|
+
- `client` picks `fetch` or `axios` when both client plugins are registered. A single client is detected automatically.
|
|
16
|
+
- `hooks` adds the `use*` hooks on top of the option factories.
|
|
17
|
+
- `suspense` adds `useSuspenseQuery` hooks.
|
|
18
|
+
- `infinite` adds infinite queries for pagination. Set `infinite.queryParam` to the query parameter that holds the page cursor.
|
|
19
|
+
- `query` and `mutation` set which HTTP methods become queries (`GET`) and mutations (`POST`, `PUT`, `PATCH`, `DELETE`), and where the TanStack Query runtime is imported from. Set either to `false` to skip it.
|
|
20
|
+
- `customOptions` routes every hook through your own function that returns extra options.
|
package/dist/index.cjs
CHANGED
|
@@ -350,8 +350,14 @@ function createGroupConfig(group) {
|
|
|
350
350
|
};
|
|
351
351
|
}
|
|
352
352
|
//#endregion
|
|
353
|
+
//#region kubb-extension.json
|
|
354
|
+
var compatibility = {
|
|
355
|
+
"kubb": ">=5.8.0",
|
|
356
|
+
"node": ">=22"
|
|
357
|
+
};
|
|
358
|
+
//#endregion
|
|
353
359
|
//#region package.json
|
|
354
|
-
var version = "5.3.
|
|
360
|
+
var version = "5.3.1";
|
|
355
361
|
//#endregion
|
|
356
362
|
//#region ../../internals/client/src/resolveClient.ts
|
|
357
363
|
/**
|
|
@@ -691,21 +697,60 @@ function classifyOperation(node, { query, mutation }) {
|
|
|
691
697
|
};
|
|
692
698
|
}
|
|
693
699
|
/**
|
|
700
|
+
* Helper to define a typed page param function for `infinite.getNextPageParam` or
|
|
701
|
+
* `infinite.getPreviousPageParam`. Serializes the function to a string for inlining in generated code.
|
|
702
|
+
*
|
|
703
|
+
* Note: Because the function is inlined verbatim into the generated file via `.toString()`,
|
|
704
|
+
* it must be self-contained and cannot reference local closures or external variables from
|
|
705
|
+
* the config file.
|
|
706
|
+
*/
|
|
707
|
+
function definePageParam(fn) {
|
|
708
|
+
return fn.toString();
|
|
709
|
+
}
|
|
710
|
+
/**
|
|
694
711
|
* Applies the shared infinite-query defaults during plugin setup: a falsy value disables infinite
|
|
695
712
|
* queries, and an object merges over `queryParam: 'id'` and `initialPageParam: 0` with the cursor
|
|
696
713
|
* paths cleared.
|
|
697
714
|
*/
|
|
698
715
|
function resolveInfiniteConfig(infinite) {
|
|
699
716
|
if (!infinite) return false;
|
|
717
|
+
const hasExplicitInitialPageParam = infinite.hasExplicitInitialPageParam ?? infinite.initialPageParam !== void 0;
|
|
718
|
+
const getNextPageParam = infinite.getNextPageParam ? typeof infinite.getNextPageParam === "function" ? infinite.getNextPageParam.toString() : infinite.getNextPageParam : null;
|
|
719
|
+
const getPreviousPageParam = infinite.getPreviousPageParam ? typeof infinite.getPreviousPageParam === "function" ? infinite.getPreviousPageParam.toString() : infinite.getPreviousPageParam : null;
|
|
700
720
|
return {
|
|
701
721
|
queryParam: "id",
|
|
702
722
|
initialPageParam: 0,
|
|
723
|
+
hasExplicitInitialPageParam,
|
|
703
724
|
cursorParam: null,
|
|
704
725
|
nextParam: null,
|
|
705
726
|
previousParam: null,
|
|
706
|
-
|
|
727
|
+
getNextPageParam,
|
|
728
|
+
getPreviousPageParam,
|
|
729
|
+
...infinite,
|
|
730
|
+
...getNextPageParam ? { getNextPageParam } : {},
|
|
731
|
+
...getPreviousPageParam ? { getPreviousPageParam } : {}
|
|
707
732
|
};
|
|
708
733
|
}
|
|
734
|
+
/**
|
|
735
|
+
* Whether the infinite hook for `node` should be generated: the operation takes the configured
|
|
736
|
+
* `queryParam`.
|
|
737
|
+
*/
|
|
738
|
+
function matchesInfinite(node, infinite) {
|
|
739
|
+
if (!infinite.queryParam) return false;
|
|
740
|
+
return getOperationParameters(node).query.some((param) => param.name.replace(/\?$/, "") === infinite.queryParam);
|
|
741
|
+
}
|
|
742
|
+
/**
|
|
743
|
+
* Warning for an infinite hook that falls back to the built-in page params on a response that
|
|
744
|
+
* isn't an array. Those params only stop on an empty array, so `hasNextPage` never turns false.
|
|
745
|
+
*/
|
|
746
|
+
function getDefaultPageParamsWarning(node, infinite) {
|
|
747
|
+
if (!(infinite.getNextPageParam == null && infinite.getPreviousPageParam == null && infinite.nextParam == null && infinite.previousParam == null && !infinite.cursorParam)) return null;
|
|
748
|
+
const content = getPrimarySuccessResponse(node)?.content;
|
|
749
|
+
let resolved = (content?.find((item) => item.contentType?.includes("json")) ?? content?.[0])?.schema;
|
|
750
|
+
while (resolved?.type === "ref" || resolved?.type === "intersection" && resolved.members?.length === 1) resolved = resolved.type === "ref" ? resolved.schema : resolved.members?.[0];
|
|
751
|
+
if (!resolved || resolved.type === "array") return null;
|
|
752
|
+
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.`;
|
|
753
|
+
}
|
|
709
754
|
function matchesPattern(node, ov) {
|
|
710
755
|
const { type, pattern } = ov;
|
|
711
756
|
const matches = (value) => typeof pattern === "string" ? value === pattern : pattern.test(value);
|
|
@@ -763,7 +808,7 @@ function buildQueryKeyParams(node, options) {
|
|
|
763
808
|
//#region ../../internals/tanstack-query/src/components/InfiniteQueryOptions.tsx
|
|
764
809
|
const declarationPrinter$7 = (0, _kubb_plugin_ts.functionPrinter)({ mode: "declaration" });
|
|
765
810
|
const callPrinter$3 = (0, _kubb_plugin_ts.functionPrinter)({ mode: "call" });
|
|
766
|
-
function InfiniteQueryOptions({ name, clientName, initialPageParam, cursorParam, nextParam, previousParam, node, tsResolver, queryParam, queryKeyName, queryKeyType = "typeof queryKey", memberTypeWrapper, unwrapName, returnType = "full" }) {
|
|
811
|
+
function InfiniteQueryOptions({ name, clientName, initialPageParam, hasExplicitInitialPageParam, cursorParam, nextParam, previousParam, getNextPageParam, getPreviousPageParam, node, tsResolver, queryParam, queryKeyName, queryKeyType = "typeof queryKey", memberTypeWrapper, unwrapName, returnType = "full" }) {
|
|
767
812
|
const { TData: queryFnDataType, TError: errorType } = buildResponseTypes(node, tsResolver);
|
|
768
813
|
const { queryParamsTypeName, pageParamType } = resolvePageParamType(node, {
|
|
769
814
|
resolver: tsResolver,
|
|
@@ -787,18 +832,25 @@ function InfiniteQueryOptions({ name, clientName, initialPageParam, cursorParam,
|
|
|
787
832
|
signal: true,
|
|
788
833
|
unwrapName
|
|
789
834
|
}), { returnType });
|
|
790
|
-
const
|
|
791
|
-
const
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
835
|
+
const initialPageParamLiteral = typeof initialPageParam === "string" || typeof initialPageParam === "object" && initialPageParam !== null ? JSON.stringify(initialPageParam) : String(initialPageParam === void 0 ? 0 : initialPageParam);
|
|
836
|
+
const serializedGetNextPageParam = typeof getNextPageParam === "function" ? getNextPageParam.toString() : getNextPageParam;
|
|
837
|
+
const getNextPageParamExpr = (() => {
|
|
838
|
+
if (serializedGetNextPageParam) return `getNextPageParam: ${serializedGetNextPageParam}`;
|
|
839
|
+
if (nextParam) return `getNextPageParam: (lastPage) => ${getNestedAccessor(nextParam, "lastPage")}`;
|
|
840
|
+
if (cursorParam) return `getNextPageParam: (lastPage) => lastPage['${cursorParam}']`;
|
|
841
|
+
return "getNextPageParam: (lastPage, _allPages, lastPageParam) => Array.isArray(lastPage) && lastPage.length === 0 ? undefined : lastPageParam + 1";
|
|
842
|
+
})();
|
|
843
|
+
const serializedGetPreviousPageParam = typeof getPreviousPageParam === "function" ? getPreviousPageParam.toString() : getPreviousPageParam;
|
|
844
|
+
const defaultPreviousThreshold = hasExplicitInitialPageParam ? initialPageParamLiteral : "1";
|
|
845
|
+
const getPreviousPageParamExpr = (() => {
|
|
846
|
+
if (serializedGetPreviousPageParam) return `getPreviousPageParam: ${serializedGetPreviousPageParam}`;
|
|
847
|
+
if (previousParam) return `getPreviousPageParam: (firstPage) => ${getNestedAccessor(previousParam, "firstPage")}`;
|
|
848
|
+
if (cursorParam) return `getPreviousPageParam: (firstPage) => firstPage['${cursorParam}']`;
|
|
849
|
+
if (serializedGetNextPageParam || nextParam) return null;
|
|
850
|
+
return `getPreviousPageParam: (_firstPage, _allPages, firstPageParam) => firstPageParam <= ${defaultPreviousThreshold} ? undefined : firstPageParam - 1`;
|
|
799
851
|
})();
|
|
800
852
|
const queryOptionsArr = [
|
|
801
|
-
`initialPageParam: ${
|
|
853
|
+
`initialPageParam: ${initialPageParamLiteral}`,
|
|
802
854
|
getNextPageParamExpr,
|
|
803
855
|
getPreviousPageParamExpr
|
|
804
856
|
].filter(Boolean);
|
|
@@ -1549,8 +1601,7 @@ const infiniteQueryGenerator = (0, kubb_kit.defineGenerator)({
|
|
|
1549
1601
|
});
|
|
1550
1602
|
const infiniteOptions = infinite && typeof infinite === "object" ? infinite : null;
|
|
1551
1603
|
if (!isQuery || isMutation || !infiniteOptions || !hooks) return false;
|
|
1552
|
-
|
|
1553
|
-
return infiniteOptions.queryParam ? queryParamKeys.includes(infiniteOptions.queryParam) || queryParamKeys.includes(`${infiniteOptions.queryParam}?`) : false;
|
|
1604
|
+
return matchesInfinite(operationNode, infiniteOptions);
|
|
1554
1605
|
},
|
|
1555
1606
|
operation(node, ctx) {
|
|
1556
1607
|
if (!kubb_kit.ast.isHttpOperationNode(node)) return null;
|
|
@@ -1560,6 +1611,8 @@ const infiniteQueryGenerator = (0, kubb_kit.defineGenerator)({
|
|
|
1560
1611
|
const tsResolver = driver.getResolver(_kubb_plugin_ts.pluginTsName);
|
|
1561
1612
|
const infiniteOptions = infinite && typeof infinite === "object" ? infinite : null;
|
|
1562
1613
|
if (!infiniteOptions) return null;
|
|
1614
|
+
const pageParamsWarning = getDefaultPageParamsWarning(node, infiniteOptions);
|
|
1615
|
+
if (pageParamsWarning) ctx.warn(pageParamsWarning);
|
|
1563
1616
|
const importPath = query ? query.importPath : "@tanstack/react-query";
|
|
1564
1617
|
const contractOp = resolveClientOperation({
|
|
1565
1618
|
clientPlugin: { pluginName: client.pluginName },
|
|
@@ -1673,7 +1726,10 @@ const infiniteQueryGenerator = (0, kubb_kit.defineGenerator)({
|
|
|
1673
1726
|
cursorParam: infiniteOptions.cursorParam,
|
|
1674
1727
|
nextParam: infiniteOptions.nextParam,
|
|
1675
1728
|
previousParam: infiniteOptions.previousParam,
|
|
1729
|
+
getNextPageParam: infiniteOptions.getNextPageParam,
|
|
1730
|
+
getPreviousPageParam: infiniteOptions.getPreviousPageParam,
|
|
1676
1731
|
initialPageParam: infiniteOptions.initialPageParam,
|
|
1732
|
+
hasExplicitInitialPageParam: infiniteOptions.hasExplicitInitialPageParam,
|
|
1677
1733
|
queryParam: infiniteOptions.queryParam,
|
|
1678
1734
|
returnType: contractOp.returnType
|
|
1679
1735
|
}),
|
|
@@ -2027,8 +2083,7 @@ const suspenseInfiniteQueryGenerator = (0, kubb_kit.defineGenerator)({
|
|
|
2027
2083
|
});
|
|
2028
2084
|
const infiniteOptions = infinite && typeof infinite === "object" ? infinite : null;
|
|
2029
2085
|
if (!isQuery || isMutation || !suspense || !infiniteOptions || !hooks) return false;
|
|
2030
|
-
|
|
2031
|
-
return infiniteOptions.queryParam ? queryParamKeys.includes(infiniteOptions.queryParam) || queryParamKeys.includes(`${infiniteOptions.queryParam}?`) : false;
|
|
2086
|
+
return matchesInfinite(operationNode, infiniteOptions);
|
|
2032
2087
|
},
|
|
2033
2088
|
operation(node, ctx) {
|
|
2034
2089
|
if (!kubb_kit.ast.isHttpOperationNode(node)) return null;
|
|
@@ -2068,12 +2123,16 @@ const suspenseInfiniteQueryGenerator = (0, kubb_kit.defineGenerator)({
|
|
|
2068
2123
|
group: pluginTs.options?.group
|
|
2069
2124
|
})
|
|
2070
2125
|
};
|
|
2071
|
-
const
|
|
2072
|
-
|
|
2126
|
+
const { queryParamsTypeName } = resolvePageParamType(node, {
|
|
2127
|
+
resolver: tsResolver,
|
|
2128
|
+
initialPageParam: infiniteOptions.initialPageParam,
|
|
2129
|
+
queryParam: infiniteOptions.queryParam
|
|
2130
|
+
});
|
|
2073
2131
|
const importedTypeNames = [
|
|
2074
2132
|
tsResolver.response.options(node),
|
|
2075
2133
|
queryParamsTypeName,
|
|
2076
2134
|
...resolveOperationTypeNames(node, tsResolver, {
|
|
2135
|
+
exclude: [queryKeyTypeName],
|
|
2077
2136
|
order: "body-response-first",
|
|
2078
2137
|
includeParams: false
|
|
2079
2138
|
})
|
|
@@ -2147,7 +2206,10 @@ const suspenseInfiniteQueryGenerator = (0, kubb_kit.defineGenerator)({
|
|
|
2147
2206
|
cursorParam: infiniteOptions.cursorParam,
|
|
2148
2207
|
nextParam: infiniteOptions.nextParam,
|
|
2149
2208
|
previousParam: infiniteOptions.previousParam,
|
|
2209
|
+
getNextPageParam: infiniteOptions.getNextPageParam,
|
|
2210
|
+
getPreviousPageParam: infiniteOptions.getPreviousPageParam,
|
|
2150
2211
|
initialPageParam: infiniteOptions.initialPageParam,
|
|
2212
|
+
hasExplicitInitialPageParam: infiniteOptions.hasExplicitInitialPageParam,
|
|
2151
2213
|
queryParam: infiniteOptions.queryParam,
|
|
2152
2214
|
returnType: contractOp.returnType
|
|
2153
2215
|
}),
|
|
@@ -2416,7 +2478,7 @@ const pluginReactQuery = (0, kubb_kit.definePlugin)({
|
|
|
2416
2478
|
meta: {
|
|
2417
2479
|
name: pluginReactQueryName,
|
|
2418
2480
|
version,
|
|
2419
|
-
compatibility
|
|
2481
|
+
compatibility
|
|
2420
2482
|
},
|
|
2421
2483
|
dependencies: { [_kubb_plugin_ts.pluginTsName]: {} },
|
|
2422
2484
|
setup(options) {
|
|
@@ -2455,6 +2517,7 @@ const pluginReactQuery = (0, kubb_kit.definePlugin)({
|
|
|
2455
2517
|
});
|
|
2456
2518
|
//#endregion
|
|
2457
2519
|
exports.default = pluginReactQuery;
|
|
2520
|
+
exports.definePageParam = definePageParam;
|
|
2458
2521
|
exports.pluginReactQuery = pluginReactQuery;
|
|
2459
2522
|
exports.pluginReactQueryName = pluginReactQueryName;
|
|
2460
2523
|
exports.resolverReactQuery = resolverReactQuery;
|