@ipcom/asterisk-ari 0.0.138 → 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
 
@@ -803,6 +862,9 @@ var Asterisk = class {
803
862
  constructor(client) {
804
863
  this.client = client;
805
864
  }
865
+ async ping() {
866
+ return this.client.get("/asterisk/ping");
867
+ }
806
868
  /**
807
869
  * Retrieves information about the Asterisk server.
808
870
  */
@@ -1017,102 +1079,199 @@ function toQueryParams2(options) {
1017
1079
  }
1018
1080
 
1019
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
+ };
1020
1092
  var ChannelInstance = class {
1021
- // ID do canal
1022
- constructor(client, baseClient, channelId = `channel-${Date.now()}`) {
1093
+ constructor(client, baseClient, channelId) {
1023
1094
  this.client = client;
1024
1095
  this.baseClient = baseClient;
1025
- this.channelId = channelId;
1026
1096
  this.id = channelId || `channel-${Date.now()}`;
1097
+ console.log(`Channel instance initialized with ID: ${this.id}`);
1027
1098
  }
1028
1099
  eventEmitter = new import_events.EventEmitter();
1029
1100
  channelData = null;
1030
1101
  id;
1031
1102
  /**
1032
- * Registra um listener para eventos específicos deste canal.
1103
+ * Registers an event listener for specific channel events
1033
1104
  */
1034
1105
  on(event, listener) {
1106
+ if (!event) {
1107
+ throw new Error("Event type is required");
1108
+ }
1035
1109
  const wrappedListener = (data) => {
1036
1110
  if ("channel" in data && data.channel?.id === this.id) {
1037
1111
  listener(data);
1038
1112
  }
1039
1113
  };
1040
1114
  this.eventEmitter.on(event, wrappedListener);
1115
+ console.log(`Event listener registered for ${event} on channel ${this.id}`);
1041
1116
  }
1042
1117
  /**
1043
- * Registra um listener único para eventos específicos deste canal.
1118
+ * Registers a one-time event listener
1044
1119
  */
1045
1120
  once(event, listener) {
1121
+ if (!event) {
1122
+ throw new Error("Event type is required");
1123
+ }
1046
1124
  const wrappedListener = (data) => {
1047
1125
  if ("channel" in data && data.channel?.id === this.id) {
1048
1126
  listener(data);
1049
1127
  }
1050
1128
  };
1051
1129
  this.eventEmitter.once(event, wrappedListener);
1130
+ console.log(`One-time event listener registered for ${event} on channel ${this.id}`);
1052
1131
  }
1053
1132
  /**
1054
- * 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
1055
1140
  */
1056
1141
  off(event, listener) {
1142
+ if (!event) {
1143
+ throw new Error("Event type is required");
1144
+ }
1057
1145
  if (listener) {
1058
1146
  this.eventEmitter.off(event, listener);
1147
+ console.log(`Specific listener removed for ${event} on channel ${this.id}`);
1059
1148
  } else {
1060
- const listeners = this.eventEmitter.listeners(event);
1061
- listeners.forEach((fn) => {
1062
- this.eventEmitter.off(event, fn);
1063
- });
1149
+ this.eventEmitter.removeAllListeners(event);
1150
+ console.log(`All listeners removed for ${event} on channel ${this.id}`);
1064
1151
  }
1065
1152
  }
1066
1153
  /**
1067
- * Obtém a quantidade de listeners registrados para o evento especificado.
1068
- */
1069
- getListenerCount(event) {
1070
- return this.eventEmitter.listenerCount(event);
1071
- }
1072
- /**
1073
- * Emite eventos internamente para o canal.
1074
- * Verifica o ID do canal antes de emitir.
1154
+ * Emits an event if it matches the current channel
1075
1155
  */
1076
1156
  emitEvent(event) {
1157
+ if (!event) {
1158
+ console.warn("Received invalid event");
1159
+ return;
1160
+ }
1077
1161
  if ("channel" in event && event.channel?.id === this.id) {
1078
1162
  this.eventEmitter.emit(event.type, event);
1163
+ console.log(`Event ${event.type} emitted for channel ${this.id}`);
1079
1164
  }
1080
1165
  }
1081
1166
  /**
1082
- * 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.
1083
1171
  */
1084
1172
  removeAllListeners() {
1085
1173
  console.log(`Removendo todos os listeners para o canal ${this.id}`);
1086
1174
  this.eventEmitter.removeAllListeners();
1087
1175
  }
1176
+ /**
1177
+ * Answers the channel
1178
+ */
1088
1179
  async answer() {
1089
- 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
+ }
1090
1188
  }
1091
1189
  /**
1092
- * 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
1093
1195
  */
1094
1196
  async originate(data) {
1095
1197
  if (this.channelData) {
1096
- 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}`);
1097
1208
  }
1098
- const channel = await this.baseClient.post("/channels", data);
1099
- this.channelData = channel;
1100
- return channel;
1101
1209
  }
1102
1210
  /**
1103
- * Obtém os detalhes do canal.
1211
+ * Plays media on the channel
1104
1212
  */
1105
- async getDetails() {
1106
- if (this.channelData) {
1107
- return this.channelData;
1213
+ async play(options, playbackId) {
1214
+ if (!options.media) {
1215
+ throw new Error("Media URL is required");
1108
1216
  }
1109
- if (!this.id) {
1110
- 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}`);
1111
1233
  }
