@forklaunch/ws 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 +21 -0
- package/lib/index.d.mts +809 -0
- package/lib/index.d.ts +809 -0
- package/lib/index.js +521 -0
- package/lib/index.mjs +491 -0
- package/package.json +59 -0
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,809 @@
|
|
|
1
|
+
import { EventSchema, ExtractSchemaFromRecord, ExtractSchemaFromEntry, ServerEventSchema } from '@forklaunch/core/ws';
|
|
2
|
+
import { AnySchemaValidator, IdiomaticSchema, Schema } from '@forklaunch/validator';
|
|
3
|
+
import { IncomingMessage, ClientRequest } from 'http';
|
|
4
|
+
import { WebSocket, WebSocketServer } from 'ws';
|
|
5
|
+
export { WebSocket, WebSocketServer } from 'ws';
|
|
6
|
+
export { EventEmitter } from 'events';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Event map for outgoing events (emit)
|
|
10
|
+
* Maps event names to their argument signatures for type-safe event emission
|
|
11
|
+
*
|
|
12
|
+
* @internal
|
|
13
|
+
*/
|
|
14
|
+
type OutgoingEventMap<SV extends AnySchemaValidator, ES extends EventSchema<SV>> = {
|
|
15
|
+
message: [
|
|
16
|
+
data: Schema<ExtractSchemaFromRecord<SV, ES['clientMessages']>, SV>,
|
|
17
|
+
isBinary: boolean
|
|
18
|
+
];
|
|
19
|
+
close: [
|
|
20
|
+
code: number,
|
|
21
|
+
reason: Schema<ExtractSchemaFromRecord<SV, ES['closeReason']>, SV>
|
|
22
|
+
];
|
|
23
|
+
error: [error: Schema<ExtractSchemaFromRecord<SV, ES['errors']>, SV>];
|
|
24
|
+
open: [];
|
|
25
|
+
ping: [data: Schema<ExtractSchemaFromEntry<SV, ES['ping']>, SV>];
|
|
26
|
+
pong: [data: Schema<ExtractSchemaFromEntry<SV, ES['pong']>, SV>];
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Extended WebSocket with built-in schema validation and automatic data transformation.
|
|
30
|
+
*
|
|
31
|
+
* ForklaunchWebSocket automatically:
|
|
32
|
+
* - Validates incoming and outgoing messages against provided schemas
|
|
33
|
+
* - Decodes Buffer data to JavaScript objects for incoming messages
|
|
34
|
+
* - Encodes JavaScript objects to Buffer data for outgoing messages
|
|
35
|
+
* - Provides type-safe event handlers with full TypeScript support
|
|
36
|
+
*
|
|
37
|
+
* @template SV - The schema validator type (e.g., ZodSchemaValidator)
|
|
38
|
+
* @template ES - The event schema defining message types for each event
|
|
39
|
+
*
|
|
40
|
+
* @example Basic Usage
|
|
41
|
+
* ```typescript
|
|
42
|
+
* import { ZodSchemaValidator } from '@forklaunch/validator';
|
|
43
|
+
* import { z } from 'zod';
|
|
44
|
+
* import { ForklaunchWebSocket } from '@forklaunch/ws';
|
|
45
|
+
*
|
|
46
|
+
* const validator = new ZodSchemaValidator();
|
|
47
|
+
* const schemas = {
|
|
48
|
+
* ping: z.object({ ts: z.number() }),
|
|
49
|
+
* pong: z.object({ ts: z.number() }),
|
|
50
|
+
* clientMessages: z.object({ type: z.string(), data: z.any() }),
|
|
51
|
+
* serverMessages: z.object({ type: z.string(), data: z.any() }),
|
|
52
|
+
* errors: z.object({ code: z.number(), message: z.string() }),
|
|
53
|
+
* closeReason: z.object({ reason: z.string() })
|
|
54
|
+
* };
|
|
55
|
+
*
|
|
56
|
+
* const ws = new ForklaunchWebSocket(
|
|
57
|
+
* validator,
|
|
58
|
+
* schemas,
|
|
59
|
+
* 'ws://localhost:8080'
|
|
60
|
+
* );
|
|
61
|
+
*
|
|
62
|
+
* // Incoming messages are automatically validated and decoded
|
|
63
|
+
* ws.on('message', (data, isBinary) => {
|
|
64
|
+
* console.log('Received:', data); // data is typed and validated
|
|
65
|
+
* });
|
|
66
|
+
*
|
|
67
|
+
* // Outgoing messages are automatically validated and encoded
|
|
68
|
+
* ws.send({ type: 'hello', data: 'world' });
|
|
69
|
+
* ```
|
|
70
|
+
*
|
|
71
|
+
* @example With Custom Schemas
|
|
72
|
+
* ```typescript
|
|
73
|
+
* const chatSchemas = {
|
|
74
|
+
* ping: z.object({ timestamp: z.number() }),
|
|
75
|
+
* pong: z.object({ timestamp: z.number() }),
|
|
76
|
+
* clientMessages: z.discriminatedUnion('type', [
|
|
77
|
+
* z.object({ type: z.literal('chat'), message: z.string(), userId: z.string() }),
|
|
78
|
+
* z.object({ type: z.literal('join'), roomId: z.string() })
|
|
79
|
+
* ]),
|
|
80
|
+
* serverMessages: z.discriminatedUnion('type', [
|
|
81
|
+
* z.object({ type: z.literal('chat'), message: z.string(), userId: z.string() }),
|
|
82
|
+
* z.object({ type: z.literal('user-joined'), userId: z.string() })
|
|
83
|
+
* ])
|
|
84
|
+
* };
|
|
85
|
+
*
|
|
86
|
+
* const ws = new ForklaunchWebSocket(validator, chatSchemas, 'ws://chat.example.com');
|
|
87
|
+
* ```
|
|
88
|
+
*
|
|
89
|
+
* @see {@link EventSchema} for schema structure
|
|
90
|
+
* @see {@link ForklaunchWebSocketServer} for server-side usage
|
|
91
|
+
*/
|
|
92
|
+
declare class ForklaunchWebSocket<SV extends AnySchemaValidator, const ES extends EventSchema<SV>> extends WebSocket {
|
|
93
|
+
private eventSchemas;
|
|
94
|
+
private schemas;
|
|
95
|
+
private schemaValidator;
|
|
96
|
+
/**
|
|
97
|
+
* Creates a new ForklaunchWebSocket instance with schema validation.
|
|
98
|
+
*
|
|
99
|
+
* @param schemaValidator - The schema validator instance (e.g., ZodSchemaValidator)
|
|
100
|
+
* @param eventSchemas - Schema definitions for all WebSocket events
|
|
101
|
+
* @param websocketParams - Standard WebSocket constructor parameters (address, protocols, options)
|
|
102
|
+
*
|
|
103
|
+
* @example
|
|
104
|
+
* ```typescript
|
|
105
|
+
* const ws = new ForklaunchWebSocket(
|
|
106
|
+
* validator,
|
|
107
|
+
* schemas,
|
|
108
|
+
* 'ws://localhost:8080',
|
|
109
|
+
* ['chat-protocol'],
|
|
110
|
+
* { handshakeTimeout: 5000 }
|
|
111
|
+
* );
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
constructor(schemaValidator: SV, eventSchemas: ES, ...websocketParams: ConstructorParameters<typeof WebSocket>);
|
|
115
|
+
/**
|
|
116
|
+
* Decodes and validates incoming data from the WebSocket.
|
|
117
|
+
*
|
|
118
|
+
* This method handles multiple data formats:
|
|
119
|
+
* - Buffer → decoded to UTF-8 string → parsed as JSON → validated
|
|
120
|
+
* - ArrayBuffer → converted to Buffer → decoded → parsed → validated
|
|
121
|
+
* - TypedArray → converted to Buffer → decoded → parsed → validated
|
|
122
|
+
* - String → parsed as JSON → validated
|
|
123
|
+
* - Object → validated directly (already parsed)
|
|
124
|
+
*
|
|
125
|
+
* @param data - The raw data received from the WebSocket
|
|
126
|
+
* @param schema - Optional schema to validate against
|
|
127
|
+
* @returns The validated and decoded data
|
|
128
|
+
* @throws {Error} If validation fails with pretty-printed error messages
|
|
129
|
+
*
|
|
130
|
+
* @internal
|
|
131
|
+
*/
|
|
132
|
+
protected decodeAndValidate(data: unknown, schema: IdiomaticSchema<SV> | undefined): unknown;
|
|
133
|
+
/**
|
|
134
|
+
* Validates and encodes outgoing data for transmission over the WebSocket.
|
|
135
|
+
*
|
|
136
|
+
* This method:
|
|
137
|
+
* 1. Validates data against the provided schema (if present)
|
|
138
|
+
* 2. Encodes data to Buffer format:
|
|
139
|
+
* - Buffer → returned as-is
|
|
140
|
+
* - Object/Array → JSON.stringify → Buffer
|
|
141
|
+
* - String → Buffer
|
|
142
|
+
* - Number/Boolean → JSON.stringify → Buffer
|
|
143
|
+
* - null/undefined → returned as-is
|
|
144
|
+
*
|
|
145
|
+
* @param data - The data to validate and encode
|
|
146
|
+
* @param schema - Optional schema to validate against
|
|
147
|
+
* @returns The validated and encoded data as Buffer, or null/undefined
|
|
148
|
+
* @throws {Error} If validation fails with pretty-printed error messages
|
|
149
|
+
*
|
|
150
|
+
* @internal
|
|
151
|
+
*/
|
|
152
|
+
protected validateAndEncode(data: unknown, schema: IdiomaticSchema<SV> | undefined, allowUndefined?: boolean, context?: string): Buffer<ArrayBufferLike> | undefined;
|
|
153
|
+
/**
|
|
154
|
+
* Transforms incoming event arguments by decoding and validating them.
|
|
155
|
+
*
|
|
156
|
+
* Applies transformation for:
|
|
157
|
+
* - `message` events: validates message data
|
|
158
|
+
* - `close` events: validates close reason
|
|
159
|
+
* - `ping` events: validates ping data
|
|
160
|
+
* - `pong` events: validates pong data
|
|
161
|
+
*
|
|
162
|
+
* @param event - The event name
|
|
163
|
+
* @param args - The raw event arguments
|
|
164
|
+
* @returns Transformed and validated arguments
|
|
165
|
+
*
|
|
166
|
+
* @internal
|
|
167
|
+
*/
|
|
168
|
+
protected transformIncomingArgs(event: string | symbol, args: unknown[]): unknown[];
|
|
169
|
+
/**
|
|
170
|
+
* Wraps an event listener with data transformation logic.
|
|
171
|
+
*
|
|
172
|
+
* This helper intercepts listener registration to inject automatic
|
|
173
|
+
* decoding and validation of incoming event data before passing it
|
|
174
|
+
* to the user's listener function.
|
|
175
|
+
*
|
|
176
|
+
* @param superMethod - The parent class method to call (super.on, super.once, etc.)
|
|
177
|
+
* @param event - The event name
|
|
178
|
+
* @param listener - The user's listener function
|
|
179
|
+
* @returns `this` for method chaining
|
|
180
|
+
*
|
|
181
|
+
* @internal
|
|
182
|
+
*/
|
|
183
|
+
protected wrapListenerWithTransformation<Event extends string | symbol>(superMethod: (event: Event, listener: (ws: WebSocket, ...args: never[]) => void) => this, event: Event, listener: (ws: WebSocket, ...args: unknown[]) => void): this;
|
|
184
|
+
/**
|
|
185
|
+
* Registers an event listener with automatic data validation and transformation.
|
|
186
|
+
*
|
|
187
|
+
* All incoming data is automatically:
|
|
188
|
+
* - Decoded from Buffer to JavaScript objects
|
|
189
|
+
* - Parsed from JSON
|
|
190
|
+
* - Validated against the provided schemas
|
|
191
|
+
*
|
|
192
|
+
* @param event - The event name to listen for
|
|
193
|
+
* @param listener - The callback function to invoke when the event occurs
|
|
194
|
+
* @returns `this` for method chaining
|
|
195
|
+
*
|
|
196
|
+
* @example Listen for validated messages
|
|
197
|
+
* ```typescript
|
|
198
|
+
* ws.on('message', (data, isBinary) => {
|
|
199
|
+
* // data is automatically validated and typed according to serverMessages schema
|
|
200
|
+
* console.log('Received:', data);
|
|
201
|
+
* });
|
|
202
|
+
* ```
|
|
203
|
+
*
|
|
204
|
+
* @example Listen for connection events
|
|
205
|
+
* ```typescript
|
|
206
|
+
* ws.on('open', () => {
|
|
207
|
+
* console.log('Connected!');
|
|
208
|
+
* });
|
|
209
|
+
*
|
|
210
|
+
* ws.on('close', (code, reason) => {
|
|
211
|
+
* console.log('Disconnected:', code, reason);
|
|
212
|
+
* });
|
|
213
|
+
*
|
|
214
|
+
* ws.on('error', (error) => {
|
|
215
|
+
* console.error('WebSocket error:', error);
|
|
216
|
+
* });
|
|
217
|
+
* ```
|
|
218
|
+
*/
|
|
219
|
+
on(event: 'close', listener: (this: WebSocket, code: number, reason: Schema<ExtractSchemaFromRecord<SV, ES['closeReason']>, SV>) => void): this;
|
|
220
|
+
on(event: 'error', listener: (this: WebSocket, error: Error) => void): this;
|
|
221
|
+
on(event: 'upgrade', listener: (this: WebSocket, request: IncomingMessage) => void): this;
|
|
222
|
+
on(event: 'message', listener: (this: WebSocket, data: Schema<ExtractSchemaFromRecord<SV, ES['serverMessages']>, SV>, isBinary: boolean) => void): this;
|
|
223
|
+
on(event: 'open', listener: (this: WebSocket) => void): this;
|
|
224
|
+
on(event: 'ping', listener: (this: WebSocket, data: Schema<ExtractSchemaFromEntry<SV, ES['ping']>, SV>) => void): this;
|
|
225
|
+
on(event: 'pong', listener: (this: WebSocket, data: Schema<ExtractSchemaFromEntry<SV, ES['pong']>, SV>) => void): this;
|
|
226
|
+
on(event: 'redirect', listener: (this: WebSocket, url: string, request: ClientRequest) => void): this;
|
|
227
|
+
on(event: 'unexpected-response', listener: (this: WebSocket, request: ClientRequest, response: IncomingMessage) => void): this;
|
|
228
|
+
on(event: string | symbol, listener: (this: WebSocket, ...args: never[]) => void): this;
|
|
229
|
+
/**
|
|
230
|
+
* Registers a one-time event listener with automatic data validation and transformation.
|
|
231
|
+
*
|
|
232
|
+
* The listener will be invoked at most once after being registered, and then removed.
|
|
233
|
+
* All incoming data is automatically decoded, parsed, and validated.
|
|
234
|
+
*
|
|
235
|
+
* @param event - The event name to listen for
|
|
236
|
+
* @param listener - The callback function to invoke when the event occurs
|
|
237
|
+
* @returns `this` for method chaining
|
|
238
|
+
*
|
|
239
|
+
* @example
|
|
240
|
+
* ```typescript
|
|
241
|
+
* // Listen for the first message only
|
|
242
|
+
* ws.once('message', (data, isBinary) => {
|
|
243
|
+
* console.log('First message:', data);
|
|
244
|
+
* });
|
|
245
|
+
*
|
|
246
|
+
* // Wait for connection
|
|
247
|
+
* ws.once('open', () => {
|
|
248
|
+
* console.log('Connected! This will only fire once.');
|
|
249
|
+
* });
|
|
250
|
+
* ```
|
|
251
|
+
*/
|
|
252
|
+
once(event: 'close', listener: (this: WebSocket, code: number, reason: Schema<ExtractSchemaFromRecord<SV, ES['closeReason']>, SV>) => void): this;
|
|
253
|
+
once(event: 'error', listener: (this: WebSocket, error: Error) => void): this;
|
|
254
|
+
once(event: 'upgrade', listener: (this: WebSocket, request: IncomingMessage) => void): this;
|
|
255
|
+
once(event: 'message', listener: (this: WebSocket, data: Schema<ExtractSchemaFromRecord<SV, ES['serverMessages']>, SV>, isBinary: boolean) => void): this;
|
|
256
|
+
once(event: 'open', listener: (this: WebSocket) => void): this;
|
|
257
|
+
once(event: 'ping', listener: (this: WebSocket, data: Schema<ExtractSchemaFromEntry<SV, ES['ping']>, SV>) => void): this;
|
|
258
|
+
once(event: 'pong', listener: (this: WebSocket, data: Schema<ExtractSchemaFromEntry<SV, ES['pong']>, SV>) => void): this;
|
|
259
|
+
once(event: 'redirect', listener: (this: WebSocket, url: string, request: ClientRequest) => void): this;
|
|
260
|
+
once(event: 'unexpected-response', listener: (this: WebSocket, request: ClientRequest, response: IncomingMessage) => void): this;
|
|
261
|
+
once(event: string | symbol, listener: (this: WebSocket, ...args: never[]) => void): this;
|
|
262
|
+
/**
|
|
263
|
+
* Removes a previously registered event listener.
|
|
264
|
+
*
|
|
265
|
+
* To successfully remove a listener, you must pass the exact same function
|
|
266
|
+
* reference that was used when registering it.
|
|
267
|
+
*
|
|
268
|
+
* @param event - The event name
|
|
269
|
+
* @param listener - The exact function reference to remove
|
|
270
|
+
* @returns `this` for method chaining
|
|
271
|
+
*
|
|
272
|
+
* @example
|
|
273
|
+
* ```typescript
|
|
274
|
+
* const messageHandler = (data, isBinary) => {
|
|
275
|
+
* console.log('Message:', data);
|
|
276
|
+
* };
|
|
277
|
+
*
|
|
278
|
+
* // Register
|
|
279
|
+
* ws.on('message', messageHandler);
|
|
280
|
+
*
|
|
281
|
+
* // Later, remove
|
|
282
|
+
* ws.off('message', messageHandler);
|
|
283
|
+
* ```
|
|
284
|
+
*/
|
|
285
|
+
off(event: 'close', listener: (this: WebSocket, code: number, reason: Schema<ExtractSchemaFromRecord<SV, ES['closeReason']>, SV>) => void): this;
|
|
286
|
+
off(event: 'error', listener: (this: WebSocket, error: Error) => void): this;
|
|
287
|
+
off(event: 'upgrade', listener: (this: WebSocket, request: IncomingMessage) => void): this;
|
|
288
|
+
off(event: 'message', listener: (this: WebSocket, data: Schema<ExtractSchemaFromRecord<SV, ES['serverMessages']>, SV>, isBinary: boolean) => void): this;
|
|
289
|
+
off(event: 'open', listener: (this: WebSocket) => void): this;
|
|
290
|
+
off(event: 'ping', listener: (this: WebSocket, data: Schema<ExtractSchemaFromEntry<SV, ES['ping']>, SV>) => void): this;
|
|
291
|
+
off(event: 'pong', listener: (this: WebSocket, data: Schema<ExtractSchemaFromEntry<SV, ES['pong']>, SV>) => void): this;
|
|
292
|
+
off(event: 'redirect', listener: (this: WebSocket, url: string, request: ClientRequest) => void): this;
|
|
293
|
+
off(event: 'unexpected-response', listener: (this: WebSocket, request: ClientRequest, response: IncomingMessage) => void): this;
|
|
294
|
+
off(event: string | symbol, listener: (this: WebSocket, ...args: never[]) => void): this;
|
|
295
|
+
/**
|
|
296
|
+
* Registers an event listener (alias for `on()`).
|
|
297
|
+
*
|
|
298
|
+
* This method is functionally identical to `on()` and is provided for
|
|
299
|
+
* compatibility with the EventEmitter API.
|
|
300
|
+
*
|
|
301
|
+
* @param event - The event name to listen for
|
|
302
|
+
* @param listener - The callback function to invoke when the event occurs
|
|
303
|
+
* @returns `this` for method chaining
|
|
304
|
+
*
|
|
305
|
+
* @see {@link on} for detailed documentation and examples
|
|
306
|
+
*/
|
|
307
|
+
addListener(event: 'close', listener: (this: WebSocket, code: number, reason: Schema<ExtractSchemaFromRecord<SV, ES['closeReason']>, SV>) => void): this;
|
|
308
|
+
addListener(event: 'error', listener: (this: WebSocket, error: Error) => void): this;
|
|
309
|
+
addListener(event: 'upgrade', listener: (this: WebSocket, request: IncomingMessage) => void): this;
|
|
310
|
+
addListener(event: 'message', listener: (this: WebSocket, data: Schema<ExtractSchemaFromRecord<SV, ES['serverMessages']>, SV>, isBinary: boolean) => void): this;
|
|
311
|
+
addListener(event: 'open', listener: (this: WebSocket) => void): this;
|
|
312
|
+
addListener(event: 'ping', listener: (this: WebSocket, data: Schema<ExtractSchemaFromEntry<SV, ES['ping']>, SV>) => void): this;
|
|
313
|
+
addListener(event: 'pong', listener: (this: WebSocket, data: Schema<ExtractSchemaFromEntry<SV, ES['pong']>, SV>) => void): this;
|
|
314
|
+
addListener(event: 'redirect', listener: (this: WebSocket, url: string, request: ClientRequest) => void): this;
|
|
315
|
+
addListener(event: 'unexpected-response', listener: (this: WebSocket, request: ClientRequest, response: IncomingMessage) => void): this;
|
|
316
|
+
addListener(event: string | symbol, listener: (this: WebSocket, ...args: never[]) => void): this;
|
|
317
|
+
/**
|
|
318
|
+
* Removes a previously registered event listener (alias for `off()`).
|
|
319
|
+
*
|
|
320
|
+
* This method is functionally identical to `off()` and is provided for
|
|
321
|
+
* compatibility with the EventEmitter API.
|
|
322
|
+
*
|
|
323
|
+
* @param event - The event name
|
|
324
|
+
* @param listener - The exact function reference to remove
|
|
325
|
+
* @returns `this` for method chaining
|
|
326
|
+
*
|
|
327
|
+
* @see {@link off} for detailed documentation and examples
|
|
328
|
+
*/
|
|
329
|
+
removeListener(event: 'close', listener: (this: WebSocket, code: number, reason: Schema<ExtractSchemaFromRecord<SV, ES['closeReason']>, SV>) => void): this;
|
|
330
|
+
removeListener(event: 'error', listener: (this: WebSocket, error: Error) => void): this;
|
|
331
|
+
removeListener(event: 'upgrade', listener: (this: WebSocket, request: IncomingMessage) => void): this;
|
|
332
|
+
removeListener(event: 'message', listener: (this: WebSocket, data: Schema<ExtractSchemaFromRecord<SV, ES['serverMessages']>, SV>, isBinary: boolean) => void): this;
|
|
333
|
+
removeListener(event: 'open', listener: (this: WebSocket) => void): this;
|
|
334
|
+
removeListener(event: 'ping', listener: (this: WebSocket, data: Schema<ExtractSchemaFromEntry<SV, ES['ping']>, SV>) => void): this;
|
|
335
|
+
removeListener(event: 'pong', listener: (this: WebSocket, data: Schema<ExtractSchemaFromEntry<SV, ES['pong']>, SV>) => void): this;
|
|
336
|
+
removeListener(event: 'redirect', listener: (this: WebSocket, url: string, request: ClientRequest) => void): this;
|
|
337
|
+
removeListener(event: 'unexpected-response', listener: (this: WebSocket, request: ClientRequest, response: IncomingMessage) => void): this;
|
|
338
|
+
removeListener(event: string | symbol, listener: (this: WebSocket, ...args: never[]) => void): this;
|
|
339
|
+
/**
|
|
340
|
+
* Emits an event with automatic data validation and encoding.
|
|
341
|
+
*
|
|
342
|
+
* All outgoing data is automatically:
|
|
343
|
+
* - Validated against the provided schemas
|
|
344
|
+
* - Encoded from JavaScript objects to Buffer format
|
|
345
|
+
* - Transmitted over the WebSocket connection
|
|
346
|
+
*
|
|
347
|
+
* @param event - The event name to emit
|
|
348
|
+
* @param args - The event arguments (type-checked based on event name)
|
|
349
|
+
* @returns `true` if the event had listeners, `false` otherwise
|
|
350
|
+
*
|
|
351
|
+
* @example Emit a message
|
|
352
|
+
* ```typescript
|
|
353
|
+
* // Data is validated against clientMessages schema and auto-encoded
|
|
354
|
+
* ws.emit('message', { type: 'chat', text: 'Hello!' }, true);
|
|
355
|
+
* ```
|
|
356
|
+
*
|
|
357
|
+
* @example Emit other events
|
|
358
|
+
* ```typescript
|
|
359
|
+
* ws.emit('ping', { timestamp: Date.now() });
|
|
360
|
+
* ws.emit('close', 1000, { reason: 'Normal closure' });
|
|
361
|
+
* ws.emit('error', { code: 500, message: 'Server error' });
|
|
362
|
+
* ```
|
|
363
|
+
*/
|
|
364
|
+
emit<K extends keyof OutgoingEventMap<SV, ES>>(event: K, ...args: OutgoingEventMap<SV, ES>[K]): boolean;
|
|
365
|
+
/**
|
|
366
|
+
* Sends data over the WebSocket with automatic validation and encoding.
|
|
367
|
+
*
|
|
368
|
+
* The data is:
|
|
369
|
+
* 1. Validated against the `clientMessages` schema
|
|
370
|
+
* 2. Automatically encoded to Buffer format (JSON.stringify)
|
|
371
|
+
* 3. Transmitted to the server
|
|
372
|
+
*
|
|
373
|
+
* @param data - The message data to send (must match clientMessages schema)
|
|
374
|
+
* @param options - Optional send options (mask, binary, compress, fin)
|
|
375
|
+
* @param cb - Optional callback invoked when send completes or errors
|
|
376
|
+
* @throws {Error} If validation fails or data cannot be encoded
|
|
377
|
+
*
|
|
378
|
+
* @example Send a message
|
|
379
|
+
* ```typescript
|
|
380
|
+
* // Data is type-checked and validated at runtime
|
|
381
|
+
* ws.send({ type: 'chat', message: 'Hello, world!', userId: '123' });
|
|
382
|
+
* ```
|
|
383
|
+
*
|
|
384
|
+
* @example Send with options and callback
|
|
385
|
+
* ```typescript
|
|
386
|
+
* ws.send(
|
|
387
|
+
* { type: 'ping', timestamp: Date.now() },
|
|
388
|
+
* { compress: true, binary: true },
|
|
389
|
+
* (error) => {
|
|
390
|
+
* if (error) console.error('Send failed:', error);
|
|
391
|
+
* else console.log('Send succeeded');
|
|
392
|
+
* }
|
|
393
|
+
* );
|
|
394
|
+
* ```
|
|
395
|
+
*
|
|
396
|
+
* @remarks
|
|
397
|
+
* This method intentionally restricts the parameter type from `BufferLike` to
|
|
398
|
+
* schema-validated types to provide compile-time type safety. This is a deliberate
|
|
399
|
+
* design choice to catch type errors at compile time rather than runtime.
|
|
400
|
+
*/
|
|
401
|
+
send(data: Schema<ExtractSchemaFromRecord<SV, ES['clientMessages']>, SV>, cb?: (err?: Error) => void): void;
|
|
402
|
+
send(data: Schema<ExtractSchemaFromRecord<SV, ES['clientMessages']>, SV>, options: {
|
|
403
|
+
mask?: boolean;
|
|
404
|
+
binary?: boolean;
|
|
405
|
+
compress?: boolean;
|
|
406
|
+
fin?: boolean;
|
|
407
|
+
}, cb?: (err?: Error) => void): void;
|
|
408
|
+
/**
|
|
409
|
+
* Closes the WebSocket connection with optional validated close reason.
|
|
410
|
+
*
|
|
411
|
+
* @param code - Optional close code (default: 1000 for normal closure)
|
|
412
|
+
* @param reason - Optional close reason (validated against closeReason schema)
|
|
413
|
+
*
|
|
414
|
+
* @example Close with default code
|
|
415
|
+
* ```typescript
|
|
416
|
+
* ws.close();
|
|
417
|
+
* ```
|
|
418
|
+
*
|
|
419
|
+
* @example Close with code and reason
|
|
420
|
+
* ```typescript
|
|
421
|
+
* ws.close(1000, { reason: 'User logged out' });
|
|
422
|
+
* ```
|
|
423
|
+
*
|
|
424
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent/code|WebSocket Close Codes}
|
|
425
|
+
*/
|
|
426
|
+
close(code?: number, reason?: Schema<ExtractSchemaFromRecord<SV, ES['closeReason']>, SV>): void;
|
|
427
|
+
/**
|
|
428
|
+
* Sends a ping frame with optional validated data payload.
|
|
429
|
+
*
|
|
430
|
+
* Ping frames are used to check if the connection is alive. The server
|
|
431
|
+
* should respond with a pong frame.
|
|
432
|
+
*
|
|
433
|
+
* @param data - Optional ping data (validated against ping schema)
|
|
434
|
+
* @param mask - Whether to mask the frame (default: true for clients)
|
|
435
|
+
* @param cb - Optional callback invoked when ping is sent or errors
|
|
436
|
+
*
|
|
437
|
+
* @example Send a ping
|
|
438
|
+
* ```typescript
|
|
439
|
+
* ws.ping({ timestamp: Date.now() });
|
|
440
|
+
* ```
|
|
441
|
+
*
|
|
442
|
+
* @example Send ping with callback
|
|
443
|
+
* ```typescript
|
|
444
|
+
* ws.ping({ ts: Date.now() }, true, (error) => {
|
|
445
|
+
* if (error) console.error('Ping failed:', error);
|
|
446
|
+
* });
|
|
447
|
+
* ```
|
|
448
|
+
*/
|
|
449
|
+
ping(data?: Schema<ExtractSchemaFromEntry<SV, ES['ping']>, SV>, mask?: boolean, cb?: (err: Error) => void): void;
|
|
450
|
+
/**
|
|
451
|
+
* Sends a pong frame with optional validated data payload.
|
|
452
|
+
*
|
|
453
|
+
* Pong frames are typically sent in response to ping frames, but can
|
|
454
|
+
* also be sent unsolicited as a unidirectional heartbeat.
|
|
455
|
+
*
|
|
456
|
+
* @param data - Optional pong data (validated against pong schema)
|
|
457
|
+
* @param mask - Whether to mask the frame (default: true for clients)
|
|
458
|
+
* @param cb - Optional callback invoked when pong is sent or errors
|
|
459
|
+
*
|
|
460
|
+
* @example Send a pong
|
|
461
|
+
* ```typescript
|
|
462
|
+
* ws.pong({ timestamp: Date.now() });
|
|
463
|
+
* ```
|
|
464
|
+
*
|
|
465
|
+
* @example Respond to ping
|
|
466
|
+
* ```typescript
|
|
467
|
+
* ws.on('ping', (data) => {
|
|
468
|
+
* console.log('Received ping:', data);
|
|
469
|
+
* ws.pong(data); // Echo the ping data back
|
|
470
|
+
* });
|
|
471
|
+
* ```
|
|
472
|
+
*/
|
|
473
|
+
pong(data?: Schema<ExtractSchemaFromEntry<SV, ES['pong']>, SV>, mask?: boolean, cb?: (err: Error) => void): void;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* Extended WebSocketServer that automatically injects schema validation into all connected clients.
|
|
478
|
+
*
|
|
479
|
+
* When clients connect, they receive a {@link ForklaunchWebSocket} instance with automatic:
|
|
480
|
+
* - Message validation against provided schemas
|
|
481
|
+
* - Buffer ↔ Object transformation
|
|
482
|
+
* - Type-safe event handlers
|
|
483
|
+
*
|
|
484
|
+
* Note: The server-side WebSocket swaps `clientMessages` and `serverMessages` schemas,
|
|
485
|
+
* so what the client sends as `clientMessages` arrives at the server as `serverMessages`.
|
|
486
|
+
*
|
|
487
|
+
* @template SV - The schema validator type (e.g., ZodSchemaValidator)
|
|
488
|
+
* @template ES - The event schema defining message types for each event
|
|
489
|
+
*
|
|
490
|
+
* @example Basic Chat Server
|
|
491
|
+
* ```typescript
|
|
492
|
+
* import { ZodSchemaValidator } from '@forklaunch/validator';
|
|
493
|
+
* import { z } from 'zod';
|
|
494
|
+
* import { ForklaunchWebSocketServer } from '@forklaunch/ws';
|
|
495
|
+
*
|
|
496
|
+
* const validator = new ZodSchemaValidator();
|
|
497
|
+
* const schemas = {
|
|
498
|
+
* ping: z.object({ ts: z.number() }),
|
|
499
|
+
* pong: z.object({ ts: z.number() }),
|
|
500
|
+
* clientMessages: z.discriminatedUnion('type', [
|
|
501
|
+
* z.object({ type: z.literal('chat'), message: z.string(), userId: z.string() }),
|
|
502
|
+
* z.object({ type: z.literal('join'), roomId: z.string() })
|
|
503
|
+
* ]),
|
|
504
|
+
* serverMessages: z.discriminatedUnion('type', [
|
|
505
|
+
* z.object({ type: z.literal('chat'), message: z.string(), userId: z.string() }),
|
|
506
|
+
* z.object({ type: z.literal('user-joined'), userId: z.string() })
|
|
507
|
+
* ])
|
|
508
|
+
* };
|
|
509
|
+
*
|
|
510
|
+
* const wss = new ForklaunchWebSocketServer(validator, schemas, { port: 8080 });
|
|
511
|
+
*
|
|
512
|
+
* wss.on('connection', (ws, request) => {
|
|
513
|
+
* console.log('Client connected:', request.socket.remoteAddress);
|
|
514
|
+
*
|
|
515
|
+
* // Send welcome message (validated and encoded automatically)
|
|
516
|
+
* ws.send({ type: 'chat', message: 'Welcome!', userId: 'server' });
|
|
517
|
+
*
|
|
518
|
+
* // Listen for incoming messages (validated and decoded automatically)
|
|
519
|
+
* ws.on('message', (data, isBinary) => {
|
|
520
|
+
* console.log('Received:', data); // data is typed and validated
|
|
521
|
+
*
|
|
522
|
+
* // Broadcast to other clients
|
|
523
|
+
* wss.clients.forEach((client) => {
|
|
524
|
+
* if (client !== ws && client.readyState === WebSocket.OPEN) {
|
|
525
|
+
* client.send(data);
|
|
526
|
+
* }
|
|
527
|
+
* });
|
|
528
|
+
* });
|
|
529
|
+
*
|
|
530
|
+
* ws.on('close', (code, reason) => {
|
|
531
|
+
* console.log('Client disconnected:', code, reason);
|
|
532
|
+
* });
|
|
533
|
+
* });
|
|
534
|
+
* ```
|
|
535
|
+
*
|
|
536
|
+
* @example With Authentication
|
|
537
|
+
* ```typescript
|
|
538
|
+
* wss.on('connection', (ws, request) => {
|
|
539
|
+
* const token = new URL(request.url!, 'ws://localhost').searchParams.get('token');
|
|
540
|
+
*
|
|
541
|
+
* if (!token || !isValidToken(token)) {
|
|
542
|
+
* ws.close(1008, { reason: 'Unauthorized' });
|
|
543
|
+
* return;
|
|
544
|
+
* }
|
|
545
|
+
*
|
|
546
|
+
* // Proceed with authenticated connection
|
|
547
|
+
* ws.on('message', (data) => {
|
|
548
|
+
* // Handle authenticated messages
|
|
549
|
+
* });
|
|
550
|
+
* });
|
|
551
|
+
* ```
|
|
552
|
+
*
|
|
553
|
+
* @see {@link ForklaunchWebSocket} for client-side usage
|
|
554
|
+
* @see {@link EventSchema} for schema structure
|
|
555
|
+
*/
|
|
556
|
+
declare class ForklaunchWebSocketServer<SV extends AnySchemaValidator, const ES extends EventSchema<SV>> extends WebSocketServer {
|
|
557
|
+
/**
|
|
558
|
+
* Creates a new ForklaunchWebSocketServer with schema validation.
|
|
559
|
+
*
|
|
560
|
+
* @param _schemaValidator - The schema validator instance (e.g., ZodSchemaValidator)
|
|
561
|
+
* @param _eventSchemas - Schema definitions for all WebSocket events
|
|
562
|
+
* @param options - Standard WebSocketServer options (port, host, server, etc.)
|
|
563
|
+
* @param callback - Optional callback invoked when the server starts listening
|
|
564
|
+
*
|
|
565
|
+
* @example Create a server on port 8080
|
|
566
|
+
* ```typescript
|
|
567
|
+
* const wss = new ForklaunchWebSocketServer(
|
|
568
|
+
* validator,
|
|
569
|
+
* schemas,
|
|
570
|
+
* { port: 8080 },
|
|
571
|
+
* () => console.log('Server started on port 8080')
|
|
572
|
+
* );
|
|
573
|
+
* ```
|
|
574
|
+
*
|
|
575
|
+
* @example Create a server with existing HTTP server
|
|
576
|
+
* ```typescript
|
|
577
|
+
* import { createServer } from 'http';
|
|
578
|
+
*
|
|
579
|
+
* const httpServer = createServer();
|
|
580
|
+
* const wss = new ForklaunchWebSocketServer(
|
|
581
|
+
* validator,
|
|
582
|
+
* schemas,
|
|
583
|
+
* { server: httpServer }
|
|
584
|
+
* );
|
|
585
|
+
*
|
|
586
|
+
* httpServer.listen(8080);
|
|
587
|
+
* ```
|
|
588
|
+
*
|
|
589
|
+
* @example No server mode (for upgrade handling)
|
|
590
|
+
* ```typescript
|
|
591
|
+
* const wss = new ForklaunchWebSocketServer(
|
|
592
|
+
* validator,
|
|
593
|
+
* schemas,
|
|
594
|
+
* { noServer: true }
|
|
595
|
+
* );
|
|
596
|
+
*
|
|
597
|
+
* httpServer.on('upgrade', (request, socket, head) => {
|
|
598
|
+
* wss.handleUpgrade(request, socket, head, (ws) => {
|
|
599
|
+
* wss.emit('connection', ws, request);
|
|
600
|
+
* });
|
|
601
|
+
* });
|
|
602
|
+
* ```
|
|
603
|
+
*/
|
|
604
|
+
constructor(_schemaValidator: SV, _eventSchemas: ES, options?: ConstructorParameters<typeof WebSocketServer>[0], callback?: () => void);
|
|
605
|
+
/**
|
|
606
|
+
* Registers an event listener for server events.
|
|
607
|
+
*
|
|
608
|
+
* The `connection` event provides a {@link ForklaunchWebSocket} instance (not a plain WebSocket),
|
|
609
|
+
* which includes automatic validation and transformation for all messages.
|
|
610
|
+
*
|
|
611
|
+
* @param event - The server event name to listen for
|
|
612
|
+
* @param listener - The callback function to invoke when the event occurs
|
|
613
|
+
* @returns `this` for method chaining
|
|
614
|
+
*
|
|
615
|
+
* @example Handle new connections
|
|
616
|
+
* ```typescript
|
|
617
|
+
* wss.on('connection', (ws, request) => {
|
|
618
|
+
* console.log('Client connected from:', request.socket.remoteAddress);
|
|
619
|
+
*
|
|
620
|
+
* ws.on('message', (data, isBinary) => {
|
|
621
|
+
* console.log('Received:', data); // Auto-validated and typed
|
|
622
|
+
* });
|
|
623
|
+
* });
|
|
624
|
+
* ```
|
|
625
|
+
*
|
|
626
|
+
* @example Handle server errors
|
|
627
|
+
* ```typescript
|
|
628
|
+
* wss.on('error', (error) => {
|
|
629
|
+
* console.error('Server error:', error);
|
|
630
|
+
* });
|
|
631
|
+
* ```
|
|
632
|
+
*
|
|
633
|
+
* @example Listen for server lifecycle events
|
|
634
|
+
* ```typescript
|
|
635
|
+
* wss.on('listening', () => {
|
|
636
|
+
* console.log('Server is listening');
|
|
637
|
+
* });
|
|
638
|
+
*
|
|
639
|
+
* wss.on('close', () => {
|
|
640
|
+
* console.log('Server closed');
|
|
641
|
+
* });
|
|
642
|
+
* ```
|
|
643
|
+
*
|
|
644
|
+
* @remarks
|
|
645
|
+
* Note: TypeScript shows `ws` as `WebSocket` in the type signature due to override
|
|
646
|
+
* limitations, but at runtime it's actually a `ForklaunchWebSocket` with full validation.
|
|
647
|
+
*/
|
|
648
|
+
on(event: 'connection', listener: (ws: ForklaunchWebSocket<SV, ServerEventSchema<SV, ES>>, request: IncomingMessage) => void): this;
|
|
649
|
+
on(event: 'error', listener: (error: Error) => void): this;
|
|
650
|
+
on(event: 'headers', listener: (headers: string[], request: IncomingMessage) => void): this;
|
|
651
|
+
on(event: 'close', listener: () => void): this;
|
|
652
|
+
on(event: 'listening', listener: () => void): this;
|
|
653
|
+
on(event: string | symbol, listener: (...args: never[]) => void): this;
|
|
654
|
+
/**
|
|
655
|
+
* Registers a one-time event listener for server events.
|
|
656
|
+
*
|
|
657
|
+
* The listener will be invoked at most once after being registered, and then removed.
|
|
658
|
+
*
|
|
659
|
+
* @param event - The server event name to listen for
|
|
660
|
+
* @param listener - The callback function to invoke when the event occurs
|
|
661
|
+
* @returns `this` for method chaining
|
|
662
|
+
*
|
|
663
|
+
* @example Wait for first connection
|
|
664
|
+
* ```typescript
|
|
665
|
+
* wss.once('connection', (ws, request) => {
|
|
666
|
+
* console.log('First client connected!');
|
|
667
|
+
* // This will only fire for the first connection
|
|
668
|
+
* });
|
|
669
|
+
* ```
|
|
670
|
+
*
|
|
671
|
+
* @example Wait for server to start
|
|
672
|
+
* ```typescript
|
|
673
|
+
* wss.once('listening', () => {
|
|
674
|
+
* console.log('Server is now ready to accept connections');
|
|
675
|
+
* });
|
|
676
|
+
* ```
|
|
677
|
+
*/
|
|
678
|
+
once(event: 'connection', listener: (ws: ForklaunchWebSocket<SV, ServerEventSchema<SV, ES>>, request: IncomingMessage) => void): this;
|
|
679
|
+
once(event: 'error', listener: (error: Error) => void): this;
|
|
680
|
+
once(event: 'headers', listener: (headers: string[], request: IncomingMessage) => void): this;
|
|
681
|
+
once(event: 'close', listener: () => void): this;
|
|
682
|
+
once(event: 'listening', listener: () => void): this;
|
|
683
|
+
once(event: string | symbol, listener: (...args: never[]) => void): this;
|
|
684
|
+
/**
|
|
685
|
+
* Removes a previously registered event listener.
|
|
686
|
+
*
|
|
687
|
+
* To successfully remove a listener, you must pass the exact same function
|
|
688
|
+
* reference that was used when registering it.
|
|
689
|
+
*
|
|
690
|
+
* @param event - The server event name
|
|
691
|
+
* @param listener - The exact function reference to remove
|
|
692
|
+
* @returns `this` for method chaining
|
|
693
|
+
*
|
|
694
|
+
* @example
|
|
695
|
+
* ```typescript
|
|
696
|
+
* const connectionHandler = (ws, request) => {
|
|
697
|
+
* console.log('Client connected');
|
|
698
|
+
* };
|
|
699
|
+
*
|
|
700
|
+
* // Register
|
|
701
|
+
* wss.on('connection', connectionHandler);
|
|
702
|
+
*
|
|
703
|
+
* // Later, remove
|
|
704
|
+
* wss.off('connection', connectionHandler);
|
|
705
|
+
* ```
|
|
706
|
+
*/
|
|
707
|
+
off(event: 'connection', listener: (ws: ForklaunchWebSocket<SV, ServerEventSchema<SV, ES>>, request: IncomingMessage) => void): this;
|
|
708
|
+
off(event: 'error', listener: (error: Error) => void): this;
|
|
709
|
+
off(event: 'headers', listener: (headers: string[], request: IncomingMessage) => void): this;
|
|
710
|
+
off(event: 'close', listener: () => void): this;
|
|
711
|
+
off(event: 'listening', listener: () => void): this;
|
|
712
|
+
off(event: string | symbol, listener: (...args: never[]) => void): this;
|
|
713
|
+
/**
|
|
714
|
+
* Registers an event listener (alias for `on()`).
|
|
715
|
+
*
|
|
716
|
+
* This method is functionally identical to `on()` and is provided for
|
|
717
|
+
* compatibility with the EventEmitter API.
|
|
718
|
+
*
|
|
719
|
+
* @param event - The server event name to listen for
|
|
720
|
+
* @param listener - The callback function to invoke when the event occurs
|
|
721
|
+
* @returns `this` for method chaining
|
|
722
|
+
*
|
|
723
|
+
* @see {@link on} for detailed documentation and examples
|
|
724
|
+
*/
|
|
725
|
+
addListener(event: 'connection', listener: (ws: ForklaunchWebSocket<SV, ServerEventSchema<SV, ES>>, request: IncomingMessage) => void): this;
|
|
726
|
+
addListener(event: 'error', listener: (error: Error) => void): this;
|
|
727
|
+
addListener(event: 'headers', listener: (headers: string[], request: IncomingMessage) => void): this;
|
|
728
|
+
addListener(event: 'close', listener: () => void): this;
|
|
729
|
+
addListener(event: 'listening', listener: () => void): this;
|
|
730
|
+
addListener(event: string | symbol, listener: (...args: never[]) => void): this;
|
|
731
|
+
/**
|
|
732
|
+
* Removes a previously registered event listener (alias for `off()`).
|
|
733
|
+
*
|
|
734
|
+
* This method is functionally identical to `off()` and is provided for
|
|
735
|
+
* compatibility with the EventEmitter API.
|
|
736
|
+
*
|
|
737
|
+
* @param event - The server event name
|
|
738
|
+
* @param listener - The exact function reference to remove
|
|
739
|
+
* @returns `this` for method chaining
|
|
740
|
+
*
|
|
741
|
+
* @see {@link off} for detailed documentation and examples
|
|
742
|
+
*/
|
|
743
|
+
removeListener(event: 'connection', listener: (ws: ForklaunchWebSocket<SV, ServerEventSchema<SV, ES>>, request: IncomingMessage) => void): this;
|
|
744
|
+
removeListener(event: 'error', listener: (error: Error) => void): this;
|
|
745
|
+
removeListener(event: 'headers', listener: (headers: string[], request: IncomingMessage) => void): this;
|
|
746
|
+
removeListener(event: 'close', listener: () => void): this;
|
|
747
|
+
removeListener(event: 'listening', listener: () => void): this;
|
|
748
|
+
removeListener(event: string | symbol, listener: (...args: never[]) => void): this;
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
/**
|
|
752
|
+
* @packageDocumentation
|
|
753
|
+
*
|
|
754
|
+
* # ForkLaunch WebSocket Library
|
|
755
|
+
*
|
|
756
|
+
* Type-safe WebSocket client and server with automatic schema validation and data transformation.
|
|
757
|
+
*
|
|
758
|
+
* ## Features
|
|
759
|
+
*
|
|
760
|
+
* - **Automatic Validation**: All messages validated against provided schemas
|
|
761
|
+
* - **Auto Transformation**: Buffer ↔ Object conversion handled automatically
|
|
762
|
+
* - **Type Safety**: Full TypeScript support with proper event typing
|
|
763
|
+
* - **Schema Agnostic**: Works with Zod, TypeBox, or any validator
|
|
764
|
+
* - **Drop-in Replacement**: Extends standard `ws` library
|
|
765
|
+
*
|
|
766
|
+
* ## Quick Start
|
|
767
|
+
*
|
|
768
|
+
* ```typescript
|
|
769
|
+
* import { ZodSchemaValidator } from '@forklaunch/validator';
|
|
770
|
+
* import { z } from 'zod';
|
|
771
|
+
* import { ForklaunchWebSocket, ForklaunchWebSocketServer } from '@forklaunch/ws';
|
|
772
|
+
*
|
|
773
|
+
* // Define schemas
|
|
774
|
+
* const validator = new ZodSchemaValidator();
|
|
775
|
+
* const schemas = {
|
|
776
|
+
* clientMessages: {
|
|
777
|
+
* chat: z.object({ type: z.literal('chat'), message: z.string() })
|
|
778
|
+
* },
|
|
779
|
+
* serverMessages: {
|
|
780
|
+
* response: z.object({ type: z.literal('response'), data: z.string() })
|
|
781
|
+
* }
|
|
782
|
+
* };
|
|
783
|
+
*
|
|
784
|
+
* // Server
|
|
785
|
+
* const wss = new ForklaunchWebSocketServer(validator, schemas, { port: 8080 });
|
|
786
|
+
* wss.on('connection', (ws) => {
|
|
787
|
+
* ws.on('message', (data) => {
|
|
788
|
+
* console.log('Validated message:', data);
|
|
789
|
+
* });
|
|
790
|
+
* });
|
|
791
|
+
*
|
|
792
|
+
* // Client
|
|
793
|
+
* const ws = new ForklaunchWebSocket(validator, schemas, 'ws://localhost:8080');
|
|
794
|
+
* ws.on('open', () => {
|
|
795
|
+
* ws.send({ type: 'chat', message: 'Hello!' });
|
|
796
|
+
* });
|
|
797
|
+
* ```
|
|
798
|
+
*
|
|
799
|
+
* @see {@link ForklaunchWebSocket} for client documentation
|
|
800
|
+
* @see {@link ForklaunchWebSocketServer} for server documentation
|
|
801
|
+
* @see {@link EventSchema} for schema structure
|
|
802
|
+
*/
|
|
803
|
+
|
|
804
|
+
declare const CLOSED: 3;
|
|
805
|
+
declare const CLOSING: 2;
|
|
806
|
+
declare const CONNECTING: 0;
|
|
807
|
+
declare const OPEN: 1;
|
|
808
|
+
|
|
809
|
+
export { CLOSED, CLOSING, CONNECTING, ForklaunchWebSocket, ForklaunchWebSocketServer, OPEN, ForklaunchWebSocket as default };
|