verani 0.1.5 → 0.1.7
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/dist/client.cjs +1 -0
- package/dist/client.d.cts +208 -0
- package/dist/client.d.mts +208 -0
- package/dist/client.mjs +1 -0
- package/dist/decode-9DerwlQ1.d.mts +87 -0
- package/dist/decode-DMA_rBWB.d.cts +87 -0
- package/dist/types-083oWz55.cjs +1 -0
- package/dist/types-CJLnZrA8.mjs +1 -0
- package/dist/verani.cjs +1 -1
- package/dist/verani.d.cts +3 -289
- package/dist/verani.d.mts +3 -289
- package/dist/verani.mjs +1 -1
- package/package.json +11 -1
package/dist/client.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const require_types=require(`./types-083oWz55.cjs`);function encodeClientMessage$1(t){return require_types.n(t)}function decodeServerMessage$1(t){return require_types.s(t)}const DEFAULT_RECONNECTION_CONFIG={enabled:!0,maxAttempts:10,initialDelay:1e3,maxDelay:3e4,backoffMultiplier:1.5};var ConnectionManager=class{constructor(e=DEFAULT_RECONNECTION_CONFIG,t){this.config=e,this.onStateChange=t,this.state=`disconnected`,this.reconnectAttempts=0,this.currentDelay=e.initialDelay}getState(){return this.state}setState(e){this.state!==e&&(this.state=e,this.onStateChange?.(e))}resetReconnection(){this.reconnectAttempts=0,this.currentDelay=this.config.initialDelay,this.clearReconnectTimer()}scheduleReconnect(e){return this.config.enabled?this.config.maxAttempts>0&&this.reconnectAttempts>=this.config.maxAttempts?(this.setState(`error`),!1):(this.clearReconnectTimer(),this.setState(`reconnecting`),this.reconnectAttempts++,this.reconnectTimer=setTimeout(()=>{e(),this.currentDelay=Math.min(this.currentDelay*this.config.backoffMultiplier,this.config.maxDelay)},this.currentDelay),!0):!1}cancelReconnect(){this.clearReconnectTimer(),this.state===`reconnecting`&&this.setState(`disconnected`)}clearReconnectTimer(){this.reconnectTimer!==void 0&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=void 0)}getReconnectAttempts(){return this.reconnectAttempts}getNextDelay(){return this.currentDelay}destroy(){this.clearReconnectTimer()}},VeraniClient=class{constructor(e,t={}){this.url=e,this.listeners=new Map,this.messageQueue=[],this.options={reconnection:{enabled:t.reconnection?.enabled??DEFAULT_RECONNECTION_CONFIG.enabled,maxAttempts:t.reconnection?.maxAttempts??DEFAULT_RECONNECTION_CONFIG.maxAttempts,initialDelay:t.reconnection?.initialDelay??DEFAULT_RECONNECTION_CONFIG.initialDelay,maxDelay:t.reconnection?.maxDelay??DEFAULT_RECONNECTION_CONFIG.maxDelay,backoffMultiplier:t.reconnection?.backoffMultiplier??DEFAULT_RECONNECTION_CONFIG.backoffMultiplier},maxQueueSize:t.maxQueueSize??100,connectionTimeout:t.connectionTimeout??1e4},this.connectionManager=new ConnectionManager(this.options.reconnection,e=>{this.onStateChangeCallback?.(e)}),this.connect()}connect(){try{this.connectionManager.setState(`connecting`),this.emitLifecycleEvent(`connecting`),this.ws=new WebSocket(this.url);let e=setTimeout(()=>{this.connectionManager.getState()===`connecting`&&(this.ws?.close(),this.handleConnectionError(Error(`Connection timeout`)))},this.options.connectionTimeout);this.ws.addEventListener(`open`,()=>{clearTimeout(e),this.handleOpen()}),this.ws.addEventListener(`message`,e=>{this.handleMessage(e)}),this.ws.addEventListener(`close`,t=>{clearTimeout(e),this.handleClose(t)}),this.ws.addEventListener(`error`,t=>{clearTimeout(e),this.handleError(t)})}catch(e){this.handleConnectionError(e)}}handleOpen(){this.connectionManager.setState(`connected`),this.connectionManager.resetReconnection(),this.flushMessageQueue(),this.connectionResolve&&(this.connectionResolve(),this.connectionPromise=void 0,this.connectionResolve=void 0,this.connectionReject=void 0),this.emitLifecycleEvent(`open`),this.emitLifecycleEvent(`connected`),this.onOpenCallback?.()}handleMessage(e){let t=decodeServerMessage$1(e.data);if(!t)return;let r=t.type,i=t.data;t.type===`event`&&t.data&&typeof t.data==`object`&&`type`in t.data&&(r=t.data.type,i=t.data);let a=this.listeners.get(r);if(a)for(let e of a)try{e(i)}catch{}}handleClose(e){this.connectionManager.setState(`disconnected`),this.connectionReject&&=(this.connectionReject(Error(`Connection closed: ${e.reason||`Unknown reason`}`)),this.connectionPromise=void 0,this.connectionResolve=void 0,void 0),this.emitLifecycleEvent(`close`,e),this.emitLifecycleEvent(`disconnected`,e),this.onCloseCallback?.(e),e.code!==1e3&&e.code!==1001&&this.connectionManager.scheduleReconnect(()=>this.connect())&&this.emitLifecycleEvent(`reconnecting`)}handleError(e){this.emitLifecycleEvent(`error`,e),this.onErrorCallback?.(e)}handleConnectionError(e){this.connectionReject&&=(this.connectionReject(e),this.connectionPromise=void 0,this.connectionResolve=void 0,void 0),this.emitLifecycleEvent(`error`,e),this.connectionManager.scheduleReconnect(()=>this.connect())&&this.emitLifecycleEvent(`reconnecting`)}emitLifecycleEvent(e,t){let n=this.listeners.get(e);if(n)for(let e of n)try{e(t)}catch{}}flushMessageQueue(){if(!(!this.ws||this.ws.readyState!==WebSocket.OPEN))for(;this.messageQueue.length>0;){let e=this.messageQueue.shift();try{this.ws.send(encodeClientMessage$1(e))}catch{}}}getState(){return this.connectionManager.getState()}isConnected(){return this.ws?.readyState===WebSocket.OPEN}waitForConnection(){return this.isConnected()?Promise.resolve():(this.connectionPromise||=new Promise((e,t)=>{this.connectionResolve=e,this.connectionReject=t}),this.connectionPromise)}on(e,t){this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(t)}off(e,t){let n=this.listeners.get(e);n&&(n.delete(t),n.size===0&&this.listeners.delete(e))}once(e,t){let n=r=>{this.off(e,n),t(r)};this.on(e,n)}emit(e,n){let r={type:e,data:n};if(this.isConnected())try{this.ws.send(encodeClientMessage$1(r))}catch{this.queueMessage(r)}else this.queueMessage(r)}queueMessage(e){this.messageQueue.length>=this.options.maxQueueSize&&this.messageQueue.shift(),this.messageQueue.push(e)}onOpen(e){this.onOpenCallback=e}onClose(e){this.onCloseCallback=e}onError(e){this.onErrorCallback=e}onStateChange(e){this.onStateChangeCallback=e}reconnect(){this.disconnect(),this.connect()}disconnect(){this.connectionManager.cancelReconnect(),this.ws&&=(this.ws.close(1e3,`Client disconnect`),void 0)}close(){this.disconnect(),this.listeners.clear(),this.messageQueue=[],this.connectionManager.destroy()}};exports.ConnectionManager=ConnectionManager,exports.DEFAULT_RECONNECTION_CONFIG=DEFAULT_RECONNECTION_CONFIG,exports.PROTOCOL_VERSION=require_types.t,exports.VeraniClient=VeraniClient,exports.decodeClientMessage=require_types.a,exports.decodeFrame=require_types.o,exports.decodeServerMessage=require_types.s,exports.encodeClientMessage=require_types.n,exports.encodeFrame=require_types.r,exports.encodeServerMessage=require_types.i;
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { a as encodeFrame, d as ServerMessage, f as VeraniMessage, i as encodeClientMessage, n as decodeFrame, o as encodeServerMessage, r as decodeServerMessage, s as ClientMessage, t as decodeClientMessage, u as PROTOCOL_VERSION } from "./decode-DMA_rBWB.cjs";
|
|
2
|
+
|
|
3
|
+
//#region src/client/connection.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Connection state management for Verani client
|
|
6
|
+
*/
|
|
7
|
+
type ConnectionState = "connecting" | "connected" | "disconnected" | "reconnecting" | "error";
|
|
8
|
+
interface ReconnectionConfig {
|
|
9
|
+
/** Enable automatic reconnection */
|
|
10
|
+
enabled: boolean;
|
|
11
|
+
/** Maximum number of reconnection attempts (0 = infinite) */
|
|
12
|
+
maxAttempts: number;
|
|
13
|
+
/** Initial delay in milliseconds */
|
|
14
|
+
initialDelay: number;
|
|
15
|
+
/** Maximum delay in milliseconds */
|
|
16
|
+
maxDelay: number;
|
|
17
|
+
/** Backoff multiplier for exponential backoff */
|
|
18
|
+
backoffMultiplier: number;
|
|
19
|
+
}
|
|
20
|
+
declare const DEFAULT_RECONNECTION_CONFIG: ReconnectionConfig;
|
|
21
|
+
/**
|
|
22
|
+
* Manages WebSocket connection lifecycle and reconnection logic
|
|
23
|
+
*/
|
|
24
|
+
declare class ConnectionManager {
|
|
25
|
+
private config;
|
|
26
|
+
private onStateChange?;
|
|
27
|
+
private state;
|
|
28
|
+
private reconnectAttempts;
|
|
29
|
+
private reconnectTimer?;
|
|
30
|
+
private currentDelay;
|
|
31
|
+
constructor(config?: ReconnectionConfig, onStateChange?: ((state: ConnectionState) => void) | undefined);
|
|
32
|
+
/**
|
|
33
|
+
* Gets the current connection state
|
|
34
|
+
*/
|
|
35
|
+
getState(): ConnectionState;
|
|
36
|
+
/**
|
|
37
|
+
* Updates the connection state and notifies listeners
|
|
38
|
+
*/
|
|
39
|
+
setState(newState: ConnectionState): void;
|
|
40
|
+
/**
|
|
41
|
+
* Resets reconnection state (called on successful connection)
|
|
42
|
+
*/
|
|
43
|
+
resetReconnection(): void;
|
|
44
|
+
/**
|
|
45
|
+
* Schedules a reconnection attempt
|
|
46
|
+
*/
|
|
47
|
+
scheduleReconnect(connectFn: () => void): boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Cancels any pending reconnection
|
|
50
|
+
*/
|
|
51
|
+
cancelReconnect(): void;
|
|
52
|
+
/**
|
|
53
|
+
* Clears the reconnect timer
|
|
54
|
+
*/
|
|
55
|
+
private clearReconnectTimer;
|
|
56
|
+
/**
|
|
57
|
+
* Gets the current reconnection attempt count
|
|
58
|
+
*/
|
|
59
|
+
getReconnectAttempts(): number;
|
|
60
|
+
/**
|
|
61
|
+
* Gets the next reconnection delay
|
|
62
|
+
*/
|
|
63
|
+
getNextDelay(): number;
|
|
64
|
+
/**
|
|
65
|
+
* Cleanup method
|
|
66
|
+
*/
|
|
67
|
+
destroy(): void;
|
|
68
|
+
}
|
|
69
|
+
//#endregion
|
|
70
|
+
//#region src/client/client.d.ts
|
|
71
|
+
/**
|
|
72
|
+
* Client options for configuring the Verani client
|
|
73
|
+
*/
|
|
74
|
+
interface VeraniClientOptions {
|
|
75
|
+
/** Reconnection configuration */
|
|
76
|
+
reconnection?: Partial<ReconnectionConfig>;
|
|
77
|
+
/** Maximum number of messages to queue when disconnected */
|
|
78
|
+
maxQueueSize?: number;
|
|
79
|
+
/** Connection timeout in milliseconds */
|
|
80
|
+
connectionTimeout?: number;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Verani WebSocket client with automatic reconnection and lifecycle management
|
|
84
|
+
*/
|
|
85
|
+
declare class VeraniClient {
|
|
86
|
+
private url;
|
|
87
|
+
private ws?;
|
|
88
|
+
private listeners;
|
|
89
|
+
private connectionManager;
|
|
90
|
+
private messageQueue;
|
|
91
|
+
private options;
|
|
92
|
+
private onOpenCallback?;
|
|
93
|
+
private onCloseCallback?;
|
|
94
|
+
private onErrorCallback?;
|
|
95
|
+
private onStateChangeCallback?;
|
|
96
|
+
private connectionPromise?;
|
|
97
|
+
private connectionResolve?;
|
|
98
|
+
private connectionReject?;
|
|
99
|
+
/**
|
|
100
|
+
* Creates a new Verani client
|
|
101
|
+
* @param url - WebSocket URL to connect to
|
|
102
|
+
* @param options - Client configuration options
|
|
103
|
+
*/
|
|
104
|
+
constructor(url: string, options?: VeraniClientOptions);
|
|
105
|
+
/**
|
|
106
|
+
* Establishes WebSocket connection
|
|
107
|
+
*/
|
|
108
|
+
private connect;
|
|
109
|
+
/**
|
|
110
|
+
* Handles successful WebSocket connection
|
|
111
|
+
*/
|
|
112
|
+
private handleOpen;
|
|
113
|
+
/**
|
|
114
|
+
* Handles incoming WebSocket messages
|
|
115
|
+
*/
|
|
116
|
+
private handleMessage;
|
|
117
|
+
/**
|
|
118
|
+
* Handles WebSocket closure
|
|
119
|
+
*/
|
|
120
|
+
private handleClose;
|
|
121
|
+
/**
|
|
122
|
+
* Handles WebSocket errors
|
|
123
|
+
*/
|
|
124
|
+
private handleError;
|
|
125
|
+
/**
|
|
126
|
+
* Handles connection errors
|
|
127
|
+
*/
|
|
128
|
+
private handleConnectionError;
|
|
129
|
+
/**
|
|
130
|
+
* Emits a lifecycle event to registered listeners
|
|
131
|
+
*/
|
|
132
|
+
private emitLifecycleEvent;
|
|
133
|
+
/**
|
|
134
|
+
* Flushes queued messages when connection is established
|
|
135
|
+
*/
|
|
136
|
+
private flushMessageQueue;
|
|
137
|
+
/**
|
|
138
|
+
* Gets the current connection state
|
|
139
|
+
*/
|
|
140
|
+
getState(): ConnectionState;
|
|
141
|
+
/**
|
|
142
|
+
* Checks if the client is currently connected
|
|
143
|
+
*/
|
|
144
|
+
isConnected(): boolean;
|
|
145
|
+
/**
|
|
146
|
+
* Waits for the connection to be established
|
|
147
|
+
* @returns Promise that resolves when connected
|
|
148
|
+
*/
|
|
149
|
+
waitForConnection(): Promise<void>;
|
|
150
|
+
/**
|
|
151
|
+
* Registers an event listener
|
|
152
|
+
* @param event - Event type to listen for
|
|
153
|
+
* @param callback - Callback function to invoke when event is received
|
|
154
|
+
*/
|
|
155
|
+
on(event: string, callback: (data: any) => void): void;
|
|
156
|
+
/**
|
|
157
|
+
* Removes an event listener
|
|
158
|
+
* @param event - Event type to remove listener from
|
|
159
|
+
* @param callback - Callback function to remove
|
|
160
|
+
*/
|
|
161
|
+
off(event: string, callback: (data: any) => void): void;
|
|
162
|
+
/**
|
|
163
|
+
* Registers a one-time event listener
|
|
164
|
+
* @param event - Event type to listen for
|
|
165
|
+
* @param callback - Callback function to invoke once
|
|
166
|
+
*/
|
|
167
|
+
once(event: string, callback: (data: any) => void): void;
|
|
168
|
+
/**
|
|
169
|
+
* Sends a message to the server
|
|
170
|
+
* @param type - Message type
|
|
171
|
+
* @param data - Optional message data
|
|
172
|
+
*/
|
|
173
|
+
emit(type: string, data?: any): void;
|
|
174
|
+
/**
|
|
175
|
+
* Queues a message for sending when connected
|
|
176
|
+
*/
|
|
177
|
+
private queueMessage;
|
|
178
|
+
/**
|
|
179
|
+
* Registers lifecycle callback for connection open
|
|
180
|
+
*/
|
|
181
|
+
onOpen(callback: () => void): void;
|
|
182
|
+
/**
|
|
183
|
+
* Registers lifecycle callback for connection close
|
|
184
|
+
*/
|
|
185
|
+
onClose(callback: (event: CloseEvent) => void): void;
|
|
186
|
+
/**
|
|
187
|
+
* Registers lifecycle callback for connection error
|
|
188
|
+
*/
|
|
189
|
+
onError(callback: (error: Event) => void): void;
|
|
190
|
+
/**
|
|
191
|
+
* Registers lifecycle callback for state changes
|
|
192
|
+
*/
|
|
193
|
+
onStateChange(callback: (state: ConnectionState) => void): void;
|
|
194
|
+
/**
|
|
195
|
+
* Manually triggers a reconnection
|
|
196
|
+
*/
|
|
197
|
+
reconnect(): void;
|
|
198
|
+
/**
|
|
199
|
+
* Closes the connection without reconnecting
|
|
200
|
+
*/
|
|
201
|
+
disconnect(): void;
|
|
202
|
+
/**
|
|
203
|
+
* Closes the connection and cleans up resources
|
|
204
|
+
*/
|
|
205
|
+
close(): void;
|
|
206
|
+
}
|
|
207
|
+
//#endregion
|
|
208
|
+
export { type ClientMessage, ConnectionManager, type ConnectionState, DEFAULT_RECONNECTION_CONFIG, PROTOCOL_VERSION, type ReconnectionConfig, type ServerMessage, VeraniClient, type VeraniClientOptions, type VeraniMessage, decodeClientMessage, decodeFrame, decodeServerMessage, encodeClientMessage, encodeFrame, encodeServerMessage };
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { a as encodeFrame, d as ServerMessage, f as VeraniMessage, i as encodeClientMessage, n as decodeFrame, o as encodeServerMessage, r as decodeServerMessage, s as ClientMessage, t as decodeClientMessage, u as PROTOCOL_VERSION } from "./decode-9DerwlQ1.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/client/connection.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Connection state management for Verani client
|
|
6
|
+
*/
|
|
7
|
+
type ConnectionState = "connecting" | "connected" | "disconnected" | "reconnecting" | "error";
|
|
8
|
+
interface ReconnectionConfig {
|
|
9
|
+
/** Enable automatic reconnection */
|
|
10
|
+
enabled: boolean;
|
|
11
|
+
/** Maximum number of reconnection attempts (0 = infinite) */
|
|
12
|
+
maxAttempts: number;
|
|
13
|
+
/** Initial delay in milliseconds */
|
|
14
|
+
initialDelay: number;
|
|
15
|
+
/** Maximum delay in milliseconds */
|
|
16
|
+
maxDelay: number;
|
|
17
|
+
/** Backoff multiplier for exponential backoff */
|
|
18
|
+
backoffMultiplier: number;
|
|
19
|
+
}
|
|
20
|
+
declare const DEFAULT_RECONNECTION_CONFIG: ReconnectionConfig;
|
|
21
|
+
/**
|
|
22
|
+
* Manages WebSocket connection lifecycle and reconnection logic
|
|
23
|
+
*/
|
|
24
|
+
declare class ConnectionManager {
|
|
25
|
+
private config;
|
|
26
|
+
private onStateChange?;
|
|
27
|
+
private state;
|
|
28
|
+
private reconnectAttempts;
|
|
29
|
+
private reconnectTimer?;
|
|
30
|
+
private currentDelay;
|
|
31
|
+
constructor(config?: ReconnectionConfig, onStateChange?: ((state: ConnectionState) => void) | undefined);
|
|
32
|
+
/**
|
|
33
|
+
* Gets the current connection state
|
|
34
|
+
*/
|
|
35
|
+
getState(): ConnectionState;
|
|
36
|
+
/**
|
|
37
|
+
* Updates the connection state and notifies listeners
|
|
38
|
+
*/
|
|
39
|
+
setState(newState: ConnectionState): void;
|
|
40
|
+
/**
|
|
41
|
+
* Resets reconnection state (called on successful connection)
|
|
42
|
+
*/
|
|
43
|
+
resetReconnection(): void;
|
|
44
|
+
/**
|
|
45
|
+
* Schedules a reconnection attempt
|
|
46
|
+
*/
|
|
47
|
+
scheduleReconnect(connectFn: () => void): boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Cancels any pending reconnection
|
|
50
|
+
*/
|
|
51
|
+
cancelReconnect(): void;
|
|
52
|
+
/**
|
|
53
|
+
* Clears the reconnect timer
|
|
54
|
+
*/
|
|
55
|
+
private clearReconnectTimer;
|
|
56
|
+
/**
|
|
57
|
+
* Gets the current reconnection attempt count
|
|
58
|
+
*/
|
|
59
|
+
getReconnectAttempts(): number;
|
|
60
|
+
/**
|
|
61
|
+
* Gets the next reconnection delay
|
|
62
|
+
*/
|
|
63
|
+
getNextDelay(): number;
|
|
64
|
+
/**
|
|
65
|
+
* Cleanup method
|
|
66
|
+
*/
|
|
67
|
+
destroy(): void;
|
|
68
|
+
}
|
|
69
|
+
//#endregion
|
|
70
|
+
//#region src/client/client.d.ts
|
|
71
|
+
/**
|
|
72
|
+
* Client options for configuring the Verani client
|
|
73
|
+
*/
|
|
74
|
+
interface VeraniClientOptions {
|
|
75
|
+
/** Reconnection configuration */
|
|
76
|
+
reconnection?: Partial<ReconnectionConfig>;
|
|
77
|
+
/** Maximum number of messages to queue when disconnected */
|
|
78
|
+
maxQueueSize?: number;
|
|
79
|
+
/** Connection timeout in milliseconds */
|
|
80
|
+
connectionTimeout?: number;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Verani WebSocket client with automatic reconnection and lifecycle management
|
|
84
|
+
*/
|
|
85
|
+
declare class VeraniClient {
|
|
86
|
+
private url;
|
|
87
|
+
private ws?;
|
|
88
|
+
private listeners;
|
|
89
|
+
private connectionManager;
|
|
90
|
+
private messageQueue;
|
|
91
|
+
private options;
|
|
92
|
+
private onOpenCallback?;
|
|
93
|
+
private onCloseCallback?;
|
|
94
|
+
private onErrorCallback?;
|
|
95
|
+
private onStateChangeCallback?;
|
|
96
|
+
private connectionPromise?;
|
|
97
|
+
private connectionResolve?;
|
|
98
|
+
private connectionReject?;
|
|
99
|
+
/**
|
|
100
|
+
* Creates a new Verani client
|
|
101
|
+
* @param url - WebSocket URL to connect to
|
|
102
|
+
* @param options - Client configuration options
|
|
103
|
+
*/
|
|
104
|
+
constructor(url: string, options?: VeraniClientOptions);
|
|
105
|
+
/**
|
|
106
|
+
* Establishes WebSocket connection
|
|
107
|
+
*/
|
|
108
|
+
private connect;
|
|
109
|
+
/**
|
|
110
|
+
* Handles successful WebSocket connection
|
|
111
|
+
*/
|
|
112
|
+
private handleOpen;
|
|
113
|
+
/**
|
|
114
|
+
* Handles incoming WebSocket messages
|
|
115
|
+
*/
|
|
116
|
+
private handleMessage;
|
|
117
|
+
/**
|
|
118
|
+
* Handles WebSocket closure
|
|
119
|
+
*/
|
|
120
|
+
private handleClose;
|
|
121
|
+
/**
|
|
122
|
+
* Handles WebSocket errors
|
|
123
|
+
*/
|
|
124
|
+
private handleError;
|
|
125
|
+
/**
|
|
126
|
+
* Handles connection errors
|
|
127
|
+
*/
|
|
128
|
+
private handleConnectionError;
|
|
129
|
+
/**
|
|
130
|
+
* Emits a lifecycle event to registered listeners
|
|
131
|
+
*/
|
|
132
|
+
private emitLifecycleEvent;
|
|
133
|
+
/**
|
|
134
|
+
* Flushes queued messages when connection is established
|
|
135
|
+
*/
|
|
136
|
+
private flushMessageQueue;
|
|
137
|
+
/**
|
|
138
|
+
* Gets the current connection state
|
|
139
|
+
*/
|
|
140
|
+
getState(): ConnectionState;
|
|
141
|
+
/**
|
|
142
|
+
* Checks if the client is currently connected
|
|
143
|
+
*/
|
|
144
|
+
isConnected(): boolean;
|
|
145
|
+
/**
|
|
146
|
+
* Waits for the connection to be established
|
|
147
|
+
* @returns Promise that resolves when connected
|
|
148
|
+
*/
|
|
149
|
+
waitForConnection(): Promise<void>;
|
|
150
|
+
/**
|
|
151
|
+
* Registers an event listener
|
|
152
|
+
* @param event - Event type to listen for
|
|
153
|
+
* @param callback - Callback function to invoke when event is received
|
|
154
|
+
*/
|
|
155
|
+
on(event: string, callback: (data: any) => void): void;
|
|
156
|
+
/**
|
|
157
|
+
* Removes an event listener
|
|
158
|
+
* @param event - Event type to remove listener from
|
|
159
|
+
* @param callback - Callback function to remove
|
|
160
|
+
*/
|
|
161
|
+
off(event: string, callback: (data: any) => void): void;
|
|
162
|
+
/**
|
|
163
|
+
* Registers a one-time event listener
|
|
164
|
+
* @param event - Event type to listen for
|
|
165
|
+
* @param callback - Callback function to invoke once
|
|
166
|
+
*/
|
|
167
|
+
once(event: string, callback: (data: any) => void): void;
|
|
168
|
+
/**
|
|
169
|
+
* Sends a message to the server
|
|
170
|
+
* @param type - Message type
|
|
171
|
+
* @param data - Optional message data
|
|
172
|
+
*/
|
|
173
|
+
emit(type: string, data?: any): void;
|
|
174
|
+
/**
|
|
175
|
+
* Queues a message for sending when connected
|
|
176
|
+
*/
|
|
177
|
+
private queueMessage;
|
|
178
|
+
/**
|
|
179
|
+
* Registers lifecycle callback for connection open
|
|
180
|
+
*/
|
|
181
|
+
onOpen(callback: () => void): void;
|
|
182
|
+
/**
|
|
183
|
+
* Registers lifecycle callback for connection close
|
|
184
|
+
*/
|
|
185
|
+
onClose(callback: (event: CloseEvent) => void): void;
|
|
186
|
+
/**
|
|
187
|
+
* Registers lifecycle callback for connection error
|
|
188
|
+
*/
|
|
189
|
+
onError(callback: (error: Event) => void): void;
|
|
190
|
+
/**
|
|
191
|
+
* Registers lifecycle callback for state changes
|
|
192
|
+
*/
|
|
193
|
+
onStateChange(callback: (state: ConnectionState) => void): void;
|
|
194
|
+
/**
|
|
195
|
+
* Manually triggers a reconnection
|
|
196
|
+
*/
|
|
197
|
+
reconnect(): void;
|
|
198
|
+
/**
|
|
199
|
+
* Closes the connection without reconnecting
|
|
200
|
+
*/
|
|
201
|
+
disconnect(): void;
|
|
202
|
+
/**
|
|
203
|
+
* Closes the connection and cleans up resources
|
|
204
|
+
*/
|
|
205
|
+
close(): void;
|
|
206
|
+
}
|
|
207
|
+
//#endregion
|
|
208
|
+
export { type ClientMessage, ConnectionManager, type ConnectionState, DEFAULT_RECONNECTION_CONFIG, PROTOCOL_VERSION, type ReconnectionConfig, type ServerMessage, VeraniClient, type VeraniClientOptions, type VeraniMessage, decodeClientMessage, decodeFrame, decodeServerMessage, encodeClientMessage, encodeFrame, encodeServerMessage };
|
package/dist/client.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a as decodeClientMessage,i as encodeServerMessage,n as encodeClientMessage,o as decodeFrame,r as encodeFrame,s as decodeServerMessage,t as PROTOCOL_VERSION}from"./types-CJLnZrA8.mjs";function encodeClientMessage$1(e){return encodeClientMessage(e)}function decodeServerMessage$1(e){return decodeServerMessage(e)}const DEFAULT_RECONNECTION_CONFIG={enabled:!0,maxAttempts:10,initialDelay:1e3,maxDelay:3e4,backoffMultiplier:1.5};var ConnectionManager=class{constructor(e=DEFAULT_RECONNECTION_CONFIG,c){this.config=e,this.onStateChange=c,this.state=`disconnected`,this.reconnectAttempts=0,this.currentDelay=e.initialDelay}getState(){return this.state}setState(e){this.state!==e&&(this.state=e,this.onStateChange?.(e))}resetReconnection(){this.reconnectAttempts=0,this.currentDelay=this.config.initialDelay,this.clearReconnectTimer()}scheduleReconnect(e){return this.config.enabled?this.config.maxAttempts>0&&this.reconnectAttempts>=this.config.maxAttempts?(this.setState(`error`),!1):(this.clearReconnectTimer(),this.setState(`reconnecting`),this.reconnectAttempts++,this.reconnectTimer=setTimeout(()=>{e(),this.currentDelay=Math.min(this.currentDelay*this.config.backoffMultiplier,this.config.maxDelay)},this.currentDelay),!0):!1}cancelReconnect(){this.clearReconnectTimer(),this.state===`reconnecting`&&this.setState(`disconnected`)}clearReconnectTimer(){this.reconnectTimer!==void 0&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=void 0)}getReconnectAttempts(){return this.reconnectAttempts}getNextDelay(){return this.currentDelay}destroy(){this.clearReconnectTimer()}},VeraniClient=class{constructor(e,c={}){this.url=e,this.listeners=new Map,this.messageQueue=[],this.options={reconnection:{enabled:c.reconnection?.enabled??DEFAULT_RECONNECTION_CONFIG.enabled,maxAttempts:c.reconnection?.maxAttempts??DEFAULT_RECONNECTION_CONFIG.maxAttempts,initialDelay:c.reconnection?.initialDelay??DEFAULT_RECONNECTION_CONFIG.initialDelay,maxDelay:c.reconnection?.maxDelay??DEFAULT_RECONNECTION_CONFIG.maxDelay,backoffMultiplier:c.reconnection?.backoffMultiplier??DEFAULT_RECONNECTION_CONFIG.backoffMultiplier},maxQueueSize:c.maxQueueSize??100,connectionTimeout:c.connectionTimeout??1e4},this.connectionManager=new ConnectionManager(this.options.reconnection,e=>{this.onStateChangeCallback?.(e)}),this.connect()}connect(){try{this.connectionManager.setState(`connecting`),this.emitLifecycleEvent(`connecting`),this.ws=new WebSocket(this.url);let e=setTimeout(()=>{this.connectionManager.getState()===`connecting`&&(this.ws?.close(),this.handleConnectionError(Error(`Connection timeout`)))},this.options.connectionTimeout);this.ws.addEventListener(`open`,()=>{clearTimeout(e),this.handleOpen()}),this.ws.addEventListener(`message`,e=>{this.handleMessage(e)}),this.ws.addEventListener(`close`,c=>{clearTimeout(e),this.handleClose(c)}),this.ws.addEventListener(`error`,c=>{clearTimeout(e),this.handleError(c)})}catch(e){this.handleConnectionError(e)}}handleOpen(){this.connectionManager.setState(`connected`),this.connectionManager.resetReconnection(),this.flushMessageQueue(),this.connectionResolve&&(this.connectionResolve(),this.connectionPromise=void 0,this.connectionResolve=void 0,this.connectionReject=void 0),this.emitLifecycleEvent(`open`),this.emitLifecycleEvent(`connected`),this.onOpenCallback?.()}handleMessage(e){let c=decodeServerMessage$1(e.data);if(!c)return;let l=c.type,u=c.data;c.type===`event`&&c.data&&typeof c.data==`object`&&`type`in c.data&&(l=c.data.type,u=c.data);let d=this.listeners.get(l);if(d)for(let e of d)try{e(u)}catch{}}handleClose(e){this.connectionManager.setState(`disconnected`),this.connectionReject&&=(this.connectionReject(Error(`Connection closed: ${e.reason||`Unknown reason`}`)),this.connectionPromise=void 0,this.connectionResolve=void 0,void 0),this.emitLifecycleEvent(`close`,e),this.emitLifecycleEvent(`disconnected`,e),this.onCloseCallback?.(e),e.code!==1e3&&e.code!==1001&&this.connectionManager.scheduleReconnect(()=>this.connect())&&this.emitLifecycleEvent(`reconnecting`)}handleError(e){this.emitLifecycleEvent(`error`,e),this.onErrorCallback?.(e)}handleConnectionError(e){this.connectionReject&&=(this.connectionReject(e),this.connectionPromise=void 0,this.connectionResolve=void 0,void 0),this.emitLifecycleEvent(`error`,e),this.connectionManager.scheduleReconnect(()=>this.connect())&&this.emitLifecycleEvent(`reconnecting`)}emitLifecycleEvent(e,c){let l=this.listeners.get(e);if(l)for(let e of l)try{e(c)}catch{}}flushMessageQueue(){if(!(!this.ws||this.ws.readyState!==WebSocket.OPEN))for(;this.messageQueue.length>0;){let e=this.messageQueue.shift();try{this.ws.send(encodeClientMessage$1(e))}catch{}}}getState(){return this.connectionManager.getState()}isConnected(){return this.ws?.readyState===WebSocket.OPEN}waitForConnection(){return this.isConnected()?Promise.resolve():(this.connectionPromise||=new Promise((e,c)=>{this.connectionResolve=e,this.connectionReject=c}),this.connectionPromise)}on(e,c){this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(c)}off(e,c){let l=this.listeners.get(e);l&&(l.delete(c),l.size===0&&this.listeners.delete(e))}once(e,c){let l=u=>{this.off(e,l),c(u)};this.on(e,l)}emit(e,c){let l={type:e,data:c};if(this.isConnected())try{this.ws.send(encodeClientMessage$1(l))}catch{this.queueMessage(l)}else this.queueMessage(l)}queueMessage(e){this.messageQueue.length>=this.options.maxQueueSize&&this.messageQueue.shift(),this.messageQueue.push(e)}onOpen(e){this.onOpenCallback=e}onClose(e){this.onCloseCallback=e}onError(e){this.onErrorCallback=e}onStateChange(e){this.onStateChangeCallback=e}reconnect(){this.disconnect(),this.connect()}disconnect(){this.connectionManager.cancelReconnect(),this.ws&&=(this.ws.close(1e3,`Client disconnect`),void 0)}close(){this.disconnect(),this.listeners.clear(),this.messageQueue=[],this.connectionManager.destroy()}};export{ConnectionManager,DEFAULT_RECONNECTION_CONFIG,PROTOCOL_VERSION,VeraniClient,decodeClientMessage,decodeFrame,decodeServerMessage,encodeClientMessage,encodeFrame,encodeServerMessage};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
//#region src/shared/types.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Core message types shared between client and server
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Base message frame structure used for all WebSocket communication
|
|
7
|
+
*/
|
|
8
|
+
interface MessageFrame {
|
|
9
|
+
type: string;
|
|
10
|
+
channel?: string;
|
|
11
|
+
data?: any;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Message sent from client to server
|
|
15
|
+
*/
|
|
16
|
+
interface ClientMessage extends MessageFrame {
|
|
17
|
+
type: string;
|
|
18
|
+
channel?: string;
|
|
19
|
+
data?: any;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Message sent from server to client
|
|
23
|
+
*/
|
|
24
|
+
interface ServerMessage extends MessageFrame {
|
|
25
|
+
type: string;
|
|
26
|
+
channel?: string;
|
|
27
|
+
data?: any;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Connection metadata attached to each WebSocket
|
|
31
|
+
*/
|
|
32
|
+
interface ConnectionMeta {
|
|
33
|
+
userId: string;
|
|
34
|
+
clientId: string;
|
|
35
|
+
channels: string[];
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Unified message type for both directions
|
|
39
|
+
*/
|
|
40
|
+
type VeraniMessage = ClientMessage | ServerMessage;
|
|
41
|
+
/**
|
|
42
|
+
* Protocol version for future compatibility
|
|
43
|
+
*/
|
|
44
|
+
declare const PROTOCOL_VERSION = "1.0.0";
|
|
45
|
+
//#endregion
|
|
46
|
+
//#region src/shared/encode.d.ts
|
|
47
|
+
/**
|
|
48
|
+
* Encodes a message frame to JSON string for transmission
|
|
49
|
+
* @param frame - The message frame to encode
|
|
50
|
+
* @returns JSON string representation of the frame
|
|
51
|
+
* @throws Error if encoding fails
|
|
52
|
+
*/
|
|
53
|
+
declare function encodeFrame(frame: MessageFrame): string;
|
|
54
|
+
/**
|
|
55
|
+
* Encodes a client message to JSON string
|
|
56
|
+
* @param message - The client message to encode
|
|
57
|
+
* @returns JSON string representation
|
|
58
|
+
*/
|
|
59
|
+
declare function encodeClientMessage(message: MessageFrame): string;
|
|
60
|
+
/**
|
|
61
|
+
* Encodes a server message to JSON string
|
|
62
|
+
* @param message - The server message to encode
|
|
63
|
+
* @returns JSON string representation
|
|
64
|
+
*/
|
|
65
|
+
declare function encodeServerMessage(message: MessageFrame): string;
|
|
66
|
+
//#endregion
|
|
67
|
+
//#region src/shared/decode.d.ts
|
|
68
|
+
/**
|
|
69
|
+
* Decodes a raw message into a MessageFrame
|
|
70
|
+
* @param raw - Raw data from WebSocket (string, ArrayBuffer, etc)
|
|
71
|
+
* @returns Decoded MessageFrame or null if invalid
|
|
72
|
+
*/
|
|
73
|
+
declare function decodeFrame(raw: any): MessageFrame | null;
|
|
74
|
+
/**
|
|
75
|
+
* Decodes a client message
|
|
76
|
+
* @param raw - Raw data from client WebSocket
|
|
77
|
+
* @returns Decoded message or null if invalid
|
|
78
|
+
*/
|
|
79
|
+
declare function decodeClientMessage(raw: any): MessageFrame | null;
|
|
80
|
+
/**
|
|
81
|
+
* Decodes a server message
|
|
82
|
+
* @param raw - Raw data from server WebSocket
|
|
83
|
+
* @returns Decoded message or null if invalid
|
|
84
|
+
*/
|
|
85
|
+
declare function decodeServerMessage(raw: any): MessageFrame | null;
|
|
86
|
+
//#endregion
|
|
87
|
+
export { encodeFrame as a, ConnectionMeta as c, ServerMessage as d, VeraniMessage as f, encodeClientMessage as i, MessageFrame as l, decodeFrame as n, encodeServerMessage as o, decodeServerMessage as r, ClientMessage as s, decodeClientMessage as t, PROTOCOL_VERSION as u };
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
//#region src/shared/types.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Core message types shared between client and server
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Base message frame structure used for all WebSocket communication
|
|
7
|
+
*/
|
|
8
|
+
interface MessageFrame {
|
|
9
|
+
type: string;
|
|
10
|
+
channel?: string;
|
|
11
|
+
data?: any;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Message sent from client to server
|
|
15
|
+
*/
|
|
16
|
+
interface ClientMessage extends MessageFrame {
|
|
17
|
+
type: string;
|
|
18
|
+
channel?: string;
|
|
19
|
+
data?: any;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Message sent from server to client
|
|
23
|
+
*/
|
|
24
|
+
interface ServerMessage extends MessageFrame {
|
|
25
|
+
type: string;
|
|
26
|
+
channel?: string;
|
|
27
|
+
data?: any;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Connection metadata attached to each WebSocket
|
|
31
|
+
*/
|
|
32
|
+
interface ConnectionMeta {
|
|
33
|
+
userId: string;
|
|
34
|
+
clientId: string;
|
|
35
|
+
channels: string[];
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Unified message type for both directions
|
|
39
|
+
*/
|
|
40
|
+
type VeraniMessage = ClientMessage | ServerMessage;
|
|
41
|
+
/**
|
|
42
|
+
* Protocol version for future compatibility
|
|
43
|
+
*/
|
|
44
|
+
declare const PROTOCOL_VERSION = "1.0.0";
|
|
45
|
+
//#endregion
|
|
46
|
+
//#region src/shared/encode.d.ts
|
|
47
|
+
/**
|
|
48
|
+
* Encodes a message frame to JSON string for transmission
|
|
49
|
+
* @param frame - The message frame to encode
|
|
50
|
+
* @returns JSON string representation of the frame
|
|
51
|
+
* @throws Error if encoding fails
|
|
52
|
+
*/
|
|
53
|
+
declare function encodeFrame(frame: MessageFrame): string;
|
|
54
|
+
/**
|
|
55
|
+
* Encodes a client message to JSON string
|
|
56
|
+
* @param message - The client message to encode
|
|
57
|
+
* @returns JSON string representation
|
|
58
|
+
*/
|
|
59
|
+
declare function encodeClientMessage(message: MessageFrame): string;
|
|
60
|
+
/**
|
|
61
|
+
* Encodes a server message to JSON string
|
|
62
|
+
* @param message - The server message to encode
|
|
63
|
+
* @returns JSON string representation
|
|
64
|
+
*/
|
|
65
|
+
declare function encodeServerMessage(message: MessageFrame): string;
|
|
66
|
+
//#endregion
|
|
67
|
+
//#region src/shared/decode.d.ts
|
|
68
|
+
/**
|
|
69
|
+
* Decodes a raw message into a MessageFrame
|
|
70
|
+
* @param raw - Raw data from WebSocket (string, ArrayBuffer, etc)
|
|
71
|
+
* @returns Decoded MessageFrame or null if invalid
|
|
72
|
+
*/
|
|
73
|
+
declare function decodeFrame(raw: any): MessageFrame | null;
|
|
74
|
+
/**
|
|
75
|
+
* Decodes a client message
|
|
76
|
+
* @param raw - Raw data from client WebSocket
|
|
77
|
+
* @returns Decoded message or null if invalid
|
|
78
|
+
*/
|
|
79
|
+
declare function decodeClientMessage(raw: any): MessageFrame | null;
|
|
80
|
+
/**
|
|
81
|
+
* Decodes a server message
|
|
82
|
+
* @param raw - Raw data from server WebSocket
|
|
83
|
+
* @returns Decoded message or null if invalid
|
|
84
|
+
*/
|
|
85
|
+
declare function decodeServerMessage(raw: any): MessageFrame | null;
|
|
86
|
+
//#endregion
|
|
87
|
+
export { encodeFrame as a, ConnectionMeta as c, ServerMessage as d, VeraniMessage as f, encodeClientMessage as i, MessageFrame as l, decodeFrame as n, encodeServerMessage as o, decodeServerMessage as r, ClientMessage as s, decodeClientMessage as t, PROTOCOL_VERSION as u };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function isValidFrame(e){return e&&typeof e==`object`&&typeof e.type==`string`&&(e.channel===void 0||typeof e.channel==`string`)}function decodeFrame(a){try{let o=typeof a==`string`?a:a.toString(),s=JSON.parse(o);return isValidFrame(s)?s:null}catch{return null}}function decodeClientMessage(e){return decodeFrame(e)}function decodeServerMessage(e){return decodeFrame(e)}function encodeFrame(e){try{return JSON.stringify(e)}catch(e){throw Error(`Failed to encode frame: ${e instanceof Error?e.message:`unknown error`}`)}}function encodeClientMessage(e){return encodeFrame(e)}function encodeServerMessage(e){return encodeFrame(e)}const PROTOCOL_VERSION=`1.0.0`;Object.defineProperty(exports,`a`,{enumerable:!0,get:function(){return decodeClientMessage}}),Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return encodeServerMessage}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return encodeClientMessage}}),Object.defineProperty(exports,`o`,{enumerable:!0,get:function(){return decodeFrame}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return encodeFrame}}),Object.defineProperty(exports,`s`,{enumerable:!0,get:function(){return decodeServerMessage}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return`1.0.0`}});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function isValidFrame(e){return e&&typeof e==`object`&&typeof e.type==`string`&&(e.channel===void 0||typeof e.channel==`string`)}function decodeFrame(a){try{let o=typeof a==`string`?a:a.toString(),s=JSON.parse(o);return isValidFrame(s)?s:null}catch{return null}}function decodeClientMessage(e){return decodeFrame(e)}function decodeServerMessage(e){return decodeFrame(e)}function encodeFrame(e){try{return JSON.stringify(e)}catch(e){throw Error(`Failed to encode frame: ${e instanceof Error?e.message:`unknown error`}`)}}function encodeClientMessage(e){return encodeFrame(e)}function encodeServerMessage(e){return encodeFrame(e)}const PROTOCOL_VERSION=`1.0.0`;export{decodeClientMessage as a,encodeServerMessage as i,encodeClientMessage as n,decodeFrame as o,encodeFrame as r,decodeServerMessage as s,PROTOCOL_VERSION as t};
|
package/dist/verani.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
let __cloudflare_actors=require(`@cloudflare/actors`);function defaultExtractMeta(e){let
|
|
1
|
+
const require_types=require(`./types-083oWz55.cjs`);let __cloudflare_actors=require(`@cloudflare/actors`);function defaultExtractMeta(e){let a=crypto.randomUUID(),o=crypto.randomUUID(),s=new URL(e.url).searchParams.get(`channels`);return{userId:a,clientId:o,channels:s?s.split(`,`).map(e=>e.trim()).filter(Boolean):[`default`]}}function defineRoom(e){return{name:e.name,websocketPath:e.websocketPath,extractMeta:e.extractMeta||defaultExtractMeta,onConnect:e.onConnect,onDisconnect:e.onDisconnect,onMessage:e.onMessage,onError:e.onError}}function storeAttachment(e,a){e.serializeAttachment(a)}function restoreSessions(e){let a=0;for(let o of e.ctx.getWebSockets()){let s=o.deserializeAttachment();s&&(e.sessions.set(o,{ws:o,meta:s}),a++)}}function decodeFrame$1(a){return require_types.o(a)??{type:`invalid`}}function encodeFrame$1(a){return require_types.r(a)}function sanitizeToClassName(e){return e.replace(/^\/+/,``).split(/[-_\/\s]+/).map(e=>e.replace(/[^a-zA-Z0-9]/g,``)).filter(e=>e.length>0).map(e=>e.charAt(0).toUpperCase()+e.slice(1).toLowerCase()).join(``)||`VeraniActor`}function createActorHandler(e){let o=sanitizeToClassName(e.name||e.websocketPath||`VeraniActor`);class s extends __cloudflare_actors.Actor{constructor(...e){super(...e),this.sessions=new Map}static configuration(a){return{locationHint:`me`,sockets:{upgradePath:e.websocketPath,autoResponse:{ping:`ping`,pong:`pong`}}}}async shouldUpgradeWebSocket(e){return!0}async fetch(a){let o=new URL(a.url),s=a.headers.get(`Upgrade`);return o.pathname===e.websocketPath&&s===`websocket`&&await this.shouldUpgradeWebSocket(a)?this.onWebSocketUpgrade(a):this.onRequest(a)}async onInit(){try{restoreSessions(this),e.onHibernationRestore&&this.sessions.size>0&&await e.onHibernationRestore(this)}catch{}}onWebSocketConnect(a,o){try{let s;if(s=e.extractMeta?e.extractMeta(o):{userId:`anonymous`,clientId:crypto.randomUUID(),channels:[`default`]},storeAttachment(a,s),this.sessions.set(a,{ws:a,meta:s}),e.onConnect){let o={actor:this,ws:a,meta:s};e.onConnect(o)}}catch(o){if(e.onError)try{e.onError(o,{actor:this,ws:a,meta:{userId:`unknown`,clientId:`unknown`,channels:[]}})}catch{}a.close(1011,`Internal server error`)}}onWebSocketMessage(a,o){let s;try{let c=decodeFrame$1(o);if(s=this.sessions.get(a),!s)return;if(e.onMessage){let o={actor:this,ws:a,meta:s.meta,frame:c};e.onMessage(o,c)}}catch(o){if(e.onError&&s)try{e.onError(o,{actor:this,ws:a,meta:s.meta})}catch{}}}onWebSocketDisconnect(a){try{let o=this.sessions.get(a);if(this.sessions.delete(a),o&&e.onDisconnect){let s={actor:this,ws:a,meta:o.meta};e.onDisconnect(s)}}catch{}}broadcast(e,a,o){let s=0,c=encodeFrame$1({type:`event`,channel:e,data:a});for(let{ws:a,meta:l}of this.sessions.values())if(l.channels.includes(e)&&!(o?.except&&a===o.except)&&!(o?.userIds&&!o.userIds.includes(l.userId))&&!(o?.clientIds&&!o.clientIds.includes(l.clientId)))try{a.send(c),s++}catch{}return s}getSessionCount(){return this.sessions.size}getConnectedUserIds(){let e=new Set;for(let{meta:a}of this.sessions.values())e.add(a.userId);return Array.from(e)}getUserSessions(e){let a=[];for(let{ws:o,meta:s}of this.sessions.values())s.userId===e&&a.push(o);return a}sendToUser(e,a,o){let s=0,c=encodeFrame$1({type:`event`,channel:a,data:o});for(let{ws:o,meta:l}of this.sessions.values())if(l.userId===e&&l.channels.includes(a))try{o.send(c),s++}catch{}return s}getStorage(){return this.ctx.storage}}return Object.defineProperty(s,`name`,{value:o,writable:!1,configurable:!0}),s}exports.PROTOCOL_VERSION=require_types.t,exports.createActorHandler=createActorHandler,exports.decodeClientMessage=require_types.a,exports.decodeFrame=require_types.o,exports.decodeServerMessage=require_types.s,exports.defineRoom=defineRoom,exports.encodeClientMessage=require_types.n,exports.encodeFrame=require_types.r,exports.encodeServerMessage=require_types.i,exports.restoreSessions=restoreSessions,exports.storeAttachment=storeAttachment;
|
package/dist/verani.d.cts
CHANGED
|
@@ -1,52 +1,8 @@
|
|
|
1
|
+
import { a as encodeFrame, c as ConnectionMeta, d as ServerMessage, f as VeraniMessage, i as encodeClientMessage, l as MessageFrame, n as decodeFrame, o as encodeServerMessage, r as decodeServerMessage, s as ClientMessage, t as decodeClientMessage, u as PROTOCOL_VERSION } from "./decode-DMA_rBWB.cjs";
|
|
1
2
|
import { Actor, ActorConfiguration } from "@cloudflare/actors";
|
|
2
3
|
|
|
3
|
-
//#region src/shared/types.d.ts
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Core message types shared between client and server
|
|
7
|
-
*/
|
|
8
|
-
/**
|
|
9
|
-
* Base message frame structure used for all WebSocket communication
|
|
10
|
-
*/
|
|
11
|
-
interface MessageFrame {
|
|
12
|
-
type: string;
|
|
13
|
-
channel?: string;
|
|
14
|
-
data?: any;
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* Message sent from client to server
|
|
18
|
-
*/
|
|
19
|
-
interface ClientMessage extends MessageFrame {
|
|
20
|
-
type: string;
|
|
21
|
-
channel?: string;
|
|
22
|
-
data?: any;
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* Message sent from server to client
|
|
26
|
-
*/
|
|
27
|
-
interface ServerMessage extends MessageFrame {
|
|
28
|
-
type: string;
|
|
29
|
-
channel?: string;
|
|
30
|
-
data?: any;
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Connection metadata attached to each WebSocket
|
|
34
|
-
*/
|
|
35
|
-
interface ConnectionMeta {
|
|
36
|
-
userId: string;
|
|
37
|
-
clientId: string;
|
|
38
|
-
channels: string[];
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Unified message type for both directions
|
|
42
|
-
*/
|
|
43
|
-
type VeraniMessage = ClientMessage | ServerMessage;
|
|
44
|
-
/**
|
|
45
|
-
* Protocol version for future compatibility
|
|
46
|
-
*/
|
|
47
|
-
declare const PROTOCOL_VERSION = "1.0.0";
|
|
48
|
-
//#endregion
|
|
49
4
|
//#region src/actor/types.d.ts
|
|
5
|
+
|
|
50
6
|
/**
|
|
51
7
|
* Options for broadcasting messages to connections
|
|
52
8
|
*/
|
|
@@ -181,246 +137,4 @@ declare function createActorHandler<TMeta extends ConnectionMeta = ConnectionMet
|
|
|
181
137
|
declare function storeAttachment(ws: WebSocket, meta: ConnectionMeta): void;
|
|
182
138
|
declare function restoreSessions(actor: any): void;
|
|
183
139
|
//#endregion
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* Connection state management for Verani client
|
|
187
|
-
*/
|
|
188
|
-
type ConnectionState = "connecting" | "connected" | "disconnected" | "reconnecting" | "error";
|
|
189
|
-
interface ReconnectionConfig {
|
|
190
|
-
/** Enable automatic reconnection */
|
|
191
|
-
enabled: boolean;
|
|
192
|
-
/** Maximum number of reconnection attempts (0 = infinite) */
|
|
193
|
-
maxAttempts: number;
|
|
194
|
-
/** Initial delay in milliseconds */
|
|
195
|
-
initialDelay: number;
|
|
196
|
-
/** Maximum delay in milliseconds */
|
|
197
|
-
maxDelay: number;
|
|
198
|
-
/** Backoff multiplier for exponential backoff */
|
|
199
|
-
backoffMultiplier: number;
|
|
200
|
-
}
|
|
201
|
-
declare const DEFAULT_RECONNECTION_CONFIG: ReconnectionConfig;
|
|
202
|
-
/**
|
|
203
|
-
* Manages WebSocket connection lifecycle and reconnection logic
|
|
204
|
-
*/
|
|
205
|
-
declare class ConnectionManager {
|
|
206
|
-
private config;
|
|
207
|
-
private onStateChange?;
|
|
208
|
-
private state;
|
|
209
|
-
private reconnectAttempts;
|
|
210
|
-
private reconnectTimer?;
|
|
211
|
-
private currentDelay;
|
|
212
|
-
constructor(config?: ReconnectionConfig, onStateChange?: ((state: ConnectionState) => void) | undefined);
|
|
213
|
-
/**
|
|
214
|
-
* Gets the current connection state
|
|
215
|
-
*/
|
|
216
|
-
getState(): ConnectionState;
|
|
217
|
-
/**
|
|
218
|
-
* Updates the connection state and notifies listeners
|
|
219
|
-
*/
|
|
220
|
-
setState(newState: ConnectionState): void;
|
|
221
|
-
/**
|
|
222
|
-
* Resets reconnection state (called on successful connection)
|
|
223
|
-
*/
|
|
224
|
-
resetReconnection(): void;
|
|
225
|
-
/**
|
|
226
|
-
* Schedules a reconnection attempt
|
|
227
|
-
*/
|
|
228
|
-
scheduleReconnect(connectFn: () => void): boolean;
|
|
229
|
-
/**
|
|
230
|
-
* Cancels any pending reconnection
|
|
231
|
-
*/
|
|
232
|
-
cancelReconnect(): void;
|
|
233
|
-
/**
|
|
234
|
-
* Clears the reconnect timer
|
|
235
|
-
*/
|
|
236
|
-
private clearReconnectTimer;
|
|
237
|
-
/**
|
|
238
|
-
* Gets the current reconnection attempt count
|
|
239
|
-
*/
|
|
240
|
-
getReconnectAttempts(): number;
|
|
241
|
-
/**
|
|
242
|
-
* Gets the next reconnection delay
|
|
243
|
-
*/
|
|
244
|
-
getNextDelay(): number;
|
|
245
|
-
/**
|
|
246
|
-
* Cleanup method
|
|
247
|
-
*/
|
|
248
|
-
destroy(): void;
|
|
249
|
-
}
|
|
250
|
-
//#endregion
|
|
251
|
-
//#region src/client/client.d.ts
|
|
252
|
-
/**
|
|
253
|
-
* Client options for configuring the Verani client
|
|
254
|
-
*/
|
|
255
|
-
interface VeraniClientOptions {
|
|
256
|
-
/** Reconnection configuration */
|
|
257
|
-
reconnection?: Partial<ReconnectionConfig>;
|
|
258
|
-
/** Maximum number of messages to queue when disconnected */
|
|
259
|
-
maxQueueSize?: number;
|
|
260
|
-
/** Connection timeout in milliseconds */
|
|
261
|
-
connectionTimeout?: number;
|
|
262
|
-
}
|
|
263
|
-
/**
|
|
264
|
-
* Verani WebSocket client with automatic reconnection and lifecycle management
|
|
265
|
-
*/
|
|
266
|
-
declare class VeraniClient {
|
|
267
|
-
private url;
|
|
268
|
-
private ws?;
|
|
269
|
-
private listeners;
|
|
270
|
-
private connectionManager;
|
|
271
|
-
private messageQueue;
|
|
272
|
-
private options;
|
|
273
|
-
private onOpenCallback?;
|
|
274
|
-
private onCloseCallback?;
|
|
275
|
-
private onErrorCallback?;
|
|
276
|
-
private onStateChangeCallback?;
|
|
277
|
-
private connectionPromise?;
|
|
278
|
-
private connectionResolve?;
|
|
279
|
-
private connectionReject?;
|
|
280
|
-
/**
|
|
281
|
-
* Creates a new Verani client
|
|
282
|
-
* @param url - WebSocket URL to connect to
|
|
283
|
-
* @param options - Client configuration options
|
|
284
|
-
*/
|
|
285
|
-
constructor(url: string, options?: VeraniClientOptions);
|
|
286
|
-
/**
|
|
287
|
-
* Establishes WebSocket connection
|
|
288
|
-
*/
|
|
289
|
-
private connect;
|
|
290
|
-
/**
|
|
291
|
-
* Handles successful WebSocket connection
|
|
292
|
-
*/
|
|
293
|
-
private handleOpen;
|
|
294
|
-
/**
|
|
295
|
-
* Handles incoming WebSocket messages
|
|
296
|
-
*/
|
|
297
|
-
private handleMessage;
|
|
298
|
-
/**
|
|
299
|
-
* Handles WebSocket closure
|
|
300
|
-
*/
|
|
301
|
-
private handleClose;
|
|
302
|
-
/**
|
|
303
|
-
* Handles WebSocket errors
|
|
304
|
-
*/
|
|
305
|
-
private handleError;
|
|
306
|
-
/**
|
|
307
|
-
* Handles connection errors
|
|
308
|
-
*/
|
|
309
|
-
private handleConnectionError;
|
|
310
|
-
/**
|
|
311
|
-
* Flushes queued messages when connection is established
|
|
312
|
-
*/
|
|
313
|
-
private flushMessageQueue;
|
|
314
|
-
/**
|
|
315
|
-
* Gets the current connection state
|
|
316
|
-
*/
|
|
317
|
-
getState(): ConnectionState;
|
|
318
|
-
/**
|
|
319
|
-
* Checks if the client is currently connected
|
|
320
|
-
*/
|
|
321
|
-
isConnected(): boolean;
|
|
322
|
-
/**
|
|
323
|
-
* Waits for the connection to be established
|
|
324
|
-
* @returns Promise that resolves when connected
|
|
325
|
-
*/
|
|
326
|
-
waitForConnection(): Promise<void>;
|
|
327
|
-
/**
|
|
328
|
-
* Registers an event listener
|
|
329
|
-
* @param event - Event type to listen for
|
|
330
|
-
* @param callback - Callback function to invoke when event is received
|
|
331
|
-
*/
|
|
332
|
-
on(event: string, callback: (data: any) => void): void;
|
|
333
|
-
/**
|
|
334
|
-
* Removes an event listener
|
|
335
|
-
* @param event - Event type to remove listener from
|
|
336
|
-
* @param callback - Callback function to remove
|
|
337
|
-
*/
|
|
338
|
-
off(event: string, callback: (data: any) => void): void;
|
|
339
|
-
/**
|
|
340
|
-
* Registers a one-time event listener
|
|
341
|
-
* @param event - Event type to listen for
|
|
342
|
-
* @param callback - Callback function to invoke once
|
|
343
|
-
*/
|
|
344
|
-
once(event: string, callback: (data: any) => void): void;
|
|
345
|
-
/**
|
|
346
|
-
* Sends a message to the server
|
|
347
|
-
* @param type - Message type
|
|
348
|
-
* @param data - Optional message data
|
|
349
|
-
*/
|
|
350
|
-
emit(type: string, data?: any): void;
|
|
351
|
-
/**
|
|
352
|
-
* Queues a message for sending when connected
|
|
353
|
-
*/
|
|
354
|
-
private queueMessage;
|
|
355
|
-
/**
|
|
356
|
-
* Registers lifecycle callback for connection open
|
|
357
|
-
*/
|
|
358
|
-
onOpen(callback: () => void): void;
|
|
359
|
-
/**
|
|
360
|
-
* Registers lifecycle callback for connection close
|
|
361
|
-
*/
|
|
362
|
-
onClose(callback: (event: CloseEvent) => void): void;
|
|
363
|
-
/**
|
|
364
|
-
* Registers lifecycle callback for connection error
|
|
365
|
-
*/
|
|
366
|
-
onError(callback: (error: Event) => void): void;
|
|
367
|
-
/**
|
|
368
|
-
* Registers lifecycle callback for state changes
|
|
369
|
-
*/
|
|
370
|
-
onStateChange(callback: (state: ConnectionState) => void): void;
|
|
371
|
-
/**
|
|
372
|
-
* Manually triggers a reconnection
|
|
373
|
-
*/
|
|
374
|
-
reconnect(): void;
|
|
375
|
-
/**
|
|
376
|
-
* Closes the connection without reconnecting
|
|
377
|
-
*/
|
|
378
|
-
disconnect(): void;
|
|
379
|
-
/**
|
|
380
|
-
* Closes the connection and cleans up resources
|
|
381
|
-
*/
|
|
382
|
-
close(): void;
|
|
383
|
-
}
|
|
384
|
-
//#endregion
|
|
385
|
-
//#region src/shared/encode.d.ts
|
|
386
|
-
/**
|
|
387
|
-
* Encodes a message frame to JSON string for transmission
|
|
388
|
-
* @param frame - The message frame to encode
|
|
389
|
-
* @returns JSON string representation of the frame
|
|
390
|
-
* @throws Error if encoding fails
|
|
391
|
-
*/
|
|
392
|
-
declare function encodeFrame(frame: MessageFrame): string;
|
|
393
|
-
/**
|
|
394
|
-
* Encodes a client message to JSON string
|
|
395
|
-
* @param message - The client message to encode
|
|
396
|
-
* @returns JSON string representation
|
|
397
|
-
*/
|
|
398
|
-
declare function encodeClientMessage(message: MessageFrame): string;
|
|
399
|
-
/**
|
|
400
|
-
* Encodes a server message to JSON string
|
|
401
|
-
* @param message - The server message to encode
|
|
402
|
-
* @returns JSON string representation
|
|
403
|
-
*/
|
|
404
|
-
declare function encodeServerMessage(message: MessageFrame): string;
|
|
405
|
-
//#endregion
|
|
406
|
-
//#region src/shared/decode.d.ts
|
|
407
|
-
/**
|
|
408
|
-
* Decodes a raw message into a MessageFrame
|
|
409
|
-
* @param raw - Raw data from WebSocket (string, ArrayBuffer, etc)
|
|
410
|
-
* @returns Decoded MessageFrame or null if invalid
|
|
411
|
-
*/
|
|
412
|
-
declare function decodeFrame(raw: any): MessageFrame | null;
|
|
413
|
-
/**
|
|
414
|
-
* Decodes a client message
|
|
415
|
-
* @param raw - Raw data from client WebSocket
|
|
416
|
-
* @returns Decoded message or null if invalid
|
|
417
|
-
*/
|
|
418
|
-
declare function decodeClientMessage(raw: any): MessageFrame | null;
|
|
419
|
-
/**
|
|
420
|
-
* Decodes a server message
|
|
421
|
-
* @param raw - Raw data from server WebSocket
|
|
422
|
-
* @returns Decoded message or null if invalid
|
|
423
|
-
*/
|
|
424
|
-
declare function decodeServerMessage(raw: any): MessageFrame | null;
|
|
425
|
-
//#endregion
|
|
426
|
-
export { type ActorHandlerClass, type ActorStub, type BroadcastOptions, type ClientMessage, ConnectionManager, type ConnectionMeta, type ConnectionState, DEFAULT_RECONNECTION_CONFIG, type MessageContext, type MessageFrame, PROTOCOL_VERSION, type ReconnectionConfig, type RoomContext, type RoomDefinition, type ServerMessage, type VeraniActor, VeraniClient, type VeraniClientOptions, type VeraniMessage, createActorHandler, decodeClientMessage, decodeFrame, decodeServerMessage, defineRoom, encodeClientMessage, encodeFrame, encodeServerMessage, restoreSessions, storeAttachment };
|
|
140
|
+
export { type ActorHandlerClass, type ActorStub, type BroadcastOptions, type ClientMessage, type ConnectionMeta, type MessageContext, type MessageFrame, PROTOCOL_VERSION, type RoomContext, type RoomDefinition, type ServerMessage, type VeraniActor, type VeraniMessage, createActorHandler, decodeClientMessage, decodeFrame, decodeServerMessage, defineRoom, encodeClientMessage, encodeFrame, encodeServerMessage, restoreSessions, storeAttachment };
|
package/dist/verani.d.mts
CHANGED
|
@@ -1,52 +1,8 @@
|
|
|
1
|
+
import { a as encodeFrame, c as ConnectionMeta, d as ServerMessage, f as VeraniMessage, i as encodeClientMessage, l as MessageFrame, n as decodeFrame, o as encodeServerMessage, r as decodeServerMessage, s as ClientMessage, t as decodeClientMessage, u as PROTOCOL_VERSION } from "./decode-9DerwlQ1.mjs";
|
|
1
2
|
import { Actor, ActorConfiguration } from "@cloudflare/actors";
|
|
2
3
|
|
|
3
|
-
//#region src/shared/types.d.ts
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Core message types shared between client and server
|
|
7
|
-
*/
|
|
8
|
-
/**
|
|
9
|
-
* Base message frame structure used for all WebSocket communication
|
|
10
|
-
*/
|
|
11
|
-
interface MessageFrame {
|
|
12
|
-
type: string;
|
|
13
|
-
channel?: string;
|
|
14
|
-
data?: any;
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* Message sent from client to server
|
|
18
|
-
*/
|
|
19
|
-
interface ClientMessage extends MessageFrame {
|
|
20
|
-
type: string;
|
|
21
|
-
channel?: string;
|
|
22
|
-
data?: any;
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* Message sent from server to client
|
|
26
|
-
*/
|
|
27
|
-
interface ServerMessage extends MessageFrame {
|
|
28
|
-
type: string;
|
|
29
|
-
channel?: string;
|
|
30
|
-
data?: any;
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Connection metadata attached to each WebSocket
|
|
34
|
-
*/
|
|
35
|
-
interface ConnectionMeta {
|
|
36
|
-
userId: string;
|
|
37
|
-
clientId: string;
|
|
38
|
-
channels: string[];
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Unified message type for both directions
|
|
42
|
-
*/
|
|
43
|
-
type VeraniMessage = ClientMessage | ServerMessage;
|
|
44
|
-
/**
|
|
45
|
-
* Protocol version for future compatibility
|
|
46
|
-
*/
|
|
47
|
-
declare const PROTOCOL_VERSION = "1.0.0";
|
|
48
|
-
//#endregion
|
|
49
4
|
//#region src/actor/types.d.ts
|
|
5
|
+
|
|
50
6
|
/**
|
|
51
7
|
* Options for broadcasting messages to connections
|
|
52
8
|
*/
|
|
@@ -181,246 +137,4 @@ declare function createActorHandler<TMeta extends ConnectionMeta = ConnectionMet
|
|
|
181
137
|
declare function storeAttachment(ws: WebSocket, meta: ConnectionMeta): void;
|
|
182
138
|
declare function restoreSessions(actor: any): void;
|
|
183
139
|
//#endregion
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* Connection state management for Verani client
|
|
187
|
-
*/
|
|
188
|
-
type ConnectionState = "connecting" | "connected" | "disconnected" | "reconnecting" | "error";
|
|
189
|
-
interface ReconnectionConfig {
|
|
190
|
-
/** Enable automatic reconnection */
|
|
191
|
-
enabled: boolean;
|
|
192
|
-
/** Maximum number of reconnection attempts (0 = infinite) */
|
|
193
|
-
maxAttempts: number;
|
|
194
|
-
/** Initial delay in milliseconds */
|
|
195
|
-
initialDelay: number;
|
|
196
|
-
/** Maximum delay in milliseconds */
|
|
197
|
-
maxDelay: number;
|
|
198
|
-
/** Backoff multiplier for exponential backoff */
|
|
199
|
-
backoffMultiplier: number;
|
|
200
|
-
}
|
|
201
|
-
declare const DEFAULT_RECONNECTION_CONFIG: ReconnectionConfig;
|
|
202
|
-
/**
|
|
203
|
-
* Manages WebSocket connection lifecycle and reconnection logic
|
|
204
|
-
*/
|
|
205
|
-
declare class ConnectionManager {
|
|
206
|
-
private config;
|
|
207
|
-
private onStateChange?;
|
|
208
|
-
private state;
|
|
209
|
-
private reconnectAttempts;
|
|
210
|
-
private reconnectTimer?;
|
|
211
|
-
private currentDelay;
|
|
212
|
-
constructor(config?: ReconnectionConfig, onStateChange?: ((state: ConnectionState) => void) | undefined);
|
|
213
|
-
/**
|
|
214
|
-
* Gets the current connection state
|
|
215
|
-
*/
|
|
216
|
-
getState(): ConnectionState;
|
|
217
|
-
/**
|
|
218
|
-
* Updates the connection state and notifies listeners
|
|
219
|
-
*/
|
|
220
|
-
setState(newState: ConnectionState): void;
|
|
221
|
-
/**
|
|
222
|
-
* Resets reconnection state (called on successful connection)
|
|
223
|
-
*/
|
|
224
|
-
resetReconnection(): void;
|
|
225
|
-
/**
|
|
226
|
-
* Schedules a reconnection attempt
|
|
227
|
-
*/
|
|
228
|
-
scheduleReconnect(connectFn: () => void): boolean;
|
|
229
|
-
/**
|
|
230
|
-
* Cancels any pending reconnection
|
|
231
|
-
*/
|
|
232
|
-
cancelReconnect(): void;
|
|
233
|
-
/**
|
|
234
|
-
* Clears the reconnect timer
|
|
235
|
-
*/
|
|
236
|
-
private clearReconnectTimer;
|
|
237
|
-
/**
|
|
238
|
-
* Gets the current reconnection attempt count
|
|
239
|
-
*/
|
|
240
|
-
getReconnectAttempts(): number;
|
|
241
|
-
/**
|
|
242
|
-
* Gets the next reconnection delay
|
|
243
|
-
*/
|
|
244
|
-
getNextDelay(): number;
|
|
245
|
-
/**
|
|
246
|
-
* Cleanup method
|
|
247
|
-
*/
|
|
248
|
-
destroy(): void;
|
|
249
|
-
}
|
|
250
|
-
//#endregion
|
|
251
|
-
//#region src/client/client.d.ts
|
|
252
|
-
/**
|
|
253
|
-
* Client options for configuring the Verani client
|
|
254
|
-
*/
|
|
255
|
-
interface VeraniClientOptions {
|
|
256
|
-
/** Reconnection configuration */
|
|
257
|
-
reconnection?: Partial<ReconnectionConfig>;
|
|
258
|
-
/** Maximum number of messages to queue when disconnected */
|
|
259
|
-
maxQueueSize?: number;
|
|
260
|
-
/** Connection timeout in milliseconds */
|
|
261
|
-
connectionTimeout?: number;
|
|
262
|
-
}
|
|
263
|
-
/**
|
|
264
|
-
* Verani WebSocket client with automatic reconnection and lifecycle management
|
|
265
|
-
*/
|
|
266
|
-
declare class VeraniClient {
|
|
267
|
-
private url;
|
|
268
|
-
private ws?;
|
|
269
|
-
private listeners;
|
|
270
|
-
private connectionManager;
|
|
271
|
-
private messageQueue;
|
|
272
|
-
private options;
|
|
273
|
-
private onOpenCallback?;
|
|
274
|
-
private onCloseCallback?;
|
|
275
|
-
private onErrorCallback?;
|
|
276
|
-
private onStateChangeCallback?;
|
|
277
|
-
private connectionPromise?;
|
|
278
|
-
private connectionResolve?;
|
|
279
|
-
private connectionReject?;
|
|
280
|
-
/**
|
|
281
|
-
* Creates a new Verani client
|
|
282
|
-
* @param url - WebSocket URL to connect to
|
|
283
|
-
* @param options - Client configuration options
|
|
284
|
-
*/
|
|
285
|
-
constructor(url: string, options?: VeraniClientOptions);
|
|
286
|
-
/**
|
|
287
|
-
* Establishes WebSocket connection
|
|
288
|
-
*/
|
|
289
|
-
private connect;
|
|
290
|
-
/**
|
|
291
|
-
* Handles successful WebSocket connection
|
|
292
|
-
*/
|
|
293
|
-
private handleOpen;
|
|
294
|
-
/**
|
|
295
|
-
* Handles incoming WebSocket messages
|
|
296
|
-
*/
|
|
297
|
-
private handleMessage;
|
|
298
|
-
/**
|
|
299
|
-
* Handles WebSocket closure
|
|
300
|
-
*/
|
|
301
|
-
private handleClose;
|
|
302
|
-
/**
|
|
303
|
-
* Handles WebSocket errors
|
|
304
|
-
*/
|
|
305
|
-
private handleError;
|
|
306
|
-
/**
|
|
307
|
-
* Handles connection errors
|
|
308
|
-
*/
|
|
309
|
-
private handleConnectionError;
|
|
310
|
-
/**
|
|
311
|
-
* Flushes queued messages when connection is established
|
|
312
|
-
*/
|
|
313
|
-
private flushMessageQueue;
|
|
314
|
-
/**
|
|
315
|
-
* Gets the current connection state
|
|
316
|
-
*/
|
|
317
|
-
getState(): ConnectionState;
|
|
318
|
-
/**
|
|
319
|
-
* Checks if the client is currently connected
|
|
320
|
-
*/
|
|
321
|
-
isConnected(): boolean;
|
|
322
|
-
/**
|
|
323
|
-
* Waits for the connection to be established
|
|
324
|
-
* @returns Promise that resolves when connected
|
|
325
|
-
*/
|
|
326
|
-
waitForConnection(): Promise<void>;
|
|
327
|
-
/**
|
|
328
|
-
* Registers an event listener
|
|
329
|
-
* @param event - Event type to listen for
|
|
330
|
-
* @param callback - Callback function to invoke when event is received
|
|
331
|
-
*/
|
|
332
|
-
on(event: string, callback: (data: any) => void): void;
|
|
333
|
-
/**
|
|
334
|
-
* Removes an event listener
|
|
335
|
-
* @param event - Event type to remove listener from
|
|
336
|
-
* @param callback - Callback function to remove
|
|
337
|
-
*/
|
|
338
|
-
off(event: string, callback: (data: any) => void): void;
|
|
339
|
-
/**
|
|
340
|
-
* Registers a one-time event listener
|
|
341
|
-
* @param event - Event type to listen for
|
|
342
|
-
* @param callback - Callback function to invoke once
|
|
343
|
-
*/
|
|
344
|
-
once(event: string, callback: (data: any) => void): void;
|
|
345
|
-
/**
|
|
346
|
-
* Sends a message to the server
|
|
347
|
-
* @param type - Message type
|
|
348
|
-
* @param data - Optional message data
|
|
349
|
-
*/
|
|
350
|
-
emit(type: string, data?: any): void;
|
|
351
|
-
/**
|
|
352
|
-
* Queues a message for sending when connected
|
|
353
|
-
*/
|
|
354
|
-
private queueMessage;
|
|
355
|
-
/**
|
|
356
|
-
* Registers lifecycle callback for connection open
|
|
357
|
-
*/
|
|
358
|
-
onOpen(callback: () => void): void;
|
|
359
|
-
/**
|
|
360
|
-
* Registers lifecycle callback for connection close
|
|
361
|
-
*/
|
|
362
|
-
onClose(callback: (event: CloseEvent) => void): void;
|
|
363
|
-
/**
|
|
364
|
-
* Registers lifecycle callback for connection error
|
|
365
|
-
*/
|
|
366
|
-
onError(callback: (error: Event) => void): void;
|
|
367
|
-
/**
|
|
368
|
-
* Registers lifecycle callback for state changes
|
|
369
|
-
*/
|
|
370
|
-
onStateChange(callback: (state: ConnectionState) => void): void;
|
|
371
|
-
/**
|
|
372
|
-
* Manually triggers a reconnection
|
|
373
|
-
*/
|
|
374
|
-
reconnect(): void;
|
|
375
|
-
/**
|
|
376
|
-
* Closes the connection without reconnecting
|
|
377
|
-
*/
|
|
378
|
-
disconnect(): void;
|
|
379
|
-
/**
|
|
380
|
-
* Closes the connection and cleans up resources
|
|
381
|
-
*/
|
|
382
|
-
close(): void;
|
|
383
|
-
}
|
|
384
|
-
//#endregion
|
|
385
|
-
//#region src/shared/encode.d.ts
|
|
386
|
-
/**
|
|
387
|
-
* Encodes a message frame to JSON string for transmission
|
|
388
|
-
* @param frame - The message frame to encode
|
|
389
|
-
* @returns JSON string representation of the frame
|
|
390
|
-
* @throws Error if encoding fails
|
|
391
|
-
*/
|
|
392
|
-
declare function encodeFrame(frame: MessageFrame): string;
|
|
393
|
-
/**
|
|
394
|
-
* Encodes a client message to JSON string
|
|
395
|
-
* @param message - The client message to encode
|
|
396
|
-
* @returns JSON string representation
|
|
397
|
-
*/
|
|
398
|
-
declare function encodeClientMessage(message: MessageFrame): string;
|
|
399
|
-
/**
|
|
400
|
-
* Encodes a server message to JSON string
|
|
401
|
-
* @param message - The server message to encode
|
|
402
|
-
* @returns JSON string representation
|
|
403
|
-
*/
|
|
404
|
-
declare function encodeServerMessage(message: MessageFrame): string;
|
|
405
|
-
//#endregion
|
|
406
|
-
//#region src/shared/decode.d.ts
|
|
407
|
-
/**
|
|
408
|
-
* Decodes a raw message into a MessageFrame
|
|
409
|
-
* @param raw - Raw data from WebSocket (string, ArrayBuffer, etc)
|
|
410
|
-
* @returns Decoded MessageFrame or null if invalid
|
|
411
|
-
*/
|
|
412
|
-
declare function decodeFrame(raw: any): MessageFrame | null;
|
|
413
|
-
/**
|
|
414
|
-
* Decodes a client message
|
|
415
|
-
* @param raw - Raw data from client WebSocket
|
|
416
|
-
* @returns Decoded message or null if invalid
|
|
417
|
-
*/
|
|
418
|
-
declare function decodeClientMessage(raw: any): MessageFrame | null;
|
|
419
|
-
/**
|
|
420
|
-
* Decodes a server message
|
|
421
|
-
* @param raw - Raw data from server WebSocket
|
|
422
|
-
* @returns Decoded message or null if invalid
|
|
423
|
-
*/
|
|
424
|
-
declare function decodeServerMessage(raw: any): MessageFrame | null;
|
|
425
|
-
//#endregion
|
|
426
|
-
export { type ActorHandlerClass, type ActorStub, type BroadcastOptions, type ClientMessage, ConnectionManager, type ConnectionMeta, type ConnectionState, DEFAULT_RECONNECTION_CONFIG, type MessageContext, type MessageFrame, PROTOCOL_VERSION, type ReconnectionConfig, type RoomContext, type RoomDefinition, type ServerMessage, type VeraniActor, VeraniClient, type VeraniClientOptions, type VeraniMessage, createActorHandler, decodeClientMessage, decodeFrame, decodeServerMessage, defineRoom, encodeClientMessage, encodeFrame, encodeServerMessage, restoreSessions, storeAttachment };
|
|
140
|
+
export { type ActorHandlerClass, type ActorStub, type BroadcastOptions, type ClientMessage, type ConnectionMeta, type MessageContext, type MessageFrame, PROTOCOL_VERSION, type RoomContext, type RoomDefinition, type ServerMessage, type VeraniActor, type VeraniMessage, createActorHandler, decodeClientMessage, decodeFrame, decodeServerMessage, defineRoom, encodeClientMessage, encodeFrame, encodeServerMessage, restoreSessions, storeAttachment };
|
package/dist/verani.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Actor}from"@cloudflare/actors";function defaultExtractMeta(e){let
|
|
1
|
+
import{a as decodeClientMessage,i as encodeServerMessage,n as encodeClientMessage,o as decodeFrame,r as encodeFrame,s as decodeServerMessage,t as PROTOCOL_VERSION}from"./types-CJLnZrA8.mjs";import{Actor}from"@cloudflare/actors";function defaultExtractMeta(e){let d=crypto.randomUUID(),f=crypto.randomUUID(),p=new URL(e.url).searchParams.get(`channels`);return{userId:d,clientId:f,channels:p?p.split(`,`).map(e=>e.trim()).filter(Boolean):[`default`]}}function defineRoom(e){return{name:e.name,websocketPath:e.websocketPath,extractMeta:e.extractMeta||defaultExtractMeta,onConnect:e.onConnect,onDisconnect:e.onDisconnect,onMessage:e.onMessage,onError:e.onError}}function storeAttachment(e,d){e.serializeAttachment(d)}function restoreSessions(e){let d=0;for(let f of e.ctx.getWebSockets()){let p=f.deserializeAttachment();p&&(e.sessions.set(f,{ws:f,meta:p}),d++)}}function decodeFrame$1(e){return decodeFrame(e)??{type:`invalid`}}function encodeFrame$1(e){return encodeFrame(e)}function sanitizeToClassName(e){return e.replace(/^\/+/,``).split(/[-_\/\s]+/).map(e=>e.replace(/[^a-zA-Z0-9]/g,``)).filter(e=>e.length>0).map(e=>e.charAt(0).toUpperCase()+e.slice(1).toLowerCase()).join(``)||`VeraniActor`}function createActorHandler(e){let d=sanitizeToClassName(e.name||e.websocketPath||`VeraniActor`);class f extends Actor{constructor(...e){super(...e),this.sessions=new Map}static configuration(d){return{locationHint:`me`,sockets:{upgradePath:e.websocketPath,autoResponse:{ping:`ping`,pong:`pong`}}}}async shouldUpgradeWebSocket(e){return!0}async fetch(d){let f=new URL(d.url),p=d.headers.get(`Upgrade`);return f.pathname===e.websocketPath&&p===`websocket`&&await this.shouldUpgradeWebSocket(d)?this.onWebSocketUpgrade(d):this.onRequest(d)}async onInit(){try{restoreSessions(this),e.onHibernationRestore&&this.sessions.size>0&&await e.onHibernationRestore(this)}catch{}}onWebSocketConnect(d,f){try{let p;if(p=e.extractMeta?e.extractMeta(f):{userId:`anonymous`,clientId:crypto.randomUUID(),channels:[`default`]},storeAttachment(d,p),this.sessions.set(d,{ws:d,meta:p}),e.onConnect){let f={actor:this,ws:d,meta:p};e.onConnect(f)}}catch(f){if(e.onError)try{e.onError(f,{actor:this,ws:d,meta:{userId:`unknown`,clientId:`unknown`,channels:[]}})}catch{}d.close(1011,`Internal server error`)}}onWebSocketMessage(d,f){let p;try{let m=decodeFrame$1(f);if(p=this.sessions.get(d),!p)return;if(e.onMessage){let f={actor:this,ws:d,meta:p.meta,frame:m};e.onMessage(f,m)}}catch(f){if(e.onError&&p)try{e.onError(f,{actor:this,ws:d,meta:p.meta})}catch{}}}onWebSocketDisconnect(d){try{let f=this.sessions.get(d);if(this.sessions.delete(d),f&&e.onDisconnect){let p={actor:this,ws:d,meta:f.meta};e.onDisconnect(p)}}catch{}}broadcast(e,d,f){let p=0,m=encodeFrame$1({type:`event`,channel:e,data:d});for(let{ws:d,meta:h}of this.sessions.values())if(h.channels.includes(e)&&!(f?.except&&d===f.except)&&!(f?.userIds&&!f.userIds.includes(h.userId))&&!(f?.clientIds&&!f.clientIds.includes(h.clientId)))try{d.send(m),p++}catch{}return p}getSessionCount(){return this.sessions.size}getConnectedUserIds(){let e=new Set;for(let{meta:d}of this.sessions.values())e.add(d.userId);return Array.from(e)}getUserSessions(e){let d=[];for(let{ws:f,meta:p}of this.sessions.values())p.userId===e&&d.push(f);return d}sendToUser(e,d,f){let p=0,m=encodeFrame$1({type:`event`,channel:d,data:f});for(let{ws:f,meta:h}of this.sessions.values())if(h.userId===e&&h.channels.includes(d))try{f.send(m),p++}catch{}return p}getStorage(){return this.ctx.storage}}return Object.defineProperty(f,`name`,{value:d,writable:!1,configurable:!0}),f}export{PROTOCOL_VERSION,createActorHandler,decodeClientMessage,decodeFrame,decodeServerMessage,defineRoom,encodeClientMessage,encodeFrame,encodeServerMessage,restoreSessions,storeAttachment};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "verani",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"description": "A simple, focused realtime SDK for Cloudflare Actors with Socket.io-like semantics",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"keywords": [
|
|
@@ -24,6 +24,16 @@
|
|
|
24
24
|
"types": "./dist/verani.d.cts",
|
|
25
25
|
"default": "./dist/verani.cjs"
|
|
26
26
|
}
|
|
27
|
+
},
|
|
28
|
+
"./client": {
|
|
29
|
+
"import": {
|
|
30
|
+
"types": "./dist/client.d.mts",
|
|
31
|
+
"default": "./dist/client.mjs"
|
|
32
|
+
},
|
|
33
|
+
"require": {
|
|
34
|
+
"types": "./dist/client.d.cts",
|
|
35
|
+
"default": "./dist/client.cjs"
|
|
36
|
+
}
|
|
27
37
|
}
|
|
28
38
|
},
|
|
29
39
|
"files": [
|