@supabase/realtime-js 2.99.3-canary.0 → 2.99.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 (111) hide show
  1. package/dist/main/RealtimeChannel.d.ts +28 -35
  2. package/dist/main/RealtimeChannel.d.ts.map +1 -1
  3. package/dist/main/RealtimeChannel.js +301 -140
  4. package/dist/main/RealtimeChannel.js.map +1 -1
  5. package/dist/main/RealtimeClient.d.ts +57 -38
  6. package/dist/main/RealtimeClient.d.ts.map +1 -1
  7. package/dist/main/RealtimeClient.js +520 -232
  8. package/dist/main/RealtimeClient.js.map +1 -1
  9. package/dist/main/RealtimePresence.d.ts +24 -8
  10. package/dist/main/RealtimePresence.d.ts.map +1 -1
  11. package/dist/main/RealtimePresence.js +202 -6
  12. package/dist/main/RealtimePresence.js.map +1 -1
  13. package/dist/main/lib/constants.d.ts +35 -39
  14. package/dist/main/lib/constants.d.ts.map +1 -1
  15. package/dist/main/lib/constants.js +35 -30
  16. package/dist/main/lib/constants.js.map +1 -1
  17. package/dist/main/lib/push.d.ts +48 -0
  18. package/dist/main/lib/push.d.ts.map +1 -0
  19. package/dist/main/lib/push.js +102 -0
  20. package/dist/main/lib/push.js.map +1 -0
  21. package/dist/main/lib/timer.d.ts +22 -0
  22. package/dist/main/lib/timer.d.ts.map +1 -0
  23. package/dist/main/lib/timer.js +39 -0
  24. package/dist/main/lib/timer.js.map +1 -0
  25. package/dist/main/lib/version.d.ts +1 -1
  26. package/dist/main/lib/version.d.ts.map +1 -1
  27. package/dist/main/lib/version.js +1 -1
  28. package/dist/main/lib/version.js.map +1 -1
  29. package/dist/main/lib/websocket-factory.d.ts +9 -0
  30. package/dist/main/lib/websocket-factory.d.ts.map +1 -1
  31. package/dist/main/lib/websocket-factory.js +12 -0
  32. package/dist/main/lib/websocket-factory.js.map +1 -1
  33. package/dist/module/RealtimeChannel.d.ts +28 -35
  34. package/dist/module/RealtimeChannel.d.ts.map +1 -1
  35. package/dist/module/RealtimeChannel.js +302 -141
  36. package/dist/module/RealtimeChannel.js.map +1 -1
  37. package/dist/module/RealtimeClient.d.ts +57 -38
  38. package/dist/module/RealtimeClient.d.ts.map +1 -1
  39. package/dist/module/RealtimeClient.js +521 -233
  40. package/dist/module/RealtimeClient.js.map +1 -1
  41. package/dist/module/RealtimePresence.d.ts +24 -8
  42. package/dist/module/RealtimePresence.d.ts.map +1 -1
  43. package/dist/module/RealtimePresence.js +202 -5
  44. package/dist/module/RealtimePresence.js.map +1 -1
  45. package/dist/module/lib/constants.d.ts +35 -39
  46. package/dist/module/lib/constants.d.ts.map +1 -1
  47. package/dist/module/lib/constants.js +35 -30
  48. package/dist/module/lib/constants.js.map +1 -1
  49. package/dist/module/lib/push.d.ts +48 -0
  50. package/dist/module/lib/push.d.ts.map +1 -0
  51. package/dist/module/lib/push.js +99 -0
  52. package/dist/module/lib/push.js.map +1 -0
  53. package/dist/module/lib/timer.d.ts +22 -0
  54. package/dist/module/lib/timer.d.ts.map +1 -0
  55. package/dist/module/lib/timer.js +36 -0
  56. package/dist/module/lib/timer.js.map +1 -0
  57. package/dist/module/lib/version.d.ts +1 -1
  58. package/dist/module/lib/version.d.ts.map +1 -1
  59. package/dist/module/lib/version.js +1 -1
  60. package/dist/module/lib/version.js.map +1 -1
  61. package/dist/module/lib/websocket-factory.d.ts +9 -0
  62. package/dist/module/lib/websocket-factory.d.ts.map +1 -1
  63. package/dist/module/lib/websocket-factory.js +12 -0
  64. package/dist/module/lib/websocket-factory.js.map +1 -1
  65. package/dist/tsconfig.module.tsbuildinfo +1 -1
  66. package/dist/tsconfig.tsbuildinfo +1 -1
  67. package/package.json +3 -3
  68. package/src/RealtimeChannel.ts +364 -201
  69. package/src/RealtimeClient.ts +583 -296
  70. package/src/RealtimePresence.ts +287 -10
  71. package/src/lib/constants.ts +37 -50
  72. package/src/lib/push.ts +121 -0
  73. package/src/lib/timer.ts +43 -0
  74. package/src/lib/version.ts +1 -1
  75. package/src/lib/websocket-factory.ts +13 -0
  76. package/dist/main/phoenix/channelAdapter.d.ts +0 -32
  77. package/dist/main/phoenix/channelAdapter.d.ts.map +0 -1
  78. package/dist/main/phoenix/channelAdapter.js +0 -103
  79. package/dist/main/phoenix/channelAdapter.js.map +0 -1
  80. package/dist/main/phoenix/presenceAdapter.d.ts +0 -53
  81. package/dist/main/phoenix/presenceAdapter.d.ts.map +0 -1
  82. package/dist/main/phoenix/presenceAdapter.js +0 -93
  83. package/dist/main/phoenix/presenceAdapter.js.map +0 -1
  84. package/dist/main/phoenix/socketAdapter.d.ts +0 -38
  85. package/dist/main/phoenix/socketAdapter.d.ts.map +0 -1
  86. package/dist/main/phoenix/socketAdapter.js +0 -114
  87. package/dist/main/phoenix/socketAdapter.js.map +0 -1
  88. package/dist/main/phoenix/types.d.ts +0 -5
  89. package/dist/main/phoenix/types.d.ts.map +0 -1
  90. package/dist/main/phoenix/types.js +0 -3
  91. package/dist/main/phoenix/types.js.map +0 -1
  92. package/dist/module/phoenix/channelAdapter.d.ts +0 -32
  93. package/dist/module/phoenix/channelAdapter.d.ts.map +0 -1
  94. package/dist/module/phoenix/channelAdapter.js +0 -100
  95. package/dist/module/phoenix/channelAdapter.js.map +0 -1
  96. package/dist/module/phoenix/presenceAdapter.d.ts +0 -53
  97. package/dist/module/phoenix/presenceAdapter.d.ts.map +0 -1
  98. package/dist/module/phoenix/presenceAdapter.js +0 -90
  99. package/dist/module/phoenix/presenceAdapter.js.map +0 -1
  100. package/dist/module/phoenix/socketAdapter.d.ts +0 -38
  101. package/dist/module/phoenix/socketAdapter.d.ts.map +0 -1
  102. package/dist/module/phoenix/socketAdapter.js +0 -111
  103. package/dist/module/phoenix/socketAdapter.js.map +0 -1
  104. package/dist/module/phoenix/types.d.ts +0 -5
  105. package/dist/module/phoenix/types.d.ts.map +0 -1
  106. package/dist/module/phoenix/types.js +0 -2
  107. package/dist/module/phoenix/types.js.map +0 -1
  108. package/src/phoenix/channelAdapter.ts +0 -147
  109. package/src/phoenix/presenceAdapter.ts +0 -116
  110. package/src/phoenix/socketAdapter.ts +0 -168
  111. package/src/phoenix/types.ts +0 -32
