All files / apps/web/src/hooks use-query-client-helper.ts

95.83% Statements 23/24
66.66% Branches 4/6
100% Functions 11/11
95.83% Lines 23/24

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75                                                    332x 1666x 1666x 327x     327x 327x 380x 380x 2843x 330x 2618x   380x   330x                           380x 372x   380x 8x 138x 8x     8x 8x 8x 8x            
import React from "react";
 
import type {
	DehydratedState,
	QueryClient,
	hashKey,
} from "@tanstack/react-query";
import { dehydrate, useQueryClient } from "@tanstack/react-query";
 
import type { TRPCKey } from "~app/trpc";
import type { ActualCacheAmounts } from "~tests/frontend/fixtures/cache";
import { promisifyEvent } from "~utils/promise";
import { transformer } from "~utils/transformer";
 
declare global {
	// external interface extension
	// oxlint-disable-next-line typescript/consistent-type-definitions
	interface Window {
		getDehydratedCache?: (timeout: number) => Promise<DehydratedState>;
		queryClient?: QueryClient;
		querySubscriptions: Record<string, (() => void)[]>;
		onCacheEvent: (key: TRPCKey, amounts: ActualCacheAmounts) => void;
		hashKey: typeof hashKey;
	}
}
 
export const useQueryClientHelper = () => {
	const queryClient = useQueryClient();
	React.useEffect(() => {
		if (import.meta.env.MODE !== "test") {
			return;
		}
		window.queryClient = queryClient;
		window.getDehydratedCache = async (timeout: number) => {
			const getData = () => {
				const dehydratedData = dehydrate(queryClient, {
					shouldDehydrateQuery: () => true,
					shouldDehydrateMutation: () => true,
					serializeData: (data) => transformer.serialize(data),
				});
				return {
					...dehydratedData,
					mutations: dehydratedData.mutations.map((mutation) => ({
						...mutation,
						state: {
							...mutation.state,
							variables: transformer.serialize(mutation.state.variables),
							data: transformer.serialize(mutation.state.data),
							// `context` carries the live `queryClient`/`trpc` client
							// instances (see use-trpc-mutation-options.ts), which
							// can't cross the page.evaluate() browser/server boundary.
							context: undefined,
						},
					})),
				};
			};
			if (!queryClient.isFetching()) {
				return getData();
			}
			return promisifyEvent((listener, errorListener) => {
				const unsub = queryClient.getQueryCache().subscribe(() => {
					if (!queryClient.isFetching()) {
						listener(getData());
					}
				});
				const timeoutId = setTimeout(errorListener, timeout);
				return () => {
					unsub();
					clearTimeout(timeoutId);
				};
			});
		};
	}, [queryClient]);
};