@ipcom/asterisk-ari 0.0.153 → 0.0.155

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.
@@ -582,6 +582,7 @@ __export(src_exports, {
582
582
  Applications: () => Applications,
583
583
  AriClient: () => AriClient,
584
584
  Asterisk: () => Asterisk,
585
+ BridgeInstance: () => BridgeInstance,
585
586
  Bridges: () => Bridges,
586
587
  ChannelInstance: () => ChannelInstance,
587
588
  Channels: () => Channels,
@@ -809,7 +810,7 @@ var Applications = class {
809
810
  }
810
811
  /**
811
812
  * Lists all applications.
812
- *
813
+ *
813
814
  * @returns A promise that resolves to an array of Application objects.
814
815
  * @throws {Error} If the API response is not an array.
815
816
  */
@@ -822,7 +823,7 @@ var Applications = class {
822
823
  }
823
824
  /**
824
825
  * Retrieves details of a specific application.
825
- *
826
+ *
826
827
  * @param appName - The name of the application to retrieve details for.
827
828
  * @returns A promise that resolves to an ApplicationDetails object.
828
829
  * @throws {Error} If there's an error fetching the application details.
@@ -839,7 +840,7 @@ var Applications = class {
839
840
  }
840
841
  /**
841
842
  * Sends a message to a specific application.
842
- *
843
+ *
843
844
  * @param appName - The name of the application to send the message to.
844
845
  * @param body - The message to be sent, containing an event and optional data.
845
846
  * @returns A promise that resolves when the message is successfully sent.
@@ -932,97 +933,681 @@ var Asterisk = class {
932
933
  };
933
934
 
934
935
  // src/ari-client/resources/bridges.ts
936
+ var import_events = require("events");
937
+ var import_axios2 = require("axios");
938
+
939
+ // src/ari-client/interfaces/events.types.ts
940
+ var bridgeEvents = [
941
+ "BridgeCreated",
942
+ "BridgeDestroyed",
943
+ "BridgeMerged",
944
+ "BridgeBlindTransfer",
945
+ "BridgeAttendedTransfer",
946
+ "BridgeVideoSourceChanged"
947
+ ];
948
+
949
+ // src/ari-client/utils.ts
950
+ function toQueryParams2(options) {
951
+ return new URLSearchParams(
952
+ Object.entries(options).filter(([, value]) => value !== void 0).map(([key, value]) => [key, value])
953
+ ).toString();
954
+ }
955
+
956
+ // src/ari-client/resources/bridges.ts
957
+ var getErrorMessage = (error) => {
958
+ if ((0, import_axios2.isAxiosError)(error)) {
959
+ return error.response?.data?.message || error.message || "Um erro do axios ocorreu";
960
+ }
961
+ if (error instanceof Error) {
962
+ return error.message;
963
+ }
964
+ return "Um erro desconhecido ocorreu";
965
+ };
966
+ var BridgeInstance = class {
967
+ /**
968
+ * Creates a new BridgeInstance.
969
+ *
970
+ * @param client - The AriClient instance for making API calls.
971
+ * @param baseClient - The BaseClient instance for making HTTP requests.
972
+ * @param bridgeId - Optional. The ID of the bridge. If not provided, a new ID will be generated.
973
+ */
974
+ constructor(client, baseClient, bridgeId) {
975
+ this.client = client;
976
+ this.baseClient = baseClient;
977
+ this.id = bridgeId || `bridge-${Date.now()}`;
978
+ console.log(`BridgeInstance inicializada com ID: ${this.id}`);
979
+ }
980
+ eventEmitter = new import_events.EventEmitter();
981
+ bridgeData = null;
982
+ id;
983
+ /**
984
+ * Registers a listener for specific bridge events.
985
+ *
986
+ * @param event - The type of event to listen for.
987
+ * @param listener - The callback function to be called when the event occurs.
988
+ */
989
+ /**
990
+ * Registers a listener for specific bridge events.
991
+ *
992
+ * This method allows you to attach an event listener to the bridge instance for a specific event type.
993
+ * When the specified event occurs, the provided listener function will be called with the event data.
994
+ *
995
+ * @template T - The specific type of WebSocketEvent to listen for.
996
+ * It receives the event data as its parameter.
997
+ * @returns {void}
998
+ *
999
+ * @example
1000
+ * bridge.on('BridgeCreated', (event) => {
1001
+ * console.log('Bridge created:', event.bridge.id);
1002
+ * });
1003
+ * @param event
1004
+ * @param listener
1005
+ */
1006
+ on(event, listener) {
1007
+ if (!event) {
1008
+ throw new Error("Event type is required");
1009
+ }
1010
+ const wrappedListener = (data) => {
1011
+ if ("bridge" in data && data.bridge?.id === this.id) {
1012
+ listener(data);
1013
+ }
1014
+ };
1015
+ this.eventEmitter.on(event, wrappedListener);
1016
+ console.log(`Event listener registered for ${event} on bridge ${this.id}`);
1017
+ }
1018
+ /**
1019
+ * Registers a one-time listener for specific bridge events.
1020
+ *
1021
+ * @param event - The type of event to listen for.
1022
+ * @param listener - The callback function to be called when the event occurs.
1023
+ */
1024
+ once(event, listener) {
1025
+ if (!event) {
1026
+ throw new Error("Event type is required");
1027
+ }
1028
+ const wrappedListener = (data) => {
1029
+ if ("bridge" in data && data.bridge?.id === this.id) {
1030
+ listener(data);
1031
+ }
1032
+ };
1033
+ this.eventEmitter.once(event, wrappedListener);
1034
+ console.log(
1035
+ `One-time listener registered for ${event} on bridge ${this.id}`
1036
+ );
1037
+ }
1038
+ /**
1039
+ * Removes event listener(s) from the bridge.
1040
+ *
1041
+ * @param event - The type of event to remove listeners for.
1042
+ * @param listener - Optional. The specific listener to remove. If not provided, all listeners for the event will be removed.
1043
+ */
1044
+ off(event, listener) {
1045
+ if (!event) {
1046
+ throw new Error("Event type is required");
1047
+ }
1048
+ if (listener) {
1049
+ this.eventEmitter.off(event, listener);
1050
+ console.log(
1051
+ `Specific listener removed for ${event} on bridge ${this.id}`
1052
+ );
1053
+ } else {
1054
+ this.eventEmitter.removeAllListeners(event);
1055
+ console.log(`All listeners removed for ${event} on bridge ${this.id}`);
1056
+ }
1057
+ }
1058
+ /**
1059
+ * Emits an event if it corresponds to the current bridge.
1060
+ *
1061
+ * @param event - The WebSocketEvent to emit.
1062
+ */
1063
+ emitEvent(event) {
1064
+ if (!event) {
1065
+ console.warn("Invalid event received");
1066
+ return;
1067
+ }
1068
+ if ("bridge" in event && event.bridge?.id === this.id) {
1069
+ this.eventEmitter.emit(event.type, event);
1070
+ console.log(`Event ${event.type} emitted for bridge ${this.id}`);
1071
+ }
1072
+ }
1073
+ /**
1074
+ * Removes all event listeners from this bridge instance.
1075
+ */
1076
+ removeAllListeners() {
1077
+ this.eventEmitter.removeAllListeners();
1078
+ console.log(`All listeners removed from bridge ${this.id}`);
1079
+ }
1080
+ /**
1081
+ * Retrieves the current details of the bridge.
1082
+ *
1083
+ * @returns A Promise that resolves to the Bridge object containing the current details.
1084
+ * @throws An error if the retrieval fails.
1085
+ */
1086
+ async get() {
1087
+ try {
1088
+ if (!this.id) {
1089
+ throw new Error("No bridge associated with this instance");
1090
+ }
1091
+ this.bridgeData = await this.baseClient.get(
1092
+ `/bridges/${this.id}`
1093
+ );
1094
+ console.log(`Details retrieved for bridge ${this.id}`);
1095
+ return this.bridgeData;
1096
+ } catch (error) {
1097
+ const message = getErrorMessage(error);
1098
+ console.error(`Error retrieving details for bridge ${this.id}:`, message);
1099
+ throw new Error(`Failed to get bridge details: ${message}`);
1100
+ }
1101
+ }
1102
+ /**
1103
+ * Adds channels to the bridge.
1104
+ *
1105
+ * @param request - The AddChannelRequest object containing the channels to add.
1106
+ * @throws An error if the operation fails.
1107
+ */
1108
+ async add(request) {
1109
+ try {
1110
+ const queryParams = toQueryParams2({
1111
+ channel: Array.isArray(request.channel) ? request.channel.join(",") : request.channel,
1112
+ ...request.role && { role: request.role }
1113
+ });
1114
+ await this.baseClient.post(
1115
+ `/bridges/${this.id}/addChannel?${queryParams}`
1116
+ );
1117
+ console.log(`Channels added to bridge ${this.id}`);
1118
+ } catch (error) {
1119
+ const message = getErrorMessage(error);
1120
+ console.error(`Error adding channels to bridge ${this.id}:`, message);
1121
+ throw new Error(`Failed to add channels: ${message}`);
1122
+ }
1123
+ }
1124
+ /**
1125
+ * Removes channels from the bridge.
1126
+ *
1127
+ * @param request - The RemoveChannelRequest object containing the channels to remove.
1128
+ * @throws An error if the operation fails.
1129
+ */
1130
+ async remove(request) {
1131
+ try {
1132
+ const queryParams = toQueryParams2({
1133
+ channel: Array.isArray(request.channel) ? request.channel.join(",") : request.channel
1134
+ });
1135
+ await this.baseClient.post(
1136
+ `/bridges/${this.id}/removeChannel?${queryParams}`
1137
+ );
1138
+ console.log(`Channels removed from bridge ${this.id}`);
1139
+ } catch (error) {
1140
+ const message = getErrorMessage(error);
1141
+ console.error(`Error removing channels from bridge ${this.id}:`, message);
1142
+ throw new Error(`Failed to remove channels: ${message}`);
1143
+ }
1144
+ }
1145
+ /**
1146
+ * Plays media on the bridge.
1147
+ *
1148
+ * @param request - The PlayMediaRequest object containing the media details to play.
1149
+ * @returns A Promise that resolves to a BridgePlayback object.
1150
+ * @throws An error if the operation fails.
1151
+ */
1152
+ async playMedia(request) {
1153
+ try {
1154
+ const queryParams = new URLSearchParams({
1155
+ ...request.lang && { lang: request.lang },
1156
+ ...request.offsetms && { offsetms: request.offsetms.toString() },
1157
+ ...request.skipms && { skipms: request.skipms.toString() },
1158
+ ...request.playbackId && { playbackId: request.playbackId }
1159
+ }).toString();
1160
+ const result = await this.baseClient.post(
1161
+ `/bridges/${this.id}/play?${queryParams}`,
1162
+ { media: request.media }
1163
+ );
1164
+ console.log(`Media playback started on bridge ${this.id}`);
1165
+ return result;
1166
+ } catch (error) {
1167
+ const message = getErrorMessage(error);
1168
+ console.error(`Error playing media on bridge ${this.id}:`, message);
1169
+ throw new Error(`Failed to play media: ${message}`);
1170
+ }
1171
+ }
1172
+ /**
1173
+ * Stops media playback on the bridge.
1174
+ *
1175
+ * @param playbackId - The ID of the playback to stop.
1176
+ * @throws An error if the operation fails.
1177
+ */
1178
+ async stopPlayback(playbackId) {
1179
+ try {
1180
+ await this.baseClient.delete(
1181
+ `/bridges/${this.id}/play/${playbackId}`
1182
+ );
1183
+ console.log(`Playback ${playbackId} stopped on bridge ${this.id}`);
1184
+ } catch (error) {
1185
+ const message = getErrorMessage(error);
1186
+ console.error(`Error stopping playback on bridge ${this.id}:`, message);
1187
+ throw new Error(`Failed to stop playback: ${message}`);
1188
+ }
1189
+ }
1190
+ /**
1191
+ * Sets the video source for the bridge.
1192
+ *
1193
+ * @param channelId - The ID of the channel to set as the video source.
1194
+ * @throws An error if the operation fails.
1195
+ */
1196
+ async setVideoSource(channelId) {
1197
+ try {
1198
+ await this.baseClient.post(
1199
+ `/bridges/${this.id}/videoSource/${channelId}`
1200
+ );
1201
+ console.log(`Video source set for bridge ${this.id}`);
1202
+ } catch (error) {
1203
+ const message = getErrorMessage(error);
1204
+ console.error(
1205
+ `Error setting video source for bridge ${this.id}:`,
1206
+ message
1207
+ );
1208
+ throw new Error(`Failed to set video source: ${message}`);
1209
+ }
1210
+ }
1211
+ /**
1212
+ * Removes the video source from the bridge.
1213
+ *
1214
+ * @throws An error if the operation fails.
1215
+ */
1216
+ async clearVideoSource() {
1217
+ try {
1218
+ await this.baseClient.delete(`/bridges/${this.id}/videoSource`);
1219
+ console.log(`Video source removed from bridge ${this.id}`);
1220
+ } catch (error) {
1221
+ const message = getErrorMessage(error);
1222
+ console.error(
1223
+ `Error removing video source from bridge ${this.id}:`,
1224
+ message
1225
+ );
1226
+ throw new Error(`Failed to remove video source: ${message}`);
1227
+ }
1228
+ }
1229
+ /**
1230
+ * Checks if the bridge has listeners for a specific event.
1231
+ *
1232
+ * @param event - The event type to check for listeners.
1233
+ * @returns A boolean indicating whether there are listeners for the event.
1234
+ */
1235
+ hasListeners(event) {
1236
+ return this.eventEmitter.listenerCount(event) > 0;
1237
+ }
1238
+ /**
1239
+ * Retrieves the current bridge data without making an API call.
1240
+ *
1241
+ * @returns The current Bridge object or null if no data is available.
1242
+ */
1243
+ getCurrentData() {
1244
+ return this.bridgeData;
1245
+ }
1246
+ };
935
1247
  var Bridges = class {
936
- constructor(client) {
1248
+ constructor(baseClient, client) {
1249
+ this.baseClient = baseClient;
937
1250
  this.client = client;
938
1251
  }
1252
+ bridgeInstances = /* @__PURE__ */ new Map();
1253
+ /**
1254
+ * Creates or retrieves a Bridge instance.
1255
+ *
1256
+ * This method manages the creation and retrieval of BridgeInstance objects.
1257
+ * If an ID is provided and an instance with that ID already exists, it returns the existing instance.
1258
+ * If an ID is provided but no instance exists, it creates a new instance with that ID.
1259
+ * If no ID is provided, it creates a new instance with a generated ID.
1260
+ *
1261
+ * @param {Object} params - The parameters for creating or retrieving a Bridge instance.
1262
+ * @param {string} [params.id] - Optional. The ID of the Bridge instance to create or retrieve.
1263
+ *
1264
+ * @returns {BridgeInstance} A BridgeInstance object, either newly created or retrieved from existing instances.
1265
+ *
1266
+ * @throws {Error} If there's an error in creating or retrieving the Bridge instance.
1267
+ */
1268
+ Bridge({ id }) {
1269
+ try {
1270
+ if (!id) {
1271
+ const instance = new BridgeInstance(this.client, this.baseClient);
1272
+ this.bridgeInstances.set(instance.id, instance);
1273
+ console.log(`New bridge instance created with ID: ${instance.id}`);
1274
+ return instance;
1275
+ }
1276
+ if (!this.bridgeInstances.has(id)) {
1277
+ const instance = new BridgeInstance(this.client, this.baseClient, id);
1278
+ this.bridgeInstances.set(id, instance);
1279
+ console.log(`New bridge instance created with provided ID: ${id}`);
1280
+ return instance;
1281
+ }
1282
+ console.log(`Returning existing bridge instance: ${id}`);
1283
+ return this.bridgeInstances.get(id);
1284
+ } catch (error) {
1285
+ const message = getErrorMessage(error);
1286
+ console.error(`Error creating/retrieving bridge instance:`, message);
1287
+ throw new Error(`Failed to manage bridge instance: ${message}`);
1288
+ }
1289
+ }
1290
+ /**
1291
+ * Removes a bridge instance from the collection of managed bridges.
1292
+ *
1293
+ * This function removes the specified bridge instance, cleans up its event listeners,
1294
+ * and logs the removal. If the bridge instance doesn't exist, it logs a warning.
1295
+ *
1296
+ * @param {string} bridgeId - The unique identifier of the bridge instance to be removed.
1297
+ * @throws {Error} Throws an error if the bridgeId is not provided.
1298
+ * @returns {void}
1299
+ */
1300
+ removeBridgeInstance(bridgeId) {
1301
+ if (!bridgeId) {
1302
+ throw new Error("ID da bridge \xE9 obrigat\xF3rio");
1303
+ }
1304
+ if (this.bridgeInstances.has(bridgeId)) {
1305
+ const instance = this.bridgeInstances.get(bridgeId);
1306
+ instance?.removeAllListeners();
1307
+ this.bridgeInstances.delete(bridgeId);
1308
+ console.log(`Inst\xE2ncia de bridge removida: ${bridgeId}`);
1309
+ } else {
1310
+ console.warn(`Tentativa de remover inst\xE2ncia inexistente: ${bridgeId}`);
1311
+ }
1312
+ }
939
1313
  /**
940
- * Lists all active bridges.
1314
+ * Propagates a WebSocket event to a specific bridge instance.
1315
+ *
1316
+ * This function checks if the received event is valid and related to a bridge,
1317
+ * then emits the event to the corresponding bridge instance if it exists.
1318
+ *
1319
+ * @param {WebSocketEvent} event - The WebSocket event to be propagated.
1320
+ * This should be an object containing information about the event,
1321
+ * including the bridge ID and event type.
1322
+ *
1323
+ * @returns {void}
1324
+ *
1325
+ * @remarks
1326
+ * - If the event is invalid (null or undefined), a warning is logged and the function returns early.
1327
+ * - The function checks if the event is bridge-related and if the event type is included in the predefined bridge events.
1328
+ * - If a matching bridge instance is found, the event is emitted to that instance.
1329
+ * - If no matching bridge instance is found, a warning is logged.
1330
+ */
1331
+ propagateEventToBridge(event) {
1332
+ if (!event) {
1333
+ console.warn("Evento WebSocket inv\xE1lido recebido");
1334
+ return;
1335
+ }
1336
+ if ("bridge" in event && event.bridge?.id && bridgeEvents.includes(event.type)) {
1337
+ const instance = this.bridgeInstances.get(event.bridge.id);
1338
+ if (instance) {
1339
+ instance.emitEvent(event);
1340
+ console.log(
1341
+ `Evento propagado para bridge ${event.bridge.id}: ${event.type}`
1342
+ );
1343
+ } else {
1344
+ console.warn(
1345
+ `Nenhuma inst\xE2ncia encontrada para bridge ${event.bridge.id}`
1346
+ );
1347
+ }
1348
+ }
1349
+ }
1350
+ /**
1351
+ * Lists all active bridges in the system.
1352
+ *
1353
+ * This asynchronous function retrieves a list of all currently active bridges
1354
+ * by making a GET request to the "/bridges" endpoint using the base client.
1355
+ *
1356
+ * @returns {Promise<Bridge[]>} A promise that resolves to an array of Bridge objects.
1357
+ * Each Bridge object represents an active bridge in the system.
1358
+ *
1359
+ * @throws {Error} If there's an error in fetching the bridges or if the request fails.
1360
+ *
1361
+ * @example
1362
+ * try {
1363
+ * const bridges = await bridgesInstance.list();
1364
+ * console.log('Active bridges:', bridges);
1365
+ * } catch (error) {
1366
+ * console.error('Failed to fetch bridges:', error);
1367
+ * }
941
1368
  */
942
1369
  async list() {
943
- return this.client.get("/bridges");
1370
+ return this.baseClient.get("/bridges");
944
1371
  }
945
1372
  /**
946
- * Creates a new bridge.
1373
+ * Creates a new bridge in the system.
1374
+ *
1375
+ * This asynchronous function sends a POST request to create a new bridge
1376
+ * using the provided configuration details.
1377
+ *
1378
+ * @param request - The configuration details for creating the new bridge.
1379
+ * @param request.type - The type of bridge to create (e.g., 'mixing', 'holding').
1380
+ * @param request.name - Optional. A custom name for the bridge.
1381
+ * @param request.bridgeId - Optional. A specific ID for the bridge. If not provided, one will be generated.
1382
+ *
1383
+ * @returns A Promise that resolves to a Bridge object representing the newly created bridge.
1384
+ * The Bridge object contains details such as id, technology, bridge_type, bridge_class, channels, etc.
1385
+ *
1386
+ * @throws Will throw an error if the bridge creation fails or if there's a network issue.
947
1387
  */
948
1388
  async createBridge(request) {
949
- return this.client.post("/bridges", request);
1389
+ return this.baseClient.post("/bridges", request);
950
1390
  }
951
1391
  /**
952
- * Retrieves details of a specific bridge.
1392
+ * Retrieves detailed information about a specific bridge.
1393
+ *
1394
+ * This asynchronous function fetches the complete details of a bridge
1395
+ * identified by its unique ID. It makes a GET request to the ARI endpoint
1396
+ * for the specified bridge.
1397
+ *
1398
+ * @param bridgeId - The unique identifier of the bridge to retrieve details for.
1399
+ * This should be a string that uniquely identifies the bridge in the system.
1400
+ *
1401
+ * @returns A Promise that resolves to a Bridge object containing all the details
1402
+ * of the specified bridge. This includes information such as the bridge's
1403
+ * ID, type, channels, and other relevant properties.
1404
+ *
1405
+ * @throws Will throw an error if the bridge cannot be found, if there's a network issue,
1406
+ * or if the server responds with an error.
953
1407
  */
954
- async getDetails(bridgeId) {
955
- return this.client.get(`/bridges/${bridgeId}`);
1408
+ async get(bridgeId) {
1409
+ return this.baseClient.get(`/bridges/${bridgeId}`);
956
1410
  }
957
1411
  /**
958
- * Destroys (deletes) a specific bridge.
1412
+ * Destroys (deletes) a specific bridge in the system.
1413
+ *
1414
+ * This asynchronous function sends a DELETE request to remove a bridge
1415
+ * identified by its unique ID. Once destroyed, the bridge and all its
1416
+ * associated resources are permanently removed from the system.
1417
+ *
1418
+ * @param bridgeId - The unique identifier of the bridge to be destroyed.
1419
+ * This should be a string that uniquely identifies the bridge in the system.
1420
+ *
1421
+ * @returns A Promise that resolves to void when the bridge is successfully destroyed.
1422
+ * If the operation is successful, the bridge no longer exists in the system.
1423
+ *
1424
+ * @throws Will throw an error if the bridge cannot be found, if there's a network issue,
1425
+ * or if the server responds with an error during the deletion process.
959
1426
  */
960
1427
  async destroy(bridgeId) {
961
- return this.client.delete(`/bridges/${bridgeId}`);
1428
+ return this.baseClient.delete(`/bridges/${bridgeId}`);
962
1429
  }
963
1430
  /**
964
- * Adds a channel or multiple channels to a bridge.
1431
+ * Adds one or more channels to a specified bridge.
1432
+ *
1433
+ * This asynchronous function sends a POST request to add channels to an existing bridge.
1434
+ * It can handle adding a single channel or multiple channels in one operation.
1435
+ *
1436
+ * @param bridgeId - The unique identifier of the bridge to which channels will be added.
1437
+ * @param request - An object containing the details of the channel(s) to be added.
1438
+ * @param request.channel - A single channel ID or an array of channel IDs to add to the bridge.
1439
+ * @param request.role - Optional. Specifies the role of the channel(s) in the bridge.
1440
+ *
1441
+ * @returns A Promise that resolves to void when the operation is successful.
1442
+ *
1443
+ * @throws Will throw an error if the request fails, such as if the bridge doesn't exist
1444
+ * or if there's a network issue.
965
1445
  */
966
1446
  async addChannels(bridgeId, request) {
967
- const queryParams = new URLSearchParams({
1447
+ const queryParams = toQueryParams2({
968
1448
  channel: Array.isArray(request.channel) ? request.channel.join(",") : request.channel,
969
1449
  ...request.role && { role: request.role }
970
- }).toString();
971
- await this.client.post(
1450
+ });
1451
+ await this.baseClient.post(
972
1452
  `/bridges/${bridgeId}/addChannel?${queryParams}`
973
1453
  );
974
1454
  }
975
1455
  /**
976
- * Removes a channel or multiple channels from a bridge.
1456
+ * Removes one or more channels from a specified bridge.
1457
+ *
1458
+ * This asynchronous function sends a POST request to remove channels from an existing bridge.
1459
+ * It can handle removing a single channel or multiple channels in one operation.
1460
+ *
1461
+ * @param bridgeId - The unique identifier of the bridge from which channels will be removed.
1462
+ * @param request - An object containing the details of the channel(s) to be removed.
1463
+ * @param request.channel - A single channel ID or an array of channel IDs to remove from the bridge.
1464
+ *
1465
+ * @returns A Promise that resolves to void when the operation is successful.
1466
+ *
1467
+ * @throws Will throw an error if the request fails, such as if the bridge doesn't exist,
1468
+ * if the channels are not in the bridge, or if there's a network issue.
977
1469
  */
978
1470
  async removeChannels(bridgeId, request) {
979
- const queryParams = new URLSearchParams({
1471
+ const queryParams = toQueryParams2({
980
1472
  channel: Array.isArray(request.channel) ? request.channel.join(",") : request.channel
981
- }).toString();
982
- await this.client.post(
1473
+ });
1474
+ await this.baseClient.post(
983
1475
  `/bridges/${bridgeId}/removeChannel?${queryParams}`
984
1476
  );
985
1477
  }
986
1478
  /**
987
- * Plays media to a bridge.
1479
+ * Plays media on a specified bridge.
1480
+ *
1481
+ * This asynchronous function initiates media playback on a bridge identified by its ID.
1482
+ * It allows for customization of the playback through various options in the request.
1483
+ *
1484
+ * @param bridgeId - The unique identifier of the bridge on which to play the media.
1485
+ * @param request - An object containing the media playback request details.
1486
+ * @param request.media - The media to be played (e.g., sound file, URL).
1487
+ * @param request.lang - Optional. The language of the media content.
1488
+ * @param request.offsetms - Optional. The offset in milliseconds to start playing from.
1489
+ * @param request.skipms - Optional. The number of milliseconds to skip before playing.
1490
+ * @param request.playbackId - Optional. A custom ID for the playback session.
1491
+ *
1492
+ * @returns A Promise that resolves to a BridgePlayback object, containing details about the initiated playback.
1493
+ *
1494
+ * @throws Will throw an error if the playback request fails or if there's a network issue.
988
1495
  */
989
1496
  async playMedia(bridgeId, request) {
990
- const queryParams = new URLSearchParams({
1497
+ const queryParams = toQueryParams2({
991
1498
  ...request.lang && { lang: request.lang },
992
1499
  ...request.offsetms && { offsetms: request.offsetms.toString() },
993
1500
  ...request.skipms && { skipms: request.skipms.toString() },
994
1501
  ...request.playbackId && { playbackId: request.playbackId }
995
- }).toString();
996
- return this.client.post(
1502
+ });
1503
+ return this.baseClient.post(
997
1504
  `/bridges/${bridgeId}/play?${queryParams}`,
998
1505
  { media: request.media }
999
1506
  );
1000
1507
  }
1001
1508
  /**
1002
- * Stops media playback on a bridge.
1509
+ * Stops media playback on a specified bridge.
1510
+ *
1511
+ * This asynchronous function sends a DELETE request to stop the playback of media
1512
+ * on a bridge identified by its ID and a specific playback session.
1513
+ *
1514
+ * @param bridgeId - The unique identifier of the bridge where the playback is to be stopped.
1515
+ * @param playbackId - The unique identifier of the playback session to be stopped.
1516
+ *
1517
+ * @returns A Promise that resolves to void when the playback is successfully stopped.
1518
+ *
1519
+ * @throws Will throw an error if the request fails, such as if the bridge or playback session
1520
+ * doesn't exist, or if there's a network issue.
1003
1521
  */
1004
1522
  async stopPlayback(bridgeId, playbackId) {
1005
- await this.client.delete(`/bridges/${bridgeId}/play/${playbackId}`);
1523
+ await this.baseClient.delete(
1524
+ `/bridges/${bridgeId}/play/${playbackId}`
1525
+ );
1006
1526
  }
1007
1527
  /**
1008
- * Sets the video source for a bridge.
1528
+ * Sets the video source for a specified bridge.
1529
+ *
1530
+ * This asynchronous function configures a channel as the video source for a given bridge.
1531
+ * It sends a POST request to the ARI endpoint to update the bridge's video source.
1532
+ *
1533
+ * @param bridgeId - The unique identifier of the bridge for which to set the video source.
1534
+ * @param channelId - The unique identifier of the channel to be set as the video source.
1535
+ *
1536
+ * @returns A Promise that resolves to void when the video source is successfully set.
1537
+ *
1538
+ * @throws Will throw an error if the request fails, such as if the bridge or channel
1539
+ * doesn't exist, or if there's a network issue.
1009
1540
  */
1010
1541
  async setVideoSource(bridgeId, channelId) {
1011
- await this.client.post(
1012
- `/bridges/${bridgeId}/videoSource?channelId=${encodeURIComponent(channelId)}`
1542
+ const queryParams = toQueryParams2({ channelId });
1543
+ await this.baseClient.post(
1544
+ `/bridges/${bridgeId}/videoSource?${queryParams}`
1013
1545
  );
1014
1546
  }
1015
1547
  /**
1016
- * Clears the video source for a bridge.
1548
+ * Clears the video source for a specified bridge.
1549
+ *
1550
+ * This asynchronous function removes the currently set video source from a bridge.
1551
+ * It sends a DELETE request to the ARI endpoint to clear the video source configuration.
1552
+ *
1553
+ * @param bridgeId - The unique identifier of the bridge from which to clear the video source.
1554
+ * This should be a string that uniquely identifies the bridge in the system.
1555
+ *
1556
+ * @returns A Promise that resolves to void when the video source is successfully cleared.
1557
+ * If the operation is successful, the bridge will no longer have a designated video source.
1558
+ *
1559
+ * @throws Will throw an error if the request fails, such as if the bridge doesn't exist,
1560
+ * if there's no video source set, or if there's a network issue.
1017
1561
  */
1018
1562
  async clearVideoSource(bridgeId) {
1019
- await this.client.delete(`/bridges/${bridgeId}/videoSource`);
1563
+ await this.baseClient.delete(`/bridges/${bridgeId}/videoSource`);
1564
+ }
1565
+ /**
1566
+ * Retrieves the count of active bridge instances.
1567
+ *
1568
+ * This function returns the total number of bridge instances currently
1569
+ * managed by the Bridges class. It provides a quick way to check how many
1570
+ * active bridges are present in the system.
1571
+ *
1572
+ * @returns {number} The count of active bridge instances.
1573
+ */
1574
+ getInstanceCount() {
1575
+ return this.bridgeInstances.size;
1576
+ }
1577
+ /**
1578
+ * Checks if a bridge instance exists in the collection of managed bridges.
1579
+ *
1580
+ * This function verifies whether a bridge instance with the specified ID
1581
+ * is currently being managed by the Bridges class.
1582
+ *
1583
+ * @param bridgeId - The unique identifier of the bridge instance to check.
1584
+ * This should be a string that uniquely identifies the bridge in the system.
1585
+ *
1586
+ * @returns A boolean value indicating whether the bridge instance exists.
1587
+ * Returns true if the bridge instance is found, false otherwise.
1588
+ */
1589
+ hasInstance(bridgeId) {
1590
+ return this.bridgeInstances.has(bridgeId);
1591
+ }
1592
+ /**
1593
+ * Retrieves all active bridge instances currently managed by the Bridges class.
1594
+ *
1595
+ * This method provides a way to access all the BridgeInstance objects that are
1596
+ * currently active and being managed. It returns a new Map to prevent direct
1597
+ * modification of the internal bridgeInstances collection.
1598
+ *
1599
+ * @returns A new Map object containing all active bridge instances, where the keys
1600
+ * are the bridge IDs (strings) and the values are the corresponding
1601
+ * BridgeInstance objects. If no bridges are active, an empty Map is returned.
1602
+ */
1603
+ getAllInstances() {
1604
+ return new Map(this.bridgeInstances);
1020
1605
  }
1021
1606
  };
1022
1607
 
1023
1608
  // src/ari-client/resources/channels.ts
1024
- var import_events = require("events");
1025
- var import_axios2 = require("axios");
1609
+ var import_events3 = require("events");
1610
+ var import_axios3 = require("axios");
1026
1611
 
1027
1612
  // node_modules/uuid/dist/esm/stringify.js
1028
1613
  var byteToHex = [];
@@ -1069,16 +1654,9 @@ function v4(options, buf, offset) {
1069
1654
  }
1070
1655
  var v4_default = v4;
1071
1656
 
1072
- // src/ari-client/utils.ts
1073
- function toQueryParams2(options) {
1074
- return new URLSearchParams(
1075
- Object.entries(options).filter(([, value]) => value !== void 0).map(([key, value]) => [key, value])
1076
- ).toString();
1077
- }
1078
-
1079
1657
  // src/ari-client/resources/channels.ts
1080
- var getErrorMessage = (error) => {
1081
- if ((0, import_axios2.isAxiosError)(error)) {
1658
+ var getErrorMessage2 = (error) => {
1659
+ if ((0, import_axios3.isAxiosError)(error)) {
1082
1660
  return error.response?.data?.message || error.message || "An axios error occurred";
1083
1661
  }
1084
1662
  if (error instanceof Error) {
@@ -1092,7 +1670,7 @@ var ChannelInstance = class {
1092
1670
  this.baseClient = baseClient;
1093
1671
  this.id = channelId || `channel-${Date.now()}`;
1094
1672
  }
1095
- eventEmitter = new import_events.EventEmitter();
1673
+ eventEmitter = new import_events3.EventEmitter();
1096
1674
  channelData = null;
1097
1675
  id;
1098
1676
  /**
@@ -1170,7 +1748,7 @@ var ChannelInstance = class {
1170
1748
  try {
1171
1749
  await this.baseClient.post(`/channels/${this.id}/answer`);
1172
1750
  } catch (error) {
1173
- const message = getErrorMessage(error);
1751
+ const message = getErrorMessage2(error);
1174
1752
  console.error(`Error answering channel ${this.id}:`, message);
1175
1753
  throw new Error(`Failed to answer channel: ${message}`);
1176
1754
  }
@@ -1193,7 +1771,7 @@ var ChannelInstance = class {
1193
1771
  );
1194
1772
  return this.channelData;
1195
1773
  } catch (error) {
1196
- const message = getErrorMessage(error);
1774
+ const message = getErrorMessage2(error);
1197
1775
  console.error(`Error originating channel:`, message);
1198
1776
  throw new Error(`Failed to originate channel: ${message}`);
1199
1777
  }
@@ -1216,7 +1794,7 @@ var ChannelInstance = class {
1216
1794
  );
1217
1795
  return playback;
1218
1796
  } catch (error) {
1219
- const message = getErrorMessage(error);
1797
+ const message = getErrorMessage2(error);
1220
1798
  console.error(`Error playing media on channel ${this.id}:`, message);
1221
1799
  throw new Error(`Failed to play media: ${message}`);
1222
1800
  }
@@ -1238,7 +1816,7 @@ var ChannelInstance = class {
1238
1816
  this.channelData = details;
1239
1817
  return details;
1240
1818
  } catch (error) {
1241
- const message = getErrorMessage(error);
1819
+ const message = getErrorMessage2(error);
1242
1820
  console.error(
1243
1821
  `Error retrieving channel details for ${this.id}:`,
1244
1822
  message
@@ -1479,7 +2057,7 @@ var Channels = class {
1479
2057
  }
1480
2058
  return this.channelInstances.get(id);
1481
2059
  } catch (error) {
1482
- const message = getErrorMessage(error);
2060
+ const message = getErrorMessage2(error);
1483
2061
  console.error(`Error creating/retrieving channel instance:`, message);
1484
2062
  throw new Error(`Failed to manage channel instance: ${message}`);
1485
2063
  }
@@ -1498,7 +2076,7 @@ var Channels = class {
1498
2076
  }
1499
2077
  return await this.baseClient.get(`/channels/${id}`);
1500
2078
  } catch (error) {
1501
- const message = getErrorMessage(error);
2079
+ const message = getErrorMessage2(error);
1502
2080
  console.error(`Error retrieving channel details for ${id}:`, message);
1503
2081
  throw new Error(`Failed to get channel details: ${message}`);
1504
2082
  }
@@ -1545,7 +2123,7 @@ var Channels = class {
1545
2123
  try {
1546
2124
  return await this.baseClient.post("/channels", data);
1547
2125
  } catch (error) {
1548
- const message = getErrorMessage(error);
2126
+ const message = getErrorMessage2(error);
1549
2127
  console.error(`Error originating channel:`, message);
1550
2128
  throw new Error(`Failed to originate channel: ${message}`);
1551
2129
  }
@@ -1561,7 +2139,7 @@ var Channels = class {
1561
2139
  }
1562
2140
  return channels;
1563
2141
  } catch (error) {
1564
- const message = getErrorMessage(error);
2142
+ const message = getErrorMessage2(error);
1565
2143
  console.error(`Error listing channels:`, message);
1566
2144
  throw new Error(`Failed to list channels: ${message}`);
1567
2145
  }
@@ -1988,10 +2566,10 @@ var Endpoints = class {
1988
2566
  };
1989
2567
 
1990
2568
  // src/ari-client/resources/playbacks.ts
1991
- var import_events2 = require("events");
1992
- var import_axios3 = require("axios");
1993
- var getErrorMessage2 = (error) => {
1994
- if ((0, import_axios3.isAxiosError)(error)) {
2569
+ var import_events4 = require("events");
2570
+ var import_axios4 = require("axios");
2571
+ var getErrorMessage3 = (error) => {
2572
+ if ((0, import_axios4.isAxiosError)(error)) {
1995
2573
  return error.response?.data?.message || error.message || "An axios error occurred";
1996
2574
  }
1997
2575
  if (error instanceof Error) {
@@ -2013,7 +2591,7 @@ var PlaybackInstance = class {
2013
2591
  this.playbackId = playbackId;
2014
2592
  this.id = playbackId;
2015
2593
  }
2016
- eventEmitter = new import_events2.EventEmitter();
2594
+ eventEmitter = new import_events4.EventEmitter();
2017
2595
  playbackData = null;
2018
2596
  id;
2019
2597
  /**
@@ -2096,7 +2674,7 @@ var PlaybackInstance = class {
2096
2674
  );
2097
2675
  return this.playbackData;
2098
2676
  } catch (error) {
2099
- const message = getErrorMessage2(error);
2677
+ const message = getErrorMessage3(error);
2100
2678
  console.warn(`Error retrieving playback data for ${this.id}:`, message);
2101
2679
  throw new Error(`Failed to get playback data: ${message}`);
2102
2680
  }
@@ -2116,7 +2694,7 @@ var PlaybackInstance = class {
2116
2694
  `/playbacks/${this.id}/control?operation=${operation}`
2117
2695
  );
2118
2696
  } catch (error) {
2119
- const message = getErrorMessage2(error);
2697
+ const message = getErrorMessage3(error);
2120
2698
  console.warn(`Error controlling playback ${this.id}:`, message);
2121
2699
  throw new Error(`Failed to control playback: ${message}`);
2122
2700
  }
@@ -2133,7 +2711,7 @@ var PlaybackInstance = class {
2133
2711
  try {
2134
2712
  await this.baseClient.delete(`/playbacks/${this.id}`);
2135
2713
  } catch (error) {
2136
- const message = getErrorMessage2(error);
2714
+ const message = getErrorMessage3(error);
2137
2715
  console.warn(`Error stopping playback ${this.id}:`, message);
2138
2716
  throw new Error(`Failed to stop playback: ${message}`);
2139
2717
  }
@@ -2189,7 +2767,7 @@ var Playbacks = class {
2189
2767
  }
2190
2768
  return this.playbackInstances.get(id);
2191
2769
  } catch (error) {
2192
- const message = getErrorMessage2(error);
2770
+ const message = getErrorMessage3(error);
2193
2771
  console.warn(`Error creating/retrieving playback instance:`, message);
2194
2772
  throw new Error(`Failed to manage playback instance: ${message}`);
2195
2773
  }
@@ -2241,7 +2819,7 @@ var Playbacks = class {
2241
2819
  try {
2242
2820
  return await this.baseClient.get(`/playbacks/${playbackId}`);
2243
2821
  } catch (error) {
2244
- const message = getErrorMessage2(error);
2822
+ const message = getErrorMessage3(error);
2245
2823
  console.warn(`Error getting playback details ${playbackId}:`, message);
2246
2824
  throw new Error(`Failed to get playback details: ${message}`);
2247
2825
  }
@@ -2260,7 +2838,7 @@ var Playbacks = class {
2260
2838
  const playback = this.Playback({ id: playbackId });
2261
2839
  await playback.control(operation);
2262
2840
  } catch (error) {
2263
- const message = getErrorMessage2(error);
2841
+ const message = getErrorMessage3(error);
2264
2842
  console.warn(`Error controlling playback ${playbackId}:`, message);
2265
2843
  throw new Error(`Failed to control playback: ${message}`);
2266
2844
  }
@@ -2278,7 +2856,7 @@ var Playbacks = class {
2278
2856
  const playback = this.Playback({ id: playbackId });
2279
2857
  await playback.stop();
2280
2858
  } catch (error) {
2281
- const message = getErrorMessage2(error);
2859
+ const message = getErrorMessage3(error);
2282
2860
  console.warn(`Error stopping playback ${playbackId}:`, message);
2283
2861
  throw new Error(`Failed to stop playback: ${message}`);
2284
2862
  }
@@ -2332,20 +2910,25 @@ var Sounds = class {
2332
2910
  };
2333
2911
 
2334
2912
  // src/ari-client/websocketClient.ts
2335
- var import_events3 = require("events");
2913
+ var import_events5 = require("events");
2336
2914
  var import_exponential_backoff = __toESM(require_backoff(), 1);
2337
2915
  var import_ws = __toESM(require("ws"), 1);
2338
- var DEFAULT_MAX_RECONNECT_ATTEMPTS = 10;
2916
+ var DEFAULT_MAX_RECONNECT_ATTEMPTS = 30;
2339
2917
  var DEFAULT_STARTING_DELAY = 500;
2340
2918
  var DEFAULT_MAX_DELAY = 1e4;
2341
- var WebSocketClient = class extends import_events3.EventEmitter {
2919
+ var WebSocketClient = class extends import_events5.EventEmitter {
2342
2920
  /**
2343
- * Creates a new WebSocket client instance.
2921
+ * Creates a new WebSocketClient instance.
2344
2922
  *
2345
- * @param {BaseClient} baseClient - The base client containing connection details
2346
- * @param {string[]} apps - List of applications to connect to
2347
- * @param {WebSocketEventType[]} [subscribedEvents] - Optional list of events to subscribe to
2348
- * @param {AriClient} [ariClient] - Optional ARI client for handling channel and playback events
2923
+ * This constructor initializes a WebSocketClient with the necessary dependencies and configuration.
2924
+ * It ensures that at least one application name is provided.
2925
+ *
2926
+ * @param baseClient - The BaseClient instance used for basic ARI operations and authentication.
2927
+ * @param apps - An array of application names to connect to via the WebSocket.
2928
+ * @param subscribedEvents - Optional. An array of WebSocketEventTypes to subscribe to. If not provided, all events will be subscribed.
2929
+ * @param ariClient - Optional. The AriClient instance, used for creating Channel and Playback instances when processing events.
2930
+ *
2931
+ * @throws {Error} Throws an error if the apps array is empty.
2349
2932
  */
2350
2933
  constructor(baseClient, apps, subscribedEvents, ariClient) {
2351
2934
  super();
@@ -2360,6 +2943,8 @@ var WebSocketClient = class extends import_events3.EventEmitter {
2360
2943
  ws;
2361
2944
  isReconnecting = false;
2362
2945
  maxReconnectAttempts = DEFAULT_MAX_RECONNECT_ATTEMPTS;
2946
+ reconnectionAttempts = 0;
2947
+ lastWsUrl = "";
2363
2948
  backOffOptions = {
2364
2949
  numOfAttempts: DEFAULT_MAX_RECONNECT_ATTEMPTS,
2365
2950
  startingDelay: DEFAULT_STARTING_DELAY,
@@ -2376,10 +2961,14 @@ var WebSocketClient = class extends import_events3.EventEmitter {
2376
2961
  }
2377
2962
  };
2378
2963
  /**
2379
- * Establishes a WebSocket connection.
2964
+ * Establishes a WebSocket connection to the Asterisk server.
2380
2965
  *
2381
- * @returns {Promise<void>} Resolves when connection is established
2382
- * @throws {Error} If connection fails
2966
+ * This method constructs the WebSocket URL using the base URL, credentials,
2967
+ * application names, and subscribed events. It then initiates the connection
2968
+ * using the constructed URL.
2969
+ *
2970
+ * @returns A Promise that resolves when the WebSocket connection is successfully established.
2971
+ * @throws Will throw an error if the connection cannot be established.
2383
2972
  */
2384
2973
  async connect() {
2385
2974
  const { baseUrl, username, password } = this.baseClient.getCredentials();
@@ -2394,15 +2983,24 @@ var WebSocketClient = class extends import_events3.EventEmitter {
2394
2983
  } else {
2395
2984
  queryParams.append("subscribeAll", "true");
2396
2985
  }
2397
- const wsUrl = `${protocol}://${encodeURIComponent(username)}:${encodeURIComponent(password)}@${normalizedHost}/ari/events?${queryParams.toString()}`;
2986
+ this.lastWsUrl = `${protocol}://${encodeURIComponent(username)}:${encodeURIComponent(password)}@${normalizedHost}/ari/events?${queryParams.toString()}`;
2398
2987
  console.log("Connecting to WebSocket...");
2399
- return this.initializeWebSocket(wsUrl);
2988
+ return this.initializeWebSocket(this.lastWsUrl);
2400
2989
  }
2401
2990
  /**
2402
- * Initializes WebSocket connection with reconnection logic.
2991
+ * Initializes a WebSocket connection with exponential backoff retry mechanism.
2403
2992
  *
2404
- * @param {string} wsUrl - The WebSocket URL to connect to
2405
- * @returns {Promise<void>} Resolves when connection is established
2993
+ * This method attempts to establish a WebSocket connection to the specified URL.
2994
+ * It sets up event listeners for the WebSocket's 'open', 'message', 'close', and 'error' events.
2995
+ * If the connection is successful, it emits a 'connected' event. If it's a reconnection,
2996
+ * it also emits a 'reconnected' event with the current apps and subscribed events.
2997
+ * In case of connection failure, it uses an exponential backoff strategy to retry.
2998
+ *
2999
+ * @param wsUrl - The WebSocket URL to connect to.
3000
+ * @returns A Promise that resolves when the connection is successfully established,
3001
+ * or rejects if an error occurs during the connection process.
3002
+ * @throws Will throw an error if the WebSocket connection cannot be established
3003
+ * after the maximum number of retry attempts.
2406
3004
  */
2407
3005
  async initializeWebSocket(wsUrl) {
2408
3006
  return (0, import_exponential_backoff.backOff)(async () => {
@@ -2411,7 +3009,14 @@ var WebSocketClient = class extends import_events3.EventEmitter {
2411
3009
  this.ws = new import_ws.default(wsUrl);
2412
3010
  this.ws.on("open", () => {
2413
3011
  console.log("WebSocket connection established successfully");
3012
+ if (this.isReconnecting) {
3013
+ this.emit("reconnected", {
3014
+ apps: this.apps,
3015
+ subscribedEvents: this.subscribedEvents
3016
+ });
3017
+ }
2414
3018
  this.isReconnecting = false;
3019
+ this.reconnectionAttempts = 0;
2415
3020
  this.emit("connected");
2416
3021
  resolve();
2417
3022
  });
@@ -2421,13 +3026,13 @@ var WebSocketClient = class extends import_events3.EventEmitter {
2421
3026
  `WebSocket disconnected with code ${code}. Attempting to reconnect...`
2422
3027
  );
2423
3028
  if (!this.isReconnecting) {
2424
- this.reconnect(wsUrl);
3029
+ this.reconnect(this.lastWsUrl);
2425
3030
  }
2426
3031
  });
2427
3032
  this.ws.on("error", (err) => {
2428
3033
  console.error("WebSocket error:", err.message);
2429
3034
  if (!this.isReconnecting) {
2430
- this.reconnect(wsUrl);
3035
+ this.reconnect(this.lastWsUrl);
2431
3036
  }
2432
3037
  reject(err);
2433
3038
  });
@@ -2438,9 +3043,16 @@ var WebSocketClient = class extends import_events3.EventEmitter {
2438
3043
  }, this.backOffOptions);
2439
3044
  }
2440
3045
  /**
2441
- * Processes incoming WebSocket messages.
3046
+ * Handles incoming WebSocket messages by parsing and processing events.
3047
+ *
3048
+ * This method parses the raw message into a WebSocketEvent, filters it based on
3049
+ * subscribed events (if any), processes channel and playback events, and emits
3050
+ * the event to listeners. It also handles any errors that occur during processing.
3051
+ *
3052
+ * @param rawMessage - The raw message string received from the WebSocket connection.
3053
+ * @returns void This method doesn't return a value but emits events.
2442
3054
  *
2443
- * @param {string} rawMessage - The raw message received from WebSocket
3055
+ * @throws Will emit an 'error' event if the message cannot be parsed or processed.
2444
3056
  */
2445
3057
  handleMessage(rawMessage) {
2446
3058
  try {
@@ -2458,6 +3070,11 @@ var WebSocketClient = class extends import_events3.EventEmitter {
2458
3070
  instancePlayback.emitEvent(event);
2459
3071
  event.instancePlayback = instancePlayback;
2460
3072
  }
3073
+ if ("bridge" in event && event.bridge?.id && this.ariClient) {
3074
+ const instanceBridge = this.ariClient.Bridge(event.bridge.id);
3075
+ instanceBridge.emitEvent(event);
3076
+ event.instanceBridge = instanceBridge;
3077
+ }
2461
3078
  this.emit(event.type, event);
2462
3079
  } catch (error) {
2463
3080
  console.error(
@@ -2468,18 +3085,27 @@ var WebSocketClient = class extends import_events3.EventEmitter {
2468
3085
  }
2469
3086
  }
2470
3087
  /**
2471
- * Attempts to reconnect to the WebSocket.
3088
+ * Attempts to reconnect to the WebSocket server using an exponential backoff strategy.
3089
+ *
3090
+ * This method is called when the WebSocket connection is closed unexpectedly.
3091
+ * It increments the reconnection attempt counter, logs the attempt, and uses
3092
+ * the backOff utility to retry the connection with exponential delays between attempts.
3093
+ *
3094
+ * @param wsUrl - The WebSocket URL to reconnect to.
3095
+ * @returns void - This method doesn't return a value.
2472
3096
  *
2473
- * @param {string} wsUrl - The WebSocket URL to reconnect to
3097
+ * @emits reconnectFailed - Emitted if all reconnection attempts fail.
2474
3098
  */
2475
3099
  reconnect(wsUrl) {
2476
3100
  this.isReconnecting = true;
2477
- console.log("Initiating reconnection attempt...");
2478
- this.removeAllListeners();
3101
+ this.reconnectionAttempts++;
3102
+ console.log(
3103
+ `Initiating reconnection attempt #${this.reconnectionAttempts}...`
3104
+ );
2479
3105
  (0, import_exponential_backoff.backOff)(() => this.initializeWebSocket(wsUrl), this.backOffOptions).catch(
2480
3106
  (error) => {
2481
3107
  console.error(
2482
- "Failed to reconnect after multiple attempts:",
3108
+ `Failed to reconnect after ${this.reconnectionAttempts} attempts:`,
2483
3109
  error instanceof Error ? error.message : "Unknown error"
2484
3110
  );
2485
3111
  this.emit("reconnectFailed", error);
@@ -2487,7 +3113,13 @@ var WebSocketClient = class extends import_events3.EventEmitter {
2487
3113
  );
2488
3114
  }
2489
3115
  /**
2490
- * Manually closes the WebSocket connection.
3116
+ * Closes the WebSocket connection if it exists.
3117
+ *
3118
+ * This method attempts to gracefully close the WebSocket connection
3119
+ * and sets the WebSocket instance to undefined. If an error occurs
3120
+ * during the closing process, it will be caught and logged.
3121
+ *
3122
+ * @throws {Error} Logs an error message if closing the WebSocket fails.
2491
3123
  */
2492
3124
  close() {
2493
3125
  try {
@@ -2504,17 +3136,30 @@ var WebSocketClient = class extends import_events3.EventEmitter {
2504
3136
  }
2505
3137
  }
2506
3138
  /**
2507
- * Checks if the WebSocket is currently connected.
3139
+ * Checks if the WebSocket connection is currently open and active.
2508
3140
  *
2509
- * @returns {boolean} True if connected, false otherwise
3141
+ * This method provides a way to determine the current state of the WebSocket connection.
3142
+ * It checks if the WebSocket's readyState property is equal to WebSocket.OPEN,
3143
+ * which indicates an active connection.
3144
+ *
3145
+ * @returns {boolean} True if the WebSocket connection is open and active, false otherwise.
2510
3146
  */
2511
3147
  isConnected() {
2512
3148
  return this.ws?.readyState === import_ws.default.OPEN;
2513
3149
  }
2514
3150
  /**
2515
- * Gets the current connection state.
3151
+ * Retrieves the current state of the WebSocket connection.
3152
+ *
3153
+ * This method provides a way to check the current state of the WebSocket connection.
3154
+ * It returns a number corresponding to one of the WebSocket readyState values:
3155
+ * - 0 (CONNECTING): The connection is not yet open.
3156
+ * - 1 (OPEN): The connection is open and ready to communicate.
3157
+ * - 2 (CLOSING): The connection is in the process of closing.
3158
+ * - 3 (CLOSED): The connection is closed or couldn't be opened.
3159
+ *
3160
+ * If the WebSocket instance doesn't exist, it returns WebSocket.CLOSED (3).
2516
3161
  *
2517
- * @returns {number} The WebSocket ready state
3162
+ * @returns {number} A number representing the current state of the WebSocket connection.
2518
3163
  */
2519
3164
  getState() {
2520
3165
  return this.ws?.readyState ?? import_ws.default.CLOSED;
@@ -2540,11 +3185,11 @@ var AriClient = class {
2540
3185
  this.baseClient = new BaseClient(baseUrl, config.username, config.password);
2541
3186
  this.channels = new Channels(this.baseClient, this);
2542
3187
  this.playbacks = new Playbacks(this.baseClient, this);
3188
+ this.bridges = new Bridges(this.baseClient, this);
2543
3189
  this.endpoints = new Endpoints(this.baseClient);
2544
3190
  this.applications = new Applications(this.baseClient);
2545
3191
  this.sounds = new Sounds(this.baseClient);
2546
3192
  this.asterisk = new Asterisk(this.baseClient);
2547
- this.bridges = new Bridges(this.baseClient);
2548
3193
  console.log(`ARI Client initialized with base URL: ${baseUrl}`);
2549
3194
  }
2550
3195
  baseClient;
@@ -2660,6 +3305,20 @@ var AriClient = class {
2660
3305
  Playback(playbackId, _app) {
2661
3306
  return this.playbacks.Playback({ id: playbackId });
2662
3307
  }
3308
+ /**
3309
+ * Creates or retrieves a Bridge instance.
3310
+ *
3311
+ * This function allows you to create a new Bridge instance or retrieve an existing one
3312
+ * based on the provided bridge ID.
3313
+ *
3314
+ * @param {string} [bridgeId] - Optional ID of an existing bridge. If provided, retrieves the
3315
+ * existing bridge with this ID. If omitted, creates a new bridge.
3316
+ * @returns {BridgeInstance} A new or existing Bridge instance that can be used to interact
3317
+ * with the Asterisk bridge.
3318
+ */
3319
+ Bridge(bridgeId) {
3320
+ return this.bridges.Bridge({ id: bridgeId });
3321
+ }
2663
3322
  /**
2664
3323
  * Gets the current WebSocket connection status.
2665
3324
  *
@@ -2674,6 +3333,7 @@ var AriClient = class {
2674
3333
  Applications,
2675
3334
  AriClient,
2676
3335
  Asterisk,
3336
+ BridgeInstance,
2677
3337
  Bridges,
2678
3338
  ChannelInstance,
2679
3339
  Channels,