@@ -3,10 +3,10 @@
3
3
  License: https://github.com/phoenixframework/phoenix/blob/d344ec0a732ab4ee204215b31de69cf4be72e3bf/LICENSE.md
4
4
  */
5
5
 
6
+ import type { PresenceOpts, PresenceOnJoinCallback, PresenceOnLeaveCallback } from 'phoenix'
6
7
  import type RealtimeChannel from './RealtimeChannel'
7
- import PresenceAdapter from './phoenix/presenceAdapter'
8
8
 
9
- export type Presence<T extends { [key: string]: any } = {}> = {
9
+ type Presence<T extends { [key: string]: any } = {}> = {
10
10
  presence_ref: string
11
11
  } & T
12
12
 
@@ -34,16 +34,42 @@ export enum REALTIME_PRESENCE_LISTEN_EVENTS {
34
34
  LEAVE = 'leave',
35
35
  }
36
36
 
37
- export type RealtimePresenceOptions = {
38
- events?: { state: string; diff: string }
37
+ type PresenceDiff = {
38
+ joins: RealtimePresenceState
39
+ leaves: RealtimePresenceState
39
40
  }
40
41
 
41
- export default class RealtimePresence {
42
- get state() {
43
- return this.presenceAdapter.state
42
+ type RawPresenceState = {
43
+ [key: string]: {
44
+ metas: {
45
+ phx_ref?: string
46
+ phx_ref_prev?: string
47
+ [key: string]: any
48
+ }[]
44
49
  }
50
+ }
51
+
52
+ type RawPresenceDiff = {
53
+ joins: RawPresenceState
54
+ leaves: RawPresenceState
55
+ }
56
+
57
+ type PresenceChooser<T> = (key: string, presences: Presence[]) => T
45
58
 
46
- private presenceAdapter: PresenceAdapter
59
+ export default class RealtimePresence {
60
+ state: RealtimePresenceState = {}
61
+ pendingDiffs: RawPresenceDiff[] = []
62
+ joinRef: string | null = null
63
+ enabled: boolean = false
64
+ caller: {
65
+ onJoin: PresenceOnJoinCallback
66
+ onLeave: PresenceOnLeaveCallback
67
+ onSync: () => void
68
+ } = {
69
+ onJoin: () => {},
70
+ onLeave: () => {},
71
+ onSync: () => {},
72
+ }
47
73
 
48
74
  /**
49
75
  * Creates a Presence helper that keeps the local presence state in sync with the server.
@@ -62,8 +88,259 @@ export default class RealtimePresence {
62
88
  */
63
89
  constructor(
64
90
  public channel: RealtimeChannel,
65
- opts?: RealtimePresenceOptions
91
+ opts?: PresenceOpts
66
92
  ) {
67
- this.presenceAdapter = new PresenceAdapter(this.channel.channelAdapter, opts)
93
+ const events = opts?.events || {
94
+ state: 'presence_state',
95
+ diff: 'presence_diff',
96
+ }
97
+
98
+ this.channel._on(events.state, {}, (newState: RawPresenceState) => {
99
+ const { onJoin, onLeave, onSync } = this.caller
100
+
101
+ this.joinRef = this.channel._joinRef()
102
+
103
+ this.state = RealtimePresence.syncState(this.state, newState, onJoin, onLeave)
104
+
105
+ this.pendingDiffs.forEach((diff) => {
106
+ this.state = RealtimePresence.syncDiff(this.state, diff, onJoin, onLeave)
107
+ })
108
+
109
+ this.pendingDiffs = []
110
+
111
+ onSync()
112
+ })
113
+
114
+ this.channel._on(events.diff, {}, (diff: RawPresenceDiff) => {
115
+ const { onJoin, onLeave, onSync } = this.caller
116
+
117
+ if (this.inPendingSyncState()) {
118
+ this.pendingDiffs.push(diff)
119
+ } else {
120
+ this.state = RealtimePresence.syncDiff(this.state, diff, onJoin, onLeave)
121
+
122
+ onSync()
123
+ }
124
+ })
125
+
126
+ this.onJoin((key, currentPresences, newPresences) => {
127
+ this.channel._trigger('presence', {
128
+ event: 'join',
129
+ key,
130
+ currentPresences,
131
+ newPresences,
132
+ })
133
+ })
134
+
135
+ this.onLeave((key, currentPresences, leftPresences) => {
136
+ this.channel._trigger('presence', {
137
+ event: 'leave',
138
+ key,
139
+ currentPresences,
140
+ leftPresences,
141
+ })
142
+ })
143
+
144
+ this.onSync(() => {
145
+ this.channel._trigger('presence', { event: 'sync' })
146
+ })
147
+ }
148
+
149
+ /**
150
+ * Used to sync the list of presences on the server with the
151
+ * client's state.
152
+ *
153
+ * An optional `onJoin` and `onLeave` callback can be provided to
154
+ * react to changes in the client's local presences across
155
+ * disconnects and reconnects with the server.
156
+ *
157
+ * @internal
158
+ */
159
+ private static syncState(
160
+ currentState: RealtimePresenceState,
161
+ newState: RawPresenceState | RealtimePresenceState,
162
+ onJoin: PresenceOnJoinCallback,
163
+ onLeave: PresenceOnLeaveCallback
164
+ ): RealtimePresenceState {
165
+ const state = this.cloneDeep(currentState)
166
+ const transformedState = this.transformState(newState)
167
+ const joins: RealtimePresenceState = {}
168
+ const leaves: RealtimePresenceState = {}
169
+
170
+ this.map(state, (key: string, presences: Presence[]) => {
171
+ if (!transformedState[key]) {
172
+ leaves[key] = presences
173
+ }
174
+ })
175
+
176
+ this.map(transformedState, (key, newPresences: Presence[]) => {
177
+ const currentPresences: Presence[] = state[key]
178
+
179
+ if (currentPresences) {
180
+ const newPresenceRefs = newPresences.map((m: Presence) => m.presence_ref)
181
+ const curPresenceRefs = currentPresences.map((m: Presence) => m.presence_ref)
182
+ const joinedPresences: Presence[] = newPresences.filter(
183
+ (m: Presence) => curPresenceRefs.indexOf(m.presence_ref) < 0
184
+ )
185
+ const leftPresences: Presence[] = currentPresences.filter(
186
+ (m: Presence) => newPresenceRefs.indexOf(m.presence_ref) < 0
187
+ )
188
+
189
+ if (joinedPresences.length > 0) {
190
+ joins[key] = joinedPresences
191
+ }
192
+
193
+ if (leftPresences.length > 0) {
194
+ leaves[key] = leftPresences
195
+ }
196
+ } else {
197
+ joins[key] = newPresences
198
+ }
199
+ })
200
+
201
+ return this.syncDiff(state, { joins, leaves }, onJoin, onLeave)
202
+ }
203
+
204
+ /**
205
+ * Used to sync a diff of presence join and leave events from the
206
+ * server, as they happen.
207
+ *
208
+ * Like `syncState`, `syncDiff` accepts optional `onJoin` and
209
+ * `onLeave` callbacks to react to a user joining or leaving from a
210
+ * device.
211
+ *
212
+ * @internal
213
+ */
214
+ private static syncDiff(
215
+ state: RealtimePresenceState,
216
+ diff: RawPresenceDiff | PresenceDiff,
217
+ onJoin: PresenceOnJoinCallback,
218
+ onLeave: PresenceOnLeaveCallback
219
+ ): RealtimePresenceState {
220
+ const { joins, leaves } = {
221
+ joins: this.transformState(diff.joins),
222
+ leaves: this.transformState(diff.leaves),
223
+ }
224
+
225
+ if (!onJoin) {
226
+ onJoin = () => {}
227
+ }
228
+
229
+ if (!onLeave) {
230
+ onLeave = () => {}
231
+ }
232
+
233
+ this.map(joins, (key, newPresences: Presence[]) => {
234
+ const currentPresences: Presence[] = state[key] ?? []
235
+ state[key] = this.cloneDeep(newPresences)
236
+
237
+ if (currentPresences.length > 0) {
238
+ const joinedPresenceRefs = state[key].map((m: Presence) => m.presence_ref)
239
+ const curPresences: Presence[] = currentPresences.filter(
240
+ (m: Presence) => joinedPresenceRefs.indexOf(m.presence_ref) < 0
241
+ )
242
+
243
+ state[key].unshift(...curPresences)
244
+ }
245
+
246
+ onJoin(key, currentPresences, newPresences)
247
+ })
248
+
249
+ this.map(leaves, (key, leftPresences: Presence[]) => {
250
+ let currentPresences: Presence[] = state[key]
251
+
252
+ if (!currentPresences) return
253
+
254
+ const presenceRefsToRemove = leftPresences.map((m: Presence) => m.presence_ref)
255
+ currentPresences = currentPresences.filter(
256
+ (m: Presence) => presenceRefsToRemove.indexOf(m.presence_ref) < 0
257
+ )
258
+
259
+ state[key] = currentPresences
260
+
261
+ onLeave(key, currentPresences, leftPresences)
262
+
263
+ if (currentPresences.length === 0) delete state[key]
264
+ })
265
+
266
+ return state
267
+ }
268
+
269
+ /** @internal */
270
+ private static map<T = any>(obj: RealtimePresenceState, func: PresenceChooser<T>): T[] {
271
+ return Object.getOwnPropertyNames(obj).map((key) => func(key, obj[key]))
272
+ }
273
+
274
+ /**
275
+ * Remove 'metas' key
276
+ * Change 'phx_ref' to 'presence_ref'
277
+ * Remove 'phx_ref' and 'phx_ref_prev'
278
+ *
279
+ * @example
280
+ * // returns {
281
+ * abc123: [
282
+ * { presence_ref: '2', user_id: 1 },
283
+ * { presence_ref: '3', user_id: 2 }
284
+ * ]
285
+ * }
286
+ * RealtimePresence.transformState({
287
+ * abc123: {
288
+ * metas: [
289
+ * { phx_ref: '2', phx_ref_prev: '1' user_id: 1 },
290
+ * { phx_ref: '3', user_id: 2 }
291
+ * ]
292
+ * }
293
+ * })
294
+ *
295
+ * @internal
296
+ */
297
+ private static transformState(
298
+ state: RawPresenceState | RealtimePresenceState
299
+ ): RealtimePresenceState {
300
+ state = this.cloneDeep(state)
301
+
302
+ return Object.getOwnPropertyNames(state).reduce((newState, key) => {
303
+ const presences = state[key]
304
+
305
+ if ('metas' in presences) {
306
+ newState[key] = presences.metas.map((presence) => {
307
+ presence['presence_ref'] = presence['phx_ref']
308
+
309
+ delete presence['phx_ref']
310
+ delete presence['phx_ref_prev']
311
+
312
+ return presence
313
+ }) as Presence[]
314
+ } else {
315
+ newState[key] = presences
316
+ }
317
+
318
+ return newState
319
+ }, {} as RealtimePresenceState)
320
+ }
321
+
322
+ /** @internal */
323
+ private static cloneDeep(obj: { [key: string]: any }) {
324
+ return JSON.parse(JSON.stringify(obj))
325
+ }
326
+
327
+ /** @internal */
328
+ private onJoin(callback: PresenceOnJoinCallback): void {
329
+ this.caller.onJoin = callback
330
+ }
331
+
332
+ /** @internal */
333
+ private onLeave(callback: PresenceOnLeaveCallback): void {
334
+ this.caller.onLeave = callback
335
+ }
336
+
337
+ /** @internal */
338
+ private onSync(callback: () => void): void {
339
+ this.caller.onSync = callback
340
+ }
341
+
342
+ /** @internal */
343
+ private inPendingSyncState(): boolean {
344
+ return !this.joinRef || this.joinRef !== this.channel._joinRef()
68
345
  }
69
346
  }
@@ -1,19 +1,10 @@
1
1
  import { version } from './version'
2
- import type {
3
- SocketState,
4
- ChannelState,
5
- ChannelEvent as PhoenixChannelEvent,
6
- Transport,
7
- Vsn,
8
- } from '../phoenix/types'
9
-
10
- export type { SocketState, ChannelState, Transport }
11
2
 
12
3
  export const DEFAULT_VERSION = `realtime-js/${version}`
13
4
 
14
- export const VSN_1_0_0: Vsn = '1.0.0'
15
- export const VSN_2_0_0: Vsn = '2.0.0'
16
- export const DEFAULT_VSN: Vsn = VSN_2_0_0
5
+ export const VSN_1_0_0: string = '1.0.0'
6
+ export const VSN_2_0_0: string = '2.0.0'
7
+ export const DEFAULT_VSN: string = VSN_2_0_0
17
8
 
18
9
  export const VERSION = version
19
10
 
@@ -22,41 +13,37 @@ export const DEFAULT_TIMEOUT = 10000
22
13
  export const WS_CLOSE_NORMAL = 1000
23
14
  export const MAX_PUSH_BUFFER_SIZE = 100
24
15
 
25
- export const SOCKET_STATES = {
26
- connecting: 0,
27
- open: 1,
28
- closing: 2,
29
- closed: 3,
30
- } as const
31
-
32
- export const CHANNEL_STATES = {
33
- closed: 'closed',
34
- errored: 'errored',
35
- joined: 'joined',
36
- joining: 'joining',
37
- leaving: 'leaving',
38
- } as const
39
-
40
- export type ChannelEvent = PhoenixChannelEvent | 'access_token'
41
-
42
- export const CHANNEL_EVENTS = {
43
- close: 'phx_close',
44
- error: 'phx_error',
45
- join: 'phx_join',
46
- reply: 'phx_reply',
47
- leave: 'phx_leave',
48
- access_token: 'access_token',
49
- } as const
50
-
51
- export const TRANSPORTS = {
52
- websocket: 'websocket',
53
- } as const
54
-
55
- export type ConnectionState = 'connecting' | 'open' | 'closing' | 'closed'
56
-
57
- export const CONNECTION_STATE = {
58
- connecting: 'connecting',
59
- open: 'open',
60
- closing: 'closing',
61
- closed: 'closed',
62
- } as const
16
+ export enum SOCKET_STATES {
17
+ connecting = 0,
18
+ open = 1,
19
+ closing = 2,
20
+ closed = 3,
21
+ }
22
+
23
+ export enum CHANNEL_STATES {
24
+ closed = 'closed',
25
+ errored = 'errored',
26
+ joined = 'joined',
27
+ joining = 'joining',
28
+ leaving = 'leaving',
29
+ }
30
+
31
+ export enum CHANNEL_EVENTS {
32
+ close = 'phx_close',
33
+ error = 'phx_error',
34
+ join = 'phx_join',
35
+ reply = 'phx_reply',
36
+ leave = 'phx_leave',
37
+ access_token = 'access_token',
38
+ }
39
+
40
+ export enum TRANSPORTS {
41
+ websocket = 'websocket',
42
+ }
43
+
44
+ export enum CONNECTION_STATE {
45
+ Connecting = 'connecting',
46
+ Open = 'open',
47
+ Closing = 'closing',
48
+ Closed = 'closed',
49
+ }
@@ -0,0 +1,121 @@
1
+ import { DEFAULT_TIMEOUT } from '../lib/constants'
2
+ import type RealtimeChannel from '../RealtimeChannel'
3
+
4
+ export default class Push {
5
+ sent: boolean = false
6
+ timeoutTimer: number | undefined = undefined
7
+ ref: string = ''
8
+ receivedResp: {
9
+ status: string
10
+ response: { [key: string]: any }
11
+ } | null = null
12
+ recHooks: {
13
+ status: string
14
+ callback: Function
15
+ }[] = []
16
+ refEvent: string | null = null
17
+
18
+ /**
19
+ * Initializes the Push
20
+ *
21
+ * @param channel The Channel
22
+ * @param event The event, for example `"phx_join"`
23
+ * @param payload The payload, for example `{user_id: 123}`
24
+ * @param timeout The push timeout in milliseconds
25
+ */
26
+ constructor(
27
+ public channel: RealtimeChannel,
28
+ public event: string,
29
+ public payload: { [key: string]: any } = {},
30
+ public timeout: number = DEFAULT_TIMEOUT
31
+ ) {}
32
+
33
+ resend(timeout: number) {
34
+ this.timeout = timeout
35
+ this._cancelRefEvent()
36
+ this.ref = ''
37
+ this.refEvent = null
38
+ this.receivedResp = null
39
+ this.sent = false
40
+ this.send()
41
+ }
42
+
43
+ send() {
44
+ if (this._hasReceived('timeout')) {
45
+ return
46
+ }
47
+ this.startTimeout()
48
+ this.sent = true
49
+ this.channel.socket.push({
50
+ topic: this.channel.topic,
51
+ event: this.event,
52
+ payload: this.payload,
53
+ ref: this.ref,
54
+ join_ref: this.channel._joinRef(),
55
+ })
56
+ }
57
+
58
+ updatePayload(payload: { [key: string]: any }): void {
59
+ this.payload = { ...this.payload, ...payload }
60
+ }
61
+
62
+ receive(status: string, callback: Function) {
63
+ if (this._hasReceived(status)) {
64
+ callback(this.receivedResp?.response)
65
+ }
66
+
67
+ this.recHooks.push({ status, callback })
68
+ return this
69
+ }
70
+
71
+ startTimeout() {
72
+ if (this.timeoutTimer) {
73
+ return
74
+ }
75
+ this.ref = this.channel.socket._makeRef()
76
+ this.refEvent = this.channel._replyEventName(this.ref)
77
+
78
+ const callback = (payload: any) => {
79
+ this._cancelRefEvent()
80
+ this._cancelTimeout()
81
+ this.receivedResp = payload
82
+ this._matchReceive(payload)
83
+ }
84
+
85
+ this.channel._on(this.refEvent, {}, callback)
86
+
87
+ this.timeoutTimer = <any>setTimeout(() => {
88
+ this.trigger('timeout', {})
89
+ }, this.timeout)
90
+ }
91
+
92
+ trigger(status: string, response: any) {
93
+ if (this.refEvent) this.channel._trigger(this.refEvent, { status, response })
94
+ }
95
+
96
+ destroy() {
97
+ this._cancelRefEvent()
98
+ this._cancelTimeout()
99
+ }
100
+
101
+ private _cancelRefEvent() {
102
+ if (!this.refEvent) {
103
+ return
104
+ }
105
+
106
+ this.channel._off(this.refEvent, {})
107
+ }
108
+
109
+ private _cancelTimeout() {
110
+ clearTimeout(this.timeoutTimer)
111
+ this.timeoutTimer = undefined
112
+ }
113
+
114
+ private _matchReceive({ status, response }: { status: string; response: Function }) {
115
+ this.recHooks.filter((h) => h.status === status).forEach((h) => h.callback(response))
116
+ }
117
+
118
+ private _hasReceived(status: string) {
119
+ return this.receivedResp && this.receivedResp.status === status
120
+ }
121
+ }
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Creates a timer that accepts a `timerCalc` function to perform calculated timeout retries, such as exponential backoff.
3
+ *
4
+ * @example
5
+ * let reconnectTimer = new Timer(() => this.connect(), function(tries){
6
+ * return [1000, 5000, 10000][tries - 1] || 10000
7
+ * })
8
+ * reconnectTimer.scheduleTimeout() // fires after 1000
9
+ * reconnectTimer.scheduleTimeout() // fires after 5000
10
+ * reconnectTimer.reset()
11
+ * reconnectTimer.scheduleTimeout() // fires after 1000
12
+ */
13
+ export default class Timer {
14
+ timer: number | undefined = undefined
15
+ tries: number = 0
16
+
17
+ constructor(
18
+ public callback: Function,
19
+ public timerCalc: Function
20
+ ) {
21
+ this.callback = callback
22
+ this.timerCalc = timerCalc
23
+ }
24
+
25
+ reset() {
26
+ this.tries = 0
27
+ clearTimeout(this.timer)
28
+ this.timer = undefined
29
+ }
30
+
31
+ // Cancels any previous scheduleTimeout and schedules callback
32
+ scheduleTimeout() {
33
+ clearTimeout(this.timer)
34
+
35
+ this.timer = <any>setTimeout(
36
+ () => {
37
+ this.tries = this.tries + 1
38
+ this.callback()
39
+ },
40
+ this.timerCalc(this.tries + 1)
41
+ )
42
+ }
43
+ }
@@ -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.99.3-canary.0'
7
+ export const version = '2.99.3'
@@ -156,6 +156,19 @@ export class WebSocketFactory {
156
156
  throw new Error(errorMessage)
157
157
  }
158
158
 
159
+ /**
160
+ * Creates a WebSocket using the detected constructor.
161
+ *
162
+ * @example
163
+ * ```ts
164
+ * const socket = WebSocketFactory.createWebSocket('wss://realtime.supabase.co/socket')
165
+ * ```
166
+ */
167
+ public static createWebSocket(url: string | URL, protocols?: string | string[]): WebSocketLike {
168
+ const WS = this.getWebSocketConstructor()
169
+ return new WS(url, protocols)
170
+ }
171
+
159
172
  /**
160
173
  * Detects whether the runtime can establish WebSocket connections.
161
174
  *
@@ -1,32 +0,0 @@
1
- import type { RealtimeChannelOptions } from '../RealtimeChannel';
2
- import SocketAdapter from './socketAdapter';
3
- import type { ChannelBindingCallback, ChannelOnMessage, ChannelOnErrorCallback, ChannelFilterBindings, ChannelState, Push, Timer } from './types';
4
- export default class ChannelAdapter {
5
- private channel;
6
- private socket;
7
- constructor(socket: SocketAdapter, topic: string, params: RealtimeChannelOptions);
8
- get state(): ChannelState;
9
- set state(state: ChannelState);
10
- get joinedOnce(): boolean;
11
- get joinPush(): Push;
12
- get rejoinTimer(): Timer;
13
- on(event: string, callback: ChannelBindingCallback): number;
14
- off(event: string, refNumber?: number): void;
15
- subscribe(timeout?: number): Push;
16
- unsubscribe(timeout?: number): Push;
17
- teardown(): void;
18
- onClose(callback: ChannelBindingCallback): void;
19
- onError(callback: ChannelOnErrorCallback): number;
20
- push(event: string, payload: {
21
- [key: string]: any;
22
- }, timeout?: number): Push;
23
- updateJoinPayload(payload: Record<string, any>): void;
24
- canPush(): boolean;
25
- isJoined(): boolean;
26
- isJoining(): boolean;
27
- isClosed(): boolean;
28
- isLeaving(): boolean;
29
- updateFilterBindings(filterBindings: ChannelFilterBindings): void;
30
- updatePayloadTransform(callback: ChannelOnMessage): void;
31
- }
32
- //# sourceMappingURL=channelAdapter.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"channelAdapter.d.ts","sourceRoot":"","sources":["../../../src/phoenix/channelAdapter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAA;AAChE,OAAO,aAAa,MAAM,iBAAiB,CAAA;AAC3C,OAAO,KAAK,EACV,sBAAsB,EACtB,gBAAgB,EAChB,sBAAsB,EACtB,qBAAqB,EAErB,YAAY,EACZ,IAAI,EACJ,KAAK,EACN,MAAM,SAAS,CAAA;AAEhB,MAAM,CAAC,OAAO,OAAO,cAAc;IACjC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAe;gBAEjB,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,sBAAsB;IAMhF,IAAI,KAAK,IAAI,YAAY,CAExB;IAED,IAAI,KAAK,CAAC,KAAK,EAAE,YAAY,EAE5B;IAED,IAAI,UAAU,IAAI,OAAO,CAExB;IAED,IAAI,QAAQ,IAAI,IAAI,CAEnB;IAED,IAAI,WAAW,IAAI,KAAK,CAEvB;IAED,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,sBAAsB,GAAG,MAAM;IAI3D,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM;IAIrC,SAAS,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAIjC,WAAW,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAInC,QAAQ;IAIR,OAAO,CAAC,QAAQ,EAAE,sBAAsB;IAIxC,OAAO,CAAC,QAAQ,EAAE,sBAAsB,GAAG,MAAM;IAIjD,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAqB5E,iBAAiB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAK9C,OAAO;IAIP,QAAQ;IAIR,SAAS;IAIT,QAAQ;IAIR,SAAS;IAIT,oBAAoB,CAAC,cAAc,EAAE,qBAAqB;IAI1D,sBAAsB,CAAC,QAAQ,EAAE,gBAAgB;CAUlD"}