@@ -163,6 +163,20 @@ export interface ServerOptions<E = unknown> {
163163 | Record < string , unknown >
164164 | boolean
165165 | void ;
166+ /**
167+ * Called when the socket/client closes/disconnects for
168+ * whatever reason. Provides the close event too. Beware
169+ * that this callback happens AFTER all subscriptions have
170+ * been gracefuly completed.
171+ *
172+ * If you are interested in tracking the subscriptions completions,
173+ * consider using the `onComplete` callback.
174+ */
175+ onDisconnect ?: (
176+ ctx : Context < E > ,
177+ code : number ,
178+ reason : string ,
179+ ) => Promise < void > | void ;
166180 /**
167181 * The subscribe callback executed right after
168182 * acknowledging the request before any payload
@@ -294,10 +308,14 @@ export interface Server<E = undefined> {
294308 * original WebSocket, if you need it down the road.
295309 *
296310 * Returns a function that should be called when the same socket
297- * has been closed, for whatever reason. The returned promise will
298- * resolve once the internal cleanup is complete.
311+ * has been closed, for whatever reason. The close code and reason
312+ * must be passed for reporting to the `onDisconnect` callback. Returned
313+ * promise will resolve once the internal cleanup is complete.
299314 */
300- opened ( socket : WebSocket , ctxExtra : E ) : ( ) => Promise < void > ; // closed
315+ opened (
316+ socket : WebSocket ,
317+ ctxExtra : E ,
318+ ) : ( code : number , reason : string ) => Promise < void > ; // closed
301319}
302320
303321export interface WebSocket {
@@ -320,7 +338,8 @@ export interface WebSocket {
320338 send ( data : string ) : Promise < void > | void ;
321339 /**
322340 * Closes the socket gracefully. Will always provide
323- * the appropriate code and close reason.
341+ * the appropriate code and close reason. `onDisconnect`
342+ * callback will be called.
324343 *
325344 * The returned promise is used to control the graceful
326345 * closure.
@@ -392,6 +411,7 @@ export function makeServer<E = unknown>(options: ServerOptions<E>): Server<E> {
392411 subscribe,
393412 connectionInitWaitTimeout = 3 * 1000 , // 3 seconds
394413 onConnect,
414+ onDisconnect,
395415 onSubscribe,
396416 onOperation,
397417 onNext,
@@ -653,12 +673,13 @@ export function makeServer<E = unknown>(options: ServerOptions<E>): Server<E> {
653673 }
654674 } ) ;
655675
656- // wait for close and cleanup
657- return async ( ) => {
676+ // wait for close, cleanup and the disconnect callback
677+ return async ( code , reason ) => {
658678 if ( connectionInitWait ) clearTimeout ( connectionInitWait ) ;
659679 for ( const sub of Object . values ( ctx . subscriptions ) ) {
660680 await sub ?. return ?.( ) ;
661681 }
682+ await onDisconnect ?.( ctx , code , reason ) ;
662683 } ;
663684 } ,
664685 } ;
0 commit comments