@ts-rest/react-query
Version:
react-query client integration for @ts-rest
185 lines (180 loc) • 8.73 kB
JavaScript
Object.defineProperty(exports, '__esModule', { value: true });
var reactQuery = require('@tanstack/react-query');
var core = require('@ts-rest/core');
var react = require('react');
const queryFn = (route, clientArgs, args) => {
return async (queryFnContext) => {
const fetchApiArgs = core.evaluateFetchApiArgs(route, clientArgs, args);
const result = await core.fetchApi({
...fetchApiArgs,
fetchOptions: {
...((queryFnContext === null || queryFnContext === void 0 ? void 0 : queryFnContext.signal) && { signal: queryFnContext.signal }),
...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;
};
};
const getRouteUseQuery = (route, clientArgs) => {
return (queryKey, args, options) => {
const dataFn = queryFn(route, clientArgs, args);
return reactQuery.useQuery({ queryKey, queryFn: dataFn, ...options });
};
};
const getRouteUseQueries = (route, clientArgs) => {
return (args) => {
const queries = args.queries.map((fullQueryArgs) => {
const { credentials, queryKey, retry, ...queryArgs } = fullQueryArgs;
const dataFn = queryFn(route, clientArgs, queryArgs);
return {
queryFn: dataFn,
...fullQueryArgs,
};
});
return reactQuery.useQueries({ queries, context: args.context });
};
};
const getRouteUseInfiniteQuery = (route, clientArgs) => {
return (queryKey, argsMapper, options) => {
const dataFn = async (context) => {
const resultingQueryArgs = argsMapper(context);
const innerDataFn = queryFn(route, clientArgs, resultingQueryArgs);
return innerDataFn(undefined);
};
return reactQuery.useInfiniteQuery({ queryKey, queryFn: dataFn, ...options });
};
};
const getRouteUseMutation = (route, clientArgs) => {
return (options) => {
const mutationFunction = async (args) => {
const dataFn = queryFn(route, clientArgs, args);
return dataFn(undefined);
};
return reactQuery.useMutation({
mutationFn: mutationFunction,
...options,
});
};
};
const ClientParameters = Symbol('ClientParameters');
const initQueryClient = (router, clientArgs) => {
const recursiveInit = (innerRouter) => {
return Object.fromEntries(Object.entries(innerRouter).map(([key, subRouter]) => {
if (core.isAppRoute(subRouter)) {
return [
key,
{
query: core.getRouteQuery(subRouter, clientArgs),
mutation: core.getRouteQuery(subRouter, clientArgs),
useQuery: getRouteUseQuery(subRouter, clientArgs),
useQueries: getRouteUseQueries(subRouter, clientArgs),
useInfiniteQuery: getRouteUseInfiniteQuery(subRouter, clientArgs),
useMutation: getRouteUseMutation(subRouter, clientArgs),
fetchQuery: (queryClient, queryKey, args, options) => {
const dataFn = queryFn(subRouter, clientArgs, args);
return queryClient.fetchQuery({
queryKey,
queryFn: dataFn,
...options,
});
},
fetchInfiniteQuery: (queryClient, queryKey, argsMapper, options) => {
return queryClient.fetchInfiniteQuery({
queryKey,
queryFn: async (context) => {
const resultingQueryArgs = argsMapper(context);
const innerDataFn = queryFn(subRouter, clientArgs, resultingQueryArgs);
return innerDataFn(undefined);
},
...options,
});
},
prefetchQuery: (queryClient, queryKey, args, options) => {
const dataFn = queryFn(subRouter, clientArgs, args);
return queryClient.prefetchQuery({
queryKey,
queryFn: dataFn,
...options,
});
},
prefetchInfiniteQuery: (queryClient, queryKey, argsMapper, options) => {
return queryClient.prefetchInfiniteQuery({
queryKey,
queryFn: async (context) => {
const resultingQueryArgs = argsMapper(context);
const innerDataFn = queryFn(subRouter, clientArgs, resultingQueryArgs);
return innerDataFn(undefined);
},
...options,
});
},
getQueryData: (queryClient, queryKey, filters) => {
return queryClient.getQueryData(queryKey, filters);
},
ensureQueryData: (queryClient, queryKey, args, options) => {
const dataFn = queryFn(subRouter, clientArgs, args);
return queryClient.ensureQueryData({
queryKey,
queryFn: dataFn,
...options,
});
},
getQueriesData: (queryClient, filters) => {
return queryClient.getQueriesData(filters);
},
setQueryData: (queryClient, queryKey, updater) => {
return queryClient.setQueryData(queryKey, updater);
},
},
];
}
else {
return [key, recursiveInit(subRouter)];
}
}));
};
return {
...recursiveInit(router),
[ClientParameters]: {
router,
clientArgs,
},
};
};
const useTsRestQueryClient = (client) => {
// @ts-expect-error - hidden symbol, so we can refetch the original client router and clientArgs
const { router } = client[ClientParameters];
const queryClient = reactQuery.useQueryClient();
const recursiveInit = (innerRouter, innerClient) => {
return Object.fromEntries(Object.entries(innerRouter).map(([key, subRouter]) => {
if (core.isAppRoute(subRouter)) {
const routeFunctions = innerClient[key];
return [
key,
{
...routeFunctions,
fetchQuery: (queryKey, args, options) => routeFunctions.fetchQuery(queryClient, queryKey, args, options),
fetchInfiniteQuery: (queryKey, argsMapper, options) => routeFunctions.fetchInfiniteQuery(queryClient, queryKey, argsMapper, options),
prefetchQuery: (queryKey, args, options) => routeFunctions.prefetchQuery(queryClient, queryKey, args, options),
prefetchInfiniteQuery: (queryKey, argsMapper, options) => routeFunctions.prefetchInfiniteQuery(queryClient, queryKey, argsMapper, options),
getQueryData: (queryKey, filters) => routeFunctions.getQueryData(queryClient, queryKey, filters),
ensureQueryData: (queryKey, args, options) => routeFunctions.ensureQueryData(queryClient, queryKey, args, options),
getQueriesData: (filters) => routeFunctions.getQueriesData(queryClient, filters),
setQueryData: (queryKey, updater) => routeFunctions.setQueryData(queryClient, queryKey, updater),
},
];
}
else {
return [key, recursiveInit(subRouter, innerClient[key])];
}
}));
};
return react.useMemo(() => recursiveInit(router, client), [client]);
};
exports.initQueryClient = initQueryClient;
exports.useTsRestQueryClient = useTsRestQueryClient;
;