@supabase/realtime-js 2.80.1-canary.2 → 2.80.1-canary.3

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.
Files changed (35) hide show
  1. package/dist/main/RealtimeClient.d.ts +2 -0
  2. package/dist/main/RealtimeClient.d.ts.map +1 -1
  3. package/dist/main/RealtimeClient.js +23 -8
  4. package/dist/main/RealtimeClient.js.map +1 -1
  5. package/dist/main/lib/constants.d.ts +5 -3
  6. package/dist/main/lib/constants.d.ts.map +1 -1
  7. package/dist/main/lib/constants.js +4 -2
  8. package/dist/main/lib/constants.js.map +1 -1
  9. package/dist/main/lib/serializer.d.ts +30 -0
  10. package/dist/main/lib/serializer.d.ts.map +1 -1
  11. package/dist/main/lib/serializer.js +198 -6
  12. package/dist/main/lib/serializer.js.map +1 -1
  13. package/dist/main/lib/version.d.ts +1 -1
  14. package/dist/main/lib/version.js +1 -1
  15. package/dist/module/RealtimeClient.d.ts +2 -0
  16. package/dist/module/RealtimeClient.d.ts.map +1 -1
  17. package/dist/module/RealtimeClient.js +24 -9
  18. package/dist/module/RealtimeClient.js.map +1 -1
  19. package/dist/module/lib/constants.d.ts +5 -3
  20. package/dist/module/lib/constants.d.ts.map +1 -1
  21. package/dist/module/lib/constants.js +3 -1
  22. package/dist/module/lib/constants.js.map +1 -1
  23. package/dist/module/lib/serializer.d.ts +30 -0
  24. package/dist/module/lib/serializer.d.ts.map +1 -1
  25. package/dist/module/lib/serializer.js +197 -5
  26. package/dist/module/lib/serializer.js.map +1 -1
  27. package/dist/module/lib/version.d.ts +1 -1
  28. package/dist/module/lib/version.js +1 -1
  29. package/dist/tsconfig.module.tsbuildinfo +1 -1
  30. package/dist/tsconfig.tsbuildinfo +1 -1
  31. package/package.json +1 -1
  32. package/src/RealtimeClient.ts +28 -8
  33. package/src/lib/constants.ts +4 -1
  34. package/src/lib/serializer.ts +271 -5
  35. package/src/lib/version.ts +1 -1
@@ -1,16 +1,160 @@
1
1
  // This file draws heavily from https://github.com/phoenixframework/phoenix/commit/cf098e9cf7a44ee6479d31d911a97d3c7430c6fe
2
2
  // License: https://github.com/phoenixframework/phoenix/blob/master/LICENSE.md
3
+ import { CHANNEL_EVENTS } from '../lib/constants'
4
+
5
+ export type Msg<T> = {
6
+ join_ref: string
7
+ ref: string
8
+ topic: string
9
+ event: string
10
+ payload: T
11
+ }
3
12
 
