@ipcom/asterisk-ari 0.0.66 → 0.0.68
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.cjs +113 -68
- package/dist/cjs/index.cjs.map +2 -2
- package/dist/esm/index.js +113 -68
- package/dist/esm/index.js.map +2 -2
- package/dist/types/ari-client/ariClient.d.ts +20 -12
- package/dist/types/ari-client/ariClient.d.ts.map +1 -1
- package/dist/types/ari-client/resources/channels.d.ts +1 -4
- package/dist/types/ari-client/resources/channels.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/cjs/index.cjs
CHANGED
|
@@ -890,6 +890,7 @@ var ChannelInstance = class extends import_events2.EventEmitter {
|
|
|
890
890
|
this.client = client;
|
|
891
891
|
this.baseClient = baseClient;
|
|
892
892
|
this.channelId = channelId;
|
|
893
|
+
this.id = channelId || `channel-${Date.now()}`;
|
|
893
894
|
this.baseClient.onWebSocketEvent((event) => {
|
|
894
895
|
if (this.isChannelEvent(event) && event.channel?.id === this.channelId) {
|
|
895
896
|
this.emit(event.type, event);
|
|
@@ -897,6 +898,8 @@ var ChannelInstance = class extends import_events2.EventEmitter {
|
|
|
897
898
|
});
|
|
898
899
|
}
|
|
899
900
|
channelData = null;
|
|
901
|
+
id;
|
|
902
|
+
// ID do canal
|
|
900
903
|
/**
|
|
901
904
|
* Verifica se o evento possui a propriedade `channel`.
|
|
902
905
|
* @param event Evento recebido.
|
|
@@ -925,12 +928,6 @@ var ChannelInstance = class extends import_events2.EventEmitter {
|
|
|
925
928
|
super.off(event, callback);
|
|
926
929
|
return this;
|
|
927
930
|
}
|
|
928
|
-
/**
|
|
929
|
-
* Getter para o ID do canal.
|
|
930
|
-
*/
|
|
931
|
-
get id() {
|
|
932
|
-
return this.channelId;
|
|
933
|
-
}
|
|
934
931
|
async answer() {
|
|
935
932
|
await this.baseClient.post(`/channels/${this.id}/answer`);
|
|
936
933
|
}
|
|
@@ -1706,18 +1703,19 @@ var AriClient = class {
|
|
|
1706
1703
|
this.bridges = new Bridges(this.baseClient);
|
|
1707
1704
|
}
|
|
1708
1705
|
eventListeners = /* @__PURE__ */ new Map();
|
|
1709
|
-
|
|
1706
|
+
wsClients = /* @__PURE__ */ new Map();
|
|
1707
|
+
// Map para armazenar conexões por app
|
|
1710
1708
|
baseClient;
|
|
1711
|
-
isReconnecting =
|
|
1712
|
-
|
|
1713
|
-
webSocketReady =
|
|
1714
|
-
//
|
|
1709
|
+
isReconnecting = /* @__PURE__ */ new Map();
|
|
1710
|
+
// Estado de reconexão por app
|
|
1711
|
+
webSocketReady = /* @__PURE__ */ new Map();
|
|
1712
|
+
// Rastreamento do estado de cada conexão
|
|
1715
1713
|
channelInstances = /* @__PURE__ */ new Map();
|
|
1716
1714
|
pendingListeners = [];
|
|
1717
1715
|
processPendingListeners() {
|
|
1718
|
-
if (
|
|
1716
|
+
if (this.wsClients.size === 0) {
|
|
1719
1717
|
console.warn(
|
|
1720
|
-
"
|
|
1718
|
+
"Nenhuma conex\xE3o WebSocket est\xE1 pronta. N\xE3o \xE9 poss\xEDvel processar a fila."
|
|
1721
1719
|
);
|
|
1722
1720
|
return;
|
|
1723
1721
|
}
|
|
@@ -1727,7 +1725,12 @@ var AriClient = class {
|
|
|
1727
1725
|
while (this.pendingListeners.length > 0) {
|
|
1728
1726
|
const { event, callback } = this.pendingListeners.shift();
|
|
1729
1727
|
console.log(`Registrando listener pendente para evento: ${event}`);
|
|
1730
|
-
this.
|
|
1728
|
+
for (const [app, wsClient] of this.wsClients.entries()) {
|
|
1729
|
+
console.log(
|
|
1730
|
+
`Registrando listener no app '${app}' para evento: ${event}`
|
|
1731
|
+
);
|
|
1732
|
+
wsClient.on(event, callback);
|
|
1733
|
+
}
|
|
1731
1734
|
}
|
|
1732
1735
|
}
|
|
1733
1736
|
channels;
|
|
@@ -1743,14 +1746,24 @@ var AriClient = class {
|
|
|
1743
1746
|
* @param callback Callback a ser executado quando o evento for recebido.
|
|
1744
1747
|
*/
|
|
1745
1748
|
onChannelEvent(eventType, callback) {
|
|
1746
|
-
this.
|
|
1749
|
+
if (this.wsClients.size === 0) {
|
|
1750
|
+
console.warn(
|
|
1751
|
+
"Nenhuma conex\xE3o WebSocket est\xE1 ativa. O listener ser\xE1 pendente."
|
|
1752
|
+
);
|
|
1753
|
+
this.pendingListeners.push({ event: eventType, callback });
|
|
1754
|
+
return;
|
|
1755
|
+
}
|
|
1756
|
+
for (const [app, wsClient] of this.wsClients.entries()) {
|
|
1757
|
+
console.log(`Registrando evento '${eventType}' no app '${app}'`);
|
|
1758
|
+
wsClient.on(eventType, callback);
|
|
1759
|
+
}
|
|
1747
1760
|
}
|
|
1748
1761
|
/**
|
|
1749
1762
|
* Registra um listener para eventos globais de WebSocket.
|
|
1750
1763
|
* O channel no evento será automaticamente transformado em uma instância de ChannelInstance.
|
|
1751
1764
|
*/
|
|
1752
1765
|
on(eventType, callback) {
|
|
1753
|
-
console.log(`Registrando listener
|
|
1766
|
+
console.log(`Registrando listener global para evento: ${eventType}`);
|
|
1754
1767
|
const wrappedCallback = (event) => {
|
|
1755
1768
|
if (isChannelEvent(event)) {
|
|
1756
1769
|
const channelId = event.channel.id;
|
|
@@ -1814,70 +1827,84 @@ var AriClient = class {
|
|
|
1814
1827
|
* @returns A Promise that resolves when the WebSocket connection is successfully established and the application is registered.
|
|
1815
1828
|
* @throws Error if the 'app' parameter is not provided, or if connection attempts fail after multiple retries.
|
|
1816
1829
|
*/
|
|
1817
|
-
|
|
1830
|
+
/**
|
|
1831
|
+
* Connects to the ARI WebSocket for one or more applications.
|
|
1832
|
+
* Establishes a WebSocket connection for each app and subscribes to events.
|
|
1833
|
+
*
|
|
1834
|
+
* @param apps - Array of application names to connect to.
|
|
1835
|
+
* @param subscribedEvents - Optional array of events to subscribe to.
|
|
1836
|
+
* If not provided or empty, subscribes to all events.
|
|
1837
|
+
* @returns A Promise that resolves when all connections are established.
|
|
1838
|
+
*/
|
|
1839
|
+
async connectWebSocket(apps, subscribedEvents) {
|
|
1840
|
+
if (!Array.isArray(apps) || apps.length === 0) {
|
|
1841
|
+
throw new Error("\xC9 necess\xE1rio fornecer pelo menos um aplicativo.");
|
|
1842
|
+
}
|
|
1843
|
+
return Promise.all(
|
|
1844
|
+
apps.map((app) => this.connectSingleWebSocket(app, subscribedEvents))
|
|
1845
|
+
);
|
|
1846
|
+
}
|
|
1847
|
+
/**
|
|
1848
|
+
* Establishes a single WebSocket connection for a given app.
|
|
1849
|
+
*/
|
|
1850
|
+
async connectSingleWebSocket(app, subscribedEvents) {
|
|
1818
1851
|
if (!app) {
|
|
1819
|
-
throw new Error(
|
|
1820
|
-
"O par\xE2metro 'app' \xE9 obrigat\xF3rio para conectar ao WebSocket."
|
|
1821
|
-
);
|
|
1852
|
+
throw new Error("O nome do aplicativo \xE9 obrigat\xF3rio.");
|
|
1822
1853
|
}
|
|
1823
|
-
if (this.webSocketReady) {
|
|
1824
|
-
console.log(
|
|
1825
|
-
return this.webSocketReady;
|
|
1854
|
+
if (this.webSocketReady.get(app)) {
|
|
1855
|
+
console.log(`Conex\xE3o WebSocket para '${app}' j\xE1 est\xE1 ativa.`);
|
|
1856
|
+
return this.webSocketReady.get(app);
|
|
1826
1857
|
}
|
|
1827
|
-
|
|
1858
|
+
const protocol = this.config.secure ? "wss" : "ws";
|
|
1859
|
+
const eventsParam = subscribedEvents && subscribedEvents.length > 0 ? `&event=${subscribedEvents.join(",")}` : "&subscribeAll=true";
|
|
1860
|
+
const wsUrl = `${protocol}://${encodeURIComponent(
|
|
1861
|
+
this.config.username
|
|
1862
|
+
)}:${encodeURIComponent(this.config.password)}@${this.config.host}:${this.config.port}/ari/events?app=${app}${eventsParam}`;
|
|
1863
|
+
const backoffOptions = {
|
|
1864
|
+
delayFirstAttempt: false,
|
|
1865
|
+
startingDelay: 1e3,
|
|
1866
|
+
timeMultiple: 2,
|
|
1867
|
+
maxDelay: 3e4,
|
|
1868
|
+
numOfAttempts: 10,
|
|
1869
|
+
jitter: "full",
|
|
1870
|
+
retry: (error, attemptNumber) => {
|
|
1871
|
+
console.warn(`Tentativa ${attemptNumber} falhou: ${error.message}`);
|
|
1872
|
+
return Array.from(this.wsClients.values()).some(
|
|
1873
|
+
(wsClient) => !wsClient.isConnected()
|
|
1874
|
+
);
|
|
1875
|
+
}
|
|
1876
|
+
};
|
|
1877
|
+
const webSocketPromise = new Promise(async (resolve, reject) => {
|
|
1828
1878
|
try {
|
|
1829
|
-
if (this.isReconnecting) {
|
|
1830
|
-
console.warn(
|
|
1831
|
-
"J\xE1 est\xE1 tentando reconectar. Ignorando esta tentativa."
|
|
1832
|
-
);
|
|
1879
|
+
if (this.isReconnecting.get(app)) {
|
|
1880
|
+
console.warn(`J\xE1 est\xE1 tentando reconectar para o app '${app}'.`);
|
|
1833
1881
|
return;
|
|
1834
1882
|
}
|
|
1835
|
-
this.isReconnecting
|
|
1836
|
-
const
|
|
1837
|
-
const protocol = this.config.secure ? "wss" : "ws";
|
|
1838
|
-
const wsUrl = `${protocol}://${encodeURIComponent(this.config.username)}:${encodeURIComponent(this.config.password)}@${this.config.host}:${this.config.port}/ari/events?app=${app}${eventsParam}`;
|
|
1839
|
-
const backoffOptions = {
|
|
1840
|
-
delayFirstAttempt: false,
|
|
1841
|
-
startingDelay: 1e3,
|
|
1842
|
-
timeMultiple: 2,
|
|
1843
|
-
maxDelay: 3e4,
|
|
1844
|
-
numOfAttempts: 10,
|
|
1845
|
-
jitter: "full",
|
|
1846
|
-
retry: (error, attemptNumber) => {
|
|
1847
|
-
console.warn(`Tentativa ${attemptNumber} falhou: ${error.message}`);
|
|
1848
|
-
return !this.wsClient?.isConnected();
|
|
1849
|
-
}
|
|
1850
|
-
};
|
|
1851
|
-
if (this.wsClient?.isConnected()) {
|
|
1852
|
-
console.log("WebSocket j\xE1 conectado. Removendo listeners antigos...");
|
|
1853
|
-
this.wsClient.removeAllListeners();
|
|
1854
|
-
this.wsClient.close();
|
|
1855
|
-
}
|
|
1856
|
-
this.wsClient = new WebSocketClient(wsUrl);
|
|
1883
|
+
this.isReconnecting.set(app, true);
|
|
1884
|
+
const wsClient = new WebSocketClient(wsUrl);
|
|
1857
1885
|
await (0, import_exponential_backoff.backOff)(async () => {
|
|
1858
|
-
if (!
|
|
1886
|
+
if (!wsClient) {
|
|
1859
1887
|
throw new Error("WebSocketClient instance is null.");
|
|
1860
1888
|
}
|
|
1861
|
-
await
|
|
1862
|
-
this.integrateWebSocketEvents(app,
|
|
1889
|
+
await wsClient.connect();
|
|
1890
|
+
this.integrateWebSocketEvents(app, wsClient);
|
|
1863
1891
|
console.log(`WebSocket conectado para o app: ${app}`);
|
|
1864
1892
|
await this.ensureAppRegistered(app);
|
|
1865
|
-
this.
|
|
1866
|
-
this.processPendingListeners();
|
|
1893
|
+
this.wsClients.set(app, wsClient);
|
|
1867
1894
|
}, backoffOptions);
|
|
1868
1895
|
resolve();
|
|
1869
|
-
} catch (
|
|
1896
|
+
} catch (error) {
|
|
1870
1897
|
console.error(
|
|
1871
|
-
|
|
1872
|
-
|
|
1898
|
+
`Erro ao conectar o WebSocket para o app '${app}':`,
|
|
1899
|
+
error
|
|
1873
1900
|
);
|
|
1874
|
-
reject(
|
|
1901
|
+
reject(error);
|
|
1875
1902
|
} finally {
|
|
1876
|
-
this.isReconnecting
|
|
1877
|
-
this.webSocketReady = null;
|
|
1903
|
+
this.isReconnecting.delete(app);
|
|
1878
1904
|
}
|
|
1879
1905
|
});
|
|
1880
|
-
|
|
1906
|
+
this.webSocketReady.set(app, webSocketPromise);
|
|
1907
|
+
return webSocketPromise;
|
|
1881
1908
|
}
|
|
1882
1909
|
/**
|
|
1883
1910
|
* Integrates WebSocket events with playback listeners.
|
|
@@ -1949,8 +1976,14 @@ var AriClient = class {
|
|
|
1949
1976
|
*
|
|
1950
1977
|
* @returns {boolean} True if connected, false otherwise.
|
|
1951
1978
|
*/
|
|
1952
|
-
|
|
1953
|
-
return
|
|
1979
|
+
anyWebSocketConnected() {
|
|
1980
|
+
return Array.from(this.wsClients.values()).every(
|
|
1981
|
+
(wsClient) => wsClient.isConnected()
|
|
1982
|
+
);
|
|
1983
|
+
}
|
|
1984
|
+
isWebSocketConnected(app) {
|
|
1985
|
+
const wsClient = this.wsClients.get(app);
|
|
1986
|
+
return wsClient ? wsClient.isConnected() : false;
|
|
1954
1987
|
}
|
|
1955
1988
|
/**
|
|
1956
1989
|
* Closes the WebSocket connection and removes all associated listeners.
|
|
@@ -1962,12 +1995,24 @@ var AriClient = class {
|
|
|
1962
1995
|
*
|
|
1963
1996
|
* @returns {void} This function doesn't return a value.
|
|
1964
1997
|
*/
|
|
1965
|
-
closeWebSocket() {
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1998
|
+
closeWebSocket(app) {
|
|
1999
|
+
const wsClient = this.wsClients.get(app);
|
|
2000
|
+
if (wsClient) {
|
|
2001
|
+
wsClient.close();
|
|
2002
|
+
this.wsClients.delete(app);
|
|
2003
|
+
console.log(`WebSocket para o app '${app}' foi fechado.`);
|
|
2004
|
+
} else {
|
|
2005
|
+
console.warn(`WebSocket para o app '${app}' n\xE3o encontrado.`);
|
|
1969
2006
|
}
|
|
1970
2007
|
}
|
|
2008
|
+
closeAllWebSockets() {
|
|
2009
|
+
this.wsClients.forEach((wsClient, app) => {
|
|
2010
|
+
wsClient.close();
|
|
2011
|
+
console.log(`WebSocket para o app '${app}' foi fechado.`);
|
|
2012
|
+
});
|
|
2013
|
+
this.wsClients.clear();
|
|
2014
|
+
console.log("Todos os WebSockets foram fechados.");
|
|
2015
|
+
}
|
|
1971
2016
|
/**
|
|
1972
2017
|
* Retrieves a list of active channels from the Asterisk ARI.
|
|
1973
2018
|
*
|