diff --git a/src/Layers/trpc/TRPCWebSocketServer.ts b/src/Layers/trpc/TRPCWebSocketServer.ts index d36f03b..bcf214a 100644 --- a/src/Layers/trpc/TRPCWebSocketServer.ts +++ b/src/Layers/trpc/TRPCWebSocketServer.ts @@ -1,44 +1,64 @@ -import { applyWSSHandler } from "@trpc/server/adapters/ws" -import { Context, Effect, Layer } from "effect" -import ws from "ws" -import { ExpressHTTPServer } from "../http/ExpressHTTPServer.service" -import { ServerConfig } from "../ServerConfig" -import { TRPCContextCreator } from "../trpc/TRPCContextCreator.service" -import { RPCRouter } from "./RPCRouter.service" +import type { applyWSSHandler } from "@trpc/server/adapters/ws" +import { Config, Context, Effect, Layer } from "effect" +import type ws from "ws" +import { ImportError } from "../../ImportError" +import { ExpressNodeHTTPServer } from "../express" +import { TRPCUnknownContextCreator } from "./TRPCContextCreator" +import { TRPCAnyRouter } from "./TRPCRouter" -export class TRPCWebSocketServer extends Context.Tag("TRPCWebSocketServer") }>() {} -export const RPCWebSocketServerLive = Layer.effect(RPCWebSocketServer, ServerConfig.rpcHTTPRoot.pipe( - Effect.flatMap(rpcHTTPRoot => Effect.acquireRelease( - Effect.gen(function*() { - yield* Effect.logInfo(`WebSocket server started on ${ rpcHTTPRoot }`) - const wss = new ws.WebSocketServer({ - server: yield* ExpressHTTPServer, - host: rpcHTTPRoot, +const importWS = Effect.tryPromise({ + try: () => import("ws"), + catch: cause => new ImportError({ path: "ws", cause }), +}) + +const importTRPCServerWSAdapter = Effect.tryPromise({ + try: () => import("@trpc/server/adapters/ws"), + catch: cause => new ImportError({ path: "@trpc/server/adapters/ws", cause }), +}) + +export const TRPCWebSocketServerLive = ( + config: { + readonly host: Config.Config + } +) => Layer.effect(TRPCWebSocketServer, Effect.gen(function*() { + const { WebSocketServer } = yield* importWS + const { applyWSSHandler } = yield* importTRPCServerWSAdapter + + const host = yield* config.host + + return yield* Effect.acquireRelease( + Effect.gen(function*() { + yield* Effect.logInfo(`WebSocket server started on ${ host }`) + + const wss = new WebSocketServer({ + server: yield* ExpressNodeHTTPServer.ExpressNodeHTTPServer, + host, }) return { wss, handler: applyWSSHandler({ wss, - router: yield* RPCRouter, - createContext: (yield* TRPCContextCreator).createWebSocketContext, + router: yield* TRPCAnyRouter, + createContext: (yield* TRPCUnknownContextCreator).createWebSocketContext, }), } }), ({ wss, handler }) => Effect.gen(function*() { - yield* Effect.logInfo(`WebSocket server on ${ rpcHTTPRoot } is stopping. Waiting for existing connections to end...`) + yield* Effect.logInfo(`WebSocket server on ${ host } is stopping. Waiting for existing connections to end...`) handler.broadcastReconnectNotification() yield* Effect.async(resume => { wss.close(() => resume(Effect.logInfo("WebSocket server closed"))) }) }), - )) -)) + ) +})) diff --git a/src/Layers/trpc/index.ts b/src/Layers/trpc/index.ts index 3703bfc..9e23e90 100644 --- a/src/Layers/trpc/index.ts +++ b/src/Layers/trpc/index.ts @@ -3,3 +3,4 @@ export * as TRPCContext from "./TRPCContext" export * as TRPCContextCreator from "./TRPCContextCreator" export * as TRPCExpressRoute from "./TRPCExpressRoute" export * as TRPCRouter from "./TRPCRouter" +export * as TRPCWebSocketServer from "./TRPCWebSocketServer"