@ts-rest/react-query
Version:
react-query client integration for @ts-rest
175 lines (170 loc) • 7.32 kB
JavaScript
Object.defineProperty(exports, '__esModule', { value: true });
var reactQuery = require('@tanstack/react-query');
var core = require('@ts-rest/core');
const apiFetcher = (route, clientArgs, abortSignal) => {
return async (requestData) => {
const fetchApiArgs = core.evaluateFetchApiArgs(route, clientArgs, requestData);
const result = await core.fetchApi({
...fetchApiArgs,
fetchOptions: {
...(abortSignal && { signal: abortSignal }),
...fetchApiArgs.fetchOptions,
},
});
// If the response is not a 2XX, throw an error to be handled by react-query
if (core.isErrorResponse(result)) {
throw result;
}
return result;
};
};
function createBaseQueryOptions(route, clientArgs, options) {
const { queryData: queryDataOrFunction, ...rqOptions } = options;
return {
...rqOptions,
queryFn: queryDataOrFunction === reactQuery.skipToken
? reactQuery.skipToken
: (context) => {
const requestData = typeof queryDataOrFunction === 'function'
? queryDataOrFunction(context)
: queryDataOrFunction;
return apiFetcher(route, clientArgs, context === null || context === void 0 ? void 0 : context.signal)(requestData);
},
};
}
const appendTsRestResult = (result, tsResult) => ({
...result,
...tsResult,
});
const tanstackQueryHooks = {
query: {
useQuery: reactQuery.useQuery,
useSuspenseQuery: reactQuery.useSuspenseQuery,
useInfiniteQuery: reactQuery.useInfiniteQuery,
useSuspenseInfiniteQuery: reactQuery.useSuspenseInfiniteQuery,
},
queries: {
useQueries: reactQuery.useQueries,
useSuspenseQueries: reactQuery.useSuspenseQueries,
},
prefetch: {
usePrefetchQuery: reactQuery.usePrefetchQuery,
usePrefetchInfiniteQuery: reactQuery.usePrefetchInfiniteQuery,
},
};
const wrapHooks = (hooks, getWrapper) => {
return Object.fromEntries(Object.entries(hooks).map(([hookName, hook]) => [
hookName,
getWrapper(hook),
]));
};
const wrapAllHooks = (appRoute, clientOptions) => {
return {
...wrapHooks(tanstackQueryHooks.query, (hook) => (options, queryClient) => {
return appendTsRestResult(hook(createBaseQueryOptions(appRoute, clientOptions, options), queryClient), {
contractEndpoint: appRoute,
});
}),
...wrapHooks(tanstackQueryHooks.queries, (hook) => (options, queryClient) => {
return hook({
...options,
queries: options.queries.map((queryOptions) => createBaseQueryOptions(appRoute, clientOptions, queryOptions)),
}, queryClient);
}),
...wrapHooks(tanstackQueryHooks.prefetch, (hook) => (options) => {
return hook(createBaseQueryOptions(appRoute, clientOptions, options));
}),
};
};
const initHooksContainer = (contract, clientOptions) => {
const recursiveInit = (innerRouter) => {
return Object.fromEntries(Object.entries(innerRouter).map(([key, subRouter]) => {
if (core.isAppRoute(subRouter)) {
if (core.isAppRouteQuery(subRouter)) {
return [
key,
{
query: core.getRouteQuery(subRouter, clientOptions),
...wrapAllHooks(subRouter, clientOptions),
},
];
}
else {
return [
key,
{
mutate: core.getRouteQuery(subRouter, clientOptions),
useMutation: (options) => {
return appendTsRestResult(reactQuery.useMutation({
...options,
mutationFn: apiFetcher(subRouter, clientOptions),
}), {
contractEndpoint: subRouter,
});
},
},
];
}
}
else {
return [key, recursiveInit(subRouter)];
}
}));
};
return recursiveInit(contract);
};
const initQueryClient = (contract, clientOptions, queryClient) => {
const recursiveInit = (innerRouter) => {
return Object.fromEntries(Object.entries(innerRouter).map(([key, subRouter]) => {
if (core.isAppRoute(subRouter)) {
if (core.isAppRouteQuery(subRouter)) {
return [
key,
{
getQueryData: (queryKey) => {
return queryClient.getQueryData(queryKey);
},
ensureQueryData: (options) => {
return queryClient.ensureQueryData(createBaseQueryOptions(subRouter, clientOptions, options));
},
getQueriesData: (filters) => {
return queryClient.getQueriesData(filters);
},
setQueryData: (queryKey, updater, options) => {
return queryClient.setQueryData(queryKey, updater, options);
},
setQueriesData: (filters, updater, options) => {
return queryClient.setQueriesData(filters, updater, options);
},
getQueryState: (queryKey) => {
return queryClient.getQueryState(queryKey);
},
fetchQuery: (options) => {
return queryClient.fetchQuery(createBaseQueryOptions(subRouter, clientOptions, options));
},
prefetchQuery: (options) => {
return queryClient.prefetchQuery(createBaseQueryOptions(subRouter, clientOptions, options));
},
fetchInfiniteQuery: (options) => {
return queryClient.fetchInfiniteQuery(createBaseQueryOptions(subRouter, clientOptions, options));
},
prefetchInfiniteQuery: (options) => {
return queryClient.prefetchInfiniteQuery(createBaseQueryOptions(subRouter, clientOptions, options));
},
},
];
}
else {
return [key, undefined];
}
}
else {
return [key, recursiveInit(subRouter)];
}
}));
};
return Object.assign(queryClient, recursiveInit(contract));
};
exports.initHooksContainer = initHooksContainer;
exports.initQueryClient = initQueryClient;
;