@@ -9,29 +9,53 @@ type Headers = {
99 [key: string]: string;
1010}
1111
12- type RealtimeEvent = {
13- project: string;
14- permissions: string[];
15- data: string;
12+ type RealtimeResponse = {
13+ type: "error"|"event"|"connected"|"response";
14+ data: RealtimeResponseAuthenticated|RealtimeResponseConnected|RealtimeResponseError|RealtimeResponseEvent;
1615}
1716
18- type RealtimeMessage = {
19- code?: number;
17+ type RealtimeRequest = {
18+ type: "authentication";
19+ data: RealtimeRequestAuthenticate;
20+ }
21+
22+ type RealtimeResponseEvent = {
2023 event: string;
2124 channels: string[];
2225 timestamp: number;
2326 payload: unknown;
2427}
2528
29+ type RealtimeResponseError = {
30+ code: number;
31+ message: string;
32+ }
33+
34+ type RealtimeResponseConnected = {
35+ channels: string[];
36+ user?: object;
37+ }
38+
39+ type RealtimeResponseAuthenticated = {
40+ to: string;
41+ success: boolean;
42+ user: object;
43+ }
44+
45+ type RealtimeRequestAuthenticate = {
46+ session: string;
47+ }
48+
2649type RealtimeObject = {
2750 socket?: WebSocket;
2851 timeout?: number;
29- lastMessage?: RealtimeMessage ;
52+ lastMessage?: RealtimeResponse ;
3053 channels: {
31- [key: string]: ((event: unknown ) => void)[]
54+ [key: string]: ((event: MessageEvent ) => void)[]
3255 },
3356 createSocket: () => void;
34- onMessage: (channel: string, callback: (response: RealtimeMessage) => void) => (event: unknown) => void;
57+ authenticate: (event: MessageEvent) => void;
58+ onMessage: (channel: string, callback: (response: RealtimeResponseEvent) => void) => (event: MessageEvent) => void;
3559}
3660
3761class {{spec .title | caseUcfirst }}Exception extends Error {
@@ -126,6 +150,7 @@ class {{ spec.title | caseUcfirst }} {
126150 }
127151
128152 this.realtime.socket = new WebSocket(this.config.endpointRealtime + '/realtime?' + channels.toString());
153+ this.realtime.socket?.addEventListener('message', this.realtime.authenticate);
129154
130155 for (const channel in this.realtime.channels) {
131156 this.realtime.channels[channel].forEach(callback => {
@@ -134,7 +159,7 @@ class {{ spec.title | caseUcfirst }} {
134159 }
135160
136161 this.realtime.socket.addEventListener('close', event => {
137- if (this.realtime?.lastMessage?.code === 1008) {
162+ if (this.realtime?.lastMessage?.type === 'error' && (< RealtimeResponseError >this.realtime?.lastMessage.data). code === 1008) {
138163 return;
139164 }
140165 console.error('Realtime got disconnected. Reconnect will be attempted in 1 second.', event.reason);
@@ -143,16 +168,35 @@ class {{ spec.title | caseUcfirst }} {
143168 }, 1000);
144169 })
145170 },
171+ authenticate: (event) => {
172+ const message: RealtimeResponse = JSON.parse(event.data);
173+ if (message.type === 'connected') {
174+ const cookie = JSON.parse(window.localStorage.getItem('cookieFallback') ?? "{}");
175+ const session = cookie?.[`a_session_${this.config.project}`];
176+ const data = <RealtimeResponseConnected >message.data;
177+
178+ if (session && !data.user) {
179+ this.realtime.socket?.send(JSON.stringify(<RealtimeRequest >{
180+ type: "authentication",
181+ data: {
182+ session
183+ }
184+ }));
185+ }
186+ }
187+ },
146188 onMessage: (channel, callback) =>
147189 (event) => {
148190 try {
149- const data = JSON.parse((<RealtimeEvent >event).data);
150- this.realtime.lastMessage = data;
151-
152- if (data.channels && data.channels.includes(channel)) {
153- callback(data);
154- } else if (data.code) {
155- throw data;
191+ const message: RealtimeResponse = JSON.parse(event.data);
192+ this.realtime.lastMessage = message;
193+ if (message.type === 'event') {
194+ let data = <RealtimeResponseEvent >message.data;
195+ if (data.channels && data.channels.includes(channel)) {
196+ callback(data);
197+ }
198+ } else if (message.type === 'error') {
199+ throw message.data;
156200 }
157201 } catch (e) {
158202 console.error(e);
@@ -185,7 +229,7 @@ class {{ spec.title | caseUcfirst }} {
185229 * @param {(payload: RealtimeMessage) => void} callback Is called on every realtime update.
186230 * @returns {() => void} Unsubscribes from events.
187231 */
188- subscribe(channels: string | string[], callback: (payload: RealtimeMessage ) => void): () => void {
232+ subscribe(channels: string | string[], callback: (payload: RealtimeResponseEvent ) => void): () => void {
189233 let channelArray = typeof channels === 'string' ? [channels] : channels;
190234 let savedChannels: {
191235 name: string;
@@ -196,7 +240,7 @@ class {{ spec.title | caseUcfirst }} {
196240 this.realtime.channels[channel] = [];
197241 }
198242 savedChannels[index] = {
199- name: channel,
243+ name: channel,
200244 index: (this.realtime.channels[channel].push(this.realtime.onMessage(channel, callback)) - 1)
201245 };
202246 clearTimeout(this.realtime.timeout);
0 commit comments