@roj-ai/transport 0.0.2
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/client-connection.d.ts +48 -0
- package/dist/client/client-connection.d.ts.map +1 -0
- package/dist/client/client-connection.js +160 -0
- package/dist/client/index.d.ts +10 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +7 -0
- package/dist/core/connection.d.ts +59 -0
- package/dist/core/connection.d.ts.map +1 -0
- package/dist/core/connection.js +165 -0
- package/dist/core/index.d.ts +16 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +13 -0
- package/dist/core/protocol.d.ts +206 -0
- package/dist/core/protocol.d.ts.map +1 -0
- package/dist/core/protocol.js +93 -0
- package/dist/core/result.d.ts +26 -0
- package/dist/core/result.d.ts.map +1 -0
- package/dist/core/result.js +20 -0
- package/dist/core/router.d.ts +79 -0
- package/dist/core/router.d.ts.map +1 -0
- package/dist/core/router.js +119 -0
- package/dist/core/types.d.ts +44 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +14 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26 -0
- package/dist/platform/browser.d.ts +14 -0
- package/dist/platform/browser.d.ts.map +1 -0
- package/dist/platform/browser.js +65 -0
- package/dist/platform/bun.d.ts +69 -0
- package/dist/platform/bun.d.ts.map +1 -0
- package/dist/platform/bun.js +152 -0
- package/dist/platform/types.d.ts +83 -0
- package/dist/platform/types.d.ts.map +1 -0
- package/dist/platform/types.js +14 -0
- package/dist/server/connection-manager.d.ts +106 -0
- package/dist/server/connection-manager.d.ts.map +1 -0
- package/dist/server/connection-manager.js +234 -0
- package/dist/server/index.d.ts +12 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +8 -0
- package/dist/server/server-connection.d.ts +50 -0
- package/dist/server/server-connection.d.ts.map +1 -0
- package/dist/server/server-connection.js +84 -0
- package/package.json +52 -0
- package/src/__tests__/integration.test.ts +443 -0
- package/src/client/client-connection.ts +207 -0
- package/src/client/index.ts +24 -0
- package/src/core/connection.ts +203 -0
- package/src/core/index.ts +52 -0
- package/src/core/protocol.test.ts +235 -0
- package/src/core/protocol.ts +348 -0
- package/src/core/result.ts +35 -0
- package/src/core/router.test.ts +248 -0
- package/src/core/router.ts +186 -0
- package/src/core/types.ts +85 -0
- package/src/index.ts +80 -0
- package/src/platform/browser.ts +79 -0
- package/src/platform/bun.ts +220 -0
- package/src/platform/types.ts +102 -0
- package/src/server/connection-manager.ts +298 -0
- package/src/server/index.ts +26 -0
- package/src/server/server-connection.ts +122 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @roj-ai/transport
|
|
3
|
+
*
|
|
4
|
+
* Platform-agnostic WebSocket transport infrastructure with RPC-like protocol API.
|
|
5
|
+
*/
|
|
6
|
+
// ============================================================================
|
|
7
|
+
// Core Exports
|
|
8
|
+
// ============================================================================
|
|
9
|
+
// Protocol Definition API
|
|
10
|
+
export { defineProtocol, method, notification } from './core/protocol.js';
|
|
11
|
+
// Result Type
|
|
12
|
+
export { Err, flatMapResult, isErr, isOk, mapResult, Ok, unwrapOr, unwrapOrThrow } from './core/result.js';
|
|
13
|
+
export { DEFAULT_RECONNECT_OPTIONS } from './core/types.js';
|
|
14
|
+
// Core Components
|
|
15
|
+
export { createRouter, MessageRouter } from './core/router.js';
|
|
16
|
+
export { Connection } from './core/connection.js';
|
|
17
|
+
export { WebSocketReadyState } from './platform/types.js';
|
|
18
|
+
// ============================================================================
|
|
19
|
+
// Client Exports
|
|
20
|
+
// ============================================================================
|
|
21
|
+
export { ClientConnection, createClientConnection } from './client/client-connection.js';
|
|
22
|
+
// ============================================================================
|
|
23
|
+
// Server Exports
|
|
24
|
+
// ============================================================================
|
|
25
|
+
export { createServerConnection, ServerConnection } from './server/server-connection.js';
|
|
26
|
+
export { ConnectionManager } from './server/connection-manager.js';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser WebSocket Adapter
|
|
3
|
+
*
|
|
4
|
+
* Wraps the native browser WebSocket to conform to IWebSocket interface.
|
|
5
|
+
*/
|
|
6
|
+
import type { ICloseEvent, IWebSocket, IWebSocketFactory } from './types.js';
|
|
7
|
+
import { WebSocketReadyState } from './types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Browser WebSocket factory.
|
|
10
|
+
*/
|
|
11
|
+
export declare const browserWebSocketFactory: IWebSocketFactory;
|
|
12
|
+
export { WebSocketReadyState };
|
|
13
|
+
export type { ICloseEvent, IWebSocket, IWebSocketFactory };
|
|
14
|
+
//# sourceMappingURL=browser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../src/platform/browser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAC5E,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AA4DhD;;GAEG;AACH,eAAO,MAAM,uBAAuB,EAAE,iBAIrC,CAAA;AAGD,OAAO,EAAE,mBAAmB,EAAE,CAAA;AAC9B,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,iBAAiB,EAAE,CAAA"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser WebSocket Adapter
|
|
3
|
+
*
|
|
4
|
+
* Wraps the native browser WebSocket to conform to IWebSocket interface.
|
|
5
|
+
*/
|
|
6
|
+
import { WebSocketReadyState } from './types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Browser WebSocket adapter that wraps native WebSocket.
|
|
9
|
+
*/
|
|
10
|
+
class BrowserWebSocketAdapter {
|
|
11
|
+
ws;
|
|
12
|
+
onopen = null;
|
|
13
|
+
onclose = null;
|
|
14
|
+
onerror = null;
|
|
15
|
+
onmessage = null;
|
|
16
|
+
constructor(url) {
|
|
17
|
+
this.ws = new WebSocket(url);
|
|
18
|
+
this.ws.onopen = () => {
|
|
19
|
+
this.onopen?.();
|
|
20
|
+
};
|
|
21
|
+
this.ws.onclose = (event) => {
|
|
22
|
+
this.onclose?.({
|
|
23
|
+
code: event.code,
|
|
24
|
+
reason: event.reason,
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
this.ws.onerror = () => {
|
|
28
|
+
// Browser WebSocket doesn't provide error details
|
|
29
|
+
this.onerror?.(new Error('WebSocket error'));
|
|
30
|
+
};
|
|
31
|
+
this.ws.onmessage = (event) => {
|
|
32
|
+
// Handle text data only
|
|
33
|
+
if (typeof event.data === 'string') {
|
|
34
|
+
this.onmessage?.(event.data);
|
|
35
|
+
}
|
|
36
|
+
else if (event.data instanceof Blob) {
|
|
37
|
+
// Convert Blob to string for text-only protocol
|
|
38
|
+
event.data.text().then((text) => {
|
|
39
|
+
this.onmessage?.(text);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
get readyState() {
|
|
45
|
+
return this.ws.readyState;
|
|
46
|
+
}
|
|
47
|
+
send(data) {
|
|
48
|
+
if (this.ws.readyState === WebSocketReadyState.OPEN) {
|
|
49
|
+
this.ws.send(data);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
close(code, reason) {
|
|
53
|
+
this.ws.close(code, reason);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Browser WebSocket factory.
|
|
58
|
+
*/
|
|
59
|
+
export const browserWebSocketFactory = {
|
|
60
|
+
create(url) {
|
|
61
|
+
return new BrowserWebSocketAdapter(url);
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
// Re-export types for convenience
|
|
65
|
+
export { WebSocketReadyState };
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bun WebSocket Adapters
|
|
3
|
+
*
|
|
4
|
+
* Provides both client and server WebSocket adapters for Bun runtime.
|
|
5
|
+
*/
|
|
6
|
+
import type { ICloseEvent, IServerWebSocket, IWebSocket, IWebSocketFactory } from './types.js';
|
|
7
|
+
import { WebSocketReadyState } from './types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Bun WebSocket client factory.
|
|
10
|
+
*/
|
|
11
|
+
export declare const bunWebSocketFactory: IWebSocketFactory;
|
|
12
|
+
/**
|
|
13
|
+
* Server WebSocket data interface.
|
|
14
|
+
*/
|
|
15
|
+
export interface ServerWebSocketData<T = unknown> {
|
|
16
|
+
/** User-attached data */
|
|
17
|
+
userData: T;
|
|
18
|
+
/** Topics this connection is subscribed to */
|
|
19
|
+
topics: Set<string>;
|
|
20
|
+
}
|
|
21
|
+
type BunServerWebSocket = any;
|
|
22
|
+
/**
|
|
23
|
+
* Bun server WebSocket adapter.
|
|
24
|
+
* Wraps Bun's ServerWebSocket to conform to IServerWebSocket interface.
|
|
25
|
+
*/
|
|
26
|
+
export declare class BunServerWebSocketAdapter<T = unknown> implements IServerWebSocket<T> {
|
|
27
|
+
private readonly ws;
|
|
28
|
+
private wsData;
|
|
29
|
+
onopen: (() => void) | null;
|
|
30
|
+
onclose: ((event: ICloseEvent) => void) | null;
|
|
31
|
+
onerror: ((error: Error) => void) | null;
|
|
32
|
+
onmessage: ((data: string) => void) | null;
|
|
33
|
+
constructor(ws: BunServerWebSocket, data: T);
|
|
34
|
+
get data(): T;
|
|
35
|
+
set data(value: T);
|
|
36
|
+
get readyState(): WebSocketReadyState;
|
|
37
|
+
send(data: string): void;
|
|
38
|
+
close(code?: number, reason?: string): void;
|
|
39
|
+
subscribe(topic: string): void;
|
|
40
|
+
unsubscribe(topic: string): void;
|
|
41
|
+
publish(topic: string, message: string): void;
|
|
42
|
+
isSubscribed(topic: string): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Get the underlying Bun WebSocket (for advanced use cases).
|
|
45
|
+
*/
|
|
46
|
+
getRawWebSocket(): BunServerWebSocket;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Helper to create Bun WebSocket handlers that integrate with the transport layer.
|
|
50
|
+
*/
|
|
51
|
+
export interface BunWebSocketHandlers<T> {
|
|
52
|
+
open: (ws: BunServerWebSocket) => void;
|
|
53
|
+
close: (ws: BunServerWebSocket, code: number, reason: string) => void;
|
|
54
|
+
message: (ws: BunServerWebSocket, message: string | Buffer) => void;
|
|
55
|
+
error: (ws: BunServerWebSocket, error: Error) => void;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Create Bun WebSocket handlers with adapter integration.
|
|
59
|
+
*/
|
|
60
|
+
export declare function createBunWebSocketHandlers<T>(callbacks: {
|
|
61
|
+
onOpen: (ws: IServerWebSocket<T>) => void;
|
|
62
|
+
onClose: (ws: IServerWebSocket<T>, code: number, reason: string) => void;
|
|
63
|
+
onMessage: (ws: IServerWebSocket<T>, message: string) => void;
|
|
64
|
+
onError: (ws: IServerWebSocket<T>, error: Error) => void;
|
|
65
|
+
getData: (ws: BunServerWebSocket) => T;
|
|
66
|
+
}): BunWebSocketHandlers<T>;
|
|
67
|
+
export { WebSocketReadyState };
|
|
68
|
+
export type { ICloseEvent, IServerWebSocket, IWebSocket, IWebSocketFactory };
|
|
69
|
+
//# sourceMappingURL=bun.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bun.d.ts","sourceRoot":"","sources":["../../src/platform/bun.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bun WebSocket Adapters
|
|
3
|
+
*
|
|
4
|
+
* Provides both client and server WebSocket adapters for Bun runtime.
|
|
5
|
+
*/
|
|
6
|
+
import { WebSocketReadyState } from './types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Bun WebSocket client adapter.
|
|
9
|
+
* Wraps Bun's WebSocket client to conform to IWebSocket interface.
|
|
10
|
+
*/
|
|
11
|
+
class BunWebSocketClientAdapter {
|
|
12
|
+
ws;
|
|
13
|
+
onopen = null;
|
|
14
|
+
onclose = null;
|
|
15
|
+
onerror = null;
|
|
16
|
+
onmessage = null;
|
|
17
|
+
constructor(url) {
|
|
18
|
+
this.ws = new WebSocket(url);
|
|
19
|
+
this.ws.onopen = () => {
|
|
20
|
+
this.onopen?.();
|
|
21
|
+
};
|
|
22
|
+
this.ws.onclose = (event) => {
|
|
23
|
+
this.onclose?.({
|
|
24
|
+
code: event.code,
|
|
25
|
+
reason: event.reason,
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
this.ws.onerror = () => {
|
|
29
|
+
this.onerror?.(new Error('WebSocket error'));
|
|
30
|
+
};
|
|
31
|
+
this.ws.onmessage = (event) => {
|
|
32
|
+
if (typeof event.data === 'string') {
|
|
33
|
+
this.onmessage?.(event.data);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
get readyState() {
|
|
38
|
+
return this.ws.readyState;
|
|
39
|
+
}
|
|
40
|
+
send(data) {
|
|
41
|
+
if (this.ws.readyState === WebSocketReadyState.OPEN) {
|
|
42
|
+
this.ws.send(data);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
close(code, reason) {
|
|
46
|
+
this.ws.close(code, reason);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Bun WebSocket client factory.
|
|
51
|
+
*/
|
|
52
|
+
export const bunWebSocketFactory = {
|
|
53
|
+
create(url) {
|
|
54
|
+
return new BunWebSocketClientAdapter(url);
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Bun server WebSocket adapter.
|
|
59
|
+
* Wraps Bun's ServerWebSocket to conform to IServerWebSocket interface.
|
|
60
|
+
*/
|
|
61
|
+
export class BunServerWebSocketAdapter {
|
|
62
|
+
ws;
|
|
63
|
+
wsData;
|
|
64
|
+
onopen = null;
|
|
65
|
+
onclose = null;
|
|
66
|
+
onerror = null;
|
|
67
|
+
onmessage = null;
|
|
68
|
+
constructor(ws, data) {
|
|
69
|
+
this.ws = ws;
|
|
70
|
+
this.wsData = {
|
|
71
|
+
userData: data,
|
|
72
|
+
topics: new Set(),
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
get data() {
|
|
76
|
+
return this.wsData.userData;
|
|
77
|
+
}
|
|
78
|
+
set data(value) {
|
|
79
|
+
this.wsData.userData = value;
|
|
80
|
+
}
|
|
81
|
+
get readyState() {
|
|
82
|
+
return this.ws.readyState;
|
|
83
|
+
}
|
|
84
|
+
send(data) {
|
|
85
|
+
if (this.ws.readyState === WebSocketReadyState.OPEN) {
|
|
86
|
+
this.ws.send(data);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
close(code, reason) {
|
|
90
|
+
this.ws.close(code, reason);
|
|
91
|
+
}
|
|
92
|
+
subscribe(topic) {
|
|
93
|
+
this.ws.subscribe(topic);
|
|
94
|
+
this.wsData.topics.add(topic);
|
|
95
|
+
}
|
|
96
|
+
unsubscribe(topic) {
|
|
97
|
+
this.ws.unsubscribe(topic);
|
|
98
|
+
this.wsData.topics.delete(topic);
|
|
99
|
+
}
|
|
100
|
+
publish(topic, message) {
|
|
101
|
+
this.ws.publish(topic, message);
|
|
102
|
+
}
|
|
103
|
+
isSubscribed(topic) {
|
|
104
|
+
return this.wsData.topics.has(topic);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Get the underlying Bun WebSocket (for advanced use cases).
|
|
108
|
+
*/
|
|
109
|
+
getRawWebSocket() {
|
|
110
|
+
return this.ws;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Create Bun WebSocket handlers with adapter integration.
|
|
115
|
+
*/
|
|
116
|
+
export function createBunWebSocketHandlers(callbacks) {
|
|
117
|
+
// Map to store adapter instances
|
|
118
|
+
const adapters = new WeakMap();
|
|
119
|
+
const getOrCreateAdapter = (ws) => {
|
|
120
|
+
let adapter = adapters.get(ws);
|
|
121
|
+
if (!adapter) {
|
|
122
|
+
adapter = new BunServerWebSocketAdapter(ws, callbacks.getData(ws));
|
|
123
|
+
adapters.set(ws, adapter);
|
|
124
|
+
}
|
|
125
|
+
return adapter;
|
|
126
|
+
};
|
|
127
|
+
return {
|
|
128
|
+
open(ws) {
|
|
129
|
+
const adapter = getOrCreateAdapter(ws);
|
|
130
|
+
callbacks.onOpen(adapter);
|
|
131
|
+
},
|
|
132
|
+
close(ws, code, reason) {
|
|
133
|
+
const adapter = adapters.get(ws);
|
|
134
|
+
if (adapter) {
|
|
135
|
+
callbacks.onClose(adapter, code, reason);
|
|
136
|
+
adapters.delete(ws);
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
message(ws, message) {
|
|
140
|
+
const adapter = getOrCreateAdapter(ws);
|
|
141
|
+
// Convert Buffer to string if needed
|
|
142
|
+
const data = typeof message === 'string' ? message : message.toString('utf-8');
|
|
143
|
+
callbacks.onMessage(adapter, data);
|
|
144
|
+
},
|
|
145
|
+
error(ws, error) {
|
|
146
|
+
const adapter = getOrCreateAdapter(ws);
|
|
147
|
+
callbacks.onError(adapter, error);
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
// Re-export types for convenience
|
|
152
|
+
export { WebSocketReadyState };
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Platform Abstraction Types
|
|
3
|
+
*
|
|
4
|
+
* Common interfaces for WebSocket implementations across platforms (browser + Bun).
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* WebSocket ready state values.
|
|
8
|
+
*/
|
|
9
|
+
export declare const WebSocketReadyState: {
|
|
10
|
+
readonly CONNECTING: 0;
|
|
11
|
+
readonly OPEN: 1;
|
|
12
|
+
readonly CLOSING: 2;
|
|
13
|
+
readonly CLOSED: 3;
|
|
14
|
+
};
|
|
15
|
+
export type WebSocketReadyState = (typeof WebSocketReadyState)[keyof typeof WebSocketReadyState];
|
|
16
|
+
/**
|
|
17
|
+
* Close event structure.
|
|
18
|
+
*/
|
|
19
|
+
export interface ICloseEvent {
|
|
20
|
+
code: number;
|
|
21
|
+
reason: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Platform-agnostic WebSocket interface.
|
|
25
|
+
*/
|
|
26
|
+
export interface IWebSocket {
|
|
27
|
+
/** Current ready state */
|
|
28
|
+
readonly readyState: WebSocketReadyState;
|
|
29
|
+
/** Send a text message */
|
|
30
|
+
send(data: string): void;
|
|
31
|
+
/** Close the connection */
|
|
32
|
+
close(code?: number, reason?: string): void;
|
|
33
|
+
/** Called when connection opens */
|
|
34
|
+
onopen: (() => void) | null;
|
|
35
|
+
/** Called when connection closes */
|
|
36
|
+
onclose: ((event: ICloseEvent) => void) | null;
|
|
37
|
+
/** Called on error */
|
|
38
|
+
onerror: ((error: Error) => void) | null;
|
|
39
|
+
/** Called when a message is received */
|
|
40
|
+
onmessage: ((data: string) => void) | null;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Factory for creating WebSocket client connections.
|
|
44
|
+
*/
|
|
45
|
+
export interface IWebSocketFactory {
|
|
46
|
+
/** Create a new WebSocket connection to the given URL */
|
|
47
|
+
create(url: string): IWebSocket;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Server-side WebSocket interface (for handling incoming connections).
|
|
51
|
+
* Extended from IWebSocket with server-specific capabilities.
|
|
52
|
+
*/
|
|
53
|
+
export interface IServerWebSocket<T = unknown> extends IWebSocket {
|
|
54
|
+
/** Attached data for this connection */
|
|
55
|
+
data: T;
|
|
56
|
+
/** Subscribe to a topic for pub/sub messaging */
|
|
57
|
+
subscribe(topic: string): void;
|
|
58
|
+
/** Unsubscribe from a topic */
|
|
59
|
+
unsubscribe(topic: string): void;
|
|
60
|
+
/** Publish to a topic (message sent to all subscribers except sender) */
|
|
61
|
+
publish(topic: string, message: string): void;
|
|
62
|
+
/** Check if subscribed to a topic */
|
|
63
|
+
isSubscribed(topic: string): boolean;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* WebSocket server upgrade request data.
|
|
67
|
+
*/
|
|
68
|
+
export interface IUpgradeData<T = unknown> {
|
|
69
|
+
/** Data to attach to the WebSocket connection */
|
|
70
|
+
data: T;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* WebSocket server interface for handling multiple connections.
|
|
74
|
+
*/
|
|
75
|
+
export interface IWebSocketServer<T = unknown> {
|
|
76
|
+
/** Handle WebSocket upgrade from HTTP request */
|
|
77
|
+
upgrade(request: Request, data: T): boolean;
|
|
78
|
+
/** Publish to all connections subscribed to a topic */
|
|
79
|
+
publish(topic: string, message: string): void;
|
|
80
|
+
/** Get all active connections */
|
|
81
|
+
getConnections(): Iterable<IServerWebSocket<T>>;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/platform/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,eAAO,MAAM,mBAAmB;;;;;CAKtB,CAAA;AAEV,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,OAAO,mBAAmB,CAAC,CAAA;AAEhG;;GAEG;AACH,MAAM,WAAW,WAAW;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;CACd;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IAC1B,0BAA0B;IAC1B,QAAQ,CAAC,UAAU,EAAE,mBAAmB,CAAA;IAExC,0BAA0B;IAC1B,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IAExB,2BAA2B;IAC3B,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAE3C,mCAAmC;IACnC,MAAM,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAA;IAE3B,oCAAoC;IACpC,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC,GAAG,IAAI,CAAA;IAE9C,sBAAsB;IACtB,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC,GAAG,IAAI,CAAA;IAExC,wCAAwC;IACxC,SAAS,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,IAAI,CAAA;CAC1C;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IACjC,yDAAyD;IACzD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAAA;CAC/B;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB,CAAC,CAAC,GAAG,OAAO,CAAE,SAAQ,UAAU;IAChE,wCAAwC;IACxC,IAAI,EAAE,CAAC,CAAA;IAEP,iDAAiD;IACjD,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IAE9B,+BAA+B;IAC/B,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IAEhC,yEAAyE;IACzE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IAE7C,qCAAqC;IACrC,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAA;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,YAAY,CAAC,CAAC,GAAG,OAAO;IACxC,iDAAiD;IACjD,IAAI,EAAE,CAAC,CAAA;CACP;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB,CAAC,CAAC,GAAG,OAAO;IAC5C,iDAAiD;IACjD,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,GAAG,OAAO,CAAA;IAE3C,uDAAuD;IACvD,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IAE7C,iCAAiC;IACjC,cAAc,IAAI,QAAQ,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAA;CAC/C"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Platform Abstraction Types
|
|
3
|
+
*
|
|
4
|
+
* Common interfaces for WebSocket implementations across platforms (browser + Bun).
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* WebSocket ready state values.
|
|
8
|
+
*/
|
|
9
|
+
export const WebSocketReadyState = {
|
|
10
|
+
CONNECTING: 0,
|
|
11
|
+
OPEN: 1,
|
|
12
|
+
CLOSING: 2,
|
|
13
|
+
CLOSED: 3,
|
|
14
|
+
};
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Connection Manager
|
|
3
|
+
*
|
|
4
|
+
* Manages multiple WebSocket connections and session subscriptions.
|
|
5
|
+
*/
|
|
6
|
+
import type { ProtocolDef } from '../core/protocol.js';
|
|
7
|
+
import type { ServerConnection } from './server-connection.js';
|
|
8
|
+
/**
|
|
9
|
+
* Connection statistics.
|
|
10
|
+
*/
|
|
11
|
+
export interface ConnectionStats {
|
|
12
|
+
/** Total number of connections */
|
|
13
|
+
totalConnections: number;
|
|
14
|
+
/** Number of active (connected) connections */
|
|
15
|
+
activeConnections: number;
|
|
16
|
+
/** Number of unique sessions with subscribers */
|
|
17
|
+
activeSessions: number;
|
|
18
|
+
/** Connections by client type */
|
|
19
|
+
byClientType: Record<string, number>;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Manages multiple server connections and session subscriptions.
|
|
23
|
+
*
|
|
24
|
+
* Features:
|
|
25
|
+
* - Track all active connections
|
|
26
|
+
* - Manage session subscriptions
|
|
27
|
+
* - Broadcast to subscribed connections
|
|
28
|
+
* - Connection statistics
|
|
29
|
+
*/
|
|
30
|
+
export declare class ConnectionManager<TReceive extends ProtocolDef = ProtocolDef, TSend extends ProtocolDef = ProtocolDef> {
|
|
31
|
+
private connections;
|
|
32
|
+
private sessionSubscriptions;
|
|
33
|
+
/**
|
|
34
|
+
* Add a connection.
|
|
35
|
+
*/
|
|
36
|
+
add(connection: ServerConnection<TReceive, TSend>): void;
|
|
37
|
+
/**
|
|
38
|
+
* Remove a connection.
|
|
39
|
+
*/
|
|
40
|
+
remove(connectionId: string): void;
|
|
41
|
+
/**
|
|
42
|
+
* Get a connection by ID.
|
|
43
|
+
*/
|
|
44
|
+
get(connectionId: string): ServerConnection<TReceive, TSend> | undefined;
|
|
45
|
+
/**
|
|
46
|
+
* Check if a connection exists.
|
|
47
|
+
*/
|
|
48
|
+
has(connectionId: string): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Get all connections.
|
|
51
|
+
*/
|
|
52
|
+
getAll(): Iterable<ServerConnection<TReceive, TSend>>;
|
|
53
|
+
/**
|
|
54
|
+
* Get all connection IDs.
|
|
55
|
+
*/
|
|
56
|
+
getAllIds(): Iterable<string>;
|
|
57
|
+
/**
|
|
58
|
+
* Get connection count.
|
|
59
|
+
*/
|
|
60
|
+
get size(): number;
|
|
61
|
+
/**
|
|
62
|
+
* Subscribe a connection to a session.
|
|
63
|
+
*/
|
|
64
|
+
subscribe(connectionId: string, sessionId: string): boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Unsubscribe a connection from a session.
|
|
67
|
+
*/
|
|
68
|
+
unsubscribe(connectionId: string, sessionId: string): boolean;
|
|
69
|
+
/**
|
|
70
|
+
* Get all subscribers for a session.
|
|
71
|
+
*/
|
|
72
|
+
getSubscribers(sessionId: string): ServerConnection<TReceive, TSend>[];
|
|
73
|
+
/**
|
|
74
|
+
* Get subscriber count for a session.
|
|
75
|
+
*/
|
|
76
|
+
getSubscriberCount(sessionId: string): number;
|
|
77
|
+
/**
|
|
78
|
+
* Check if a session has any subscribers.
|
|
79
|
+
*/
|
|
80
|
+
hasSubscribers(sessionId: string): boolean;
|
|
81
|
+
/**
|
|
82
|
+
* Broadcast a raw message to all subscribers of a session.
|
|
83
|
+
*/
|
|
84
|
+
broadcast(sessionId: string, message: string): number;
|
|
85
|
+
/**
|
|
86
|
+
* Broadcast to all connections.
|
|
87
|
+
*/
|
|
88
|
+
broadcastToAll(message: string): number;
|
|
89
|
+
/**
|
|
90
|
+
* Get connection statistics.
|
|
91
|
+
*/
|
|
92
|
+
getStats(): ConnectionStats;
|
|
93
|
+
/**
|
|
94
|
+
* Clear all connections.
|
|
95
|
+
*/
|
|
96
|
+
clear(): void;
|
|
97
|
+
/**
|
|
98
|
+
* Remove disconnected connections.
|
|
99
|
+
*/
|
|
100
|
+
cleanup(): number;
|
|
101
|
+
/**
|
|
102
|
+
* Internal unsubscribe (updates subscription map only).
|
|
103
|
+
*/
|
|
104
|
+
private unsubscribeInternal;
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=connection-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection-manager.d.ts","sourceRoot":"","sources":["../../src/server/connection-manager.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AAM9D;;GAEG;AACH,MAAM,WAAW,eAAe;IAC/B,kCAAkC;IAClC,gBAAgB,EAAE,MAAM,CAAA;IACxB,+CAA+C;IAC/C,iBAAiB,EAAE,MAAM,CAAA;IACzB,iDAAiD;IACjD,cAAc,EAAE,MAAM,CAAA;IACtB,iCAAiC;IACjC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACpC;AAMD;;;;;;;;GAQG;AACH,qBAAa,iBAAiB,CAC7B,QAAQ,SAAS,WAAW,GAAG,WAAW,EAC1C,KAAK,SAAS,WAAW,GAAG,WAAW;IAEvC,OAAO,CAAC,WAAW,CAAuD;IAC1E,OAAO,CAAC,oBAAoB,CAAiC;IAM7D;;OAEG;IACH,GAAG,CAAC,UAAU,EAAE,gBAAgB,CAAC,QAAQ,EAAE,KAAK,CAAC,GAAG,IAAI;IAIxD;;OAEG;IACH,MAAM,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI;IAYlC;;OAEG;IACH,GAAG,CAAC,YAAY,EAAE,MAAM,GAAG,gBAAgB,CAAC,QAAQ,EAAE,KAAK,CAAC,GAAG,SAAS;IAIxE;;OAEG;IACH,GAAG,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO;IAIlC;;OAEG;IACH,MAAM,IAAI,QAAQ,CAAC,gBAAgB,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAIrD;;OAEG;IACH,SAAS,IAAI,QAAQ,CAAC,MAAM,CAAC;IAI7B;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;IAMD;;OAEG;IACH,SAAS,CAAC,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO;IAgB3D;;OAEG;IACH,WAAW,CAAC,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO;IAU7D;;OAEG;IACH,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,gBAAgB,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE;IA0BtE;;OAEG;IACH,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAI7C;;OAEG;IACH,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAQ1C;;OAEG;IACH,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM;IAarD;;OAEG;IACH,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAgBvC;;OAEG;IACH,QAAQ,IAAI,eAAe;IAyB3B;;OAEG;IACH,KAAK,IAAI,IAAI;IAQb;;OAEG;IACH,OAAO,IAAI,MAAM;IAiBjB;;OAEG;IACH,OAAO,CAAC,mBAAmB;CAS3B"}
|