@agentxjs/network 0.2.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/dist/browser-qLiqDF2b.d.cts +56 -0
- package/dist/browser-qLiqDF2b.d.ts +56 -0
- package/dist/browser.cjs +308 -0
- package/dist/browser.cjs.map +1 -0
- package/dist/browser.d.cts +2 -0
- package/dist/browser.d.ts +2 -0
- package/dist/browser.js +9 -0
- package/dist/browser.js.map +1 -0
- package/dist/chunk-63P5VUHB.js +275 -0
- package/dist/chunk-63P5VUHB.js.map +1 -0
- package/dist/index.cjs +491 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +28 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +192 -0
- package/dist/index.js.map +1 -0
- package/package.json +60 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { ChannelClient, ChannelClientOptions, Unsubscribe } from '@agentxjs/types/network';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* WebSocket Client implementation of ChannelClient
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* WebSocket Client (Node.js version - no auto-reconnect)
|
|
9
|
+
*/
|
|
10
|
+
declare class WebSocketClient implements ChannelClient {
|
|
11
|
+
private ws;
|
|
12
|
+
private serverUrl;
|
|
13
|
+
private messageHandlers;
|
|
14
|
+
private openHandlers;
|
|
15
|
+
private closeHandlers;
|
|
16
|
+
private errorHandlers;
|
|
17
|
+
constructor(options: ChannelClientOptions);
|
|
18
|
+
get readyState(): "connecting" | "open" | "closing" | "closed";
|
|
19
|
+
connect(): Promise<void>;
|
|
20
|
+
send(message: string): void;
|
|
21
|
+
onMessage(handler: (message: string) => void): Unsubscribe;
|
|
22
|
+
onOpen(handler: () => void): Unsubscribe;
|
|
23
|
+
onClose(handler: () => void): Unsubscribe;
|
|
24
|
+
onError(handler: (error: Error) => void): Unsubscribe;
|
|
25
|
+
close(): void;
|
|
26
|
+
dispose(): void;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Browser WebSocket Client with auto-reconnect
|
|
30
|
+
*/
|
|
31
|
+
declare class BrowserWebSocketClient implements ChannelClient {
|
|
32
|
+
private ws;
|
|
33
|
+
private serverUrl;
|
|
34
|
+
private options;
|
|
35
|
+
private messageHandlers;
|
|
36
|
+
private openHandlers;
|
|
37
|
+
private closeHandlers;
|
|
38
|
+
private errorHandlers;
|
|
39
|
+
private hasConnectedBefore;
|
|
40
|
+
constructor(options: ChannelClientOptions);
|
|
41
|
+
get readyState(): "connecting" | "open" | "closing" | "closed";
|
|
42
|
+
connect(): Promise<void>;
|
|
43
|
+
send(message: string): void;
|
|
44
|
+
onMessage(handler: (message: string) => void): Unsubscribe;
|
|
45
|
+
onOpen(handler: () => void): Unsubscribe;
|
|
46
|
+
onClose(handler: () => void): Unsubscribe;
|
|
47
|
+
onError(handler: (error: Error) => void): Unsubscribe;
|
|
48
|
+
close(): void;
|
|
49
|
+
dispose(): void;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Factory function to create the appropriate WebSocket client
|
|
53
|
+
*/
|
|
54
|
+
declare function createWebSocketClient(options: ChannelClientOptions): Promise<ChannelClient>;
|
|
55
|
+
|
|
56
|
+
export { BrowserWebSocketClient as B, WebSocketClient as W, createWebSocketClient as c };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { ChannelClient, ChannelClientOptions, Unsubscribe } from '@agentxjs/types/network';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* WebSocket Client implementation of ChannelClient
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* WebSocket Client (Node.js version - no auto-reconnect)
|
|
9
|
+
*/
|
|
10
|
+
declare class WebSocketClient implements ChannelClient {
|
|
11
|
+
private ws;
|
|
12
|
+
private serverUrl;
|
|
13
|
+
private messageHandlers;
|
|
14
|
+
private openHandlers;
|
|
15
|
+
private closeHandlers;
|
|
16
|
+
private errorHandlers;
|
|
17
|
+
constructor(options: ChannelClientOptions);
|
|
18
|
+
get readyState(): "connecting" | "open" | "closing" | "closed";
|
|
19
|
+
connect(): Promise<void>;
|
|
20
|
+
send(message: string): void;
|
|
21
|
+
onMessage(handler: (message: string) => void): Unsubscribe;
|
|
22
|
+
onOpen(handler: () => void): Unsubscribe;
|
|
23
|
+
onClose(handler: () => void): Unsubscribe;
|
|
24
|
+
onError(handler: (error: Error) => void): Unsubscribe;
|
|
25
|
+
close(): void;
|
|
26
|
+
dispose(): void;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Browser WebSocket Client with auto-reconnect
|
|
30
|
+
*/
|
|
31
|
+
declare class BrowserWebSocketClient implements ChannelClient {
|
|
32
|
+
private ws;
|
|
33
|
+
private serverUrl;
|
|
34
|
+
private options;
|
|
35
|
+
private messageHandlers;
|
|
36
|
+
private openHandlers;
|
|
37
|
+
private closeHandlers;
|
|
38
|
+
private errorHandlers;
|
|
39
|
+
private hasConnectedBefore;
|
|
40
|
+
constructor(options: ChannelClientOptions);
|
|
41
|
+
get readyState(): "connecting" | "open" | "closing" | "closed";
|
|
42
|
+
connect(): Promise<void>;
|
|
43
|
+
send(message: string): void;
|
|
44
|
+
onMessage(handler: (message: string) => void): Unsubscribe;
|
|
45
|
+
onOpen(handler: () => void): Unsubscribe;
|
|
46
|
+
onClose(handler: () => void): Unsubscribe;
|
|
47
|
+
onError(handler: (error: Error) => void): Unsubscribe;
|
|
48
|
+
close(): void;
|
|
49
|
+
dispose(): void;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Factory function to create the appropriate WebSocket client
|
|
53
|
+
*/
|
|
54
|
+
declare function createWebSocketClient(options: ChannelClientOptions): Promise<ChannelClient>;
|
|
55
|
+
|
|
56
|
+
export { BrowserWebSocketClient as B, WebSocketClient as W, createWebSocketClient as c };
|
package/dist/browser.cjs
ADDED
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
9
|
+
var __export = (target, all) => {
|
|
10
|
+
for (var name in all)
|
|
11
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
12
|
+
};
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from))
|
|
16
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
17
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
18
|
+
}
|
|
19
|
+
return to;
|
|
20
|
+
};
|
|
21
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
22
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
23
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
24
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
25
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
26
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
27
|
+
mod
|
|
28
|
+
));
|
|
29
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
30
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
31
|
+
|
|
32
|
+
// src/browser.ts
|
|
33
|
+
var browser_exports = {};
|
|
34
|
+
__export(browser_exports, {
|
|
35
|
+
BrowserWebSocketClient: () => BrowserWebSocketClient,
|
|
36
|
+
createWebSocketClient: () => createWebSocketClient
|
|
37
|
+
});
|
|
38
|
+
module.exports = __toCommonJS(browser_exports);
|
|
39
|
+
|
|
40
|
+
// src/WebSocketClient.ts
|
|
41
|
+
var import_common = require("@agentxjs/common");
|
|
42
|
+
var logger = (0, import_common.createLogger)("network/WebSocketClient");
|
|
43
|
+
var isBrowser = typeof globalThis !== "undefined" && typeof globalThis.window !== "undefined" && typeof globalThis.window.WebSocket !== "undefined";
|
|
44
|
+
var WebSocketClient = class {
|
|
45
|
+
constructor(options) {
|
|
46
|
+
__publicField(this, "ws", null);
|
|
47
|
+
__publicField(this, "serverUrl");
|
|
48
|
+
__publicField(this, "messageHandlers", /* @__PURE__ */ new Set());
|
|
49
|
+
__publicField(this, "openHandlers", /* @__PURE__ */ new Set());
|
|
50
|
+
__publicField(this, "closeHandlers", /* @__PURE__ */ new Set());
|
|
51
|
+
__publicField(this, "errorHandlers", /* @__PURE__ */ new Set());
|
|
52
|
+
if (isBrowser) {
|
|
53
|
+
throw new Error(
|
|
54
|
+
"Use createBrowserWebSocketClient() in browser environment for auto-reconnect support"
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
this.serverUrl = options.serverUrl;
|
|
58
|
+
}
|
|
59
|
+
get readyState() {
|
|
60
|
+
if (!this.ws) return "closed";
|
|
61
|
+
const state = this.ws.readyState;
|
|
62
|
+
if (state === 0) return "connecting";
|
|
63
|
+
if (state === 1) return "open";
|
|
64
|
+
if (state === 2) return "closing";
|
|
65
|
+
return "closed";
|
|
66
|
+
}
|
|
67
|
+
async connect() {
|
|
68
|
+
if (this.ws) {
|
|
69
|
+
throw new Error("Already connected or connecting");
|
|
70
|
+
}
|
|
71
|
+
const { WebSocket: NodeWebSocket } = await import("ws");
|
|
72
|
+
this.ws = new NodeWebSocket(this.serverUrl);
|
|
73
|
+
return new Promise((resolve, reject) => {
|
|
74
|
+
const onOpen = () => {
|
|
75
|
+
logger.info("WebSocket connected", { serverUrl: this.serverUrl });
|
|
76
|
+
for (const handler of this.openHandlers) {
|
|
77
|
+
handler();
|
|
78
|
+
}
|
|
79
|
+
resolve();
|
|
80
|
+
};
|
|
81
|
+
const onError = (err) => {
|
|
82
|
+
logger.error("WebSocket connection failed", {
|
|
83
|
+
serverUrl: this.serverUrl,
|
|
84
|
+
error: err?.message
|
|
85
|
+
});
|
|
86
|
+
reject(err || new Error("WebSocket connection failed"));
|
|
87
|
+
};
|
|
88
|
+
this.ws.once("open", onOpen);
|
|
89
|
+
this.ws.once("error", onError);
|
|
90
|
+
this.ws.on("message", (data) => {
|
|
91
|
+
const message = data.toString();
|
|
92
|
+
for (const handler of this.messageHandlers) {
|
|
93
|
+
handler(message);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
this.ws.on("close", () => {
|
|
97
|
+
logger.warn("WebSocket closed");
|
|
98
|
+
for (const handler of this.closeHandlers) {
|
|
99
|
+
handler();
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
this.ws.on("error", (err) => {
|
|
103
|
+
logger.error("WebSocket error", { error: err.message });
|
|
104
|
+
for (const handler of this.errorHandlers) {
|
|
105
|
+
handler(err);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
send(message) {
|
|
111
|
+
if (!this.ws || this.ws.readyState !== 1) {
|
|
112
|
+
throw new Error("WebSocket is not open");
|
|
113
|
+
}
|
|
114
|
+
this.ws.send(message);
|
|
115
|
+
}
|
|
116
|
+
onMessage(handler) {
|
|
117
|
+
this.messageHandlers.add(handler);
|
|
118
|
+
return () => {
|
|
119
|
+
this.messageHandlers.delete(handler);
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
onOpen(handler) {
|
|
123
|
+
this.openHandlers.add(handler);
|
|
124
|
+
return () => {
|
|
125
|
+
this.openHandlers.delete(handler);
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
onClose(handler) {
|
|
129
|
+
this.closeHandlers.add(handler);
|
|
130
|
+
return () => {
|
|
131
|
+
this.closeHandlers.delete(handler);
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
onError(handler) {
|
|
135
|
+
this.errorHandlers.add(handler);
|
|
136
|
+
return () => {
|
|
137
|
+
this.errorHandlers.delete(handler);
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
close() {
|
|
141
|
+
if (this.ws) {
|
|
142
|
+
this.ws.close();
|
|
143
|
+
this.ws = null;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
dispose() {
|
|
147
|
+
this.close();
|
|
148
|
+
this.messageHandlers.clear();
|
|
149
|
+
this.openHandlers.clear();
|
|
150
|
+
this.closeHandlers.clear();
|
|
151
|
+
this.errorHandlers.clear();
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
var BrowserWebSocketClient = class {
|
|
155
|
+
// Track if this is a reconnection
|
|
156
|
+
constructor(options) {
|
|
157
|
+
__publicField(this, "ws", null);
|
|
158
|
+
__publicField(this, "serverUrl");
|
|
159
|
+
__publicField(this, "options");
|
|
160
|
+
__publicField(this, "messageHandlers", /* @__PURE__ */ new Set());
|
|
161
|
+
__publicField(this, "openHandlers", /* @__PURE__ */ new Set());
|
|
162
|
+
__publicField(this, "closeHandlers", /* @__PURE__ */ new Set());
|
|
163
|
+
__publicField(this, "errorHandlers", /* @__PURE__ */ new Set());
|
|
164
|
+
__publicField(this, "hasConnectedBefore", false);
|
|
165
|
+
if (!isBrowser) {
|
|
166
|
+
throw new Error("BrowserWebSocketClient can only be used in browser environment");
|
|
167
|
+
}
|
|
168
|
+
this.serverUrl = options.serverUrl;
|
|
169
|
+
this.options = {
|
|
170
|
+
autoReconnect: true,
|
|
171
|
+
minReconnectionDelay: 1e3,
|
|
172
|
+
maxReconnectionDelay: 1e4,
|
|
173
|
+
maxRetries: Infinity,
|
|
174
|
+
connectionTimeout: 4e3,
|
|
175
|
+
debug: false,
|
|
176
|
+
...options
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
get readyState() {
|
|
180
|
+
if (!this.ws) return "closed";
|
|
181
|
+
const state = this.ws.readyState;
|
|
182
|
+
if (state === 0) return "connecting";
|
|
183
|
+
if (state === 1) return "open";
|
|
184
|
+
if (state === 2) return "closing";
|
|
185
|
+
return "closed";
|
|
186
|
+
}
|
|
187
|
+
async connect() {
|
|
188
|
+
if (this.ws) {
|
|
189
|
+
throw new Error("Already connected or connecting");
|
|
190
|
+
}
|
|
191
|
+
if (this.options.autoReconnect) {
|
|
192
|
+
const ReconnectingWebSocket = (await import("reconnecting-websocket")).default;
|
|
193
|
+
this.ws = new ReconnectingWebSocket(this.serverUrl, [], {
|
|
194
|
+
maxReconnectionDelay: this.options.maxReconnectionDelay,
|
|
195
|
+
minReconnectionDelay: this.options.minReconnectionDelay,
|
|
196
|
+
reconnectionDelayGrowFactor: 1.3,
|
|
197
|
+
connectionTimeout: this.options.connectionTimeout,
|
|
198
|
+
maxRetries: this.options.maxRetries,
|
|
199
|
+
debug: this.options.debug
|
|
200
|
+
});
|
|
201
|
+
} else {
|
|
202
|
+
this.ws = new WebSocket(this.serverUrl);
|
|
203
|
+
}
|
|
204
|
+
return new Promise((resolve, reject) => {
|
|
205
|
+
const onOpen = () => {
|
|
206
|
+
if (this.hasConnectedBefore) {
|
|
207
|
+
logger.info("WebSocket reconnected successfully", { serverUrl: this.serverUrl });
|
|
208
|
+
} else {
|
|
209
|
+
logger.info("WebSocket connected", { serverUrl: this.serverUrl });
|
|
210
|
+
this.hasConnectedBefore = true;
|
|
211
|
+
}
|
|
212
|
+
for (const handler of this.openHandlers) {
|
|
213
|
+
handler();
|
|
214
|
+
}
|
|
215
|
+
resolve();
|
|
216
|
+
};
|
|
217
|
+
const onError = (_event) => {
|
|
218
|
+
logger.error("WebSocket connection failed", { serverUrl: this.serverUrl });
|
|
219
|
+
const error = new Error("WebSocket connection failed");
|
|
220
|
+
for (const handler of this.errorHandlers) {
|
|
221
|
+
handler(error);
|
|
222
|
+
}
|
|
223
|
+
reject(error);
|
|
224
|
+
};
|
|
225
|
+
this.ws.addEventListener("open", onOpen, { once: true });
|
|
226
|
+
this.ws.addEventListener("error", onError, { once: true });
|
|
227
|
+
this.ws.addEventListener("message", ((event) => {
|
|
228
|
+
const message = event.data;
|
|
229
|
+
for (const handler of this.messageHandlers) {
|
|
230
|
+
handler(message);
|
|
231
|
+
}
|
|
232
|
+
}));
|
|
233
|
+
this.ws.addEventListener("close", (() => {
|
|
234
|
+
logger.info("WebSocket closed, attempting to reconnect...");
|
|
235
|
+
for (const handler of this.closeHandlers) {
|
|
236
|
+
handler();
|
|
237
|
+
}
|
|
238
|
+
}));
|
|
239
|
+
this.ws.addEventListener("error", ((_event) => {
|
|
240
|
+
logger.error("WebSocket error");
|
|
241
|
+
const error = new Error("WebSocket error");
|
|
242
|
+
for (const handler of this.errorHandlers) {
|
|
243
|
+
handler(error);
|
|
244
|
+
}
|
|
245
|
+
}));
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
send(message) {
|
|
249
|
+
if (!this.ws || this.ws.readyState !== 1) {
|
|
250
|
+
throw new Error("WebSocket is not open");
|
|
251
|
+
}
|
|
252
|
+
this.ws.send(message);
|
|
253
|
+
}
|
|
254
|
+
onMessage(handler) {
|
|
255
|
+
this.messageHandlers.add(handler);
|
|
256
|
+
return () => {
|
|
257
|
+
this.messageHandlers.delete(handler);
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
onOpen(handler) {
|
|
261
|
+
this.openHandlers.add(handler);
|
|
262
|
+
return () => {
|
|
263
|
+
this.openHandlers.delete(handler);
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
onClose(handler) {
|
|
267
|
+
this.closeHandlers.add(handler);
|
|
268
|
+
return () => {
|
|
269
|
+
this.closeHandlers.delete(handler);
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
onError(handler) {
|
|
273
|
+
this.errorHandlers.add(handler);
|
|
274
|
+
return () => {
|
|
275
|
+
this.errorHandlers.delete(handler);
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
close() {
|
|
279
|
+
if (this.ws) {
|
|
280
|
+
this.ws.close();
|
|
281
|
+
this.ws = null;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
dispose() {
|
|
285
|
+
this.close();
|
|
286
|
+
this.messageHandlers.clear();
|
|
287
|
+
this.openHandlers.clear();
|
|
288
|
+
this.closeHandlers.clear();
|
|
289
|
+
this.errorHandlers.clear();
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
async function createWebSocketClient(options) {
|
|
293
|
+
if (isBrowser) {
|
|
294
|
+
const client = new BrowserWebSocketClient(options);
|
|
295
|
+
await client.connect();
|
|
296
|
+
return client;
|
|
297
|
+
} else {
|
|
298
|
+
const client = new WebSocketClient(options);
|
|
299
|
+
await client.connect();
|
|
300
|
+
return client;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
304
|
+
0 && (module.exports = {
|
|
305
|
+
BrowserWebSocketClient,
|
|
306
|
+
createWebSocketClient
|
|
307
|
+
});
|
|
308
|
+
//# sourceMappingURL=browser.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/browser.ts","../src/WebSocketClient.ts"],"sourcesContent":["/**\n * @agentxjs/network - Network layer abstraction (Browser)\n *\n * Browser-only exports with auto-reconnect support.\n */\n\nexport { BrowserWebSocketClient, createWebSocketClient } from \"./WebSocketClient\";\n\n// Re-export types\nexport type { ChannelClient, ChannelClientOptions, Unsubscribe } from \"@agentxjs/types/network\";\n","/**\n * WebSocket Client implementation of ChannelClient\n */\n\nimport type { ChannelClient, ChannelClientOptions, Unsubscribe } from \"@agentxjs/types/network\";\nimport { createLogger } from \"@agentxjs/common\";\n\nconst logger = createLogger(\"network/WebSocketClient\");\n\n// Detect browser environment\nconst isBrowser =\n typeof globalThis !== \"undefined\" &&\n typeof (globalThis as any).window !== \"undefined\" &&\n typeof (globalThis as any).window.WebSocket !== \"undefined\";\n\n/**\n * WebSocket Client (Node.js version - no auto-reconnect)\n */\nexport class WebSocketClient implements ChannelClient {\n private ws: WebSocket | null = null;\n private serverUrl: string;\n private messageHandlers = new Set<(message: string) => void>();\n private openHandlers = new Set<() => void>();\n private closeHandlers = new Set<() => void>();\n private errorHandlers = new Set<(error: Error) => void>();\n\n constructor(options: ChannelClientOptions) {\n if (isBrowser) {\n throw new Error(\n \"Use createBrowserWebSocketClient() in browser environment for auto-reconnect support\"\n );\n }\n\n this.serverUrl = options.serverUrl;\n }\n\n get readyState(): \"connecting\" | \"open\" | \"closing\" | \"closed\" {\n if (!this.ws) return \"closed\";\n const state = this.ws.readyState;\n if (state === 0) return \"connecting\";\n if (state === 1) return \"open\";\n if (state === 2) return \"closing\";\n return \"closed\";\n }\n\n async connect(): Promise<void> {\n if (this.ws) {\n throw new Error(\"Already connected or connecting\");\n }\n\n const { WebSocket: NodeWebSocket } = await import(\"ws\");\n this.ws = new NodeWebSocket(this.serverUrl) as unknown as WebSocket;\n\n return new Promise<void>((resolve, reject) => {\n const onOpen = () => {\n logger.info(\"WebSocket connected\", { serverUrl: this.serverUrl });\n for (const handler of this.openHandlers) {\n handler();\n }\n resolve();\n };\n\n const onError = (err?: Error) => {\n logger.error(\"WebSocket connection failed\", {\n serverUrl: this.serverUrl,\n error: err?.message,\n });\n reject(err || new Error(\"WebSocket connection failed\"));\n };\n\n (this.ws as any).once(\"open\", onOpen);\n (this.ws as any).once(\"error\", onError);\n\n // Setup permanent handlers\n (this.ws as any).on(\"message\", (data: Buffer) => {\n const message = data.toString();\n for (const handler of this.messageHandlers) {\n handler(message);\n }\n });\n\n (this.ws as any).on(\"close\", () => {\n logger.warn(\"WebSocket closed\");\n for (const handler of this.closeHandlers) {\n handler();\n }\n });\n\n (this.ws as any).on(\"error\", (err: Error) => {\n logger.error(\"WebSocket error\", { error: err.message });\n for (const handler of this.errorHandlers) {\n handler(err);\n }\n });\n });\n }\n\n send(message: string): void {\n if (!this.ws || this.ws.readyState !== 1) {\n throw new Error(\"WebSocket is not open\");\n }\n this.ws.send(message);\n }\n\n onMessage(handler: (message: string) => void): Unsubscribe {\n this.messageHandlers.add(handler);\n return () => {\n this.messageHandlers.delete(handler);\n };\n }\n\n onOpen(handler: () => void): Unsubscribe {\n this.openHandlers.add(handler);\n return () => {\n this.openHandlers.delete(handler);\n };\n }\n\n onClose(handler: () => void): Unsubscribe {\n this.closeHandlers.add(handler);\n return () => {\n this.closeHandlers.delete(handler);\n };\n }\n\n onError(handler: (error: Error) => void): Unsubscribe {\n this.errorHandlers.add(handler);\n return () => {\n this.errorHandlers.delete(handler);\n };\n }\n\n close(): void {\n if (this.ws) {\n this.ws.close();\n this.ws = null;\n }\n }\n\n dispose(): void {\n this.close();\n this.messageHandlers.clear();\n this.openHandlers.clear();\n this.closeHandlers.clear();\n this.errorHandlers.clear();\n }\n}\n\n/**\n * Browser WebSocket Client with auto-reconnect\n */\nexport class BrowserWebSocketClient implements ChannelClient {\n private ws: WebSocket | null = null;\n private serverUrl: string;\n private options: ChannelClientOptions;\n private messageHandlers = new Set<(message: string) => void>();\n private openHandlers = new Set<() => void>();\n private closeHandlers = new Set<() => void>();\n private errorHandlers = new Set<(error: Error) => void>();\n private hasConnectedBefore = false; // Track if this is a reconnection\n\n constructor(options: ChannelClientOptions) {\n if (!isBrowser) {\n throw new Error(\"BrowserWebSocketClient can only be used in browser environment\");\n }\n\n this.serverUrl = options.serverUrl;\n this.options = {\n autoReconnect: true,\n minReconnectionDelay: 1000,\n maxReconnectionDelay: 10000,\n maxRetries: Infinity,\n connectionTimeout: 4000,\n debug: false,\n ...options,\n };\n }\n\n get readyState(): \"connecting\" | \"open\" | \"closing\" | \"closed\" {\n if (!this.ws) return \"closed\";\n const state = this.ws.readyState;\n if (state === 0) return \"connecting\";\n if (state === 1) return \"open\";\n if (state === 2) return \"closing\";\n return \"closed\";\n }\n\n async connect(): Promise<void> {\n if (this.ws) {\n throw new Error(\"Already connected or connecting\");\n }\n\n if (this.options.autoReconnect) {\n // Use reconnecting-websocket for auto-reconnect\n const ReconnectingWebSocket = (await import(\"reconnecting-websocket\")).default;\n this.ws = new ReconnectingWebSocket(this.serverUrl, [], {\n maxReconnectionDelay: this.options.maxReconnectionDelay,\n minReconnectionDelay: this.options.minReconnectionDelay,\n reconnectionDelayGrowFactor: 1.3,\n connectionTimeout: this.options.connectionTimeout,\n maxRetries: this.options.maxRetries,\n debug: this.options.debug,\n });\n } else {\n // Use native WebSocket\n this.ws = new WebSocket(this.serverUrl);\n }\n\n return new Promise<void>((resolve, reject) => {\n const onOpen = () => {\n if (this.hasConnectedBefore) {\n logger.info(\"WebSocket reconnected successfully\", { serverUrl: this.serverUrl });\n } else {\n logger.info(\"WebSocket connected\", { serverUrl: this.serverUrl });\n this.hasConnectedBefore = true;\n }\n for (const handler of this.openHandlers) {\n handler();\n }\n resolve();\n };\n\n const onError = (_event: Event) => {\n logger.error(\"WebSocket connection failed\", { serverUrl: this.serverUrl });\n const error = new Error(\"WebSocket connection failed\");\n for (const handler of this.errorHandlers) {\n handler(error);\n }\n reject(error);\n };\n\n this.ws!.addEventListener(\"open\", onOpen as any, { once: true });\n this.ws!.addEventListener(\"error\", onError as any, { once: true });\n\n // Setup permanent handlers\n this.ws!.addEventListener(\"message\", ((event: any) => {\n const message = event.data;\n for (const handler of this.messageHandlers) {\n handler(message);\n }\n }) as any);\n\n this.ws!.addEventListener(\"close\", (() => {\n logger.info(\"WebSocket closed, attempting to reconnect...\");\n for (const handler of this.closeHandlers) {\n handler();\n }\n }) as any);\n\n this.ws!.addEventListener(\"error\", ((_event: Event) => {\n logger.error(\"WebSocket error\");\n const error = new Error(\"WebSocket error\");\n for (const handler of this.errorHandlers) {\n handler(error);\n }\n }) as any);\n });\n }\n\n send(message: string): void {\n if (!this.ws || this.ws.readyState !== 1) {\n throw new Error(\"WebSocket is not open\");\n }\n this.ws.send(message);\n }\n\n onMessage(handler: (message: string) => void): Unsubscribe {\n this.messageHandlers.add(handler);\n return () => {\n this.messageHandlers.delete(handler);\n };\n }\n\n onOpen(handler: () => void): Unsubscribe {\n this.openHandlers.add(handler);\n return () => {\n this.openHandlers.delete(handler);\n };\n }\n\n onClose(handler: () => void): Unsubscribe {\n this.closeHandlers.add(handler);\n return () => {\n this.closeHandlers.delete(handler);\n };\n }\n\n onError(handler: (error: Error) => void): Unsubscribe {\n this.errorHandlers.add(handler);\n return () => {\n this.errorHandlers.delete(handler);\n };\n }\n\n close(): void {\n if (this.ws) {\n this.ws.close();\n this.ws = null;\n }\n }\n\n dispose(): void {\n this.close();\n this.messageHandlers.clear();\n this.openHandlers.clear();\n this.closeHandlers.clear();\n this.errorHandlers.clear();\n }\n}\n\n/**\n * Factory function to create the appropriate WebSocket client\n */\nexport async function createWebSocketClient(options: ChannelClientOptions): Promise<ChannelClient> {\n if (isBrowser) {\n const client = new BrowserWebSocketClient(options);\n await client.connect();\n return client;\n } else {\n const client = new WebSocketClient(options);\n await client.connect();\n return client;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACKA,oBAA6B;AAE7B,IAAM,aAAS,4BAAa,yBAAyB;AAGrD,IAAM,YACJ,OAAO,eAAe,eACtB,OAAQ,WAAmB,WAAW,eACtC,OAAQ,WAAmB,OAAO,cAAc;AAK3C,IAAM,kBAAN,MAA+C;AAAA,EAQpD,YAAY,SAA+B;AAP3C,wBAAQ,MAAuB;AAC/B,wBAAQ;AACR,wBAAQ,mBAAkB,oBAAI,IAA+B;AAC7D,wBAAQ,gBAAe,oBAAI,IAAgB;AAC3C,wBAAQ,iBAAgB,oBAAI,IAAgB;AAC5C,wBAAQ,iBAAgB,oBAAI,IAA4B;AAGtD,QAAI,WAAW;AACb,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,SAAK,YAAY,QAAQ;AAAA,EAC3B;AAAA,EAEA,IAAI,aAA2D;AAC7D,QAAI,CAAC,KAAK,GAAI,QAAO;AACrB,UAAM,QAAQ,KAAK,GAAG;AACtB,QAAI,UAAU,EAAG,QAAO;AACxB,QAAI,UAAU,EAAG,QAAO;AACxB,QAAI,UAAU,EAAG,QAAO;AACxB,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,UAAyB;AAC7B,QAAI,KAAK,IAAI;AACX,YAAM,IAAI,MAAM,iCAAiC;AAAA,IACnD;AAEA,UAAM,EAAE,WAAW,cAAc,IAAI,MAAM,OAAO,IAAI;AACtD,SAAK,KAAK,IAAI,cAAc,KAAK,SAAS;AAE1C,WAAO,IAAI,QAAc,CAAC,SAAS,WAAW;AAC5C,YAAM,SAAS,MAAM;AACnB,eAAO,KAAK,uBAAuB,EAAE,WAAW,KAAK,UAAU,CAAC;AAChE,mBAAW,WAAW,KAAK,cAAc;AACvC,kBAAQ;AAAA,QACV;AACA,gBAAQ;AAAA,MACV;AAEA,YAAM,UAAU,CAAC,QAAgB;AAC/B,eAAO,MAAM,+BAA+B;AAAA,UAC1C,WAAW,KAAK;AAAA,UAChB,OAAO,KAAK;AAAA,QACd,CAAC;AACD,eAAO,OAAO,IAAI,MAAM,6BAA6B,CAAC;AAAA,MACxD;AAEA,MAAC,KAAK,GAAW,KAAK,QAAQ,MAAM;AACpC,MAAC,KAAK,GAAW,KAAK,SAAS,OAAO;AAGtC,MAAC,KAAK,GAAW,GAAG,WAAW,CAAC,SAAiB;AAC/C,cAAM,UAAU,KAAK,SAAS;AAC9B,mBAAW,WAAW,KAAK,iBAAiB;AAC1C,kBAAQ,OAAO;AAAA,QACjB;AAAA,MACF,CAAC;AAED,MAAC,KAAK,GAAW,GAAG,SAAS,MAAM;AACjC,eAAO,KAAK,kBAAkB;AAC9B,mBAAW,WAAW,KAAK,eAAe;AACxC,kBAAQ;AAAA,QACV;AAAA,MACF,CAAC;AAED,MAAC,KAAK,GAAW,GAAG,SAAS,CAAC,QAAe;AAC3C,eAAO,MAAM,mBAAmB,EAAE,OAAO,IAAI,QAAQ,CAAC;AACtD,mBAAW,WAAW,KAAK,eAAe;AACxC,kBAAQ,GAAG;AAAA,QACb;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA,EAEA,KAAK,SAAuB;AAC1B,QAAI,CAAC,KAAK,MAAM,KAAK,GAAG,eAAe,GAAG;AACxC,YAAM,IAAI,MAAM,uBAAuB;AAAA,IACzC;AACA,SAAK,GAAG,KAAK,OAAO;AAAA,EACtB;AAAA,EAEA,UAAU,SAAiD;AACzD,SAAK,gBAAgB,IAAI,OAAO;AAChC,WAAO,MAAM;AACX,WAAK,gBAAgB,OAAO,OAAO;AAAA,IACrC;AAAA,EACF;AAAA,EAEA,OAAO,SAAkC;AACvC,SAAK,aAAa,IAAI,OAAO;AAC7B,WAAO,MAAM;AACX,WAAK,aAAa,OAAO,OAAO;AAAA,IAClC;AAAA,EACF;AAAA,EAEA,QAAQ,SAAkC;AACxC,SAAK,cAAc,IAAI,OAAO;AAC9B,WAAO,MAAM;AACX,WAAK,cAAc,OAAO,OAAO;AAAA,IACnC;AAAA,EACF;AAAA,EAEA,QAAQ,SAA8C;AACpD,SAAK,cAAc,IAAI,OAAO;AAC9B,WAAO,MAAM;AACX,WAAK,cAAc,OAAO,OAAO;AAAA,IACnC;AAAA,EACF;AAAA,EAEA,QAAc;AACZ,QAAI,KAAK,IAAI;AACX,WAAK,GAAG,MAAM;AACd,WAAK,KAAK;AAAA,IACZ;AAAA,EACF;AAAA,EAEA,UAAgB;AACd,SAAK,MAAM;AACX,SAAK,gBAAgB,MAAM;AAC3B,SAAK,aAAa,MAAM;AACxB,SAAK,cAAc,MAAM;AACzB,SAAK,cAAc,MAAM;AAAA,EAC3B;AACF;AAKO,IAAM,yBAAN,MAAsD;AAAA;AAAA,EAU3D,YAAY,SAA+B;AAT3C,wBAAQ,MAAuB;AAC/B,wBAAQ;AACR,wBAAQ;AACR,wBAAQ,mBAAkB,oBAAI,IAA+B;AAC7D,wBAAQ,gBAAe,oBAAI,IAAgB;AAC3C,wBAAQ,iBAAgB,oBAAI,IAAgB;AAC5C,wBAAQ,iBAAgB,oBAAI,IAA4B;AACxD,wBAAQ,sBAAqB;AAG3B,QAAI,CAAC,WAAW;AACd,YAAM,IAAI,MAAM,gEAAgE;AAAA,IAClF;AAEA,SAAK,YAAY,QAAQ;AACzB,SAAK,UAAU;AAAA,MACb,eAAe;AAAA,MACf,sBAAsB;AAAA,MACtB,sBAAsB;AAAA,MACtB,YAAY;AAAA,MACZ,mBAAmB;AAAA,MACnB,OAAO;AAAA,MACP,GAAG;AAAA,IACL;AAAA,EACF;AAAA,EAEA,IAAI,aAA2D;AAC7D,QAAI,CAAC,KAAK,GAAI,QAAO;AACrB,UAAM,QAAQ,KAAK,GAAG;AACtB,QAAI,UAAU,EAAG,QAAO;AACxB,QAAI,UAAU,EAAG,QAAO;AACxB,QAAI,UAAU,EAAG,QAAO;AACxB,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,UAAyB;AAC7B,QAAI,KAAK,IAAI;AACX,YAAM,IAAI,MAAM,iCAAiC;AAAA,IACnD;AAEA,QAAI,KAAK,QAAQ,eAAe;AAE9B,YAAM,yBAAyB,MAAM,OAAO,wBAAwB,GAAG;AACvE,WAAK,KAAK,IAAI,sBAAsB,KAAK,WAAW,CAAC,GAAG;AAAA,QACtD,sBAAsB,KAAK,QAAQ;AAAA,QACnC,sBAAsB,KAAK,QAAQ;AAAA,QACnC,6BAA6B;AAAA,QAC7B,mBAAmB,KAAK,QAAQ;AAAA,QAChC,YAAY,KAAK,QAAQ;AAAA,QACzB,OAAO,KAAK,QAAQ;AAAA,MACtB,CAAC;AAAA,IACH,OAAO;AAEL,WAAK,KAAK,IAAI,UAAU,KAAK,SAAS;AAAA,IACxC;AAEA,WAAO,IAAI,QAAc,CAAC,SAAS,WAAW;AAC5C,YAAM,SAAS,MAAM;AACnB,YAAI,KAAK,oBAAoB;AAC3B,iBAAO,KAAK,sCAAsC,EAAE,WAAW,KAAK,UAAU,CAAC;AAAA,QACjF,OAAO;AACL,iBAAO,KAAK,uBAAuB,EAAE,WAAW,KAAK,UAAU,CAAC;AAChE,eAAK,qBAAqB;AAAA,QAC5B;AACA,mBAAW,WAAW,KAAK,cAAc;AACvC,kBAAQ;AAAA,QACV;AACA,gBAAQ;AAAA,MACV;AAEA,YAAM,UAAU,CAAC,WAAkB;AACjC,eAAO,MAAM,+BAA+B,EAAE,WAAW,KAAK,UAAU,CAAC;AACzE,cAAM,QAAQ,IAAI,MAAM,6BAA6B;AACrD,mBAAW,WAAW,KAAK,eAAe;AACxC,kBAAQ,KAAK;AAAA,QACf;AACA,eAAO,KAAK;AAAA,MACd;AAEA,WAAK,GAAI,iBAAiB,QAAQ,QAAe,EAAE,MAAM,KAAK,CAAC;AAC/D,WAAK,GAAI,iBAAiB,SAAS,SAAgB,EAAE,MAAM,KAAK,CAAC;AAGjE,WAAK,GAAI,iBAAiB,YAAY,CAAC,UAAe;AACpD,cAAM,UAAU,MAAM;AACtB,mBAAW,WAAW,KAAK,iBAAiB;AAC1C,kBAAQ,OAAO;AAAA,QACjB;AAAA,MACF,EAAS;AAET,WAAK,GAAI,iBAAiB,UAAU,MAAM;AACxC,eAAO,KAAK,8CAA8C;AAC1D,mBAAW,WAAW,KAAK,eAAe;AACxC,kBAAQ;AAAA,QACV;AAAA,MACF,EAAS;AAET,WAAK,GAAI,iBAAiB,UAAU,CAAC,WAAkB;AACrD,eAAO,MAAM,iBAAiB;AAC9B,cAAM,QAAQ,IAAI,MAAM,iBAAiB;AACzC,mBAAW,WAAW,KAAK,eAAe;AACxC,kBAAQ,KAAK;AAAA,QACf;AAAA,MACF,EAAS;AAAA,IACX,CAAC;AAAA,EACH;AAAA,EAEA,KAAK,SAAuB;AAC1B,QAAI,CAAC,KAAK,MAAM,KAAK,GAAG,eAAe,GAAG;AACxC,YAAM,IAAI,MAAM,uBAAuB;AAAA,IACzC;AACA,SAAK,GAAG,KAAK,OAAO;AAAA,EACtB;AAAA,EAEA,UAAU,SAAiD;AACzD,SAAK,gBAAgB,IAAI,OAAO;AAChC,WAAO,MAAM;AACX,WAAK,gBAAgB,OAAO,OAAO;AAAA,IACrC;AAAA,EACF;AAAA,EAEA,OAAO,SAAkC;AACvC,SAAK,aAAa,IAAI,OAAO;AAC7B,WAAO,MAAM;AACX,WAAK,aAAa,OAAO,OAAO;AAAA,IAClC;AAAA,EACF;AAAA,EAEA,QAAQ,SAAkC;AACxC,SAAK,cAAc,IAAI,OAAO;AAC9B,WAAO,MAAM;AACX,WAAK,cAAc,OAAO,OAAO;AAAA,IACnC;AAAA,EACF;AAAA,EAEA,QAAQ,SAA8C;AACpD,SAAK,cAAc,IAAI,OAAO;AAC9B,WAAO,MAAM;AACX,WAAK,cAAc,OAAO,OAAO;AAAA,IACnC;AAAA,EACF;AAAA,EAEA,QAAc;AACZ,QAAI,KAAK,IAAI;AACX,WAAK,GAAG,MAAM;AACd,WAAK,KAAK;AAAA,IACZ;AAAA,EACF;AAAA,EAEA,UAAgB;AACd,SAAK,MAAM;AACX,SAAK,gBAAgB,MAAM;AAC3B,SAAK,aAAa,MAAM;AACxB,SAAK,cAAc,MAAM;AACzB,SAAK,cAAc,MAAM;AAAA,EAC3B;AACF;AAKA,eAAsB,sBAAsB,SAAuD;AACjG,MAAI,WAAW;AACb,UAAM,SAAS,IAAI,uBAAuB,OAAO;AACjD,UAAM,OAAO,QAAQ;AACrB,WAAO;AAAA,EACT,OAAO;AACL,UAAM,SAAS,IAAI,gBAAgB,OAAO;AAC1C,UAAM,OAAO,QAAQ;AACrB,WAAO;AAAA,EACT;AACF;","names":[]}
|
package/dist/browser.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|