@lifeart/async-dom 2.0.0-alpha.3

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.
Files changed (117) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +623 -0
  3. package/dist/base.d.cts +398 -0
  4. package/dist/base.d.cts.map +1 -0
  5. package/dist/base.d.ts +398 -0
  6. package/dist/base.d.ts.map +1 -0
  7. package/dist/cli.cjs +528 -0
  8. package/dist/cli.cjs.map +1 -0
  9. package/dist/cli.d.cts +1 -0
  10. package/dist/cli.d.ts +1 -0
  11. package/dist/cli.js +493 -0
  12. package/dist/cli.js.map +1 -0
  13. package/dist/debug.d.cts +145 -0
  14. package/dist/debug.d.cts.map +1 -0
  15. package/dist/debug.d.ts +145 -0
  16. package/dist/debug.d.ts.map +1 -0
  17. package/dist/index.cjs +26 -0
  18. package/dist/index.d.cts +560 -0
  19. package/dist/index.d.cts.map +1 -0
  20. package/dist/index.d.ts +560 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/index.js +5 -0
  23. package/dist/index2.d.cts +5 -0
  24. package/dist/index2.d.ts +5 -0
  25. package/dist/index3.d.cts +882 -0
  26. package/dist/index3.d.cts.map +1 -0
  27. package/dist/index3.d.ts +882 -0
  28. package/dist/index3.d.ts.map +1 -0
  29. package/dist/main-thread.cjs +5459 -0
  30. package/dist/main-thread.cjs.map +1 -0
  31. package/dist/main-thread.js +5429 -0
  32. package/dist/main-thread.js.map +1 -0
  33. package/dist/react.cjs +116 -0
  34. package/dist/react.cjs.map +1 -0
  35. package/dist/react.d.cts +91 -0
  36. package/dist/react.d.cts.map +1 -0
  37. package/dist/react.d.ts +91 -0
  38. package/dist/react.d.ts.map +1 -0
  39. package/dist/react.js +113 -0
  40. package/dist/react.js.map +1 -0
  41. package/dist/resolve-debug.cjs +24 -0
  42. package/dist/resolve-debug.cjs.map +1 -0
  43. package/dist/resolve-debug.js +19 -0
  44. package/dist/resolve-debug.js.map +1 -0
  45. package/dist/server.cjs +250 -0
  46. package/dist/server.cjs.map +1 -0
  47. package/dist/server.d.cts +127 -0
  48. package/dist/server.d.cts.map +1 -0
  49. package/dist/server.d.ts +127 -0
  50. package/dist/server.d.ts.map +1 -0
  51. package/dist/server.js +245 -0
  52. package/dist/server.js.map +1 -0
  53. package/dist/svelte.cjs +48 -0
  54. package/dist/svelte.cjs.map +1 -0
  55. package/dist/svelte.d.cts +38 -0
  56. package/dist/svelte.d.cts.map +1 -0
  57. package/dist/svelte.d.ts +38 -0
  58. package/dist/svelte.d.ts.map +1 -0
  59. package/dist/svelte.js +47 -0
  60. package/dist/svelte.js.map +1 -0
  61. package/dist/sync-channel.cjs +532 -0
  62. package/dist/sync-channel.cjs.map +1 -0
  63. package/dist/sync-channel.js +425 -0
  64. package/dist/sync-channel.js.map +1 -0
  65. package/dist/transport.cjs +213 -0
  66. package/dist/transport.cjs.map +1 -0
  67. package/dist/transport.d.cts +79 -0
  68. package/dist/transport.d.cts.map +1 -0
  69. package/dist/transport.d.ts +79 -0
  70. package/dist/transport.d.ts.map +1 -0
  71. package/dist/transport.js +202 -0
  72. package/dist/transport.js.map +1 -0
  73. package/dist/vite-plugin.cjs +112 -0
  74. package/dist/vite-plugin.cjs.map +1 -0
  75. package/dist/vite-plugin.d.cts +39 -0
  76. package/dist/vite-plugin.d.cts.map +1 -0
  77. package/dist/vite-plugin.d.ts +39 -0
  78. package/dist/vite-plugin.d.ts.map +1 -0
  79. package/dist/vite-plugin.js +107 -0
  80. package/dist/vite-plugin.js.map +1 -0
  81. package/dist/vue.cjs +123 -0
  82. package/dist/vue.cjs.map +1 -0
  83. package/dist/vue.d.cts +126 -0
  84. package/dist/vue.d.cts.map +1 -0
  85. package/dist/vue.d.ts +126 -0
  86. package/dist/vue.d.ts.map +1 -0
  87. package/dist/vue.js +120 -0
  88. package/dist/vue.js.map +1 -0
  89. package/dist/worker-thread.cjs +2751 -0
  90. package/dist/worker-thread.cjs.map +1 -0
  91. package/dist/worker-thread.js +2692 -0
  92. package/dist/worker-thread.js.map +1 -0
  93. package/dist/worker-transport.cjs +136 -0
  94. package/dist/worker-transport.cjs.map +1 -0
  95. package/dist/worker-transport.d.cts +162 -0
  96. package/dist/worker-transport.d.cts.map +1 -0
  97. package/dist/worker-transport.d.ts +162 -0
  98. package/dist/worker-transport.d.ts.map +1 -0
  99. package/dist/worker-transport.js +125 -0
  100. package/dist/worker-transport.js.map +1 -0
  101. package/dist/worker.cjs +12 -0
  102. package/dist/worker.d.cts +2 -0
  103. package/dist/worker.d.ts +2 -0
  104. package/dist/worker.js +2 -0
  105. package/dist/ws-server-transport.cjs +147 -0
  106. package/dist/ws-server-transport.cjs.map +1 -0
  107. package/dist/ws-server-transport.d.cts +64 -0
  108. package/dist/ws-server-transport.d.cts.map +1 -0
  109. package/dist/ws-server-transport.d.ts +64 -0
  110. package/dist/ws-server-transport.d.ts.map +1 -0
  111. package/dist/ws-server-transport.js +142 -0
  112. package/dist/ws-server-transport.js.map +1 -0
  113. package/dist/ws-transport.cjs +954 -0
  114. package/dist/ws-transport.cjs.map +1 -0
  115. package/dist/ws-transport.js +913 -0
  116. package/dist/ws-transport.js.map +1 -0
  117. package/package.json +145 -0
