From c25c525d6f6b518c735b799673f1eceb4adbbd5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Tue, 9 Jul 2024 02:15:18 +0200 Subject: [PATCH] RPCWebSocketServer --- bun.lockb | Bin 261298 -> 261719 bytes packages/server/package.json | 3 +- packages/server/src/config.ts | 8 +++++ .../server/src/express/ExpressHTTPServer.ts | 25 ++++++++-------- packages/server/src/rpc/RPCPlaygroundRoute.ts | 6 ++-- packages/server/src/rpc/RPCServerRoute.ts | 4 +-- packages/server/src/rpc/RPCWebSocketServer.ts | 28 ++++++++++++++++++ packages/server/src/rpc/config.ts | 5 ---- 8 files changed, 55 insertions(+), 24 deletions(-) create mode 100644 packages/server/src/config.ts create mode 100644 packages/server/src/rpc/RPCWebSocketServer.ts delete mode 100644 packages/server/src/rpc/config.ts diff --git a/bun.lockb b/bun.lockb index 23fdc556ea57d8fd48b8e2f167bb6075a9bda3f7..87eb5c2f361656034fedd57e3edad16316b68f41 100755 GIT binary patch delta 9855 zcmeI2c~lhFw#KWf!B8d|2Q(<4qM|Z1*eEo}&@s*fDsez!93u)E4TuA36fnj(#&FBH z9izrP1&m&C0t8eBgE(s(Kt)7jA~EKMo6#i3_wBCJfNQ1@7m|o zsp{(LV;y+>;`QHO{J_U!@Yu%_&aeF3oZK*Xr&pVqBYN~4d25CLtwVSJ_;|_oMxESC zo){$Fwxve4Rd&*j#HLB}60AhJze|!{l%(VZZ%wv>jNOu?!k;sHb{vD~#JE|}2?Z^Wdd@8EA5GQvKZ0>i ziO7kLHcpA1l`uO`_?~;U*3J65Rg1JaGvi|8q9v(9_?Jc6E-j^5=OoWeNot5x?af?}(J-Ef@|D!1;(?pxF_vNApf@>oB1$f%jzT{UyO~0Y4Fw%G)$8rTJG$t54{s zVKJ0P=U$*s?;>a`__M*ecuS}Y^xZ-|zeBMkxxqI;+d;o5lBBlKlR|ex+rVE5b%oA^ z^8Ul2&d@+zlakw@(Hg)`=tFeC9alhkK$oFBo!PivczXJk>Y4$c<2CSk0E+q0Pb1gYz_=h2KmvNXgR=#@x%rc?1Mdm}O&w9L27 zY7nNaFFaYR@ifZ^wb%m|^)6TsD>H?fRd39HS9p>Z-`_01u6Z1^sMFFVX^76cnbmA~ z1FiX)Qvw|_B&omEi63oN2g2)Z^|;jg!jm-9G_!gc-Ya^{XjUEfNK#LIzkOzPB)l-I zR})}XHF)}f;=Ro3Ie3BASmr{rYX7Munczv*!wG=*vNdM%H>-2uaTP@~p~@k6`hF&( z+2I=zqk_Y7S8cnegBq~cwr@PfGZ!9bD;hk9eeie^>auTx1n52C$Q<`ck{>)A*&MUn zSBuTII3$93KeNv#AY4V(GS>uZ9yu1(?(eofd477s>u!z52b$Hyx>z4fGCX}ocyvF( zv*?vJm=*v1TE@{Z`^Eb)WX(7ySUrLk567U@gqY7J=&{ zt6|oH&FYu%jPM$0roLvi?E%}Ea0cboT6Lbq{u0 zxN3Qw7i3lg@pSoXv4#jG+6g=+@s*>v&2Wb4Bjwntj1(kufYp} zr)Zf$W~Jj1?d#)V_TzA8=%E=ygVhaa=_dupZGWCUZH7;1Bn_~(VrpBNwXI)kTfOpZ zd8=z%S8H2s@@>(nX!Wz!+h=V(DhjcyMIpyH_^9Nm+=o+S(yC8c>Uwyu>GO!p@8Iz{!e_zPtauk{U!M+B*Wo_L zmyP~W>|HELlWM(P@FvuH4NgkZxLR-WGhQLQ*K1>KKGVC^YbL_uOG@`H!W&iVbtr^DTwkjDS=(G^ zUNFn^52j!8YMS(dBuPsQlB7VFLZ5@Kg7U`7d=1nNnhM1il(ZizLo=bg{Tb!`4~zVI znq)1&pb=VyB7v1VC=x!aJ^WL`|1-+_mx}!VO8G!98ub3rfM*4D$}@8doC{Sz`3R~+ z9xKnxJrVyx@cPR8-3RCWszscY59C|nf16}$)KgCQ9)1JpV<;E;Rp@U*e~03q^b~)1 zATsyz-zdioB3@saC)p#w9W;P4a1h#1>`-5yN4y1iOQ@HK|C^fhe^uyD)!_s6#=v>z ze4+Ld&VP4tB&?j^FEl{#`pT#W{xpFO6!Cvc`TG0c6yQ@d7#;IK!=XHe2%#g{!N$sY zk;1R9eB`eQ&Z=_a>uAUaD=z)qZzM9V;4c zs0=S@bYN}R)pPgqw}11~*{y*V%0D7I(V`>rAlZ#dkI0dfm?bwNV-`RMnx6&GB^#iE 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 Ce_8ne diff --git a/packages/server/package.json b/packages/server/package.json index 3c381d7..bfdf540 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -14,7 +14,8 @@ "@trpc/server": "^10.45.2", "effect": "^3.4.7", "express": "^4.19.2", - "trpc-playground": "^1.0.4" + "trpc-playground": "^1.0.4", + "ws": "^8.18.0" }, "devDependencies": { "@types/express": "^4.17.21", diff --git a/packages/server/src/config.ts b/packages/server/src/config.ts new file mode 100644 index 0000000..0e78978 --- /dev/null +++ b/packages/server/src/config.ts @@ -0,0 +1,8 @@ +import { Config } from "effect" + + +export const httpPort = Config.number("HTTP_PORT").pipe(Config.withDefault(8080)) +export const websocketPort = Config.number("WEBSOCKET_PORT").pipe(Config.withDefault(3001)) + +export const rpcHTTPRoot = Config.string("RPC_HTTP_ROOT").pipe(Config.withDefault("/rpc")) +export const rpcHTTPPlaygroundRoot = Config.string("RPC_HTTP_PLAYGROUND_ROOT").pipe(Config.withDefault("/rpc/playground")) diff --git a/packages/server/src/express/ExpressHTTPServer.ts b/packages/server/src/express/ExpressHTTPServer.ts index 9080588..e17efd5 100644 --- a/packages/server/src/express/ExpressHTTPServer.ts +++ b/packages/server/src/express/ExpressHTTPServer.ts @@ -1,20 +1,19 @@ -import { Config, Effect, Layer } from "effect" +import { Effect, Layer } from "effect" +import { httpPort } from "../config" import { ExpressApp } from "./ExpressApp" export module ExpressHTTPServer { - export const Live = Layer.scopedDiscard(Effect.gen(function*() { - const app = yield* ExpressApp - const port = yield* Config.number("PORT").pipe(Config.withDefault(8080)) + export const Live = Layer.scopedDiscard(Effect.acquireRelease( + Effect.gen(function*() { + const app = yield* ExpressApp + const port = yield* httpPort - yield* Effect.acquireRelease( - Effect.sync(() => - app.listen(port, () => console.log(`HTTP server listening on ${ port }.`)) - ), + return app.listen(port, () => console.log(`HTTP server listening on ${ port }.`)) + }), - server => Effect.sync(() => - server.close() - ), - ) - })) + server => Effect.sync(() => + server.close() + ), + )) } diff --git a/packages/server/src/rpc/RPCPlaygroundRoute.ts b/packages/server/src/rpc/RPCPlaygroundRoute.ts index a3e7ca8..aae1a3c 100644 --- a/packages/server/src/rpc/RPCPlaygroundRoute.ts +++ b/packages/server/src/rpc/RPCPlaygroundRoute.ts @@ -1,8 +1,8 @@ import { Effect, Layer } from "effect" import { expressHandler } from "trpc-playground/handlers/express" +import { rpcHTTPPlaygroundRoot, rpcHTTPRoot } from "../config" import { ExpressApp } from "../express/ExpressApp" import { RPCRouter } from "./RPCRouter" -import { rpcPlaygroundRoot, rpcRoot } from "./config" export module RPCPlaygroundRoute { @@ -10,10 +10,10 @@ export module RPCPlaygroundRoute { export const Dev = Layer.effectDiscard(Effect.gen(function*() { const app = yield* ExpressApp - const playgroundEndpoint = yield* rpcPlaygroundRoot + const playgroundEndpoint = yield* rpcHTTPPlaygroundRoot const handler = expressHandler({ - trpcApiEndpoint: yield* rpcRoot, + trpcApiEndpoint: yield* rpcHTTPRoot, playgroundEndpoint, router: yield* RPCRouter, }) diff --git a/packages/server/src/rpc/RPCServerRoute.ts b/packages/server/src/rpc/RPCServerRoute.ts index f015200..950e1ff 100644 --- a/packages/server/src/rpc/RPCServerRoute.ts +++ b/packages/server/src/rpc/RPCServerRoute.ts @@ -1,16 +1,16 @@ import { createExpressMiddleware } from "@trpc/server/adapters/express" import { Effect, Layer } from "effect" +import { rpcHTTPRoot } from "../config" import { ExpressApp } from "../express/ExpressApp" import { TRPCContextCreator } from "../trpc/TRPCContextCreator" import { RPCRouter } from "./RPCRouter" -import { rpcRoot } from "./config" export module RPCServerRoute { export const Live = Layer.effectDiscard(Effect.gen(function*() { const app = yield* ExpressApp - app.use(yield* rpcRoot, + app.use(yield* rpcHTTPRoot, createExpressMiddleware({ router: yield* RPCRouter, createContext: yield* TRPCContextCreator, diff --git a/packages/server/src/rpc/RPCWebSocketServer.ts b/packages/server/src/rpc/RPCWebSocketServer.ts new file mode 100644 index 0000000..303b3f4 --- /dev/null +++ b/packages/server/src/rpc/RPCWebSocketServer.ts @@ -0,0 +1,28 @@ +import { applyWSSHandler } from "@trpc/server/adapters/ws" +import { Effect, Layer } from "effect" +import ws from "ws" +import { websocketPort } from "../config" +import { TRPCContextCreator } from "../trpc/TRPCContextCreator" +import { RPCRouter } from "./RPCRouter" + + +export module RPCWebSocketServer { + export const Live = Layer.scopedDiscard(Effect.acquireRelease( + Effect.gen(function*() { + const wss = new ws.Server({ port: yield* websocketPort }) + + const handler = applyWSSHandler({ + wss, + router: yield* RPCRouter, + createContext: yield* TRPCContextCreator, + }) + + return { wss, handler } + }), + + ({ wss, handler }) => Effect.sync(() => { + handler.broadcastReconnectNotification() + wss.close() + }), + )) +} diff --git a/packages/server/src/rpc/config.ts b/packages/server/src/rpc/config.ts deleted file mode 100644 index 9a0077b..0000000 --- a/packages/server/src/rpc/config.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { Config } from "effect" - - -export const rpcRoot = Config.string("RPC_ROOT").pipe(Config.withDefault("/rpc")) -export const rpcPlaygroundRoot = Config.string("RPC_PLAYGROUND_ROOT").pipe(Config.withDefault("/rpc/playground"))