1- import path from "node:path" ;
2- import * as trpcExpress from "@trpc/server/adapters/express" ;
3- import { applyWSSHandler } from "@trpc/server/adapters/ws" ;
4- import cors from "cors" ;
5- import express from "express" ;
6- import { WebSocketServer } from "ws" ;
7-
1+ import cors from "@fastify/cors" ;
2+ import ws from "@fastify/websocket" ;
3+ import {
4+ type FastifyTRPCPluginOptions ,
5+ fastifyTRPCPlugin ,
6+ } from "@trpc/server/adapters/fastify" ;
7+ import type { TRPCReconnectNotification } from "@trpc/server/rpc" ;
8+ import fastify from "fastify" ;
89import { env } from "./env" ;
910import { roomRouter } from "./routers/room" ;
1011import { roomAdminRouter } from "./routers/room-admin" ;
@@ -23,64 +24,90 @@ export const appRouter = mergeRouters(mainRouter);
2324
2425export type AppRouter = typeof appRouter ;
2526
26- const app = express ( ) ;
27+ const server = fastify ( {
28+ routerOptions : {
29+ maxParamLength : 5000 ,
30+ } ,
31+ } ) ;
32+
33+ await server . register ( ws , {
34+ preClose ( done ) {
35+ console . log ( "Broadcasting reconnect to clients before shutdown" ) ;
36+ const response : TRPCReconnectNotification = {
37+ id : null ,
38+ method : "reconnect" ,
39+ } ;
40+
41+ const data = JSON . stringify ( response ) ;
42+
43+ for ( const client of server . websocketServer . clients ) {
44+ if ( client . readyState === 1 ) {
45+ client . send ( data ) ;
46+ }
47+ }
48+
49+ server . websocketServer . close ( done ) ;
50+ } ,
51+ } ) ;
52+
53+ server . websocketServer . on ( "connection" , ( ws ) => {
54+ console . log ( `➕➕ Connection (${ server . websocketServer . clients . size } )` ) ;
55+ ws . once ( "close" , ( ) => {
56+ console . log ( `➖➖ Connection (${ server . websocketServer . clients . size } )` ) ;
57+ } ) ;
58+ } )
2759
2860// Allow CORS for dev
2961if ( process . env . NODE_ENV !== "production" ) {
30- app . use (
31- cors ( {
32- origin : "*" ,
33- credentials : true ,
34- } ) ,
35- ) ;
62+ await server . register ( cors , {
63+ origin : "*" ,
64+ credentials : true ,
65+ } ) ;
3666}
3767
3868// Create the express server
39- app . use (
40- "/trpc" ,
41- trpcExpress . createExpressMiddleware ( {
69+ await server . register ( fastifyTRPCPlugin , {
70+ prefix : "/trpc" ,
71+ useWSS : true ,
72+ // Enable heartbeat messages to keep connection open (disabled by default)
73+ keepAlive : {
74+ enabled : true ,
75+ // server ping message interval in milliseconds
76+ pingMs : 30000 ,
77+ // connection is terminated if pong message is not received in this many milliseconds
78+ pongWaitMs : 5000 ,
79+ } ,
80+ trpcOptions : {
4281 router : appRouter ,
43- } ) ,
44- ) ;
82+ onError ( { path, error } ) {
83+ // report to error monitoring
84+ console . error ( `Error in tRPC handler on path '${ path } ':` , error ) ;
85+ } ,
86+ } satisfies FastifyTRPCPluginOptions < AppRouter > [ "trpcOptions" ] ,
87+ } ) ;
4588
4689if ( env . publicDir ) {
4790 const publicDir = env . publicDir ;
48- // Serve up the single page app
49- app . use ( express . static ( publicDir ) ) ;
50- app . get ( "*" , ( _req , res ) => {
51- res . sendFile ( path . resolve ( publicDir , "index.html" ) ) ;
91+ await server . register ( import ( "@fastify/static" ) , {
92+ root : publicDir ,
93+ prefix : "/" ,
5294 } ) ;
53- }
54-
55- const server = app . listen ( 8080 , ( ) => {
56- console . log ( "Server started on port 8080" ) ;
57- } ) ;
5895
59- // Create the websocket server
96+ server . setNotFoundHandler ( ( _request , reply ) => {
97+ reply . sendFile ( "index.html" ) ;
98+ } ) ;
99+ }
60100
61- const websocketServer = new WebSocketServer ( {
62- noServer : true ,
63- path : "/trpc/socket" ,
101+ const PORT = env . port || 8080 ;
102+ server . listen ( { port : Number ( PORT ) , host : "0.0.0.0" } ) . then ( ( ) => {
103+ console . log ( `Server listening on port ${ PORT } ` ) ;
64104} ) ;
65105
66- const handler = applyWSSHandler ( { wss : websocketServer , router : appRouter } ) ;
67-
68- server . on ( "upgrade" , ( request , socket , head ) => {
69- websocketServer . handleUpgrade ( request , socket , head , ( websocket ) => {
70- websocketServer . emit ( "connection" , websocket , request ) ;
106+ process . on ( "SIGTERM" , ( ) => {
107+ server . close ( ) . then ( ( ) => {
108+ console . log ( "Server closed" ) ;
109+ process . exit ( 0 ) ;
71110 } ) ;
72111} ) ;
73112
74- process . on ( "SIGTERM" , ( ) => {
75- console . log ( "SIGTERM" ) ;
76- handler . broadcastReconnectNotification ( ) ;
77- websocketServer . close ( ) ;
78- console . log ( "Server killed, broadcasting reconnect notification" ) ;
79- } ) ;
80113
81- websocketServer . on ( "connection" , ( ws ) => {
82- console . log ( `➕➕ Connection (${ websocketServer . clients . size } )` ) ;
83- ws . once ( "close" , ( ) => {
84- console . log ( `➖➖ Connection (${ websocketServer . clients . size } )` ) ;
85- } ) ;
86- } ) ;
0 commit comments