@azure/ai-voicelive 1.0.0-alpha.20260105.1 → 1.0.0-alpha.20260106.1
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/index.d.ts +1 -1
- package/dist/browser/index.js +1 -1
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/models/index.d.ts +1 -1
- package/dist/browser/models/index.js +1 -1
- package/dist/browser/models/index.js.map +1 -1
- package/dist/browser/models/models.d.ts +357 -25
- package/dist/browser/models/models.js +361 -56
- package/dist/browser/models/models.js.map +1 -1
- package/dist/browser/protocol/messageParser.d.ts +1 -1
- package/dist/browser/protocol/messageParser.js +19 -76
- package/dist/browser/protocol/messageParser.js.map +1 -1
- package/dist/browser/voiceLiveSession.d.ts +2 -2
- package/dist/browser/voiceLiveSession.js +11 -10
- package/dist/browser/voiceLiveSession.js.map +1 -1
- package/dist/browser/websocket/websocket-browser.mjs.map +1 -0
- package/dist/browser/websocket/{websocketBrowser.d.ts → websocket.d.ts} +8 -2
- package/dist/{react-native/websocket/websocketBrowser.js → browser/websocket/websocket.js} +43 -3
- package/dist/browser/websocket/websocketFactory.d.ts +0 -11
- package/dist/browser/websocket/websocketFactory.js +2 -66
- package/dist/browser/websocket/websocketFactory.js.map +1 -1
- package/dist/browser/websocket/websocketLike.d.ts +3 -0
- package/dist/browser/websocket/websocketLike.js.map +1 -1
- package/dist/commonjs/index.d.ts +1 -1
- package/dist/commonjs/index.js +6 -1
- package/dist/commonjs/index.js.map +1 -1
- package/dist/commonjs/models/index.d.ts +1 -1
- package/dist/commonjs/models/index.js +6 -1
- package/dist/commonjs/models/index.js.map +1 -1
- package/dist/commonjs/models/models.d.ts +357 -25
- package/dist/commonjs/models/models.js +386 -59
- package/dist/commonjs/models/models.js.map +1 -1
- package/dist/commonjs/protocol/messageParser.d.ts +1 -1
- package/dist/commonjs/protocol/messageParser.js +18 -75
- package/dist/commonjs/protocol/messageParser.js.map +1 -1
- package/dist/commonjs/voiceLiveSession.d.ts +2 -2
- package/dist/commonjs/voiceLiveSession.js +20 -19
- package/dist/commonjs/voiceLiveSession.js.map +1 -1
- package/dist/{esm/websocket/websocketNode.d.ts → commonjs/websocket/websocket.d.ts} +2 -2
- package/dist/commonjs/websocket/{websocketNode.js → websocket.js} +31 -6
- package/dist/commonjs/websocket/websocket.js.map +1 -0
- package/dist/commonjs/websocket/websocketFactory.d.ts +0 -11
- package/dist/commonjs/websocket/websocketFactory.js +2 -68
- package/dist/commonjs/websocket/websocketFactory.js.map +1 -1
- package/dist/commonjs/websocket/websocketLike.d.ts +3 -0
- package/dist/commonjs/websocket/websocketLike.js.map +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/models/index.d.ts +1 -1
- package/dist/esm/models/index.js +1 -1
- package/dist/esm/models/index.js.map +1 -1
- package/dist/esm/models/models.d.ts +357 -25
- package/dist/esm/models/models.js +361 -56
- package/dist/esm/models/models.js.map +1 -1
- package/dist/esm/protocol/messageParser.d.ts +1 -1
- package/dist/esm/protocol/messageParser.js +19 -76
- package/dist/esm/protocol/messageParser.js.map +1 -1
- package/dist/esm/voiceLiveSession.d.ts +2 -2
- package/dist/esm/voiceLiveSession.js +11 -10
- package/dist/esm/voiceLiveSession.js.map +1 -1
- package/dist/{react-native/websocket/websocketNode.d.ts → esm/websocket/websocket.d.ts} +2 -2
- package/dist/{browser/websocket/websocketNode.js → esm/websocket/websocket.js} +29 -4
- package/dist/esm/websocket/websocket.js.map +1 -0
- package/dist/esm/websocket/websocketFactory.d.ts +0 -11
- package/dist/esm/websocket/websocketFactory.js +2 -66
- package/dist/esm/websocket/websocketFactory.js.map +1 -1
- package/dist/esm/websocket/websocketLike.d.ts +3 -0
- package/dist/esm/websocket/websocketLike.js.map +1 -1
- package/dist/react-native/index.d.ts +1 -1
- package/dist/react-native/index.js +1 -1
- package/dist/react-native/index.js.map +1 -1
- package/dist/react-native/models/index.d.ts +1 -1
- package/dist/react-native/models/index.js +1 -1
- package/dist/react-native/models/index.js.map +1 -1
- package/dist/react-native/models/models.d.ts +357 -25
- package/dist/react-native/models/models.js +361 -56
- package/dist/react-native/models/models.js.map +1 -1
- package/dist/react-native/protocol/messageParser.d.ts +1 -1
- package/dist/react-native/protocol/messageParser.js +19 -76
- package/dist/react-native/protocol/messageParser.js.map +1 -1
- package/dist/react-native/voiceLiveSession.d.ts +2 -2
- package/dist/react-native/voiceLiveSession.js +11 -10
- package/dist/react-native/voiceLiveSession.js.map +1 -1
- package/dist/{commonjs/websocket/websocketNode.d.ts → react-native/websocket/websocket.d.ts} +2 -2
- package/dist/{esm/websocket/websocketNode.js → react-native/websocket/websocket.js} +29 -4
- package/dist/react-native/websocket/websocket.js.map +1 -0
- package/dist/react-native/websocket/websocketFactory.d.ts +0 -11
- package/dist/react-native/websocket/websocketFactory.js +2 -66
- package/dist/react-native/websocket/websocketFactory.js.map +1 -1
- package/dist/react-native/websocket/websocketLike.d.ts +3 -0
- package/dist/react-native/websocket/websocketLike.js.map +1 -1
- package/package.json +15 -2
- package/dist/browser/websocket/websocketBrowser.js +0 -175
- package/dist/browser/websocket/websocketBrowser.js.map +0 -1
- package/dist/browser/websocket/websocketNode.d.ts +0 -26
- package/dist/browser/websocket/websocketNode.js.map +0 -1
- package/dist/commonjs/websocket/websocketBrowser.d.ts +0 -26
- package/dist/commonjs/websocket/websocketBrowser.js +0 -179
- package/dist/commonjs/websocket/websocketBrowser.js.map +0 -1
- package/dist/commonjs/websocket/websocketNode.js.map +0 -1
- package/dist/esm/websocket/websocketBrowser.d.ts +0 -26
- package/dist/esm/websocket/websocketBrowser.js +0 -175
- package/dist/esm/websocket/websocketBrowser.js.map +0 -1
- package/dist/esm/websocket/websocketNode.js.map +0 -1
- package/dist/react-native/websocket/websocketBrowser.d.ts +0 -26
- package/dist/react-native/websocket/websocketBrowser.js.map +0 -1
- package/dist/react-native/websocket/websocketNode.js +0 -180
- package/dist/react-native/websocket/websocketNode.js.map +0 -1
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Microsoft Corporation.
|
|
2
|
-
// Licensed under the MIT License.
|
|
3
|
-
import WebSocket from "ws";
|
|
4
|
-
import { WebSocketState, } from "./websocketLike.js";
|
|
5
|
-
import { VoiceLiveConnectionError, VoiceLiveErrorCodes } from "../errors/connectionErrors.js";
|
|
6
|
-
/**
|
|
7
|
-
* Node.js WebSocket implementation using 'ws' library
|
|
8
|
-
*/
|
|
9
|
-
export class VoiceLiveWebSocketNode {
|
|
10
|
-
_ws;
|
|
11
|
-
_url;
|
|
12
|
-
_options;
|
|
13
|
-
_onOpen;
|
|
14
|
-
_onClose;
|
|
15
|
-
_onMessage;
|
|
16
|
-
_onError;
|
|
17
|
-
constructor(options = {}) {
|
|
18
|
-
this._options = {
|
|
19
|
-
connectionTimeoutInMs: 30000,
|
|
20
|
-
maxMessageSize: 1024 * 1024, // 1MB
|
|
21
|
-
compression: true,
|
|
22
|
-
...options,
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
async connect(url, protocols, abortSignal) {
|
|
26
|
-
if (this._ws && this._ws.readyState !== WebSocket.CLOSED) {
|
|
27
|
-
throw new VoiceLiveConnectionError("WebSocket is already connected or connecting", VoiceLiveErrorCodes.AlreadyConnected);
|
|
28
|
-
}
|
|
29
|
-
return new Promise((resolve, reject) => {
|
|
30
|
-
const timeoutId = setTimeout(() => {
|
|
31
|
-
reject(new VoiceLiveConnectionError(`WebSocket connection timeout after ${this._options.connectionTimeoutInMs}ms`, VoiceLiveErrorCodes.ConnectionTimeout));
|
|
32
|
-
}, this._options.connectionTimeoutInMs);
|
|
33
|
-
// Handle abort signal
|
|
34
|
-
const abortHandler = () => {
|
|
35
|
-
clearTimeout(timeoutId);
|
|
36
|
-
if (this._ws) {
|
|
37
|
-
this._ws.terminate();
|
|
38
|
-
}
|
|
39
|
-
reject(new VoiceLiveConnectionError("WebSocket connection aborted", VoiceLiveErrorCodes.OperationCancelled));
|
|
40
|
-
};
|
|
41
|
-
if (abortSignal) {
|
|
42
|
-
if (abortSignal.aborted) {
|
|
43
|
-
abortHandler();
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
abortSignal.addEventListener("abort", abortHandler);
|
|
47
|
-
}
|
|
48
|
-
try {
|
|
49
|
-
this._ws = new WebSocket(url, protocols, {
|
|
50
|
-
headers: this._options.headers,
|
|
51
|
-
maxPayload: this._options.maxMessageSize,
|
|
52
|
-
perMessageDeflate: this._options.compression,
|
|
53
|
-
});
|
|
54
|
-
this._url = url;
|
|
55
|
-
this._ws.on("open", () => {
|
|
56
|
-
clearTimeout(timeoutId);
|
|
57
|
-
if (abortSignal) {
|
|
58
|
-
abortSignal.removeEventListener("abort", abortHandler);
|
|
59
|
-
}
|
|
60
|
-
this._onOpen?.();
|
|
61
|
-
resolve();
|
|
62
|
-
});
|
|
63
|
-
this._ws.on("close", (code, reason) => {
|
|
64
|
-
clearTimeout(timeoutId);
|
|
65
|
-
if (abortSignal) {
|
|
66
|
-
abortSignal.removeEventListener("abort", abortHandler);
|
|
67
|
-
}
|
|
68
|
-
this._onClose?.(code, reason.toString());
|
|
69
|
-
});
|
|
70
|
-
this._ws.on("message", (data) => {
|
|
71
|
-
if (typeof data === "string") {
|
|
72
|
-
this._onMessage?.(data);
|
|
73
|
-
}
|
|
74
|
-
else if (data instanceof Buffer) {
|
|
75
|
-
// Convert Buffer to ArrayBuffer
|
|
76
|
-
const arrayBuffer = new ArrayBuffer(data.length);
|
|
77
|
-
const view = new Uint8Array(arrayBuffer);
|
|
78
|
-
view.set(data);
|
|
79
|
-
this._onMessage?.(arrayBuffer);
|
|
80
|
-
}
|
|
81
|
-
else if (data instanceof ArrayBuffer) {
|
|
82
|
-
this._onMessage?.(data);
|
|
83
|
-
}
|
|
84
|
-
else {
|
|
85
|
-
// Handle other data types by converting to ArrayBuffer
|
|
86
|
-
const buffer = Buffer.from(data);
|
|
87
|
-
const arrayBuffer = new ArrayBuffer(buffer.length);
|
|
88
|
-
const view = new Uint8Array(arrayBuffer);
|
|
89
|
-
view.set(buffer);
|
|
90
|
-
this._onMessage?.(arrayBuffer);
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
this._ws.on("error", (error) => {
|
|
94
|
-
clearTimeout(timeoutId);
|
|
95
|
-
if (abortSignal) {
|
|
96
|
-
abortSignal.removeEventListener("abort", abortHandler);
|
|
97
|
-
}
|
|
98
|
-
this._onError?.(error);
|
|
99
|
-
reject(new VoiceLiveConnectionError(`WebSocket error: ${error.message}`, VoiceLiveErrorCodes.WebSocketError, "websocket_connection", true, // Potentially recoverable
|
|
100
|
-
error));
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
catch (error) {
|
|
104
|
-
clearTimeout(timeoutId);
|
|
105
|
-
if (abortSignal) {
|
|
106
|
-
abortSignal.removeEventListener("abort", abortHandler);
|
|
107
|
-
}
|
|
108
|
-
reject(new VoiceLiveConnectionError(`Failed to create WebSocket: ${error instanceof Error ? error.message : "Unknown error"}`, VoiceLiveErrorCodes.ConnectionFailed, "websocket_creation", false, error instanceof Error ? error : new Error(String(error))));
|
|
109
|
-
}
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
async disconnect(code = 1000, reason) {
|
|
113
|
-
if (!this._ws || this._ws.readyState === WebSocket.CLOSED) {
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
return new Promise((resolve) => {
|
|
117
|
-
const closeHandler = () => {
|
|
118
|
-
resolve();
|
|
119
|
-
};
|
|
120
|
-
if (this._ws.readyState === WebSocket.CLOSING) {
|
|
121
|
-
this._ws.once("close", closeHandler);
|
|
122
|
-
}
|
|
123
|
-
else {
|
|
124
|
-
this._ws.once("close", closeHandler);
|
|
125
|
-
this._ws.close(code, reason);
|
|
126
|
-
}
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
async send(data, abortSignal) {
|
|
130
|
-
if (!this._ws || this._ws.readyState !== WebSocket.OPEN) {
|
|
131
|
-
throw new VoiceLiveConnectionError("WebSocket is not connected", VoiceLiveErrorCodes.NotConnected);
|
|
132
|
-
}
|
|
133
|
-
if (abortSignal?.aborted) {
|
|
134
|
-
throw new VoiceLiveConnectionError("Send operation aborted", VoiceLiveErrorCodes.OperationCancelled);
|
|
135
|
-
}
|
|
136
|
-
return new Promise((resolve, reject) => {
|
|
137
|
-
const abortHandler = () => {
|
|
138
|
-
reject(new VoiceLiveConnectionError("Send operation aborted", VoiceLiveErrorCodes.OperationCancelled));
|
|
139
|
-
};
|
|
140
|
-
if (abortSignal) {
|
|
141
|
-
abortSignal.addEventListener("abort", abortHandler);
|
|
142
|
-
}
|
|
143
|
-
this._ws.send(data, (error) => {
|
|
144
|
-
if (abortSignal) {
|
|
145
|
-
abortSignal.removeEventListener("abort", abortHandler);
|
|
146
|
-
}
|
|
147
|
-
if (error) {
|
|
148
|
-
reject(new VoiceLiveConnectionError(`Failed to send WebSocket message: ${error.message}`, VoiceLiveErrorCodes.WebSocketError, "message_send", true, error));
|
|
149
|
-
}
|
|
150
|
-
else {
|
|
151
|
-
resolve();
|
|
152
|
-
}
|
|
153
|
-
});
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
onOpen(handler) {
|
|
157
|
-
this._onOpen = handler;
|
|
158
|
-
}
|
|
159
|
-
onClose(handler) {
|
|
160
|
-
this._onClose = handler;
|
|
161
|
-
}
|
|
162
|
-
onMessage(handler) {
|
|
163
|
-
this._onMessage = handler;
|
|
164
|
-
}
|
|
165
|
-
onError(handler) {
|
|
166
|
-
this._onError = handler;
|
|
167
|
-
}
|
|
168
|
-
get isConnected() {
|
|
169
|
-
return this._ws?.readyState === WebSocket.OPEN;
|
|
170
|
-
}
|
|
171
|
-
get readyState() {
|
|
172
|
-
if (!this._ws)
|
|
173
|
-
return WebSocketState.Closed;
|
|
174
|
-
return this._ws.readyState;
|
|
175
|
-
}
|
|
176
|
-
get url() {
|
|
177
|
-
return this._url;
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
//# sourceMappingURL=websocketNode.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"websocketNode.js","sourceRoot":"","sources":["../../../src/websocket/websocketNode.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { AbortSignalLike } from \"@azure/abort-controller\";\nimport WebSocket from \"ws\";\nimport {\n WebSocketState,\n type VoiceLiveWebSocketLike,\n type WebSocketFactoryOptions,\n} from \"./websocketLike.js\";\nimport { VoiceLiveConnectionError, VoiceLiveErrorCodes } from \"../errors/connectionErrors.js\";\n\n/**\n * Node.js WebSocket implementation using 'ws' library\n */\nexport class VoiceLiveWebSocketNode implements VoiceLiveWebSocketLike {\n private _ws?: WebSocket;\n private _url?: string;\n private _options: WebSocketFactoryOptions;\n\n private _onOpen?: () => void;\n private _onClose?: (code: number, reason: string) => void;\n private _onMessage?: (data: string | ArrayBuffer) => void;\n private _onError?: (error: Error) => void;\n\n constructor(options: WebSocketFactoryOptions = {}) {\n this._options = {\n connectionTimeoutInMs: 30000,\n maxMessageSize: 1024 * 1024, // 1MB\n compression: true,\n ...options,\n };\n }\n\n async connect(url: string, protocols?: string[], abortSignal?: AbortSignalLike): Promise<void> {\n if (this._ws && this._ws.readyState !== WebSocket.CLOSED) {\n throw new VoiceLiveConnectionError(\n \"WebSocket is already connected or connecting\",\n VoiceLiveErrorCodes.AlreadyConnected,\n );\n }\n\n return new Promise((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n reject(\n new VoiceLiveConnectionError(\n `WebSocket connection timeout after ${this._options.connectionTimeoutInMs}ms`,\n VoiceLiveErrorCodes.ConnectionTimeout,\n ),\n );\n }, this._options.connectionTimeoutInMs);\n\n // Handle abort signal\n const abortHandler = (): void => {\n clearTimeout(timeoutId);\n if (this._ws) {\n this._ws.terminate();\n }\n reject(\n new VoiceLiveConnectionError(\n \"WebSocket connection aborted\",\n VoiceLiveErrorCodes.OperationCancelled,\n ),\n );\n };\n\n if (abortSignal) {\n if (abortSignal.aborted) {\n abortHandler();\n return;\n }\n abortSignal.addEventListener(\"abort\", abortHandler);\n }\n\n try {\n this._ws = new WebSocket(url, protocols, {\n headers: this._options.headers,\n maxPayload: this._options.maxMessageSize,\n perMessageDeflate: this._options.compression,\n });\n\n this._url = url;\n\n this._ws.on(\"open\", () => {\n clearTimeout(timeoutId);\n if (abortSignal) {\n abortSignal.removeEventListener(\"abort\", abortHandler);\n }\n this._onOpen?.();\n resolve();\n });\n\n this._ws.on(\"close\", (code: number, reason: Buffer) => {\n clearTimeout(timeoutId);\n if (abortSignal) {\n abortSignal.removeEventListener(\"abort\", abortHandler);\n }\n this._onClose?.(code, reason.toString());\n });\n\n this._ws.on(\"message\", (data: WebSocket.Data) => {\n if (typeof data === \"string\") {\n this._onMessage?.(data);\n } else if (data instanceof Buffer) {\n // Convert Buffer to ArrayBuffer\n const arrayBuffer = new ArrayBuffer(data.length);\n const view = new Uint8Array(arrayBuffer);\n view.set(data);\n this._onMessage?.(arrayBuffer);\n } else if (data instanceof ArrayBuffer) {\n this._onMessage?.(data);\n } else {\n // Handle other data types by converting to ArrayBuffer\n const buffer = Buffer.from(data as any);\n const arrayBuffer = new ArrayBuffer(buffer.length);\n const view = new Uint8Array(arrayBuffer);\n view.set(buffer);\n this._onMessage?.(arrayBuffer);\n }\n });\n\n this._ws.on(\"error\", (error: Error) => {\n clearTimeout(timeoutId);\n if (abortSignal) {\n abortSignal.removeEventListener(\"abort\", abortHandler);\n }\n this._onError?.(error);\n reject(\n new VoiceLiveConnectionError(\n `WebSocket error: ${error.message}`,\n VoiceLiveErrorCodes.WebSocketError,\n \"websocket_connection\",\n true, // Potentially recoverable\n error,\n ),\n );\n });\n } catch (error) {\n clearTimeout(timeoutId);\n if (abortSignal) {\n abortSignal.removeEventListener(\"abort\", abortHandler);\n }\n reject(\n new VoiceLiveConnectionError(\n `Failed to create WebSocket: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n VoiceLiveErrorCodes.ConnectionFailed,\n \"websocket_creation\",\n false,\n error instanceof Error ? error : new Error(String(error)),\n ),\n );\n }\n });\n }\n\n async disconnect(code: number = 1000, reason?: string): Promise<void> {\n if (!this._ws || this._ws.readyState === WebSocket.CLOSED) {\n return;\n }\n\n return new Promise((resolve) => {\n const closeHandler = (): void => {\n resolve();\n };\n\n if (this._ws!.readyState === WebSocket.CLOSING) {\n this._ws!.once(\"close\", closeHandler);\n } else {\n this._ws!.once(\"close\", closeHandler);\n this._ws!.close(code, reason);\n }\n });\n }\n\n async send(data: string | ArrayBuffer, abortSignal?: AbortSignalLike): Promise<void> {\n if (!this._ws || this._ws.readyState !== WebSocket.OPEN) {\n throw new VoiceLiveConnectionError(\n \"WebSocket is not connected\",\n VoiceLiveErrorCodes.NotConnected,\n );\n }\n\n if (abortSignal?.aborted) {\n throw new VoiceLiveConnectionError(\n \"Send operation aborted\",\n VoiceLiveErrorCodes.OperationCancelled,\n );\n }\n\n return new Promise((resolve, reject) => {\n const abortHandler = (): void => {\n reject(\n new VoiceLiveConnectionError(\n \"Send operation aborted\",\n VoiceLiveErrorCodes.OperationCancelled,\n ),\n );\n };\n\n if (abortSignal) {\n abortSignal.addEventListener(\"abort\", abortHandler);\n }\n\n this._ws!.send(data, (error?: Error) => {\n if (abortSignal) {\n abortSignal.removeEventListener(\"abort\", abortHandler);\n }\n\n if (error) {\n reject(\n new VoiceLiveConnectionError(\n `Failed to send WebSocket message: ${error.message}`,\n VoiceLiveErrorCodes.WebSocketError,\n \"message_send\",\n true,\n error,\n ),\n );\n } else {\n resolve();\n }\n });\n });\n }\n\n onOpen(handler: () => void): void {\n this._onOpen = handler;\n }\n\n onClose(handler: (code: number, reason: string) => void): void {\n this._onClose = handler;\n }\n\n onMessage(handler: (data: string | ArrayBuffer) => void): void {\n this._onMessage = handler;\n }\n\n onError(handler: (error: Error) => void): void {\n this._onError = handler;\n }\n\n get isConnected(): boolean {\n return this._ws?.readyState === WebSocket.OPEN;\n }\n\n get readyState(): WebSocketState {\n if (!this._ws) return WebSocketState.Closed;\n return this._ws.readyState as WebSocketState;\n }\n\n get url(): string | undefined {\n return this._url;\n }\n}\n"]}
|