UNPKG

@trpc/tanstack-react-query

Version:

TanStack React Query Integration for tRPC

303 lines • 16.5 kB
import { A as FeatureFlags, F as TRPCInfiniteData, P as ResolverDef, T as UnusedSkipTokenTRPCInfiniteQueryOptionsOut, a as DecorateRouterKeyable, b as UnusedSkipTokenTRPCQueryOptionsIn, i as DecorateQueryProcedure, k as ExtractCursorType, t as DecorateInfiniteQueryProcedure, w as UnusedSkipTokenTRPCInfiniteQueryOptionsIn, x as UnusedSkipTokenTRPCQueryOptionsOut, z as TRPCQueryBaseOptions } from "../createOptionsProxy-DPbXqxn8.cjs"; import { FetchQueryOptions, GetNextPageParamFunction } from "@tanstack/react-query"; import { TRPCClientErrorLike } from "@trpc/client"; import { TRPCError, TRPC_ERROR_CODE_KEY } from "@trpc/server"; //#region src/unstable-handles/entryError.d.ts type ErrorOf<TDef extends ResolverDef> = TRPCClientErrorLike<{ transformer: TDef['transformer']; errorShape: TDef['errorShape']; }>; /** * What `loadHandles()` rejects with when a fetch or ensure entry fails. It * names the entry, and keeps the request's error as `cause`. * @see https://trpc.io/docs/client/tanstack-react-query/handles#errors-ensure */ export declare class TRPCEntryError<TDef extends ResolverDef = ResolverDef> extends Error { /** The entry's key in the object passed to `loadHandles()` */ readonly key: string; /** The procedure's path, such as `post.byId` */ readonly path: string; /** The tRPC error code, such as `NOT_FOUND`, when the error has one */ readonly code: TRPC_ERROR_CODE_KEY | undefined; /** * The request's error: a `TRPCError` on a proxy created with `router`, a * `TRPCClientError` on one created with `client`. */ readonly cause: ErrorOf<TDef> | TRPCError; constructor(opts: { key: string; path: string; code: TRPC_ERROR_CODE_KEY | undefined; cause: ErrorOf<TDef> | TRPCError; }); } //#endregion //#region src/unstable-handles/handles.d.ts declare const handleDef: unique symbol; declare const entryDef: unique symbol; type InfiniteHandleInput<TInput> = TInput extends object ? Omit<TInput, 'cursor' | 'direction'> : TInput; /** * A plain tuple typed with the procedure's input. TanStack Router's serializability check * rejects `unknown` inputs and `DataTag`-ged keys, so handles in `beforeLoad` need this shape. */ type HandleQueryKey<TDef extends ResolverDef, TInput, TType extends 'query' | 'infinite'> = TDef['featureFlags']['keyPrefix'] extends true ? [prefix: string[], path: string[], opts?: { input?: TInput; type?: TType; }] : [path: string[], opts?: { input?: TInput; type?: TType; }]; /** * A serializable reference to a query, from `loadHandles()`. * Pass it to a component and read it with `fromHandle(trpc, handle)`. */ interface TRPCQueryHandle<TDef extends ResolverDef = ResolverDef> { /** * Type-only: never present at runtime. Required, so only * `loadHandles` creates handles. */ readonly [handleDef]: TDef & { kind: 'query'; }; readonly queryKey: HandleQueryKey<TDef, TDef['input'], 'query'>; /** The query's input. The key is absent when the input is `undefined`. */ readonly input: TDef['input']; } /** * A serializable reference to an infinite query, from `loadHandles()`. * Read it with `fromHandle(trpc, handle, { getNextPageParam })`. */ interface TRPCInfiniteQueryHandle<TDef extends ResolverDef = ResolverDef> { /** * Type-only: never present at runtime. Required, so only * `loadHandles` creates handles. */ readonly [handleDef]: TDef & { kind: 'infinite'; }; readonly queryKey: HandleQueryKey<TDef, InfiniteHandleInput<TDef['input']>, 'infinite'>; /** The query's input, without `cursor` and `direction` */ readonly input: InfiniteHandleInput<TDef['input']>; readonly initialCursor?: NonNullable<ExtractCursorType<TDef['input']>> | null; } /** Any query or infinite query handle. */ type AnyTRPCHandle = TRPCQueryHandle<any> | TRPCInfiniteQueryHandle<any>; /** * How `loadHandles` starts an entry's query, named after the * `QueryClient` method it calls: `prefetchQuery`, `fetchQuery` or `ensureQueryData`. */ type TRPCEntryKind = 'prefetch' | 'fetch' | 'ensure'; /** * A query for `loadHandles()` to start, from `prefetchEntry`, `fetchEntry` or * `ensureEntry`. * Creating it starts nothing. */ interface TRPCQueryEntry<TDef extends ResolverDef = ResolverDef, TKind extends TRPCEntryKind = TRPCEntryKind> { /** Type-only: never present at runtime. */ readonly [entryDef]: { def: TDef; kind: TKind; type: 'query'; }; } /** * An infinite query for `loadHandles()` to start, from `prefetchInfiniteEntry`, * `fetchInfiniteEntry` or `ensureInfiniteEntry`. Creating it starts nothing. */ interface TRPCInfiniteQueryEntry<TDef extends ResolverDef = ResolverDef, TKind extends TRPCEntryKind = TRPCEntryKind> { /** Type-only: never present at runtime. */ readonly [entryDef]: { def: TDef; kind: TKind; type: 'infinite'; }; } /** Any query or infinite query entry. */ type AnyTRPCEntry = TRPCQueryEntry<any, any> | TRPCInfiniteQueryEntry<any, any>; type HandleOfEntry<TEntry> = TEntry extends TRPCQueryEntry<infer TDef, any> ? TRPCQueryHandle<TDef> : TEntry extends TRPCInfiniteQueryEntry<infer TDef, any> ? TRPCInfiniteQueryHandle<TDef> : never; type DataOfEntry<TEntry> = TEntry extends TRPCQueryEntry<infer TDef, any> ? TDef['output'] : TEntry extends TRPCInfiniteQueryEntry<infer TDef, any> ? TRPCInfiniteData<TDef['input'], TDef['output']> : never; type HandlesOf<TEntries extends Record<string, AnyTRPCEntry>> = { [TKey in keyof TEntries]: HandleOfEntry<TEntries[TKey]>; }; type DefOfEntry<TEntry> = TEntry extends { readonly [entryDef]: { def: infer TDef extends ResolverDef; }; } ? TDef : never; /** Only fetch and ensure entries are waited for, so only they have data */ type WaitedKey<TEntries, TKey extends keyof TEntries> = TEntries[TKey] extends { readonly [entryDef]: { kind: 'fetch' | 'ensure'; }; } ? TKey : never; type DataOf<TEntries extends Record<string, AnyTRPCEntry>> = { [TKey in keyof TEntries as WaitedKey<TEntries, TKey>]: DataOfEntry<TEntries[TKey]>; }; type ResultsOf<TEntries extends Record<string, AnyTRPCEntry>> = { [TKey in keyof TEntries as WaitedKey<TEntries, TKey>]: TRPCEntryResult<DefOfEntry<TEntries[TKey]>, DataOfEntry<TEntries[TKey]>>; }; /** * What `loadHandlesSettled()` has for a fetch or ensure entry: its data, or * the error it failed with. * @see https://trpc.io/docs/client/tanstack-react-query/handles#errors-as-values */ type TRPCEntryResult<TDef extends ResolverDef, TData> = { readonly status: 'success'; readonly data: TData; } | { readonly status: 'error'; readonly error: TRPCEntryError<TDef>; }; /** * What `loadHandles()` resolves to: `[handles, data]`. `handles` has a handle * for every entry, by the entry's key; return them from the loader. `data` has the data of * every fetch and ensure entry, by the entry's key. * @see https://trpc.io/docs/client/tanstack-react-query/handles#loader-data */ type TRPCLoadedHandles<TEntries extends Record<string, AnyTRPCEntry>> = readonly [handles: HandlesOf<TEntries>, data: DataOf<TEntries>]; /** * What `loadHandlesSettled()` resolves to: `[handles, results]`. `results` * has a `TRPCEntryResult` for every fetch and ensure entry, by the entry's key. * @see https://trpc.io/docs/client/tanstack-react-query/handles#errors-as-values */ type TRPCSettledHandles<TEntries extends Record<string, AnyTRPCEntry>> = readonly [handles: HandlesOf<TEntries>, results: ResultsOf<TEntries>]; /** Options for an entry */ interface TRPCEntryOptions extends Pick<FetchQueryOptions, 'staleTime' | 'retry' | 'retryDelay' | 'gcTime' | 'meta'>, TRPCQueryBaseOptions {} type HandleGetNextPageParam<TDef extends ResolverDef> = GetNextPageParamFunction<NonNullable<ExtractCursorType<TDef['input']>> | null, TDef['output']>; /** * Options for an infinite query entry. Pass `pages` and `getNextPageParam` * to load several pages up front. * @see https://trpc.io/docs/client/tanstack-react-query/handles#infinite-queries */ type TRPCInfiniteEntryOptions<TDef extends ResolverDef> = TRPCEntryOptions & { initialCursor?: NonNullable<ExtractCursorType<TDef['input']>> | null; } & ({ pages?: never; /** * Without it, refetching a cached query with more than one page * fails on the second page. */ getNextPageParam?: HandleGetNextPageParam<TDef>; } | { /** Number of pages to load up front */ pages: number; getNextPageParam: HandleGetNextPageParam<TDef>; }); type EntryArgs<TDef extends ResolverDef> = undefined extends TDef['input'] ? [input?: TDef['input'], opts?: TRPCEntryOptions] : [input: TDef['input'], opts?: TRPCEntryOptions]; /** * The handle type of a query procedure, for typing props. * @example * ```ts * type PostHandle = inferQueryHandle<TRPC['post']['byId']>; * ``` * @see https://trpc.io/docs/client/tanstack-react-query/handles#typing-props */ type inferQueryHandle<TProcedure extends DecorateQueryProcedure<any>> = TProcedure extends DecorateQueryProcedure<infer TDef> ? TRPCQueryHandle<TDef> : never; /** * The handle type of an infinite query procedure, for typing props. * @see https://trpc.io/docs/client/tanstack-react-query/handles#typing-props */ type inferInfiniteQueryHandle<TProcedure extends DecorateInfiniteQueryProcedure<any>> = TProcedure extends DecorateInfiniteQueryProcedure<infer TDef> ? TRPCInfiniteQueryHandle<TDef> : never; /** * Whether `error` is a failed entry from `loadHandles()`. Pass a procedure to * check that the entry was for it, which types `error.cause` with its errors. * @example * ```ts * const [handles] = await loadHandles(trpc, { * post: ensureEntry(trpc.post.byId, { id }), * }).catch((error: unknown) => { * if (isTRPCEntryError(error, trpc.post.byId) && error.code === 'NOT_FOUND') { * throw notFound(); * } * throw error; * }); * ``` * @see https://trpc.io/docs/client/tanstack-react-query/handles#errors-ensure */ export declare function isTRPCEntryError<TDef extends ResolverDef>(error: unknown, procedure: DecorateQueryProcedure<TDef>): error is TRPCEntryError<TDef>; export declare function isTRPCEntryError(error: unknown): error is TRPCEntryError; /** * Starts every entry before it waits for any, so the order of the entries doesn't * matter. Resolves to `[handles, data]` once every fetch and ensure entry has data: * a handle for every entry, and the data of the fetch and ensure entries. Rejects as * soon as a fetch or ensure entry fails. Prefetch entries never make it reject. * * Takes the root of an options proxy, from `createTRPCOptionsProxy` or `useTRPC()`. * Call it in a route loader, a server component or an event handler, not during * render: every render would start the entries again. * @example * ```ts * const [handles, data] = await loadHandles(trpc, { * comments: prefetchInfiniteEntry(trpc.post.comments, { postId: id }), * post: ensureEntry(trpc.post.byId, { id }), * }); * if (!data.post.published) throw notFound(); * return handles; * ``` * @see https://trpc.io/docs/client/tanstack-react-query/handles */ export declare function loadHandles<TFeatureFlags extends FeatureFlags, TEntries extends Record<string, AnyTRPCEntry>>(trpc: DecorateRouterKeyable<TFeatureFlags>, entries: TEntries): Promise<TRPCLoadedHandles<TEntries>>; /** * Like `loadHandles()`, but it waits for every fetch and ensure entry to * settle and never rejects because one failed. Resolves to `[handles, results]`: * `results` has `{ status: 'success', data }` or `{ status: 'error', error }`, * with a `TRPCEntryError`, for every fetch and ensure entry. * * A cancelled query still rejects, as it does with `loadHandles()`. * @example * ```ts * const [handles, results] = await loadHandlesSettled(trpc, { * post: ensureEntry(trpc.post.byId, { id }), * comments: prefetchInfiniteEntry(trpc.post.comments, { postId: id }), * }); * if (results.post.status === 'error') { * if (results.post.error.code === 'NOT_FOUND') throw notFound(); * throw results.post.error; * } * ``` * @see https://trpc.io/docs/client/tanstack-react-query/handles#errors-as-values */ export declare function loadHandlesSettled<TFeatureFlags extends FeatureFlags, TEntries extends Record<string, AnyTRPCEntry>>(trpc: DecorateRouterKeyable<TFeatureFlags>, entries: TEntries): Promise<TRPCSettledHandles<TEntries>>; /** * An entry for `loadHandles()` that starts the query without waiting, like * `queryClient.prefetchQuery`. It never makes the load reject: errors surface where * the handle is read. Creating the entry starts nothing. * @see https://trpc.io/docs/client/tanstack-react-query/handles#prefetch */ export declare function prefetchEntry<TDef extends ResolverDef>(procedure: DecorateQueryProcedure<TDef>, ...args: EntryArgs<TDef>): TRPCQueryEntry<TDef, 'prefetch'>; /** * An entry for `loadHandles()` that waits for fresh data, like `queryClient.fetchQuery`: * cached data is used only if it isn't stale. The load rejects if the request fails. * Creating the entry starts nothing. * @see https://trpc.io/docs/client/tanstack-react-query/handles#fetch */ export declare function fetchEntry<TDef extends ResolverDef>(procedure: DecorateQueryProcedure<TDef>, ...args: EntryArgs<TDef>): TRPCQueryEntry<TDef, 'fetch'>; /** * An entry for `loadHandles()` that uses any cached data, even stale, like * `queryClient.ensureQueryData({ revalidateIfStale: true })`. It fetches and waits only * when the cache has no data, and the load rejects if that request fails. Stale data is * refetched in the background. Creating the entry starts nothing. * @see https://trpc.io/docs/client/tanstack-react-query/handles#ensure */ export declare function ensureEntry<TDef extends ResolverDef>(procedure: DecorateQueryProcedure<TDef>, ...args: EntryArgs<TDef>): TRPCQueryEntry<TDef, 'ensure'>; /** * Like `prefetchEntry`, for an infinite query. Loads the first page unless `pages` is set. * @see https://trpc.io/docs/client/tanstack-react-query/handles#infinite-queries */ export declare function prefetchInfiniteEntry<TDef extends ResolverDef>(procedure: DecorateInfiniteQueryProcedure<TDef>, input: TDef['input'], opts?: TRPCInfiniteEntryOptions<TDef>): TRPCInfiniteQueryEntry<TDef, 'prefetch'>; /** * Like `fetchEntry`, for an infinite query. * @see https://trpc.io/docs/client/tanstack-react-query/handles#infinite-queries */ export declare function fetchInfiniteEntry<TDef extends ResolverDef>(procedure: DecorateInfiniteQueryProcedure<TDef>, input: TDef['input'], opts?: TRPCInfiniteEntryOptions<TDef>): TRPCInfiniteQueryEntry<TDef, 'fetch'>; /** * Like `ensureEntry`, for an infinite query. * @see https://trpc.io/docs/client/tanstack-react-query/handles#infinite-queries */ export declare function ensureInfiniteEntry<TDef extends ResolverDef>(procedure: DecorateInfiniteQueryProcedure<TDef>, input: TDef['input'], opts?: TRPCInfiniteEntryOptions<TDef>): TRPCInfiniteQueryEntry<TDef, 'ensure'>; /** * Options for a handle: the same options `trpc.<path>.queryOptions(input)` or * `trpc.<path>.infiniteQueryOptions(input, opts)` return for the handle's procedure and * input. Pass them to `useQuery`, `useSuspenseQuery`, `useSuspenseInfiniteQuery`, etc. * `trpc` is the proxy or a router on the handle's path, usually `useTRPC()`. * @see https://trpc.io/docs/client/tanstack-react-query/handles#reading-a-handle */ export declare function fromHandle<TDef extends ResolverDef, TData = TDef['output']>(trpc: DecorateRouterKeyable<NoInfer<TDef['featureFlags']>>, handle: TRPCQueryHandle<TDef>, opts?: UnusedSkipTokenTRPCQueryOptionsIn<NoInfer<TDef['output']>, TData, ErrorOf<TDef>, TDef['featureFlags']>): UnusedSkipTokenTRPCQueryOptionsOut<TDef['output'], TData, ErrorOf<TDef>, TDef['featureFlags']>; export declare function fromHandle<TDef extends ResolverDef, TData = TDef['output']>(trpc: DecorateRouterKeyable<NoInfer<TDef['featureFlags']>>, handle: TRPCInfiniteQueryHandle<TDef>, opts: UnusedSkipTokenTRPCInfiniteQueryOptionsIn<TDef['input'], NoInfer<TDef['output']>, TData, ErrorOf<TDef>, TDef['featureFlags']>): UnusedSkipTokenTRPCInfiniteQueryOptionsOut<TDef['input'], TDef['output'], TData, ErrorOf<TDef>, TDef['featureFlags']>; //#endregion export type { AnyTRPCEntry, AnyTRPCHandle, TRPCEntryKind, TRPCEntryOptions, TRPCEntryResult, TRPCInfiniteEntryOptions, TRPCInfiniteQueryEntry, TRPCInfiniteQueryHandle, TRPCLoadedHandles, TRPCQueryEntry, TRPCQueryHandle, TRPCSettledHandles, inferInfiniteQueryHandle, inferQueryHandle }; //# sourceMappingURL=index.d.cts.map