@@ -7,8 +7,8 @@ import {lookup as dnsLookup} from "node:dns/promises";
77
88import fastifyHttpProxy from "@fastify/http-proxy" ;
99import {
10+ FastifyBaseLogger ,
1011 FastifyInstance ,
11- FastifyPluginAsync ,
1212} from "fastify" ;
1313import fastifyPlugin from "fastify-plugin" ;
1414import { Db } from "mongodb" ;
@@ -21,18 +21,16 @@ import type {
2121 Response ,
2222 ServerToClientEvents ,
2323 SocketData ,
24- } from "../../../../common/index.js" ;
24+ } from "../../../../../../../ common/index.js" ;
2525import MongoWatcherCollection from "./MongoWatcherCollection.js" ;
2626import {
2727 ConnectionId ,
28- DbOptions ,
2928 MongoCustomSocket ,
3029 QueryParameters ,
3130} from "./typings.js" ;
3231import {
3332 getQuery ,
3433 getQueryHash ,
35- initializeMongoClient ,
3634 removeItemFromArray ,
3735} from "./utils.js" ;
3836
@@ -45,7 +43,7 @@ import {
4543 * names per query, limiting the number of events listeners triggered in the client.
4644 */
4745class MongoSocketIoServer {
48- #fastify: FastifyInstance ;
46+ #logger: FastifyBaseLogger ;
4947
5048 #io: Server < ClientToServerEvents , ServerToClientEvents , InterServerEvents , SocketData > ;
5149
@@ -65,36 +63,36 @@ class MongoSocketIoServer {
6563 readonly #mongoDb: Db ;
6664
6765 /**
68- * Private constructor for MongoSocketIoServer. This is not intended to be invoked publicly.
69- * Instead, use MongoSocketIoServer.create() to create a new instance of the class.
70- *
71- * @param fastify
66+ * @param io
67+ * @param logger
7268 * @param mongoDb
7369 */
74- constructor ( fastify : FastifyInstance , mongoDb : Db ) {
75- this . #fastify = fastify ;
70+ private constructor (
71+ io : Server < ClientToServerEvents , ServerToClientEvents , InterServerEvents , SocketData > ,
72+ logger : FastifyBaseLogger ,
73+ mongoDb : Db
74+ ) {
75+ this . #io = io ;
76+ this . #logger = logger ;
7677 this . #mongoDb = mongoDb ;
77- this . #io = new Server <
78- ClientToServerEvents ,
79- ServerToClientEvents ,
80- InterServerEvents ,
81- SocketData
82- > ( fastify . server ) ;
8378 this . #registerEventListeners( ) ;
8479 }
8580
8681 /**
8782 * Creates a new MongoSocketIoServer.
8883 *
8984 * @param fastify
90- * @param options
9185 * @return
86+ * @throws {Error } When MongoDB database not found
9287 */
9388 static async create (
94- fastify : FastifyInstance ,
95- options : DbOptions
89+ fastify : FastifyInstance
9690 ) : Promise < MongoSocketIoServer > {
97- const mongoDb = await initializeMongoClient ( options ) ;
91+ const mongoDb = fastify . mongo . db ;
92+
93+ if ( "undefined" === typeof mongoDb ) {
94+ throw new Error ( "MongoDB database not found" ) ;
95+ }
9896
9997 // Fastify listens on all resolved addresses for localhost (e.g. `::1` and `127.0.0.1`), but
10098 // socket.io can only intercept requests on the main server which listens only on the
@@ -124,15 +122,22 @@ class MongoSocketIoServer {
124122 JSON . stringify ( e ) } `) ;
125123 }
126124
127- return new MongoSocketIoServer ( fastify , mongoDb ) ;
125+ const io = new Server <
126+ ClientToServerEvents ,
127+ ServerToClientEvents ,
128+ InterServerEvents ,
129+ SocketData
130+ > ( fastify . server ) ;
131+
132+ return new MongoSocketIoServer ( io , fastify . log , mongoDb ) ;
128133 }
129134
130135 /**
131136 * Registers event listeners on socket connection.
132137 */
133138 #registerEventListeners ( ) {
134139 this . #io. on ( "connection" , ( socket ) => {
135- this . #fastify . log . info ( `New socket connected with ID:${ socket . id } ` ) ;
140+ this . #logger . info ( `New socket connected with ID:${ socket . id } ` ) ;
136141 socket . on ( "disconnect" , this . #disconnectListener. bind ( this , socket ) ) ;
137142 socket . on (
138143 "collection::find::subscribe" ,
@@ -151,7 +156,7 @@ class MongoSocketIoServer {
151156 * @param socket
152157 */
153158 async #disconnectListener ( socket : MongoCustomSocket ) {
154- this . #fastify . log . info ( `Socket:${ socket . id } disconnected` ) ;
159+ this . #logger . info ( `Socket:${ socket . id } disconnected` ) ;
155160 const subscribedQueryIds = this . #subscribedQueryIdsMap. get ( socket . id ) ;
156161
157162 if ( "undefined" === typeof subscribedQueryIds ) {
@@ -163,7 +168,7 @@ class MongoSocketIoServer {
163168 }
164169
165170 this . #subscribedQueryIdsMap. delete ( socket . id ) ;
166- this . #fastify . log . debug (
171+ this . #logger . debug (
167172 "Subscribed queryIDs map" +
168173 ` ${ JSON . stringify ( Array . from ( this . #subscribedQueryIdsMap. entries ( ) ) ) } `
169174 ) ;
@@ -232,8 +237,12 @@ class MongoSocketIoServer {
232237 : MongoWatcherCollection {
233238 let watcherCollection = this . #collections. get ( collectionName ) ;
234239 if ( "undefined" === typeof watcherCollection ) {
235- watcherCollection = new MongoWatcherCollection ( collectionName , this . #mongoDb) ;
236- this . #fastify. log . debug ( `Initialize Mongo watcher collection:${ collectionName } .` ) ;
240+ watcherCollection = new MongoWatcherCollection (
241+ collectionName ,
242+ this . #logger,
243+ this . #mongoDb
244+ ) ;
245+ this . #logger. debug ( `Initialize Mongo watcher collection:${ collectionName } .` ) ;
237246 this . #collections. set ( collectionName , watcherCollection ) ;
238247 }
239248
@@ -258,14 +267,14 @@ class MongoSocketIoServer {
258267 ) : Promise < void > {
259268 const { collectionName, query, options} = requestArgs ;
260269
261- this . #fastify . log . debug (
270+ this . #logger . debug (
262271 `Socket:${ socket . id } requested query:${ JSON . stringify ( query ) } ` +
263272 `with options:${ JSON . stringify ( options ) } to collection:${ collectionName } `
264273 ) ;
265274
266275 const hasCollection = await this . #hasCollection( collectionName ) ;
267276 if ( false === hasCollection ) {
268- this . #fastify . log . error ( `Collection ${ collectionName } does not exist in MongoDB` ) ;
277+ this . #logger . error ( `Collection ${ collectionName } does not exist in MongoDB` ) ;
269278 callback ( {
270279 error : `Collection ${ collectionName } does not exist in MongoDB on server` ,
271280 } ) ;
@@ -284,7 +293,7 @@ class MongoSocketIoServer {
284293 callback ( { data : { queryId, initialDocuments} } ) ;
285294
286295 this . #addQueryIdToSubscribedList( queryId , socket . id ) ;
287- this . #fastify . log . info (
296+ this . #logger . info (
288297 `Socket:${ socket . id } subscribed to query:${ JSON . stringify ( query ) } ` +
289298 `with options:${ JSON . stringify ( options ) } ` +
290299 `on collection:${ collectionName } with ID:${ queryId } `
@@ -324,7 +333,7 @@ class MongoSocketIoServer {
324333 #unsubscribe ( socket : MongoCustomSocket , queryId : number ) {
325334 const queryHash : string | undefined = this . #queryIdToQueryHashMap. get ( queryId ) ;
326335 if ( "undefined" === typeof queryHash ) {
327- this . #fastify . log . error ( `Query:${ queryId } not found in query map` ) ;
336+ this . #logger . error ( `Query:${ queryId } not found in query map` ) ;
328337
329338 return ;
330339 }
@@ -333,26 +342,26 @@ class MongoSocketIoServer {
333342
334343 const collection = this . #collections. get ( queryParams . collectionName ) ;
335344 if ( "undefined" === typeof collection ) {
336- this . #fastify . log . error ( `${ queryParams . collectionName } is missing from server` ) ;
345+ this . #logger . error ( `${ queryParams . collectionName } is missing from server` ) ;
337346
338347 return ;
339348 }
340349
341350 const isLastSubscriber = collection . unsubscribe ( queryId , socket . id ) ;
342- this . #fastify . log . info ( `Socket:${ socket . id } unsubscribed from query:${ queryId } ` ) ;
351+ this . #logger . info ( `Socket:${ socket . id } unsubscribed from query:${ queryId } ` ) ;
343352
344353 if ( isLastSubscriber ) {
345- this . #fastify . log . debug ( `Query:${ queryId } deleted from query map.` ) ;
354+ this . #logger . debug ( `Query:${ queryId } deleted from query map.` ) ;
346355 this . #queryIdToQueryHashMap. delete ( queryId ) ;
347356 }
348357
349- this . #fastify . log . debug (
358+ this . #logger . debug (
350359 "Query ID to query hash map:" +
351360 ` ${ JSON . stringify ( Array . from ( this . #queryIdToQueryHashMap. entries ( ) ) ) } `
352361 ) ;
353362
354363 if ( false === collection . isReferenced ( ) ) {
355- this . #fastify . log . debug ( `Collection:${ queryParams . collectionName } ` +
364+ this . #logger . debug ( `Collection:${ queryParams . collectionName } ` +
356365 " deallocated from server." ) ;
357366 this . #collections. delete ( queryParams . collectionName ) ;
358367 }
@@ -370,15 +379,15 @@ class MongoSocketIoServer {
370379 requestArgs : { queryId : number }
371380 ) : Promise < void > {
372381 const { queryId} = requestArgs ;
373- this . #fastify . log . debug (
382+ this . #logger . debug (
374383 `Socket:${ socket . id } requested unsubscription to query:${ queryId } `
375384 ) ;
376385
377386 const subscribedQueryIds = this . #subscribedQueryIdsMap. get ( socket . id ) ;
378387 if ( "undefined" === typeof subscribedQueryIds ||
379388 false === subscribedQueryIds . includes ( queryId )
380389 ) {
381- this . #fastify . log . error ( `Socket ${ socket . id } is not subscribed to ${ queryId } ` ) ;
390+ this . #logger . error ( `Socket ${ socket . id } is not subscribed to ${ queryId } ` ) ;
382391
383392 return ;
384393 }
@@ -388,27 +397,24 @@ class MongoSocketIoServer {
388397
389398 removeItemFromArray ( subscribedQueryIds , queryId ) ;
390399
391- this . #fastify . log . debug (
400+ this . #logger . debug (
392401 `Subscribed queryIDs map ${
393402 JSON . stringify ( Array . from ( this . #subscribedQueryIdsMap. entries ( ) ) ) } `
394403 ) ;
395404 }
396405}
397406
398- /**
399- * A Fastify plugin callback for setting up the `MongoSocketIoServer`.
400- *
401- * @param app
402- * @param options
403- * @param options.database
404- * @param options.host
405- * @param options.port
406- */
407- const MongoServerPlugin : FastifyPluginAsync < DbOptions > = async (
408- app : FastifyInstance ,
409- options : DbOptions
410- ) => {
411- await MongoSocketIoServer . create ( app , options ) ;
412- } ;
413-
414- export default fastifyPlugin ( MongoServerPlugin ) ;
407+ declare module "fastify" {
408+ export interface FastifyInstance {
409+ MongoSocketIoServer : MongoSocketIoServer ;
410+ }
411+ }
412+
413+ export default fastifyPlugin (
414+ async ( fastify ) => {
415+ fastify . decorate ( "MongoSocketIoServer" , await MongoSocketIoServer . create ( fastify ) ) ;
416+ } ,
417+ {
418+ name : "MongoSocketIoServer" ,
419+ }
420+ ) ;
0 commit comments