@ipcom/asterisk-ari 0.0.139 → 0.0.140

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.
@@ -594,29 +594,52 @@ module.exports = __toCommonJS(src_exports);
594
594
 
595
595
  // src/ari-client/baseClient.ts
596
596
  var import_axios = __toESM(require("axios"), 1);
597
+ var HTTPError = class extends Error {
598
+ constructor(message, status, method, url) {
599
+ super(message);
600
+ this.status = status;
601
+ this.method = method;
602
+ this.url = url;
603
+ this.name = "HTTPError";
604
+ }
605
+ };
597
606
  var BaseClient = class {
607
+ /**
608
+ * Creates a new BaseClient instance.
609
+ *
610
+ * @param {string} baseUrl - The base URL for the API
611
+ * @param {string} username - Username for authentication
612
+ * @param {string} password - Password for authentication
613
+ * @param {number} [timeout=5000] - Request timeout in milliseconds
614
+ * @throws {Error} If the base URL format is invalid
615
+ */
598
616
  constructor(baseUrl, username, password, timeout = 5e3) {
599
617
  this.baseUrl = baseUrl;
600
618
  this.username = username;
601
619
  this.password = password;
602
620
  if (!/^https?:\/\/.+/.test(baseUrl)) {
603
- throw new Error(
604
- "Invalid base URL. It must start with http:// or https://"
605
- );
621
+ throw new Error("Invalid base URL. It must start with http:// or https://");
606
622
  }
607
623
  this.client = import_axios.default.create({
608
624
  baseURL: baseUrl,
609
625
  auth: { username, password },
610
- timeout
626
+ timeout,
627
+ headers: {
628
+ "Content-Type": "application/json"
629
+ }
611
630
  });
612
631
  this.addInterceptors();
632
+ console.log(`BaseClient initialized for ${baseUrl}`);
613
633
  }
614
634
  client;
635
+ /**
636
+ * Gets the base URL of the client.
637
+ */
615
638
  getBaseUrl() {
616
639
  return this.baseUrl;
617
640
  }
618
641
  /**
619
- * Retorna as credenciais configuradas.
642
+ * Gets the configured credentials.
620
643
  */
621
644
  getCredentials() {
622
645
  return {
@@ -626,123 +649,159 @@ var BaseClient = class {
626
649
  };
627
650
  }
628
651
  /**
629
- * Adds interceptors to the Axios instance.
652
+ * Adds request and response interceptors to the Axios instance.
630
653
  */
631
654
  addInterceptors() {
632
655
  this.client.interceptors.request.use(
633
656
  (config) => {
657
+ console.log(`[Request] ${config.method?.toUpperCase()} ${config.url}`);
634
658
  return config;
635
659
  },
636
660
  (error) => {
637
- console.error("[Request Error]", error.message);
638
- return Promise.reject(error);
661
+ const message = this.getErrorMessage(error);
662
+ console.error("[Request Error]", message);
663
+ return Promise.reject(new HTTPError(message));
639
664
  }
640
665
  );
641
666
  this.client.interceptors.response.use(
642
- (response) => response,
667
+ (response) => {
668
+ console.log(`[Response] ${response.status} ${response.config.url}`);
669
+ return response;
670
+ },
643
671
  (error) => {
644
- const status = error.response?.status;
645
- const message = error.response?.data?.message || error.message || "Unknown error";
646
- const errorDetails = {
647
- status,
648
- message,
649
- url: error.config?.url || "Unknown URL",
650
- method: error.config?.method?.toUpperCase() || "Unknown Method"
651
- };
652
- if (status === 404) {
653
- console.warn(`[404] Not Found: ${errorDetails.url}`);
654
- } else if (status >= 500) {
655
- console.error(`[500] Server Error: ${errorDetails.url}`);
656
- } else {
657
- console.warn(
658
- `[Response Error] ${errorDetails.method} ${errorDetails.url}: ${message}`
659
- );
672
+ if ((0, import_axios.isAxiosError)(error)) {
673
+ const status = error.response?.status ?? 0;
674
+ const method = error.config?.method?.toUpperCase() ?? "UNKNOWN";
675
+ const url = error.config?.url ?? "unknown-url";
676
+ const message2 = error.response?.data?.message || error.message || "Unknown error";
677
+ if (status === 404) {
678
+ console.warn(`[404] Not Found: ${url}`);
679
+ } else if (status >= 500) {
680
+ console.error(`[${status}] Server Error: ${url}`);
681
+ } else if (status > 0) {
682
+ console.warn(`[${status}] ${method} ${url}: ${message2}`);
683
+ } else {
684
+ console.error(`[Network] Request failed: ${message2}`);
685
+ }
686
+ throw new HTTPError(message2, status || void 0, method, url);
660
687
  }
661
- return Promise.reject(
662
- new Error(
663
- `[Error] ${errorDetails.method} ${errorDetails.url} - ${message} (Status: ${status})`
664
- )
665
- );
688
+ const message = this.getErrorMessage(error);
689
+ console.error("[Unexpected Error]", message);
690
+ throw new Error(message);
666
691
  }
667
692
  );
668
693
  }
669
694
  /**
670
695
  * Executes a GET request.
671
- * @param path - The API endpoint path.
672
- * @param config - Optional Axios request configuration.
696
+ *
697
+ * @param path - API endpoint path
698
+ * @param config - Optional Axios request configuration
699
+ * @returns Promise with the response data
673
700
  */
674
701
  async get(path, config) {
675
702
  try {
676
703
  const response = await this.client.get(path, config);
677
704
  return response.data;
678
705
  } catch (error) {
679
- this.handleRequestError(error);
706
+ throw this.handleRequestError(error);
680
707
  }
681
708
  }
682
709
  /**
683
710
  * Executes a POST request.
684
- * @param path - The API endpoint path.
685
- * @param data - Optional payload to send with the request.
686
- * @param config - Optional Axios request configuration.
711
+ *
712
+ * @param path - API endpoint path
713
+ * @param data - Request payload
714
+ * @param config - Optional Axios request configuration
715
+ * @returns Promise with the response data
687
716
  */
688
717
  async post(path, data, config) {
689
718
  try {
690
719
  const response = await this.client.post(path, data, config);
691
720
  return response.data;
692
721
  } catch (error) {
693
- this.handleRequestError(error);
722
+ throw this.handleRequestError(error);
694
723
  }
695
724
  }
696
725
  /**
697
726
  * Executes a PUT request.
698
- * @param path - The API endpoint path.
699
- * @param data - Payload to send with the request.
700
- * @param config - Optional Axios request configuration.
727
+ *
728
+ * @param path - API endpoint path
729
+ * @param data - Request payload
730
+ * @param config - Optional Axios request configuration
731
+ * @returns Promise with the response data
701
732
  */
702
733
  async put(path, data, config) {
703
734
  try {
704
735
  const response = await this.client.put(path, data, config);
705
736
  return response.data;
706
737
  } catch (error) {
707
- this.handleRequestError(error);
738
+ throw this.handleRequestError(error);
708
739
  }
709
740
  }
710
741
  /**
711
742
  * Executes a DELETE request.
712
- * @param path - The API endpoint path.
713
- * @param config - Optional Axios request configuration.
743
+ *
744
+ * @param path - API endpoint path
745
+ * @param config - Optional Axios request configuration
746
+ * @returns Promise with the response data
714
747
  */
715
748
  async delete(path, config) {
716
749
  try {
717
750
  const response = await this.client.delete(path, config);
718
751
  return response.data;
719
752
  } catch (error) {
720
- this.handleRequestError(error);
753
+ throw this.handleRequestError(error);
721
754
  }
722
755
  }
723
756
  /**
724
- * Handles errors for HTTP requests.
725
- * @param error - The error to handle.
757
+ * Handles and formats error messages from various error types.
758
+ */
759
+ getErrorMessage(error) {
760
+ if ((0, import_axios.isAxiosError)(error)) {
761
+ return error.response?.data?.message || error.message || "HTTP Error";
762
+ }
763
+ if (error instanceof Error) {
764
+ return error.message;
765
+ }
766
+ return "An unknown error occurred";
767
+ }
768
+ /**
769
+ * Handles errors from HTTP requests.
726
770
  */
727
771
  handleRequestError(error) {
728
- if (import_axios.default.isAxiosError(error)) {
729
- console.error(`[HTTP Error] ${error.message}`);
730
- throw new Error(error.message || "HTTP Error");
731
- } else {
732
- console.error(`[Unexpected Error] ${error}`);
733
- throw error;
772
+ const message = this.getErrorMessage(error);
773
+ if ((0, import_axios.isAxiosError)(error)) {
774
+ throw new HTTPError(
775
+ message,
776
+ error.response?.status,
777
+ error.config?.method?.toUpperCase(),
778
+ error.config?.url
779
+ );
734
780
  }
781
+ throw new Error(message);
735
782
  }
736
783
  /**
737
784
  * Sets custom headers for the client instance.
738
- * Useful for adding dynamic tokens or specific API headers.
739
- * @param headers - Headers to merge with existing configuration.
740
785
  */
741
786
  setHeaders(headers) {
742
787
  this.client.defaults.headers.common = {
743
788
  ...this.client.defaults.headers.common,
744
789
  ...headers
745
790
  };
791
+ console.log("Updated client headers");
792
+ }
793
+ /**
794
+ * Gets the current request timeout setting.
795
+ */
796
+ getTimeout() {
797
+ return this.client.defaults.timeout || 5e3;
798
+ }
799
+ /**
800
+ * Updates the request timeout setting.
801
+ */
802
+ setTimeout(timeout) {
803
+ this.client.defaults.timeout = timeout;
804
+ console.log(`Updated timeout to ${timeout}ms`);
746
805
  }
747
806
  };
748
807
 
@@ -1020,102 +1079,199 @@ function toQueryParams2(options) {
1020
1079
  }
1021
1080
 
1022
1081
  // src/ari-client/resources/channels.ts
1082
+ var import_axios2 = require("axios");
1083
+ var getErrorMessage = (error) => {
1084
+ if ((0, import_axios2.isAxiosError)(error)) {
1085
+ return error.response?.data?.message || error.message || "An axios error occurred";
1086
+ }
1087
+ if (error instanceof Error) {
1088
+ return error.message;
1089
+ }
1090
+ return "An unknown error occurred";
1091
+ };
1023
1092
  var ChannelInstance = class {
1024
- // ID do canal
1025
- constructor(client, baseClient, channelId = `channel-${Date.now()}`) {
1093
+ constructor(client, baseClient, channelId) {
1026
1094
  this.client = client;
1027
1095
  this.baseClient = baseClient;
1028
- this.channelId = channelId;
1029
1096
  this.id = channelId || `channel-${Date.now()}`;
1097
+ console.log(`Channel instance initialized with ID: ${this.id}`);
1030
1098
  }
1031
1099
  eventEmitter = new import_events.EventEmitter();
1032
1100
  channelData = null;
1033
1101
  id;
1034
1102
  /**
1035
- * Registra um listener para eventos específicos deste canal.
1103
+ * Registers an event listener for specific channel events
1036
1104
  */
1037
1105
  on(event, listener) {
1106
+ if (!event) {
1107
+ throw new Error("Event type is required");
1108
+ }
1038
1109
  const wrappedListener = (data) => {
1039
1110
  if ("channel" in data && data.channel?.id === this.id) {
1040
1111
  listener(data);
1041
1112
  }
1042
1113
  };
1043
1114
  this.eventEmitter.on(event, wrappedListener);
1115
+ console.log(`Event listener registered for ${event} on channel ${this.id}`);
1044
1116
  }
1045
1117
  /**
1046
- * Registra um listener único para eventos específicos deste canal.
1118
+ * Registers a one-time event listener
1047
1119
  */
1048
1120
  once(event, listener) {
1121
+ if (!event) {
1122
+ throw new Error("Event type is required");
1123
+ }
1049
1124
  const wrappedListener = (data) => {
1050
1125
  if ("channel" in data && data.channel?.id === this.id) {
1051
1126
  listener(data);
1052
1127
  }
1053
1128
  };
1054
1129
  this.eventEmitter.once(event, wrappedListener);
1130
+ console.log(`One-time event listener registered for ${event} on channel ${this.id}`);
1055
1131
  }
1056
1132
  /**
1057
- * Remove um listener para eventos específicos deste canal.
1133
+ * Removes event listener(s) for a specific WebSocket event type.
1134
+ * If a specific listener is provided, only that listener is removed.
1135
+ * Otherwise, all listeners for the given event type are removed.
1136
+ *
1137
+ * @param {T} event - The type of WebSocket event to remove listener(s) for
1138
+ * @param {Function} [listener] - Optional specific listener to remove
1139
+ * @throws {Error} If no event type is provided
1058
1140
  */
1059
1141
  off(event, listener) {
1142
+ if (!event) {
1143
+ throw new Error("Event type is required");
1144
+ }
1060
1145
  if (listener) {
1061
1146
  this.eventEmitter.off(event, listener);
1147
+ console.log(`Specific listener removed for ${event} on channel ${this.id}`);
1062
1148
  } else {
1063
- const listeners = this.eventEmitter.listeners(event);
1064
- listeners.forEach((fn) => {
1065
- this.eventEmitter.off(event, fn);
1066
- });
1149
+ this.eventEmitter.removeAllListeners(event);
1150
+ console.log(`All listeners removed for ${event} on channel ${this.id}`);
1067
1151
  }
1068
1152
  }
1069
1153
  /**
1070
- * Obtém a quantidade de listeners registrados para o evento especificado.
1071
- */
1072
- getListenerCount(event) {
1073
- return this.eventEmitter.listenerCount(event);
1074
- }
1075
- /**
1076
- * Emite eventos internamente para o canal.
1077
- * Verifica o ID do canal antes de emitir.
1154
+ * Emits an event if it matches the current channel
1078
1155
  */
1079
1156
  emitEvent(event) {
1157
+ if (!event) {
1158
+ console.warn("Received invalid event");
1159
+ return;
1160
+ }
1080
1161
  if ("channel" in event && event.channel?.id === this.id) {
1081
1162
  this.eventEmitter.emit(event.type, event);
1163
+ console.log(`Event ${event.type} emitted for channel ${this.id}`);
1082
1164
  }
1083
1165
  }
1084
1166
  /**
1085
- * Remove todos os listeners para este canal.
1167
+ * Removes all event listeners associated with the current instance.
1168
+ * This ensures that there are no lingering event handlers for the channel.
1169
+ *
1170
+ * @return {void} This method does not return a value.
1086
1171
  */
1087
1172
  removeAllListeners() {
1088
1173
  console.log(`Removendo todos os listeners para o canal ${this.id}`);
1089
1174
  this.eventEmitter.removeAllListeners();
1090
1175
  }
1176
+ /**
1177
+ * Answers the channel
1178
+ */
1091
1179
  async answer() {
1092
- await this.baseClient.post(`/channels/${this.id}/answer`);
1180
+ try {
1181
+ await this.baseClient.post(`/channels/${this.id}/answer`);
1182
+ console.log(`Channel ${this.id} answered`);
1183
+ } catch (error) {
1184
+ const message = getErrorMessage(error);
1185
+ console.error(`Error answering channel ${this.id}:`, message);
1186
+ throw new Error(`Failed to answer channel: ${message}`);
1187
+ }
1093
1188
  }
1094
1189
  /**
1095
- * Origina um canal físico no Asterisk.
1190
+ * Originates a new channel
1191
+ *
1192
+ * @param data - Channel origination configuration
1193
+ * @returns Promise resolving to the created channel
1194
+ * @throws Error if channel already exists or origination fails
1096
1195
  */
1097
1196
  async originate(data) {
1098
1197
  if (this.channelData) {
1099
- throw new Error("O canal j\xE1 foi criado.");
1198
+ throw new Error("Channel has already been created");
1199
+ }
1200
+ try {
1201
+ this.channelData = await this.baseClient.post("/channels", data);
1202
+ console.log(`Channel originated successfully with ID: ${this.channelData.id}`);
1203
+ return this.channelData;
1204
+ } catch (error) {
1205
+ const message = getErrorMessage(error);
1206
+ console.error(`Error originating channel:`, message);
1207
+ throw new Error(`Failed to originate channel: ${message}`);
1100
1208
  }
1101
- const channel = await this.baseClient.post("/channels", data);
1102
- this.channelData = channel;
1103
- return channel;
1104
1209
  }
1105
1210
  /**
1106
- * Obtém os detalhes do canal.
1211
+ * Plays media on the channel
1107
1212
  */
1108
- async getDetails() {
1109
- if (this.channelData) {
1110
- return this.channelData;
1213
+ async play(options, playbackId) {
1214
+ if (!options.media) {
1215
+ throw new Error("Media URL is required");
1111
1216
  }
1112
- if (!this.id) {
1113
- throw new Error("Nenhum ID de canal associado a esta inst\xE2ncia.");
1217
+ try {
1218
+ if (!this.channelData) {
1219
+ console.log("Initializing channel details...");
1220
+ this.channelData = await this.getDetails();
1221
+ }
1222
+ const playback = this.client.Playback(playbackId || v4_default());
1223
+ await this.baseClient.post(
1224
+ `/channels/${this.id}/play/${playback.id}`,
1225
+ options
1226
+ );
1227
+ console.log(`Media playback started on channel ${this.id}`);
1228
+ return playback;
1229
+ } catch (error) {
1230
+ const message = getErrorMessage(error);
1231
+ console.error(`Error playing media on channel ${this.id}:`, message);
1232
+ throw new Error(`Failed to play media: ${message}`);
1233
+ }
1234
+ }
1235
+ /**
1236
+ * Gets the current channel details
1237
+ */
1238
+ async getDetails() {
1239
+ try {
1240
+ if (this.channelData) {
1241
+ return this.channelData;
1242
+ }
1243
+ if (!this.id) {
1244
+ throw new Error("No channel ID associated with this instance");
1245
+ }
1246
+ const details = await this.baseClient.get(`/channels/${this.id}`);
1247
+ this.channelData = details;
1248
+ console.log(`Retrieved channel details for ${this.id}`);
1249
+ return details;
1250
+ } catch (error) {
1251
+ const message = getErrorMessage(error);
1252
+ console.error(`Error retrieving channel details for ${this.id}:`, message);
1253
+ throw new Error(`Failed to get channel details: ${message}`);
1114
1254
  }
1115
- const details = await this.baseClient.get(`/channels/${this.id}`);
1116
- this.channelData = details;
1117
- return details;
1118
1255
  }
1256
+ /**
1257
+ * Checks if the channel has any listeners for a specific event
1258
+ */
1259
+ hasListeners(event) {
1260
+ return this.eventEmitter.listenerCount(event) > 0;
1261
+ }
1262
+ /**
1263
+ * Gets the count of listeners for a specific event
1264
+ */
1265
+ getListenerCount(event) {
1266
+ return this.eventEmitter.listenerCount(event);
1267
+ }
1268
+ /**
1269
+ * Fetches a specific channel variable.
1270
+ *
1271
+ * @param {string} variable - The name of the variable to retrieve. This parameter is required.
1272
+ * @return {Promise<ChannelVar>} A promise that resolves with the value of the requested channel variable.
1273
+ * @throws {Error} If the 'variable' parameter is not provided.
1274
+ */
1119
1275
  async getVariable(variable) {
1120
1276
  if (!variable) {
1121
1277
  throw new Error("The 'variable' parameter is required.");
@@ -1125,7 +1281,11 @@ var ChannelInstance = class {
1125
1281
  );
1126
1282
  }
1127
1283
  /**
1128
- * Encerra o canal, se ele foi criado.
1284
+ * Terminates the active call associated with the current channel.
1285
+ * This method ensures that channel details are initialized before attempting to hang up.
1286
+ * If the channel ID is invalid or cannot be determined, an error is thrown.
1287
+ *
1288
+ * @return {Promise<void>} A promise that resolves when the call is successfully terminated.
1129
1289
  */
1130
1290
  async hangup() {
1131
1291
  if (!this.channelData) {
@@ -1138,25 +1298,12 @@ var ChannelInstance = class {
1138
1298
  await this.baseClient.delete(`/channels/${this.channelData.id}`);
1139
1299
  }
1140
1300
  /**
1141
- * Reproduz mídia no canal.
1142
- */
1143
- async play(options, playbackId) {
1144
- if (!this.channelData) {
1145
- console.log("Canal n\xE3o inicializado, buscando detalhes...");
1146
- this.channelData = await this.getDetails();
1147
- }
1148
- const playback = this.client.Playback(playbackId || v4_default());
1149
- if (!this.channelData?.id) {
1150
- throw new Error("N\xE3o foi poss\xEDvel inicializar o canal. ID inv\xE1lido.");
1151
- }
1152
- await this.baseClient.post(
1153
- `/channels/${this.channelData.id}/play/${playback.id}`,
1154
- options
1155
- );
1156
- return playback;
1157
- }
1158
- /**
1159
- * Reproduz mídia em um canal.
1301
+ * Plays media on the specified channel using the provided media URL and optional playback options.
1302
+ *
1303
+ * @param {string} media - The URL or identifier of the media to be played.
1304
+ * @param {PlaybackOptions} [options] - Optional playback settings such as volume, playback speed, etc.
1305
+ * @return {Promise<ChannelPlayback>} A promise that resolves with the playback details for the channel.
1306
+ * @throws {Error} Throws an error if the channel has not been created.
1160
1307
  */
1161
1308
  async playMedia(media, options) {
1162
1309
  if (!this.channelData) {
@@ -1169,7 +1316,11 @@ var ChannelInstance = class {
1169
1316
  );
1170
1317
  }
1171
1318
  /**
1172
- * Para a reprodução de mídia.
1319
+ * Stops the playback for the given playback ID.
1320
+ *
1321
+ * @param {string} playbackId - The unique identifier for the playback to be stopped.
1322
+ * @return {Promise<void>} A promise that resolves when the playback is successfully stopped.
1323
+ * @throws {Error} Throws an error if the instance is not associated with a channel.
1173
1324
  */
1174
1325
  async stopPlayback(playbackId) {
1175
1326
  if (!this.channelData?.id) {
@@ -1180,7 +1331,11 @@ var ChannelInstance = class {
1180
1331
  );
1181
1332
  }
1182
1333
  /**
1183
- * Pausa a reprodução de mídia.
1334
+ * Pauses the playback of the specified media on a channel.
1335
+ *
1336
+ * @param {string} playbackId - The unique identifier of the playback to be paused.
1337
+ * @return {Promise<void>} A promise that resolves when the playback has been successfully paused.
1338
+ * @throws {Error} Throws an error if the channel is not associated with the current instance.
1184
1339
  */
1185
1340
  async pausePlayback(playbackId) {
1186
1341
  if (!this.channelData?.id) {
@@ -1191,7 +1346,11 @@ var ChannelInstance = class {
1191
1346
  );
1192
1347
  }
1193
1348
  /**
1194
- * Retoma a reprodução de mídia.
1349
+ * Resumes playback of the specified playback session on the associated channel.
1350
+ *
1351
+ * @param {string} playbackId - The unique identifier of the playback session to be resumed.
1352
+ * @return {Promise<void>} A promise that resolves when the playback has been successfully resumed.
1353
+ * @throws {Error} Throws an error if the channel is not associated with this instance.
1195
1354
  */
1196
1355
  async resumePlayback(playbackId) {
1197
1356
  if (!this.channelData?.id) {
@@ -1202,7 +1361,11 @@ var ChannelInstance = class {
1202
1361
  );
1203
1362
  }
1204
1363
  /**
1205
- * Retrocede a reprodução de mídia.
1364
+ * Rewinds the playback of a media by a specified amount of milliseconds.
1365
+ *
1366
+ * @param {string} playbackId - The unique identifier for the playback session to be rewound.
1367
+ * @param {number} skipMs - The number of milliseconds to rewind the playback.
1368
+ * @return {Promise<void>} A promise that resolves when the rewind operation is complete.
1206
1369
  */
1207
1370
  async rewindPlayback(playbackId, skipMs) {
1208
1371
  if (!this.channelData?.id) {
@@ -1214,7 +1377,12 @@ var ChannelInstance = class {
1214
1377
  );
1215
1378
  }
1216
1379
  /**
1217
- * Avança a reprodução de mídia.
1380
+ * Fast forwards the playback by a specific duration in milliseconds.
1381
+ *
1382
+ * @param {string} playbackId - The unique identifier of the playback to be fast-forwarded.
1383
+ * @param {number} skipMs - The number of milliseconds to fast forward the playback.
1384
+ * @return {Promise<void>} A Promise that resolves when the fast-forward operation is complete.
1385
+ * @throws {Error} If no channel is associated with this instance.
1218
1386
  */
1219
1387
  async fastForwardPlayback(playbackId, skipMs) {
1220
1388
  if (!this.channelData?.id) {
@@ -1226,7 +1394,11 @@ var ChannelInstance = class {
1226
1394
  );
1227
1395
  }
1228
1396
  /**
1229
- * Muta o canal.
1397
+ * Mutes the specified channel for the given direction.
1398
+ *
1399
+ * @param {("both" | "in" | "out")} [direction="both"] - The direction to mute the channel. It can be "both" to mute incoming and outgoing, "in" to mute incoming, or "out" to mute outgoing.
1400
+ * @return {Promise<void>} A promise that resolves when the channel is successfully muted.
1401
+ * @throws {Error} If the channel is not associated with this instance.
1230
1402
  */
1231
1403
  async muteChannel(direction = "both") {
1232
1404
  if (!this.channelData?.id) {
@@ -1237,7 +1409,12 @@ var ChannelInstance = class {
1237
1409
  );
1238
1410
  }
1239
1411
  /**
1240
- * Desmuta o canal.
1412
+ * Unmutes a previously muted channel in the specified direction.
1413
+ *
1414
+ * @param {"both" | "in" | "out"} direction - The direction in which to unmute the channel.
1415
+ * Defaults to "both", which unmutes both incoming and outgoing communication.
1416
+ * @return {Promise<void>} A promise that resolves once the channel has been successfully unmuted.
1417
+ * @throws {Error} If the channel is not associated with the current instance.
1241
1418
  */
1242
1419
  async unmuteChannel(direction = "both") {
1243
1420
  if (!this.channelData?.id) {
@@ -1248,7 +1425,10 @@ var ChannelInstance = class {
1248
1425
  );
1249
1426
  }
1250
1427
  /**
1251
- * Coloca o canal em espera.
1428
+ * Places the associated channel on hold if the channel is valid and linked to this instance.
1429
+ *
1430
+ * @return {Promise<void>} A promise that resolves when the hold action is successfully executed.
1431
+ * @throws {Error} Throws an error if the channel is not associated with this instance.
1252
1432
  */
1253
1433
  async holdChannel() {
1254
1434
  if (!this.channelData?.id) {
@@ -1257,7 +1437,12 @@ var ChannelInstance = class {
1257
1437
  await this.baseClient.post(`/channels/${this.channelData.id}/hold`);
1258
1438
  }
1259
1439
  /**
1260
- * Remove o canal da espera.
1440
+ * Removes the hold status from a specific channel associated with this instance.
1441
+ * The method sends a delete request to the server to release the hold on the channel.
1442
+ * If no channel is associated with this instance, an error will be thrown.
1443
+ *
1444
+ * @return {Promise<void>} A promise that resolves when the channel hold has been successfully removed.
1445
+ * @throws {Error} If no channel is associated with this instance.
1261
1446
  */
1262
1447
  async unholdChannel() {
1263
1448
  if (!this.channelData?.id) {
@@ -1272,73 +1457,125 @@ var Channels = class {
1272
1457
  this.client = client;
1273
1458
  }
1274
1459
  channelInstances = /* @__PURE__ */ new Map();
1460
+ /**
1461
+ * Creates or retrieves a ChannelInstance based on the provided id.
1462
+ */
1275
1463
  Channel({ id }) {
1276
- if (!id) {
1277
- const instance = new ChannelInstance(this.client, this.baseClient);
1278
- this.channelInstances.set(instance.id, instance);
1279
- return instance;
1280
- }
1281
- if (!this.channelInstances.has(id)) {
1282
- const instance = new ChannelInstance(this.client, this.baseClient, id);
1283
- this.channelInstances.set(id, instance);
1284
- return instance;
1464
+ try {
1465
+ if (!id) {
1466
+ const instance = new ChannelInstance(this.client, this.baseClient);
1467
+ this.channelInstances.set(instance.id, instance);
1468
+ console.log(`New channel instance created with ID: ${instance.id}`);
1469
+ return instance;
1470
+ }
1471
+ if (!this.channelInstances.has(id)) {
1472
+ const instance = new ChannelInstance(this.client, this.baseClient, id);
1473
+ this.channelInstances.set(id, instance);
1474
+ console.log(`New channel instance created with provided ID: ${id}`);
1475
+ return instance;
1476
+ }
1477
+ console.log(`Returning existing channel instance: ${id}`);
1478
+ return this.channelInstances.get(id);
1479
+ } catch (error) {
1480
+ const message = getErrorMessage(error);
1481
+ console.error(`Error creating/retrieving channel instance:`, message);
1482
+ throw new Error(`Failed to manage channel instance: ${message}`);
1285
1483
  }
1286
- return this.channelInstances.get(id);
1287
1484
  }
1288
1485
  /**
1289
- * Remove uma instância de canal.
1486
+ * Removes a channel instance from the collection.
1290
1487
  */
1291
1488
  removeChannelInstance(channelId) {
1489
+ if (!channelId) {
1490
+ throw new Error("Channel ID is required");
1491
+ }
1292
1492
  if (this.channelInstances.has(channelId)) {
1293
1493
  const instance = this.channelInstances.get(channelId);
1294
1494
  instance?.removeAllListeners();
1295
1495
  this.channelInstances.delete(channelId);
1296
- console.log(`Inst\xE2ncia do canal ${channelId} removida.`);
1496
+ console.log(`Channel instance removed: ${channelId}`);
1297
1497
  } else {
1298
- console.warn(
1299
- `Tentativa de remover uma inst\xE2ncia inexistente: ${channelId}`
1300
- );
1498
+ console.warn(`Attempt to remove non-existent instance: ${channelId}`);
1301
1499
  }
1302
1500
  }
1303
1501
  /**
1304
- * Propaga eventos do WebSocket para o canal correspondente.
1502
+ * Propagates a WebSocket event to a specific channel.
1305
1503
  */
1306
1504
  propagateEventToChannel(event) {
1505
+ if (!event) {
1506
+ console.warn("Invalid WebSocket event received");
1507
+ return;
1508
+ }
1307
1509
  if ("channel" in event && event.channel?.id) {
1308
1510
  const instance = this.channelInstances.get(event.channel.id);
1309
1511
  if (instance) {
1310
1512
  instance.emitEvent(event);
1513
+ console.log(`Event propagated to channel ${event.channel.id}: ${event.type}`);
1311
1514
  } else {
1312
- console.warn(
1313
- `Nenhuma inst\xE2ncia encontrada para o canal ${event.channel.id}`
1314
- );
1515
+ console.warn(`No instance found for channel ${event.channel.id}`);
1315
1516
  }
1316
1517
  }
1317
1518
  }
1318
1519
  /**
1319
- * Origina um canal físico diretamente, sem uma instância de `ChannelInstance`.
1520
+ * Initiates a new channel.
1320
1521
  */
1321
1522
  async originate(data) {
1322
- return this.baseClient.post("/channels", data);
1523
+ if (!data.endpoint) {
1524
+ throw new Error("Endpoint is required for channel origination");
1525
+ }
1526
+ try {
1527
+ const channel = await this.baseClient.post("/channels", data);
1528
+ console.log(`Channel originated successfully with ID: ${channel.id}`);
1529
+ return channel;
1530
+ } catch (error) {
1531
+ const message = getErrorMessage(error);
1532
+ console.error(`Error originating channel:`, message);
1533
+ throw new Error(`Failed to originate channel: ${message}`);
1534
+ }
1323
1535
  }
1324
1536
  /**
1325
- * Obtém detalhes de um canal específico.
1537
+ * Lists all active channels.
1326
1538
  */
1327
- async getDetails(channelId) {
1328
- return this.baseClient.get(`/channels/${channelId}`);
1539
+ async list() {
1540
+ try {
1541
+ const channels = await this.baseClient.get("/channels");
1542
+ if (!Array.isArray(channels)) {
1543
+ throw new Error("API response for /channels is not an array");
1544
+ }
1545
+ console.log(`Retrieved ${channels.length} active channels`);
1546
+ return channels;
1547
+ } catch (error) {
1548
+ const message = getErrorMessage(error);
1549
+ console.error(`Error listing channels:`, message);
1550
+ throw new Error(`Failed to list channels: ${message}`);
1551
+ }
1329
1552
  }
1330
1553
  /**
1331
- * Lista todos os canais ativos.
1554
+ * Gets the count of active channel instances.
1332
1555
  */
1333
- async list() {
1334
- const channels = await this.baseClient.get("/channels");
1335
- if (!Array.isArray(channels)) {
1336
- throw new Error("Resposta da API /channels n\xE3o \xE9 um array.");
1337
- }
1338
- return channels;
1556
+ getInstanceCount() {
1557
+ return this.channelInstances.size;
1339
1558
  }
1340
1559
  /**
1341
- * Encerra um canal específico.
1560
+ * Checks if a channel instance exists.
1561
+ */
1562
+ hasInstance(channelId) {
1563
+ return this.channelInstances.has(channelId);
1564
+ }
1565
+ /**
1566
+ * Gets all active channel instances.
1567
+ */
1568
+ getAllInstances() {
1569
+ return new Map(this.channelInstances);
1570
+ }
1571
+ /**
1572
+ * Terminates an active call on the specified channel.
1573
+ *
1574
+ * @param {string} channelId - The unique identifier of the channel to hang up.
1575
+ * @param {Object} [options] - Optional parameters for the hangup request.
1576
+ * @param {string} [options.reason_code] - A code indicating the reason for the hangup.
1577
+ * @param {string} [options.reason] - A descriptive reason for the hangup.
1578
+ * @return {Promise<void>} A promise that resolves when the call has been successfully terminated.
1342
1579
  */
1343
1580
  async hangup(channelId, options) {
1344
1581
  const queryParams = new URLSearchParams({
@@ -1350,7 +1587,11 @@ var Channels = class {
1350
1587
  );
1351
1588
  }
1352
1589
  /**
1353
- * Inicia a escuta em um canal.
1590
+ * Initiates snooping on a specified channel with the provided options.
1591
+ *
1592
+ * @param {string} channelId - The unique identifier of the channel to snoop on.
1593
+ * @param {SnoopOptions} options - Configuration options for the snooping operation.
1594
+ * @return {Promise<Channel>} A promise that resolves to the snooped channel data.
1354
1595
  */
1355
1596
  async snoopChannel(channelId, options) {
1356
1597
  const queryParams = toQueryParams2(options);
@@ -1358,23 +1599,56 @@ var Channels = class {
1358
1599
  `/channels/${channelId}/snoop?${queryParams}`
1359
1600
  );
1360
1601
  }
1602
+ /**
1603
+ * Starts a silence mode for the specified channel.
1604
+ *
1605
+ * @param {string} channelId - The unique identifier of the channel where silence mode should be started.
1606
+ * @return {Promise<void>} A promise that resolves when the silence mode is successfully started.
1607
+ */
1361
1608
  async startSilence(channelId) {
1362
1609
  return this.baseClient.post(`/channels/${channelId}/silence`);
1363
1610
  }
1611
+ /**
1612
+ * Stops the silence mode for a specific channel.
1613
+ *
1614
+ * @param {string} channelId - The unique identifier of the channel for which silence mode should be stopped.
1615
+ * @return {Promise<void>} A promise that resolves when the operation is complete.
1616
+ */
1364
1617
  async stopSilence(channelId) {
1365
1618
  return this.baseClient.delete(`/channels/${channelId}/silence`);
1366
1619
  }
1620
+ /**
1621
+ * Retrieves the Real-Time Protocol (RTP) statistics for a specific channel.
1622
+ *
1623
+ * @param {string} channelId - The unique identifier of the channel for which RTP statistics are fetched.
1624
+ * @return {Promise<RTPStats>} A promise that resolves to the RTP statistics for the specified channel.
1625
+ */
1367
1626
  async getRTPStatistics(channelId) {
1368
1627
  return this.baseClient.get(
1369
1628
  `/channels/${channelId}/rtp_statistics`
1370
1629
  );
1371
1630
  }
1631
+ /**
1632
+ * Creates an external media channel with the given options.
1633
+ *
1634
+ * @param {ExternalMediaOptions} options - The configuration options for creating the external media channel.
1635
+ * @return {Promise<Channel>} A promise that resolves with the created external media channel.
1636
+ */
1372
1637
  async createExternalMedia(options) {
1373
1638
  const queryParams = toQueryParams2(options);
1374
1639
  return this.baseClient.post(
1375
1640
  `/channels/externalMedia?${queryParams}`
1376
1641
  );
1377
1642
  }
1643
+ /**
1644
+ * Initiates playback of a specific media item on a channel using the provided playback ID.
1645
+ *
1646
+ * @param {string} channelId - The unique identifier of the channel where playback will occur.
1647
+ * @param {string} playbackId - The unique identifier for the specific playback session.
1648
+ * @param {string} media - The media content to be played.
1649
+ * @param {PlaybackOptions} [options] - Optional playback configuration parameters.
1650
+ * @return {Promise<ChannelPlayback>} A promise that resolves with the playback details for the channel.
1651
+ */
1378
1652
  async playWithId(channelId, playbackId, media, options) {
1379
1653
  const queryParams = options ? `?${toQueryParams2(options)}` : "";
1380
1654
  return this.baseClient.post(
@@ -1382,18 +1656,41 @@ var Channels = class {
1382
1656
  { media }
1383
1657
  );
1384
1658
  }
1659
+ /**
1660
+ * Initiates a snoop operation on a specific channel using the provided channel ID and snoop ID.
1661
+ *
1662
+ * @param {string} channelId - The unique identifier of the channel to snoop on.
1663
+ * @param {string} snoopId - The unique identifier for the snoop operation.
1664
+ * @param {SnoopOptions} options - Additional options and parameters for the snoop operation.
1665
+ * @return {Promise<Channel>} A promise that resolves to the channel details after the snoop operation is initiated.
1666
+ */
1385
1667
  async snoopChannelWithId(channelId, snoopId, options) {
1386
1668
  const queryParams = toQueryParams2(options);
1387
1669
  return this.baseClient.post(
1388
1670
  `/channels/${channelId}/snoop/${snoopId}?${queryParams}`
1389
1671
  );
1390
1672
  }
1673
+ /**
1674
+ * Starts Music on Hold for the specified channel with the provided Music on Hold class.
1675
+ *
1676
+ * @param {string} channelId - The unique identifier of the channel.
1677
+ * @param {string} mohClass - The Music on Hold class to be applied.
1678
+ * @return {Promise<void>} A promise that resolves when the operation is complete.
1679
+ */
1391
1680
  async startMohWithClass(channelId, mohClass) {
1392
1681
  const queryParams = `mohClass=${encodeURIComponent(mohClass)}`;
1393
1682
  await this.baseClient.post(
1394
1683
  `/channels/${channelId}/moh?${queryParams}`
1395
1684
  );
1396
1685
  }
1686
+ /**
1687
+ * Retrieves the value of a specified variable for a given channel.
1688
+ *
1689
+ * @param {string} channelId - The unique identifier of the channel.
1690
+ * @param {string} variable - The name of the variable to retrieve.
1691
+ * @return {Promise<ChannelVar>} A promise that resolves to the value of the channel variable.
1692
+ * @throws {Error} Throws an error if the 'variable' parameter is not provided.
1693
+ */
1397
1694
  async getChannelVariable(channelId, variable) {
1398
1695
  if (!variable) {
1399
1696
  throw new Error("The 'variable' parameter is required.");
@@ -1402,6 +1699,15 @@ var Channels = class {
1402
1699
  `/channels/${channelId}/variable?variable=${encodeURIComponent(variable)}`
1403
1700
  );
1404
1701
  }
1702
+ /**
1703
+ * Sets a variable for a specific channel.
1704
+ *
1705
+ * @param {string} channelId - The unique identifier of the channel.
1706
+ * @param {string} variable - The name of the variable to be set. This parameter is required.
1707
+ * @param {string} [value] - The value of the variable to be set. This parameter is optional.
1708
+ * @return {Promise<void>} A promise that resolves when the variable is successfully set.
1709
+ * @throws {Error} Throws an error if the `variable` parameter is not provided.
1710
+ */
1405
1711
  async setChannelVariable(channelId, variable, value) {
1406
1712
  if (!variable) {
1407
1713
  throw new Error("The 'variable' parameter is required.");
@@ -1414,12 +1720,30 @@ var Channels = class {
1414
1720
  `/channels/${channelId}/variable?${queryParams}`
1415
1721
  );
1416
1722
  }
1723
+ /**
1724
+ * Moves a specified channel to the given application with optional arguments.
1725
+ *
1726
+ * @param {string} channelId - The unique identifier of the channel to be moved.
1727
+ * @param {string} app - The target application to which the channel will be moved.
1728
+ * @param {string} [appArgs] - Optional arguments to be passed to the target application.
1729
+ * @return {Promise<void>} A promise that resolves when the operation is completed.
1730
+ */
1417
1731
  async moveToApplication(channelId, app, appArgs) {
1418
1732
  await this.baseClient.post(`/channels/${channelId}/move`, {
1419
1733
  app,
1420
1734
  appArgs
1421
1735
  });
1422
1736
  }
1737
+ /**
1738
+ * Continues the execution of a dialplan for a specific channel.
1739
+ *
1740
+ * @param {string} channelId - The unique identifier of the channel.
1741
+ * @param {string} [context] - The dialplan context to continue execution in, if specified.
1742
+ * @param {string} [extension] - The dialplan extension to proceed with, if provided.
1743
+ * @param {number} [priority] - The priority within the dialplan extension to resume at, if specified.
1744
+ * @param {string} [label] - The label to start from within the dialplan, if given.
1745
+ * @return {Promise<void>} Resolves when the dialplan is successfully continued.
1746
+ */
1423
1747
  async continueDialplan(channelId, context, extension, priority, label) {
1424
1748
  await this.baseClient.post(`/channels/${channelId}/continue`, {
1425
1749
  context,
@@ -1428,18 +1752,45 @@ var Channels = class {
1428
1752
  label
1429
1753
  });
1430
1754
  }
1755
+ /**
1756
+ * Stops the music on hold for the specified channel.
1757
+ *
1758
+ * @param {string} channelId - The unique identifier of the channel where music on hold should be stopped.
1759
+ * @return {Promise<void>} Resolves when the music on hold is successfully stopped.
1760
+ */
1431
1761
  async stopMusicOnHold(channelId) {
1432
1762
  await this.baseClient.delete(`/channels/${channelId}/moh`);
1433
1763
  }
1764
+ /**
1765
+ * Initiates the music on hold for the specified channel.
1766
+ *
1767
+ * @param {string} channelId - The unique identifier of the channel where the music on hold will be started.
1768
+ * @return {Promise<void>} A promise that resolves when the operation has been successfully invoked.
1769
+ */
1434
1770
  async startMusicOnHold(channelId) {
1435
1771
  await this.baseClient.post(`/channels/${channelId}/moh`);
1436
1772
  }
1773
+ /**
1774
+ * Starts recording for a specific channel based on the provided options.
1775
+ *
1776
+ * @param {string} channelId - The unique identifier of the channel to start recording.
1777
+ * @param {RecordingOptions} options - The recording options to configure the recording process.
1778
+ * @return {Promise<Channel>} A promise that resolves to the channel object with updated recording state.
1779
+ */
1437
1780
  async record(channelId, options) {
1438
1781
  const queryParams = toQueryParams2(options);
1439
1782
  return this.baseClient.post(
1440
1783
  `/channels/${channelId}/record?${queryParams}`
1441
1784
  );
1442
1785
  }
1786
+ /**
1787
+ * Initiates a call on the specified channel with optional parameters for caller identification and timeout duration.
1788
+ *
1789
+ * @param {string} channelId - The ID of the channel where the call will be initiated.
1790
+ * @param {string} [caller] - Optional parameter specifying the name or identifier of the caller.
1791
+ * @param {number} [timeout] - Optional parameter defining the timeout duration for the call in seconds.
1792
+ * @return {Promise<void>} A promise that resolves when the call has been successfully initiated.
1793
+ */
1443
1794
  async dial(channelId, caller, timeout) {
1444
1795
  const queryParams = new URLSearchParams({
1445
1796
  ...caller && { caller },
@@ -1449,45 +1800,126 @@ var Channels = class {
1449
1800
  `/channels/${channelId}/dial?${queryParams}`
1450
1801
  );
1451
1802
  }
1803
+ /**
1804
+ * Redirects a channel to the specified endpoint.
1805
+ *
1806
+ * This method sends a POST request to update the redirect endpoint for the given channel.
1807
+ *
1808
+ * @param {string} channelId - The unique identifier of the channel to be redirected.
1809
+ * @param {string} endpoint - The new endpoint to redirect the channel to.
1810
+ * @return {Promise<void>} A promise that resolves when the operation is complete.
1811
+ */
1452
1812
  async redirectChannel(channelId, endpoint) {
1453
1813
  await this.baseClient.post(
1454
1814
  `/channels/${channelId}/redirect?endpoint=${encodeURIComponent(endpoint)}`
1455
1815
  );
1456
1816
  }
1817
+ /**
1818
+ * Answers a specified channel by sending a POST request to the corresponding endpoint.
1819
+ *
1820
+ * @param {string} channelId - The unique identifier of the channel to be answered.
1821
+ * @return {Promise<void>} A promise that resolves when the channel has been successfully answered.
1822
+ */
1457
1823
  async answerChannel(channelId) {
1458
1824
  await this.baseClient.post(`/channels/${channelId}/answer`);
1459
1825
  }
1826
+ /**
1827
+ * Rings the specified channel by sending a POST request to the appropriate endpoint.
1828
+ *
1829
+ * @param {string} channelId - The unique identifier of the channel to be rung.
1830
+ * @return {Promise<void>} A promise that resolves when the operation completes successfully.
1831
+ */
1460
1832
  async ringChannel(channelId) {
1461
1833
  await this.baseClient.post(`/channels/${channelId}/ring`);
1462
1834
  }
1835
+ /**
1836
+ * Stops the ring channel for the specified channel ID.
1837
+ *
1838
+ * This method sends a DELETE request to the server to stop the ring action
1839
+ * associated with the provided channel ID.
1840
+ *
1841
+ * @param {string} channelId - The unique identifier of the channel for which the ring action should be stopped.
1842
+ * @return {Promise<void>} A promise that resolves when the ring channel is successfully stopped.
1843
+ */
1463
1844
  async stopRingChannel(channelId) {
1464
1845
  await this.baseClient.delete(`/channels/${channelId}/ring`);
1465
1846
  }
1847
+ /**
1848
+ * Sends DTMF (Dual-Tone Multi-Frequency) signals to a specified channel.
1849
+ *
1850
+ * @param {string} channelId - The ID of the channel to which the DTMF signals should be sent.
1851
+ * @param {string} dtmf - The DTMF tones to be sent, represented as a string. Each character corresponds to a specific tone.
1852
+ * @param {Object} [options] - Optional configuration for the DTMF signal timing.
1853
+ * @param {number} [options.before] - Time in milliseconds to wait before sending the first DTMF tone.
1854
+ * @param {number} [options.between] - Time in milliseconds to wait between sending successive DTMF tones.
1855
+ * @param {number} [options.duration] - Duration in milliseconds for each DTMF tone.
1856
+ * @param {number} [options.after] - Time in milliseconds to wait after sending the last DTMF tone.
1857
+ * @return {Promise<void>} A promise that resolves when the DTMF signals are successfully sent.
1858
+ */
1466
1859
  async sendDTMF(channelId, dtmf, options) {
1467
1860
  const queryParams = toQueryParams2({ dtmf, ...options });
1468
1861
  await this.baseClient.post(
1469
1862
  `/channels/${channelId}/dtmf?${queryParams}`
1470
1863
  );
1471
1864
  }
1865
+ /**
1866
+ * Mutes a specified channel in the given direction.
1867
+ *
1868
+ * @param {string} channelId - The unique identifier of the channel to be muted.
1869
+ * @param {"both" | "in" | "out"} [direction="both"] - The direction for muting, can be "both", "in", or "out". Default is "both".
1870
+ * @return {Promise<void>} A promise that resolves when the channel is successfully muted.
1871
+ */
1472
1872
  async muteChannel(channelId, direction = "both") {
1473
1873
  await this.baseClient.post(
1474
1874
  `/channels/${channelId}/mute?direction=${direction}`
1475
1875
  );
1476
1876
  }
1877
+ /**
1878
+ * Unmutes a previously muted channel, allowing communication in the specified direction(s).
1879
+ *
1880
+ * @param {string} channelId - The unique identifier of the channel to be unmuted.
1881
+ * @param {"both" | "in" | "out"} [direction="both"] - The direction of communication to unmute. Valid options are "both", "in" (incoming messages), or "out" (outgoing messages). Defaults to "both".
1882
+ * @return {Promise<void>} A promise that resolves when the channel is successfully unmuted.
1883
+ */
1477
1884
  async unmuteChannel(channelId, direction = "both") {
1478
1885
  await this.baseClient.delete(
1479
1886
  `/channels/${channelId}/mute?direction=${direction}`
1480
1887
  );
1481
1888
  }
1889
+ /**
1890
+ * Places a specific channel on hold by sending a POST request to the server.
1891
+ *
1892
+ * @param {string} channelId - The unique identifier of the channel to be placed on hold.
1893
+ * @return {Promise<void>} A promise that resolves when the channel hold operation is completed.
1894
+ */
1482
1895
  async holdChannel(channelId) {
1483
1896
  await this.baseClient.post(`/channels/${channelId}/hold`);
1484
1897
  }
1898
+ /**
1899
+ * Removes the hold status from a specific channel by its ID.
1900
+ *
1901
+ * @param {string} channelId - The unique identifier of the channel to unhold.
1902
+ * @return {Promise<void>} A promise that resolves when the channel hold is successfully removed.
1903
+ */
1485
1904
  async unholdChannel(channelId) {
1486
1905
  await this.baseClient.delete(`/channels/${channelId}/hold`);
1487
1906
  }
1907
+ /**
1908
+ * Creates a new communication channel with the specified configuration.
1909
+ *
1910
+ * @param {OriginateRequest} data - The configuration data required to create the channel, including relevant details such as endpoint and channel variables.
1911
+ * @return {Promise<Channel>} A promise that resolves with the details of the created channel.
1912
+ */
1488
1913
  async createChannel(data) {
1489
1914
  return this.baseClient.post("/channels/create", data);
1490
1915
  }
1916
+ /**
1917
+ * Initiates a new channel with the specified channel ID and originates a call using the provided data.
1918
+ *
1919
+ * @param {string} channelId - The unique identifier of the channel to be created.
1920
+ * @param {OriginateRequest} data - The data required to originate the call, including details such as endpoint and caller information.
1921
+ * @return {Promise<Channel>} A promise that resolves to the created Channel object.
1922
+ */
1491
1923
  async originateWithId(channelId, data) {
1492
1924
  return this.baseClient.post(`/channels/${channelId}`, data);
1493
1925
  }
@@ -1541,93 +1973,187 @@ var Endpoints = class {
1541
1973
 
1542
1974
  // src/ari-client/resources/playbacks.ts
1543
1975
  var import_events2 = require("events");
1976
+ var import_axios3 = require("axios");
1977
+ var getErrorMessage2 = (error) => {
1978
+ if ((0, import_axios3.isAxiosError)(error)) {
1979
+ return error.response?.data?.message || error.message || "An axios error occurred";
1980
+ }
1981
+ if (error instanceof Error) {
1982
+ return error.message;
1983
+ }
1984
+ return "An unknown error occurred";
1985
+ };
1544
1986
  var PlaybackInstance = class {
1987
+ /**
1988
+ * Creates a new PlaybackInstance.
1989
+ *
1990
+ * @param {AriClient} client - ARI client for communication
1991
+ * @param {BaseClient} baseClient - Base client for HTTP requests
1992
+ * @param {string} [playbackId] - Optional playback ID, generates timestamp-based ID if not provided
1993
+ */
1545
1994
  constructor(client, baseClient, playbackId = `playback-${Date.now()}`) {
1546
1995
  this.client = client;
1547
1996
  this.baseClient = baseClient;
1548
1997
  this.playbackId = playbackId;
1549
1998
  this.id = playbackId;
1999
+ console.log(`PlaybackInstance initialized with ID: ${this.id}`);
1550
2000
  }
1551
2001
  eventEmitter = new import_events2.EventEmitter();
1552
2002
  playbackData = null;
1553
2003
  id;
1554
2004
  /**
1555
- * Registra um listener para eventos específicos deste playback.
2005
+ * Registers an event listener for a specific WebSocket event type.
2006
+ *
2007
+ * @param {T} event - Event type to listen for
2008
+ * @param {Function} listener - Callback function for the event
1556
2009
  */
1557
2010
  on(event, listener) {
2011
+ if (!event) {
2012
+ throw new Error("Event type is required");
2013
+ }
1558
2014
  const wrappedListener = (data) => {
1559
2015
  if ("playback" in data && data.playback?.id === this.id) {
1560
2016
  listener(data);
1561
2017
  }
1562
2018
  };
1563
2019
  this.eventEmitter.on(event, wrappedListener);
2020
+ console.log(`Event listener registered for ${event} on playback ${this.id}`);
1564
2021
  }
1565
2022
  /**
1566
- * Registra um listener único para eventos específicos deste playback.
2023
+ * Registers a one-time event listener for a specific WebSocket event type.
2024
+ *
2025
+ * @param {T} event - Event type to listen for
2026
+ * @param {Function} listener - Callback function for the event
1567
2027
  */
1568
2028
  once(event, listener) {
2029
+ if (!event) {
2030
+ throw new Error("Event type is required");
2031
+ }
1569
2032
  const wrappedListener = (data) => {
1570
2033
  if ("playback" in data && data.playback?.id === this.id) {
1571
2034
  listener(data);
1572
2035
  }
1573
2036
  };
1574
2037
  this.eventEmitter.once(event, wrappedListener);
2038
+ console.log(`One-time event listener registered for ${event} on playback ${this.id}`);
1575
2039
  }
1576
2040
  /**
1577
- * Remove um listener para eventos específicos deste playback.
2041
+ * Removes event listener(s) for a specific WebSocket event type.
2042
+ *
2043
+ * @param {T} event - Event type to remove listener(s) for
2044
+ * @param {Function} [listener] - Optional specific listener to remove
1578
2045
  */
1579
2046
  off(event, listener) {
2047
+ if (!event) {
2048
+ throw new Error("Event type is required");
2049
+ }
1580
2050
  if (listener) {
1581
2051
  this.eventEmitter.off(event, listener);
2052
+ console.log(`Specific listener removed for ${event} on playback ${this.id}`);
1582
2053
  } else {
1583
2054
  this.eventEmitter.removeAllListeners(event);
2055
+ console.log(`All listeners removed for ${event} on playback ${this.id}`);
1584
2056
  }
1585
2057
  }
1586
2058
  /**
1587
- * Emite eventos internamente para o playback.
2059
+ * Emits a WebSocket event if it matches the current playback instance.
2060
+ *
2061
+ * @param {WebSocketEvent} event - Event to emit
1588
2062
  */
1589
2063
  emitEvent(event) {
2064
+ if (!event) {
2065
+ console.warn("Received invalid event");
2066
+ return;
2067
+ }
1590
2068
  if ("playback" in event && event.playback?.id === this.id) {
1591
2069
  this.eventEmitter.emit(event.type, event);
2070
+ console.log(`Event ${event.type} emitted for playback ${this.id}`);
1592
2071
  }
1593
2072
  }
1594
2073
  /**
1595
- * Obtém os detalhes do playback.
2074
+ * Retrieves current playback data.
2075
+ *
2076
+ * @returns {Promise<Playback>} Current playback data
2077
+ * @throws {Error} If playback is not properly initialized
1596
2078
  */
1597
2079
  async get() {
1598
2080
  if (!this.id) {
1599
- throw new Error("Nenhum playback associado a esta inst\xE2ncia.");
2081
+ throw new Error("No playback associated with this instance");
2082
+ }
2083
+ try {
2084
+ this.playbackData = await this.baseClient.get(
2085
+ `/playbacks/${this.id}`
2086
+ );
2087
+ console.log(`Retrieved playback data for ${this.id}`);
2088
+ return this.playbackData;
2089
+ } catch (error) {
2090
+ const message = getErrorMessage2(error);
2091
+ console.error(`Error retrieving playback data for ${this.id}:`, message);
2092
+ throw new Error(`Failed to get playback data: ${message}`);
1600
2093
  }
1601
- this.playbackData = await this.baseClient.get(
1602
- `/playbacks/${this.id}`
1603
- );
1604
- return this.playbackData;
1605
2094
  }
1606
2095
  /**
1607
- * Controla o playback.
2096
+ * Controls playback with specified operation.
2097
+ *
2098
+ * @param {"pause" | "unpause" | "reverse" | "forward"} operation - Control operation to perform
2099
+ * @throws {Error} If playback is not properly initialized or operation fails
1608
2100
  */
1609
2101
  async control(operation) {
1610
2102
  if (!this.id) {
1611
- throw new Error("Nenhum playback associado para controlar.");
2103
+ throw new Error("No playback associated with this instance");
2104
+ }
2105
+ try {
2106
+ await this.baseClient.post(
2107
+ `/playbacks/${this.id}/control?operation=${operation}`
2108
+ );
2109
+ console.log(`Operation ${operation} executed successfully on playback ${this.id}`);
2110
+ } catch (error) {
2111
+ const message = getErrorMessage2(error);
2112
+ console.error(`Error controlling playback ${this.id}:`, message);
2113
+ throw new Error(`Failed to control playback: ${message}`);
1612
2114
  }
1613
- await this.baseClient.post(
1614
- `/playbacks/${this.id}/control?operation=${operation}`
1615
- );
1616
2115
  }
1617
2116
  /**
1618
- * Encerra o playback.
2117
+ * Stops the current playback.
2118
+ *
2119
+ * @throws {Error} If playback is not properly initialized or stop operation fails
1619
2120
  */
1620
2121
  async stop() {
1621
2122
  if (!this.id) {
1622
- throw new Error("Nenhum playback associado para encerrar.");
2123
+ throw new Error("No playback associated with this instance");
2124
+ }
2125
+ try {
2126
+ await this.baseClient.delete(`/playbacks/${this.id}`);
2127
+ console.log(`Playback ${this.id} stopped successfully`);
2128
+ } catch (error) {
2129
+ const message = getErrorMessage2(error);
2130
+ console.error(`Error stopping playback ${this.id}:`, message);
2131
+ throw new Error(`Failed to stop playback: ${message}`);
1623
2132
  }
1624
- await this.baseClient.delete(`/playbacks/${this.id}`);
1625
2133
  }
1626
2134
  /**
1627
- * Remove todos os listeners para este playback.
2135
+ * Removes all event listeners from this playback instance.
1628
2136
  */
1629
2137
  removeAllListeners() {
1630
2138
  this.eventEmitter.removeAllListeners();
2139
+ console.log(`All listeners removed from playback ${this.id}`);
2140
+ }
2141
+ /**
2142
+ * Checks if the playback instance has any listeners for a specific event.
2143
+ *
2144
+ * @param {string} event - Event type to check
2145
+ * @returns {boolean} True if there are listeners for the event
2146
+ */
2147
+ hasListeners(event) {
2148
+ return this.eventEmitter.listenerCount(event) > 0;
2149
+ }
2150
+ /**
2151
+ * Gets the current playback data without making an API call.
2152
+ *
2153
+ * @returns {Playback | null} Current playback data or null if not available
2154
+ */
2155
+ getCurrentData() {
2156
+ return this.playbackData;
1631
2157
  }
1632
2158
  };
1633
2159
  var Playbacks = class {
@@ -1637,61 +2163,141 @@ var Playbacks = class {
1637
2163
  }
1638
2164
  playbackInstances = /* @__PURE__ */ new Map();
1639
2165
  /**
1640
- * Gerencia instâncias de playback.
2166
+ * Gets or creates a playback instance
2167
+ * @param {Object} params - Parameters for getting/creating a playback instance
2168
+ * @param {string} [params.id] - Optional ID of an existing playback
2169
+ * @returns {PlaybackInstance} The requested or new playback instance
1641
2170
  */
1642
2171
  Playback({ id }) {
1643
- if (!id) {
1644
- const instance = new PlaybackInstance(this.client, this.baseClient);
1645
- this.playbackInstances.set(instance.id, instance);
1646
- return instance;
1647
- }
1648
- if (!this.playbackInstances.has(id)) {
1649
- const instance = new PlaybackInstance(this.client, this.baseClient, id);
1650
- this.playbackInstances.set(id, instance);
1651
- return instance;
2172
+ try {
2173
+ if (!id) {
2174
+ const instance = new PlaybackInstance(this.client, this.baseClient);
2175
+ this.playbackInstances.set(instance.id, instance);
2176
+ console.log(`New playback instance created with ID: ${instance.id}`);
2177
+ return instance;
2178
+ }
2179
+ if (!this.playbackInstances.has(id)) {
2180
+ const instance = new PlaybackInstance(this.client, this.baseClient, id);
2181
+ this.playbackInstances.set(id, instance);
2182
+ console.log(`New playback instance created with provided ID: ${id}`);
2183
+ return instance;
2184
+ }
2185
+ console.log(`Returning existing playback instance: ${id}`);
2186
+ return this.playbackInstances.get(id);
2187
+ } catch (error) {
2188
+ const message = getErrorMessage2(error);
2189
+ console.error(`Error creating/retrieving playback instance:`, message);
2190
+ throw new Error(`Failed to manage playback instance: ${message}`);
1652
2191
  }
1653
- return this.playbackInstances.get(id);
1654
2192
  }
1655
2193
  /**
1656
- * Remove uma instância de playback.
2194
+ * Removes a playback instance and cleans up its resources
2195
+ * @param {string} playbackId - ID of the playback instance to remove
2196
+ * @throws {Error} If the playback instance doesn't exist
1657
2197
  */
1658
2198
  removePlaybackInstance(playbackId) {
2199
+ if (!playbackId) {
2200
+ throw new Error("Playback ID is required");
2201
+ }
1659
2202
  if (this.playbackInstances.has(playbackId)) {
1660
2203
  const instance = this.playbackInstances.get(playbackId);
1661
2204
  instance?.removeAllListeners();
1662
2205
  this.playbackInstances.delete(playbackId);
2206
+ console.log(`Playback instance removed: ${playbackId}`);
2207
+ } else {
2208
+ console.warn(`Attempt to remove non-existent instance: ${playbackId}`);
1663
2209
  }
1664
2210
  }
1665
2211
  /**
1666
- * Propaga eventos do WebSocket para o playback correspondente.
2212
+ * Propagates WebSocket events to the corresponding playback instance
2213
+ * @param {WebSocketEvent} event - The WebSocket event to propagate
1667
2214
  */
1668
2215
  propagateEventToPlayback(event) {
2216
+ if (!event) {
2217
+ console.warn("Invalid WebSocket event received");
2218
+ return;
2219
+ }
1669
2220
  if ("playback" in event && event.playback?.id) {
1670
2221
  const instance = this.playbackInstances.get(event.playback.id);
1671
2222
  if (instance) {
1672
2223
  instance.emitEvent(event);
2224
+ console.log(`Event propagated to playback ${event.playback.id}: ${event.type}`);
2225
+ } else {
2226
+ console.warn(`No instance found for playback ${event.playback.id}`);
1673
2227
  }
1674
2228
  }
1675
2229
  }
1676
2230
  /**
1677
- * Obtém detalhes de um playback específico.
2231
+ * Retrieves details of a specific playback
2232
+ * @param {string} playbackId - ID of the playback to get details for
2233
+ * @returns {Promise<Playback>} Promise resolving to playback details
2234
+ * @throws {Error} If the playback ID is invalid or the request fails
1678
2235
  */
1679
2236
  async getDetails(playbackId) {
1680
- return this.baseClient.get(`/playbacks/${playbackId}`);
2237
+ if (!playbackId) {
2238
+ throw new Error("Playback ID is required");
2239
+ }
2240
+ try {
2241
+ return await this.baseClient.get(`/playbacks/${playbackId}`);
2242
+ } catch (error) {
2243
+ const message = getErrorMessage2(error);
2244
+ console.error(`Error getting playback details ${playbackId}:`, message);
2245
+ throw new Error(`Failed to get playback details: ${message}`);
2246
+ }
1681
2247
  }
1682
2248
  /**
1683
- * Controla um playback específico.
2249
+ * Controls a specific playback instance
2250
+ * @param {string} playbackId - ID of the playback to control
2251
+ * @param {"pause" | "unpause" | "reverse" | "forward"} operation - Operation to perform
2252
+ * @throws {Error} If the playback ID is invalid or the operation fails
1684
2253
  */
1685
2254
  async control(playbackId, operation) {
1686
- const playback = this.Playback({ id: playbackId });
1687
- await playback.control(operation);
2255
+ if (!playbackId) {
2256
+ throw new Error("Playback ID is required");
2257
+ }
2258
+ try {
2259
+ const playback = this.Playback({ id: playbackId });
2260
+ await playback.control(operation);
2261
+ console.log(`Operation ${operation} executed on playback ${playbackId}`);
2262
+ } catch (error) {
2263
+ const message = getErrorMessage2(error);
2264
+ console.error(`Error controlling playback ${playbackId}:`, message);
2265
+ throw new Error(`Failed to control playback: ${message}`);
2266
+ }
1688
2267
  }
1689
2268
  /**
1690
- * Encerra um playback específico.
2269
+ * Stops a specific playback instance
2270
+ * @param {string} playbackId - ID of the playback to stop
2271
+ * @throws {Error} If the playback ID is invalid or the stop operation fails
1691
2272
  */
1692
2273
  async stop(playbackId) {
1693
- const playback = this.Playback({ id: playbackId });
1694
- await playback.stop();
2274
+ if (!playbackId) {
2275
+ throw new Error("Playback ID is required");
2276
+ }
2277
+ try {
2278
+ const playback = this.Playback({ id: playbackId });
2279
+ await playback.stop();
2280
+ console.log(`Playback ${playbackId} stopped`);
2281
+ } catch (error) {
2282
+ const message = getErrorMessage2(error);
2283
+ console.error(`Error stopping playback ${playbackId}:`, message);
2284
+ throw new Error(`Failed to stop playback: ${message}`);
2285
+ }
2286
+ }
2287
+ /**
2288
+ * Gets the count of active playback instances
2289
+ * @returns {number} Number of active playback instances
2290
+ */
2291
+ getInstanceCount() {
2292
+ return this.playbackInstances.size;
2293
+ }
2294
+ /**
2295
+ * Checks if a playback instance exists
2296
+ * @param {string} playbackId - ID of the playback to check
2297
+ * @returns {boolean} True if the playback instance exists
2298
+ */
2299
+ hasInstance(playbackId) {
2300
+ return this.playbackInstances.has(playbackId);
1695
2301
  }
1696
2302
  };
1697
2303
 
@@ -1730,40 +2336,51 @@ var Sounds = class {
1730
2336
  var import_events3 = require("events");
1731
2337
  var import_exponential_backoff = __toESM(require_backoff(), 1);
1732
2338
  var import_ws = __toESM(require("ws"), 1);
2339
+ var DEFAULT_MAX_RECONNECT_ATTEMPTS = 10;
2340
+ var DEFAULT_STARTING_DELAY = 500;
2341
+ var DEFAULT_MAX_DELAY = 1e4;
1733
2342
  var WebSocketClient = class extends import_events3.EventEmitter {
2343
+ /**
2344
+ * Creates a new WebSocket client instance.
2345
+ *
2346
+ * @param {BaseClient} baseClient - The base client containing connection details
2347
+ * @param {string[]} apps - List of applications to connect to
2348
+ * @param {WebSocketEventType[]} [subscribedEvents] - Optional list of events to subscribe to
2349
+ * @param {AriClient} [ariClient] - Optional ARI client for handling channel and playback events
2350
+ */
1734
2351
  constructor(baseClient, apps, subscribedEvents, ariClient) {
1735
2352
  super();
1736
2353
  this.baseClient = baseClient;
1737
2354
  this.apps = apps;
1738
2355
  this.subscribedEvents = subscribedEvents;
1739
2356
  this.ariClient = ariClient;
2357
+ if (!apps.length) {
2358
+ throw new Error("At least one application name is required");
2359
+ }
1740
2360
  }
1741
2361
  ws;
1742
2362
  isReconnecting = false;
1743
- maxReconnectAttempts = 10;
2363
+ maxReconnectAttempts = DEFAULT_MAX_RECONNECT_ATTEMPTS;
1744
2364
  backOffOptions = {
1745
- numOfAttempts: 10,
1746
- // Máximo de tentativas de reconexão
1747
- startingDelay: 500,
1748
- // Início com 500ms de atraso
1749
- maxDelay: 1e4,
1750
- // Limite máximo de atraso de 10s
2365
+ numOfAttempts: DEFAULT_MAX_RECONNECT_ATTEMPTS,
2366
+ startingDelay: DEFAULT_STARTING_DELAY,
2367
+ maxDelay: DEFAULT_MAX_DELAY,
1751
2368
  timeMultiple: 2,
1752
- // Atraso aumenta exponencialmente
1753
2369
  jitter: "full",
1754
- // Randomização para evitar colisões
1755
2370
  delayFirstAttempt: false,
1756
- // Não atrase a primeira tentativa
1757
2371
  retry: (error, attemptNumber) => {
1758
2372
  console.warn(
1759
- `Tentativa #${attemptNumber} falhou:`,
1760
- error.message || error
2373
+ `Connection attempt #${attemptNumber} failed:`,
2374
+ error.message || "Unknown error"
1761
2375
  );
1762
- return true;
2376
+ return attemptNumber < this.maxReconnectAttempts;
1763
2377
  }
1764
2378
  };
1765
2379
  /**
1766
- * Conecta ao WebSocket.
2380
+ * Establishes a WebSocket connection.
2381
+ *
2382
+ * @returns {Promise<void>} Resolves when connection is established
2383
+ * @throws {Error} If connection fails
1767
2384
  */
1768
2385
  async connect() {
1769
2386
  const { baseUrl, username, password } = this.baseClient.getCredentials();
@@ -1771,7 +2388,7 @@ var WebSocketClient = class extends import_events3.EventEmitter {
1771
2388
  const normalizedHost = baseUrl.replace(/^https?:\/\//, "").replace(/\/ari$/, "");
1772
2389
  const queryParams = new URLSearchParams();
1773
2390
  queryParams.append("app", this.apps.join(","));
1774
- if (this.subscribedEvents && this.subscribedEvents.length > 0) {
2391
+ if (this.subscribedEvents?.length) {
1775
2392
  this.subscribedEvents.forEach(
1776
2393
  (event) => queryParams.append("event", event)
1777
2394
  );
@@ -1779,48 +2396,57 @@ var WebSocketClient = class extends import_events3.EventEmitter {
1779
2396
  queryParams.append("subscribeAll", "true");
1780
2397
  }
1781
2398
  const wsUrl = `${protocol}://${encodeURIComponent(username)}:${encodeURIComponent(password)}@${normalizedHost}/ari/events?${queryParams.toString()}`;
1782
- console.log("Conectando ao WebSocket em:", wsUrl);
2399
+ console.log("Connecting to WebSocket...");
1783
2400
  return this.initializeWebSocket(wsUrl);
1784
2401
  }
1785
2402
  /**
1786
- * Inicializa a conexão WebSocket com lógica de reconexão.
2403
+ * Initializes WebSocket connection with reconnection logic.
2404
+ *
2405
+ * @param {string} wsUrl - The WebSocket URL to connect to
2406
+ * @returns {Promise<void>} Resolves when connection is established
1787
2407
  */
1788
2408
  async initializeWebSocket(wsUrl) {
1789
2409
  return (0, import_exponential_backoff.backOff)(async () => {
1790
2410
  return new Promise((resolve, reject) => {
1791
- this.ws = new import_ws.default(wsUrl);
1792
- this.ws.on("open", () => {
1793
- console.log("WebSocket conectado com sucesso.");
1794
- this.isReconnecting = false;
1795
- this.emit("connected");
1796
- resolve();
1797
- });
1798
- this.ws.on("message", (data) => this.handleMessage(data.toString()));
1799
- this.ws.on("close", (code) => {
1800
- console.warn(
1801
- `WebSocket desconectado com c\xF3digo ${code}. Tentando reconectar...`
1802
- );
1803
- if (!this.isReconnecting) {
1804
- this.reconnect(wsUrl);
1805
- }
1806
- });
1807
- this.ws.on("error", (err) => {
1808
- console.error("Erro no WebSocket:", err.message);
1809
- if (!this.isReconnecting) {
1810
- this.reconnect(wsUrl);
1811
- }
1812
- reject(err);
1813
- });
2411
+ try {
2412
+ this.ws = new import_ws.default(wsUrl);
2413
+ this.ws.on("open", () => {
2414
+ console.log("WebSocket connection established successfully");
2415
+ this.isReconnecting = false;
2416
+ this.emit("connected");
2417
+ resolve();
2418
+ });
2419
+ this.ws.on("message", (data) => this.handleMessage(data.toString()));
2420
+ this.ws.on("close", (code) => {
2421
+ console.warn(
2422
+ `WebSocket disconnected with code ${code}. Attempting to reconnect...`
2423
+ );
2424
+ if (!this.isReconnecting) {
2425
+ this.reconnect(wsUrl);
2426
+ }
2427
+ });
2428
+ this.ws.on("error", (err) => {
2429
+ console.error("WebSocket error:", err.message);
2430
+ if (!this.isReconnecting) {
2431
+ this.reconnect(wsUrl);
2432
+ }
2433
+ reject(err);
2434
+ });
2435
+ } catch (error) {
2436
+ reject(error);
2437
+ }
1814
2438
  });
1815
2439
  }, this.backOffOptions);
1816
2440
  }
1817
2441
  /**
1818
- * Processa as mensagens recebidas do WebSocket.
2442
+ * Processes incoming WebSocket messages.
2443
+ *
2444
+ * @param {string} rawMessage - The raw message received from WebSocket
1819
2445
  */
1820
2446
  handleMessage(rawMessage) {
1821
2447
  try {
1822
2448
  const event = JSON.parse(rawMessage);
1823
- if (this.subscribedEvents && !this.subscribedEvents.includes(event.type)) {
2449
+ if (this.subscribedEvents?.length && !this.subscribedEvents.includes(event.type)) {
1824
2450
  return;
1825
2451
  }
1826
2452
  if ("channel" in event && event.channel?.id && this.ariClient) {
@@ -1834,40 +2460,77 @@ var WebSocketClient = class extends import_events3.EventEmitter {
1834
2460
  event.instancePlayback = instancePlayback;
1835
2461
  }
1836
2462
  this.emit(event.type, event);
1837
- } catch (err) {
1838
- console.error("Erro ao processar mensagem WebSocket:", err);
1839
- this.emit("error", new Error("Falha ao decodificar mensagem WebSocket."));
2463
+ console.log(`Event processed: ${event.type}`);
2464
+ } catch (error) {
2465
+ console.error("Error processing WebSocket message:", error instanceof Error ? error.message : "Unknown error");
2466
+ this.emit("error", new Error("Failed to decode WebSocket message"));
1840
2467
  }
1841
2468
  }
1842
2469
  /**
1843
- * Tenta reconectar ao WebSocket.
2470
+ * Attempts to reconnect to the WebSocket.
2471
+ *
2472
+ * @param {string} wsUrl - The WebSocket URL to reconnect to
1844
2473
  */
1845
2474
  reconnect(wsUrl) {
1846
2475
  this.isReconnecting = true;
1847
- console.log("Iniciando tentativa de reconex\xE3o...");
2476
+ console.log("Initiating reconnection attempt...");
1848
2477
  this.removeAllListeners();
1849
- (0, import_exponential_backoff.backOff)(() => this.initializeWebSocket(wsUrl), this.backOffOptions).catch(
1850
- (err) => {
1851
- console.error(
1852
- "Falha ao reconectar ap\xF3s v\xE1rias tentativas:",
1853
- err.message || err
1854
- );
1855
- }
1856
- );
2478
+ (0, import_exponential_backoff.backOff)(() => this.initializeWebSocket(wsUrl), this.backOffOptions).catch((error) => {
2479
+ console.error(
2480
+ "Failed to reconnect after multiple attempts:",
2481
+ error instanceof Error ? error.message : "Unknown error"
2482
+ );
2483
+ this.emit("reconnectFailed", error);
2484
+ });
1857
2485
  }
1858
2486
  /**
1859
- * Fecha o WebSocket manualmente.
2487
+ * Manually closes the WebSocket connection.
1860
2488
  */
1861
2489
  close() {
1862
- this.ws?.close();
1863
- this.ws = void 0;
2490
+ try {
2491
+ if (this.ws) {
2492
+ this.ws.close();
2493
+ this.ws = void 0;
2494
+ console.log("WebSocket connection closed");
2495
+ }
2496
+ } catch (error) {
2497
+ console.error(
2498
+ "Error closing WebSocket:",
2499
+ error instanceof Error ? error.message : "Unknown error"
2500
+ );
2501
+ }
2502
+ }
2503
+ /**
2504
+ * Checks if the WebSocket is currently connected.
2505
+ *
2506
+ * @returns {boolean} True if connected, false otherwise
2507
+ */
2508
+ isConnected() {
2509
+ return this.ws?.readyState === import_ws.default.OPEN;
2510
+ }
2511
+ /**
2512
+ * Gets the current connection state.
2513
+ *
2514
+ * @returns {number} The WebSocket ready state
2515
+ */
2516
+ getState() {
2517
+ return this.ws?.readyState ?? import_ws.default.CLOSED;
1864
2518
  }
1865
2519
  };
1866
2520
 
1867
2521
  // src/ari-client/ariClient.ts
1868
2522
  var AriClient = class {
2523
+ /**
2524
+ * Creates a new instance of the ARI client.
2525
+ *
2526
+ * @param {AriClientConfig} config - Configuration options for the ARI client
2527
+ * @throws {Error} If required configuration parameters are missing
2528
+ */
1869
2529
  constructor(config) {
1870
2530
  this.config = config;
2531
+ if (!config.host || !config.port || !config.username || !config.password) {
2532
+ throw new Error("Missing required configuration parameters");
2533
+ }
1871
2534
  const httpProtocol = config.secure ? "https" : "http";
1872
2535
  const normalizedHost = config.host.replace(/^https?:\/\//, "");
1873
2536
  const baseUrl = `${httpProtocol}://${normalizedHost}:${config.port}/ari`;
@@ -1879,6 +2542,7 @@ var AriClient = class {
1879
2542
  this.sounds = new Sounds(this.baseClient);
1880
2543
  this.asterisk = new Asterisk(this.baseClient);
1881
2544
  this.bridges = new Bridges(this.baseClient);
2545
+ console.log(`ARI Client initialized with base URL: ${baseUrl}`);
1882
2546
  }
1883
2547
  baseClient;
1884
2548
  webSocketClient;
@@ -1890,58 +2554,117 @@ var AriClient = class {
1890
2554
  asterisk;
1891
2555
  bridges;
1892
2556
  /**
1893
- * Inicializa uma conexão WebSocket.
2557
+ * Initializes a WebSocket connection for receiving events.
2558
+ *
2559
+ * @param {string[]} apps - List of application names to subscribe to
2560
+ * @param {WebSocketEventType[]} [subscribedEvents] - Optional list of specific event types to subscribe to
2561
+ * @returns {Promise<void>} Resolves when connection is established
2562
+ * @throws {Error} If connection fails or if WebSocket is already connected
1894
2563
  */
1895
2564
  async connectWebSocket(apps, subscribedEvents) {
2565
+ if (!apps.length) {
2566
+ throw new Error("At least one application name is required");
2567
+ }
1896
2568
  if (this.webSocketClient) {
1897
- console.warn("WebSocket j\xE1 est\xE1 conectado.");
2569
+ console.warn("WebSocket is already connected");
1898
2570
  return;
1899
2571
  }
1900
- this.webSocketClient = new WebSocketClient(
1901
- this.baseClient,
1902
- apps,
1903
- subscribedEvents,
1904
- this
1905
- );
1906
- await this.webSocketClient.connect();
2572
+ try {
2573
+ this.webSocketClient = new WebSocketClient(
2574
+ this.baseClient,
2575
+ apps,
2576
+ subscribedEvents,
2577
+ this
2578
+ );
2579
+ await this.webSocketClient.connect();
2580
+ console.log("WebSocket connection established successfully");
2581
+ } catch (error) {
2582
+ console.error("Failed to establish WebSocket connection:", error);
2583
+ this.webSocketClient = void 0;
2584
+ throw error;
2585
+ }
1907
2586
  }
1908
2587
  /**
1909
- * Adiciona um listener para eventos do WebSocket.
2588
+ * Registers an event listener for WebSocket events.
2589
+ *
2590
+ * @param {T} event - The event type to listen for
2591
+ * @param {Function} listener - Callback function for handling the event
2592
+ * @throws {Error} If WebSocket is not connected
1910
2593
  */
1911
2594
  on(event, listener) {
1912
- this.webSocketClient?.on(event, listener);
2595
+ if (!this.webSocketClient) {
2596
+ throw new Error("WebSocket is not connected");
2597
+ }
2598
+ this.webSocketClient.on(event, listener);
2599
+ console.log(`Event listener registered for ${event}`);
1913
2600
  }
1914
2601
  /**
1915
- * Adiciona um listener único para eventos do WebSocket.
2602
+ * Registers a one-time event listener for WebSocket events.
2603
+ *
2604
+ * @param {T} event - The event type to listen for
2605
+ * @param {Function} listener - Callback function for handling the event
2606
+ * @throws {Error} If WebSocket is not connected
1916
2607
  */
1917
2608
  once(event, listener) {
1918
- this.webSocketClient?.once(event, listener);
2609
+ if (!this.webSocketClient) {
2610
+ throw new Error("WebSocket is not connected");
2611
+ }
2612
+ this.webSocketClient.once(event, listener);
2613
+ console.log(`One-time event listener registered for ${event}`);
1919
2614
  }
1920
2615
  /**
1921
- * Remove um listener para eventos do WebSocket.
2616
+ * Removes an event listener for WebSocket events.
2617
+ *
2618
+ * @param {T} event - The event type to remove listener for
2619
+ * @param {Function} listener - The listener function to remove
1922
2620
  */
1923
2621
  off(event, listener) {
1924
- this.webSocketClient?.off(event, listener);
2622
+ if (!this.webSocketClient) {
2623
+ console.warn("No WebSocket connection to remove listener from");
2624
+ return;
2625
+ }
2626
+ this.webSocketClient.off(event, listener);
2627
+ console.log(`Event listener removed for ${event}`);
1925
2628
  }
1926
2629
  /**
1927
- * Fecha a conexão WebSocket.
2630
+ * Closes the WebSocket connection if one exists.
1928
2631
  */
1929
2632
  closeWebSocket() {
1930
- this.webSocketClient?.close();
2633
+ if (!this.webSocketClient) {
2634
+ console.warn("No WebSocket connection to close");
2635
+ return;
2636
+ }
2637
+ this.webSocketClient.close();
1931
2638
  this.webSocketClient = void 0;
2639
+ console.log("WebSocket connection closed");
1932
2640
  }
1933
2641
  /**
1934
- * Inicializa uma nova instância de `ChannelInstance` para manipular canais localmente.
2642
+ * Creates or retrieves a Channel instance.
2643
+ *
2644
+ * @param {string} [channelId] - Optional ID of an existing channel
2645
+ * @returns {ChannelInstance} A new or existing channel instance
1935
2646
  */
1936
2647
  Channel(channelId) {
1937
2648
  return this.channels.Channel({ id: channelId });
1938
2649
  }
1939
2650
  /**
1940
- * Inicializa uma nova instância de `PlaybackInstance` para manipular playbacks.
2651
+ * Creates or retrieves a Playback instance.
2652
+ *
2653
+ * @param {string} [playbackId] - Optional ID of an existing playback
2654
+ * @param {string} [_app] - Optional application name (deprecated)
2655
+ * @returns {PlaybackInstance} A new or existing playback instance
1941
2656
  */
1942
2657
  Playback(playbackId, _app) {
1943
2658
  return this.playbacks.Playback({ id: playbackId });
1944
2659
  }
2660
+ /**
2661
+ * Gets the current WebSocket connection status.
2662
+ *
2663
+ * @returns {boolean} True if WebSocket is connected, false otherwise
2664
+ */
2665
+ isWebSocketConnected() {
2666
+ return !!this.webSocketClient;
2667
+ }
1945
2668
  };
1946
2669
  // Annotate the CommonJS export names for ESM import in node:
1947
2670
  0 && (module.exports = {