@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
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Connection Manager
|
|
3
|
+
*
|
|
4
|
+
* Manages multiple WebSocket connections and session subscriptions.
|
|
5
|
+
*/
|
|
6
|
+
// ============================================================================
|
|
7
|
+
// Connection Manager
|
|
8
|
+
// ============================================================================
|
|
9
|
+
/**
|
|
10
|
+
* Manages multiple server connections and session subscriptions.
|
|
11
|
+
*
|
|
12
|
+
* Features:
|
|
13
|
+
* - Track all active connections
|
|
14
|
+
* - Manage session subscriptions
|
|
15
|
+
* - Broadcast to subscribed connections
|
|
16
|
+
* - Connection statistics
|
|
17
|
+
*/
|
|
18
|
+
export class ConnectionManager {
|
|
19
|
+
connections = new Map();
|
|
20
|
+
sessionSubscriptions = new Map(); // sessionId -> connectionIds
|
|
21
|
+
// ============================================================================
|
|
22
|
+
// Connection Management
|
|
23
|
+
// ============================================================================
|
|
24
|
+
/**
|
|
25
|
+
* Add a connection.
|
|
26
|
+
*/
|
|
27
|
+
add(connection) {
|
|
28
|
+
this.connections.set(connection.getConnectionId(), connection);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Remove a connection.
|
|
32
|
+
*/
|
|
33
|
+
remove(connectionId) {
|
|
34
|
+
const connection = this.connections.get(connectionId);
|
|
35
|
+
if (!connection)
|
|
36
|
+
return;
|
|
37
|
+
// Clean up subscriptions
|
|
38
|
+
for (const sessionId of connection.getSubscribedSessions()) {
|
|
39
|
+
this.unsubscribeInternal(connectionId, sessionId);
|
|
40
|
+
}
|
|
41
|
+
this.connections.delete(connectionId);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Get a connection by ID.
|
|
45
|
+
*/
|
|
46
|
+
get(connectionId) {
|
|
47
|
+
return this.connections.get(connectionId);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Check if a connection exists.
|
|
51
|
+
*/
|
|
52
|
+
has(connectionId) {
|
|
53
|
+
return this.connections.has(connectionId);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Get all connections.
|
|
57
|
+
*/
|
|
58
|
+
getAll() {
|
|
59
|
+
return this.connections.values();
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Get all connection IDs.
|
|
63
|
+
*/
|
|
64
|
+
getAllIds() {
|
|
65
|
+
return this.connections.keys();
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Get connection count.
|
|
69
|
+
*/
|
|
70
|
+
get size() {
|
|
71
|
+
return this.connections.size;
|
|
72
|
+
}
|
|
73
|
+
// ============================================================================
|
|
74
|
+
// Session Subscriptions
|
|
75
|
+
// ============================================================================
|
|
76
|
+
/**
|
|
77
|
+
* Subscribe a connection to a session.
|
|
78
|
+
*/
|
|
79
|
+
subscribe(connectionId, sessionId) {
|
|
80
|
+
const connection = this.connections.get(connectionId);
|
|
81
|
+
if (!connection)
|
|
82
|
+
return false;
|
|
83
|
+
connection.subscribe(sessionId);
|
|
84
|
+
let subscribers = this.sessionSubscriptions.get(sessionId);
|
|
85
|
+
if (!subscribers) {
|
|
86
|
+
subscribers = new Set();
|
|
87
|
+
this.sessionSubscriptions.set(sessionId, subscribers);
|
|
88
|
+
}
|
|
89
|
+
subscribers.add(connectionId);
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Unsubscribe a connection from a session.
|
|
94
|
+
*/
|
|
95
|
+
unsubscribe(connectionId, sessionId) {
|
|
96
|
+
const connection = this.connections.get(connectionId);
|
|
97
|
+
if (!connection)
|
|
98
|
+
return false;
|
|
99
|
+
connection.unsubscribe(sessionId);
|
|
100
|
+
this.unsubscribeInternal(connectionId, sessionId);
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Get all subscribers for a session.
|
|
105
|
+
*/
|
|
106
|
+
getSubscribers(sessionId) {
|
|
107
|
+
const subscriberIds = this.sessionSubscriptions.get(sessionId);
|
|
108
|
+
if (!subscriberIds)
|
|
109
|
+
return [];
|
|
110
|
+
const subscribers = [];
|
|
111
|
+
const deadIds = [];
|
|
112
|
+
for (const connectionId of subscriberIds) {
|
|
113
|
+
const connection = this.connections.get(connectionId);
|
|
114
|
+
if (connection?.isConnected()) {
|
|
115
|
+
subscribers.push(connection);
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
deadIds.push(connectionId);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
// Clean up dead subscriptions
|
|
122
|
+
for (const id of deadIds) {
|
|
123
|
+
subscriberIds.delete(id);
|
|
124
|
+
}
|
|
125
|
+
if (subscriberIds.size === 0) {
|
|
126
|
+
this.sessionSubscriptions.delete(sessionId);
|
|
127
|
+
}
|
|
128
|
+
return subscribers;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Get subscriber count for a session.
|
|
132
|
+
*/
|
|
133
|
+
getSubscriberCount(sessionId) {
|
|
134
|
+
return this.sessionSubscriptions.get(sessionId)?.size ?? 0;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Check if a session has any subscribers.
|
|
138
|
+
*/
|
|
139
|
+
hasSubscribers(sessionId) {
|
|
140
|
+
return this.getSubscriberCount(sessionId) > 0;
|
|
141
|
+
}
|
|
142
|
+
// ============================================================================
|
|
143
|
+
// Broadcasting
|
|
144
|
+
// ============================================================================
|
|
145
|
+
/**
|
|
146
|
+
* Broadcast a raw message to all subscribers of a session.
|
|
147
|
+
*/
|
|
148
|
+
broadcast(sessionId, message) {
|
|
149
|
+
const subscribers = this.getSubscribers(sessionId);
|
|
150
|
+
let sent = 0;
|
|
151
|
+
for (const connection of subscribers) {
|
|
152
|
+
if (connection.send(message)) {
|
|
153
|
+
sent++;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return sent;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Broadcast to all connections.
|
|
160
|
+
*/
|
|
161
|
+
broadcastToAll(message) {
|
|
162
|
+
let sent = 0;
|
|
163
|
+
for (const connection of this.connections.values()) {
|
|
164
|
+
if (connection.isConnected() && connection.send(message)) {
|
|
165
|
+
sent++;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return sent;
|
|
169
|
+
}
|
|
170
|
+
// ============================================================================
|
|
171
|
+
// Statistics
|
|
172
|
+
// ============================================================================
|
|
173
|
+
/**
|
|
174
|
+
* Get connection statistics.
|
|
175
|
+
*/
|
|
176
|
+
getStats() {
|
|
177
|
+
const byClientType = {};
|
|
178
|
+
let activeConnections = 0;
|
|
179
|
+
for (const connection of this.connections.values()) {
|
|
180
|
+
const clientType = connection.getClientType();
|
|
181
|
+
byClientType[clientType] = (byClientType[clientType] ?? 0) + 1;
|
|
182
|
+
if (connection.isConnected()) {
|
|
183
|
+
activeConnections++;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return {
|
|
187
|
+
totalConnections: this.connections.size,
|
|
188
|
+
activeConnections,
|
|
189
|
+
activeSessions: this.sessionSubscriptions.size,
|
|
190
|
+
byClientType,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
// ============================================================================
|
|
194
|
+
// Cleanup
|
|
195
|
+
// ============================================================================
|
|
196
|
+
/**
|
|
197
|
+
* Clear all connections.
|
|
198
|
+
*/
|
|
199
|
+
clear() {
|
|
200
|
+
for (const connection of this.connections.values()) {
|
|
201
|
+
connection.disconnect();
|
|
202
|
+
}
|
|
203
|
+
this.connections.clear();
|
|
204
|
+
this.sessionSubscriptions.clear();
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Remove disconnected connections.
|
|
208
|
+
*/
|
|
209
|
+
cleanup() {
|
|
210
|
+
let removed = 0;
|
|
211
|
+
for (const [connectionId, connection] of this.connections) {
|
|
212
|
+
if (!connection.isConnected()) {
|
|
213
|
+
this.remove(connectionId);
|
|
214
|
+
removed++;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
return removed;
|
|
218
|
+
}
|
|
219
|
+
// ============================================================================
|
|
220
|
+
// Private Methods
|
|
221
|
+
// ============================================================================
|
|
222
|
+
/**
|
|
223
|
+
* Internal unsubscribe (updates subscription map only).
|
|
224
|
+
*/
|
|
225
|
+
unsubscribeInternal(connectionId, sessionId) {
|
|
226
|
+
const subscribers = this.sessionSubscriptions.get(sessionId);
|
|
227
|
+
if (subscribers) {
|
|
228
|
+
subscribers.delete(connectionId);
|
|
229
|
+
if (subscribers.size === 0) {
|
|
230
|
+
this.sessionSubscriptions.delete(sessionId);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server Connection Module
|
|
3
|
+
*
|
|
4
|
+
* WebSocket server for handling incoming client connections.
|
|
5
|
+
*/
|
|
6
|
+
export { createServerConnection, ServerConnection } from './server-connection.js';
|
|
7
|
+
export type { ServerConnectionConfig, ServerHandlerContext } from './server-connection.js';
|
|
8
|
+
export { ConnectionManager } from './connection-manager.js';
|
|
9
|
+
export type { ConnectionStats } from './connection-manager.js';
|
|
10
|
+
export type { ConnectionState, HandlerContext, Protocol, ProtocolCaller, ProtocolDef, ProtocolHandlers, ProtocolNotifier, TransportEvent, TransportEventListener, } from '../core/index.js';
|
|
11
|
+
export { defineProtocol, method, notification } from '../core/index.js';
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACjF,YAAY,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAE1F,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AAC3D,YAAY,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAG9D,YAAY,EACX,eAAe,EACf,cAAc,EACd,QAAQ,EACR,cAAc,EACd,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,sBAAsB,GACtB,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server Connection Module
|
|
3
|
+
*
|
|
4
|
+
* WebSocket server for handling incoming client connections.
|
|
5
|
+
*/
|
|
6
|
+
export { createServerConnection, ServerConnection } from './server-connection.js';
|
|
7
|
+
export { ConnectionManager } from './connection-manager.js';
|
|
8
|
+
export { defineProtocol, method, notification } from '../core/index.js';
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server Connection
|
|
3
|
+
*
|
|
4
|
+
* Represents a single client connection on the server side.
|
|
5
|
+
* Simplified: no handshake - connection is ready immediately when attached.
|
|
6
|
+
*/
|
|
7
|
+
import { Connection } from '../core/connection.js';
|
|
8
|
+
import type { ConnectionConfig } from '../core/connection.js';
|
|
9
|
+
import type { HandlerContext, ProtocolDef } from '../core/protocol.js';
|
|
10
|
+
import type { IServerWebSocket } from '../platform/types.js';
|
|
11
|
+
/**
|
|
12
|
+
* Server connection configuration.
|
|
13
|
+
*/
|
|
14
|
+
export interface ServerConnectionConfig<TReceive extends ProtocolDef, TSend extends ProtocolDef> extends ConnectionConfig<TReceive, TSend> {
|
|
15
|
+
connectionId?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Extended handler context for server connections.
|
|
19
|
+
*/
|
|
20
|
+
export interface ServerHandlerContext extends HandlerContext {
|
|
21
|
+
clientType?: string;
|
|
22
|
+
subscribedSessions: Set<string>;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Server-side WebSocket connection representing a single client.
|
|
26
|
+
*/
|
|
27
|
+
export declare class ServerConnection<TReceive extends ProtocolDef, TSend extends ProtocolDef> extends Connection<TReceive, TSend> {
|
|
28
|
+
private serverWs;
|
|
29
|
+
private clientType;
|
|
30
|
+
private subscribedSessions;
|
|
31
|
+
constructor(config: ServerConnectionConfig<TReceive, TSend>);
|
|
32
|
+
/**
|
|
33
|
+
* Attach an already-accepted WebSocket connection.
|
|
34
|
+
* Connection is immediately ready - no handshake needed.
|
|
35
|
+
*/
|
|
36
|
+
attach(ws: IServerWebSocket): void;
|
|
37
|
+
connect(): Promise<void>;
|
|
38
|
+
disconnect(): Promise<void>;
|
|
39
|
+
getClientType(): string;
|
|
40
|
+
setClientType(clientType: string): void;
|
|
41
|
+
getSubscribedSessions(): ReadonlySet<string>;
|
|
42
|
+
subscribe(sessionId: string): void;
|
|
43
|
+
unsubscribe(sessionId: string): void;
|
|
44
|
+
isSubscribedTo(sessionId: string): boolean;
|
|
45
|
+
publishToSession(sessionId: string, message: string): void;
|
|
46
|
+
getHandlerContext(): ServerHandlerContext;
|
|
47
|
+
private setupServerWebSocket;
|
|
48
|
+
}
|
|
49
|
+
export declare function createServerConnection<TReceive extends ProtocolDef, TSend extends ProtocolDef>(config: ServerConnectionConfig<TReceive, TSend>): ServerConnection<TReceive, TSend>;
|
|
50
|
+
//# sourceMappingURL=server-connection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-connection.d.ts","sourceRoot":"","sources":["../../src/server/server-connection.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAClD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACtE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAG5D;;GAEG;AACH,MAAM,WAAW,sBAAsB,CAAC,QAAQ,SAAS,WAAW,EAAE,KAAK,SAAS,WAAW,CAAE,SAAQ,gBAAgB,CAAC,QAAQ,EAAE,KAAK,CAAC;IACzI,YAAY,CAAC,EAAE,MAAM,CAAA;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAqB,SAAQ,cAAc;IAC3D,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,kBAAkB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;CAC/B;AAED;;GAEG;AACH,qBAAa,gBAAgB,CAAC,QAAQ,SAAS,WAAW,EAAE,KAAK,SAAS,WAAW,CAAE,SAAQ,UAAU,CAAC,QAAQ,EAAE,KAAK,CAAC;IACzH,OAAO,CAAC,QAAQ,CAAgC;IAChD,OAAO,CAAC,UAAU,CAAoB;IACtC,OAAO,CAAC,kBAAkB,CAAoB;gBAElC,MAAM,EAAE,sBAAsB,CAAC,QAAQ,EAAE,KAAK,CAAC;IAO3D;;;OAGG;IACH,MAAM,CAAC,EAAE,EAAE,gBAAgB,GAAG,IAAI;IAM5B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAIxB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAYjC,aAAa,IAAI,MAAM;IAIvB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAIvC,qBAAqB,IAAI,WAAW,CAAC,MAAM,CAAC;IAI5C,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAKlC,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAKpC,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAI1C,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAI1D,iBAAiB,IAAI,oBAAoB;IASzC,OAAO,CAAC,oBAAoB;CAO5B;AAED,wBAAgB,sBAAsB,CAAC,QAAQ,SAAS,WAAW,EAAE,KAAK,SAAS,WAAW,EAC7F,MAAM,EAAE,sBAAsB,CAAC,QAAQ,EAAE,KAAK,CAAC,GAC7C,gBAAgB,CAAC,QAAQ,EAAE,KAAK,CAAC,CAEnC"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server Connection
|
|
3
|
+
*
|
|
4
|
+
* Represents a single client connection on the server side.
|
|
5
|
+
* Simplified: no handshake - connection is ready immediately when attached.
|
|
6
|
+
*/
|
|
7
|
+
import { Connection } from '../core/connection.js';
|
|
8
|
+
import { WebSocketReadyState } from '../platform/types.js';
|
|
9
|
+
/**
|
|
10
|
+
* Server-side WebSocket connection representing a single client.
|
|
11
|
+
*/
|
|
12
|
+
export class ServerConnection extends Connection {
|
|
13
|
+
serverWs = null;
|
|
14
|
+
clientType = 'unknown';
|
|
15
|
+
subscribedSessions = new Set();
|
|
16
|
+
constructor(config) {
|
|
17
|
+
super(config);
|
|
18
|
+
if (config.connectionId) {
|
|
19
|
+
this.connectionId = config.connectionId;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Attach an already-accepted WebSocket connection.
|
|
24
|
+
* Connection is immediately ready - no handshake needed.
|
|
25
|
+
*/
|
|
26
|
+
attach(ws) {
|
|
27
|
+
this.serverWs = ws;
|
|
28
|
+
this.setupServerWebSocket(ws);
|
|
29
|
+
this.setState('connected');
|
|
30
|
+
}
|
|
31
|
+
async connect() {
|
|
32
|
+
throw new Error('Server connections use attach() instead of connect()');
|
|
33
|
+
}
|
|
34
|
+
async disconnect() {
|
|
35
|
+
this.cleanup();
|
|
36
|
+
if (this.serverWs && this.serverWs.readyState !== WebSocketReadyState.CLOSED) {
|
|
37
|
+
this.serverWs.close(1000, 'Server disconnect');
|
|
38
|
+
}
|
|
39
|
+
this.serverWs = null;
|
|
40
|
+
this.ws = null;
|
|
41
|
+
this.setState('disconnected');
|
|
42
|
+
}
|
|
43
|
+
getClientType() {
|
|
44
|
+
return this.clientType;
|
|
45
|
+
}
|
|
46
|
+
setClientType(clientType) {
|
|
47
|
+
this.clientType = clientType;
|
|
48
|
+
}
|
|
49
|
+
getSubscribedSessions() {
|
|
50
|
+
return this.subscribedSessions;
|
|
51
|
+
}
|
|
52
|
+
subscribe(sessionId) {
|
|
53
|
+
this.subscribedSessions.add(sessionId);
|
|
54
|
+
this.serverWs?.subscribe(`session:${sessionId}`);
|
|
55
|
+
}
|
|
56
|
+
unsubscribe(sessionId) {
|
|
57
|
+
this.subscribedSessions.delete(sessionId);
|
|
58
|
+
this.serverWs?.unsubscribe(`session:${sessionId}`);
|
|
59
|
+
}
|
|
60
|
+
isSubscribedTo(sessionId) {
|
|
61
|
+
return this.subscribedSessions.has(sessionId);
|
|
62
|
+
}
|
|
63
|
+
publishToSession(sessionId, message) {
|
|
64
|
+
this.serverWs?.publish(`session:${sessionId}`, message);
|
|
65
|
+
}
|
|
66
|
+
getHandlerContext() {
|
|
67
|
+
return {
|
|
68
|
+
connectionId: this.connectionId,
|
|
69
|
+
clientType: this.clientType,
|
|
70
|
+
subscribedSessions: this.subscribedSessions,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
// Use server context for handlers
|
|
74
|
+
setupServerWebSocket(ws) {
|
|
75
|
+
this.ws = ws;
|
|
76
|
+
this.router.setSender((message) => this.send(message));
|
|
77
|
+
ws.onmessage = (data) => this.router.handleMessage(data, this.getHandlerContext());
|
|
78
|
+
ws.onerror = (error) => this.emit('error', error);
|
|
79
|
+
ws.onclose = (event) => this.handleClose(event.code, event.reason);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
export function createServerConnection(config) {
|
|
83
|
+
return new ServerConnection(config);
|
|
84
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@roj-ai/transport",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./src/index.ts",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"import": "./src/index.ts",
|
|
10
|
+
"default": "./src/index.ts"
|
|
11
|
+
},
|
|
12
|
+
"./client": {
|
|
13
|
+
"types": "./dist/client/index.d.ts",
|
|
14
|
+
"import": "./src/client/index.ts",
|
|
15
|
+
"default": "./src/client/index.ts"
|
|
16
|
+
},
|
|
17
|
+
"./server": {
|
|
18
|
+
"types": "./dist/server/index.d.ts",
|
|
19
|
+
"import": "./src/server/index.ts",
|
|
20
|
+
"default": "./src/server/index.ts"
|
|
21
|
+
},
|
|
22
|
+
"./browser": {
|
|
23
|
+
"types": "./dist/platform/browser.d.ts",
|
|
24
|
+
"import": "./src/platform/browser.ts",
|
|
25
|
+
"default": "./src/platform/browser.ts"
|
|
26
|
+
},
|
|
27
|
+
"./bun": {
|
|
28
|
+
"types": "./dist/platform/bun.d.ts",
|
|
29
|
+
"import": "./src/platform/bun.ts",
|
|
30
|
+
"default": "./src/platform/bun.ts"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"files": [
|
|
34
|
+
"src",
|
|
35
|
+
"dist"
|
|
36
|
+
],
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"access": "public"
|
|
39
|
+
},
|
|
40
|
+
"scripts": {
|
|
41
|
+
"build": "tsc",
|
|
42
|
+
"type-check": "tsc --noEmit"
|
|
43
|
+
},
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"zod": "4.3.6"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@types/bun": "latest",
|
|
49
|
+
"typescript": "^5.7.2"
|
|
50
|
+
},
|
|
51
|
+
"types": "./dist/index.d.ts"
|
|
52
|
+
}
|