@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/esm/index.js
CHANGED
|
@@ -868,6 +868,7 @@ var ChannelInstance = class extends EventEmitter2 {
|
|
|
868
868
|
this.client = client;
|
|
869
869
|
this.baseClient = baseClient;
|
|
870
870
|
this.channelId = channelId;
|
|
871
|
+
this.id = channelId || `channel-${Date.now()}`;
|
|
871
872
|
this.baseClient.onWebSocketEvent((event) => {
|
|
872
873
|
if (this.isChannelEvent(event) && event.channel?.id === this.channelId) {
|
|
873
874
|
this.emit(event.type, event);
|
|
@@ -875,6 +876,8 @@ var ChannelInstance = class extends EventEmitter2 {
|
|
|
875
876
|
});
|
|
876
877
|
}
|
|
877
878
|
channelData = null;
|
|
879
|
+
id;
|
|
880
|
+
// ID do canal
|
|
878
881
|
/**
|
|
879
882
|
* Verifica se o evento possui a propriedade `channel`.
|
|
880
883
|
* @param event Evento recebido.
|
|
@@ -903,12 +906,6 @@ var ChannelInstance = class extends EventEmitter2 {
|
|
|
903
906
|
super.off(event, callback);
|
|
904
907
|
return this;
|
|
905
908
|
}
|
|
906
|
-
/**
|
|
907
|
-
* Getter para o ID do canal.
|
|
908
|
-
*/
|
|
909
|
-
get id() {
|
|
910
|
-
return this.channelId;
|
|
911
|
-
}
|
|
912
909
|
async answer() {
|
|
913
910
|
await this.baseClient.post(`/channels/${this.id}/answer`);
|
|
914
911
|
}
|
|
@@ -1684,18 +1681,19 @@ var AriClient = class {
|
|
|
1684
1681
|
this.bridges = new Bridges(this.baseClient);
|
|
1685
1682
|
}
|
|
1686
1683
|
eventListeners = /* @__PURE__ */ new Map();
|
|
1687
|
-
|
|
1684
|
+
wsClients = /* @__PURE__ */ new Map();
|
|
1685
|
+
// Map para armazenar conexões por app
|
|
1688
1686
|
baseClient;
|
|
1689
|
-
isReconnecting =
|
|
1690
|
-
|
|
1691
|
-
webSocketReady =
|
|
1692
|
-
//
|
|
1687
|
+
isReconnecting = /* @__PURE__ */ new Map();
|
|
1688
|
+
// Estado de reconexão por app
|
|
1689
|
+
webSocketReady = /* @__PURE__ */ new Map();
|
|
1690
|
+
// Rastreamento do estado de cada conexão
|
|
1693
1691
|
channelInstances = /* @__PURE__ */ new Map();
|
|
1694
1692
|
pendingListeners = [];
|
|
1695
1693
|
processPendingListeners() {
|
|
1696
|
-
if (
|
|
1694
|
+
if (this.wsClients.size === 0) {
|
|
1697
1695
|
console.warn(
|
|
1698
|
-
"
|
|
1696
|
+
"Nenhuma conex\xE3o WebSocket est\xE1 pronta. N\xE3o \xE9 poss\xEDvel processar a fila."
|
|
1699
1697
|
);
|
|
1700
1698
|
return;
|
|
1701
1699
|
}
|
|
@@ -1705,7 +1703,12 @@ var AriClient = class {
|
|
|
1705
1703
|
while (this.pendingListeners.length > 0) {
|
|
1706
1704
|
const { event, callback } = this.pendingListeners.shift();
|
|
1707
1705
|
console.log(`Registrando listener pendente para evento: ${event}`);
|
|
1708
|
-
this.
|
|
1706
|
+
for (const [app, wsClient] of this.wsClients.entries()) {
|
|
1707
|
+
console.log(
|
|
1708
|
+
`Registrando listener no app '${app}' para evento: ${event}`
|
|
1709
|
+
);
|
|
1710
|
+
wsClient.on(event, callback);
|
|
1711
|
+
}
|
|
1709
1712
|
}
|
|
1710
1713
|
}
|
|
1711
1714
|
channels;
|
|
@@ -1721,14 +1724,24 @@ var AriClient = class {
|
|
|
1721
1724
|
* @param callback Callback a ser executado quando o evento for recebido.
|
|
1722
1725
|
*/
|
|
1723
1726
|
onChannelEvent(eventType, callback) {
|
|
1724
|
-
this.
|
|
1727
|
+
if (this.wsClients.size === 0) {
|
|
1728
|
+
console.warn(
|
|
1729
|
+
"Nenhuma conex\xE3o WebSocket est\xE1 ativa. O listener ser\xE1 pendente."
|
|
1730
|
+
);
|
|
1731
|
+
this.pendingListeners.push({ event: eventType, callback });
|
|
1732
|
+
return;
|
|
1733
|
+
}
|
|
1734
|
+
for (const [app, wsClient] of this.wsClients.entries()) {
|
|
1735
|
+
console.log(`Registrando evento '${eventType}' no app '${app}'`);
|
|
1736
|
+
wsClient.on(eventType, callback);
|
|
1737
|
+
}
|
|
1725
1738
|
}
|
|
1726
1739
|
/**
|
|
1727
1740
|
* Registra um listener para eventos globais de WebSocket.
|
|
1728
1741
|
* O channel no evento será automaticamente transformado em uma instância de ChannelInstance.
|
|
1729
1742
|
*/
|
|
1730
1743
|
on(eventType, callback) {
|
|
1731
|
-
console.log(`Registrando listener
|
|
1744
|
+
console.log(`Registrando listener global para evento: ${eventType}`);
|
|
1732
1745
|
const wrappedCallback = (event) => {
|
|
1733
1746
|
if (isChannelEvent(event)) {
|
|
1734
1747
|
const channelId = event.channel.id;
|
|
@@ -1792,70 +1805,84 @@ var AriClient = class {
|
|
|
1792
1805
|
* @returns A Promise that resolves when the WebSocket connection is successfully established and the application is registered.
|
|
1793
1806
|
* @throws Error if the 'app' parameter is not provided, or if connection attempts fail after multiple retries.
|
|
1794
1807
|
*/
|
|
1795
|
-
|
|
1808
|
+
/**
|
|
1809
|
+
* Connects to the ARI WebSocket for one or more applications.
|
|
1810
|
+
* Establishes a WebSocket connection for each app and subscribes to events.
|
|
1811
|
+
*
|
|
1812
|
+
* @param apps - Array of application names to connect to.
|
|
1813
|
+
* @param subscribedEvents - Optional array of events to subscribe to.
|
|
1814
|
+
* If not provided or empty, subscribes to all events.
|
|
1815
|
+
* @returns A Promise that resolves when all connections are established.
|
|
1816
|
+
*/
|
|
1817
|
+
async connectWebSocket(apps, subscribedEvents) {
|
|
1818
|
+
if (!Array.isArray(apps) || apps.length === 0) {
|
|
1819
|
+
throw new Error("\xC9 necess\xE1rio fornecer pelo menos um aplicativo.");
|
|
1820
|
+
}
|
|
1821
|
+
return Promise.all(
|
|
1822
|
+
apps.map((app) => this.connectSingleWebSocket(app, subscribedEvents))
|
|
1823
|
+
);
|
|
1824
|
+
}
|
|
1825
|
+
/**
|
|
1826
|
+
* Establishes a single WebSocket connection for a given app.
|
|
1827
|
+
*/
|
|
1828
|
+
async connectSingleWebSocket(app, subscribedEvents) {
|
|
1796
1829
|
if (!app) {
|
|
1797
|
-
throw new Error(
|
|
1798
|
-
"O par\xE2metro 'app' \xE9 obrigat\xF3rio para conectar ao WebSocket."
|
|
1799
|
-
);
|
|
1830
|
+
throw new Error("O nome do aplicativo \xE9 obrigat\xF3rio.");
|
|
1800
1831
|
}
|
|
1801
|
-
if (this.webSocketReady) {
|
|
1802
|
-
console.log(
|
|
1803
|
-
return this.webSocketReady;
|
|
1832
|
+
if (this.webSocketReady.get(app)) {
|
|
1833
|
+
console.log(`Conex\xE3o WebSocket para '${app}' j\xE1 est\xE1 ativa.`);
|
|
1834
|
+
return this.webSocketReady.get(app);
|
|
1804
1835
|
}
|
|
1805
|
-
|
|
1836
|
+
const protocol = this.config.secure ? "wss" : "ws";
|
|
1837
|
+
const eventsParam = subscribedEvents && subscribedEvents.length > 0 ? `&event=${subscribedEvents.join(",")}` : "&subscribeAll=true";
|
|
1838
|
+
const wsUrl = `${protocol}://${encodeURIComponent(
|
|
1839
|
+
this.config.username
|
|
1840
|
+
)}:${encodeURIComponent(this.config.password)}@${this.config.host}:${this.config.port}/ari/events?app=${app}${eventsParam}`;
|
|
1841
|
+
const backoffOptions = {
|
|
1842
|
+
delayFirstAttempt: false,
|
|
1843
|
+
startingDelay: 1e3,
|
|
1844
|
+
timeMultiple: 2,
|
|
1845
|
+
maxDelay: 3e4,
|
|
1846
|
+
numOfAttempts: 10,
|
|
1847
|
+
jitter: "full",
|
|
1848
|
+
retry: (error, attemptNumber) => {
|
|
1849
|
+
console.warn(`Tentativa ${attemptNumber} falhou: ${error.message}`);
|
|
1850
|
+
return Array.from(this.wsClients.values()).some(
|
|
1851
|
+
(wsClient) => !wsClient.isConnected()
|
|
1852
|
+
);
|
|
1853
|
+
}
|
|
1854
|
+
};
|
|
1855
|
+
const webSocketPromise = new Promise(async (resolve, reject) => {
|
|
1806
1856
|
try {
|
|
1807
|
-
if (this.isReconnecting) {
|
|
1808
|
-
console.warn(
|
|
1809
|
-
"J\xE1 est\xE1 tentando reconectar. Ignorando esta tentativa."
|
|
1810
|
-
);
|
|
1857
|
+
if (this.isReconnecting.get(app)) {
|
|
1858
|
+
console.warn(`J\xE1 est\xE1 tentando reconectar para o app '${app}'.`);
|
|
1811
1859
|
return;
|
|
1812
1860
|
}
|
|
1813
|
-
this.isReconnecting
|
|
1814
|
-
const
|
|
1815
|
-
const protocol = this.config.secure ? "wss" : "ws";
|
|
1816
|
-
const wsUrl = `${protocol}://${encodeURIComponent(this.config.username)}:${encodeURIComponent(this.config.password)}@${this.config.host}:${this.config.port}/ari/events?app=${app}${eventsParam}`;
|
|
1817
|
-
const backoffOptions = {
|
|
1818
|
-
delayFirstAttempt: false,
|
|
1819
|
-
startingDelay: 1e3,
|
|
1820
|
-
timeMultiple: 2,
|
|
1821
|
-
maxDelay: 3e4,
|
|
1822
|
-
numOfAttempts: 10,
|
|
1823
|
-
jitter: "full",
|
|
1824
|
-
retry: (error, attemptNumber) => {
|
|
1825
|
-
console.warn(`Tentativa ${attemptNumber} falhou: ${error.message}`);
|
|
1826
|
-
return !this.wsClient?.isConnected();
|
|
1827
|
-
}
|
|
1828
|
-
};
|
|
1829
|
-
if (this.wsClient?.isConnected()) {
|
|
1830
|
-
console.log("WebSocket j\xE1 conectado. Removendo listeners antigos...");
|
|
1831
|
-
this.wsClient.removeAllListeners();
|
|
1832
|
-
this.wsClient.close();
|
|
1833
|
-
}
|
|
1834
|
-
this.wsClient = new WebSocketClient(wsUrl);
|
|
1861
|
+
this.isReconnecting.set(app, true);
|
|
1862
|
+
const wsClient = new WebSocketClient(wsUrl);
|
|
1835
1863
|
await (0, import_exponential_backoff.backOff)(async () => {
|
|
1836
|
-
if (!
|
|
1864
|
+
if (!wsClient) {
|
|
1837
1865
|
throw new Error("WebSocketClient instance is null.");
|
|
1838
1866
|
}
|
|
1839
|
-
await
|
|
1840
|
-
this.integrateWebSocketEvents(app,
|
|
1867
|
+
await wsClient.connect();
|
|
1868
|
+
this.integrateWebSocketEvents(app, wsClient);
|
|
1841
1869
|
console.log(`WebSocket conectado para o app: ${app}`);
|
|
1842
1870
|
await this.ensureAppRegistered(app);
|
|
1843
|
-
this.
|
|
1844
|
-
this.processPendingListeners();
|
|
1871
|
+
this.wsClients.set(app, wsClient);
|
|
1845
1872
|
}, backoffOptions);
|
|
1846
1873
|
resolve();
|
|
1847
|
-
} catch (
|
|
1874
|
+
} catch (error) {
|
|
1848
1875
|
console.error(
|
|
1849
|
-
|
|
1850
|
-
|
|
1876
|
+
`Erro ao conectar o WebSocket para o app '${app}':`,
|
|
1877
|
+
error
|
|
1851
1878
|
);
|
|
1852
|
-
reject(
|
|
1879
|
+
reject(error);
|
|
1853
1880
|
} finally {
|
|
1854
|
-
this.isReconnecting
|
|
1855
|
-
this.webSocketReady = null;
|
|
1881
|
+
this.isReconnecting.delete(app);
|
|
1856
1882
|
}
|
|
1857
1883
|
});
|
|
1858
|
-
|
|
1884
|
+
this.webSocketReady.set(app, webSocketPromise);
|
|
1885
|
+
return webSocketPromise;
|
|
1859
1886
|
}
|
|
1860
1887
|
/**
|
|
1861
1888
|
* Integrates WebSocket events with playback listeners.
|
|
@@ -1927,8 +1954,14 @@ var AriClient = class {
|
|
|
1927
1954
|
*
|
|
1928
1955
|
* @returns {boolean} True if connected, false otherwise.
|
|
1929
1956
|
*/
|
|
1930
|
-
|
|
1931
|
-
return
|
|
1957
|
+
anyWebSocketConnected() {
|
|
1958
|
+
return Array.from(this.wsClients.values()).every(
|
|
1959
|
+
(wsClient) => wsClient.isConnected()
|
|
1960
|
+
);
|
|
1961
|
+
}
|
|
1962
|
+
isWebSocketConnected(app) {
|
|
1963
|
+
const wsClient = this.wsClients.get(app);
|
|
1964
|
+
return wsClient ? wsClient.isConnected() : false;
|
|
1932
1965
|
}
|
|
1933
1966
|
/**
|
|
1934
1967
|
* Closes the WebSocket connection and removes all associated listeners.
|
|
@@ -1940,12 +1973,24 @@ var AriClient = class {
|
|
|
1940
1973
|
*
|
|
1941
1974
|
* @returns {void} This function doesn't return a value.
|
|
1942
1975
|
*/
|
|
1943
|
-
closeWebSocket() {
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1976
|
+
closeWebSocket(app) {
|
|
1977
|
+
const wsClient = this.wsClients.get(app);
|
|
1978
|
+
if (wsClient) {
|
|
1979
|
+
wsClient.close();
|
|
1980
|
+
this.wsClients.delete(app);
|
|
1981
|
+
console.log(`WebSocket para o app '${app}' foi fechado.`);
|
|
1982
|
+
} else {
|
|
1983
|
+
console.warn(`WebSocket para o app '${app}' n\xE3o encontrado.`);
|
|
1947
1984
|
}
|
|
1948
1985
|
}
|
|
1986
|
+
closeAllWebSockets() {
|
|
1987
|
+
this.wsClients.forEach((wsClient, app) => {
|
|
1988
|
+
wsClient.close();
|
|
1989
|
+
console.log(`WebSocket para o app '${app}' foi fechado.`);
|
|
1990
|
+
});
|
|
1991
|
+
this.wsClients.clear();
|
|
1992
|
+
console.log("Todos os WebSockets foram fechados.");
|
|
1993
|
+
}
|
|
1949
1994
|
/**
|
|
1950
1995
|
* Retrieves a list of active channels from the Asterisk ARI.
|
|
1951
1996
|
*
|