@@ -21,6 +21,18 @@ export type RealtimeResponseEvent<T = any> = {
2121 payload: T;
2222}
2323
24+ export type RealtimeResponseConnected = {
25+ channels: string[];
26+ user?: object;
27+ }
28+
29+ export type RealtimeRequest = {
30+ type: 'authentication';
31+ data: {
32+ session: string;
33+ };
34+ }
35+
2436export enum RealtimeCode {
2537 NORMAL_CLOSURE = 1000,
2638 POLICY_VIOLATION = 1008,
@@ -31,6 +43,7 @@ export class Realtime {
3143 private readonly TYPE_ERROR = 'error';
3244 private readonly TYPE_EVENT = 'event';
3345 private readonly TYPE_PONG = 'pong';
46+ private readonly TYPE_CONNECTED = 'connected';
3447 private readonly DEBOUNCE_MS = 1;
3548 private readonly HEARTBEAT_INTERVAL = 20000; // 20 seconds in milliseconds
3649
@@ -332,6 +345,9 @@ export class Realtime {
332345 }
333346
334347 switch (message.type) {
348+ case this.TYPE_CONNECTED:
349+ this.handleResponseConnected(message);
350+ break;
335351 case this.TYPE_ERROR:
336352 this.handleResponseError(message);
337353 break;
@@ -344,6 +360,33 @@ export class Realtime {
344360 }
345361 }
346362
363+ private handleResponseConnected(message: RealtimeResponse): void {
364+ if (!message.data) {
365+ return;
366+ }
367+
368+ const messageData = message.data as RealtimeResponseConnected;
369+
370+ let session = this.client.config?.session;
371+ if (!session) {
372+ try {
373+ const cookie = JSON.parse(window.localStorage.getItem('cookieFallback') ?? '{}');
374+ session = cookie?.[`a_session_${this.client.config.project}`];
375+ } catch (error) {
376+ console.error('Failed to parse cookie fallback:', error);
377+ }
378+ }
379+
380+ if (session && !messageData.user) {
381+ this.socket?.send(JSON.stringify(<RealtimeRequest >{
382+ type: 'authentication',
383+ data: {
384+ session
385+ }
386+ }));
387+ }
388+ }
389+
347390 private handleResponseError(message: RealtimeResponse): void {
348391 const error = new {{spec .title | caseUcfirst }}Exception(
349392 message.data?.message || 'Unknown error'
0 commit comments