import type { SeamActionAttemptFailedError, SeamActionAttemptTimeoutError, SeamHttpApiError, SeamHttpEndpointQueryPaths, SeamHttpEndpoints, SeamHttpInvalidInputError, } from '@seamapi/http' import type { ActionAttempt } from '@seamapi/types/connect' import { type QueryKey, useQuery, type UseQueryOptions, type UseQueryResult, } from '@tanstack/react-query' import { useSeamClient } from 'lib/use-seam-client.js' export type UseSeamQueryParameters = Parameters[0] export type UseSeamQueryResult = UseQueryResult, QueryError> export function useSeamQuery( endpointPath: T, parameters: UseSeamQueryParameters = {}, options: Parameters[1] & QueryOptions, SeamHttpApiError> = {}, ): UseSeamQueryResult & { queryKey: QueryKey } { const { endpointClient: client, queryKeyPrefixes } = useSeamClient() const queryKey = [ ...queryKeyPrefixes, ...endpointPath.split('/').filter((v) => v !== ''), parameters ?? {}, ] const result = useQuery({ enabled: client != null, ...options, queryKey, queryFn: async () => { if (client == null) return null // Using @ts-expect-error over any is preferred, but not possible here because TypeScript will run out of memory. // Type assertion is needed here for performance reasons. The types are correct at runtime. const endpoint = client[endpointPath] as (...args: any) => Promise return await endpoint(parameters, options) }, }) return { ...result, queryKey } } type QueryData = Awaited< ReturnType > type QueryError = | Error | SeamHttpApiError | SeamHttpInvalidInputError | (QueryData extends ActionAttempt ? | SeamActionAttemptFailedError> | SeamActionAttemptTimeoutError> : never) type QueryOptions = Omit, 'queryKey' | 'queryFn'>