import type { SeamActionAttemptFailedError, SeamActionAttemptTimeoutError, SeamHttpApiError, SeamHttpEndpointMutationPaths, SeamHttpEndpoints, SeamHttpInvalidInputError, } from '@seamapi/http' import type { ActionAttempt } from '@seamapi/types/connect' import { useMutation, type UseMutationOptions, type UseMutationResult, } from '@tanstack/react-query' import { NullSeamClientError, useSeamClient } from 'lib/use-seam-client.js' export type UseSeamMutationVariables = Parameters[0] export type UseSeamMutationResult = UseMutationResult< MutationData, MutationError, UseSeamMutationVariables > export function useSeamMutation( endpointPath: T, options: Parameters[1] & MutationOptions< MutationData, MutationError, UseSeamMutationVariables > = {}, ): UseSeamMutationResult { const { endpointClient: client } = useSeamClient() return useMutation({ ...options, mutationFn: async (variables) => { if (client === null) throw new NullSeamClientError() // 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(variables, options) }, }) } type MutationData = Awaited< ReturnType > type MutationError = | Error | SeamHttpApiError | SeamHttpInvalidInputError | (MutationData extends ActionAttempt ? | SeamActionAttemptFailedError> | SeamActionAttemptTimeoutError> : never) type MutationOptions = Omit, 'mutationFn'>