@ipcom/asterisk-ari 0.0.67 → 0.0.69
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 +117 -63
- package/dist/cjs/index.cjs.map +3 -3
- package/dist/esm/index.js +117 -63
- package/dist/esm/index.js.map +3 -3
- 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.map +1 -1
- package/package.json +1 -1
package/dist/cjs/index.cjs
CHANGED
|
@@ -893,6 +893,7 @@ var ChannelInstance = class extends import_events2.EventEmitter {
|
|
|
893
893
|
this.id = channelId || `channel-${Date.now()}`;
|
|
894
894
|
this.baseClient.onWebSocketEvent((event) => {
|
|
895
895
|
if (this.isChannelEvent(event) && event.channel?.id === this.channelId) {
|
|
896
|
+
console.log(`Evento recebido no ChannelInstance: ${event.type}`, event);
|
|
896
897
|
this.emit(event.type, event);
|
|
897
898
|
}
|
|
898
899
|
});
|
|
@@ -905,7 +906,11 @@ var ChannelInstance = class extends import_events2.EventEmitter {
|
|
|
905
906
|
* @param event Evento recebido.
|
|
906
907
|
*/
|
|
907
908
|
isChannelEvent(event) {
|
|
908
|
-
|
|
909
|
+
const isChannelEvent2 = event && typeof event === "object" && "channel" in event && event.channel?.id === this.channelId;
|
|
910
|
+
if (!isChannelEvent2) {
|
|
911
|
+
console.log(`Evento ignorado no ChannelInstance: ${event.type}`, event);
|
|
912
|
+
}
|
|
913
|
+
return isChannelEvent2;
|
|
909
914
|
}
|
|
910
915
|
/**
|
|
911
916
|
* Adiciona um listener para eventos de canal.
|
|
@@ -1703,18 +1708,19 @@ var AriClient = class {
|
|
|
1703
1708
|
this.bridges = new Bridges(this.baseClient);
|
|
1704
1709
|
}
|
|
1705
1710
|
eventListeners = /* @__PURE__ */ new Map();
|
|
1706
|
-
|
|
1711
|
+
wsClients = /* @__PURE__ */ new Map();
|
|
1712
|
+
// Map para armazenar conexões por app
|
|
1707
1713
|
baseClient;
|
|
1708
|
-
isReconnecting =
|
|
1709
|
-
|
|
1710
|
-
webSocketReady =
|
|
1711
|
-
//
|
|
1714
|
+
isReconnecting = /* @__PURE__ */ new Map();
|
|
1715
|
+
// Estado de reconexão por app
|
|
1716
|
+
webSocketReady = /* @__PURE__ */ new Map();
|
|
1717
|
+
// Rastreamento do estado de cada conexão
|
|
1712
1718
|
channelInstances = /* @__PURE__ */ new Map();
|
|
1713
1719
|
pendingListeners = [];
|
|
1714
1720
|
processPendingListeners() {
|
|
1715
|
-
if (
|
|
1721
|
+
if (this.wsClients.size === 0) {
|
|
1716
1722
|
console.warn(
|
|
1717
|
-
"
|
|
1723
|
+
"Nenhuma conex\xE3o WebSocket est\xE1 pronta. N\xE3o \xE9 poss\xEDvel processar a fila."
|
|
1718
1724
|
);
|
|
1719
1725
|
return;
|
|
1720
1726
|
}
|
|
@@ -1724,7 +1730,12 @@ var AriClient = class {
|
|
|
1724
1730
|
while (this.pendingListeners.length > 0) {
|
|
1725
1731
|
const { event, callback } = this.pendingListeners.shift();
|
|
1726
1732
|
console.log(`Registrando listener pendente para evento: ${event}`);
|
|
1727
|
-
this.
|
|
1733
|
+
for (const [app, wsClient] of this.wsClients.entries()) {
|
|
1734
|
+
console.log(
|
|
1735
|
+
`Registrando listener no app '${app}' para evento: ${event}`
|
|
1736
|
+
);
|
|
1737
|
+
wsClient.on(event, callback);
|
|
1738
|
+
}
|
|
1728
1739
|
}
|
|
1729
1740
|
}
|
|
1730
1741
|
channels;
|
|
@@ -1740,14 +1751,24 @@ var AriClient = class {
|
|
|
1740
1751
|
* @param callback Callback a ser executado quando o evento for recebido.
|
|
1741
1752
|
*/
|
|
1742
1753
|
onChannelEvent(eventType, callback) {
|
|
1743
|
-
this.
|
|
1754
|
+
if (this.wsClients.size === 0) {
|
|
1755
|
+
console.warn(
|
|
1756
|
+
"Nenhuma conex\xE3o WebSocket est\xE1 ativa. O listener ser\xE1 pendente."
|
|
1757
|
+
);
|
|
1758
|
+
this.pendingListeners.push({ event: eventType, callback });
|
|
1759
|
+
return;
|
|
1760
|
+
}
|
|
1761
|
+
for (const [app, wsClient] of this.wsClients.entries()) {
|
|
1762
|
+
console.log(`Registrando evento '${eventType}' no app '${app}'`);
|
|
1763
|
+
wsClient.on(eventType, callback);
|
|
1764
|
+
}
|
|
1744
1765
|
}
|
|
1745
1766
|
/**
|
|
1746
1767
|
* Registra um listener para eventos globais de WebSocket.
|
|
1747
1768
|
* O channel no evento será automaticamente transformado em uma instância de ChannelInstance.
|
|
1748
1769
|
*/
|
|
1749
1770
|
on(eventType, callback) {
|
|
1750
|
-
console.log(`Registrando listener
|
|
1771
|
+
console.log(`Registrando listener global para evento: ${eventType}`);
|
|
1751
1772
|
const wrappedCallback = (event) => {
|
|
1752
1773
|
if (isChannelEvent(event)) {
|
|
1753
1774
|
const channelId = event.channel.id;
|
|
@@ -1781,6 +1802,7 @@ var AriClient = class {
|
|
|
1781
1802
|
return this.channels.createChannelInstance(channelId);
|
|
1782
1803
|
}
|
|
1783
1804
|
handleWebSocketEvent(event) {
|
|
1805
|
+
console.log("Evento recebido no WebSocket:", event.type, event);
|
|
1784
1806
|
const { type, ...data } = event;
|
|
1785
1807
|
if (this.hasChannel(data)) {
|
|
1786
1808
|
const channelId = data.channel.id;
|
|
@@ -1811,70 +1833,84 @@ var AriClient = class {
|
|
|
1811
1833
|
* @returns A Promise that resolves when the WebSocket connection is successfully established and the application is registered.
|
|
1812
1834
|
* @throws Error if the 'app' parameter is not provided, or if connection attempts fail after multiple retries.
|
|
1813
1835
|
*/
|
|
1814
|
-
|
|
1836
|
+
/**
|
|
1837
|
+
* Connects to the ARI WebSocket for one or more applications.
|
|
1838
|
+
* Establishes a WebSocket connection for each app and subscribes to events.
|
|
1839
|
+
*
|
|
1840
|
+
* @param apps - Array of application names to connect to.
|
|
1841
|
+
* @param subscribedEvents - Optional array of events to subscribe to.
|
|
1842
|
+
* If not provided or empty, subscribes to all events.
|
|
1843
|
+
* @returns A Promise that resolves when all connections are established.
|
|
1844
|
+
*/
|
|
1845
|
+
async connectWebSocket(apps, subscribedEvents) {
|
|
1846
|
+
if (!Array.isArray(apps) || apps.length === 0) {
|
|
1847
|
+
throw new Error("\xC9 necess\xE1rio fornecer pelo menos um aplicativo.");
|
|
1848
|
+
}
|
|
1849
|
+
return Promise.all(
|
|
1850
|
+
apps.map((app) => this.connectSingleWebSocket(app, subscribedEvents))
|
|
1851
|
+
);
|
|
1852
|
+
}
|
|
1853
|
+
/**
|
|
1854
|
+
* Establishes a single WebSocket connection for a given app.
|
|
1855
|
+
*/
|
|
1856
|
+
async connectSingleWebSocket(app, subscribedEvents) {
|
|
1815
1857
|
if (!app) {
|
|
1816
|
-
throw new Error(
|
|
1817
|
-
"O par\xE2metro 'app' \xE9 obrigat\xF3rio para conectar ao WebSocket."
|
|
1818
|
-
);
|
|
1858
|
+
throw new Error("O nome do aplicativo \xE9 obrigat\xF3rio.");
|
|
1819
1859
|
}
|
|
1820
|
-
if (this.webSocketReady) {
|
|
1821
|
-
console.log(
|
|
1822
|
-
return this.webSocketReady;
|
|
1860
|
+
if (this.webSocketReady.get(app)) {
|
|
1861
|
+
console.log(`Conex\xE3o WebSocket para '${app}' j\xE1 est\xE1 ativa.`);
|
|
1862
|
+
return this.webSocketReady.get(app);
|
|
1823
1863
|
}
|
|
1824
|
-
|
|
1864
|
+
const protocol = this.config.secure ? "wss" : "ws";
|
|
1865
|
+
const eventsParam = subscribedEvents && subscribedEvents.length > 0 ? `&event=${subscribedEvents.join(",")}` : "&subscribeAll=true";
|
|
1866
|
+
const wsUrl = `${protocol}://${encodeURIComponent(
|
|
1867
|
+
this.config.username
|
|
1868
|
+
)}:${encodeURIComponent(this.config.password)}@${this.config.host}:${this.config.port}/ari/events?app=${app}${eventsParam}`;
|
|
1869
|
+
const backoffOptions = {
|
|
1870
|
+
delayFirstAttempt: false,
|
|
1871
|
+
startingDelay: 1e3,
|
|
1872
|
+
timeMultiple: 2,
|
|
1873
|
+
maxDelay: 3e4,
|
|
1874
|
+
numOfAttempts: 10,
|
|
1875
|
+
jitter: "full",
|
|
1876
|
+
retry: (error, attemptNumber) => {
|
|
1877
|
+
console.warn(`Tentativa ${attemptNumber} falhou: ${error.message}`);
|
|
1878
|
+
return Array.from(this.wsClients.values()).some(
|
|
1879
|
+
(wsClient) => !wsClient.isConnected()
|
|
1880
|
+
);
|
|
1881
|
+
}
|
|
1882
|
+
};
|
|
1883
|
+
const webSocketPromise = new Promise(async (resolve, reject) => {
|
|
1825
1884
|
try {
|
|
1826
|
-
if (this.isReconnecting) {
|
|
1827
|
-
console.warn(
|
|
1828
|
-
"J\xE1 est\xE1 tentando reconectar. Ignorando esta tentativa."
|
|
1829
|
-
);
|
|
1885
|
+
if (this.isReconnecting.get(app)) {
|
|
1886
|
+
console.warn(`J\xE1 est\xE1 tentando reconectar para o app '${app}'.`);
|
|
1830
1887
|
return;
|
|
1831
1888
|
}
|
|
1832
|
-
this.isReconnecting
|
|
1833
|
-
const
|
|
1834
|
-
const protocol = this.config.secure ? "wss" : "ws";
|
|
1835
|
-
const wsUrl = `${protocol}://${encodeURIComponent(this.config.username)}:${encodeURIComponent(this.config.password)}@${this.config.host}:${this.config.port}/ari/events?app=${app}${eventsParam}`;
|
|
1836
|
-
const backoffOptions = {
|
|
1837
|
-
delayFirstAttempt: false,
|
|
1838
|
-
startingDelay: 1e3,
|
|
1839
|
-
timeMultiple: 2,
|
|
1840
|
-
maxDelay: 3e4,
|
|
1841
|
-
numOfAttempts: 10,
|
|
1842
|
-
jitter: "full",
|
|
1843
|
-
retry: (error, attemptNumber) => {
|
|
1844
|
-
console.warn(`Tentativa ${attemptNumber} falhou: ${error.message}`);
|
|
1845
|
-
return !this.wsClient?.isConnected();
|
|
1846
|
-
}
|
|
1847
|
-
};
|
|
1848
|
-
if (this.wsClient?.isConnected()) {
|
|
1849
|
-
console.log("WebSocket j\xE1 conectado. Removendo listeners antigos...");
|
|
1850
|
-
this.wsClient.removeAllListeners();
|
|
1851
|
-
this.wsClient.close();
|
|
1852
|
-
}
|
|
1853
|
-
this.wsClient = new WebSocketClient(wsUrl);
|
|
1889
|
+
this.isReconnecting.set(app, true);
|
|
1890
|
+
const wsClient = new WebSocketClient(wsUrl);
|
|
1854
1891
|
await (0, import_exponential_backoff.backOff)(async () => {
|
|
1855
|
-
if (!
|
|
1892
|
+
if (!wsClient) {
|
|
1856
1893
|
throw new Error("WebSocketClient instance is null.");
|
|
1857
1894
|
}
|
|
1858
|
-
await
|
|
1859
|
-
this.integrateWebSocketEvents(app,
|
|
1895
|
+
await wsClient.connect();
|
|
1896
|
+
this.integrateWebSocketEvents(app, wsClient);
|
|
1860
1897
|
console.log(`WebSocket conectado para o app: ${app}`);
|
|
1861
1898
|
await this.ensureAppRegistered(app);
|
|
1862
|
-
this.
|
|
1863
|
-
this.processPendingListeners();
|
|
1899
|
+
this.wsClients.set(app, wsClient);
|
|
1864
1900
|
}, backoffOptions);
|
|
1865
1901
|
resolve();
|
|
1866
|
-
} catch (
|
|
1902
|
+
} catch (error) {
|
|
1867
1903
|
console.error(
|
|
1868
|
-
|
|
1869
|
-
|
|
1904
|
+
`Erro ao conectar o WebSocket para o app '${app}':`,
|
|
1905
|
+
error
|
|
1870
1906
|
);
|
|
1871
|
-
reject(
|
|
1907
|
+
reject(error);
|
|
1872
1908
|
} finally {
|
|
1873
|
-
this.isReconnecting
|
|
1874
|
-
this.webSocketReady = null;
|
|
1909
|
+
this.isReconnecting.delete(app);
|
|
1875
1910
|
}
|
|
1876
1911
|
});
|
|
1877
|
-
|
|
1912
|
+
this.webSocketReady.set(app, webSocketPromise);
|
|
1913
|
+
return webSocketPromise;
|
|
1878
1914
|
}
|
|
1879
1915
|
/**
|
|
1880
1916
|
* Integrates WebSocket events with playback listeners.
|
|
@@ -1946,8 +1982,14 @@ var AriClient = class {
|
|
|
1946
1982
|
*
|
|
1947
1983
|
* @returns {boolean} True if connected, false otherwise.
|
|
1948
1984
|
*/
|
|
1949
|
-
|
|
1950
|
-
return
|
|
1985
|
+
anyWebSocketConnected() {
|
|
1986
|
+
return Array.from(this.wsClients.values()).every(
|
|
1987
|
+
(wsClient) => wsClient.isConnected()
|
|
1988
|
+
);
|
|
1989
|
+
}
|
|
1990
|
+
isWebSocketConnected(app) {
|
|
1991
|
+
const wsClient = this.wsClients.get(app);
|
|
1992
|
+
return wsClient ? wsClient.isConnected() : false;
|
|
1951
1993
|
}
|
|
1952
1994
|
/**
|
|
1953
1995
|
* Closes the WebSocket connection and removes all associated listeners.
|
|
@@ -1959,12 +2001,24 @@ var AriClient = class {
|
|
|
1959
2001
|
*
|
|
1960
2002
|
* @returns {void} This function doesn't return a value.
|
|
1961
2003
|
*/
|
|
1962
|
-
closeWebSocket() {
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
2004
|
+
closeWebSocket(app) {
|
|
2005
|
+
const wsClient = this.wsClients.get(app);
|
|
2006
|
+
if (wsClient) {
|
|
2007
|
+
wsClient.close();
|
|
2008
|
+
this.wsClients.delete(app);
|
|
2009
|
+
console.log(`WebSocket para o app '${app}' foi fechado.`);
|
|
2010
|
+
} else {
|
|
2011
|
+
console.warn(`WebSocket para o app '${app}' n\xE3o encontrado.`);
|
|
1966
2012
|
}
|
|
1967
2013
|
}
|
|
2014
|
+
closeAllWebSockets() {
|
|
2015
|
+
this.wsClients.forEach((wsClient, app) => {
|
|
2016
|
+
wsClient.close();
|
|
2017
|
+
console.log(`WebSocket para o app '${app}' foi fechado.`);
|
|
2018
|
+
});
|
|
2019
|
+
this.wsClients.clear();
|
|
2020
|
+
console.log("Todos os WebSockets foram fechados.");
|
|
2021
|
+
}
|
|
1968
2022
|
/**
|
|
1969
2023
|
* Retrieves a list of active channels from the Asterisk ARI.
|
|
1970
2024
|
*
|