pulse-js-framework 1.7.11 → 1.7.13

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.
@@ -0,0 +1,347 @@
1
+ /**
2
+ * Pulse WebSocket TypeScript Definitions
3
+ * @module pulse-js-framework/runtime/websocket
4
+ */
5
+
6
+ import { Pulse } from './pulse';
7
+
8
+ // ============================================================================
9
+ // Error Types
10
+ // ============================================================================
11
+
12
+ /**
13
+ * WebSocket error codes
14
+ */
15
+ export type WebSocketErrorCode =
16
+ | 'CONNECT_FAILED'
17
+ | 'CLOSE'
18
+ | 'TIMEOUT'
19
+ | 'PARSE_ERROR'
20
+ | 'SEND_FAILED'
21
+ | 'RECONNECT_EXHAUSTED'
22
+ | 'WEBSOCKET_ERROR';
23
+
24
+ /**
25
+ * WebSocket connection state
26
+ */
27
+ export type WebSocketState = 'connecting' | 'open' | 'closing' | 'closed';
28
+
29
+ /**
30
+ * WebSocket Error with connection context
31
+ */
32
+ export declare class WebSocketError extends Error {
33
+ readonly name: 'WebSocketError';
34
+ readonly code: WebSocketErrorCode;
35
+ readonly url: string | null;
36
+ readonly closeCode: number | null;
37
+ readonly closeReason: string | null;
38
+ readonly event: Event | null;
39
+ readonly isWebSocketError: true;
40
+
41
+ constructor(message: string, options?: {
42
+ code?: WebSocketErrorCode;
43
+ url?: string;
44
+ closeCode?: number;
45
+ closeReason?: string;
46
+ context?: string;
47
+ suggestion?: string;
48
+ event?: Event;
49
+ });
50
+
51
+ static isWebSocketError(error: unknown): error is WebSocketError;
52
+
53
+ isConnectFailed(): boolean;
54
+ isClose(): boolean;
55
+ isTimeout(): boolean;
56
+ isParseError(): boolean;
57
+ isSendFailed(): boolean;
58
+ }
59
+
60
+ // ============================================================================
61
+ // Interceptor Types
62
+ // ============================================================================
63
+
64
+ /**
65
+ * Message interceptor handler
66
+ */
67
+ export interface MessageInterceptorHandler {
68
+ onMessage: (data: unknown) => unknown;
69
+ onError?: (error: Error) => void;
70
+ }
71
+
72
+ /**
73
+ * Message interceptor manager
74
+ */
75
+ export declare class MessageInterceptorManager {
76
+ /**
77
+ * Add a message interceptor
78
+ * @param onMessage Transform message data
79
+ * @param onError Handle interceptor errors
80
+ * @returns Interceptor ID for removal
81
+ */
82
+ use(onMessage: (data: unknown) => unknown, onError?: (error: Error) => void): number;
83
+
84
+ /**
85
+ * Remove an interceptor by ID
86
+ */
87
+ eject(id: number): void;
88
+
89
+ /**
90
+ * Remove all interceptors
91
+ */
92
+ clear(): void;
93
+
94
+ /**
95
+ * Number of registered interceptors
96
+ */
97
+ readonly size: number;
98
+
99
+ [Symbol.iterator](): IterableIterator<MessageInterceptorHandler>;
100
+ }
101
+
102
+ // ============================================================================
103
+ // Configuration Types
104
+ // ============================================================================
105
+
106
+ /**
107
+ * WebSocket configuration options
108
+ */
109
+ export interface WebSocketOptions {
110
+ // Connection
111
+ /** WebSocket subprotocols */
112
+ protocols?: string[];
113
+ /** Connection timeout in ms (default: 10000) */
114
+ connectTimeout?: number;
115
+ /** Connect immediately on creation (default: true) */
116
+ autoConnect?: boolean;
117
+
118
+ // Reconnection
119
+ /** Enable auto-reconnection (default: true) */
120
+ reconnect?: boolean;
121
+ /** Max reconnection attempts, 0 = infinite (default: 5) */
122
+ maxRetries?: number;
123
+ /** Base delay for exponential backoff in ms (default: 1000) */
124
+ baseDelay?: number;
125
+ /** Maximum delay between retries in ms (default: 30000) */
126
+ maxDelay?: number;
127
+ /** Jitter factor for backoff randomization 0-1 (default: 0.3) */
128
+ jitterFactor?: number;
129
+
130
+ // Heartbeat
131
+ /** Enable heartbeat/ping-pong (default: false) */
132
+ heartbeat?: boolean;
133
+ /** Heartbeat interval in ms (default: 30000) */
134
+ heartbeatInterval?: number;
135
+ /** Pong response timeout in ms (default: 10000) */
136
+ heartbeatTimeout?: number;
137
+ /** Message to send as heartbeat (default: 'ping') */
138
+ heartbeatMessage?: unknown;
139
+ /** Custom function to detect pong responses */
140
+ isPong?: (message: unknown) => boolean;
141
+
142
+ // Message handling
143
+ /** Queue messages when disconnected (default: true) */
144
+ queueWhileDisconnected?: boolean;
145
+ /** Maximum queued messages (default: 100) */
146
+ maxQueueSize?: number;
147
+ /** Default message type (default: 'json') */
148
+ messageType?: 'json' | 'text' | 'binary';
149
+ /** Auto-parse JSON messages (default: true) */
150
+ autoParseJson?: boolean;
151
+
152
+ // Callbacks
153
+ /** Called when connection opens */
154
+ onOpen?: (event: Event) => void;
155
+ /** Called when connection closes */
156
+ onClose?: (event: CloseEvent) => void;
157
+ /** Called on error */
158
+ onError?: (error: WebSocketError) => void;
159
+ /** Called on message received */
160
+ onMessage?: (data: unknown, event: MessageEvent) => void;
161
+ /** Called before each reconnection attempt */
162
+ onReconnecting?: (attempt: number, delay: number) => void;
163
+ /** Called after successful reconnection */
164
+ onReconnected?: () => void;
165
+ }
166
+
167
+ // ============================================================================
168
+ // WebSocket Instance Types
169
+ // ============================================================================
170
+
171
+ /**
172
+ * WebSocket instance returned by createWebSocket
173
+ */
174
+ export interface WebSocketInstance {
175
+ // Reactive state
176
+ /** Connection state pulse */
177
+ readonly state: Pulse<WebSocketState>;
178
+ /** True when connected */
179
+ readonly connected: Pulse<boolean>;
180
+ /** True during reconnection attempts */
181
+ readonly reconnecting: Pulse<boolean>;
182
+ /** Current reconnection attempt number */
183
+ readonly reconnectAttempt: Pulse<number>;
184
+ /** Last error */
185
+ readonly error: Pulse<WebSocketError | null>;
186
+ /** Number of queued messages */
187
+ readonly queuedCount: Pulse<number>;
188
+
189
+ // Methods
190
+ /** Manually connect (if autoConnect=false) */
191
+ connect(): void;
192
+ /** Close connection */
193
+ disconnect(code?: number, reason?: string): void;
194
+ /** Send a message (auto-serializes objects to JSON) */
195
+ send(data: unknown): void;
196
+ /** Send JSON message */
197
+ sendJson(data: unknown): void;
198
+ /** Send binary message */
199
+ sendBinary(data: ArrayBuffer | ArrayBufferView | Blob): void;
200
+ /** Clean up and close permanently */
201
+ dispose(): void;
202
+
203
+ // Interceptors
204
+ readonly interceptors: {
205
+ incoming: MessageInterceptorManager;
206
+ outgoing: MessageInterceptorManager;
207
+ };
208
+
209
+ // Events
210
+ /** Add event listener, returns unsubscribe function */
211
+ on(event: 'open', handler: (event: Event) => void): () => void;
212
+ on(event: 'close', handler: (event: CloseEvent) => void): () => void;
213
+ on(event: 'error', handler: (error: WebSocketError) => void): () => void;
214
+ on(event: 'message', handler: (data: unknown, event: MessageEvent) => void): () => void;
215
+ /** Remove event listener */
216
+ off(event: string, handler: Function): void;
217
+ /** Add one-time listener */
218
+ once(event: 'open', handler: (event: Event) => void): () => void;
219
+ once(event: 'close', handler: (event: CloseEvent) => void): () => void;
220
+ once(event: 'error', handler: (error: WebSocketError) => void): () => void;
221
+ once(event: 'message', handler: (data: unknown, event: MessageEvent) => void): () => void;
222
+
223
+ // Properties
224
+ /** WebSocket URL */
225
+ readonly url: string;
226
+ /** Raw WebSocket instance */
227
+ readonly socket: WebSocket | null;
228
+ /** Merged options */
229
+ readonly options: WebSocketOptions;
230
+ }
231
+
232
+ // ============================================================================
233
+ // useWebSocket Hook Types
234
+ // ============================================================================
235
+
236
+ /**
237
+ * useWebSocket hook options
238
+ */
239
+ export interface UseWebSocketOptions extends WebSocketOptions {
240
+ /** Connect immediately (default: true) */
241
+ immediate?: boolean;
242
+ /** Initial lastMessage value (default: null) */
243
+ initialData?: unknown;
244
+ /** Keep last N messages, 0 = no history (default: 0) */
245
+ messageHistorySize?: number;
246
+ }
247
+
248
+ /**
249
+ * useWebSocket hook return type
250
+ */
251
+ export interface UseWebSocketReturn {
252
+ // State
253
+ /** True when connected */
254
+ connected: Pulse<boolean>;
255
+ /** Most recent message */
256
+ lastMessage: Pulse<unknown>;
257
+ /** Message history (if messageHistorySize > 0) */
258
+ messages: Pulse<unknown[]>;
259
+ /** Last error */
260
+ error: Pulse<WebSocketError | null>;
261
+ /** True during reconnection */
262
+ reconnecting: Pulse<boolean>;
263
+ /** Connection state */
264
+ state: Pulse<WebSocketState>;
265
+ /** Number of queued messages */
266
+ queuedCount: Pulse<number>;
267
+ /** Current reconnection attempt */
268
+ reconnectAttempt: Pulse<number>;
269
+
270
+ // Methods
271
+ /** Send a message */
272
+ send(data: unknown): void;
273
+ /** Send JSON message */
274
+ sendJson(data: unknown): void;
275
+ /** Send binary message */
276
+ sendBinary(data: ArrayBuffer | ArrayBufferView | Blob): void;
277
+ /** Manually connect */
278
+ connect(): void;
279
+ /** Close connection */
280
+ disconnect(code?: number, reason?: string): void;
281
+ /** Clear message history */
282
+ clearMessages(): void;
283
+ /** Clear error state */
284
+ clearError(): void;
285
+
286
+ /** Underlying WebSocket instance */
287
+ readonly ws: WebSocketInstance;
288
+ }
289
+
290
+ // ============================================================================
291
+ // Factory Functions
292
+ // ============================================================================
293
+
294
+ /**
295
+ * Create a WebSocket client with auto-reconnection, heartbeat, and message queuing.
296
+ *
297
+ * @param url WebSocket URL (ws:// or wss://)
298
+ * @param options Configuration options
299
+ * @returns WebSocket instance with reactive state and controls
300
+ *
301
+ * @example
302
+ * const ws = createWebSocket('wss://api.example.com/ws', {
303
+ * reconnect: true,
304
+ * heartbeat: true
305
+ * });
306
+ *
307
+ * ws.on('message', (data) => console.log('Received:', data));
308
+ * ws.send({ type: 'subscribe', channel: 'updates' });
309
+ */
310
+ export declare function createWebSocket(
311
+ url: string,
312
+ options?: WebSocketOptions
313
+ ): WebSocketInstance;
314
+
315
+ /**
316
+ * Reactive WebSocket hook with automatic cleanup.
317
+ *
318
+ * @param url WebSocket URL
319
+ * @param options Configuration options
320
+ * @returns Reactive WebSocket state and controls
321
+ *
322
+ * @example
323
+ * const { connected, lastMessage, send } = useWebSocket('wss://api.example.com/ws');
324
+ *
325
+ * effect(() => {
326
+ * if (connected.get()) {
327
+ * send({ type: 'subscribe' });
328
+ * }
329
+ * });
330
+ */
331
+ export declare function useWebSocket(
332
+ url: string,
333
+ options?: UseWebSocketOptions
334
+ ): UseWebSocketReturn;
335
+
336
+ // ============================================================================
337
+ // Default Export
338
+ // ============================================================================
339
+
340
+ declare const _default: {
341
+ createWebSocket: typeof createWebSocket;
342
+ useWebSocket: typeof useWebSocket;
343
+ WebSocketError: typeof WebSocketError;
344
+ MessageInterceptorManager: typeof MessageInterceptorManager;
345
+ };
346
+
347
+ export default _default;