@depup/supabase__realtime-js 2.99.3-depup.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.
Files changed (104) hide show
  1. package/README.md +32 -0
  2. package/changes.json +14 -0
  3. package/dist/main/RealtimeChannel.d.ts +370 -0
  4. package/dist/main/RealtimeChannel.d.ts.map +1 -0
  5. package/dist/main/RealtimeChannel.js +644 -0
  6. package/dist/main/RealtimeChannel.js.map +1 -0
  7. package/dist/main/RealtimeClient.d.ts +238 -0
  8. package/dist/main/RealtimeClient.d.ts.map +1 -0
  9. package/dist/main/RealtimeClient.js +870 -0
  10. package/dist/main/RealtimeClient.js.map +1 -0
  11. package/dist/main/RealtimePresence.d.ts +76 -0
  12. package/dist/main/RealtimePresence.d.ts.map +1 -0
  13. package/dist/main/RealtimePresence.js +237 -0
  14. package/dist/main/RealtimePresence.js.map +1 -0
  15. package/dist/main/index.d.ts +6 -0
  16. package/dist/main/index.d.ts.map +1 -0
  17. package/dist/main/index.js +18 -0
  18. package/dist/main/index.js.map +1 -0
  19. package/dist/main/lib/constants.d.ts +39 -0
  20. package/dist/main/lib/constants.d.ts.map +1 -0
  21. package/dist/main/lib/constants.js +48 -0
  22. package/dist/main/lib/constants.js.map +1 -0
  23. package/dist/main/lib/push.d.ts +48 -0
  24. package/dist/main/lib/push.d.ts.map +1 -0
  25. package/dist/main/lib/push.js +102 -0
  26. package/dist/main/lib/push.js.map +1 -0
  27. package/dist/main/lib/serializer.d.ts +33 -0
  28. package/dist/main/lib/serializer.d.ts.map +1 -0
  29. package/dist/main/lib/serializer.js +155 -0
  30. package/dist/main/lib/serializer.js.map +1 -0
  31. package/dist/main/lib/timer.d.ts +22 -0
  32. package/dist/main/lib/timer.d.ts.map +1 -0
  33. package/dist/main/lib/timer.js +39 -0
  34. package/dist/main/lib/timer.js.map +1 -0
  35. package/dist/main/lib/transformers.d.ts +109 -0
  36. package/dist/main/lib/transformers.d.ts.map +1 -0
  37. package/dist/main/lib/transformers.js +241 -0
  38. package/dist/main/lib/transformers.js.map +1 -0
  39. package/dist/main/lib/version.d.ts +2 -0
  40. package/dist/main/lib/version.d.ts.map +1 -0
  41. package/dist/main/lib/version.js +11 -0
  42. package/dist/main/lib/version.js.map +1 -0
  43. package/dist/main/lib/websocket-factory.d.ts +81 -0
  44. package/dist/main/lib/websocket-factory.d.ts.map +1 -0
  45. package/dist/main/lib/websocket-factory.js +131 -0
  46. package/dist/main/lib/websocket-factory.js.map +1 -0
  47. package/dist/module/RealtimeChannel.d.ts +370 -0
  48. package/dist/module/RealtimeChannel.d.ts.map +1 -0
  49. package/dist/module/RealtimeChannel.js +639 -0
  50. package/dist/module/RealtimeChannel.js.map +1 -0
  51. package/dist/module/RealtimeClient.d.ts +238 -0
  52. package/dist/module/RealtimeClient.d.ts.map +1 -0
  53. package/dist/module/RealtimeClient.js +866 -0
  54. package/dist/module/RealtimeClient.js.map +1 -0
  55. package/dist/module/RealtimePresence.d.ts +76 -0
  56. package/dist/module/RealtimePresence.d.ts.map +1 -0
  57. package/dist/module/RealtimePresence.js +233 -0
  58. package/dist/module/RealtimePresence.js.map +1 -0
  59. package/dist/module/index.d.ts +6 -0
  60. package/dist/module/index.d.ts.map +1 -0
  61. package/dist/module/index.js +6 -0
  62. package/dist/module/index.js.map +1 -0
  63. package/dist/module/lib/constants.d.ts +39 -0
  64. package/dist/module/lib/constants.d.ts.map +1 -0
  65. package/dist/module/lib/constants.js +45 -0
  66. package/dist/module/lib/constants.js.map +1 -0
  67. package/dist/module/lib/push.d.ts +48 -0
  68. package/dist/module/lib/push.d.ts.map +1 -0
  69. package/dist/module/lib/push.js +99 -0
  70. package/dist/module/lib/push.js.map +1 -0
  71. package/dist/module/lib/serializer.d.ts +33 -0
  72. package/dist/module/lib/serializer.d.ts.map +1 -0
  73. package/dist/module/lib/serializer.js +152 -0
  74. package/dist/module/lib/serializer.js.map +1 -0
  75. package/dist/module/lib/timer.d.ts +22 -0
  76. package/dist/module/lib/timer.d.ts.map +1 -0
  77. package/dist/module/lib/timer.js +36 -0
  78. package/dist/module/lib/timer.js.map +1 -0
  79. package/dist/module/lib/transformers.d.ts +109 -0
  80. package/dist/module/lib/transformers.d.ts.map +1 -0
  81. package/dist/module/lib/transformers.js +229 -0
  82. package/dist/module/lib/transformers.js.map +1 -0
  83. package/dist/module/lib/version.d.ts +2 -0
  84. package/dist/module/lib/version.d.ts.map +1 -0
  85. package/dist/module/lib/version.js +8 -0
  86. package/dist/module/lib/version.js.map +1 -0
  87. package/dist/module/lib/websocket-factory.d.ts +81 -0
  88. package/dist/module/lib/websocket-factory.d.ts.map +1 -0
  89. package/dist/module/lib/websocket-factory.js +127 -0
  90. package/dist/module/lib/websocket-factory.js.map +1 -0
  91. package/dist/tsconfig.module.tsbuildinfo +1 -0
  92. package/dist/tsconfig.tsbuildinfo +1 -0
  93. package/package.json +85 -0
  94. package/src/RealtimeChannel.ts +1039 -0
  95. package/src/RealtimeClient.ts +1023 -0
  96. package/src/RealtimePresence.ts +346 -0
  97. package/src/index.ts +53 -0
  98. package/src/lib/constants.ts +49 -0
  99. package/src/lib/push.ts +121 -0
  100. package/src/lib/serializer.ts +203 -0
  101. package/src/lib/timer.ts +43 -0
  102. package/src/lib/transformers.ts +270 -0
  103. package/src/lib/version.ts +7 -0
  104. package/src/lib/websocket-factory.ts +192 -0
