@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,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Creates a timer that accepts a `timerCalc` function to perform
|
|
4
|
+
* calculated timeout retries, such as exponential backoff.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* let reconnectTimer = new Timer(() => this.connect(), function(tries){
|
|
8
|
+
* return [1000, 5000, 10000][tries - 1] || 10000
|
|
9
|
+
* })
|
|
10
|
+
* reconnectTimer.scheduleTimeout() // fires after 1000
|
|
11
|
+
* reconnectTimer.scheduleTimeout() // fires after 5000
|
|
12
|
+
* reconnectTimer.reset()
|
|
13
|
+
* reconnectTimer.scheduleTimeout() // fires after 1000
|
|
14
|
+
*
|
|
15
|
+
*/
|
|
16
|
+
export default class Timer {
|
|
17
|
+
/**
|
|
18
|
+
* @param {() => void} callback
|
|
19
|
+
* @param {(tries: number) => number} timerCalc
|
|
20
|
+
*/
|
|
21
|
+
constructor(callback, timerCalc){
|
|
22
|
+
/** @type {() => void} */
|
|
23
|
+
this.callback = callback
|
|
24
|
+
/** @type {(tries: number) => number} */
|
|
25
|
+
this.timerCalc = timerCalc
|
|
26
|
+
/** @type {ReturnType<typeof setTimeout> | undefined} */
|
|
27
|
+
this.timer = undefined
|
|
28
|
+
/** @type {number} */
|
|
29
|
+
this.tries = 0
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
reset(){
|
|
33
|
+
this.tries = 0
|
|
34
|
+
clearTimeout(this.timer)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Cancels any previous scheduleTimeout and schedules callback
|
|
39
|
+
*/
|
|
40
|
+
scheduleTimeout(){
|
|
41
|
+
clearTimeout(this.timer)
|
|
42
|
+
|
|
43
|
+
this.timer = setTimeout(() => {
|
|
44
|
+
this.tries = this.tries + 1
|
|
45
|
+
this.callback()
|
|
46
|
+
}, this.timerCalc(this.tries + 1))
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @import LongPoll from "./longpoll"
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* MISC
|
|
7
|
+
* @typedef {Record<string, unknown>} Params
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @template T
|
|
12
|
+
* @typedef {T | (() => T)} Closure
|
|
13
|
+
*
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* CHANNEL
|
|
18
|
+
* @typedef {(payload: unknown, ref: string | null | undefined, joinRef: string) => void} ChannelBindingCallback
|
|
19
|
+
* @typedef {(reason: unknown) => void} ChannelOnErrorCallback
|
|
20
|
+
* @typedef {({event: string, ref: number, callback: ChannelBindingCallback})} ChannelBinding
|
|
21
|
+
* @typedef {(event: string, payload?: unknown, ref?: ?string, joinRef?: ?string) => unknown} ChannelOnMessage
|
|
22
|
+
* @typedef {(binding: ChannelBinding, payload: unknown, ref?: ?string) => boolean} ChannelFilterBindings
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* CONSTANTS
|
|
28
|
+
* @import {SOCKET_STATES, CHANNEL_STATES, CHANNEL_EVENTS, TRANSPORTS, XHR_STATES} from "./constants"
|
|
29
|
+
* @typedef {"1.0.0" | "2.0.0"} Vsn
|
|
30
|
+
* @typedef {typeof SOCKET_STATES[keyof typeof SOCKET_STATES]} SocketState
|
|
31
|
+
* @typedef {typeof CHANNEL_STATES[keyof typeof CHANNEL_STATES]} ChannelState
|
|
32
|
+
* @typedef {typeof CHANNEL_EVENTS[keyof typeof CHANNEL_EVENTS]} ChannelEvent
|
|
33
|
+
* @typedef {typeof TRANSPORTS[keyof typeof TRANSPORTS]} Transport
|
|
34
|
+
* @typedef {typeof XHR_STATES[keyof typeof XHR_STATES]} XhrState
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* PRESENCE
|
|
39
|
+
* @typedef {{state: string, diff: string}} PresenceEvents
|
|
40
|
+
* @typedef {(key: string, currentPresence: PresenceState, newPresence: PresenceState) => void} PresenceOnJoin
|
|
41
|
+
* @typedef {(key: string, currentPresence: PresenceState, leftPresence: PresenceState) => void} PresenceOnLeave
|
|
42
|
+
* @typedef {() => void} PresenceOnSync
|
|
43
|
+
* @typedef {({joins: PresenceState, leaves: PresenceState})} PresenceDiff
|
|
44
|
+
* @typedef {(
|
|
45
|
+
* {
|
|
46
|
+
* metas: {
|
|
47
|
+
* phx_ref?: string
|
|
48
|
+
* phx_ref_prev?: string
|
|
49
|
+
* [key: string]: any
|
|
50
|
+
* }[]
|
|
51
|
+
* }
|
|
52
|
+
*)} PresenceState
|
|
53
|
+
*
|
|
54
|
+
* @typedef {Object} PresenceOptions
|
|
55
|
+
* @property {PresenceEvents} [events]
|
|
56
|
+
*/
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* SERIALIZER
|
|
60
|
+
* @template T
|
|
61
|
+
* @typedef {({
|
|
62
|
+
* join_ref?: string | null;
|
|
63
|
+
* ref?: string | null;
|
|
64
|
+
* event: string;
|
|
65
|
+
* topic: string;
|
|
66
|
+
* payload: T;
|
|
67
|
+
* })} Message
|
|
68
|
+
*/
|
|
69
|
+
/**
|
|
70
|
+
* @template T
|
|
71
|
+
* @typedef {(msg: Message<Record<string, any>>, callback: (result: ArrayBuffer | string) => T) => T} Encode
|
|
72
|
+
*/
|
|
73
|
+
/**
|
|
74
|
+
* @template T
|
|
75
|
+
* @typedef {(rawPayload: ArrayBuffer | string, callback: (msg: Message<unknown>) => T) => T} Decode
|
|
76
|
+
*/
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* SOCKET
|
|
80
|
+
* @typedef {(typeof WebSocket | typeof LongPoll)} SocketTransport
|
|
81
|
+
* @typedef {() => void} SocketOnOpen
|
|
82
|
+
* @typedef {(event: CloseEvent) => void} SocketOnClose
|
|
83
|
+
* @typedef {(error: Event, transportBefore: SocketTransport, establishedBefore: number) => void} SocketOnError
|
|
84
|
+
* @typedef {(rawMessage: Message<unknown>) => void} SocketOnMessage
|
|
85
|
+
* @typedef {({
|
|
86
|
+
* open: [string, SocketOnOpen][]
|
|
87
|
+
* close: [string, SocketOnClose][]
|
|
88
|
+
* error: [string, SocketOnError][]
|
|
89
|
+
* message: [string, SocketOnMessage][]
|
|
90
|
+
* })} SocketStateChangeCallbacks
|
|
91
|
+
* @typedef {'sent' | 'ok' | 'error' | 'timeout' | 'disconnected'} HeartbeatStatus
|
|
92
|
+
* @typedef {(status: HeartbeatStatus, latency?: number) => void} HeartbeatCallback
|
|
93
|
+
*
|
|
94
|
+
*
|
|
95
|
+
*
|
|
96
|
+
* @typedef {Object} SocketOptions
|
|
97
|
+
* @property {SocketTransport} [transport] - The Websocket Transport, for example WebSocket or Phoenix.LongPoll.
|
|
98
|
+
*
|
|
99
|
+
* @property {number} [longPollFallbackMs] - The millisecond time to attempt the primary transport
|
|
100
|
+
* before falling back to the LongPoll transport. Disabled by default.
|
|
101
|
+
*
|
|
102
|
+
* @property {number} [longpollerTimeout] - The millisecond time before LongPoll transport times out. Default 20000.
|
|
103
|
+
*
|
|
104
|
+
* @property {boolean} [debug] - When true, enables debug logging. Default false.
|
|
105
|
+
*
|
|
106
|
+
* @property {Encode<void>} [encode] - The function to encode outgoing messages.
|
|
107
|
+
* Defaults to JSON encoder.
|
|
108
|
+
*
|
|
109
|
+
* @property {Decode<void>} [decode] - The function to decode incoming messages.
|
|
110
|
+
* Defaults to JSON:
|
|
111
|
+
*
|
|
112
|
+
* ```javascript
|
|
113
|
+
* (payload, callback) => callback(JSON.parse(payload))
|
|
114
|
+
* ```
|
|
115
|
+
*
|
|
116
|
+
* @property {number} [timeout] - The default timeout in milliseconds to trigger push timeouts.
|
|
117
|
+
* Defaults `DEFAULT_TIMEOUT`
|
|
118
|
+
*
|
|
119
|
+
* @property {number} [heartbeatIntervalMs] - The millisec interval to send a heartbeat message
|
|
120
|
+
*
|
|
121
|
+
* @property {boolean} [autoSendHeartbeat] - Whether to automatically send heartbeats after
|
|
122
|
+
* connection is established.
|
|
123
|
+
*
|
|
124
|
+
* Defaults to true.
|
|
125
|
+
*
|
|
126
|
+
* @property {HeartbeatCallback} [heartbeatCallback] - The optional function to handle heartbeat status and latency.
|
|
127
|
+
*
|
|
128
|
+
* @property {(tries: number) => number} [reconnectAfterMs] - The optional function that returns the
|
|
129
|
+
* socket reconnect interval, in milliseconds.
|
|
130
|
+
*
|
|
131
|
+
* Defaults to stepped backoff of:
|
|
132
|
+
*
|
|
133
|
+
* ```javascript
|
|
134
|
+
* function(tries){
|
|
135
|
+
* return [10, 50, 100, 150, 200, 250, 500, 1000, 2000][tries - 1] || 5000
|
|
136
|
+
* }
|
|
137
|
+
* ````
|
|
138
|
+
*
|
|
139
|
+
* @property {(tries: number) => number} [rejoinAfterMs] - The optional function that returns the millisec
|
|
140
|
+
* rejoin interval for individual channels.
|
|
141
|
+
*
|
|
142
|
+
* ```javascript
|
|
143
|
+
* function(tries){
|
|
144
|
+
* return [1000, 2000, 5000][tries - 1] || 10000
|
|
145
|
+
* }
|
|
146
|
+
* ````
|
|
147
|
+
*
|
|
148
|
+
* @property {(kind: string, msg: string, data: any) => void} [logger] - The optional function for specialized logging, ie:
|
|
149
|
+
*
|
|
150
|
+
* ```javascript
|
|
151
|
+
* function(kind, msg, data) {
|
|
152
|
+
* console.log(`${kind}: ${msg}`, data)
|
|
153
|
+
* }
|
|
154
|
+
* ```
|
|
155
|
+
*
|
|
156
|
+
* @property {Closure<Params>} [params] - The optional params to pass when connecting
|
|
157
|
+
*
|
|
158
|
+
* @property {string} [authToken] - the optional authentication token to be exposed on the server
|
|
159
|
+
* under the `:auth_token` connect_info key.
|
|
160
|
+
*
|
|
161
|
+
* @property {BinaryType} [binaryType] - The binary type to use for binary WebSocket frames.
|
|
162
|
+
*
|
|
163
|
+
* Defaults to "arraybuffer"
|
|
164
|
+
*
|
|
165
|
+
* @property {Vsn} [vsn] - The serializer's protocol version to send on connect.
|
|
166
|
+
*
|
|
167
|
+
* Defaults to DEFAULT_VSN.
|
|
168
|
+
*
|
|
169
|
+
* @property {Storage} [sessionStorage] - An optional Storage compatible object
|
|
170
|
+
* Phoenix uses sessionStorage for longpoll fallback history. Overriding the store is
|
|
171
|
+
* useful when Phoenix won't have access to `sessionStorage`. For example, This could
|
|
172
|
+
* happen if a site loads a cross-domain channel in an iframe. Example usage:
|
|
173
|
+
*
|
|
174
|
+
* class InMemoryStorage {
|
|
175
|
+
* constructor() { this.storage = {} }
|
|
176
|
+
* getItem(keyName) { return this.storage[keyName] || null }
|
|
177
|
+
* removeItem(keyName) { delete this.storage[keyName] }
|
|
178
|
+
* setItem(keyName, keyValue) { this.storage[keyName] = keyValue }
|
|
179
|
+
* }
|
|
180
|
+
*
|
|
181
|
+
* @property {() => Promise<void>} [beforeReconnect] - Callback ran before socket tries to reconnect.
|
|
182
|
+
*
|
|
183
|
+
*/
|
|
184
|
+
export {}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Wraps value in closure or returns closure
|
|
4
|
+
*
|
|
5
|
+
* @template T
|
|
6
|
+
* @param {T | (() => T)} value
|
|
7
|
+
* @returns {() => T}
|
|
8
|
+
*/
|
|
9
|
+
export let closure = (value) => {
|
|
10
|
+
if(typeof value === "function"){
|
|
11
|
+
return /** @type {() => T} */ (value)
|
|
12
|
+
} else {
|
|
13
|
+
let closure = function (){ return value }
|
|
14
|
+
return closure
|
|
15
|
+
}
|
|
16
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@supabase/phoenix",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "The official JavaScript client for the Phoenix web framework.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"module": "./priv/static/phoenix.mjs",
|
|
7
|
+
"main": "./priv/static/phoenix.cjs.js",
|
|
8
|
+
"types": "./priv/static/types/index.d.ts",
|
|
9
|
+
"unpkg": "./priv/static/phoenix.min.js",
|
|
10
|
+
"jsdelivr": "./priv/static/phoenix.min.js",
|
|
11
|
+
"exports": {
|
|
12
|
+
"import": {
|
|
13
|
+
"types": "./priv/static/types/index.d.ts",
|
|
14
|
+
"default": "./priv/static/phoenix.mjs"
|
|
15
|
+
},
|
|
16
|
+
"require": {
|
|
17
|
+
"types": "./priv/static/types/index.d.ts",
|
|
18
|
+
"default": "./priv/static/phoenix.cjs.js"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "git://github.com/supabase/phoenix.git"
|
|
24
|
+
},
|
|
25
|
+
"author": "Chris McCord <chris@chrismccord.com> (https://www.phoenixframework.org)",
|
|
26
|
+
"files": [
|
|
27
|
+
"README.md",
|
|
28
|
+
"LICENSE.md",
|
|
29
|
+
"package.json",
|
|
30
|
+
"tsconfig.json",
|
|
31
|
+
"priv/static/*",
|
|
32
|
+
"assets/js/phoenix/*"
|
|
33
|
+
],
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@babel/cli": "7.28.6",
|
|
36
|
+
"@babel/core": "7.29.0",
|
|
37
|
+
"@babel/preset-env": "7.29.0",
|
|
38
|
+
"@eslint/js": "^9.28.0",
|
|
39
|
+
"@stylistic/eslint-plugin": "^5.0.0",
|
|
40
|
+
"documentation": "^14.0.3",
|
|
41
|
+
"eslint": "9.39.2",
|
|
42
|
+
"eslint-plugin-jest": "29.12.1",
|
|
43
|
+
"jest": "^30.0.0",
|
|
44
|
+
"jest-environment-jsdom": "^30.0.0",
|
|
45
|
+
"jsdom": "^27.0.0",
|
|
46
|
+
"mock-socket": "^9.3.1",
|
|
47
|
+
"typescript": "^5.9.3"
|
|
48
|
+
},
|
|
49
|
+
"scripts": {
|
|
50
|
+
"test": "jest",
|
|
51
|
+
"test.coverage": "jest --coverage",
|
|
52
|
+
"test.watch": "jest --watch",
|
|
53
|
+
"build.types": "tsc",
|
|
54
|
+
"docs": "documentation build assets/js/phoenix/index.js -f html -o doc/js",
|
|
55
|
+
"lint": "eslint assets",
|
|
56
|
+
"lint:fix": "eslint --fix assets"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
Binary file
|
|
Binary file
|