@azure/ai-voicelive 1.0.0-alpha.20251117.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.
Files changed (212) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +358 -0
  3. package/dist/browser/auth/credentialHandler.d.ts +43 -0
  4. package/dist/browser/auth/credentialHandler.js +147 -0
  5. package/dist/browser/auth/credentialHandler.js.map +1 -0
  6. package/dist/browser/errors/connectionErrors.d.ts +68 -0
  7. package/dist/browser/errors/connectionErrors.js +136 -0
  8. package/dist/browser/errors/connectionErrors.js.map +1 -0
  9. package/dist/browser/errors/index.d.ts +2 -0
  10. package/dist/browser/errors/index.js +4 -0
  11. package/dist/browser/errors/index.js.map +1 -0
  12. package/dist/browser/handlers/sessionHandlers.d.ts +250 -0
  13. package/dist/browser/handlers/sessionHandlers.js +4 -0
  14. package/dist/browser/handlers/sessionHandlers.js.map +1 -0
  15. package/dist/browser/handlers/subscriptionManager.d.ts +54 -0
  16. package/dist/browser/handlers/subscriptionManager.js +250 -0
  17. package/dist/browser/handlers/subscriptionManager.js.map +1 -0
  18. package/dist/browser/index.d.ts +7 -0
  19. package/dist/browser/index.js +12 -0
  20. package/dist/browser/index.js.map +1 -0
  21. package/dist/browser/logger.d.ts +2 -0
  22. package/dist/browser/logger.js +5 -0
  23. package/dist/browser/logger.js.map +1 -0
  24. package/dist/browser/models/index.d.ts +2 -0
  25. package/dist/browser/models/index.js +4 -0
  26. package/dist/browser/models/index.js.map +1 -0
  27. package/dist/browser/models/models.d.ts +2154 -0
  28. package/dist/browser/models/models.js +2251 -0
  29. package/dist/browser/models/models.js.map +1 -0
  30. package/dist/browser/package.json +3 -0
  31. package/dist/browser/protocol/messageParser.d.ts +42 -0
  32. package/dist/browser/protocol/messageParser.js +150 -0
  33. package/dist/browser/protocol/messageParser.js.map +1 -0
  34. package/dist/browser/voiceLiveClient.d.ts +65 -0
  35. package/dist/browser/voiceLiveClient.js +81 -0
  36. package/dist/browser/voiceLiveClient.js.map +1 -0
  37. package/dist/browser/voiceLiveSession.d.ts +138 -0
  38. package/dist/browser/voiceLiveSession.js +429 -0
  39. package/dist/browser/voiceLiveSession.js.map +1 -0
  40. package/dist/browser/websocket/connectionManager.d.ts +88 -0
  41. package/dist/browser/websocket/connectionManager.js +183 -0
  42. package/dist/browser/websocket/connectionManager.js.map +1 -0
  43. package/dist/browser/websocket/websocketBrowser.d.ts +26 -0
  44. package/dist/browser/websocket/websocketBrowser.js +175 -0
  45. package/dist/browser/websocket/websocketBrowser.js.map +1 -0
  46. package/dist/browser/websocket/websocketFactory.d.ts +23 -0
  47. package/dist/browser/websocket/websocketFactory.js +80 -0
  48. package/dist/browser/websocket/websocketFactory.js.map +1 -0
  49. package/dist/browser/websocket/websocketLike.d.ts +78 -0
  50. package/dist/browser/websocket/websocketLike.js +13 -0
  51. package/dist/browser/websocket/websocketLike.js.map +1 -0
  52. package/dist/browser/websocket/websocketNode.d.ts +26 -0
  53. package/dist/browser/websocket/websocketNode.js +180 -0
  54. package/dist/browser/websocket/websocketNode.js.map +1 -0
  55. package/dist/commonjs/auth/credentialHandler.d.ts +43 -0
  56. package/dist/commonjs/auth/credentialHandler.js +151 -0
  57. package/dist/commonjs/auth/credentialHandler.js.map +1 -0
  58. package/dist/commonjs/errors/connectionErrors.d.ts +68 -0
  59. package/dist/commonjs/errors/connectionErrors.js +146 -0
  60. package/dist/commonjs/errors/connectionErrors.js.map +1 -0
  61. package/dist/commonjs/errors/index.d.ts +2 -0
  62. package/dist/commonjs/errors/index.js +7 -0
  63. package/dist/commonjs/errors/index.js.map +1 -0
  64. package/dist/commonjs/handlers/sessionHandlers.d.ts +250 -0
  65. package/dist/commonjs/handlers/sessionHandlers.js +5 -0
  66. package/dist/commonjs/handlers/sessionHandlers.js.map +1 -0
  67. package/dist/commonjs/handlers/subscriptionManager.d.ts +54 -0
  68. package/dist/commonjs/handlers/subscriptionManager.js +255 -0
  69. package/dist/commonjs/handlers/subscriptionManager.js.map +1 -0
  70. package/dist/commonjs/index.d.ts +7 -0
  71. package/dist/commonjs/index.js +45 -0
  72. package/dist/commonjs/index.js.map +1 -0
  73. package/dist/commonjs/logger.d.ts +2 -0
  74. package/dist/commonjs/logger.js +8 -0
  75. package/dist/commonjs/logger.js.map +1 -0
  76. package/dist/commonjs/models/index.d.ts +2 -0
  77. package/dist/commonjs/models/index.js +27 -0
  78. package/dist/commonjs/models/index.js.map +1 -0
  79. package/dist/commonjs/models/models.d.ts +2154 -0
  80. package/dist/commonjs/models/models.js +2463 -0
  81. package/dist/commonjs/models/models.js.map +1 -0
  82. package/dist/commonjs/package.json +3 -0
  83. package/dist/commonjs/protocol/messageParser.d.ts +42 -0
  84. package/dist/commonjs/protocol/messageParser.js +154 -0
  85. package/dist/commonjs/protocol/messageParser.js.map +1 -0
  86. package/dist/commonjs/tsdoc-metadata.json +11 -0
  87. package/dist/commonjs/voiceLiveClient.d.ts +65 -0
  88. package/dist/commonjs/voiceLiveClient.js +85 -0
  89. package/dist/commonjs/voiceLiveClient.js.map +1 -0
  90. package/dist/commonjs/voiceLiveSession.d.ts +138 -0
  91. package/dist/commonjs/voiceLiveSession.js +433 -0
  92. package/dist/commonjs/voiceLiveSession.js.map +1 -0
  93. package/dist/commonjs/websocket/connectionManager.d.ts +88 -0
  94. package/dist/commonjs/websocket/connectionManager.js +187 -0
  95. package/dist/commonjs/websocket/connectionManager.js.map +1 -0
  96. package/dist/commonjs/websocket/websocketBrowser.d.ts +26 -0
  97. package/dist/commonjs/websocket/websocketBrowser.js +179 -0
  98. package/dist/commonjs/websocket/websocketBrowser.js.map +1 -0
  99. package/dist/commonjs/websocket/websocketFactory.d.ts +23 -0
  100. package/dist/commonjs/websocket/websocketFactory.js +86 -0
  101. package/dist/commonjs/websocket/websocketFactory.js.map +1 -0
  102. package/dist/commonjs/websocket/websocketLike.d.ts +78 -0
  103. package/dist/commonjs/websocket/websocketLike.js +16 -0
  104. package/dist/commonjs/websocket/websocketLike.js.map +1 -0
  105. package/dist/commonjs/websocket/websocketNode.d.ts +26 -0
  106. package/dist/commonjs/websocket/websocketNode.js +185 -0
  107. package/dist/commonjs/websocket/websocketNode.js.map +1 -0
  108. package/dist/esm/auth/credentialHandler.d.ts +43 -0
  109. package/dist/esm/auth/credentialHandler.js +147 -0
  110. package/dist/esm/auth/credentialHandler.js.map +1 -0
  111. package/dist/esm/errors/connectionErrors.d.ts +68 -0
  112. package/dist/esm/errors/connectionErrors.js +136 -0
  113. package/dist/esm/errors/connectionErrors.js.map +1 -0
  114. package/dist/esm/errors/index.d.ts +2 -0
  115. package/dist/esm/errors/index.js +4 -0
  116. package/dist/esm/errors/index.js.map +1 -0
  117. package/dist/esm/handlers/sessionHandlers.d.ts +250 -0
  118. package/dist/esm/handlers/sessionHandlers.js +4 -0
  119. package/dist/esm/handlers/sessionHandlers.js.map +1 -0
  120. package/dist/esm/handlers/subscriptionManager.d.ts +54 -0
  121. package/dist/esm/handlers/subscriptionManager.js +250 -0
  122. package/dist/esm/handlers/subscriptionManager.js.map +1 -0
  123. package/dist/esm/index.d.ts +7 -0
  124. package/dist/esm/index.js +12 -0
  125. package/dist/esm/index.js.map +1 -0
  126. package/dist/esm/logger.d.ts +2 -0
  127. package/dist/esm/logger.js +5 -0
  128. package/dist/esm/logger.js.map +1 -0
  129. package/dist/esm/models/index.d.ts +2 -0
  130. package/dist/esm/models/index.js +4 -0
  131. package/dist/esm/models/index.js.map +1 -0
  132. package/dist/esm/models/models.d.ts +2154 -0
  133. package/dist/esm/models/models.js +2251 -0
  134. package/dist/esm/models/models.js.map +1 -0
  135. package/dist/esm/package.json +3 -0
  136. package/dist/esm/protocol/messageParser.d.ts +42 -0
  137. package/dist/esm/protocol/messageParser.js +150 -0
  138. package/dist/esm/protocol/messageParser.js.map +1 -0
  139. package/dist/esm/voiceLiveClient.d.ts +65 -0
  140. package/dist/esm/voiceLiveClient.js +81 -0
  141. package/dist/esm/voiceLiveClient.js.map +1 -0
  142. package/dist/esm/voiceLiveSession.d.ts +138 -0
  143. package/dist/esm/voiceLiveSession.js +429 -0
  144. package/dist/esm/voiceLiveSession.js.map +1 -0
  145. package/dist/esm/websocket/connectionManager.d.ts +88 -0
  146. package/dist/esm/websocket/connectionManager.js +183 -0
  147. package/dist/esm/websocket/connectionManager.js.map +1 -0
  148. package/dist/esm/websocket/websocketBrowser.d.ts +26 -0
  149. package/dist/esm/websocket/websocketBrowser.js +175 -0
  150. package/dist/esm/websocket/websocketBrowser.js.map +1 -0
  151. package/dist/esm/websocket/websocketFactory.d.ts +23 -0
  152. package/dist/esm/websocket/websocketFactory.js +80 -0
  153. package/dist/esm/websocket/websocketFactory.js.map +1 -0
  154. package/dist/esm/websocket/websocketLike.d.ts +78 -0
  155. package/dist/esm/websocket/websocketLike.js +13 -0
  156. package/dist/esm/websocket/websocketLike.js.map +1 -0
  157. package/dist/esm/websocket/websocketNode.d.ts +26 -0
  158. package/dist/esm/websocket/websocketNode.js +180 -0
  159. package/dist/esm/websocket/websocketNode.js.map +1 -0
  160. package/dist/react-native/auth/credentialHandler.d.ts +43 -0
  161. package/dist/react-native/auth/credentialHandler.js +147 -0
  162. package/dist/react-native/auth/credentialHandler.js.map +1 -0
  163. package/dist/react-native/errors/connectionErrors.d.ts +68 -0
  164. package/dist/react-native/errors/connectionErrors.js +136 -0
  165. package/dist/react-native/errors/connectionErrors.js.map +1 -0
  166. package/dist/react-native/errors/index.d.ts +2 -0
  167. package/dist/react-native/errors/index.js +4 -0
  168. package/dist/react-native/errors/index.js.map +1 -0
  169. package/dist/react-native/handlers/sessionHandlers.d.ts +250 -0
  170. package/dist/react-native/handlers/sessionHandlers.js +4 -0
  171. package/dist/react-native/handlers/sessionHandlers.js.map +1 -0
  172. package/dist/react-native/handlers/subscriptionManager.d.ts +54 -0
  173. package/dist/react-native/handlers/subscriptionManager.js +250 -0
  174. package/dist/react-native/handlers/subscriptionManager.js.map +1 -0
  175. package/dist/react-native/index.d.ts +7 -0
  176. package/dist/react-native/index.js +12 -0
  177. package/dist/react-native/index.js.map +1 -0
  178. package/dist/react-native/logger.d.ts +2 -0
  179. package/dist/react-native/logger.js +5 -0
  180. package/dist/react-native/logger.js.map +1 -0
  181. package/dist/react-native/models/index.d.ts +2 -0
  182. package/dist/react-native/models/index.js +4 -0
  183. package/dist/react-native/models/index.js.map +1 -0
  184. package/dist/react-native/models/models.d.ts +2154 -0
  185. package/dist/react-native/models/models.js +2251 -0
  186. package/dist/react-native/models/models.js.map +1 -0
  187. package/dist/react-native/package.json +3 -0
  188. package/dist/react-native/protocol/messageParser.d.ts +42 -0
  189. package/dist/react-native/protocol/messageParser.js +150 -0
  190. package/dist/react-native/protocol/messageParser.js.map +1 -0
  191. package/dist/react-native/voiceLiveClient.d.ts +65 -0
  192. package/dist/react-native/voiceLiveClient.js +81 -0
  193. package/dist/react-native/voiceLiveClient.js.map +1 -0
  194. package/dist/react-native/voiceLiveSession.d.ts +138 -0
  195. package/dist/react-native/voiceLiveSession.js +429 -0
  196. package/dist/react-native/voiceLiveSession.js.map +1 -0
  197. package/dist/react-native/websocket/connectionManager.d.ts +88 -0
  198. package/dist/react-native/websocket/connectionManager.js +183 -0
  199. package/dist/react-native/websocket/connectionManager.js.map +1 -0
  200. package/dist/react-native/websocket/websocketBrowser.d.ts +26 -0
  201. package/dist/react-native/websocket/websocketBrowser.js +175 -0
  202. package/dist/react-native/websocket/websocketBrowser.js.map +1 -0
  203. package/dist/react-native/websocket/websocketFactory.d.ts +23 -0
  204. package/dist/react-native/websocket/websocketFactory.js +80 -0
  205. package/dist/react-native/websocket/websocketFactory.js.map +1 -0
  206. package/dist/react-native/websocket/websocketLike.d.ts +78 -0
  207. package/dist/react-native/websocket/websocketLike.js +13 -0
  208. package/dist/react-native/websocket/websocketLike.js.map +1 -0
  209. package/dist/react-native/websocket/websocketNode.d.ts +26 -0
  210. package/dist/react-native/websocket/websocketNode.js +180 -0
  211. package/dist/react-native/websocket/websocketNode.js.map +1 -0
  212. package/package.json +150 -0