1112
- const details = await this.baseClient.get(`/channels/${this.id}`);
1113
- this.channelData = details;
1114
- return details;
1115
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}`);
1254
+ }
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
+ */
1116
1275
  async getVariable(variable) {
1117
1276
  if (!variable) {
1118
1277
  throw new Error("The 'variable' parameter is required.");
@@ -1122,7 +1281,11 @@ var ChannelInstance = class {
1122
1281
  );
1123
1282
  }
1124
1283
  /**
1125
- * 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.
1126
1289
  */
1127
1290
  async hangup() {
1128
1291
  if (!this.channelData) {
@@ -1135,25 +1298,12 @@ var ChannelInstance = class {
1135
1298
  await this.baseClient.delete(`/channels/${this.channelData.id}`);
1136
1299
  }
1137
1300
  /**
1138
- * Reproduz mídia no canal.
1139
- */
1140
- async play(options, playbackId) {
1141
- if (!this.channelData) {
1142
- console.log("Canal n\xE3o inicializado, buscando detalhes...");
1143
- this.channelData = await this.getDetails();
1144
- }
1145
- const playback = this.client.Playback(playbackId || v4_default());
1146
- if (!this.channelData?.id) {
1147
- throw new Error("N\xE3o foi poss\xEDvel inicializar o canal. ID inv\xE1lido.");
1148
- }
1149
- await this.baseClient.post(
1150
- `/channels/${this.channelData.id}/play/${playback.id}`,
1151
- options
1152
- );
1153
- return playback;
1154
- }
1155
- /**
1156
- * 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.
1157
1307
  */
1158
1308
  async playMedia(media, options) {
1159
1309
  if (!this.channelData) {
@@ -1166,7 +1316,11 @@ var ChannelInstance = class {
1166
1316
  );
1167
1317
  }
1168
1318
  /**
1169
- * 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.
1170
1324
  */
1171
1325
  async stopPlayback(playbackId) {
1172
1326
  if (!this.channelData?.id) {
@@ -1177,7 +1331,11 @@ var ChannelInstance = class {
1177
1331
  );
1178
1332
  }
1179
1333
  /**
1180
- * 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.
1181
1339
  */
1182
1340
  async pausePlayback(playbackId) {
1183
1341
  if (!this.channelData?.id) {
@@ -1188,7 +1346,11 @@ var ChannelInstance = class {
1188
1346
  );
1189
1347
  }
1190
1348
  /**
1191
- * 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.
1192
1354
  */
1193
1355
  async resumePlayback(playbackId) {
1194
1356
  if (!this.channelData?.id) {
@@ -1199,7 +1361,11 @@ var ChannelInstance = class {
1199
1361
  );
1200
1362
  }
1201
1363
  /**
1202
- * 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.
1203
1369
  */
1204
1370
  async rewindPlayback(playbackId, skipMs) {
1205
1371
  if (!this.channelData?.id) {
@@ -1211,7 +1377,12 @@ var ChannelInstance = class {
1211
1377
  );
1212
1378
  }
1213
1379
  /**
1214
- * 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.
1215
1386
  */
1216
1387
  async fastForwardPlayback(playbackId, skipMs) {
1217
1388
  if (!this.channelData?.id) {
@@ -1223,7 +1394,11 @@ var ChannelInstance = class {
1223
1394
  );
1224
1395
  }
1225
1396
  /**
1226
- * 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.
1227
1402
  */
1228
1403
  async muteChannel(direction = "both") {
1229
1404
  if (!this.channelData?.id) {
@@ -1234,7 +1409,12 @@ var ChannelInstance = class {
1234
1409
  );
1235
1410
  }
1236
1411
  /**
1237
- * 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.
1238
1418
  */
1239
1419
  async unmuteChannel(direction = "both") {
1240
1420
  if (!this.channelData?.id) {
@@ -1245,7 +1425,10 @@ var ChannelInstance = class {
1245
1425
  );
1246
1426
  }
1247
1427
  /**
1248
- * 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.
1249
1432
  */
1250
1433
  async holdChannel() {
1251
1434
  if (!this.channelData?.id) {
@@ -1254,7 +1437,12 @@ var ChannelInstance = class {
1254
1437
  await this.baseClient.post(`/channels/${this.channelData.id}/hold`);
1255
1438
  }
1256
1439
  /**
1257
- * 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.
1258
1446
  */
1259
1447
  async unholdChannel() {
1260
1448
  if (!this.channelData?.id) {
@@ -1269,73 +1457,125 @@ var Channels = class {
1269
1457
  this.client = client;
1270
1458
  }
1271
1459
  channelInstances = /* @__PURE__ */ new Map();
1460
+ /**
1461
+ * Creates or retrieves a ChannelInstance based on the provided id.
1462
+ */
1272
1463
  Channel({ id }) {
1273
- if (!id) {
1274
- const instance = new ChannelInstance(this.client, this.baseClient);
1275
- this.channelInstances.set(instance.id, instance);
1276
- return instance;
1277
- }
1278
- if (!this.channelInstances.has(id)) {
1279
- const instance = new ChannelInstance(this.client, this.baseClient, id);
1280
- this.channelInstances.set(id, instance);
1281
- 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}`);
1282
1483
  }