@@ -0,0 +1,64 @@
1
+ import { n as TransportReadyState, p as Message, r as TransportStats, t as Transport } from "./base.cjs";
2
+
3
+ //#region src/transport/ws-server-transport.d.ts
4
+
5
+ /**
6
+ * Minimal WebSocket interface that works with any WebSocket server library
7
+ * (ws, uWebSockets.js, Deno, Bun, etc.) without importing their types.
8
+ */
9
+ interface WebSocketLike {
10
+ /** Send a string message through the socket. */
11
+ send(data: string): void;
12
+ /** Close the socket with an optional status code and reason. */
13
+ close(code?: number, reason?: string): void;
14
+ /** WebSocket readyState constant (0=CONNECTING, 1=OPEN, 2=CLOSING, 3=CLOSED). */
15
+ readonly readyState: number;
16
+ /** Number of bytes queued for sending but not yet transmitted. */
17
+ readonly bufferedAmount: number;
18
+ /** Handler called when a message is received. */
19
+ onmessage: ((event: {
20
+ data: unknown;
21
+ }) => void) | null;
22
+ /** Handler called when the connection closes. */
23
+ onclose: ((event: {
24
+ code: number;
25
+ reason: string;
26
+ }) => void) | null;
27
+ /** Handler called when a connection error occurs. */
28
+ onerror: ((event: unknown) => void) | null;
29
+ }
30
+ /**
31
+ * Server-side WebSocket transport for async-dom.
32
+ *
33
+ * Unlike the client-side WebSocketTransport, this does NOT handle reconnection.
34
+ * It accepts an already-connected WebSocketLike socket and wraps it with
35
+ * the Transport interface including backpressure handling.
36
+ */
37
+ declare class WebSocketServerTransport implements Transport {
38
+ private socket;
39
+ private handlers;
40
+ private _readyState;
41
+ private _stats;
42
+ private _statsEnabled;
43
+ private messageQueue;
44
+ private drainTimer;
45
+ onError?: (error: Error) => void;
46
+ onClose?: () => void;
47
+ constructor(socket: WebSocketLike);
48
+ private mapReadyState;
49
+ send(message: Message): void;
50
+ private sendRaw;
51
+ private startDrainCheck;
52
+ private stopDrainCheck;
53
+ private flushQueue;
54
+ onMessage(handler: (message: Message) => void): void;
55
+ close(): void;
56
+ get readyState(): TransportReadyState;
57
+ get bufferedAmount(): number;
58
+ getStats(): TransportStats;
59
+ enableStats(enabled: boolean): void;
60
+ }
61
+ //# sourceMappingURL=ws-server-transport.d.ts.map
62
+ //#endregion
63
+ export { WebSocketServerTransport as n, WebSocketLike as t };
64
+ //# sourceMappingURL=ws-server-transport.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ws-server-transport.d.cts","names":[],"sources":["../src/transport/ws-server-transport.ts"],"sourcesContent":[],"mappings":";;;;;AAOA;AAiCA;;AAamB,UA9CF,aAAA,CA8CE;;MAqDJ,CAAA,IAAA,EAAA,MAAA,CAAA,EAAA,IAAA;;OAwFI,CAAA,IAAA,CAAA,EAAA,MAAA,EAAA,MAAA,CAAA,EAAA,MAAA,CAAA,EAAA,IAAA;;WA1J8B,UAAA,EAAA,MAAA;EAAS;;;;;;;;;;;;;;;;;;;;;cAA7C,wBAAA,YAAoC;;;;;;;;oBAa9B;;sBAGU;;gBAkDd;;;;;+BA4Ee;;oBAYX;;cAQN"}
@@ -0,0 +1,64 @@
1
+ import { n as TransportReadyState, p as Message, r as TransportStats, t as Transport } from "./base.js";
2
+
3
+ //#region src/transport/ws-server-transport.d.ts
4
+
5
+ /**
6
+ * Minimal WebSocket interface that works with any WebSocket server library
7
+ * (ws, uWebSockets.js, Deno, Bun, etc.) without importing their types.
8
+ */
9
+ interface WebSocketLike {
10
+ /** Send a string message through the socket. */
11
+ send(data: string): void;
12
+ /** Close the socket with an optional status code and reason. */
13
+ close(code?: number, reason?: string): void;
14
+ /** WebSocket readyState constant (0=CONNECTING, 1=OPEN, 2=CLOSING, 3=CLOSED). */
15
+ readonly readyState: number;
16
+ /** Number of bytes queued for sending but not yet transmitted. */
17
+ readonly bufferedAmount: number;
18
+ /** Handler called when a message is received. */
19
+ onmessage: ((event: {
20
+ data: unknown;
21
+ }) => void) | null;
22
+ /** Handler called when the connection closes. */
23
+ onclose: ((event: {
24
+ code: number;
25
+ reason: string;
26
+ }) => void) | null;
27
+ /** Handler called when a connection error occurs. */
28
+ onerror: ((event: unknown) => void) | null;
29
+ }
30
+ /**
31
+ * Server-side WebSocket transport for async-dom.
32
+ *
33
+ * Unlike the client-side WebSocketTransport, this does NOT handle reconnection.
34
+ * It accepts an already-connected WebSocketLike socket and wraps it with
35
+ * the Transport interface including backpressure handling.
36
+ */
37
+ declare class WebSocketServerTransport implements Transport {
38
+ private socket;
39
+ private handlers;
40
+ private _readyState;
41
+ private _stats;
42
+ private _statsEnabled;
43
+ private messageQueue;
44
+ private drainTimer;
45
+ onError?: (error: Error) => void;
46
+ onClose?: () => void;
47
+ constructor(socket: WebSocketLike);
48
+ private mapReadyState;
49
+ send(message: Message): void;
50
+ private sendRaw;
51
+ private startDrainCheck;
52
+ private stopDrainCheck;
53
+ private flushQueue;
54
+ onMessage(handler: (message: Message) => void): void;
55
+ close(): void;
56
+ get readyState(): TransportReadyState;
57
+ get bufferedAmount(): number;
58
+ getStats(): TransportStats;
59
+ enableStats(enabled: boolean): void;
60
+ }
61
+ //# sourceMappingURL=ws-server-transport.d.ts.map
62
+ //#endregion
63
+ export { WebSocketServerTransport as n, WebSocketLike as t };
64
+ //# sourceMappingURL=ws-server-transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ws-server-transport.d.ts","names":[],"sources":["../src/transport/ws-server-transport.ts"],"sourcesContent":[],"mappings":";;;;;AAOA;AAiCA;;AAamB,UA9CF,aAAA,CA8CE;;MAqDJ,CAAA,IAAA,EAAA,MAAA,CAAA,EAAA,IAAA;;OAwFI,CAAA,IAAA,CAAA,EAAA,MAAA,EAAA,MAAA,CAAA,EAAA,MAAA,CAAA,EAAA,IAAA;;WA1J8B,UAAA,EAAA,MAAA;EAAS;;;;;;;;;;;;;;;;;;;;;cAA7C,wBAAA,YAAoC;;;;;;;;oBAa9B;;sBAGU;;gBAkDd;;;;;+BA4Ee;;oBAYX;;cAQN"}
@@ -0,0 +1,142 @@
1
+ //#region src/transport/ws-server-transport.ts
2
+ /** 1 MB — stop sending and start queueing */
3
+ const HIGH_WATER_MARK = 1024 * 1024;
4
+ /** 256 KB — resume sending queued messages */
5
+ const LOW_WATER_MARK = 256 * 1024;
6
+ /** Interval for checking bufferedAmount drain (ms) */
7
+ const DRAIN_CHECK_INTERVAL = 50;
8
+ /** Maximum queued messages before dropping (backpressure safety valve) */
9
+ const MAX_QUEUE_SIZE = 1e4;
10
+ /**
11
+ * Server-side WebSocket transport for async-dom.
12
+ *
13
+ * Unlike the client-side WebSocketTransport, this does NOT handle reconnection.
14
+ * It accepts an already-connected WebSocketLike socket and wraps it with
15
+ * the Transport interface including backpressure handling.
16
+ */
17
+ var WebSocketServerTransport = class {
18
+ handlers = [];
19
+ _readyState;
20
+ _stats = {
21
+ messageCount: 0,
22
+ totalBytes: 0,
23
+ largestMessageBytes: 0,
24
+ lastMessageBytes: 0
25
+ };
26
+ _statsEnabled = false;
27
+ messageQueue = [];
28
+ drainTimer = null;
29
+ onError;
30
+ onClose;
31
+ constructor(socket) {
32
+ this.socket = socket;
33
+ this._readyState = this.mapReadyState(socket.readyState);
34
+ this.socket.onmessage = (event) => {
35
+ try {
36
+ const raw = typeof event.data === "string" ? event.data : String(event.data);
37
+ const data = JSON.parse(raw);
38
+ for (const h of this.handlers) try {
39
+ h(data);
40
+ } catch (err) {
41
+ console.error("[async-dom] Server transport handler error:", err);
42
+ }
43
+ } catch {
44
+ console.error("[async-dom] Failed to parse WebSocket message");
45
+ }
46
+ };
47
+ this.socket.onclose = (_event) => {
48
+ this._readyState = "closed";
49
+ this.stopDrainCheck();
50
+ this.onClose?.();
51
+ };
52
+ this.socket.onerror = (event) => {
53
+ this.stopDrainCheck();
54
+ this.messageQueue.length = 0;
55
+ this.onError?.(event instanceof Error ? event : /* @__PURE__ */ new Error("WebSocket error"));
56
+ };
57
+ }
58
+ mapReadyState(wsState) {
59
+ switch (wsState) {
60
+ case 0: return "connecting";
61
+ case 1: return "open";
62
+ case 2:
63
+ case 3: return "closed";
64
+ default: return "closed";
65
+ }
66
+ }
67
+ send(message) {
68
+ if (this._readyState === "closed") return;
69
+ if (this.socket.bufferedAmount > HIGH_WATER_MARK) {
70
+ if (this.messageQueue.length >= MAX_QUEUE_SIZE) this.messageQueue.shift();
71
+ this.messageQueue.push(message);
72
+ this.startDrainCheck();
73
+ return;
74
+ }
75
+ this.sendRaw(message);
76
+ }
77
+ sendRaw(message) {
78
+ try {
79
+ const json = JSON.stringify(message);
80
+ const bytes = json.length;
81
+ if (this._statsEnabled) {
82
+ this._stats.messageCount++;
83
+ this._stats.totalBytes += bytes;
84
+ this._stats.lastMessageBytes = bytes;
85
+ if (bytes > this._stats.largestMessageBytes) this._stats.largestMessageBytes = bytes;
86
+ }
87
+ this.socket.send(json);
88
+ } catch (err) {
89
+ this.onError?.(err instanceof Error ? err : /* @__PURE__ */ new Error("Send failed"));
90
+ }
91
+ }
92
+ startDrainCheck() {
93
+ if (this.drainTimer !== null) return;
94
+ this.drainTimer = setInterval(() => {
95
+ if (this.socket.bufferedAmount <= LOW_WATER_MARK) this.flushQueue();
96
+ if (this.messageQueue.length === 0) this.stopDrainCheck();
97
+ }, DRAIN_CHECK_INTERVAL);
98
+ }
99
+ stopDrainCheck() {
100
+ if (this.drainTimer !== null) {
101
+ clearInterval(this.drainTimer);
102
+ this.drainTimer = null;
103
+ }
104
+ }
105
+ flushQueue() {
106
+ if (this._readyState === "closed") {
107
+ this.messageQueue.length = 0;
108
+ return;
109
+ }
110
+ while (this.messageQueue.length > 0) {
111
+ if (this.socket.bufferedAmount > HIGH_WATER_MARK) return;
112
+ const msg = this.messageQueue.shift();
113
+ if (msg) this.sendRaw(msg);
114
+ }
115
+ }
116
+ onMessage(handler) {
117
+ this.handlers.push(handler);
118
+ }
119
+ close() {
120
+ if (this._readyState === "closed") return;
121
+ this._readyState = "closed";
122
+ this.stopDrainCheck();
123
+ this.messageQueue.length = 0;
124
+ this.socket.close(1e3, "Transport closed");
125
+ }
126
+ get readyState() {
127
+ return this._readyState;
128
+ }
129
+ get bufferedAmount() {
130
+ return this.socket.bufferedAmount;
131
+ }
132
+ getStats() {
133
+ return { ...this._stats };
134
+ }
135
+ enableStats(enabled) {
136
+ this._statsEnabled = enabled;
137
+ }
138
+ };
139
+ //#endregion
140
+ export { WebSocketServerTransport as t };
141
+
142
+ //# sourceMappingURL=ws-server-transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ws-server-transport.js","names":[],"sources":["../src/transport/ws-server-transport.ts"],"sourcesContent":["import type { Message } from \"../core/protocol.ts\";\nimport type { Transport, TransportReadyState, TransportStats } from \"./base.ts\";\n\n/**\n * Minimal WebSocket interface that works with any WebSocket server library\n * (ws, uWebSockets.js, Deno, Bun, etc.) without importing their types.\n */\nexport interface WebSocketLike {\n\t/** Send a string message through the socket. */\n\tsend(data: string): void;\n\t/** Close the socket with an optional status code and reason. */\n\tclose(code?: number, reason?: string): void;\n\t/** WebSocket readyState constant (0=CONNECTING, 1=OPEN, 2=CLOSING, 3=CLOSED). */\n\treadonly readyState: number;\n\t/** Number of bytes queued for sending but not yet transmitted. */\n\treadonly bufferedAmount: number;\n\t/** Handler called when a message is received. */\n\tonmessage: ((event: { data: unknown }) => void) | null;\n\t/** Handler called when the connection closes. */\n\tonclose: ((event: { code: number; reason: string }) => void) | null;\n\t/** Handler called when a connection error occurs. */\n\tonerror: ((event: unknown) => void) | null;\n}\n\n/** 1 MB — stop sending and start queueing */\nconst HIGH_WATER_MARK = 1024 * 1024;\n/** 256 KB — resume sending queued messages */\nconst LOW_WATER_MARK = 256 * 1024;\n/** Interval for checking bufferedAmount drain (ms) */\nconst DRAIN_CHECK_INTERVAL = 50;\n/** Maximum queued messages before dropping (backpressure safety valve) */\nconst MAX_QUEUE_SIZE = 10_000;\n\n/**\n * Server-side WebSocket transport for async-dom.\n *\n * Unlike the client-side WebSocketTransport, this does NOT handle reconnection.\n * It accepts an already-connected WebSocketLike socket and wraps it with\n * the Transport interface including backpressure handling.\n */\nexport class WebSocketServerTransport implements Transport {\n\tprivate handlers: Array<(message: Message) => void> = [];\n\tprivate _readyState: TransportReadyState;\n\tprivate _stats: TransportStats = {\n\t\tmessageCount: 0,\n\t\ttotalBytes: 0,\n\t\tlargestMessageBytes: 0,\n\t\tlastMessageBytes: 0,\n\t};\n\tprivate _statsEnabled = false;\n\tprivate messageQueue: Message[] = [];\n\tprivate drainTimer: ReturnType<typeof setInterval> | null = null;\n\n\tonError?: (error: Error) => void;\n\tonClose?: () => void;\n\n\tconstructor(private socket: WebSocketLike) {\n\t\t// Map initial readyState\n\t\tthis._readyState = this.mapReadyState(socket.readyState);\n\n\t\t// Wire incoming messages\n\t\tthis.socket.onmessage = (event: { data: unknown }) => {\n\t\t\ttry {\n\t\t\t\tconst raw = typeof event.data === \"string\" ? event.data : String(event.data);\n\t\t\t\tconst data = JSON.parse(raw) as Message;\n\t\t\t\tfor (const h of this.handlers) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\th(data);\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tconsole.error(\"[async-dom] Server transport handler error:\", err);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\tconsole.error(\"[async-dom] Failed to parse WebSocket message\");\n\t\t\t}\n\t\t};\n\n\t\t// Wire close\n\t\tthis.socket.onclose = (_event: { code: number; reason: string }) => {\n\t\t\tthis._readyState = \"closed\";\n\t\t\tthis.stopDrainCheck();\n\t\t\tthis.onClose?.();\n\t\t};\n\n\t\t// Wire error\n\t\tthis.socket.onerror = (event: unknown) => {\n\t\t\tthis.stopDrainCheck();\n\t\t\tthis.messageQueue.length = 0;\n\t\t\tthis.onError?.(event instanceof Error ? event : new Error(\"WebSocket error\"));\n\t\t};\n\t}\n\n\tprivate mapReadyState(wsState: number): TransportReadyState {\n\t\tswitch (wsState) {\n\t\t\tcase 0:\n\t\t\t\treturn \"connecting\";\n\t\t\tcase 1:\n\t\t\t\treturn \"open\";\n\t\t\tcase 2:\n\t\t\tcase 3:\n\t\t\t\treturn \"closed\";\n\t\t\tdefault:\n\t\t\t\treturn \"closed\";\n\t\t}\n\t}\n\n\tsend(message: Message): void {\n\t\tif (this._readyState === \"closed\") return;\n\n\t\t// Backpressure: queue if bufferedAmount exceeds high water mark\n\t\tif (this.socket.bufferedAmount > HIGH_WATER_MARK) {\n\t\t\tif (this.messageQueue.length >= MAX_QUEUE_SIZE) {\n\t\t\t\t// Safety valve: drop oldest messages to prevent unbounded memory growth\n\t\t\t\tthis.messageQueue.shift();\n\t\t\t}\n\t\t\tthis.messageQueue.push(message);\n\t\t\tthis.startDrainCheck();\n\t\t\treturn;\n\t\t}\n\n\t\tthis.sendRaw(message);\n\t}\n\n\tprivate sendRaw(message: Message): void {\n\t\ttry {\n\t\t\tconst json = JSON.stringify(message);\n\t\t\tconst bytes = json.length;\n\n\t\t\tif (this._statsEnabled) {\n\t\t\t\tthis._stats.messageCount++;\n\t\t\t\tthis._stats.totalBytes += bytes;\n\t\t\t\tthis._stats.lastMessageBytes = bytes;\n\t\t\t\tif (bytes > this._stats.largestMessageBytes) {\n\t\t\t\t\tthis._stats.largestMessageBytes = bytes;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.socket.send(json);\n\t\t} catch (err) {\n\t\t\tthis.onError?.(err instanceof Error ? err : new Error(\"Send failed\"));\n\t\t}\n\t}\n\n\tprivate startDrainCheck(): void {\n\t\tif (this.drainTimer !== null) return;\n\n\t\tthis.drainTimer = setInterval(() => {\n\t\t\tif (this.socket.bufferedAmount <= LOW_WATER_MARK) {\n\t\t\t\tthis.flushQueue();\n\t\t\t}\n\t\t\t// Stop checking if queue is empty\n\t\t\tif (this.messageQueue.length === 0) {\n\t\t\t\tthis.stopDrainCheck();\n\t\t\t}\n\t\t}, DRAIN_CHECK_INTERVAL);\n\t}\n\n\tprivate stopDrainCheck(): void {\n\t\tif (this.drainTimer !== null) {\n\t\t\tclearInterval(this.drainTimer);\n\t\t\tthis.drainTimer = null;\n\t\t}\n\t}\n\n\tprivate flushQueue(): void {\n\t\t// Fix 5: don't waste cycles flushing a closed transport\n\t\tif (this._readyState === \"closed\") {\n\t\t\tthis.messageQueue.length = 0;\n\t\t\treturn;\n\t\t}\n\t\twhile (this.messageQueue.length > 0) {\n\t\t\t// Re-check backpressure while flushing\n\t\t\tif (this.socket.bufferedAmount > HIGH_WATER_MARK) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst msg = this.messageQueue.shift();\n\t\t\tif (msg) {\n\t\t\t\tthis.sendRaw(msg);\n\t\t\t}\n\t\t}\n\t}\n\n\tonMessage(handler: (message: Message) => void): void {\n\t\tthis.handlers.push(handler);\n\t}\n\n\tclose(): void {\n\t\tif (this._readyState === \"closed\") return;\n\t\tthis._readyState = \"closed\";\n\t\tthis.stopDrainCheck();\n\t\tthis.messageQueue.length = 0;\n\t\tthis.socket.close(1000, \"Transport closed\");\n\t}\n\n\tget readyState(): TransportReadyState {\n\t\treturn this._readyState;\n\t}\n\n\tget bufferedAmount(): number {\n\t\treturn this.socket.bufferedAmount;\n\t}\n\n\tgetStats(): TransportStats {\n\t\treturn { ...this._stats };\n\t}\n\n\tenableStats(enabled: boolean): void {\n\t\tthis._statsEnabled = enabled;\n\t}\n}\n"],"mappings":";;AAyBA,MAAM,kBAAkB,OAAO;;AAE/B,MAAM,iBAAiB,MAAM;;AAE7B,MAAM,uBAAuB;;AAE7B,MAAM,iBAAiB;;;;;;;;AASvB,IAAa,2BAAb,MAA2D;CAC1D,WAAsD,EAAE;CACxD;CACA,SAAiC;EAChC,cAAc;EACd,YAAY;EACZ,qBAAqB;EACrB,kBAAkB;EAClB;CACD,gBAAwB;CACxB,eAAkC,EAAE;CACpC,aAA4D;CAE5D;CACA;CAEA,YAAY,QAA+B;AAAvB,OAAA,SAAA;AAEnB,OAAK,cAAc,KAAK,cAAc,OAAO,WAAW;AAGxD,OAAK,OAAO,aAAa,UAA6B;AACrD,OAAI;IACH,MAAM,MAAM,OAAO,MAAM,SAAS,WAAW,MAAM,OAAO,OAAO,MAAM,KAAK;IAC5E,MAAM,OAAO,KAAK,MAAM,IAAI;AAC5B,SAAK,MAAM,KAAK,KAAK,SACpB,KAAI;AACH,OAAE,KAAK;aACC,KAAK;AACb,aAAQ,MAAM,+CAA+C,IAAI;;WAG5D;AACP,YAAQ,MAAM,gDAAgD;;;AAKhE,OAAK,OAAO,WAAW,WAA6C;AACnE,QAAK,cAAc;AACnB,QAAK,gBAAgB;AACrB,QAAK,WAAW;;AAIjB,OAAK,OAAO,WAAW,UAAmB;AACzC,QAAK,gBAAgB;AACrB,QAAK,aAAa,SAAS;AAC3B,QAAK,UAAU,iBAAiB,QAAQ,wBAAQ,IAAI,MAAM,kBAAkB,CAAC;;;CAI/E,cAAsB,SAAsC;AAC3D,UAAQ,SAAR;GACC,KAAK,EACJ,QAAO;GACR,KAAK,EACJ,QAAO;GACR,KAAK;GACL,KAAK,EACJ,QAAO;GACR,QACC,QAAO;;;CAIV,KAAK,SAAwB;AAC5B,MAAI,KAAK,gBAAgB,SAAU;AAGnC,MAAI,KAAK,OAAO,iBAAiB,iBAAiB;AACjD,OAAI,KAAK,aAAa,UAAU,eAE/B,MAAK,aAAa,OAAO;AAE1B,QAAK,aAAa,KAAK,QAAQ;AAC/B,QAAK,iBAAiB;AACtB;;AAGD,OAAK,QAAQ,QAAQ;;CAGtB,QAAgB,SAAwB;AACvC,MAAI;GACH,MAAM,OAAO,KAAK,UAAU,QAAQ;GACpC,MAAM,QAAQ,KAAK;AAEnB,OAAI,KAAK,eAAe;AACvB,SAAK,OAAO;AACZ,SAAK,OAAO,cAAc;AAC1B,SAAK,OAAO,mBAAmB;AAC/B,QAAI,QAAQ,KAAK,OAAO,oBACvB,MAAK,OAAO,sBAAsB;;AAIpC,QAAK,OAAO,KAAK,KAAK;WACd,KAAK;AACb,QAAK,UAAU,eAAe,QAAQ,sBAAM,IAAI,MAAM,cAAc,CAAC;;;CAIvE,kBAAgC;AAC/B,MAAI,KAAK,eAAe,KAAM;AAE9B,OAAK,aAAa,kBAAkB;AACnC,OAAI,KAAK,OAAO,kBAAkB,eACjC,MAAK,YAAY;AAGlB,OAAI,KAAK,aAAa,WAAW,EAChC,MAAK,gBAAgB;KAEpB,qBAAqB;;CAGzB,iBAA+B;AAC9B,MAAI,KAAK,eAAe,MAAM;AAC7B,iBAAc,KAAK,WAAW;AAC9B,QAAK,aAAa;;;CAIpB,aAA2B;AAE1B,MAAI,KAAK,gBAAgB,UAAU;AAClC,QAAK,aAAa,SAAS;AAC3B;;AAED,SAAO,KAAK,aAAa,SAAS,GAAG;AAEpC,OAAI,KAAK,OAAO,iBAAiB,gBAChC;GAED,MAAM,MAAM,KAAK,aAAa,OAAO;AACrC,OAAI,IACH,MAAK,QAAQ,IAAI;;;CAKpB,UAAU,SAA2C;AACpD,OAAK,SAAS,KAAK,QAAQ;;CAG5B,QAAc;AACb,MAAI,KAAK,gBAAgB,SAAU;AACnC,OAAK,cAAc;AACnB,OAAK,gBAAgB;AACrB,OAAK,aAAa,SAAS;AAC3B,OAAK,OAAO,MAAM,KAAM,mBAAmB;;CAG5C,IAAI,aAAkC;AACrC,SAAO,KAAK;;CAGb,IAAI,iBAAyB;AAC5B,SAAO,KAAK,OAAO;;CAGpB,WAA2B;AAC1B,SAAO,EAAE,GAAG,KAAK,QAAQ;;CAG1B,YAAY,SAAwB;AACnC,OAAK,gBAAgB"}