message-nexus 1.1.0 → 1.1.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/index.js CHANGED
@@ -1,699 +1 @@
1
- // src/drivers/BaseDriver.ts
2
- var BaseDriver = class {
3
- constructor() {
4
- this.onMessage = null;
5
- }
6
- send(data) {
7
- throw new Error("Not implemented");
8
- }
9
- destroy() {
10
- }
11
- };
12
-
13
- // src/drivers/BroadcastDriver.ts
14
- var MESSAGE_NEXUS_PROTOCOL = "message-nexus-v1";
15
- function isBridgeMessage(data) {
16
- return typeof data === "object" && data !== null && "__messageBridge" in data && data.__messageBridge === MESSAGE_NEXUS_PROTOCOL;
17
- }
18
- var BroadcastDriver = class extends BaseDriver {
19
- constructor(options) {
20
- super();
21
- this.messageHandler = null;
22
- if (!options.channel) {
23
- throw new Error("BroadcastDriver requires a channel name");
24
- }
25
- this.channel = new BroadcastChannel(options.channel);
26
- this.messageHandler = (event) => {
27
- if (!isBridgeMessage(event.data)) {
28
- return;
29
- }
30
- const { __messageBridge, ...message } = event.data;
31
- this.onMessage?.(message);
32
- };
33
- this.channel.addEventListener("message", this.messageHandler);
34
- }
35
- send(data) {
36
- const bridgeMessage = {
37
- ...data,
38
- __messageBridge: MESSAGE_NEXUS_PROTOCOL
39
- };
40
- this.channel.postMessage(bridgeMessage);
41
- }
42
- destroy() {
43
- if (this.channel) {
44
- this.channel.close();
45
- }
46
- if (this.messageHandler) {
47
- this.channel.removeEventListener("message", this.messageHandler);
48
- this.messageHandler = null;
49
- }
50
- this.onMessage = null;
51
- }
52
- };
53
-
54
- // src/drivers/MittDriver.ts
55
- var eventIndicator = "message_nexus_message_event";
56
- var MittDriver = class extends BaseDriver {
57
- constructor(emitter) {
58
- super();
59
- this.emitter = emitter;
60
- this.listener = () => {
61
- };
62
- const handler = (data) => {
63
- if (data) this.onMessage?.(data);
64
- };
65
- this.emitter.on(eventIndicator, handler);
66
- this.listener = () => {
67
- this.emitter.off(eventIndicator, handler);
68
- };
69
- }
70
- send(data) {
71
- this.emitter.emit(eventIndicator, data);
72
- }
73
- destroy() {
74
- this.listener();
75
- this.onMessage = null;
76
- }
77
- };
78
-
79
- // src/drivers/PostMessageDriver.ts
80
- var MESSAGE_NEXUS_PROTOCOL2 = "message-nexus-v1";
81
- function isBridgeMessage2(data) {
82
- return typeof data === "object" && data !== null && "__messageBridge" in data && data.__messageBridge === MESSAGE_NEXUS_PROTOCOL2;
83
- }
84
- var PostMessageDriver = class extends BaseDriver {
85
- constructor(targetWindow, targetOrigin) {
86
- super();
87
- this.messageHandler = null;
88
- if (!targetOrigin || targetOrigin === "*") {
89
- throw new Error(
90
- 'PostMessageDriver requires explicit targetOrigin for security. Do not use "*" as it allows any origin.'
91
- );
92
- }
93
- this.targetWindow = targetWindow;
94
- this.targetOrigin = targetOrigin;
95
- this.messageHandler = (event) => {
96
- if (event.origin !== this.targetOrigin) {
97
- return;
98
- }
99
- if (!isBridgeMessage2(event.data)) {
100
- return;
101
- }
102
- const { __messageBridge, ...message } = event.data;
103
- this.onMessage?.(message);
104
- };
105
- window.addEventListener("message", this.messageHandler);
106
- }
107
- send(data) {
108
- const bridgeMessage = {
109
- ...data,
110
- __messageBridge: MESSAGE_NEXUS_PROTOCOL2
111
- };
112
- this.targetWindow.postMessage(bridgeMessage, this.targetOrigin);
113
- }
114
- destroy() {
115
- if (this.messageHandler) {
116
- window.removeEventListener("message", this.messageHandler);
117
- this.messageHandler = null;
118
- }
119
- this.onMessage = null;
120
- }
121
- };
122
-
123
- // src/utils/logger.ts
124
- function isLogger(value) {
125
- if (value == null || typeof value !== "object") return false;
126
- const logger = value;
127
- return typeof logger.addHandler === "function" && typeof logger.setMinLevel === "function" && typeof logger.enable === "function" && typeof logger.disable === "function" && typeof logger.isEnabled === "function" && typeof logger.debug === "function" && typeof logger.info === "function" && typeof logger.warn === "function" && typeof logger.error === "function";
128
- }
129
- var Logger = class {
130
- constructor(context, minLevel = "info" /* INFO */, enabled = false) {
131
- this.handlers = [];
132
- this.context = context;
133
- this.minLevel = minLevel;
134
- this.enabled = enabled;
135
- }
136
- enable() {
137
- this.enabled = true;
138
- }
139
- disable() {
140
- this.enabled = false;
141
- }
142
- isEnabled() {
143
- return this.enabled;
144
- }
145
- addHandler(handler) {
146
- this.handlers.push(handler);
147
- }
148
- setMinLevel(level) {
149
- this.minLevel = level;
150
- }
151
- shouldLog(level) {
152
- const levels = ["debug" /* DEBUG */, "info" /* INFO */, "warn" /* WARN */, "error" /* ERROR */];
153
- return levels.indexOf(level) >= levels.indexOf(this.minLevel);
154
- }
155
- log(level, message, metadata) {
156
- if (!this.enabled || !this.shouldLog(level)) return;
157
- const entry = {
158
- level,
159
- timestamp: Date.now(),
160
- message,
161
- metadata,
162
- context: this.context
163
- };
164
- this.handlers.forEach((handler) => handler(entry));
165
- }
166
- debug(message, metadata) {
167
- this.log("debug" /* DEBUG */, message, metadata);
168
- }
169
- info(message, metadata) {
170
- this.log("info" /* INFO */, message, metadata);
171
- }
172
- warn(message, metadata) {
173
- this.log("warn" /* WARN */, message, metadata);
174
- }
175
- error(message, metadata) {
176
- this.log("error" /* ERROR */, message, metadata);
177
- }
178
- };
179
- function genTimestamp() {
180
- const now = /* @__PURE__ */ new Date();
181
- return now.toLocaleTimeString("zh-CN", {
182
- hour12: false,
183
- hour: "2-digit",
184
- minute: "2-digit",
185
- second: "2-digit",
186
- fractionalSecondDigits: 3
187
- });
188
- }
189
- var createConsoleHandler = () => {
190
- return (entry) => {
191
- const timestamp = genTimestamp();
192
- const prefix = `[${timestamp}] [${entry.level.toUpperCase()}] [${entry.context || "app"}]`;
193
- const logFn = entry.level === "debug" /* DEBUG */ ? console.debug : entry.level === "info" /* INFO */ ? console.info : entry.level === "warn" /* WARN */ ? console.warn : console.error;
194
- if (entry.metadata) {
195
- logFn(prefix, entry.message, entry.metadata);
196
- } else {
197
- logFn(prefix, entry.message);
198
- }
199
- };
200
- };
201
-
202
- // src/drivers/WebSocktDriver.ts
203
- var MESSAGE_NEXUS_PROTOCOL3 = "message-nexus-v1";
204
- var WebSocketDriver = class extends BaseDriver {
205
- constructor(options) {
206
- super();
207
- this.ws = null;
208
- this.retryCount = 0;
209
- this.reconnectTimer = null;
210
- this.isManuallyClosed = false;
211
- this.url = options.url;
212
- this.reconnectEnabled = options.reconnect !== false;
213
- this.maxRetries = (typeof options.reconnect === "object" ? options.reconnect.maxRetries : void 0) ?? Infinity;
214
- this.retryInterval = (typeof options.reconnect === "object" ? options.reconnect.retryInterval : void 0) ?? 5e3;
215
- this.logger = options.logger || new Logger("WebSocketDriver");
216
- this.logger.addHandler(createConsoleHandler());
217
- this.onStatusChange = options.onStatusChange;
218
- this.connect();
219
- }
220
- connect() {
221
- this.onStatusChange?.("connecting");
222
- this.ws = new WebSocket(this.url);
223
- this.ws.addEventListener("open", () => {
224
- this.logger.info("WebSocket connected", { url: this.url });
225
- this.retryCount = 0;
226
- this.onStatusChange?.("connected");
227
- });
228
- this.ws.addEventListener("message", (event) => {
229
- try {
230
- const rawData = JSON.parse(event.data);
231
- if (typeof rawData === "object" && rawData !== null && "__messageBridge" in rawData && rawData.__messageBridge === MESSAGE_NEXUS_PROTOCOL3) {
232
- const { __messageBridge, ...data } = rawData;
233
- this.logger.debug("Message received", { data });
234
- this.onMessage?.(data);
235
- } else {
236
- this.logger.debug("Ignored non-bridge message", { data: rawData });
237
- }
238
- } catch (error) {
239
- this.logger.error("Failed to parse WebSocket message", { error, data: event.data });
240
- }
241
- });
242
- this.ws.addEventListener("error", (event) => {
243
- this.logger.error("WebSocket error", { event });
244
- this.onStatusChange?.("error");
245
- });
246
- this.ws.addEventListener("close", () => {
247
- this.logger.info("WebSocket connection closed", {
248
- manuallyClosed: this.isManuallyClosed,
249
- retryCount: this.retryCount,
250
- maxRetries: this.maxRetries
251
- });
252
- if (!this.isManuallyClosed && this.reconnectEnabled && this.retryCount < this.maxRetries) {
253
- this.scheduleReconnect();
254
- } else {
255
- this.onStatusChange?.("disconnected");
256
- }
257
- });
258
- }
259
- scheduleReconnect() {
260
- this.retryCount++;
261
- const delay = this.retryInterval * this.retryCount;
262
- this.logger.info("Reconnecting scheduled", {
263
- delay,
264
- attempt: this.retryCount,
265
- maxRetries: this.maxRetries,
266
- url: this.url
267
- });
268
- this.onStatusChange?.("connecting");
269
- this.reconnectTimer = window.setTimeout(() => {
270
- this.connect();
271
- }, delay);
272
- }
273
- send(data) {
274
- if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
275
- this.logger.error("WebSocket is not open", {
276
- state: this.ws?.readyState,
277
- url: this.url
278
- });
279
- throw new Error("WebSocket is not open");
280
- }
281
- this.logger.debug("Sending message", { data });
282
- const bridgeMessage = {
283
- ...data,
284
- __messageBridge: MESSAGE_NEXUS_PROTOCOL3
285
- };
286
- this.ws.send(JSON.stringify(bridgeMessage));
287
- }
288
- close() {
289
- this.logger.info("Closing WebSocket connection", { url: this.url });
290
- this.isManuallyClosed = true;
291
- if (this.reconnectTimer) {
292
- clearTimeout(this.reconnectTimer);
293
- this.reconnectTimer = null;
294
- }
295
- if (this.ws) {
296
- this.ws.close();
297
- this.ws = null;
298
- }
299
- this.onStatusChange?.("disconnected");
300
- }
301
- destroy() {
302
- this.close();
303
- this.onMessage = null;
304
- }
305
- };
306
-
307
- // src/utils/emitter.ts
308
- import mitt from "mitt";
309
- function createEmitter() {
310
- return mitt();
311
- }
312
-
313
- // src/index.ts
314
- var MessageNexus = class {
315
- constructor(driver, options) {
316
- this.cleanupInterval = null;
317
- this.messageQueue = [];
318
- this.maxQueueSize = 100;
319
- this.errorHandler = null;
320
- this.metrics = {
321
- messagesSent: 0,
322
- messagesReceived: 0,
323
- messagesFailed: 0,
324
- pendingMessages: 0,
325
- queuedMessages: 0,
326
- totalLatency: 0,
327
- averageLatency: 0
328
- };
329
- this.metricsCallbacks = /* @__PURE__ */ new Set();
330
- this.driver = driver;
331
- this.instanceId = options?.instanceId || crypto.randomUUID();
332
- this.timeout = options?.timeout ?? 1e4;
333
- if (options?.logger && isLogger(options.logger)) {
334
- this.logger = options.logger;
335
- } else {
336
- this.logger = new Logger("MessageNexus");
337
- }
338
- const loggerEnabled = options?.loggerEnabled ?? false;
339
- if (loggerEnabled) {
340
- this.logger.enable();
341
- this.logger.addHandler(createConsoleHandler());
342
- this.logger.info("MessageNexus initialized", {
343
- instanceId: this.instanceId,
344
- timeout: this.timeout
345
- });
346
- }
347
- this.pendingTasks = /* @__PURE__ */ new Map();
348
- this.invokeHandlers = /* @__PURE__ */ new Map();
349
- this.notificationHandlers = /* @__PURE__ */ new Map();
350
- this.cleanupInterval = null;
351
- this.driver.onMessage = (data) => this._handleIncoming(data);
352
- }
353
- async invoke(methodOrOptions) {
354
- const id = crypto.randomUUID();
355
- let method;
356
- let params;
357
- let to;
358
- let metadata;
359
- let timeout;
360
- let retryCount = 0;
361
- let retryDelay = 1e3;
362
- if (typeof methodOrOptions === "string") {
363
- method = methodOrOptions;
364
- params = void 0;
365
- to = void 0;
366
- metadata = {};
367
- timeout = this.timeout;
368
- } else {
369
- const opts = methodOrOptions;
370
- method = opts.method;
371
- params = opts.params;
372
- to = opts.to;
373
- metadata = opts.metadata || {};
374
- timeout = opts.timeout ?? this.timeout;
375
- retryCount = opts.retryCount ?? 0;
376
- retryDelay = opts.retryDelay ?? 1e3;
377
- }
378
- const attempt = async (attemptNumber) => {
379
- return new Promise((resolve, reject) => {
380
- const timer = setTimeout(() => {
381
- this.pendingTasks.delete(id);
382
- this.metrics.messagesFailed++;
383
- this.metrics.pendingMessages--;
384
- reject(new Error(`Message timeout: ${method} (${id})`));
385
- }, timeout);
386
- this.pendingTasks.set(id, { resolve, reject, timer, timestamp: Date.now() });
387
- const rpcRequest = {
388
- jsonrpc: "2.0",
389
- method,
390
- params,
391
- id
392
- };
393
- const message = {
394
- from: this.instanceId,
395
- to,
396
- metadata: { ...metadata, timestamp: Date.now() },
397
- payload: rpcRequest
398
- };
399
- this._sendMessage(message);
400
- }).catch((error) => {
401
- if (attemptNumber < retryCount) {
402
- return new Promise(
403
- (resolve) => setTimeout(() => resolve(attempt(attemptNumber + 1)), retryDelay * (attemptNumber + 1))
404
- );
405
- }
406
- this.metrics.messagesFailed++;
407
- this.metrics.pendingMessages--;
408
- throw error;
409
- });
410
- };
411
- return attempt(0);
412
- }
413
- _sendMessage(message) {
414
- const payload = message.payload;
415
- const isRequest = "method" in payload;
416
- const messageId = "id" in payload ? String(payload.id) : void 0;
417
- const typeOrMethod = isRequest ? payload.method : "RESPONSE";
418
- try {
419
- this.driver.send(message);
420
- this.metrics.messagesSent++;
421
- if (isRequest && messageId !== void 0) {
422
- this.metrics.pendingMessages++;
423
- }
424
- this.logger.debug("Message sent", { messageId, type: typeOrMethod });
425
- } catch (error) {
426
- const err = error instanceof Error ? error : new Error(String(error));
427
- this.metrics.messagesFailed++;
428
- this.logger.error("Failed to send message", { error: err.message, messageId });
429
- this.errorHandler?.(err, { message });
430
- if (this.messageQueue.length < this.maxQueueSize) {
431
- this.messageQueue.push(message);
432
- this.logger.debug("Message queued", {
433
- messageId,
434
- queueSize: this.messageQueue.length + 1
435
- });
436
- } else {
437
- this.logger.warn("Message queue full, dropping oldest message", {
438
- queueSize: this.messageQueue.length
439
- });
440
- this.messageQueue.shift();
441
- this.messageQueue.push(message);
442
- }
443
- }
444
- this.metrics.queuedMessages = this.messageQueue.length;
445
- this._notifyMetrics();
446
- }
447
- onError(handler) {
448
- this.errorHandler = handler;
449
- return () => {
450
- this.errorHandler = null;
451
- };
452
- }
453
- flushQueue() {
454
- while (this.messageQueue.length > 0) {
455
- const message = this.messageQueue.shift();
456
- if (message) {
457
- try {
458
- this.driver.send(message);
459
- } catch (error) {
460
- this.messageQueue.unshift(message);
461
- break;
462
- }
463
- }
464
- }
465
- }
466
- notify(methodOrOptions) {
467
- let method;
468
- let params;
469
- let to;
470
- let metadata;
471
- if (typeof methodOrOptions === "string") {
472
- method = methodOrOptions;
473
- params = void 0;
474
- to = void 0;
475
- metadata = {};
476
- } else {
477
- const opts = methodOrOptions;
478
- method = opts.method;
479
- params = opts.params;
480
- to = opts.to;
481
- metadata = opts.metadata || {};
482
- }
483
- const rpcNotification = {
484
- jsonrpc: "2.0",
485
- method,
486
- params
487
- };
488
- const message = {
489
- from: this.instanceId,
490
- to,
491
- metadata: { ...metadata, timestamp: Date.now() },
492
- payload: rpcNotification
493
- };
494
- this._sendMessage(message);
495
- }
496
- _validateMessage(data) {
497
- if (!data || typeof data !== "object") return false;
498
- const env = data;
499
- if (typeof env.from !== "string") return false;
500
- if (env.to !== void 0 && typeof env.to !== "string") return false;
501
- if (env.metadata !== void 0 && typeof env.metadata !== "object") return false;
502
- const payload = env.payload;
503
- if (!payload || typeof payload !== "object") return false;
504
- if (payload.jsonrpc !== "2.0") return false;
505
- const isRequest = "method" in payload;
506
- const isResponse = "result" in payload || "error" in payload;
507
- if (!isRequest && !isResponse) return false;
508
- return true;
509
- }
510
- async _handleIncoming(data) {
511
- if (!this._validateMessage(data)) {
512
- this.logger.error("Invalid message format received", { data });
513
- this.errorHandler?.(new Error("Invalid message format received"), { data });
514
- this.metrics.messagesFailed++;
515
- return;
516
- }
517
- const envelope = data;
518
- const payload = envelope.payload;
519
- if (envelope.to && envelope.to !== this.instanceId) {
520
- this.logger.debug("Message filtered: not for this instance", {
521
- messageId: "id" in payload ? payload.id : void 0,
522
- to: envelope.to,
523
- instanceId: this.instanceId
524
- });
525
- return;
526
- }
527
- if ("result" in payload || "error" in payload) {
528
- const response = payload;
529
- const id = String(response.id);
530
- if (this.pendingTasks.has(id)) {
531
- const { resolve, reject, timer, timestamp } = this.pendingTasks.get(id);
532
- clearTimeout(timer);
533
- this.pendingTasks.delete(id);
534
- const latency = Date.now() - timestamp;
535
- this.metrics.messagesReceived++;
536
- this.metrics.pendingMessages--;
537
- this.metrics.totalLatency += latency;
538
- this.metrics.averageLatency = this.metrics.totalLatency / this.metrics.messagesReceived;
539
- this.logger.debug("Response received", { messageId: id, latency });
540
- if (response.error) {
541
- const err = new Error(response.error.message);
542
- err.code = response.error.code;
543
- err.data = response.error.data;
544
- reject(err);
545
- } else {
546
- resolve(response.result);
547
- }
548
- this._notifyMetrics();
549
- } else {
550
- this.logger.warn("Orphaned response received", { messageId: id });
551
- }
552
- return;
553
- }
554
- if ("method" in payload) {
555
- if ("id" in payload) {
556
- const request = payload;
557
- const id = String(request.id);
558
- this.logger.debug("Invoke message received", {
559
- messageId: id,
560
- type: request.method,
561
- from: envelope.from
562
- });
563
- const context = {
564
- messageId: id,
565
- from: envelope.from,
566
- to: envelope.to,
567
- metadata: envelope.metadata
568
- };
569
- const handler = this.invokeHandlers.get(request.method);
570
- if (handler) {
571
- try {
572
- const result = await handler(request.params, context);
573
- this._reply(id, envelope.from, result);
574
- } catch (error) {
575
- this._replyError(id, envelope.from, error);
576
- }
577
- } else {
578
- const err = new Error(`Method not found: ${request.method}`);
579
- err.code = -32601;
580
- this._replyError(id, envelope.from, err);
581
- }
582
- } else {
583
- const notification = payload;
584
- this.logger.debug("Notification message received", {
585
- type: notification.method,
586
- from: envelope.from
587
- });
588
- const context = {
589
- from: envelope.from,
590
- to: envelope.to,
591
- metadata: envelope.metadata
592
- };
593
- const handlers = this.notificationHandlers.get(notification.method);
594
- if (handlers) {
595
- handlers.forEach((handler) => {
596
- try {
597
- handler(notification.params, context);
598
- } catch (error) {
599
- this.logger.error("Error in notification handler", { error: String(error) });
600
- }
601
- });
602
- }
603
- }
604
- }
605
- }
606
- getMetrics() {
607
- return { ...this.metrics, pendingMessages: this.pendingTasks.size };
608
- }
609
- onMetrics(callback) {
610
- this.metricsCallbacks.add(callback);
611
- return () => this.metricsCallbacks.delete(callback);
612
- }
613
- _notifyMetrics() {
614
- const metrics = this.getMetrics();
615
- this.metricsCallbacks.forEach((callback) => callback(metrics));
616
- }
617
- handle(method, handler) {
618
- if (this.invokeHandlers.has(method)) {
619
- this.logger.warn(`Overriding existing handler for method: ${method}`);
620
- }
621
- this.invokeHandlers.set(method, handler);
622
- return () => this.invokeHandlers.delete(method);
623
- }
624
- removeHandler(method) {
625
- this.invokeHandlers.delete(method);
626
- }
627
- onNotification(method, handler) {
628
- if (!this.notificationHandlers.has(method)) {
629
- this.notificationHandlers.set(method, /* @__PURE__ */ new Set());
630
- }
631
- this.notificationHandlers.get(method).add(handler);
632
- return () => this.offNotification(method, handler);
633
- }
634
- offNotification(method, handler) {
635
- const handlers = this.notificationHandlers.get(method);
636
- if (handlers) {
637
- handlers.delete(handler);
638
- if (handlers.size === 0) {
639
- this.notificationHandlers.delete(method);
640
- }
641
- }
642
- }
643
- _reply(messageId, to, payload) {
644
- const rpcResponse = {
645
- jsonrpc: "2.0",
646
- id: messageId,
647
- result: payload
648
- };
649
- const message = {
650
- from: this.instanceId,
651
- to,
652
- payload: rpcResponse
653
- };
654
- this.driver.send(message);
655
- }
656
- _replyError(messageId, to, error) {
657
- const err = error instanceof Error ? error : new Error(String(error));
658
- const rpcResponse = {
659
- jsonrpc: "2.0",
660
- id: messageId,
661
- error: {
662
- code: err.code || -32e3,
663
- message: err.message,
664
- data: err.data
665
- }
666
- };
667
- const message = {
668
- from: this.instanceId,
669
- to,
670
- payload: rpcResponse
671
- };
672
- this.driver.send(message);
673
- }
674
- destroy() {
675
- this.logger.info("MessageNexus destroying", {
676
- instanceId: this.instanceId,
677
- pendingMessages: this.pendingTasks.size,
678
- queuedMessages: this.messageQueue.length,
679
- metrics: this.getMetrics()
680
- });
681
- this.driver.destroy?.();
682
- if (this.cleanupInterval) {
683
- clearInterval(this.cleanupInterval);
684
- this.cleanupInterval = null;
685
- }
686
- this.invokeHandlers.clear();
687
- this.notificationHandlers.clear();
688
- this.metricsCallbacks.clear();
689
- }
690
- };
691
- export {
692
- BaseDriver,
693
- BroadcastDriver,
694
- MittDriver,
695
- PostMessageDriver,
696
- WebSocketDriver,
697
- createEmitter,
698
- MessageNexus as default
699
- };
1
+ var c=class{constructor(){this.onMessage=null}send(t){throw new Error("Not implemented")}destroy(){}};var k="message-nexus-v1";function O(i){return typeof i=="object"&&i!==null&&"__messageBridge"in i&&i.__messageBridge===k}var v=class extends c{constructor(e){super();this.messageHandler=null;if(!e.channel)throw new Error("BroadcastDriver requires a channel name");this.channel=new BroadcastChannel(e.channel),this.messageHandler=s=>{if(!O(s.data))return;let{__messageBridge:n,...r}=s.data;this.onMessage?.(r)},this.channel.addEventListener("message",this.messageHandler)}send(e){let s={...e,__messageBridge:k};this.channel.postMessage(s)}destroy(){this.channel&&this.channel.close(),this.messageHandler&&(this.channel.removeEventListener("message",this.messageHandler),this.messageHandler=null),this.onMessage=null}};var L=Symbol("message_nexus_internal"),y=class extends c{constructor(t){super(),this.emitter=t,this.listener=()=>{};let e=s=>{s&&this.onMessage?.(s)};this.emitter.on(L,e),this.listener=()=>{this.emitter.off(L,e)}}send(t){this.emitter.emit(L,t)}destroy(){this.listener(),this.onMessage=null}};var x="message-nexus-v1";function B(i){return typeof i=="object"&&i!==null&&"__messageBridge"in i&&i.__messageBridge===x}var M=class extends c{constructor(e,s){super();this.messageHandler=null;if(!s||s==="*")throw new Error('PostMessageDriver requires explicit targetOrigin for security. Do not use "*" as it allows any origin.');this.targetWindow=e,this.targetOrigin=s,this.messageHandler=n=>{if(n.origin!==this.targetOrigin||!B(n.data))return;let{__messageBridge:r,...a}=n.data;this.onMessage?.(a)},window.addEventListener("message",this.messageHandler)}send(e){let s={...e,__messageBridge:x};this.targetWindow.postMessage(s,this.targetOrigin)}destroy(){this.messageHandler&&(window.removeEventListener("message",this.messageHandler),this.messageHandler=null),this.onMessage=null}};var S=(n=>(n.DEBUG="debug",n.INFO="info",n.WARN="warn",n.ERROR="error",n))(S||{});function I(i){if(i==null||typeof i!="object")return!1;let t=i;return typeof t.debug=="function"&&typeof t.info=="function"&&typeof t.warn=="function"&&typeof t.error=="function"&&typeof t.addHandler=="function"&&typeof t.setMinLevel=="function"&&typeof t.enable=="function"&&typeof t.disable=="function"&&typeof t.isEnabled=="function"}function H(i){if(i==null||typeof i!="object")return!1;let t=i;return typeof t.debug=="function"&&typeof t.info=="function"&&typeof t.warn=="function"&&typeof t.error=="function"}var h=class{constructor(t,e="info",s=!1){this.handlers=[];this.context=t,this.minLevel=e,this.enabled=s}enable(){this.enabled=!0}disable(){this.enabled=!1}isEnabled(){return this.enabled}addHandler(t){this.handlers.push(t)}setMinLevel(t){this.minLevel=t}shouldLog(t){let e=["debug","info","warn","error"];return e.indexOf(t)>=e.indexOf(this.minLevel)}log(t,e,s){if(!this.enabled||!this.shouldLog(t))return;let n={level:t,timestamp:Date.now(),message:e,metadata:s,context:this.context};this.handlers.forEach(r=>r(n))}debug(t,e){this.log("debug",t,e)}info(t,e){this.log("info",t,e)}warn(t,e){this.log("warn",t,e)}error(t,e){this.log("error",t,e)}};function D(){return new Date().toLocaleTimeString("zh-CN",{hour12:!1,hour:"2-digit",minute:"2-digit",second:"2-digit",fractionalSecondDigits:3})}var R=()=>i=>{let e=`[${D()}] [${i.level.toUpperCase()}] [${i.context||"app"}]`,s=i.level==="debug"?console.debug:i.level==="info"?console.info:i.level==="warn"?console.warn:console.error;i.metadata?s(e,i.message,i.metadata):s(e,i.message)};var _="message-nexus-v1",w=class extends c{constructor(e){super();this.ws=null;this.retryCount=0;this.reconnectTimer=null;this.isManuallyClosed=!1;this.url=e.url,this.reconnectEnabled=e.reconnect!==!1,this.maxRetries=(typeof e.reconnect=="object"?e.reconnect.maxRetries:void 0)??1/0,this.retryInterval=(typeof e.reconnect=="object"?e.reconnect.retryInterval:void 0)??5e3,this.logger=e.logger||new h("WebSocketDriver"),this.logger.addHandler(R()),this.onStatusChange=e.onStatusChange,this.connect()}connect(){this.onStatusChange?.("connecting"),this.ws=new WebSocket(this.url),this.ws.addEventListener("open",()=>{this.logger.info("WebSocket connected",{url:this.url}),this.retryCount=0,this.onStatusChange?.("connected")}),this.ws.addEventListener("message",e=>{try{let s=JSON.parse(e.data);if(typeof s=="object"&&s!==null&&"__messageBridge"in s&&s.__messageBridge===_){let{__messageBridge:n,...r}=s;this.logger.debug("Message received",{data:r}),this.onMessage?.(r)}else this.logger.debug("Ignored non-bridge message",{data:s})}catch(s){this.logger.error("Failed to parse WebSocket message",{error:s,data:e.data})}}),this.ws.addEventListener("error",e=>{this.logger.error("WebSocket error",{event:e}),this.onStatusChange?.("error")}),this.ws.addEventListener("close",()=>{this.logger.info("WebSocket connection closed",{manuallyClosed:this.isManuallyClosed,retryCount:this.retryCount,maxRetries:this.maxRetries}),!this.isManuallyClosed&&this.reconnectEnabled&&this.retryCount<this.maxRetries?this.scheduleReconnect():this.onStatusChange?.("disconnected")})}scheduleReconnect(){this.retryCount++;let e=this.retryInterval*this.retryCount;this.logger.info("Reconnecting scheduled",{delay:e,attempt:this.retryCount,maxRetries:this.maxRetries,url:this.url}),this.onStatusChange?.("connecting"),this.reconnectTimer=window.setTimeout(()=>{this.connect()},e)}send(e){if(!this.ws||this.ws.readyState!==WebSocket.OPEN)throw this.logger.error("WebSocket is not open",{state:this.ws?.readyState,url:this.url}),new Error("WebSocket is not open");this.logger.debug("Sending message",{data:e});let s={...e,__messageBridge:_};this.ws.send(JSON.stringify(s))}close(){this.logger.info("Closing WebSocket connection",{url:this.url}),this.isManuallyClosed=!0,this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null),this.ws&&(this.ws.close(),this.ws=null),this.onStatusChange?.("disconnected")}destroy(){this.close(),this.onMessage=null}};import J from"mitt";function P(){return J()}var E=class{constructor(t,e){this.cleanupInterval=null;this.messageQueue=[];this.maxQueueSize=100;this.errorHandler=null;this.metrics={messagesSent:0,messagesReceived:0,messagesFailed:0,pendingMessages:0,queuedMessages:0,totalLatency:0,averageLatency:0};this.metricsCallbacks=new Set;this.driver=t,this.instanceId=e?.instanceId||crypto.randomUUID(),this.timeout=e?.timeout??1e4;let s=e?.logLevel??"info",n=e?.loggerEnabled??!1;if(e?.logger&&I(e.logger))this.logger=e.logger;else if(this.logger=new h("MessageNexus",s,n),e?.logger&&H(e.logger)){let r=e.logger;this.logger.addHandler(a=>{let{level:g,message:o,metadata:d}=a;g==="debug"?r.debug(o,d):g==="info"?r.info(o,d):g==="warn"?r.warn(o,d):g==="error"&&r.error(o,d)})}else n&&this.logger.addHandler(R());n&&(this.logger.enable(),this.logger.info("MessageNexus initialized",{instanceId:this.instanceId,timeout:this.timeout,logLevel:s})),this.pendingTasks=new Map,this.invokeHandlers=new Map,this.notificationHandlers=new Map,this.cleanupInterval=null,this.driver.onMessage=r=>this._handleIncoming(r)}async invoke(t){let e=crypto.randomUUID(),s,n,r,a,g,o=0,d=1e3;if(typeof t=="string")s=t,n=void 0,r=void 0,a={},g=this.timeout;else{let l=t;s=l.method,n=l.params,r=l.to,a=l.metadata||{},g=l.timeout??this.timeout,o=l.retryCount??0,d=l.retryDelay??1e3}let p=async l=>new Promise((b,f)=>{let C=setTimeout(()=>{this.pendingTasks.delete(e),this.metrics.messagesFailed++,this.metrics.pendingMessages--,f(new Error(`Message timeout: ${s} (${e})`))},g);this.pendingTasks.set(e,{resolve:b,reject:f,timer:C,timestamp:Date.now()});let N={jsonrpc:"2.0",method:s,params:n,id:e},T={from:this.instanceId,to:r,metadata:{...a,timestamp:Date.now()},payload:N};this._sendMessage(T)}).catch(b=>{if(l<o)return new Promise(f=>setTimeout(()=>f(p(l+1)),d*(l+1)));throw this.metrics.messagesFailed++,this.metrics.pendingMessages--,b});return p(0)}_sendMessage(t){let e=t.payload,s="method"in e,n="id"in e?String(e.id):void 0,r=s?e.method:"RESPONSE";try{this.driver.send(t),this.metrics.messagesSent++,s&&n!==void 0&&this.metrics.pendingMessages++,this.logger.debug("Message sent",{messageId:n,type:r})}catch(a){let g=a instanceof Error?a:new Error(String(a));this.metrics.messagesFailed++,this.logger.error("Failed to send message",{error:g.message,messageId:n}),this.errorHandler?.(g,{message:t}),this.messageQueue.length<this.maxQueueSize?(this.messageQueue.push(t),this.logger.debug("Message queued",{messageId:n,queueSize:this.messageQueue.length+1})):(this.logger.warn("Message queue full, dropping oldest message",{queueSize:this.messageQueue.length}),this.messageQueue.shift(),this.messageQueue.push(t))}this.metrics.queuedMessages=this.messageQueue.length,this._notifyMetrics()}onError(t){return this.errorHandler=t,()=>{this.errorHandler=null}}flushQueue(){for(;this.messageQueue.length>0;){let t=this.messageQueue.shift();if(t)try{this.driver.send(t)}catch{this.messageQueue.unshift(t);break}}}notify(t){let e,s,n,r;if(typeof t=="string")e=t,s=void 0,n=void 0,r={};else{let o=t;e=o.method,s=o.params,n=o.to,r=o.metadata||{}}let a={jsonrpc:"2.0",method:e,params:s},g={from:this.instanceId,to:n,metadata:{...r,timestamp:Date.now()},payload:a};this._sendMessage(g)}_validateMessage(t){if(!t||typeof t!="object")return!1;let e=t;if(typeof e.from!="string"||e.to!==void 0&&typeof e.to!="string"||e.metadata!==void 0&&typeof e.metadata!="object")return!1;let s=e.payload;if(!s||typeof s!="object"||s.jsonrpc!=="2.0")return!1;let n="method"in s,r="result"in s||"error"in s;return!(!n&&!r)}async _handleIncoming(t){if(!this._validateMessage(t)){this.logger.error("Invalid message format received",{data:t}),this.errorHandler?.(new Error("Invalid message format received"),{data:t}),this.metrics.messagesFailed++;return}let e=t,s=e.payload;if(e.to&&e.to!==this.instanceId){this.logger.debug("Message filtered: not for this instance",{messageId:"id"in s?s.id:void 0,to:e.to,instanceId:this.instanceId});return}if("result"in s||"error"in s){let n=s,r=String(n.id);if(this.pendingTasks.has(r)){let{resolve:a,reject:g,timer:o,timestamp:d}=this.pendingTasks.get(r);clearTimeout(o),this.pendingTasks.delete(r);let p=Date.now()-d;if(this.metrics.messagesReceived++,this.metrics.pendingMessages--,this.metrics.totalLatency+=p,this.metrics.averageLatency=this.metrics.totalLatency/this.metrics.messagesReceived,this.logger.debug("Response received",{messageId:r,latency:p}),n.error){let l=new Error(n.error.message);l.code=n.error.code,l.data=n.error.data,g(l)}else a(n.result);this._notifyMetrics()}else this.logger.warn("Orphaned response received",{messageId:r});return}if("method"in s)if("id"in s){let n=s,r=String(n.id);this.logger.debug("Invoke message received",{messageId:r,type:n.method,from:e.from});let a={messageId:r,from:e.from,to:e.to,metadata:e.metadata},g=this.invokeHandlers.get(n.method);if(g)try{let o=await g(n.params,a);this._reply(r,e.from,o)}catch(o){this._replyError(r,e.from,o)}else{let o=new Error(`Method not found: ${n.method}`);o.code=-32601,this._replyError(r,e.from,o)}}else{let n=s;this.logger.debug("Notification message received",{type:n.method,from:e.from});let r={from:e.from,to:e.to,metadata:e.metadata},a=this.notificationHandlers.get(n.method);a&&a.forEach(g=>{try{g(n.params,r)}catch(o){this.logger.error("Error in notification handler",{error:String(o)})}})}}getMetrics(){return{...this.metrics,pendingMessages:this.pendingTasks.size}}onMetrics(t){return this.metricsCallbacks.add(t),()=>this.metricsCallbacks.delete(t)}_notifyMetrics(){let t=this.getMetrics();this.metricsCallbacks.forEach(e=>e(t))}handle(t,e){return this.invokeHandlers.has(t)&&this.logger.warn(`Overriding existing handler for method: ${t}`),this.invokeHandlers.set(t,e),()=>this.invokeHandlers.delete(t)}removeHandler(t){this.invokeHandlers.delete(t)}onNotification(t,e){return this.notificationHandlers.has(t)||this.notificationHandlers.set(t,new Set),this.notificationHandlers.get(t).add(e),()=>this.offNotification(t,e)}offNotification(t,e){let s=this.notificationHandlers.get(t);s&&(s.delete(e),s.size===0&&this.notificationHandlers.delete(t))}_reply(t,e,s){let n={jsonrpc:"2.0",id:t,result:s},r={from:this.instanceId,to:e,payload:n};this.driver.send(r)}_replyError(t,e,s){let n=s instanceof Error?s:new Error(String(s)),r={jsonrpc:"2.0",id:t,error:{code:n.code||-32e3,message:n.message,data:n.data}},a={from:this.instanceId,to:e,payload:r};this.driver.send(a)}destroy(){this.logger.info("MessageNexus destroying",{instanceId:this.instanceId,pendingMessages:this.pendingTasks.size,queuedMessages:this.messageQueue.length,metrics:this.getMetrics()}),this.driver.destroy?.(),this.cleanupInterval&&(clearInterval(this.cleanupInterval),this.cleanupInterval=null),this.invokeHandlers.clear(),this.notificationHandlers.clear(),this.metricsCallbacks.clear()}};export{c as BaseDriver,v as BroadcastDriver,S as LogLevel,y as MittDriver,M as PostMessageDriver,w as WebSocketDriver,P as createEmitter,E as default};