@@ -0,0 +1,346 @@
1
+ /*
2
+ This file draws heavily from https://github.com/phoenixframework/phoenix/blob/d344ec0a732ab4ee204215b31de69cf4be72e3bf/assets/js/phoenix/presence.js
3
+ License: https://github.com/phoenixframework/phoenix/blob/d344ec0a732ab4ee204215b31de69cf4be72e3bf/LICENSE.md
4
+ */
5
+
6
+ import type { PresenceOpts, PresenceOnJoinCallback, PresenceOnLeaveCallback } from 'phoenix'
7
+ import type RealtimeChannel from './RealtimeChannel'
8
+
9
+ type Presence<T extends { [key: string]: any } = {}> = {
10
+ presence_ref: string
11
+ } & T
12
+
13
+ export type RealtimePresenceState<T extends { [key: string]: any } = {}> = {
14
+ [key: string]: Presence<T>[]
15
+ }
16
+
17
+ export type RealtimePresenceJoinPayload<T extends { [key: string]: any }> = {
18
+ event: `${REALTIME_PRESENCE_LISTEN_EVENTS.JOIN}`
19
+ key: string
20
+ currentPresences: Presence<T>[]
21
+ newPresences: Presence<T>[]
22
+ }
23
+
24
+ export type RealtimePresenceLeavePayload<T extends { [key: string]: any }> = {
25
+ event: `${REALTIME_PRESENCE_LISTEN_EVENTS.LEAVE}`
26
+ key: string
27
+ currentPresences: Presence<T>[]
28
+ leftPresences: Presence<T>[]
29
+ }
30
+
31
+ export enum REALTIME_PRESENCE_LISTEN_EVENTS {
32
+ SYNC = 'sync',
33
+ JOIN = 'join',
34
+ LEAVE = 'leave',
35
+ }
36
+
37
+ type PresenceDiff = {
38
+ joins: RealtimePresenceState
39
+ leaves: RealtimePresenceState
40
+ }
41
+
42
+ type RawPresenceState = {
43
+ [key: string]: {
44
+ metas: {
45
+ phx_ref?: string
46
+ phx_ref_prev?: string
47
+ [key: string]: any
48
+ }[]
49
+ }
50
+ }
51
+
52
+ type RawPresenceDiff = {
53
+ joins: RawPresenceState
54
+ leaves: RawPresenceState
55
+ }
56
+
57
+ type PresenceChooser<T> = (key: string, presences: Presence[]) => T
58
+
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
+ }
73
+
74
+ /**
75
+ * Creates a Presence helper that keeps the local presence state in sync with the server.
76
+ *
77
+ * @param channel - The realtime channel to bind to.
78
+ * @param opts - Optional custom event names, e.g. `{ events: { state: 'state', diff: 'diff' } }`.
79
+ *
80
+ * @example
81
+ * ```ts
82
+ * const presence = new RealtimePresence(channel)
83
+ *
84
+ * channel.on('presence', ({ event, key }) => {
85
+ * console.log(`Presence ${event} on ${key}`)
86
+ * })
87
+ * ```
88
+ */
89
+ constructor(
90
+ public channel: RealtimeChannel,
91
+ opts?: PresenceOpts
92
+ ) {
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()
345
+ }
346
+ }
package/src/index.ts ADDED
@@ -0,0 +1,53 @@
1
+ import RealtimeClient, {
2
+ RealtimeClientOptions,
3
+ RealtimeMessage,
4
+ RealtimeRemoveChannelResponse,
5
+ WebSocketLikeConstructor,
6
+ } from './RealtimeClient'
7
+ import RealtimeChannel, {
8
+ RealtimeChannelOptions,
9
+ RealtimeChannelSendResponse,
10
+ RealtimePostgresChangesFilter,
11
+ RealtimePostgresChangesPayload,
12
+ RealtimePostgresInsertPayload,
13
+ RealtimePostgresUpdatePayload,
14
+ RealtimePostgresDeletePayload,
15
+ REALTIME_LISTEN_TYPES,
16
+ REALTIME_POSTGRES_CHANGES_LISTEN_EVENT,
17
+ REALTIME_SUBSCRIBE_STATES,
18
+ REALTIME_CHANNEL_STATES,
19
+ } from './RealtimeChannel'
20
+ import RealtimePresence, {
21
+ RealtimePresenceState,
22
+ RealtimePresenceJoinPayload,
23
+ RealtimePresenceLeavePayload,
24
+ REALTIME_PRESENCE_LISTEN_EVENTS,
25
+ } from './RealtimePresence'
26
+ import WebSocketFactory, { WebSocketLike } from './lib/websocket-factory'
27
+
28
+ export {
29
+ RealtimePresence,
30
+ RealtimeChannel,
31
+ RealtimeChannelOptions,
32
+ RealtimeChannelSendResponse,
33
+ RealtimeClient,
34
+ RealtimeClientOptions,
35
+ RealtimeMessage,
36
+ RealtimePostgresChangesFilter,
37
+ RealtimePostgresChangesPayload,
38
+ RealtimePostgresInsertPayload,
39
+ RealtimePostgresUpdatePayload,
40
+ RealtimePostgresDeletePayload,
41
+ RealtimePresenceJoinPayload,
42
+ RealtimePresenceLeavePayload,
43
+ RealtimePresenceState,
44
+ RealtimeRemoveChannelResponse,
45
+ REALTIME_LISTEN_TYPES,
46
+ REALTIME_POSTGRES_CHANGES_LISTEN_EVENT,
47
+ REALTIME_PRESENCE_LISTEN_EVENTS,
48
+ REALTIME_SUBSCRIBE_STATES,
49
+ REALTIME_CHANNEL_STATES,
50
+ WebSocketFactory,
51
+ WebSocketLike,
52
+ WebSocketLikeConstructor,
53
+ }
@@ -0,0 +1,49 @@
1
+ import { version } from './version'
2
+
3
+ export const DEFAULT_VERSION = `realtime-js/${version}`
4
+
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
8
+
9
+ export const VERSION = version
10
+
11
+ export const DEFAULT_TIMEOUT = 10000
12
+
13
+ export const WS_CLOSE_NORMAL = 1000
14
+ export const MAX_PUSH_BUFFER_SIZE = 100
15
+
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
+ }