@@ -19,9 +19,9 @@ type Headers = {
1919 */
2020type RealtimeResponse = {
2121 /**
22- * Type of the response: 'error', 'event', 'connected', or 'response'.
22+ * Type of the response: 'error', 'event', 'connected', 'pong', or 'response'.
2323 */
24- type: 'error' | 'event' | 'connected' | 'response';
24+ type: 'error' | 'event' | 'connected' | 'response' | 'pong' ;
2525
2626 /**
2727 * Data associated with the response based on the response type.
@@ -139,9 +139,14 @@ type Realtime = {
139139 socket?: WebSocket;
140140
141141 /**
142- * Timeout duration for communication operations.
142+ * Timeout for reconnect operations.
143143 */
144- timeout?: number;
144+ timeout?: ReturnType<typeof setTimeout >;
145+
146+ /**
147+ * Heartbeat interval for the realtime connection.
148+ */
149+ heartbeat?: ReturnType<typeof setTimeout >;
145150
146151 /**
147152 * URL for establishing the WebSocket connection.
@@ -196,6 +201,11 @@ type Realtime = {
196201 */
197202 createSocket: () => void;
198203
204+ /**
205+ * Function to create a new heartbeat interval.
206+ */
207+ createHeartbeat: () => void;
208+
199209 /**
200210 * Function to clean up resources associated with specified channels.
201211 *
@@ -359,6 +369,7 @@ class Client {
359369 private realtime: Realtime = {
360370 socket: undefined,
361371 timeout: undefined,
372+ heartbeat: undefined,
362373 url: '',
363374 channels: new Set(),
364375 subscriptions: new Map(),
@@ -384,6 +395,17 @@ class Client {
384395 return 60_000;
385396 }
386397 },
398+ createHeartbeat: () => {
399+ if (this.realtime.heartbeat) {
400+ clearTimeout(this.realtime.heartbeat);
401+ }
402+
403+ this.realtime.heartbeat = window?.setInterval(() => {
404+ this.realtime.socket?.send(JSON.stringify({
405+ type: 'ping'
406+ }));
407+ }, 20_000);
408+ },
387409 createSocket: () => {
388410 if (this.realtime.channels.size < 1) {
389411 this.realtime.reconnect = false;
@@ -417,6 +439,7 @@ class Client {
417439 this.realtime.socket.addEventListener('message', this.realtime.onMessage);
418440 this.realtime.socket.addEventListener('open', _event => {
419441 this.realtime.reconnectAttempts = 0;
442+ this.realtime.createHeartbeat();
420443 });
421444 this.realtime.socket.addEventListener('close', event => {
422445 if (
@@ -497,10 +520,10 @@ class Client {
497520
498521 /**
499522 * Subscribes to {{spec .title | caseUcfirst }} events and passes you the payload in realtime.
500- *
501- * @param {string|string[]} channels
523+ *
524+ * @param {string|string[]} channels
502525 * Channel to subscribe - pass a single channel as a string or multiple with an array of strings.
503- *
526+ *
504527 * Possible channels are:
505528 * - account
506529 * - collections
@@ -628,7 +651,7 @@ class Client {
628651
629652 async redirect(method: string, url: URL, headers: Headers = {}, params: Payload = {}): Promise<string > {
630653 const { uri, options } = this.prepareRequest(method, url, headers, params);
631-
654+
632655 const response = await fetch(uri, {
633656 ...options,
634657 redirect: 'manual'
0 commit comments