import { type DataTag, type QueryKey, queryOptions, type UseQueryOptions } from "@tanstack/react-query" import type { BetterFetchError, BetterFetchOption } from "better-auth/client" /** * Read-style Better Auth client method (params shape `{ query?, fetchOptions? }`). * Mutation-style endpoints use `AuthMutationFn` / `useAuthMutation` instead. */ export type AuthQueryFn = (params: { query?: Record fetchOptions?: BetterFetchOption }) => Promise<{ data: TData }> export type AuthQueryFnData = TFn extends AuthQueryFn ? TData : never /** * Final query key produced by {@link authQueryOptions}: the caller's prefix * followed by `params.query ?? null`. */ export type AuthQueryKey< TFn extends AuthQueryFn = AuthQueryFn, TPrefix extends QueryKey = QueryKey > = readonly [...TPrefix, NonNullable[0]>["query"] | null] /** * Return type of {@link authQueryOptions}. Named so TypeScript emits * `DataTag<…>` by reference in the `.d.ts`, instead of the raw * `{ [dataTagSymbol]: … }` intersection — which triggers a declaration-emit * bug where `dataTagSymbol` isn't re-imported at the use site and silently * breaks `setQueryData`/`getQueryData` type inference at the consumer. */ export type AuthQueryOptions< TFn extends AuthQueryFn = AuthQueryFn, TPrefix extends QueryKey = QueryKey > = Omit< UseQueryOptions< AuthQueryFnData, BetterFetchError, AuthQueryFnData, AuthQueryKey >, "queryKey" > & { queryKey: DataTag< AuthQueryKey, AuthQueryFnData, BetterFetchError > } /** * Build `queryOptions` for a Better Auth endpoint. * * Injects React Query's `signal` and `throw: true` into `fetchOptions` so the * request is cancelled on unmount and errors surface as `BetterFetchError` * instead of `{ data, error }`. * * @param authFn - Better Auth client method (e.g. `authClient.getSession`). * @param queryKey - Scope prefix for the key. `params.query` is appended automatically. * @param params - Parameters forwarded to `authFn`. */ export function authQueryOptions< TFn extends AuthQueryFn, const TPrefix extends QueryKey >( authFn: TFn, queryKey: TPrefix, params?: Parameters[0] ): AuthQueryOptions { return queryOptions, BetterFetchError>({ queryKey: [...queryKey, params?.query ?? null] as const, queryFn: ({ signal }) => authFn({ ...params, fetchOptions: { ...params?.fetchOptions, signal, throw: true } }) as Promise> }) as AuthQueryOptions }