4
13
  export default class Serializer {
5
14
  HEADER_LENGTH = 1
15
+ META_LENGTH = 4
16
+ USER_BROADCAST_PUSH_META_LENGTH = 5
17
+ KINDS = { push: 0, reply: 1, broadcast: 2, userBroadcastPush: 3, userBroadcast: 4 }
18
+ BINARY_ENCODING = 0
19
+ JSON_ENCODING = 1
20
+ BROADCAST = 'broadcast'
21
+
22
+ encode(
23
+ msg: Msg<{ [key: string]: any } | ArrayBuffer>,
24
+ callback: (result: ArrayBuffer | string) => any
25
+ ) {
26
+ if (this._isArrayBuffer(msg.payload)) {
27
+ return callback(this._binaryEncodePush(msg as Msg<ArrayBuffer>))
28
+ }
29
+
30
+ if (
31
+ msg.event === this.BROADCAST &&
32
+ !(msg.payload instanceof ArrayBuffer) &&
33
+ typeof msg.payload.event === 'string'
34
+ ) {
35
+ return callback(
36
+ this._binaryEncodeUserBroadcastPush(msg as Msg<{ event: string } & { [key: string]: any }>)
37
+ )
38
+ }
39
+
40
+ let payload = [msg.join_ref, msg.ref, msg.topic, msg.event, msg.payload]
41
+ return callback(JSON.stringify(payload))
42
+ }
43
+
44
+ private _binaryEncodePush(message: Msg<ArrayBuffer>) {
45
+ const { join_ref, ref, event, topic, payload } = message
46
+ const metaLength = this.META_LENGTH + join_ref.length + ref.length + topic.length + event.length
47
+
48
+ const header = new ArrayBuffer(this.HEADER_LENGTH + metaLength)
49
+ let view = new DataView(header)
50
+ let offset = 0
51
+
52
+ view.setUint8(offset++, this.KINDS.push) // kind
53
+ view.setUint8(offset++, join_ref.length)
54
+ view.setUint8(offset++, ref.length)
55
+ view.setUint8(offset++, topic.length)
56
+ view.setUint8(offset++, event.length)
57
+ Array.from(join_ref, (char) => view.setUint8(offset++, char.charCodeAt(0)))
58
+ Array.from(ref, (char) => view.setUint8(offset++, char.charCodeAt(0)))
59
+ Array.from(topic, (char) => view.setUint8(offset++, char.charCodeAt(0)))
60
+ Array.from(event, (char) => view.setUint8(offset++, char.charCodeAt(0)))
61
+
62
+ var combined = new Uint8Array(header.byteLength + payload.byteLength)
63
+ combined.set(new Uint8Array(header), 0)
64
+ combined.set(new Uint8Array(payload), header.byteLength)
65
+
66
+ return combined.buffer
67
+ }
68
+
69
+ private _binaryEncodeUserBroadcastPush(message: Msg<{ event: string } & { [key: string]: any }>) {
70
+ if (this._isArrayBuffer(message.payload?.payload)) {
71
+ return this._encodeBinaryUserBroadcastPush(message)
72
+ } else {
73
+ return this._encodeJsonUserBroadcastPush(message)
74
+ }
75
+ }
76
+
77
+ private _encodeBinaryUserBroadcastPush(message: Msg<{ event: string } & { [key: string]: any }>) {
78
+ const { join_ref, ref, topic } = message
79
+ const userEvent = message.payload.event
80
+ const userPayload = message.payload?.payload ?? new ArrayBuffer(0)
81
+
82
+ const metaLength =
83
+ this.USER_BROADCAST_PUSH_META_LENGTH +
84
+ join_ref.length +
85
+ ref.length +
86
+ topic.length +
87
+ userEvent.length
88
+
89
+ const header = new ArrayBuffer(this.HEADER_LENGTH + metaLength)
90
+ let view = new DataView(header)
91
+ let offset = 0
92
+
93
+ view.setUint8(offset++, this.KINDS.userBroadcastPush) // kind
94
+ view.setUint8(offset++, join_ref.length)
95
+ view.setUint8(offset++, ref.length)
96
+ view.setUint8(offset++, topic.length)
97
+ view.setUint8(offset++, userEvent.length)
98
+ view.setUint8(offset++, this.BINARY_ENCODING)
99
+ Array.from(join_ref, (char) => view.setUint8(offset++, char.charCodeAt(0)))
100
+ Array.from(ref, (char) => view.setUint8(offset++, char.charCodeAt(0)))
101
+ Array.from(topic, (char) => view.setUint8(offset++, char.charCodeAt(0)))
102
+ Array.from(userEvent, (char) => view.setUint8(offset++, char.charCodeAt(0)))
103
+
104
+ var combined = new Uint8Array(header.byteLength + userPayload.byteLength)
105
+ combined.set(new Uint8Array(header), 0)
106
+ combined.set(new Uint8Array(userPayload), header.byteLength)
107
+
108
+ return combined.buffer
109
+ }
110
+
111
+ private _encodeJsonUserBroadcastPush(message: Msg<{ event: string } & { [key: string]: any }>) {
112
+ const { join_ref, ref, topic } = message
113
+ const userEvent = message.payload.event
114
+ const userPayload = message.payload?.payload ?? {}
115
+
116
+ const encoder = new TextEncoder() // Encodes to UTF-8
117
+ const encodedUserPayload = encoder.encode(JSON.stringify(userPayload)).buffer
118
+
119
+ const metaLength =
120
+ this.USER_BROADCAST_PUSH_META_LENGTH +
121
+ join_ref.length +
122
+ ref.length +
123
+ topic.length +
124
+ userEvent.length
125
+
126
+ const header = new ArrayBuffer(this.HEADER_LENGTH + metaLength)
127
+ let view = new DataView(header)
128
+ let offset = 0
129
+
130
+ view.setUint8(offset++, this.KINDS.userBroadcastPush) // kind
131
+ view.setUint8(offset++, join_ref.length)
132
+ view.setUint8(offset++, ref.length)
133
+ view.setUint8(offset++, topic.length)
134
+ view.setUint8(offset++, userEvent.length)
135
+ view.setUint8(offset++, this.JSON_ENCODING)
136
+ Array.from(join_ref, (char) => view.setUint8(offset++, char.charCodeAt(0)))
137
+ Array.from(ref, (char) => view.setUint8(offset++, char.charCodeAt(0)))
138
+ Array.from(topic, (char) => view.setUint8(offset++, char.charCodeAt(0)))
139
+ Array.from(userEvent, (char) => view.setUint8(offset++, char.charCodeAt(0)))
140
+
141
+ var combined = new Uint8Array(header.byteLength + encodedUserPayload.byteLength)
142
+ combined.set(new Uint8Array(header), 0)
143
+ combined.set(new Uint8Array(encodedUserPayload), header.byteLength)
144
+
145
+ return combined.buffer
146
+ }
6
147
 
7
148
  decode(rawPayload: ArrayBuffer | string, callback: Function) {
8
- if (rawPayload.constructor === ArrayBuffer) {
9
- return callback(this._binaryDecode(rawPayload))
149
+ if (this._isArrayBuffer(rawPayload)) {
150
+ let result = this._binaryDecode(rawPayload as ArrayBuffer)
151
+ return callback(result)
10
152
  }
11
153
 
12
154
  if (typeof rawPayload === 'string') {
13
- return callback(JSON.parse(rawPayload))
155
+ const jsonPayload = JSON.parse(rawPayload)
156
+ const [join_ref, ref, topic, event, payload] = jsonPayload
157
+ return callback({ join_ref, ref, topic, event, payload })
14
158
  }
15
159
 
16
160
  return callback({})
@@ -18,9 +162,84 @@ export default class Serializer {
18
162
 
19
163
  private _binaryDecode(buffer: ArrayBuffer) {
20
164
  const view = new DataView(buffer)
165
+ const kind = view.getUint8(0)
21
166
  const decoder = new TextDecoder()
167
+ switch (kind) {
168
+ case this.KINDS.push:
169
+ return this._decodePush(buffer, view, decoder)
170
+ case this.KINDS.reply:
171
+ return this._decodeReply(buffer, view, decoder)
172
+ case this.KINDS.broadcast:
173
+ return this._decodeBroadcast(buffer, view, decoder)
174
+ case this.KINDS.userBroadcast:
175
+ return this._decodeUserBroadcast(buffer, view, decoder)
176
+ }
177
+ }
178
+
179
+ private _decodePush(
180
+ buffer: ArrayBuffer,
181
+ view: DataView,
182
+ decoder: TextDecoder
183
+ ): {
184
+ join_ref: string
185
+ ref: null
186
+ topic: string
187
+ event: string
188
+ payload: { [key: string]: any }
189
+ } {
190
+ const joinRefSize = view.getUint8(1)
191
+ const topicSize = view.getUint8(2)
192
+ const eventSize = view.getUint8(3)
193
+ let offset = this.HEADER_LENGTH + this.META_LENGTH - 1 // pushes have no ref
194
+ const joinRef = decoder.decode(buffer.slice(offset, offset + joinRefSize))
195
+ offset = offset + joinRefSize
196
+ const topic = decoder.decode(buffer.slice(offset, offset + topicSize))
197
+ offset = offset + topicSize
198
+ const event = decoder.decode(buffer.slice(offset, offset + eventSize))
199
+ offset = offset + eventSize
200
+ const data = JSON.parse(decoder.decode(buffer.slice(offset, buffer.byteLength)))
201
+ return {
202
+ join_ref: joinRef,
203
+ ref: null,
204
+ topic: topic,
205
+ event: event,
206
+ payload: data,
207
+ }
208
+ }
22
209
 
23
- return this._decodeBroadcast(buffer, view, decoder)
210
+ private _decodeReply(
211
+ buffer: ArrayBuffer,
212
+ view: DataView,
213
+ decoder: TextDecoder
214
+ ): {
215
+ join_ref: string
216
+ ref: string
217
+ topic: string
218
+ event: CHANNEL_EVENTS.reply
219
+ payload: { status: string; response: { [key: string]: any } }
220
+ } {
221
+ const joinRefSize = view.getUint8(1)
222
+ const refSize = view.getUint8(2)
223
+ const topicSize = view.getUint8(3)
224
+ const eventSize = view.getUint8(4)
225
+ let offset = this.HEADER_LENGTH + this.META_LENGTH
226
+ const joinRef = decoder.decode(buffer.slice(offset, offset + joinRefSize))
227
+ offset = offset + joinRefSize
228
+ const ref = decoder.decode(buffer.slice(offset, offset + refSize))
229
+ offset = offset + refSize
230
+ const topic = decoder.decode(buffer.slice(offset, offset + topicSize))
231
+ offset = offset + topicSize
232
+ const event = decoder.decode(buffer.slice(offset, offset + eventSize))
233
+ offset = offset + eventSize
234
+ const data = JSON.parse(decoder.decode(buffer.slice(offset, buffer.byteLength)))
235
+ const payload = { status: event, response: data }
236
+ return {
237
+ join_ref: joinRef,
238
+ ref: ref,
239
+ topic: topic,
240
+ event: CHANNEL_EVENTS.reply,
241
+ payload: payload,
242
+ }
24
243
  }
25
244
 
26
245
  private _decodeBroadcast(
@@ -28,6 +247,7 @@ export default class Serializer {
28
247
  view: DataView,
29
248
  decoder: TextDecoder
30
249
  ): {
250
+ join_ref: null
31
251
  ref: null
32
252
  topic: string
33
253
  event: string
@@ -42,6 +262,52 @@ export default class Serializer {
42
262
  offset = offset + eventSize
43
263
  const data = JSON.parse(decoder.decode(buffer.slice(offset, buffer.byteLength)))
44
264
 
45
- return { ref: null, topic: topic, event: event, payload: data }
265
+ return { join_ref: null, ref: null, topic: topic, event: event, payload: data }
266
+ }
267
+
268
+ private _decodeUserBroadcast(
269
+ buffer: ArrayBuffer,
270
+ view: DataView,
271
+ decoder: TextDecoder
272
+ ): {
273
+ join_ref: null
274
+ ref: null
275
+ topic: string
276
+ event: string
277
+ payload: { [key: string]: any }
278
+ } {
279
+ const topicSize = view.getUint8(1)
280
+ const userEventSize = view.getUint8(2)
281
+ const metadataSize = view.getUint8(3)
282
+ const payloadEncoding = view.getUint8(4)
283
+
284
+ let offset = this.HEADER_LENGTH + 4
285
+ const topic = decoder.decode(buffer.slice(offset, offset + topicSize))
286
+ offset = offset + topicSize
287
+ const userEvent = decoder.decode(buffer.slice(offset, offset + userEventSize))
288
+ offset = offset + userEventSize
289
+ const metadata = decoder.decode(buffer.slice(offset, offset + metadataSize))
290
+ offset = offset + metadataSize
291
+
292
+ const payload = buffer.slice(offset, buffer.byteLength)
293
+ const parsedPayload =
294
+ payloadEncoding === this.JSON_ENCODING ? JSON.parse(decoder.decode(payload)) : payload
295
+
296
+ const data: { [key: string]: any } = {
297
+ type: this.BROADCAST,
298
+ event: userEvent,
299
+ payload: parsedPayload,
300
+ }
301
+
302
+ // Metadata is optional and always JSON encoded
303
+ if (metadataSize > 0) {
304
+ data['meta'] = JSON.parse(metadata)
305
+ }
306
+
307
+ return { join_ref: null, ref: null, topic: topic, event: this.BROADCAST, payload: data }
308
+ }
309
+
310
+ private _isArrayBuffer(buffer: any): boolean {
311
+ return buffer instanceof ArrayBuffer || buffer?.constructor?.name === 'ArrayBuffer'
46
312
  }
47
313
  }
@@ -4,4 +4,4 @@
4
4
  // - Debugging and support (identifying which version is running)
5
5
  // - Telemetry and logging (version reporting in errors/analytics)
6
6
  // - Ensuring build artifacts match the published package version
7
- export const version = '2.80.1-canary.2'
7
+ export const version = '2.80.1-canary.3'