@thewhateverapp/platform 0.7.25 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,4 +8,6 @@ export { TileStateClient } from './tile-state';
8
8
  export type * from './tile-state/types';
9
9
  export { MobileAuthClient, AuthError } from './auth';
10
10
  export type * from './auth/types';
11
+ export { RealtimeClient, useRealtime } from './realtime';
12
+ export type * from './realtime/types';
11
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,mBAAmB,oBAAoB,CAAC;AAGxC,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACrD,mBAAmB,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,mBAAmB,oBAAoB,CAAC;AAGxC,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACrD,mBAAmB,cAAc,CAAC;AAGlC,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzD,mBAAmB,kBAAkB,CAAC"}
@@ -8,4 +8,6 @@
8
8
  export { TileStateClient } from './tile-state';
9
9
  // Mobile Authentication client
10
10
  export { MobileAuthClient, AuthError } from './auth';
11
+ // Realtime WebSocket client and React hook
12
+ export { RealtimeClient, useRealtime } from './realtime';
11
13
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,sCAAsC;AACtC,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAG/C,+BAA+B;AAC/B,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,sCAAsC;AACtC,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAG/C,+BAA+B;AAC/B,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAGrD,2CAA2C;AAC3C,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Client-side Realtime Module
3
+ *
4
+ * Provides WebSocket-based real-time pub/sub for tile apps.
5
+ * Includes both a vanilla JavaScript client and a React hook.
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * import { useRealtime } from '@thewhateverapp/platform/client';
10
+ *
11
+ * function Counter() {
12
+ * const { lastMessage, isConnected } = useRealtime<{ count: number }>('my-app', {
13
+ * channels: ['counter'],
14
+ * });
15
+ *
16
+ * return (
17
+ * <div>
18
+ * <p>Status: {isConnected ? 'Connected' : 'Disconnected'}</p>
19
+ * <p>Count: {lastMessage?.data.count ?? 0}</p>
20
+ * </div>
21
+ * );
22
+ * }
23
+ * ```
24
+ */
25
+ import type { RealtimeClientConfig, UseRealtimeOptions, UseRealtimeReturn, MessageHandler, StateChangeHandler, RealtimeConnectionState } from './types';
26
+ export type * from './types';
27
+ /**
28
+ * RealtimeClient - Vanilla JavaScript WebSocket client
29
+ *
30
+ * Handles WebSocket connection, reconnection, and message handling.
31
+ * Can be used without React for vanilla JS applications.
32
+ *
33
+ * @example
34
+ * ```typescript
35
+ * const client = new RealtimeClient({
36
+ * appId: 'my-app',
37
+ * channels: ['counter'],
38
+ * });
39
+ *
40
+ * client.on('counter', (data) => {
41
+ * console.log('Counter updated:', data);
42
+ * });
43
+ *
44
+ * client.connect();
45
+ * ```
46
+ */
47
+ export declare class RealtimeClient {
48
+ private config;
49
+ private ws;
50
+ private state;
51
+ private subscribedChannels;
52
+ private messageHandlers;
53
+ private anyMessageHandlers;
54
+ private stateChangeHandlers;
55
+ private reconnectAttempts;
56
+ private reconnectTimeout;
57
+ private pingInterval;
58
+ constructor(config: RealtimeClientConfig);
59
+ /**
60
+ * Get current connection state
61
+ */
62
+ get connectionState(): RealtimeConnectionState;
63
+ /**
64
+ * Get subscribed channels
65
+ */
66
+ get channels(): string[];
67
+ /**
68
+ * Connect to the realtime server
69
+ */
70
+ connect(): void;
71
+ /**
72
+ * Disconnect from the realtime server
73
+ */
74
+ disconnect(): void;
75
+ /**
76
+ * Subscribe to a channel
77
+ */
78
+ subscribe(channel: string): void;
79
+ /**
80
+ * Unsubscribe from a channel
81
+ */
82
+ unsubscribe(channel: string): void;
83
+ /**
84
+ * Publish data to a channel (client-to-server-to-all)
85
+ */
86
+ publish(channel: string, data: unknown): void;
87
+ /**
88
+ * Add a message handler for a specific channel
89
+ */
90
+ on<T = unknown>(channel: string, handler: MessageHandler<T>): () => void;
91
+ /**
92
+ * Add a handler for all messages
93
+ */
94
+ onAny(handler: (channel: string, data: unknown) => void): () => void;
95
+ /**
96
+ * Add a connection state change handler
97
+ */
98
+ onStateChange(handler: StateChangeHandler): () => void;
99
+ private setupWebSocketHandlers;
100
+ private handleMessage;
101
+ private handleDisconnect;
102
+ private setState;
103
+ private send;
104
+ private startPingInterval;
105
+ private clearPingInterval;
106
+ private clearReconnectTimeout;
107
+ }
108
+ /**
109
+ * useRealtime - React hook for real-time pub/sub
110
+ *
111
+ * Provides a simple interface for subscribing to channels and receiving
112
+ * real-time updates in React components.
113
+ *
114
+ * @param appId - App ID for channel isolation
115
+ * @param options - Hook options
116
+ * @returns Realtime state and controls
117
+ *
118
+ * @example
119
+ * ```tsx
120
+ * function Counter() {
121
+ * const { lastMessage, isConnected, publish } = useRealtime<{ count: number }>('my-app', {
122
+ * channels: ['counter'],
123
+ * });
124
+ *
125
+ * return (
126
+ * <div>
127
+ * <p>Connected: {isConnected ? 'Yes' : 'No'}</p>
128
+ * <p>Count: {lastMessage?.data.count ?? 0}</p>
129
+ * <button onClick={() => publish('counter', { count: 42 })}>
130
+ * Update
131
+ * </button>
132
+ * </div>
133
+ * );
134
+ * }
135
+ * ```
136
+ */
137
+ export declare function useRealtime<T = unknown>(appId: string, options?: UseRealtimeOptions): UseRealtimeReturn<T>;
138
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/realtime/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAGH,OAAO,KAAK,EACV,oBAAoB,EACpB,kBAAkB,EAClB,iBAAiB,EACjB,cAAc,EACd,kBAAkB,EAClB,uBAAuB,EAExB,MAAM,SAAS,CAAC;AAGjB,mBAAmB,SAAS,CAAC;AAE7B;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAiC;IAC/C,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,KAAK,CAA2C;IACxD,OAAO,CAAC,kBAAkB,CAA0B;IACpD,OAAO,CAAC,eAAe,CAA+C;IACtE,OAAO,CAAC,kBAAkB,CAA4D;IACtF,OAAO,CAAC,mBAAmB,CAAsC;IACjE,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,gBAAgB,CAA8C;IACtE,OAAO,CAAC,YAAY,CAA+C;gBAEvD,MAAM,EAAE,oBAAoB;IAiBxC;;OAEG;IACH,IAAI,eAAe,IAAI,uBAAuB,CAE7C;IAED;;OAEG;IACH,IAAI,QAAQ,IAAI,MAAM,EAAE,CAEvB;IAED;;OAEG;IACH,OAAO,IAAI,IAAI;IAwBf;;OAEG;IACH,UAAU,IAAI,IAAI;IAalB;;OAEG;IACH,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAYhC;;OAEG;IACH,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAYlC;;OAEG;IACH,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI;IAS7C;;OAEG;IACH,EAAE,CAAC,CAAC,GAAG,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI;IAaxE;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI;IAQpE;;OAEG;IACH,aAAa,CAAC,OAAO,EAAE,kBAAkB,GAAG,MAAM,IAAI;IAUtD,OAAO,CAAC,sBAAsB;IA4B9B,OAAO,CAAC,aAAa;IAiDrB,OAAO,CAAC,gBAAgB;IA2BxB,OAAO,CAAC,QAAQ;IAchB,OAAO,CAAC,IAAI;IAMZ,OAAO,CAAC,iBAAiB;IAQzB,OAAO,CAAC,iBAAiB;IAOzB,OAAO,CAAC,qBAAqB;CAM9B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,WAAW,CAAC,CAAC,GAAG,OAAO,EACrC,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,kBAAuB,GAC/B,iBAAiB,CAAC,CAAC,CAAC,CA4GtB"}
@@ -0,0 +1,438 @@
1
+ /**
2
+ * Client-side Realtime Module
3
+ *
4
+ * Provides WebSocket-based real-time pub/sub for tile apps.
5
+ * Includes both a vanilla JavaScript client and a React hook.
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * import { useRealtime } from '@thewhateverapp/platform/client';
10
+ *
11
+ * function Counter() {
12
+ * const { lastMessage, isConnected } = useRealtime<{ count: number }>('my-app', {
13
+ * channels: ['counter'],
14
+ * });
15
+ *
16
+ * return (
17
+ * <div>
18
+ * <p>Status: {isConnected ? 'Connected' : 'Disconnected'}</p>
19
+ * <p>Count: {lastMessage?.data.count ?? 0}</p>
20
+ * </div>
21
+ * );
22
+ * }
23
+ * ```
24
+ */
25
+ import { useState, useEffect, useCallback, useRef } from 'react';
26
+ /**
27
+ * RealtimeClient - Vanilla JavaScript WebSocket client
28
+ *
29
+ * Handles WebSocket connection, reconnection, and message handling.
30
+ * Can be used without React for vanilla JS applications.
31
+ *
32
+ * @example
33
+ * ```typescript
34
+ * const client = new RealtimeClient({
35
+ * appId: 'my-app',
36
+ * channels: ['counter'],
37
+ * });
38
+ *
39
+ * client.on('counter', (data) => {
40
+ * console.log('Counter updated:', data);
41
+ * });
42
+ *
43
+ * client.connect();
44
+ * ```
45
+ */
46
+ export class RealtimeClient {
47
+ config;
48
+ ws = null;
49
+ state = 'disconnected';
50
+ subscribedChannels = new Set();
51
+ messageHandlers = new Map();
52
+ anyMessageHandlers = new Set();
53
+ stateChangeHandlers = new Set();
54
+ reconnectAttempts = 0;
55
+ reconnectTimeout = null;
56
+ pingInterval = null;
57
+ constructor(config) {
58
+ this.config = {
59
+ baseUrl: config.baseUrl || 'wss://realtime.thewhatever.app',
60
+ appId: config.appId,
61
+ channels: config.channels || [],
62
+ autoReconnect: config.autoReconnect ?? true,
63
+ reconnectDelay: config.reconnectDelay || 1000,
64
+ maxReconnectAttempts: config.maxReconnectAttempts || 10,
65
+ pingInterval: config.pingInterval || 30000,
66
+ };
67
+ // Add initial channels
68
+ for (const channel of this.config.channels) {
69
+ this.subscribedChannels.add(channel);
70
+ }
71
+ }
72
+ /**
73
+ * Get current connection state
74
+ */
75
+ get connectionState() {
76
+ return this.state;
77
+ }
78
+ /**
79
+ * Get subscribed channels
80
+ */
81
+ get channels() {
82
+ return Array.from(this.subscribedChannels);
83
+ }
84
+ /**
85
+ * Connect to the realtime server
86
+ */
87
+ connect() {
88
+ if (this.ws?.readyState === WebSocket.OPEN) {
89
+ return; // Already connected
90
+ }
91
+ this.setState('connecting');
92
+ // Build WebSocket URL
93
+ const url = new URL('/ws', this.config.baseUrl);
94
+ url.searchParams.set('appId', this.config.appId);
95
+ if (this.subscribedChannels.size > 0) {
96
+ url.searchParams.set('channels', Array.from(this.subscribedChannels).join(','));
97
+ }
98
+ try {
99
+ this.ws = new WebSocket(url.toString());
100
+ this.setupWebSocketHandlers();
101
+ }
102
+ catch (error) {
103
+ console.error('[Realtime] Failed to create WebSocket:', error);
104
+ this.handleDisconnect();
105
+ }
106
+ }
107
+ /**
108
+ * Disconnect from the realtime server
109
+ */
110
+ disconnect() {
111
+ this.clearReconnectTimeout();
112
+ this.clearPingInterval();
113
+ if (this.ws) {
114
+ this.ws.close(1000, 'Client disconnect');
115
+ this.ws = null;
116
+ }
117
+ this.setState('disconnected');
118
+ this.reconnectAttempts = 0;
119
+ }
120
+ /**
121
+ * Subscribe to a channel
122
+ */
123
+ subscribe(channel) {
124
+ if (this.subscribedChannels.has(channel)) {
125
+ return; // Already subscribed
126
+ }
127
+ this.subscribedChannels.add(channel);
128
+ if (this.ws?.readyState === WebSocket.OPEN) {
129
+ this.send({ type: 'subscribe', channel });
130
+ }
131
+ }
132
+ /**
133
+ * Unsubscribe from a channel
134
+ */
135
+ unsubscribe(channel) {
136
+ if (!this.subscribedChannels.has(channel)) {
137
+ return; // Not subscribed
138
+ }
139
+ this.subscribedChannels.delete(channel);
140
+ if (this.ws?.readyState === WebSocket.OPEN) {
141
+ this.send({ type: 'unsubscribe', channel });
142
+ }
143
+ }
144
+ /**
145
+ * Publish data to a channel (client-to-server-to-all)
146
+ */
147
+ publish(channel, data) {
148
+ if (this.ws?.readyState !== WebSocket.OPEN) {
149
+ console.warn('[Realtime] Cannot publish: not connected');
150
+ return;
151
+ }
152
+ this.send({ type: 'publish', channel, data });
153
+ }
154
+ /**
155
+ * Add a message handler for a specific channel
156
+ */
157
+ on(channel, handler) {
158
+ if (!this.messageHandlers.has(channel)) {
159
+ this.messageHandlers.set(channel, new Set());
160
+ }
161
+ this.messageHandlers.get(channel).add(handler);
162
+ // Return unsubscribe function
163
+ return () => {
164
+ this.messageHandlers.get(channel)?.delete(handler);
165
+ };
166
+ }
167
+ /**
168
+ * Add a handler for all messages
169
+ */
170
+ onAny(handler) {
171
+ this.anyMessageHandlers.add(handler);
172
+ return () => {
173
+ this.anyMessageHandlers.delete(handler);
174
+ };
175
+ }
176
+ /**
177
+ * Add a connection state change handler
178
+ */
179
+ onStateChange(handler) {
180
+ this.stateChangeHandlers.add(handler);
181
+ return () => {
182
+ this.stateChangeHandlers.delete(handler);
183
+ };
184
+ }
185
+ // ==================== Private Methods ====================
186
+ setupWebSocketHandlers() {
187
+ if (!this.ws)
188
+ return;
189
+ this.ws.addEventListener('open', () => {
190
+ this.setState('connected');
191
+ this.reconnectAttempts = 0;
192
+ this.startPingInterval();
193
+ });
194
+ this.ws.addEventListener('message', (event) => {
195
+ try {
196
+ const message = JSON.parse(event.data);
197
+ this.handleMessage(message);
198
+ }
199
+ catch (error) {
200
+ console.error('[Realtime] Failed to parse message:', error);
201
+ }
202
+ });
203
+ this.ws.addEventListener('close', (event) => {
204
+ console.log(`[Realtime] Connection closed: code=${event.code}, reason=${event.reason}`);
205
+ this.handleDisconnect();
206
+ });
207
+ this.ws.addEventListener('error', (event) => {
208
+ console.error('[Realtime] WebSocket error:', event);
209
+ });
210
+ }
211
+ handleMessage(message) {
212
+ switch (message.type) {
213
+ case 'data':
214
+ if (message.channel) {
215
+ // Notify channel-specific handlers
216
+ const handlers = this.messageHandlers.get(message.channel);
217
+ if (handlers) {
218
+ for (const handler of handlers) {
219
+ try {
220
+ handler(message.data, message.channel);
221
+ }
222
+ catch (error) {
223
+ console.error('[Realtime] Handler error:', error);
224
+ }
225
+ }
226
+ }
227
+ // Notify any-message handlers
228
+ for (const handler of this.anyMessageHandlers) {
229
+ try {
230
+ handler(message.channel, message.data);
231
+ }
232
+ catch (error) {
233
+ console.error('[Realtime] Any handler error:', error);
234
+ }
235
+ }
236
+ }
237
+ break;
238
+ case 'connected':
239
+ console.log('[Realtime] Connected, channels:', message.channels);
240
+ break;
241
+ case 'subscribed':
242
+ console.log('[Realtime] Subscribed to:', message.channel || message.channels);
243
+ break;
244
+ case 'unsubscribed':
245
+ console.log('[Realtime] Unsubscribed from:', message.channel);
246
+ break;
247
+ case 'pong':
248
+ // Heartbeat response received
249
+ break;
250
+ case 'error':
251
+ console.error('[Realtime] Server error:', message.message);
252
+ break;
253
+ }
254
+ }
255
+ handleDisconnect() {
256
+ this.clearPingInterval();
257
+ this.ws = null;
258
+ if (this.config.autoReconnect && this.state !== 'disconnected') {
259
+ if (this.config.maxReconnectAttempts === 0 ||
260
+ this.reconnectAttempts < this.config.maxReconnectAttempts) {
261
+ this.reconnectAttempts++;
262
+ this.setState('reconnecting');
263
+ const delay = this.config.reconnectDelay * Math.min(this.reconnectAttempts, 5);
264
+ console.log(`[Realtime] Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts})`);
265
+ this.reconnectTimeout = setTimeout(() => {
266
+ this.connect();
267
+ }, delay);
268
+ }
269
+ else {
270
+ console.error('[Realtime] Max reconnect attempts reached');
271
+ this.setState('disconnected');
272
+ }
273
+ }
274
+ else {
275
+ this.setState('disconnected');
276
+ }
277
+ }
278
+ setState(newState) {
279
+ if (this.state === newState)
280
+ return;
281
+ this.state = newState;
282
+ for (const handler of this.stateChangeHandlers) {
283
+ try {
284
+ handler(newState);
285
+ }
286
+ catch (error) {
287
+ console.error('[Realtime] State change handler error:', error);
288
+ }
289
+ }
290
+ }
291
+ send(message) {
292
+ if (this.ws?.readyState === WebSocket.OPEN) {
293
+ this.ws.send(JSON.stringify(message));
294
+ }
295
+ }
296
+ startPingInterval() {
297
+ if (this.config.pingInterval <= 0)
298
+ return;
299
+ this.pingInterval = setInterval(() => {
300
+ this.send({ type: 'ping' });
301
+ }, this.config.pingInterval);
302
+ }
303
+ clearPingInterval() {
304
+ if (this.pingInterval) {
305
+ clearInterval(this.pingInterval);
306
+ this.pingInterval = null;
307
+ }
308
+ }
309
+ clearReconnectTimeout() {
310
+ if (this.reconnectTimeout) {
311
+ clearTimeout(this.reconnectTimeout);
312
+ this.reconnectTimeout = null;
313
+ }
314
+ }
315
+ }
316
+ /**
317
+ * useRealtime - React hook for real-time pub/sub
318
+ *
319
+ * Provides a simple interface for subscribing to channels and receiving
320
+ * real-time updates in React components.
321
+ *
322
+ * @param appId - App ID for channel isolation
323
+ * @param options - Hook options
324
+ * @returns Realtime state and controls
325
+ *
326
+ * @example
327
+ * ```tsx
328
+ * function Counter() {
329
+ * const { lastMessage, isConnected, publish } = useRealtime<{ count: number }>('my-app', {
330
+ * channels: ['counter'],
331
+ * });
332
+ *
333
+ * return (
334
+ * <div>
335
+ * <p>Connected: {isConnected ? 'Yes' : 'No'}</p>
336
+ * <p>Count: {lastMessage?.data.count ?? 0}</p>
337
+ * <button onClick={() => publish('counter', { count: 42 })}>
338
+ * Update
339
+ * </button>
340
+ * </div>
341
+ * );
342
+ * }
343
+ * ```
344
+ */
345
+ export function useRealtime(appId, options = {}) {
346
+ const [state, setState] = useState('disconnected');
347
+ const [channels, setChannels] = useState(options.channels || []);
348
+ const [lastMessage, setLastMessage] = useState(null);
349
+ const clientRef = useRef(null);
350
+ // Initialize client
351
+ useEffect(() => {
352
+ const client = new RealtimeClient({
353
+ appId,
354
+ baseUrl: options.baseUrl,
355
+ channels: options.channels,
356
+ autoReconnect: options.autoReconnect,
357
+ reconnectDelay: options.reconnectDelay,
358
+ maxReconnectAttempts: options.maxReconnectAttempts,
359
+ });
360
+ clientRef.current = client;
361
+ // Set up state change handler
362
+ const unsubState = client.onStateChange((newState) => {
363
+ setState(newState);
364
+ if (newState === 'connected') {
365
+ options.onConnect?.();
366
+ }
367
+ else if (newState === 'disconnected') {
368
+ options.onDisconnect?.();
369
+ }
370
+ else if (newState === 'reconnecting') {
371
+ options.onReconnecting?.(client['reconnectAttempts']);
372
+ }
373
+ });
374
+ // Set up message handler
375
+ const unsubAny = client.onAny((channel, data) => {
376
+ setLastMessage({ channel, data: data });
377
+ });
378
+ // Connect
379
+ client.connect();
380
+ return () => {
381
+ unsubState();
382
+ unsubAny();
383
+ client.disconnect();
384
+ clientRef.current = null;
385
+ };
386
+ }, [appId, options.baseUrl]); // Only re-create on appId or baseUrl change
387
+ // Handle channel changes
388
+ useEffect(() => {
389
+ const client = clientRef.current;
390
+ if (!client)
391
+ return;
392
+ const currentChannels = new Set(client.channels);
393
+ const newChannels = new Set(options.channels || []);
394
+ // Subscribe to new channels
395
+ for (const channel of newChannels) {
396
+ if (!currentChannels.has(channel)) {
397
+ client.subscribe(channel);
398
+ }
399
+ }
400
+ // Unsubscribe from removed channels
401
+ for (const channel of currentChannels) {
402
+ if (!newChannels.has(channel)) {
403
+ client.unsubscribe(channel);
404
+ }
405
+ }
406
+ setChannels(client.channels);
407
+ }, [options.channels?.join(',')]);
408
+ const subscribe = useCallback((channel) => {
409
+ clientRef.current?.subscribe(channel);
410
+ setChannels(clientRef.current?.channels || []);
411
+ }, []);
412
+ const unsubscribe = useCallback((channel) => {
413
+ clientRef.current?.unsubscribe(channel);
414
+ setChannels(clientRef.current?.channels || []);
415
+ }, []);
416
+ const publish = useCallback((channel, data) => {
417
+ clientRef.current?.publish(channel, data);
418
+ }, []);
419
+ const reconnect = useCallback(() => {
420
+ clientRef.current?.disconnect();
421
+ clientRef.current?.connect();
422
+ }, []);
423
+ const disconnect = useCallback(() => {
424
+ clientRef.current?.disconnect();
425
+ }, []);
426
+ return {
427
+ state,
428
+ isConnected: state === 'connected',
429
+ channels,
430
+ lastMessage,
431
+ subscribe,
432
+ unsubscribe,
433
+ publish,
434
+ reconnect,
435
+ disconnect,
436
+ };
437
+ }
438
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/client/realtime/index.ts"],"names":[],"mappings":"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"}