@@ -0,0 +1,183 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+ import { VoiceLiveConnectionError, VoiceLiveErrorCodes, classifyWebSocketClose, } from "../errors/index.js";
4
+ import { logger } from "../logger.js";
5
+ /**
6
+ * Connection state enumeration for lifecycle management
7
+ */
8
+ export var ConnectionState;
9
+ (function (ConnectionState) {
10
+ ConnectionState["Disconnected"] = "disconnected";
11
+ ConnectionState["Connecting"] = "connecting";
12
+ ConnectionState["Connected"] = "connected";
13
+ ConnectionState["Disconnecting"] = "disconnecting";
14
+ // Removed: Reconnecting - no reconnection in fail-fast model
15
+ })(ConnectionState || (ConnectionState = {}));
16
+ /**
17
+ * Manages WebSocket connection lifecycle with fail-fast semantics
18
+ */
19
+ export class ConnectionManager {
20
+ _websocketFactory;
21
+ _options;
22
+ _eventHandlers;
23
+ _state = ConnectionState.Disconnected;
24
+ _previousState = ConnectionState.Disconnected;
25
+ _websocket;
26
+ _abortController;
27
+ constructor(_websocketFactory, _options, _eventHandlers = {}) {
28
+ this._websocketFactory = _websocketFactory;
29
+ this._options = _options;
30
+ this._eventHandlers = _eventHandlers;
31
+ // No reconnection setup needed - fail fast model
32
+ }
33
+ /**
34
+ * Initiates a WebSocket connection
35
+ */
36
+ async connect(abortSignal) {
37
+ if (this._state === ConnectionState.Connected) {
38
+ return;
39
+ }
40
+ if (this._state === ConnectionState.Connecting) {
41
+ throw new VoiceLiveConnectionError("Connection attempt already in progress", VoiceLiveErrorCodes.InvalidState);
42
+ }
43
+ this._setState(ConnectionState.Connecting);
44
+ // Create new abort controller for this connection attempt
45
+ this._abortController = new AbortController();
46
+ // Chain with provided abort signal
47
+ if (abortSignal) {
48
+ if (abortSignal.aborted) {
49
+ this._abortController.abort();
50
+ }
51
+ else {
52
+ abortSignal.addEventListener("abort", () => {
53
+ this._abortController?.abort();
54
+ });
55
+ }
56
+ }
57
+ try {
58
+ this._websocket = this._websocketFactory();
59
+ this._setupWebSocketHandlers();
60
+ await this._websocket.connect(this._options.endpoint, this._options.protocols, this._abortController.signal);
61
+ this._setState(ConnectionState.Connected);
62
+ }
63
+ catch (error) {
64
+ this._setState(ConnectionState.Disconnected);
65
+ if (error instanceof VoiceLiveConnectionError) {
66
+ throw error;
67
+ }
68
+ else {
69
+ throw new VoiceLiveConnectionError(`Failed to connect: ${error instanceof Error ? error.message : "Unknown error"}`, VoiceLiveErrorCodes.ConnectionFailed, "connection_attempt", true, error instanceof Error ? error : new Error(String(error)));
70
+ }
71
+ }
72
+ }
73
+ /**
74
+ * Disconnects the WebSocket connection
75
+ */
76
+ async disconnect(_abortSignal) {
77
+ if (this._state === ConnectionState.Disconnected) {
78
+ return;
79
+ }
80
+ // Abort any ongoing connection attempt
81
+ this._abortController?.abort();
82
+ this._setState(ConnectionState.Disconnecting);
83
+ try {
84
+ if (this._websocket) {
85
+ await this._websocket.disconnect(1000, "Client disconnect");
86
+ }
87
+ }
88
+ finally {
89
+ this._setState(ConnectionState.Disconnected);
90
+ }
91
+ }
92
+ /**
93
+ * Sends data through the WebSocket connection
94
+ */
95
+ async send(data, abortSignal) {
96
+ if (!this._websocket || this._state !== ConnectionState.Connected) {
97
+ throw new VoiceLiveConnectionError("Cannot send message: WebSocket not connected", VoiceLiveErrorCodes.NotConnected);
98
+ }
99
+ return this._websocket.send(data, abortSignal);
100
+ }
101
+ /**
102
+ * Sets up event handlers for the WebSocket instance
103
+ */
104
+ _setupWebSocketHandlers() {
105
+ if (!this._websocket)
106
+ return;
107
+ logger.info("Setting up WebSocket event handlers");
108
+ this._websocket.onOpen(() => {
109
+ logger.info("WebSocket connection opened");
110
+ // Connection opened - handled in connect() method
111
+ });
112
+ this._websocket.onClose((code, reason) => {
113
+ this._handleConnectionLost(code, reason);
114
+ });
115
+ this._websocket.onError((error) => {
116
+ this._handleConnectionError(error);
117
+ });
118
+ this._websocket.onMessage((data) => {
119
+ this._eventHandlers.onMessage?.(data);
120
+ });
121
+ }
122
+ /**
123
+ * Handles any connection loss - always fatal in fail-fast model
124
+ */
125
+ _handleConnectionLost(code, reason) {
126
+ // Check if this was an expected disconnection before changing state
127
+ if (this._state === ConnectionState.Disconnecting) {
128
+ // This was an expected disconnection, don't treat as error
129
+ this._setState(ConnectionState.Disconnected);
130
+ return;
131
+ }
132
+ this._setState(ConnectionState.Disconnected);
133
+ // In fail-fast model, ANY unexpected connection loss is fatal
134
+ let error;
135
+ if (code === 1000) {
136
+ // Normal close, but unexpected
137
+ error = new VoiceLiveConnectionError("WebSocket connection closed unexpectedly", VoiceLiveErrorCodes.ConnectionLost, "connection_lost");
138
+ }
139
+ else {
140
+ // Use classifier for other codes
141
+ error = classifyWebSocketClose(code, reason);
142
+ }
143
+ // Always notify of fatal error for unexpected disconnections
144
+ this._eventHandlers.onError?.(error);
145
+ }
146
+ /**
147
+ * Handles WebSocket errors
148
+ */
149
+ _handleConnectionError(error) {
150
+ const connectionError = new VoiceLiveConnectionError(`WebSocket error: ${error.message}`, VoiceLiveErrorCodes.WebSocketError, "websocket_error", true, error);
151
+ this._eventHandlers.onError?.(connectionError);
152
+ }
153
+ /**
154
+ * Updates the connection state and notifies handlers
155
+ */
156
+ _setState(state) {
157
+ if (this._state !== state) {
158
+ this._previousState = this._state;
159
+ this._state = state;
160
+ this._eventHandlers.onStateChange?.(state, this._previousState);
161
+ }
162
+ }
163
+ // Public properties and methods
164
+ /**
165
+ * Gets the current connection state
166
+ */
167
+ get state() {
168
+ return this._state;
169
+ }
170
+ /**
171
+ * Checks if the connection is currently established
172
+ */
173
+ get isConnected() {
174
+ return this._state === ConnectionState.Connected;
175
+ }
176
+ /**
177
+ * Updates the event handlers
178
+ */
179
+ updateEventHandlers(handlers) {
180
+ Object.assign(this._eventHandlers, handlers);
181
+ }
182
+ }
183
+ //# sourceMappingURL=connectionManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connectionManager.js","sourceRoot":"","sources":["../../../src/websocket/connectionManager.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 type { VoiceLiveWebSocketLike } from \"./websocketLike.js\";\nimport {\n VoiceLiveConnectionError,\n VoiceLiveErrorCodes,\n classifyWebSocketClose,\n} from \"../errors/index.js\";\nimport { logger } from \"../logger.js\";\n\n/**\n * Connection state enumeration for lifecycle management\n */\nexport enum ConnectionState {\n Disconnected = \"disconnected\",\n Connecting = \"connecting\",\n Connected = \"connected\",\n Disconnecting = \"disconnecting\",\n // Removed: Reconnecting - no reconnection in fail-fast model\n}\n\n/**\n * Configuration options for connection management\n */\nexport interface ConnectionOptions {\n /** WebSocket endpoint URL */\n endpoint: string;\n /** WebSocket protocols to use */\n protocols?: string[];\n /** Connection timeout in milliseconds */\n connectionTimeout?: number;\n // Removed all reconnection options - fail fast model\n}\n\n/**\n * Event handlers for connection lifecycle events\n */\nexport interface ConnectionEventHandlers {\n /** Called when connection state changes */\n onStateChange?: (state: ConnectionState, previousState: ConnectionState) => void;\n /** Called when a message is received */\n onMessage?: (data: string | ArrayBuffer) => void;\n /** Called when an error occurs or connection is lost */\n onError?: (error: VoiceLiveConnectionError) => void;\n // Removed: onReconnectAttempt - no reconnection in fail-fast model\n}\n\n/**\n * Manages WebSocket connection lifecycle with fail-fast semantics\n */\nexport class ConnectionManager {\n private _state: ConnectionState = ConnectionState.Disconnected;\n private _previousState: ConnectionState = ConnectionState.Disconnected;\n private _websocket?: VoiceLiveWebSocketLike;\n private _abortController?: AbortController;\n\n constructor(\n private _websocketFactory: () => VoiceLiveWebSocketLike,\n private _options: ConnectionOptions,\n private _eventHandlers: ConnectionEventHandlers = {},\n ) {\n // No reconnection setup needed - fail fast model\n }\n\n /**\n * Initiates a WebSocket connection\n */\n async connect(abortSignal?: AbortSignalLike): Promise<void> {\n if (this._state === ConnectionState.Connected) {\n return;\n }\n\n if (this._state === ConnectionState.Connecting) {\n throw new VoiceLiveConnectionError(\n \"Connection attempt already in progress\",\n VoiceLiveErrorCodes.InvalidState,\n );\n }\n\n this._setState(ConnectionState.Connecting);\n\n // Create new abort controller for this connection attempt\n this._abortController = new AbortController();\n\n // Chain with provided abort signal\n if (abortSignal) {\n if (abortSignal.aborted) {\n this._abortController.abort();\n } else {\n abortSignal.addEventListener(\"abort\", () => {\n this._abortController?.abort();\n });\n }\n }\n\n try {\n this._websocket = this._websocketFactory();\n this._setupWebSocketHandlers();\n\n await this._websocket.connect(\n this._options.endpoint,\n this._options.protocols,\n this._abortController.signal,\n );\n\n this._setState(ConnectionState.Connected);\n } catch (error) {\n this._setState(ConnectionState.Disconnected);\n\n if (error instanceof VoiceLiveConnectionError) {\n throw error;\n } else {\n throw new VoiceLiveConnectionError(\n `Failed to connect: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n VoiceLiveErrorCodes.ConnectionFailed,\n \"connection_attempt\",\n true,\n error instanceof Error ? error : new Error(String(error)),\n );\n }\n }\n }\n\n /**\n * Disconnects the WebSocket connection\n */\n async disconnect(_abortSignal?: AbortSignalLike): Promise<void> {\n if (this._state === ConnectionState.Disconnected) {\n return;\n }\n\n // Abort any ongoing connection attempt\n this._abortController?.abort();\n\n this._setState(ConnectionState.Disconnecting);\n\n try {\n if (this._websocket) {\n await this._websocket.disconnect(1000, \"Client disconnect\");\n }\n } finally {\n this._setState(ConnectionState.Disconnected);\n }\n }\n\n /**\n * Sends data through the WebSocket connection\n */\n async send(data: string | ArrayBuffer, abortSignal?: AbortSignalLike): Promise<void> {\n if (!this._websocket || this._state !== ConnectionState.Connected) {\n throw new VoiceLiveConnectionError(\n \"Cannot send message: WebSocket not connected\",\n VoiceLiveErrorCodes.NotConnected,\n );\n }\n\n return this._websocket.send(data, abortSignal);\n }\n\n /**\n * Sets up event handlers for the WebSocket instance\n */\n private _setupWebSocketHandlers(): void {\n if (!this._websocket) return;\n logger.info(\"Setting up WebSocket event handlers\");\n this._websocket.onOpen(() => {\n logger.info(\"WebSocket connection opened\");\n // Connection opened - handled in connect() method\n });\n\n this._websocket.onClose((code, reason) => {\n this._handleConnectionLost(code, reason);\n });\n\n this._websocket.onError((error) => {\n this._handleConnectionError(error);\n });\n\n this._websocket.onMessage((data) => {\n this._eventHandlers.onMessage?.(data);\n });\n }\n\n /**\n * Handles any connection loss - always fatal in fail-fast model\n */\n private _handleConnectionLost(code: number, reason: string): void {\n // Check if this was an expected disconnection before changing state\n if (this._state === ConnectionState.Disconnecting) {\n // This was an expected disconnection, don't treat as error\n this._setState(ConnectionState.Disconnected);\n return;\n }\n\n this._setState(ConnectionState.Disconnected);\n\n // In fail-fast model, ANY unexpected connection loss is fatal\n let error: VoiceLiveConnectionError;\n\n if (code === 1000) {\n // Normal close, but unexpected\n error = new VoiceLiveConnectionError(\n \"WebSocket connection closed unexpectedly\",\n VoiceLiveErrorCodes.ConnectionLost,\n \"connection_lost\",\n );\n } else {\n // Use classifier for other codes\n error = classifyWebSocketClose(code, reason);\n }\n\n // Always notify of fatal error for unexpected disconnections\n this._eventHandlers.onError?.(error);\n }\n\n /**\n * Handles WebSocket errors\n */\n private _handleConnectionError(error: Error): void {\n const connectionError = new VoiceLiveConnectionError(\n `WebSocket error: ${error.message}`,\n VoiceLiveErrorCodes.WebSocketError,\n \"websocket_error\",\n true,\n error,\n );\n\n this._eventHandlers.onError?.(connectionError);\n }\n\n /**\n * Updates the connection state and notifies handlers\n */\n private _setState(state: ConnectionState): void {\n if (this._state !== state) {\n this._previousState = this._state;\n this._state = state;\n this._eventHandlers.onStateChange?.(state, this._previousState);\n }\n }\n\n // Public properties and methods\n\n /**\n * Gets the current connection state\n */\n get state(): ConnectionState {\n return this._state;\n }\n\n /**\n * Checks if the connection is currently established\n */\n get isConnected(): boolean {\n return this._state === ConnectionState.Connected;\n }\n\n /**\n * Updates the event handlers\n */\n updateEventHandlers(handlers: Partial<ConnectionEventHandlers>): void {\n Object.assign(this._eventHandlers, handlers);\n }\n}\n"]}
@@ -0,0 +1,26 @@
1
+ import type { AbortSignalLike } from "@azure/abort-controller";
2
+ import { WebSocketState, type VoiceLiveWebSocketLike, type WebSocketFactoryOptions } from "./websocketLike.js";
3
+ /**
4
+ * Browser WebSocket implementation using native WebSocket API
5
+ */
6
+ export declare class VoiceLiveWebSocketBrowser implements VoiceLiveWebSocketLike {
7
+ private _ws?;
8
+ private _url?;
9
+ private _options;
10
+ private _onOpen?;
11
+ private _onClose?;
12
+ private _onMessage?;
13
+ private _onError?;
14
+ constructor(options?: WebSocketFactoryOptions);
15
+ connect(url: string, protocols?: string[], abortSignal?: AbortSignalLike): Promise<void>;
16
+ disconnect(code?: number, reason?: string): Promise<void>;
17
+ send(data: string | ArrayBuffer, abortSignal?: AbortSignalLike): Promise<void>;
18
+ onOpen(handler: () => void): void;
19
+ onClose(handler: (code: number, reason: string) => void): void;
20
+ onMessage(handler: (data: string | ArrayBuffer) => void): void;
21
+ onError(handler: (error: Error) => void): void;
22
+ get isConnected(): boolean;
23
+ get readyState(): WebSocketState;
24
+ get url(): string | undefined;
25
+ }
26
+ //# sourceMappingURL=websocketBrowser.d.ts.map
@@ -0,0 +1,175 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+ import { WebSocketState, } from "./websocketLike.js";
4
+ import { VoiceLiveConnectionError, VoiceLiveErrorCodes } from "../errors/connectionErrors.js";
5
+ /**
6
+ * Browser WebSocket implementation using native WebSocket API
7
+ */
8
+ export class VoiceLiveWebSocketBrowser {
9
+ _ws;
10
+ _url;
11
+ _options;
12
+ _onOpen;
13
+ _onClose;
14
+ _onMessage;
15
+ _onError;
16
+ constructor(options = {}) {
17
+ this._options = {
18
+ connectionTimeoutInMs: 30000,
19
+ maxMessageSize: 1024 * 1024, // 1MB
20
+ ...options,
21
+ };
22
+ }
23
+ async connect(url, protocols, abortSignal) {
24
+ if (this._ws && this._ws.readyState !== WebSocket.CLOSED) {
25
+ throw new VoiceLiveConnectionError("WebSocket is already connected or connecting", VoiceLiveErrorCodes.AlreadyConnected);
26
+ }
27
+ return new Promise((resolve, reject) => {
28
+ const timeoutId = setTimeout(() => {
29
+ reject(new VoiceLiveConnectionError(`WebSocket connection timeout after ${this._options.connectionTimeoutInMs}ms`, VoiceLiveErrorCodes.ConnectionTimeout));
30
+ }, this._options.connectionTimeoutInMs);
31
+ // Handle abort signal
32
+ const abortHandler = () => {
33
+ clearTimeout(timeoutId);
34
+ if (this._ws) {
35
+ this._ws.close();
36
+ }
37
+ reject(new VoiceLiveConnectionError("WebSocket connection aborted", VoiceLiveErrorCodes.OperationCancelled));
38
+ };
39
+ if (abortSignal) {
40
+ if (abortSignal.aborted) {
41
+ abortHandler();
42
+ return;
43
+ }
44
+ abortSignal.addEventListener("abort", abortHandler);
45
+ }
46
+ try {
47
+ this._ws = new WebSocket(url, protocols);
48
+ this._ws.binaryType = "arraybuffer";
49
+ this._url = url;
50
+ this._ws.addEventListener("open", () => {
51
+ clearTimeout(timeoutId);
52
+ if (abortSignal) {
53
+ abortSignal.removeEventListener("abort", abortHandler);
54
+ }
55
+ this._onOpen?.();
56
+ resolve();
57
+ });
58
+ this._ws.addEventListener("close", (event) => {
59
+ clearTimeout(timeoutId);
60
+ if (abortSignal) {
61
+ abortSignal.removeEventListener("abort", abortHandler);
62
+ }
63
+ this._onClose?.(event.code, event.reason);
64
+ });
65
+ this._ws.addEventListener("message", (event) => {
66
+ if (typeof event.data === "string") {
67
+ this._onMessage?.(event.data);
68
+ }
69
+ else if (event.data instanceof ArrayBuffer) {
70
+ this._onMessage?.(event.data);
71
+ }
72
+ else if (event.data instanceof Blob) {
73
+ // Convert Blob to ArrayBuffer
74
+ const reader = new FileReader();
75
+ reader.onload = () => {
76
+ if (reader.result instanceof ArrayBuffer) {
77
+ this._onMessage?.(reader.result);
78
+ }
79
+ };
80
+ reader.onerror = () => {
81
+ this._onError?.(new VoiceLiveConnectionError("Failed to read blob data", VoiceLiveErrorCodes.WebSocketError, "blob_read"));
82
+ };
83
+ reader.readAsArrayBuffer(event.data);
84
+ }
85
+ });
86
+ this._ws.addEventListener("error", () => {
87
+ clearTimeout(timeoutId);
88
+ if (abortSignal) {
89
+ abortSignal.removeEventListener("abort", abortHandler);
90
+ }
91
+ const error = new VoiceLiveConnectionError("WebSocket connection failed", VoiceLiveErrorCodes.WebSocketError, "websocket_connection", true);
92
+ this._onError?.(error);
93
+ reject(error);
94
+ });
95
+ }
96
+ catch (error) {
97
+ clearTimeout(timeoutId);
98
+ if (abortSignal) {
99
+ abortSignal.removeEventListener("abort", abortHandler);
100
+ }
101
+ 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))));
102
+ }
103
+ });
104
+ }
105
+ async disconnect(code = 1000, reason) {
106
+ if (!this._ws || this._ws.readyState === WebSocket.CLOSED) {
107
+ return;
108
+ }
109
+ return new Promise((resolve) => {
110
+ const closeHandler = () => {
111
+ resolve();
112
+ };
113
+ if (this._ws.readyState === WebSocket.CLOSING) {
114
+ this._ws.addEventListener("close", closeHandler, { once: true });
115
+ }
116
+ else {
117
+ this._ws.addEventListener("close", closeHandler, { once: true });
118
+ this._ws.close(code, reason);
119
+ }
120
+ });
121
+ }
122
+ async send(data, abortSignal) {
123
+ if (!this._ws || this._ws.readyState !== WebSocket.OPEN) {
124
+ throw new VoiceLiveConnectionError("WebSocket is not connected", VoiceLiveErrorCodes.NotConnected);
125
+ }
126
+ if (abortSignal?.aborted) {
127
+ throw new VoiceLiveConnectionError("Send operation aborted", VoiceLiveErrorCodes.OperationCancelled);
128
+ }
129
+ return new Promise((resolve, reject) => {
130
+ const abortHandler = () => {
131
+ reject(new VoiceLiveConnectionError("Send operation aborted", VoiceLiveErrorCodes.OperationCancelled));
132
+ };
133
+ if (abortSignal) {
134
+ abortSignal.addEventListener("abort", abortHandler, { once: true });
135
+ }
136
+ try {
137
+ this._ws.send(data);
138
+ if (abortSignal) {
139
+ abortSignal.removeEventListener("abort", abortHandler);
140
+ }
141
+ resolve();
142
+ }
143
+ catch (error) {
144
+ if (abortSignal) {
145
+ abortSignal.removeEventListener("abort", abortHandler);
146
+ }
147
+ reject(new VoiceLiveConnectionError(`Failed to send WebSocket message: ${error instanceof Error ? error.message : "Unknown error"}`, VoiceLiveErrorCodes.WebSocketError, "message_send", true, error instanceof Error ? error : new Error(String(error))));
148
+ }
149
+ });
150
+ }
151
+ onOpen(handler) {
152
+ this._onOpen = handler;
153
+ }
154
+ onClose(handler) {
155
+ this._onClose = handler;
156
+ }
157
+ onMessage(handler) {
158
+ this._onMessage = handler;
159
+ }
160
+ onError(handler) {
161
+ this._onError = handler;
162
+ }
163
+ get isConnected() {
164
+ return this._ws?.readyState === WebSocket.OPEN;
165
+ }
166
+ get readyState() {
167
+ if (!this._ws)
168
+ return WebSocketState.Closed;
169
+ return this._ws.readyState;
170
+ }
171
+ get url() {
172
+ return this._url;
173
+ }
174
+ }
175
+ //# sourceMappingURL=websocketBrowser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"websocketBrowser.js","sourceRoot":"","sources":["../../../src/websocket/websocketBrowser.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 {\n WebSocketState,\n type VoiceLiveWebSocketLike,\n type WebSocketFactoryOptions,\n} from \"./websocketLike.js\";\nimport { VoiceLiveConnectionError, VoiceLiveErrorCodes } from \"../errors/connectionErrors.js\";\n\n/**\n * Browser WebSocket implementation using native WebSocket API\n */\nexport class VoiceLiveWebSocketBrowser 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 ...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 // Handle abort signal\n const abortHandler = (): void => {\n clearTimeout(timeoutId);\n if (this._ws) {\n this._ws.close();\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 this._ws.binaryType = \"arraybuffer\";\n this._url = url;\n\n this._ws.addEventListener(\"open\", () => {\n clearTimeout(timeoutId);\n if (abortSignal) {\n abortSignal.removeEventListener(\"abort\", abortHandler);\n }\n this._onOpen?.();\n resolve();\n });\n\n this._ws.addEventListener(\"close\", (event: CloseEvent) => {\n clearTimeout(timeoutId);\n if (abortSignal) {\n abortSignal.removeEventListener(\"abort\", abortHandler);\n }\n this._onClose?.(event.code, event.reason);\n });\n\n this._ws.addEventListener(\"message\", (event: MessageEvent) => {\n if (typeof event.data === \"string\") {\n this._onMessage?.(event.data);\n } else if (event.data instanceof ArrayBuffer) {\n this._onMessage?.(event.data);\n } else if (event.data instanceof Blob) {\n // Convert Blob to ArrayBuffer\n const reader = new FileReader();\n reader.onload = () => {\n if (reader.result instanceof ArrayBuffer) {\n this._onMessage?.(reader.result);\n }\n };\n reader.onerror = () => {\n this._onError?.(\n new VoiceLiveConnectionError(\n \"Failed to read blob data\",\n VoiceLiveErrorCodes.WebSocketError,\n \"blob_read\",\n ),\n );\n };\n reader.readAsArrayBuffer(event.data);\n }\n });\n\n this._ws.addEventListener(\"error\", () => {\n clearTimeout(timeoutId);\n if (abortSignal) {\n abortSignal.removeEventListener(\"abort\", abortHandler);\n }\n const error = new VoiceLiveConnectionError(\n \"WebSocket connection failed\",\n VoiceLiveErrorCodes.WebSocketError,\n \"websocket_connection\",\n true,\n );\n this._onError?.(error);\n reject(error);\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!.addEventListener(\"close\", closeHandler, { once: true });\n } else {\n this._ws!.addEventListener(\"close\", closeHandler, { once: true });\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, { once: true });\n }\n\n try {\n this._ws!.send(data);\n if (abortSignal) {\n abortSignal.removeEventListener(\"abort\", abortHandler);\n }\n resolve();\n } catch (error) {\n if (abortSignal) {\n abortSignal.removeEventListener(\"abort\", abortHandler);\n }\n reject(\n new VoiceLiveConnectionError(\n `Failed to send WebSocket message: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n VoiceLiveErrorCodes.WebSocketError,\n \"message_send\",\n true,\n error instanceof Error ? error : new Error(String(error)),\n ),\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"]}
@@ -0,0 +1,23 @@
1
+ import type { VoiceLiveWebSocketLike, VoiceLiveWebSocketFactoryLike, WebSocketFactoryOptions } from "./websocketLike.js";
2
+ /**
3
+ * Factory for creating platform-appropriate WebSocket instances
4
+ */
5
+ export declare class VoiceLiveWebSocketFactory implements VoiceLiveWebSocketFactoryLike {
6
+ create(options?: WebSocketFactoryOptions): VoiceLiveWebSocketLike;
7
+ private _createBrowserWebSocket;
8
+ private _createNodeWebSocket;
9
+ private _detectPlatform;
10
+ }
11
+ /**
12
+ * Platform detection utility
13
+ */
14
+ export declare function detectPlatform(): "browser" | "node" | "unknown";
15
+ /**
16
+ * Check if platform supports WebSocket
17
+ */
18
+ export declare function isWebSocketSupported(): boolean;
19
+ /**
20
+ * Default factory instance
21
+ */
22
+ export declare const defaultWebSocketFactory: VoiceLiveWebSocketFactory;
23
+ //# sourceMappingURL=websocketFactory.d.ts.map
@@ -0,0 +1,80 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+ /**
4
+ * Factory for creating platform-appropriate WebSocket instances
5
+ */
6
+ export class VoiceLiveWebSocketFactory {
7
+ create(options) {
8
+ const platform = this._detectPlatform();
9
+ switch (platform) {
10
+ case "browser":
11
+ return this._createBrowserWebSocket(options);
12
+ case "node":
13
+ return this._createNodeWebSocket(options);
14
+ default:
15
+ throw new Error(`Unsupported environment for WebSocket: ${platform}`);
16
+ }
17
+ }
18
+ _createBrowserWebSocket(options) {
19
+ // Use dynamic require to avoid bundling Node.js specific code in browser builds
20
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
21
+ const { VoiceLiveWebSocketBrowser } = require("./websocketBrowser.js");
22
+ return new VoiceLiveWebSocketBrowser(options);
23
+ }
24
+ _createNodeWebSocket(options) {
25
+ // Use dynamic require to avoid bundling browser specific code in Node.js builds
26
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
27
+ const { VoiceLiveWebSocketNode } = require("./websocketNode.js");
28
+ return new VoiceLiveWebSocketNode(options);
29
+ }
30
+ _detectPlatform() {
31
+ // Check for browser environment
32
+ if (typeof self !== "undefined" && typeof self.WebSocket !== "undefined") {
33
+ return "browser";
34
+ }
35
+ // Check for Node.js environment
36
+ if (typeof process !== "undefined" &&
37
+ process.versions != null &&
38
+ process.versions.node != null) {
39
+ return "node";
40
+ }
41
+ // Check for global object (Node.js) vs window (browser)
42
+ if (typeof global !== "undefined" && typeof require !== "undefined") {
43
+ return "node";
44
+ }
45
+ return "unknown";
46
+ }
47
+ }
48
+ /**
49
+ * Platform detection utility
50
+ */
51
+ export function detectPlatform() {
52
+ const factory = new VoiceLiveWebSocketFactory();
53
+ return factory._detectPlatform();
54
+ }
55
+ /**
56
+ * Check if platform supports WebSocket
57
+ */
58
+ export function isWebSocketSupported() {
59
+ const platform = detectPlatform();
60
+ switch (platform) {
61
+ case "browser":
62
+ return typeof WebSocket !== "undefined";
63
+ case "node":
64
+ try {
65
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
66
+ require("ws");
67
+ return true;
68
+ }
69
+ catch {
70
+ return false;
71
+ }
72
+ default:
73
+ return false;
74
+ }
75
+ }
76
+ /**
77
+ * Default factory instance
78
+ */
79
+ export const defaultWebSocketFactory = new VoiceLiveWebSocketFactory();
80
+ //# sourceMappingURL=websocketFactory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"websocketFactory.js","sourceRoot":"","sources":["../../../src/websocket/websocketFactory.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAQlC;;GAEG;AACH,MAAM,OAAO,yBAAyB;IACpC,MAAM,CAAC,OAAiC;QACtC,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;QAExC,QAAQ,QAAQ,EAAE,CAAC;YACjB,KAAK,SAAS;gBACZ,OAAO,IAAI,CAAC,uBAAuB,CAAC,OAAO,CAAC,CAAC;YAE/C,KAAK,MAAM;gBACT,OAAO,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC;YAE5C;gBACE,MAAM,IAAI,KAAK,CAAC,0CAA0C,QAAQ,EAAE,CAAC,CAAC;QAC1E,CAAC;IACH,CAAC;IAEO,uBAAuB,CAAC,OAAiC;QAC/D,gFAAgF;QAChF,iEAAiE;QACjE,MAAM,EAAE,yBAAyB,EAAE,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAAC;QACvE,OAAO,IAAI,yBAAyB,CAAC,OAAO,CAAC,CAAC;IAChD,CAAC;IAEO,oBAAoB,CAAC,OAAiC;QAC5D,gFAAgF;QAChF,iEAAiE;QACjE,MAAM,EAAE,sBAAsB,EAAE,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;QACjE,OAAO,IAAI,sBAAsB,CAAC,OAAO,CAAC,CAAC;IAC7C,CAAC;IAEO,eAAe;QACrB,gCAAgC;QAChC,IAAI,OAAO,IAAI,KAAK,WAAW,IAAI,OAAQ,IAAY,CAAC,SAAS,KAAK,WAAW,EAAE,CAAC;YAClF,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,gCAAgC;QAChC,IACE,OAAO,OAAO,KAAK,WAAW;YAC9B,OAAO,CAAC,QAAQ,IAAI,IAAI;YACxB,OAAO,CAAC,QAAQ,CAAC,IAAI,IAAI,IAAI,EAC7B,CAAC;YACD,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,wDAAwD;QACxD,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,OAAO,OAAO,KAAK,WAAW,EAAE,CAAC;YACpE,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;CACF;AAED;;GAEG;AACH,MAAM,UAAU,cAAc;IAC5B,MAAM,OAAO,GAAG,IAAI,yBAAyB,EAAE,CAAC;IAChD,OAAQ,OAAe,CAAC,eAAe,EAAE,CAAC;AAC5C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB;IAClC,MAAM,QAAQ,GAAG,cAAc,EAAE,CAAC;IAElC,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,SAAS;YACZ,OAAO,OAAO,SAAS,KAAK,WAAW,CAAC;QAE1C,KAAK,MAAM;YACT,IAAI,CAAC;gBACH,iEAAiE;gBACjE,OAAO,CAAC,IAAI,CAAC,CAAC;gBACd,OAAO,IAAI,CAAC;YACd,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,KAAK,CAAC;YACf,CAAC;QAEH;YACE,OAAO,KAAK,CAAC;IACjB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,IAAI,yBAAyB,EAAE,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type {\n VoiceLiveWebSocketLike,\n VoiceLiveWebSocketFactoryLike,\n WebSocketFactoryOptions,\n} from \"./websocketLike.js\";\n\n/**\n * Factory for creating platform-appropriate WebSocket instances\n */\nexport class VoiceLiveWebSocketFactory implements VoiceLiveWebSocketFactoryLike {\n create(options?: WebSocketFactoryOptions): VoiceLiveWebSocketLike {\n const platform = this._detectPlatform();\n\n switch (platform) {\n case \"browser\":\n return this._createBrowserWebSocket(options);\n\n case \"node\":\n return this._createNodeWebSocket(options);\n\n default:\n throw new Error(`Unsupported environment for WebSocket: ${platform}`);\n }\n }\n\n private _createBrowserWebSocket(options?: WebSocketFactoryOptions): VoiceLiveWebSocketLike {\n // Use dynamic require to avoid bundling Node.js specific code in browser builds\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { VoiceLiveWebSocketBrowser } = require(\"./websocketBrowser.js\");\n return new VoiceLiveWebSocketBrowser(options);\n }\n\n private _createNodeWebSocket(options?: WebSocketFactoryOptions): VoiceLiveWebSocketLike {\n // Use dynamic require to avoid bundling browser specific code in Node.js builds\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { VoiceLiveWebSocketNode } = require(\"./websocketNode.js\");\n return new VoiceLiveWebSocketNode(options);\n }\n\n private _detectPlatform(): \"browser\" | \"node\" | \"unknown\" {\n // Check for browser environment\n if (typeof self !== \"undefined\" && typeof (self as any).WebSocket !== \"undefined\") {\n return \"browser\";\n }\n\n // Check for Node.js environment\n if (\n typeof process !== \"undefined\" &&\n process.versions != null &&\n process.versions.node != null\n ) {\n return \"node\";\n }\n\n // Check for global object (Node.js) vs window (browser)\n if (typeof global !== \"undefined\" && typeof require !== \"undefined\") {\n return \"node\";\n }\n\n return \"unknown\";\n }\n}\n\n/**\n * Platform detection utility\n */\nexport function detectPlatform(): \"browser\" | \"node\" | \"unknown\" {\n const factory = new VoiceLiveWebSocketFactory();\n return (factory as any)._detectPlatform();\n}\n\n/**\n * Check if platform supports WebSocket\n */\nexport function isWebSocketSupported(): boolean {\n const platform = detectPlatform();\n\n switch (platform) {\n case \"browser\":\n return typeof WebSocket !== \"undefined\";\n\n case \"node\":\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n require(\"ws\");\n return true;\n } catch {\n return false;\n }\n\n default:\n return false;\n }\n}\n\n/**\n * Default factory instance\n */\nexport const defaultWebSocketFactory = new VoiceLiveWebSocketFactory();\n"]}
@@ -0,0 +1,78 @@
1
+ import type { AbortSignalLike } from "@azure/abort-controller";
2
+ /**
3
+ * WebSocket ready state enumeration matching standard WebSocket values
4
+ */
5
+ export declare enum WebSocketState {
6
+ Connecting = 0,
7
+ Open = 1,
8
+ Closing = 2,
9
+ Closed = 3
10
+ }
11
+ /**
12
+ * Options for WebSocket creation and connection
13
+ */
14
+ export interface WebSocketFactoryOptions {
15
+ /** Connection timeout in milliseconds */
16
+ connectionTimeoutInMs?: number;
17
+ /** Maximum message size in bytes */
18
+ maxMessageSize?: number;
19
+ /** Enable compression if supported */
20
+ compression?: boolean;
21
+ /** Custom headers for connection (Node.js only) */
22
+ headers?: Record<string, string>;
23
+ }
24
+ /**
25
+ * Platform-agnostic WebSocket interface for Voice Live connections
26
+ */
27
+ export interface VoiceLiveWebSocketLike {
28
+ /**
29
+ * Establishes WebSocket connection to the specified URL
30
+ */
31
+ connect(url: string, protocols?: string[], abortSignal?: AbortSignalLike): Promise<void>;
32
+ /**
33
+ * Closes the WebSocket connection
34
+ */
35
+ disconnect(code?: number, reason?: string): Promise<void>;
36
+ /**
37
+ * Sends data through the WebSocket connection
38
+ */
39
+ send(data: string | ArrayBuffer, abortSignal?: AbortSignalLike): Promise<void>;
40
+ /**
41
+ * Registers handler for connection open event
42
+ */
43
+ onOpen(handler: () => void): void;
44
+ /**
45
+ * Registers handler for connection close event
46
+ */
47
+ onClose(handler: (code: number, reason: string) => void): void;
48
+ /**
49
+ * Registers handler for message reception
50
+ */
51
+ onMessage(handler: (data: string | ArrayBuffer) => void): void;
52
+ /**
53
+ * Registers handler for connection errors
54
+ */
55
+ onError(handler: (error: Error) => void): void;
56
+ /**
57
+ * Gets current connection state
58
+ */
59
+ readonly isConnected: boolean;
60
+ /**
61
+ * Gets current connection state enum
62
+ */
63
+ readonly readyState: WebSocketState;
64
+ /**
65
+ * Gets the connected URL if applicable
66
+ */
67
+ readonly url?: string;
68
+ }
69
+ /**
70
+ * Factory interface for creating WebSocket instances
71
+ */
72
+ export interface VoiceLiveWebSocketFactoryLike {
73
+ /**
74
+ * Creates a new WebSocket instance for the target platform
75
+ */
76
+ create(options?: WebSocketFactoryOptions): VoiceLiveWebSocketLike;
77
+ }
78
+ //# sourceMappingURL=websocketLike.d.ts.map
@@ -0,0 +1,13 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+ /**
4
+ * WebSocket ready state enumeration matching standard WebSocket values
5
+ */
6
+ export var WebSocketState;
7
+ (function (WebSocketState) {
8
+ WebSocketState[WebSocketState["Connecting"] = 0] = "Connecting";
9
+ WebSocketState[WebSocketState["Open"] = 1] = "Open";
10
+ WebSocketState[WebSocketState["Closing"] = 2] = "Closing";
11
+ WebSocketState[WebSocketState["Closed"] = 3] = "Closed";
12
+ })(WebSocketState || (WebSocketState = {}));
13
+ //# sourceMappingURL=websocketLike.js.map