1283
- return this.channelInstances.get(id);
1284
1484
  }
1285
1485
  /**
1286
- * Remove uma instância de canal.
1486
+ * Removes a channel instance from the collection.
1287
1487
  */
1288
1488
  removeChannelInstance(channelId) {
1489
+ if (!channelId) {
1490
+ throw new Error("Channel ID is required");
1491
+ }
1289
1492
  if (this.channelInstances.has(channelId)) {
1290
1493
  const instance = this.channelInstances.get(channelId);
1291
1494
  instance?.removeAllListeners();
1292
1495
  this.channelInstances.delete(channelId);
1293
- console.log(`Inst\xE2ncia do canal ${channelId} removida.`);
1496
+ console.log(`Channel instance removed: ${channelId}`);
1294
1497
  } else {
1295
- console.warn(
1296
- `Tentativa de remover uma inst\xE2ncia inexistente: ${channelId}`
1297
- );
1498
+ console.warn(`Attempt to remove non-existent instance: ${channelId}`);
1298
1499
  }
1299
1500
  }
1300
1501
  /**
1301
- * Propaga eventos do WebSocket para o canal correspondente.
1502
+ * Propagates a WebSocket event to a specific channel.
1302
1503
  */
1303
1504
  propagateEventToChannel(event) {
1505
+ if (!event) {
1506
+ console.warn("Invalid WebSocket event received");
1507
+ return;
1508
+ }
1304
1509
  if ("channel" in event && event.channel?.id) {
1305
1510
  const instance = this.channelInstances.get(event.channel.id);
1306
1511
  if (instance) {
1307
1512
  instance.emitEvent(event);
1513
+ console.log(`Event propagated to channel ${event.channel.id}: ${event.type}`);
1308
1514
  } else {
1309
- console.warn(
1310
- `Nenhuma inst\xE2ncia encontrada para o canal ${event.channel.id}`
1311
- );
1515
+ console.warn(`No instance found for channel ${event.channel.id}`);
1312
1516
  }
1313
1517
  }
1314
1518
  }
1315
1519
  /**
1316
- * Origina um canal físico diretamente, sem uma instância de `ChannelInstance`.
1520
+ * Initiates a new channel.
1317
1521
  */
1318
1522
  async originate(data) {
1319
- 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
+ }
1320
1535
  }
1321
1536
  /**
1322
- * Obtém detalhes de um canal específico.
1537
+ * Lists all active channels.
1323
1538
  */
1324
- async getDetails(channelId) {
1325
- 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
+ }
1326
1552
  }
1327
1553
  /**
1328
- * Lista todos os canais ativos.
1554
+ * Gets the count of active channel instances.
1329
1555
  */
