Skip to content

Commit 335b309

Browse files
committed
Refactor interfaces.ts: Add comments and descriptions for connection, message, reply, response, logger, WebSocket, and client options
1 parent 1165291 commit 335b309

File tree

2 files changed

+332
-51
lines changed

2 files changed

+332
-51
lines changed

libs/client.ts

Lines changed: 128 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -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
*/
2023
const 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
*/
4956
class 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
*/
9290
export 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

Comments
 (0)