@trpc/tanstack-react-query
Version:
TanStack React Query Integration for tRPC
303 lines • 16.5 kB
text/typescript
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-CIAOgeem.mjs";
import { TRPCClientErrorLike } from "@trpc/client";
import { TRPCError, TRPC_ERROR_CODE_KEY } from "@trpc/server";
import { FetchQueryOptions, GetNextPageParamFunction } from "@tanstack/react-query";
//#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.mts.map