1330
- async list() {
1331
- const channels = await this.baseClient.get("/channels");
1332
- if (!Array.isArray(channels)) {
1333
- throw new Error("Resposta da API /channels n\xE3o \xE9 um array.");
1334
- }
1335
- return channels;
1556
+ getInstanceCount() {
1557
+ return this.channelInstances.size;
1558
+ }
1559
+ /**
1560
+ * Checks if a channel instance exists.
1561
+ */
1562
+ hasInstance(channelId) {
1563
+ return this.channelInstances.has(channelId);
1336
1564
  }
1337
1565
  /**
1338
- * Encerra um canal específico.
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.
1339
1579
  */
1340
1580
  async hangup(channelId, options) {
1341
1581
  const queryParams = new URLSearchParams({
@@ -1347,7 +1587,11 @@ var Channels = class {
1347
1587
  );
1348
1588
  }
1349
1589
  /**
1350
- * 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.
1351
1595
  */
1352
1596
  async snoopChannel(channelId, options) {
1353
1597
  const queryParams = toQueryParams2(options);
@@ -1355,23 +1599,56 @@ var Channels = class {
1355
1599
  `/channels/${channelId}/snoop?${queryParams}`
1356
1600
  );
1357
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
+ */
1358
1608
  async startSilence(channelId) {
1359
1609
  return this.baseClient.post(`/channels/${channelId}/silence`);
1360
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
+ */
1361
1617
  async stopSilence(channelId) {
1362
1618
  return this.baseClient.delete(`/channels/${channelId}/silence`);
1363
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
+ */
1364
1626
  async getRTPStatistics(channelId) {
1365
1627
  return this.baseClient.get(
1366
1628
  `/channels/${channelId}/rtp_statistics`
1367
1629
  );
1368
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
+ */
1369
1637
  async createExternalMedia(options) {
1370
1638
  const queryParams = toQueryParams2(options);
1371
1639
  return this.baseClient.post(
1372
1640
  `/channels/externalMedia?${queryParams}`
1373
1641
  );
1374
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
+ */
1375
1652
  async playWithId(channelId, playbackId, media, options) {
1376
1653
  const queryParams = options ? `?${toQueryParams2(options)}` : "";
1377
1654
  return this.baseClient.post(
@@ -1379,18 +1656,41 @@ var Channels = class {
1379
1656
  { media }
1380
1657
  );
1381
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
+ */
1382
1667
  async snoopChannelWithId(channelId, snoopId, options) {
1383
1668
  const queryParams = toQueryParams2(options);
1384
1669
  return this.baseClient.post(
1385
1670
  `/channels/${channelId}/snoop/${snoopId}?${queryParams}`
1386
1671
  );
1387
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
+ */
1388
1680
  async startMohWithClass(channelId, mohClass) {
1389
1681
  const queryParams = `mohClass=${encodeURIComponent(mohClass)}`;
1390
1682
  await this.baseClient.post(
1391
1683
  `/channels/${channelId}/moh?${queryParams}`
1392
1684
  );
1393
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
+ */
1394
1694
  async getChannelVariable(channelId, variable) {
1395
1695
  if (!variable) {
1396
1696
  throw new Error("The 'variable' parameter is required.");
@@ -1399,6 +1699,15 @@ var Channels = class {
1399
1699
  `/channels/${channelId}/variable?variable=${encodeURIComponent(variable)}`
1400
1700
  );
1401
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
+ */
1402
1711
  async setChannelVariable(channelId, variable, value) {
1403
1712
  if (!variable) {
1404
1713
  throw new Error("The 'variable' parameter is required.");
@@ -1411,12 +1720,30 @@ var Channels = class {
1411
1720
  `/channels/${channelId}/variable?${queryParams}`
1412
1721
  );
1413
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
+ */
1414
1731
  async moveToApplication(channelId, app, appArgs) {
1415
1732
  await this.baseClient.post(`/channels/${channelId}/move`, {
1416
1733
  app,
1417
1734
  appArgs
1418
1735
  });
1419
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
+ */
1420
1747
  async continueDialplan(channelId, context, extension, priority, label) {
1421
1748
  await this.baseClient.post(`/channels/${channelId}/continue`, {
1422
1749
  context,
@@ -1425,18 +1752,45 @@ var Channels = class {
1425
1752
  label
1426
1753
  });
1427
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
+ */
1428
1761
  async stopMusicOnHold(channelId) {
1429
1762
  await this.baseClient.delete(`/channels/${channelId}/moh`);
1430
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
+ */
1431
1770
  async startMusicOnHold(channelId) {
1432
1771
  await this.baseClient.post(`/channels/${channelId}/moh`);
1433
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
+ */
1434
1780
  async record(channelId, options) {
1435
1781
  const queryParams = toQueryParams2(options);
1436
1782
  return this.baseClient.post(
1437
1783
  `/channels/${channelId}/record?${queryParams}`
1438
1784
  );
1439
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
+ */
1440
1794
  async dial(channelId, caller, timeout) {
1441
1795
  const queryParams = new URLSearchParams({
1442
1796
  ...caller && { caller },
@@ -1446,45 +1800,126 @@ var Channels = class {
1446
1800
  `/channels/${channelId}/dial?${queryParams}`
1447
1801
  );
1448
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
+ */
1449
1812
  async redirectChannel(channelId, endpoint) {
1450
1813
  await this.baseClient.post(
1451
1814
  `/channels/${channelId}/redirect?endpoint=${encodeURIComponent(endpoint)}`
1452
1815
  );
1453
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
+ */
1454
1823
  async answerChannel(channelId) {
1455
1824
  await this.baseClient.post(`/channels/${channelId}/answer`);
1456
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
+ */
1457
1832
  async ringChannel(channelId) {
1458
1833
  await this.baseClient.post(`/channels/${channelId}/ring`);
1459
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
+ */
1460
1844
  async stopRingChannel(channelId) {
1461
1845
  await this.baseClient.delete(`/channels/${channelId}/ring`);
1462
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
+ */
1463
1859
  async sendDTMF(channelId, dtmf, options) {
1464
1860
  const queryParams = toQueryParams2({ dtmf, ...options });
1465
1861
  await this.baseClient.post(
1466
1862
  `/channels/${channelId}/dtmf?${queryParams}`
1467
1863
  );
1468
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
+ */
1469
1872
  async muteChannel(channelId, direction = "both") {
1470
1873
  await this.baseClient.post(
1471
1874
  `/channels/${channelId}/mute?direction=${direction}`
1472
1875
  );
1473
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
+ */
1474
1884
  async unmuteChannel(channelId, direction = "both") {
1475
1885
  await this.baseClient.delete(
1476
1886
  `/channels/${channelId}/mute?direction=${direction}`
1477
1887
  );
1478
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
+ */
1479
1895
  async holdChannel(channelId) {
1480
1896
  await this.baseClient.post(`/channels/${channelId}/hold`);
1481
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
+ */
1482
1904
  async unholdChannel(channelId) {
1483
1905
  await this.baseClient.delete(`/channels/${channelId}/hold`);
1484
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
+ */
1485
1913
  async createChannel(data) {
1486
1914
  return this.baseClient.post("/channels/create", data);
1487
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
+ */
1488
1923
  async originateWithId(channelId, data) {
1489
1924
  return this.baseClient.post(`/channels/${channelId}`, data);
1490
1925
  }
@@ -1538,93 +1973,187 @@ var Endpoints = class {
1538
1973
 
1539
1974
  // src/ari-client/resources/playbacks.ts
1540
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
+ };
1541
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
+ */
1542
1994
  constructor(client, baseClient, playbackId = `playback-${Date.now()}`) {
1543
1995
  this.client = client;
1544
1996
  this.baseClient = baseClient;
1545
1997
  this.playbackId = playbackId;
1546
1998
  this.id = playbackId;
1999
+ console.log(`PlaybackInstance initialized with ID: ${this.id}`);
1547
2000
  }
1548
2001
  eventEmitter = new import_events2.EventEmitter();
1549
2002
  playbackData = null;
1550
2003
  id;
1551
2004
  /**
1552
- * 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
1553
2009
  */
1554
2010
  on(event, listener) {
2011
+ if (!event) {
2012
+ throw new Error("Event type is required");
2013
+ }
1555
2014
  const wrappedListener = (data) => {
1556
2015
  if ("playback" in data && data.playback?.id === this.id) {
1557
2016
  listener(data);
1558
2017
  }
1559
2018
  };
1560
2019
  this.eventEmitter.on(event, wrappedListener);
2020
+ console.log(`Event listener registered for ${event} on playback ${this.id}`);
1561
2021
  }
1562
2022
  /**
1563
- * 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
1564
2027
  */
1565
2028
  once(event, listener) {
2029
+ if (!event) {
2030
+ throw new Error("Event type is required");
2031
+ }
1566
2032
  const wrappedListener = (data) => {
1567
2033
  if ("playback" in data && data.playback?.id === this.id) {
1568
2034
  listener(data);
1569
2035
  }
1570
2036
  };
1571
2037
  this.eventEmitter.once(event, wrappedListener);
2038
+ console.log(`One-time event listener registered for ${event} on playback ${this.id}`);
1572
2039
  }
1573
2040
  /**
1574
- * 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
1575
2045
  */
1576
2046
  off(event, listener) {
2047
+ if (!event) {
2048
+ throw new Error("Event type is required");
2049
+ }
1577
2050
  if (listener) {
1578
2051
  this.eventEmitter.off(event, listener);
2052
+ console.log(`Specific listener removed for ${event} on playback ${this.id}`);
1579
2053
  } else {
1580
2054
  this.eventEmitter.removeAllListeners(event);
2055
+ console.log(`All listeners removed for ${event} on playback ${this.id}`);
1581
2056
  }
1582
2057
  }
1583
2058
  /**
1584
- * 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
1585
2062
  */
1586
2063
  emitEvent(event) {
2064
+ if (!event) {
2065
+ console.warn("Received invalid event");
2066
+ return;
2067
+ }
1587
2068
  if ("playback" in event && event.playback?.id === this.id) {
1588
2069
  this.eventEmitter.emit(event.type, event);
2070
+ console.log(`Event ${event.type} emitted for playback ${this.id}`);
1589
2071
  }
1590
2072
  }
1591
2073
  /**
1592
- * 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
1593
2078
  */
1594
2079
  async get() {
1595
2080
  if (!this.id) {
1596
- 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}`);
1597
2093
  }
1598
- this.playbackData = await this.baseClient.get(
1599
- `/playbacks/${this.id}`
1600
- );
1601
- return this.playbackData;
1602
2094
  }
1603
2095
  /**
1604
- * 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
1605
2100
  */
1606
2101
  async control(operation) {
1607
2102
  if (!this.id) {
1608
- 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}`);
1609
2114
  }
1610
- await this.baseClient.post(
1611
- `/playbacks/${this.id}/control?operation=${operation}`
1612
- );
1613
2115
  }
1614
2116
  /**
1615
- * Encerra o playback.
2117
+ * Stops the current playback.
2118
+ *
2119
+ * @throws {Error} If playback is not properly initialized or stop operation fails
1616
2120
  */
1617
2121
  async stop() {
1618
2122
  if (!this.id) {
1619
- 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}`);
1620
2132
  }
1621
- await this.baseClient.delete(`/playbacks/${this.id}`);
1622
2133
  }
1623
2134
  /**
1624
- * Remove todos os listeners para este playback.
2135
+ * Removes all event listeners from this playback instance.
1625
2136
  */
1626
2137
  removeAllListeners() {
1627
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;
1628
2157
  }
1629
2158
  };
1630
2159
  var Playbacks = class {
@@ -1634,61 +2163,141 @@ var Playbacks = class {
1634
2163
  }
1635
2164
  playbackInstances = /* @__PURE__ */ new Map();
1636
2165
  /**
1637
- * 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
1638
2170
  */
1639
2171
  Playback({ id }) {
1640
- if (!id) {
1641
- const instance = new PlaybackInstance(this.client, this.baseClient);
1642
- this.playbackInstances.set(instance.id, instance);
1643
- return instance;
1644
- }
1645
- if (!this.playbackInstances.has(id)) {
1646
- const instance = new PlaybackInstance(this.client, this.baseClient, id);
1647
- this.playbackInstances.set(id, instance);
1648
- 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}`);
1649
2191
  }
1650
- return this.playbackInstances.get(id);
1651
2192
  }
1652
2193
  /**
1653
- * 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
1654
2197
  */
1655
2198
  removePlaybackInstance(playbackId) {
2199
+ if (!playbackId) {
2200
+ throw new Error("Playback ID is required");
2201
+ }
1656
2202
  if (this.playbackInstances.has(playbackId)) {
1657
2203
  const instance = this.playbackInstances.get(playbackId);
1658
2204
  instance?.removeAllListeners();
1659
2205
  this.playbackInstances.delete(playbackId);
2206
+ console.log(`Playback instance removed: ${playbackId}`);
2207
+ } else {
2208
+ console.warn(`Attempt to remove non-existent instance: ${playbackId}`);
1660
2209
  }
1661
2210
  }
1662
2211
  /**
1663
- * 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
1664
2214
  */
1665
2215
  propagateEventToPlayback(event) {
2216
+ if (!event) {
2217
+ console.warn("Invalid WebSocket event received");
2218
+ return;
2219
+ }
1666
2220
  if ("playback" in event && event.playback?.id) {
1667
2221
  const instance = this.playbackInstances.get(event.playback.id);
1668
2222
  if (instance) {
1669
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}`);
1670
2227
  }
1671
2228
  }
1672
2229
  }
1673
2230
  /**
1674
- * 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
1675
2235
  */
1676
2236
  async getDetails(playbackId) {
1677
- 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
+ }
1678
2247
  }
1679
2248
  /**
1680
- * 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
1681
2253
  */
1682
2254
  async control(playbackId, operation) {
1683
- const playback = this.Playback({ id: playbackId });
1684
- 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
+ }
1685
2267
  }
1686
2268
  /**
1687
- * 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
1688
2272
  */
1689
2273
  async stop(playbackId) {
1690
- const playback = this.Playback({ id: playbackId });
1691
- 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);
1692
2301
  }
1693
2302
  };
1694
2303
 
@@ -1727,40 +2336,51 @@ var Sounds = class {
1727
2336
  var import_events3 = require("events");
1728
2337
  var import_exponential_backoff = __toESM(require_backoff(), 1);
1729
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;
1730
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
+ */
1731
2351
  constructor(baseClient, apps, subscribedEvents, ariClient) {
1732
2352
  super();
1733
2353
  this.baseClient = baseClient;
1734
2354
  this.apps = apps;
1735
2355
  this.subscribedEvents = subscribedEvents;
1736
2356
  this.ariClient = ariClient;
2357
+ if (!apps.length) {
2358
+ throw new Error("At least one application name is required");
2359
+ }
1737
2360
  }
1738
2361
  ws;
1739
2362
  isReconnecting = false;
1740
- maxReconnectAttempts = 10;
2363
+ maxReconnectAttempts = DEFAULT_MAX_RECONNECT_ATTEMPTS;
1741
2364
  backOffOptions = {
1742
- numOfAttempts: 10,
1743
- // Máximo de tentativas de reconexão
1744
- startingDelay: 500,
1745
- // Início com 500ms de atraso
1746
- maxDelay: 1e4,
1747
- // Limite máximo de atraso de 10s
2365
+ numOfAttempts: DEFAULT_MAX_RECONNECT_ATTEMPTS,
2366
+ startingDelay: DEFAULT_STARTING_DELAY,
2367
+ maxDelay: DEFAULT_MAX_DELAY,
1748
2368
  timeMultiple: 2,
1749
- // Atraso aumenta exponencialmente
1750
2369
  jitter: "full",
1751
- // Randomização para evitar colisões
1752
2370
  delayFirstAttempt: false,
1753
- // Não atrase a primeira tentativa
1754
2371
  retry: (error, attemptNumber) => {
1755
2372
  console.warn(
1756
- `Tentativa #${attemptNumber} falhou:`,
1757
- error.message || error
2373
+ `Connection attempt #${attemptNumber} failed:`,
2374
+ error.message || "Unknown error"
1758
2375
  );
1759
- return true;
2376
+ return attemptNumber < this.maxReconnectAttempts;
1760
2377
  }
1761
2378
  };
1762
2379
  /**
1763
- * Conecta ao WebSocket.
2380
+ * Establishes a WebSocket connection.
2381
+ *
2382
+ * @returns {Promise<void>} Resolves when connection is established
2383
+ * @throws {Error} If connection fails
1764
2384
  */
1765
2385
  async connect() {
1766
2386
  const { baseUrl, username, password } = this.baseClient.getCredentials();
@@ -1768,7 +2388,7 @@ var WebSocketClient = class extends import_events3.EventEmitter {
1768
2388
  const normalizedHost = baseUrl.replace(/^https?:\/\//, "").replace(/\/ari$/, "");
1769
2389
  const queryParams = new URLSearchParams();
1770
2390
  queryParams.append("app", this.apps.join(","));
1771
- if (this.subscribedEvents && this.subscribedEvents.length > 0) {
2391
+ if (this.subscribedEvents?.length) {
1772
2392
  this.subscribedEvents.forEach(
1773
2393
  (event) => queryParams.append("event", event)
1774
2394
  );
@@ -1776,48 +2396,57 @@ var WebSocketClient = class extends import_events3.EventEmitter {
1776
2396
  queryParams.append("subscribeAll", "true");
1777
2397
  }
1778
2398
  const wsUrl = `${protocol}://${encodeURIComponent(username)}:${encodeURIComponent(password)}@${normalizedHost}/ari/events?${queryParams.toString()}`;
1779
- console.log("Conectando ao WebSocket em:", wsUrl);
2399
+ console.log("Connecting to WebSocket...");
1780
2400
  return this.initializeWebSocket(wsUrl);
1781
2401
  }
1782
2402
  /**
1783
- * 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
1784
2407
  */
1785
2408
  async initializeWebSocket(wsUrl) {
1786
2409
  return (0, import_exponential_backoff.backOff)(async () => {
1787
2410
  return new Promise((resolve, reject) => {
1788
- this.ws = new import_ws.default(wsUrl);
1789
- this.ws.on("open", () => {
1790
- console.log("WebSocket conectado com sucesso.");
1791
- this.isReconnecting = false;
1792
- this.emit("connected");
1793
- resolve();
1794
- });
1795
- this.ws.on("message", (data) => this.handleMessage(data.toString()));
1796
- this.ws.on("close", (code) => {
1797
- console.warn(
1798
- `WebSocket desconectado com c\xF3digo ${code}. Tentando reconectar...`
1799
- );
1800
- if (!this.isReconnecting) {
1801
- this.reconnect(wsUrl);
1802
- }
1803
- });
1804
- this.ws.on("error", (err) => {
1805
- console.error("Erro no WebSocket:", err.message);
1806
- if (!this.isReconnecting) {
1807
- this.reconnect(wsUrl);
1808
- }
1809
- reject(err);
1810
- });
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
+ }
1811
2438
  });
1812
2439
  }, this.backOffOptions);
1813
2440
  }
1814
2441
  /**
1815
- * Processa as mensagens recebidas do WebSocket.
2442
+ * Processes incoming WebSocket messages.
2443
+ *
2444
+ * @param {string} rawMessage - The raw message received from WebSocket
1816
2445
  */
1817
2446
  handleMessage(rawMessage) {
1818
2447
  try {
1819
2448
  const event = JSON.parse(rawMessage);
1820
- if (this.subscribedEvents && !this.subscribedEvents.includes(event.type)) {
2449
+ if (this.subscribedEvents?.length && !this.subscribedEvents.includes(event.type)) {
1821
2450
  return;
1822
2451
  }
1823
2452
  if ("channel" in event && event.channel?.id && this.ariClient) {
@@ -1831,40 +2460,77 @@ var WebSocketClient = class extends import_events3.EventEmitter {
1831
2460
  event.instancePlayback = instancePlayback;
1832
2461
  }
1833
2462
  this.emit(event.type, event);
1834
- } catch (err) {
1835
- console.error("Erro ao processar mensagem WebSocket:", err);
1836
- 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"));
1837
2467
  }
1838
2468
  }
1839
2469
  /**
1840
- * Tenta reconectar ao WebSocket.
2470
+ * Attempts to reconnect to the WebSocket.
2471
+ *
2472
+ * @param {string} wsUrl - The WebSocket URL to reconnect to
1841
2473
  */
1842
2474
  reconnect(wsUrl) {
1843
2475
  this.isReconnecting = true;
1844
- console.log("Iniciando tentativa de reconex\xE3o...");
2476
+ console.log("Initiating reconnection attempt...");
1845
2477
  this.removeAllListeners();
1846
- (0, import_exponential_backoff.backOff)(() => this.initializeWebSocket(wsUrl), this.backOffOptions).catch(
1847
- (err) => {
1848
- console.error(
1849
- "Falha ao reconectar ap\xF3s v\xE1rias tentativas:",
1850
- err.message || err
1851
- );
1852
- }
1853
- );
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
+ });
1854
2485
  }
1855
2486
  /**
1856
- * Fecha o WebSocket manualmente.
2487
+ * Manually closes the WebSocket connection.
1857
2488
  */
1858
2489
  close() {
1859
- this.ws?.close();
1860
- 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;
1861
2518
  }
1862
2519
  };
1863
2520
 
1864
2521
  // src/ari-client/ariClient.ts
1865
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
+ */
1866
2529
  constructor(config) {
1867
2530
  this.config = config;
2531
+ if (!config.host || !config.port || !config.username || !config.password) {
2532
+ throw new Error("Missing required configuration parameters");
2533
+ }
1868
2534
  const httpProtocol = config.secure ? "https" : "http";
1869
2535
  const normalizedHost = config.host.replace(/^https?:\/\//, "");
1870
2536
  const baseUrl = `${httpProtocol}://${normalizedHost}:${config.port}/ari`;
@@ -1876,6 +2542,7 @@ var AriClient = class {
1876
2542
  this.sounds = new Sounds(this.baseClient);
1877
2543
  this.asterisk = new Asterisk(this.baseClient);
1878
2544
  this.bridges = new Bridges(this.baseClient);
2545
+ console.log(`ARI Client initialized with base URL: ${baseUrl}`);
1879
2546
  }
1880
2547
  baseClient;
1881
2548
  webSocketClient;
@@ -1887,58 +2554,117 @@ var AriClient = class {
1887
2554
  asterisk;
1888
2555
  bridges;
1889
2556
  /**
1890
- * 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
1891
2563
  */
1892
2564
  async connectWebSocket(apps, subscribedEvents) {
2565
+ if (!apps.length) {
2566
+ throw new Error("At least one application name is required");
2567
+ }
1893
2568
  if (this.webSocketClient) {
1894
- console.warn("WebSocket j\xE1 est\xE1 conectado.");
2569
+ console.warn("WebSocket is already connected");
1895
2570
  return;
1896
2571
  }
1897
- this.webSocketClient = new WebSocketClient(
1898
- this.baseClient,
1899
- apps,
1900
- subscribedEvents,
1901
- this
1902
- );
1903
- 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
+ }
1904
2586
  }
1905
2587
  /**
1906
- * 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
1907
2593
  */
1908
2594
  on(event, listener) {
1909
- 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}`);
1910
2600
  }
1911
2601
  /**
1912
- * 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
1913
2607
  */
1914
2608
  once(event, listener) {
1915
- 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}`);
1916
2614
  }
1917
2615
  /**
1918
- * 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
1919
2620
  */
1920
2621
  off(event, listener) {
1921
- 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}`);
1922
2628
  }
1923
2629
  /**
1924
- * Fecha a conexão WebSocket.
2630
+ * Closes the WebSocket connection if one exists.
1925
2631
  */
1926
2632
  closeWebSocket() {
1927
- this.webSocketClient?.close();
2633
+ if (!this.webSocketClient) {
2634
+ console.warn("No WebSocket connection to close");
2635
+ return;
2636
+ }
2637
+ this.webSocketClient.close();
1928
2638
  this.webSocketClient = void 0;
2639
+ console.log("WebSocket connection closed");
1929
2640
  }
1930
2641
  /**
1931
- * 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
1932
2646
  */
1933
2647
  Channel(channelId) {
1934
2648
  return this.channels.Channel({ id: channelId });
1935
2649
  }
1936
2650
  /**
1937
- * 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
1938
2656
  */
1939
2657
  Playback(playbackId, _app) {
1940
2658
  return this.playbacks.Playback({ id: playbackId });
1941
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
+ }
1942
2668
  };
1943
2669
  // Annotate the CommonJS export names for ESM import in node:
1944
2670
  0 && (module.exports = {