{"version":3,"file":"client.mjs","names":[],"sources":["../../src/app-dir/create-action-hook.tsx","../../src/app-dir/client.ts"],"sourcesContent":["import type {\n  CreateTRPCClientOptions,\n  TRPCLink,\n  TRPCProcedureOptions,\n  TRPCRequestOptions,\n} from '@trpc/client';\nimport { createTRPCUntypedClient, TRPCClientError } from '@trpc/client';\nimport type {\n  CoercedTransformerParameters,\n  TransformerOptions,\n} from '@trpc/client/unstable-internals';\nimport { getTransformer } from '@trpc/client/unstable-internals';\nimport { observable } from '@trpc/server/observable';\nimport type {\n  inferClientTypes,\n  InferrableClientTypes,\n  MaybePromise,\n  Simplify,\n  TypeError,\n} from '@trpc/server/unstable-core-do-not-import';\nimport { transformResult } from '@trpc/server/unstable-core-do-not-import';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport type { TRPCActionHandler } from './server';\nimport type { ActionHandlerDef } from './shared';\nimport { isFormData } from './shared';\n\ntype MutationArgs<TDef extends ActionHandlerDef> = TDef['input'] extends void\n  ? [input?: undefined | void, opts?: TRPCProcedureOptions]\n  : [input: FormData | TDef['input'], opts?: TRPCProcedureOptions];\n\ninterface UseTRPCActionBaseResult<TDef extends ActionHandlerDef> {\n  mutate: (...args: MutationArgs<TDef>) => void;\n  mutateAsync: (...args: MutationArgs<TDef>) => Promise<TDef['output']>;\n}\n\ninterface UseTRPCActionSuccessResult<\n  TDef extends ActionHandlerDef,\n> extends UseTRPCActionBaseResult<TDef> {\n  data: TDef['output'];\n  error?: never;\n  status: 'success';\n}\n\ninterface UseTRPCActionErrorResult<\n  TDef extends ActionHandlerDef,\n> extends UseTRPCActionBaseResult<TDef> {\n  data?: never;\n  error: TRPCClientError<TDef['errorShape']>;\n  status: 'error';\n}\n\ninterface UseTRPCActionIdleResult<\n  TDef extends ActionHandlerDef,\n> extends UseTRPCActionBaseResult<TDef> {\n  data?: never;\n  error?: never;\n  status: 'idle';\n}\n\ninterface UseTRPCActionLoadingResult<\n  TDef extends ActionHandlerDef,\n> extends UseTRPCActionBaseResult<TDef> {\n  data?: never;\n  error?: never;\n  status: 'loading';\n}\n\n// ts-prune-ignore-next\nexport type UseTRPCActionResult<TDef extends ActionHandlerDef> =\n  | UseTRPCActionErrorResult<TDef>\n  | UseTRPCActionIdleResult<TDef>\n  | UseTRPCActionLoadingResult<TDef>\n  | UseTRPCActionSuccessResult<TDef>;\n\ntype ActionContext = {\n  _action: (...args: any[]) => Promise<any>;\n};\n\n// ts-prune-ignore-next\nexport function experimental_serverActionLink<\n  TInferrable extends InferrableClientTypes,\n>(\n  ...args: InferrableClientTypes extends TInferrable\n    ? [\n        TypeError<'Generic parameter missing in `experimental_createActionHook<HERE>()` or experimental_serverActionLink<HERE>()'>,\n      ]\n    : inferClientTypes<TInferrable>['transformer'] extends true\n      ? [\n          opts: TransformerOptions<{\n            transformer: true;\n          }>,\n        ]\n      : [\n          opts?: TransformerOptions<{\n            transformer: false;\n          }>,\n        ]\n): TRPCLink<TInferrable> {\n  const [opts] = args as [CoercedTransformerParameters];\n  const transformer = getTransformer(opts?.transformer);\n  return () =>\n    ({ op }) =>\n      observable((observer) => {\n        const context = op.context as ActionContext;\n\n        context\n          ._action(\n            isFormData(op.input)\n              ? op.input\n              : transformer.input.serialize(op.input),\n          )\n          .then((data) => {\n            const transformed = transformResult(data, transformer.output);\n\n            if (!transformed.ok) {\n              observer.error(TRPCClientError.from(transformed.error, {}));\n              return;\n            }\n            observer.next({\n              context: op.context,\n              result: transformed.result,\n            });\n            observer.complete();\n          })\n          .catch((cause) => {\n            observer.error(TRPCClientError.from(cause));\n          });\n      });\n}\n\ninterface UseTRPCActionOptions<TDef extends ActionHandlerDef> {\n  onSuccess?: (result: TDef['output']) => MaybePromise<void> | void;\n  onError?: (result: TRPCClientError<TDef['errorShape']>) => MaybePromise<void>;\n}\n// ts-prune-ignore-next\nexport function experimental_createActionHook<\n  TInferrable extends InferrableClientTypes,\n>(\n  opts: InferrableClientTypes extends TInferrable\n    ? TypeError<'Generic parameter missing in `experimental_createActionHook<HERE>()`'>\n    : CreateTRPCClientOptions<TInferrable>,\n) {\n  type ActionContext = {\n    _action: (...args: any[]) => Promise<any>;\n  };\n  const client = createTRPCUntypedClient(\n    opts as Exclude<typeof opts, TypeError<any>>,\n  );\n  return function useAction<TDef extends ActionHandlerDef>(\n    handler: TRPCActionHandler<TDef>,\n    useActionOpts?: UseTRPCActionOptions<Simplify<TDef>>,\n  ) {\n    const count = useRef(0);\n\n    type Result = UseTRPCActionResult<TDef>;\n    type State = Omit<Result, 'mutate' | 'mutateAsync'>;\n    const [state, setState] = useState<State>({\n      status: 'idle',\n    });\n\n    const actionOptsRef = useRef(useActionOpts);\n    actionOptsRef.current = useActionOpts;\n\n    useEffect(() => {\n      return () => {\n        // cleanup after unmount to prevent calling hook opts after unmount\n        count.current = -1;\n        actionOptsRef.current = undefined;\n      };\n    }, []);\n\n    const mutateAsync = useCallback(\n      (input: any, requestOptions?: TRPCRequestOptions) => {\n        const idx = ++count.current;\n        const context: ActionContext = {\n          ...requestOptions?.context,\n          _action(innerInput) {\n            return handler(innerInput);\n          },\n        };\n\n        setState({\n          status: 'loading',\n        });\n        return client\n          .mutation('serverAction', input, {\n            ...requestOptions,\n            context,\n          })\n          .then(async (data) => {\n            await actionOptsRef.current?.onSuccess?.(data);\n            if (idx !== count.current) {\n              return;\n            }\n            setState({\n              status: 'success',\n              data,\n            });\n          })\n          .catch(async (error) => {\n            await actionOptsRef.current?.onError?.(error);\n            throw error;\n          })\n          .catch((error) => {\n            if (idx !== count.current) {\n              return;\n            }\n            setState({\n              status: 'error',\n              error: TRPCClientError.from(error, {}),\n            });\n            throw error;\n          });\n      },\n      [handler],\n    ) as Result['mutateAsync'];\n\n    const mutate: Result['mutate'] = useCallback(\n      (...args: any[]) => {\n        void (mutateAsync as any)(...args).catch(() => {\n          // ignored\n        });\n      },\n      [mutateAsync],\n    );\n\n    return useMemo(\n      () => ({\n        ...state,\n        mutate,\n        mutateAsync,\n      }),\n      [mutate, mutateAsync, state],\n    ) as Result;\n  };\n}\n","import type { TRPCClient } from '@trpc/client';\nimport {\n  clientCallTypeToProcedureType,\n  createTRPCUntypedClient,\n} from '@trpc/client';\nimport type { AnyRouter } from '@trpc/server/unstable-core-do-not-import';\nimport { createRecursiveProxy } from '@trpc/server/unstable-core-do-not-import';\nimport type { CreateTRPCNextAppRouterOptions } from './shared';\n\nexport {\n  // ts-prune-ignore-next\n  experimental_createActionHook,\n  // ts-prune-ignore-next\n  experimental_serverActionLink,\n  // ts-prune-ignore-next\n  type UseTRPCActionResult,\n} from './create-action-hook';\n\ntype QueryResult = {\n  data?: unknown;\n  error?: unknown;\n  promise?: Promise<unknown>;\n};\n\n// ts-prune-ignore-next\nexport function experimental_createTRPCNextAppDirClient<\n  TRouter extends AnyRouter,\n>(opts: CreateTRPCNextAppRouterOptions<TRouter>) {\n  const client = createTRPCUntypedClient<TRouter>(opts.config());\n  // const useProxy = createUseProxy<TRouter>(client);\n\n  const cache = new Map<string, QueryResult>();\n\n  return createRecursiveProxy<TRPCClient<TRouter>>(({ path, args }) => {\n    // const pathCopy = [key, ...path];\n    const pathCopy = [...path];\n    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n    const procedureType = clientCallTypeToProcedureType(pathCopy.pop()!);\n\n    if (procedureType === 'query') {\n      const queryCacheKey = JSON.stringify([path, args[0]]);\n      const cached = cache.get(queryCacheKey);\n\n      if (cached?.promise) {\n        return cached.promise;\n      }\n    }\n\n    const fullPath = pathCopy.join('.');\n\n    const promise: Promise<unknown> = (client as any)[procedureType](\n      fullPath,\n      ...args,\n    );\n    if (procedureType !== 'query') {\n      return promise;\n    }\n\n    const queryCacheKey = JSON.stringify([path, args[0]]);\n\n    cache.set(queryCacheKey, {\n      promise,\n    });\n\n    return promise;\n  });\n  // });\n}\n"],"mappings":"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"}