@@ -12,10 +12,13 @@ import ReconnectingWebSocket from 'reconnecting-websocket'
1212/**
1313 * Creates a reply function for the given client and message.
1414 *
15- * @param client - The RealtimeClient instance.
16- * @param message - The incoming message to reply to.
17- * @returns A function that sends a reply.
18- * @throws Error if the connection ID is not available in the message.
15+ * This function generates a `ReplyFunction` that can be used to send a response back to the sender
16+ * of the incoming message. It ensures that the reply is correctly routed to the appropriate connection.
17+ *
18+ * @param client - The `RealtimeClient` instance used to send the reply.
19+ * @param message - The incoming message to which the reply is responding.
20+ * @returns A `ReplyFunction` that sends a reply message.
21+ * @throws Error if the connection ID is not available in the incoming message.
1922 */
2023const reply =
2124 ( client : RealtimeClient , message : IncomingMessage ) : ReplyFunction =>
@@ -45,40 +48,32 @@ const reply =
4548
4649/**
4750 * Class representing a factory for waiting on acknowledgements or replies.
51+ *
52+ * The `WaitFor` class provides methods to wait for acknowledgements from the Messaging Gateway
53+ * or replies from other subscribers or backend services. It is used in conjunction with
54+ * message publishing and sending methods to ensure reliable communication.
4855 */
4956class WaitFor implements WaitForFactory {
5057 private client : RealtimeClient
5158 private options : MessageOptions
5259
5360 /**
54- * Initializes a new instance of the WaitFor class.
61+ * Initializes a new instance of the ` WaitFor` class.
5562 *
56- * @param client - The RealtimeClient instance.
57- * @param options - The message options.
63+ * @param client - The ` RealtimeClient` instance associated with this factory .
64+ * @param options - The message options used for publishing or sending messages .
5865 */
5966 constructor ( client : RealtimeClient , options : MessageOptions ) {
6067 this . client = client
6168 this . options = options
6269 }
6370
64- /**
65- * Waits for an acknowledgement of the message.
66- *
67- * @param timeout - The timeout in milliseconds (default is 5000 ms).
68- * @returns A promise that resolves when an acknowledgement is received.
69- */
7071 waitForAck ( timeout : number = 5000 ) : CancelablePromise < any [ ] > {
7172 return this . client . waitFor ( `ack.${ this . options . id } ` , {
7273 timeout,
7374 } as WaitForOptions )
7475 }
7576
76- /**
77- * Waits for a reply to the message.
78- *
79- * @param timeout - The timeout in milliseconds (default is 5000 ms).
80- * @returns A promise that resolves when a reply is received.
81- */
8277 waitForReply ( timeout : number = 5000 ) : CancelablePromise < any [ ] > {
8378 return this . client . waitFor ( `response.${ this . options . id } ` , {
8479 timeout,
@@ -88,27 +83,30 @@ class WaitFor implements WaitForFactory {
8883
8984/**
9085 * RealtimeClient class encapsulates WebSocket connection, subscription, and message handling.
86+ *
87+ * The `RealtimeClient` is the core class for interacting with the Realtime Pub/Sub service. It manages the WebSocket
88+ * connection, handles message publishing and subscribing, and provides mechanisms to wait for acknowledgements and replies.
9189 */
9290export class RealtimeClient extends EventEmitter2 {
9391 private ws : ReconnectingWebSocket | null = null
9492 private opts : ClientOptions
9593
9694 /**
97- * Initializes a new instance of the RealtimeClient class.
95+ * Initializes a new instance of the ` RealtimeClient` class.
9896 *
99- * @param config - The client configuration options.
97+ * @param config - The client configuration options, including WebSocket settings, logger, and event emitter options .
10098 */
10199 constructor ( config : ClientOptions ) {
102100 super ( { ...config . emitterOptions , wildcard : true } )
103101 this . opts = config
104102
105- // Listen for acknowledgement messages
103+ // Listen for acknowledgment messages from the Messaging Gateway
106104 this . on ( 'priv/acks.ack' , ( message : IncomingMessage ) => {
107105 this . opts . logger ?. debug ( 'Received ack:' , message . data )
108106 this . emit ( `ack.${ message . data . data } ` )
109107 } )
110108
111- // Listen for response messages
109+ // Listen for response messages from other subscribers or backend services
112110 this . on ( '*.response' , ( message : IncomingMessage ) => {
113111 if ( message . topic . startsWith ( 'priv/' ) ) {
114112 this . opts . logger ?. debug ( 'Received response:' , message . data )
@@ -117,7 +115,7 @@ export class RealtimeClient extends EventEmitter2 {
117115 }
118116 } )
119117
120- // Wait for 'welcome' message to trigger session.started event
118+ // Listen for the 'welcome' message to trigger the ' session.started' event
121119 this . on ( 'main.welcome' , ( message : IncomingMessage ) => {
122120 this . opts . logger ?. info ( 'Session started!' )
123121
@@ -128,7 +126,12 @@ export class RealtimeClient extends EventEmitter2 {
128126 /**
129127 * Establishes a connection to the WebSocket server.
130128 *
131- * @returns A promise that resolves with the connection information.
129+ * Initiates the WebSocket connection using the provided URL from the `urlProvider` function.
130+ * Sets up event handlers for incoming messages, errors, and closure events.
131+ *
132+ * @returns A promise that resolves when the connection is successfully established.
133+ *
134+ * @throws `Error` if the WebSocket instance is not initialized or if an error occurs during connection.
132135 */
133136 async connect ( ) : Promise < void > {
134137 this . ws = new ReconnectingWebSocket (
@@ -142,13 +145,18 @@ export class RealtimeClient extends EventEmitter2 {
142145 return reject ( new Error ( 'WebSocket instance is not initialized' ) )
143146 }
144147
148+ // Bind the onMessage handler to process incoming WebSocket messages
145149 this . ws . onmessage = this . onMessage . bind ( this )
150+
151+ // Handle WebSocket errors
146152 this . ws . onerror = ( event : ErrorEvent ) => {
147153 const error = new Error ( 'WebSocket error event' )
148154 this . handleError ( error )
149155
150156 reject ( error )
151157 }
158+
159+ // Handle WebSocket closure
152160 this . ws . onclose = this . handleClose . bind ( this )
153161
154162 resolve ( )
@@ -158,7 +166,9 @@ export class RealtimeClient extends EventEmitter2 {
158166 /**
159167 * Disconnects from the WebSocket server.
160168 *
161- * @returns The RealtimeClient instance.
169+ * Closes the active WebSocket connection and cleans up resources.
170+ *
171+ * @returns The `RealtimeClient` instance for method chaining.
162172 */
163173 disconnect ( ) : RealtimeClient {
164174 if ( this . ws ) {
@@ -169,13 +179,23 @@ export class RealtimeClient extends EventEmitter2 {
169179 }
170180
171181 /**
172- * Publishes a message to a topic.
182+ * Publishes a message to a specified topic.
183+ *
184+ * Sends a message payload to the designated topic, allowing subscribers to receive and process it.
185+ * Returns a `WaitForFactory` instance to enable waiting for acknowledgements or replies.
173186 *
174- * @param topic - The topic to publish to.
175- * @param payload - The message payload.
176- * @param options - The message options.
177- * @returns A WaitForFactory instance to wait for acknowledgements or replies.
178- * @throws Error if the WebSocket connection is not established.
187+ * @param topic - The topic to publish the message to.
188+ * @param payload - The message payload, which can be a string or an object.
189+ * @param options - Optional message options, including `id`, `messageType`, and `compress`.
190+ *
191+ * @returns A `WaitForFactory` instance to wait for acknowledgements or replies.
192+ *
193+ * @throws `Error` if the WebSocket connection is not established.
194+ *
195+ * @example
196+ * ```typescript
197+ * await client.publish('chat', 'Hello, world!', { messageType: 'text-message' }).waitForAck();
198+ * ```
179199 */
180200 publish (
181201 topic : string ,
@@ -206,12 +226,27 @@ export class RealtimeClient extends EventEmitter2 {
206226 }
207227
208228 /**
209- * Sends a message to the server.
229+ * Sends a message directly to the server.
230+ *
231+ * Useful for scenarios where you need to send messages to backend services.
232+ * Returns a `WaitForFactory` instance to enable waiting for acknowledgements or replies.
210233 *
211- * @param payload - The message payload.
212- * @param options - The message options.
213- * @returns A WaitForFactory instance to wait for acknowledgements or replies.
214- * @throws Error if the WebSocket connection is not established.
234+ * **Reference:**
235+ * - [WebSocket Inbound Messaging Documentation](https://realtime.21no.de/documentation/#websocket-inbound-messaging)
236+ *
237+ *
238+ * @param payload - The message payload, which can be a string or an object.
239+ * @param options - Optional message options, including `id`, `messageType`, and `compress`.
240+ *
241+ * @returns A `WaitForFactory` instance to wait for acknowledgements or replies.
242+ *
243+ * @throws `Error` if the WebSocket connection is not established.
244+ *
245+ * @example
246+ * ```typescript
247+ * const [response] = await client.send('Get server status', { messageType: 'get-status' }).waitForReply();
248+ * console.log('Server status:', response.data.status);
249+ * ```
215250 */
216251 send (
217252 payload : string | Record < string , any > ,
@@ -240,11 +275,20 @@ export class RealtimeClient extends EventEmitter2 {
240275 }
241276
242277 /**
243- * Subscribes to a topic.
278+ * Subscribes to a remote topic to receive messages.
279+ *
280+ * Establishes a subscription to the specified topic, enabling the client to receive messages published to it.
244281 *
245282 * @param topic - The topic to subscribe to.
246- * @returns The RealtimeClient instance.
247- * @throws Error if the WebSocket connection is not established.
283+ *
284+ * @returns The `RealtimeClient` instance for method chaining.
285+ *
286+ * @throws `Error` if the WebSocket connection is not established.
287+ *
288+ * @example
289+ * ```typescript
290+ * client.subscribeRemoteTopic('notifications');
291+ * ```
248292 */
249293 subscribeRemoteTopic ( topic : string ) : RealtimeClient {
250294 if ( this . ws ) {
@@ -262,11 +306,20 @@ export class RealtimeClient extends EventEmitter2 {
262306 }
263307
264308 /**
265- * Unsubscribes from a topic.
309+ * Unsubscribes from a previously subscribed topic.
310+ *
311+ * Removes the subscription to the specified topic, stopping the client from receiving further messages from it.
266312 *
267313 * @param topic - The topic to unsubscribe from.
268- * @returns The RealtimeClient instance.
269- * @throws Error if the WebSocket connection is not established.
314+ *
315+ * @returns The `RealtimeClient` instance for method chaining.
316+ *
317+ * @throws `Error` if the WebSocket connection is not established.
318+ *
319+ * @example
320+ * ```typescript
321+ * client.unsubscribeRemoteTopic('notifications');
322+ * ```
270323 */
271324 unsubscribeRemoteTopic ( topic : string ) : RealtimeClient {
272325 if ( this . ws ) {
@@ -284,10 +337,18 @@ export class RealtimeClient extends EventEmitter2 {
284337 }
285338
286339 /**
287- * Waits for a specified duration.
340+ * Waits for a specified duration before proceeding.
341+ *
342+ * Useful for introducing delays or pacing message sending in your application flow.
288343 *
289344 * @param ms - The duration to wait in milliseconds.
345+ *
290346 * @returns A promise that resolves after the specified time.
347+ *
348+ * @example
349+ * ```typescript
350+ * await client.wait(1000); // Wait for 1 second
351+ * ```
291352 */
292353 wait ( ms : number ) : Promise < void > {
293354 return new Promise ( ( resolve ) => setTimeout ( resolve , ms ) )
@@ -296,7 +357,14 @@ export class RealtimeClient extends EventEmitter2 {
296357 /**
297358 * Generates a random identifier string.
298359 *
299- * @returns A random string.
360+ * Utilizes a simple random string generation method to create unique message identifiers.
361+ *
362+ * @returns A random string suitable for use as a message ID.
363+ *
364+ * @example
365+ * ```typescript
366+ * const messageId = client.getRandomId();
367+ * ```
300368 */
301369 private getRandomId ( ) : string {
302370 return Math . random ( ) . toString ( 36 ) . substring ( 2 )
@@ -305,25 +373,33 @@ export class RealtimeClient extends EventEmitter2 {
305373 /**
306374 * Handles incoming WebSocket messages.
307375 *
308- * @param event - The message event from the WebSocket.
376+ * Processes messages received from the WebSocket connection, deserializes them,
377+ * and emits appropriate events based on the message topic and type.
378+ *
379+ * @param event - The message event received from the WebSocket.
309380 */
310381 private async onMessage ( event : MessageEvent ) : Promise < void > {
311382 let messageData : any
312383
313384 try {
314385 if ( this . opts . websocketOptions . messageDeserializer ) {
386+ // Use custom message deserializer if provided
315387 messageData = this . opts . websocketOptions . messageDeserializer ( event . data )
316388 } else if ( event . data instanceof Blob ) {
389+ // Handle Blob data by converting to text
317390 messageData = JSON . parse ( await event . data . text ( ) )
318391 } else if ( typeof event . data === 'string' ) {
392+ // Handle string data by parsing JSON
319393 messageData = JSON . parse ( event . data )
320394 } else if ( event . data instanceof ArrayBuffer ) {
395+ // Handle ArrayBuffer data by decoding to string
321396 messageData = JSON . parse ( new TextDecoder ( ) . decode ( event . data ) )
322397 } else {
323398 throw new Error ( 'Unable to deserialize incoming message' )
324399 }
325400 } catch ( error ) {
326- this . handleError ( error )
401+ // Handle deserialization errors
402+ this . handleError ( error as Error )
327403 return
328404 }
329405
@@ -338,6 +414,7 @@ export class RealtimeClient extends EventEmitter2 {
338414 this . opts . logger ?. debug ( '> Incoming message:' , messageEvent )
339415
340416 if ( messageType ) {
417+ // Emit an event based on the topic and message type
341418 this . emit (
342419 `${ topic } .${ messageType } ` ,
343420 messageEvent ,
@@ -347,9 +424,9 @@ export class RealtimeClient extends EventEmitter2 {
347424 }
348425
349426 /**
350- * Handles WebSocket errors.
427+ * Handles WebSocket errors by logging and emitting an 'error' event .
351428 *
352- * @param error - The error object.
429+ * @param error - The error object encountered during WebSocket communication .
353430 */
354431 private handleError ( error : Error ) : void {
355432 this . opts . logger ?. error ( 'WebSocket error:' , error )
@@ -358,9 +435,9 @@ export class RealtimeClient extends EventEmitter2 {
358435 }
359436
360437 /**
361- * Handles WebSocket closure events.
438+ * Handles WebSocket closure events by logging and emitting a 'close' event .
362439 *
363- * @param event - The close event from the WebSocket.
440+ * @param event - The close event received from the WebSocket.
364441 */
365442 private handleClose ( event : CloseEvent ) : void {
366443 this . opts . logger ?. info ( 'WebSocket closed:' , {
0 commit comments