import type { CreateExpressContextOptions } from "@trpc/server/adapters/express" import type { CreateWSSContextFnOptions } from "@trpc/server/adapters/ws" import { Context, Effect, Layer, Runtime } from "effect" import { createTRCPErrorMapper } from "./createTRCPErrorMapper" import { TRPCContextTransactionEnum, type TRPCContext, type TRPCContextTransaction } from "./TRPCContext" export const Identifier = "@thilalib/TRPC/TRPCContextCreator" export interface TRPCContextCreator extends Context.Tag> {} export interface TRPCContextCreatorService { readonly createContext: (transaction: TRPCContextTransaction) => TRPCContext readonly createExpressContext: (context: CreateExpressContextOptions) => TRPCContext readonly createWebSocketContext: (context: CreateWSSContextFnOptions) => TRPCContext } export const TRPCUnknownContextCreator = Context.GenericTag>(Identifier) export const make = () => { const TRPCContextCreator = Context.GenericTag>(Identifier) const TRPCContextCreatorLive = Layer.effect(TRPCContextCreator, Effect.gen(function*() { const runtime = yield* Effect.runtime() const mapErrors = yield* createTRCPErrorMapper const run = ( effect: Effect.Effect, options?: { readonly signal?: AbortSignal }, ) => Runtime.runPromise(runtime)( effect.pipe(mapErrors), options, ) const fork = ( effect: Effect.Effect, options?: Runtime.RunForkOptions, ) => Runtime.runFork(runtime)( effect.pipe(mapErrors), options, ) const createContext = (transaction: TRPCContextTransaction) => ({ runtime, run, fork, transaction, }) const createExpressContext = (context: CreateExpressContextOptions) => createContext(TRPCContextTransactionEnum.Express(context)) const createWebSocketContext = (context: CreateWSSContextFnOptions) => createContext(TRPCContextTransactionEnum.WebSocket(context)) return { createContext, createExpressContext, createWebSocketContext } })) return { TRPCContextCreator, TRPCContextCreatorLive } as const }