import { organizationPlugin, organizationQueryKeys } from "@better-auth-ui/core/plugins" import { type DataTag, type QueryClient, queryOptions, skipToken, useQuery } from "@tanstack/react-query" import type { BetterFetchError } from "better-auth/react" import { useAuthPlugin } from "../../hooks/use-auth-plugin" import type { OrganizationAuthClient } from "../../lib/auth-client" import { useSession } from "../auth/session-query" import type { FullOrganizationParams } from "./full-organization-query" import type { ListOrganization } from "./list-organizations-query" // The active-organization cache holds a `ListOrganization`-shaped value even // though we fetch via `getFullOrganization`. The `members`/`invitations` // fields are intentionally discarded by the `as Promise` cast in // `queryFn` below so that `setActive`'s optimistic update — which can only // produce a list-shaped org — never corrupts a full-detail cache entry. // See `organizationQueryKeys.activeOrganization` for the rationale. export type ActiveOrganizationData< TAuthClient extends OrganizationAuthClient = OrganizationAuthClient > = ListOrganization export type ActiveOrganizationParams< TAuthClient extends OrganizationAuthClient = OrganizationAuthClient > = FullOrganizationParams export type ActiveOrganizationOptions< TAuthClient extends OrganizationAuthClient = OrganizationAuthClient > = Omit< ReturnType>, "queryKey" | "queryFn" > export function activeOrganizationOptions< TAuthClient extends OrganizationAuthClient >( authClient: TAuthClient, userId: string | undefined, params?: ActiveOrganizationParams ) { type TData = ActiveOrganizationData const queryKey = organizationQueryKeys.activeOrganization( userId, params?.query ) const options = queryOptions( { queryKey, queryFn: ({ signal }) => authClient.organization.getFullOrganization({ ...params, fetchOptions: { ...params?.fetchOptions, signal, throw: true } }) as Promise } ) return options as typeof options & { queryKey: DataTag } } export const ensureActiveOrganization = < TAuthClient extends OrganizationAuthClient >( queryClient: QueryClient, authClient: TAuthClient, userId: string | undefined, params?: ActiveOrganizationParams ) => queryClient.ensureQueryData( activeOrganizationOptions(authClient, userId, params) ) export const prefetchActiveOrganization = < TAuthClient extends OrganizationAuthClient >( queryClient: QueryClient, authClient: TAuthClient, userId: string | undefined, params?: ActiveOrganizationParams ) => queryClient.prefetchQuery( activeOrganizationOptions(authClient, userId, params) ) export const fetchActiveOrganization = < TAuthClient extends OrganizationAuthClient >( queryClient: QueryClient, authClient: TAuthClient, userId: string | undefined, params?: ActiveOrganizationParams ) => queryClient.fetchQuery(activeOrganizationOptions(authClient, userId, params)) export type UseActiveOrganizationOptions< TAuthClient extends OrganizationAuthClient > = ActiveOrganizationOptions & ActiveOrganizationParams export function useActiveOrganization< TAuthClient extends OrganizationAuthClient >( authClient: TAuthClient, options: UseActiveOrganizationOptions = {}, queryClient?: QueryClient ) { const { data: session } = useSession(authClient, undefined, queryClient) const userId = session?.user.id const { slug } = useAuthPlugin(organizationPlugin) const { query, fetchOptions, ...queryOptions } = options const baseOptions = activeOrganizationOptions(authClient, userId, { fetchOptions, query: slug ? { organizationSlug: slug } : query }) return useQuery( { ...queryOptions, ...baseOptions, queryFn: slug === null ? async () => null : userId ? baseOptions.queryFn : skipToken }, queryClient ) }