@supabase/phoenix 0.1.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.
- package/LICENSE.md +22 -0
- package/README.md +122 -0
- package/assets/js/phoenix/ajax.js +116 -0
- package/assets/js/phoenix/channel.js +331 -0
- package/assets/js/phoenix/constants.js +35 -0
- package/assets/js/phoenix/index.js +212 -0
- package/assets/js/phoenix/longpoll.js +192 -0
- package/assets/js/phoenix/presence.js +208 -0
- package/assets/js/phoenix/push.js +134 -0
- package/assets/js/phoenix/serializer.js +133 -0
- package/assets/js/phoenix/socket.js +747 -0
- package/assets/js/phoenix/timer.js +48 -0
- package/assets/js/phoenix/types.js +184 -0
- package/assets/js/phoenix/utils.js +16 -0
- package/package.json +58 -0
- package/priv/static/favicon.ico +0 -0
- package/priv/static/phoenix-orange.png +0 -0
- package/priv/static/phoenix.cjs.js +1812 -0
- package/priv/static/phoenix.cjs.js.map +7 -0
- package/priv/static/phoenix.js +1834 -0
- package/priv/static/phoenix.min.js +2 -0
- package/priv/static/phoenix.mjs +1789 -0
- package/priv/static/phoenix.mjs.map +7 -0
- package/priv/static/phoenix.png +0 -0
- package/priv/static/types/ajax.d.ts +10 -0
- package/priv/static/types/ajax.d.ts.map +1 -0
- package/priv/static/types/channel.d.ts +167 -0
- package/priv/static/types/channel.d.ts.map +1 -0
- package/priv/static/types/constants.d.ts +36 -0
- package/priv/static/types/constants.d.ts.map +1 -0
- package/priv/static/types/index.d.ts +10 -0
- package/priv/static/types/index.d.ts.map +1 -0
- package/priv/static/types/longpoll.d.ts +29 -0
- package/priv/static/types/longpoll.d.ts.map +1 -0
- package/priv/static/types/presence.d.ts +107 -0
- package/priv/static/types/presence.d.ts.map +1 -0
- package/priv/static/types/push.d.ts +70 -0
- package/priv/static/types/push.d.ts.map +1 -0
- package/priv/static/types/serializer.d.ts +74 -0
- package/priv/static/types/serializer.d.ts.map +1 -0
- package/priv/static/types/socket.d.ts +284 -0
- package/priv/static/types/socket.d.ts.map +1 -0
- package/priv/static/types/timer.d.ts +36 -0
- package/priv/static/types/timer.d.ts.map +1 -0
- package/priv/static/types/types.d.ts +280 -0
- package/priv/static/types/types.d.ts.map +1 -0
- package/priv/static/types/utils.d.ts +2 -0
- package/priv/static/types/utils.d.ts.map +1 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @import Channel from "./channel"
|
|
3
|
+
* @import { ChannelEvent } from "./types"
|
|
4
|
+
*/
|
|
5
|
+
export default class Push {
|
|
6
|
+
/**
|
|
7
|
+
* Initializes the Push
|
|
8
|
+
* @param {Channel} channel - The Channel
|
|
9
|
+
* @param {ChannelEvent} event - The event, for example `"phx_join"`
|
|
10
|
+
* @param {() => Record<string, unknown>} payload - The payload, for example `{user_id: 123}`
|
|
11
|
+
* @param {number} timeout - The push timeout in milliseconds
|
|
12
|
+
*/
|
|
13
|
+
constructor(channel, event, payload, timeout){
|
|
14
|
+
/** @type{Channel} */
|
|
15
|
+
this.channel = channel
|
|
16
|
+
/** @type{ChannelEvent} */
|
|
17
|
+
this.event = event
|
|
18
|
+
/** @type{() => Record<string, unknown>} */
|
|
19
|
+
this.payload = payload || function (){ return {} }
|
|
20
|
+
this.receivedResp = null
|
|
21
|
+
/** @type{number} */
|
|
22
|
+
this.timeout = timeout
|
|
23
|
+
/** @type{(ReturnType<typeof setTimeout>) | null} */
|
|
24
|
+
this.timeoutTimer = null
|
|
25
|
+
/** @type{{status: string; callback: (response: any) => void}[]} */
|
|
26
|
+
this.recHooks = []
|
|
27
|
+
/** @type{boolean} */
|
|
28
|
+
this.sent = false
|
|
29
|
+
/** @type{string | null | undefined} */
|
|
30
|
+
this.ref = undefined
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
*
|
|
35
|
+
* @param {number} timeout
|
|
36
|
+
*/
|
|
37
|
+
resend(timeout){
|
|
38
|
+
this.timeout = timeout
|
|
39
|
+
this.reset()
|
|
40
|
+
this.send()
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
*
|
|
45
|
+
*/
|
|
46
|
+
send(){
|
|
47
|
+
if(this.hasReceived("timeout")){ return }
|
|
48
|
+
this.startTimeout()
|
|
49
|
+
this.sent = true
|
|
50
|
+
this.channel.socket.push({
|
|
51
|
+
topic: this.channel.topic,
|
|
52
|
+
event: this.event,
|
|
53
|
+
payload: this.payload(),
|
|
54
|
+
ref: this.ref,
|
|
55
|
+
join_ref: this.channel.joinRef()
|
|
56
|
+
})
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
*
|
|
61
|
+
* @param {string} status
|
|
62
|
+
* @param {(response: any) => void} callback
|
|
63
|
+
*/
|
|
64
|
+
receive(status, callback){
|
|
65
|
+
if(this.hasReceived(status)){
|
|
66
|
+
callback(this.receivedResp.response)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
this.recHooks.push({status, callback})
|
|
70
|
+
return this
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
reset(){
|
|
74
|
+
this.cancelRefEvent()
|
|
75
|
+
this.ref = null
|
|
76
|
+
this.refEvent = null
|
|
77
|
+
this.receivedResp = null
|
|
78
|
+
this.sent = false
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
destroy(){
|
|
82
|
+
this.cancelRefEvent()
|
|
83
|
+
this.cancelTimeout()
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* @private
|
|
88
|
+
*/
|
|
89
|
+
matchReceive({status, response, _ref}){
|
|
90
|
+
this.recHooks.filter(h => h.status === status)
|
|
91
|
+
.forEach(h => h.callback(response))
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* @private
|
|
96
|
+
*/
|
|
97
|
+
cancelRefEvent(){
|
|
98
|
+
if(!this.refEvent){ return }
|
|
99
|
+
this.channel.off(this.refEvent)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
cancelTimeout(){
|
|
103
|
+
clearTimeout(this.timeoutTimer)
|
|
104
|
+
this.timeoutTimer = null
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
startTimeout(){
|
|
108
|
+
if(this.timeoutTimer){ this.cancelTimeout() }
|
|
109
|
+
this.ref = this.channel.socket.makeRef()
|
|
110
|
+
this.refEvent = this.channel.replyEventName(this.ref)
|
|
111
|
+
|
|
112
|
+
this.channel.on(this.refEvent, payload => {
|
|
113
|
+
this.cancelRefEvent()
|
|
114
|
+
this.cancelTimeout()
|
|
115
|
+
this.receivedResp = payload
|
|
116
|
+
this.matchReceive(payload)
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
this.timeoutTimer = setTimeout(() => {
|
|
120
|
+
this.trigger("timeout", {})
|
|
121
|
+
}, this.timeout)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* @private
|
|
126
|
+
*/
|
|
127
|
+
hasReceived(status){
|
|
128
|
+
return this.receivedResp && this.receivedResp.status === status
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
trigger(status, response){
|
|
132
|
+
this.channel.trigger(this.refEvent, {status, response})
|
|
133
|
+
}
|
|
134
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/* The default serializer for encoding and decoding messages */
|
|
2
|
+
import {
|
|
3
|
+
CHANNEL_EVENTS
|
|
4
|
+
} from "./constants"
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @import { Message } from "./types"
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export default {
|
|
11
|
+
HEADER_LENGTH: 1,
|
|
12
|
+
META_LENGTH: 4,
|
|
13
|
+
KINDS: {push: 0, reply: 1, broadcast: 2},
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @template T
|
|
17
|
+
* @param {Message<Record<string, any>>} msg
|
|
18
|
+
* @param {(msg: ArrayBuffer | string) => T} callback
|
|
19
|
+
* @returns {T}
|
|
20
|
+
*/
|
|
21
|
+
encode(msg, callback){
|
|
22
|
+
if(msg.payload.constructor === ArrayBuffer){
|
|
23
|
+
return callback(this.binaryEncode(msg))
|
|
24
|
+
} else {
|
|
25
|
+
let payload = [msg.join_ref, msg.ref, msg.topic, msg.event, msg.payload]
|
|
26
|
+
return callback(JSON.stringify(payload))
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @template T
|
|
32
|
+
* @param {ArrayBuffer | string} rawPayload
|
|
33
|
+
* @param {(msg: Message<unknown>) => T} callback
|
|
34
|
+
* @returns {T}
|
|
35
|
+
*/
|
|
36
|
+
decode(rawPayload, callback){
|
|
37
|
+
if(rawPayload.constructor === ArrayBuffer){
|
|
38
|
+
return callback(this.binaryDecode(rawPayload))
|
|
39
|
+
} else {
|
|
40
|
+
let [join_ref, ref, topic, event, payload] = JSON.parse(rawPayload)
|
|
41
|
+
return callback({join_ref, ref, topic, event, payload})
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
/** @private */
|
|
46
|
+
binaryEncode(message){
|
|
47
|
+
let {join_ref, ref, event, topic, payload} = message
|
|
48
|
+
let metaLength = this.META_LENGTH + join_ref.length + ref.length + topic.length + event.length
|
|
49
|
+
let header = new ArrayBuffer(this.HEADER_LENGTH + metaLength)
|
|
50
|
+
let view = new DataView(header)
|
|
51
|
+
let offset = 0
|
|
52
|
+
|
|
53
|
+
view.setUint8(offset++, this.KINDS.push) // kind
|
|
54
|
+
view.setUint8(offset++, join_ref.length)
|
|
55
|
+
view.setUint8(offset++, ref.length)
|
|
56
|
+
view.setUint8(offset++, topic.length)
|
|
57
|
+
view.setUint8(offset++, event.length)
|
|
58
|
+
Array.from(join_ref, char => view.setUint8(offset++, char.charCodeAt(0)))
|
|
59
|
+
Array.from(ref, char => view.setUint8(offset++, char.charCodeAt(0)))
|
|
60
|
+
Array.from(topic, char => view.setUint8(offset++, char.charCodeAt(0)))
|
|
61
|
+
Array.from(event, char => view.setUint8(offset++, char.charCodeAt(0)))
|
|
62
|
+
|
|
63
|
+
var combined = new Uint8Array(header.byteLength + payload.byteLength)
|
|
64
|
+
combined.set(new Uint8Array(header), 0)
|
|
65
|
+
combined.set(new Uint8Array(payload), header.byteLength)
|
|
66
|
+
|
|
67
|
+
return combined.buffer
|
|
68
|
+
},
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* @private
|
|
72
|
+
*/
|
|
73
|
+
binaryDecode(buffer){
|
|
74
|
+
let view = new DataView(buffer)
|
|
75
|
+
let kind = view.getUint8(0)
|
|
76
|
+
let decoder = new TextDecoder()
|
|
77
|
+
switch(kind){
|
|
78
|
+
case this.KINDS.push: return this.decodePush(buffer, view, decoder)
|
|
79
|
+
case this.KINDS.reply: return this.decodeReply(buffer, view, decoder)
|
|
80
|
+
case this.KINDS.broadcast: return this.decodeBroadcast(buffer, view, decoder)
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
|
|
84
|
+
/** @private */
|
|
85
|
+
decodePush(buffer, view, decoder){
|
|
86
|
+
let joinRefSize = view.getUint8(1)
|
|
87
|
+
let topicSize = view.getUint8(2)
|
|
88
|
+
let eventSize = view.getUint8(3)
|
|
89
|
+
let offset = this.HEADER_LENGTH + this.META_LENGTH - 1 // pushes have no ref
|
|
90
|
+
let joinRef = decoder.decode(buffer.slice(offset, offset + joinRefSize))
|
|
91
|
+
offset = offset + joinRefSize
|
|
92
|
+
let topic = decoder.decode(buffer.slice(offset, offset + topicSize))
|
|
93
|
+
offset = offset + topicSize
|
|
94
|
+
let event = decoder.decode(buffer.slice(offset, offset + eventSize))
|
|
95
|
+
offset = offset + eventSize
|
|
96
|
+
let data = buffer.slice(offset, buffer.byteLength)
|
|
97
|
+
return {join_ref: joinRef, ref: null, topic: topic, event: event, payload: data}
|
|
98
|
+
},
|
|
99
|
+
|
|
100
|
+
/** @private */
|
|
101
|
+
decodeReply(buffer, view, decoder){
|
|
102
|
+
let joinRefSize = view.getUint8(1)
|
|
103
|
+
let refSize = view.getUint8(2)
|
|
104
|
+
let topicSize = view.getUint8(3)
|
|
105
|
+
let eventSize = view.getUint8(4)
|
|
106
|
+
let offset = this.HEADER_LENGTH + this.META_LENGTH
|
|
107
|
+
let joinRef = decoder.decode(buffer.slice(offset, offset + joinRefSize))
|
|
108
|
+
offset = offset + joinRefSize
|
|
109
|
+
let ref = decoder.decode(buffer.slice(offset, offset + refSize))
|
|
110
|
+
offset = offset + refSize
|
|
111
|
+
let topic = decoder.decode(buffer.slice(offset, offset + topicSize))
|
|
112
|
+
offset = offset + topicSize
|
|
113
|
+
let event = decoder.decode(buffer.slice(offset, offset + eventSize))
|
|
114
|
+
offset = offset + eventSize
|
|
115
|
+
let data = buffer.slice(offset, buffer.byteLength)
|
|
116
|
+
let payload = {status: event, response: data}
|
|
117
|
+
return {join_ref: joinRef, ref: ref, topic: topic, event: CHANNEL_EVENTS.reply, payload: payload}
|
|
118
|
+
},
|
|
119
|
+
|
|
120
|
+
/** @private */
|
|
121
|
+
decodeBroadcast(buffer, view, decoder){
|
|
122
|
+
let topicSize = view.getUint8(1)
|
|
123
|
+
let eventSize = view.getUint8(2)
|
|
124
|
+
let offset = this.HEADER_LENGTH + 2
|
|
125
|
+
let topic = decoder.decode(buffer.slice(offset, offset + topicSize))
|
|
126
|
+
offset = offset + topicSize
|
|
127
|
+
let event = decoder.decode(buffer.slice(offset, offset + eventSize))
|
|
128
|
+
offset = offset + eventSize
|
|
129
|
+
let data = buffer.slice(offset, buffer.byteLength)
|
|
130
|
+
|
|
131
|
+
return {join_ref: null, ref: null, topic: topic, event: event, payload: data}
|
|
132
|
+
}
|
|
133
|
+
}
|