@ipcom/asterisk-ari 0.0.102 → 0.0.104
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 +123 -81
- package/dist/cjs/index.cjs.map +3 -3
- package/dist/esm/index.js +123 -81
- package/dist/esm/index.js.map +3 -3
- package/dist/types/ari-client/ariClient.d.ts +5 -3
- package/dist/types/ari-client/ariClient.d.ts.map +1 -1
- package/dist/types/ari-client/interfaces/events.types.d.ts +31 -1
- package/dist/types/ari-client/interfaces/events.types.d.ts.map +1 -1
- package/dist/types/ari-client/resources/channels.d.ts +7 -2
- package/dist/types/ari-client/resources/channels.d.ts.map +1 -1
- package/dist/types/ari-client/resources/playbacks.d.ts +7 -2
- package/dist/types/ari-client/resources/playbacks.d.ts.map +1 -1
- package/dist/types/ari-client/websocketClient.d.ts +4 -2
- package/dist/types/ari-client/websocketClient.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/esm/index.js
CHANGED
|
@@ -910,38 +910,41 @@ function isChannelEvent(event, channelId) {
|
|
|
910
910
|
// src/ari-client/resources/channels.ts
|
|
911
911
|
var ChannelInstance = class extends EventEmitter2 {
|
|
912
912
|
// ID do canal
|
|
913
|
-
constructor(client, baseClient, channelId = `channel-${Date.now()}
|
|
913
|
+
constructor(client, baseClient, channelId = `channel-${Date.now()}`, app) {
|
|
914
914
|
super();
|
|
915
915
|
this.client = client;
|
|
916
916
|
this.baseClient = baseClient;
|
|
917
917
|
this.channelId = channelId;
|
|
918
|
+
this.app = app;
|
|
918
919
|
this.id = channelId || `channel-${Date.now()}`;
|
|
919
920
|
const wsClients = this.client.getWebSocketClients();
|
|
920
|
-
const wsClient =
|
|
921
|
-
(client2) => client2.isConnected()
|
|
922
|
-
);
|
|
921
|
+
const wsClient = wsClients.get(this.app);
|
|
923
922
|
if (!wsClient) {
|
|
924
923
|
throw new Error(
|
|
925
924
|
`Nenhum WebSocket conectado dispon\xEDvel para o canal: ${this.id}`
|
|
926
925
|
);
|
|
927
926
|
}
|
|
928
|
-
|
|
929
|
-
|
|
927
|
+
wsClient.addScopedMessageListener(
|
|
928
|
+
this.id,
|
|
929
|
+
this.app,
|
|
930
|
+
(event) => {
|
|
930
931
|
if (isChannelEvent(event, this.id)) {
|
|
931
932
|
const channelEventType = event.type;
|
|
932
933
|
this.emit(channelEventType, event);
|
|
933
934
|
}
|
|
934
|
-
}
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
935
|
+
}
|
|
936
|
+
);
|
|
937
|
+
this.on("removeListener", (eventName) => {
|
|
938
|
+
if (this.eventNames().length === 0 || this.listenerCount(eventName) === 0) {
|
|
939
|
+
wsClient.removeScopedMessageListeners(this.id, this.app);
|
|
940
|
+
console.log(
|
|
941
|
+
`Listeners escopados removidos para canal '${this.id}' no app '${this.app}'.`
|
|
942
|
+
);
|
|
943
|
+
}
|
|
944
|
+
});
|
|
942
945
|
this.on("removeListener", (eventName) => {
|
|
943
946
|
if (this.eventNames().length === 0 || this.listenerCount(eventName) === 0) {
|
|
944
|
-
wsClient.removeScopedMessageListeners(this.id);
|
|
947
|
+
wsClient.removeScopedMessageListeners(this.id, this.app);
|
|
945
948
|
console.log(`Listeners escopados removidos para canal '${this.id}'.`);
|
|
946
949
|
}
|
|
947
950
|
});
|
|
@@ -977,14 +980,14 @@ var ChannelInstance = class extends EventEmitter2 {
|
|
|
977
980
|
console.log(`Recebido evento '${event}' para canal '${this.id}'`);
|
|
978
981
|
this.emit(event, webSocketEvent);
|
|
979
982
|
callback(webSocketEvent);
|
|
980
|
-
wsClient.removeScopedMessageListeners(this.id);
|
|
983
|
+
wsClient.removeScopedMessageListeners(this.id, this.app);
|
|
981
984
|
console.log(
|
|
982
985
|
`Listeners escopados para canal '${this.id}' foram removidos.`
|
|
983
986
|
);
|
|
984
987
|
}
|
|
985
988
|
};
|
|
986
989
|
try {
|
|
987
|
-
wsClient.addScopedMessageListener(this.id, globalListener);
|
|
990
|
+
wsClient.addScopedMessageListener(this.id, this.app, globalListener);
|
|
988
991
|
} catch (error) {
|
|
989
992
|
console.error(
|
|
990
993
|
`Erro ao adicionar listener escopado em 'once' para canal '${this.id}':`,
|
|
@@ -1188,8 +1191,13 @@ var Channels = class extends EventEmitter2 {
|
|
|
1188
1191
|
this.baseClient = baseClient;
|
|
1189
1192
|
this.client = client;
|
|
1190
1193
|
}
|
|
1191
|
-
Channel(
|
|
1192
|
-
|
|
1194
|
+
Channel({ id, app }) {
|
|
1195
|
+
if (!app) {
|
|
1196
|
+
throw new Error(
|
|
1197
|
+
"O nome do aplicativo (app) \xE9 obrigat\xF3rio para criar um Channel."
|
|
1198
|
+
);
|
|
1199
|
+
}
|
|
1200
|
+
return new ChannelInstance(this.client, this.baseClient, id, app);
|
|
1193
1201
|
}
|
|
1194
1202
|
/**
|
|
1195
1203
|
* Origina um canal físico diretamente, sem uma instância de `ChannelInstance`.
|
|
@@ -1419,11 +1427,12 @@ var Endpoints = class {
|
|
|
1419
1427
|
import { EventEmitter as EventEmitter3 } from "events";
|
|
1420
1428
|
var PlaybackInstance = class extends EventEmitter3 {
|
|
1421
1429
|
// Garantimos que o ID esteja disponível
|
|
1422
|
-
constructor(client, baseClient, playbackId = `playback-${Date.now()}
|
|
1430
|
+
constructor(client, baseClient, playbackId = `playback-${Date.now()}`, app) {
|
|
1423
1431
|
super();
|
|
1424
1432
|
this.client = client;
|
|
1425
1433
|
this.baseClient = baseClient;
|
|
1426
1434
|
this.playbackId = playbackId;
|
|
1435
|
+
this.app = app;
|
|
1427
1436
|
this.id = playbackId || `playback-${Date.now()}`;
|
|
1428
1437
|
const wsClients = this.client.getWebSocketClients();
|
|
1429
1438
|
const wsClient = Array.from(wsClients.values()).find(
|
|
@@ -1435,12 +1444,16 @@ var PlaybackInstance = class extends EventEmitter3 {
|
|
|
1435
1444
|
);
|
|
1436
1445
|
}
|
|
1437
1446
|
try {
|
|
1438
|
-
wsClient.addScopedMessageListener(
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1447
|
+
wsClient.addScopedMessageListener(
|
|
1448
|
+
this.id,
|
|
1449
|
+
this.app,
|
|
1450
|
+
(event) => {
|
|
1451
|
+
if (isPlaybackEvent(event, this.id)) {
|
|
1452
|
+
const playbackEventType = event.type;
|
|
1453
|
+
this.emit(playbackEventType, event);
|
|
1454
|
+
}
|
|
1442
1455
|
}
|
|
1443
|
-
|
|
1456
|
+
);
|
|
1444
1457
|
} catch (error) {
|
|
1445
1458
|
console.error(
|
|
1446
1459
|
`Erro ao adicionar listener escopado para playback '${this.id}':`,
|
|
@@ -1450,7 +1463,7 @@ var PlaybackInstance = class extends EventEmitter3 {
|
|
|
1450
1463
|
}
|
|
1451
1464
|
this.on("removeListener", (eventName) => {
|
|
1452
1465
|
if (this.eventNames().length === 0 || this.listenerCount(eventName) === 0) {
|
|
1453
|
-
wsClient.removeScopedMessageListeners(this.id);
|
|
1466
|
+
wsClient.removeScopedMessageListeners(this.id, this.app);
|
|
1454
1467
|
console.log(
|
|
1455
1468
|
`Listeners escopados removidos para playback '${this.id}'.`
|
|
1456
1469
|
);
|
|
@@ -1491,14 +1504,14 @@ var PlaybackInstance = class extends EventEmitter3 {
|
|
|
1491
1504
|
console.log(`Recebido evento '${event}' para playback '${this.id}'`);
|
|
1492
1505
|
this.emit(event, webSocketEvent);
|
|
1493
1506
|
callback(webSocketEvent);
|
|
1494
|
-
wsClient.removeScopedMessageListeners(this.id);
|
|
1507
|
+
wsClient.removeScopedMessageListeners(this.id, this.app);
|
|
1495
1508
|
console.log(
|
|
1496
1509
|
`Listeners escopados para playback '${this.id}' foram removidos.`
|
|
1497
1510
|
);
|
|
1498
1511
|
}
|
|
1499
1512
|
};
|
|
1500
1513
|
try {
|
|
1501
|
-
wsClient.addScopedMessageListener(this.id, globalListener);
|
|
1514
|
+
wsClient.addScopedMessageListener(this.id, this.app, globalListener);
|
|
1502
1515
|
} catch (error) {
|
|
1503
1516
|
console.error(
|
|
1504
1517
|
`Erro ao adicionar listener escopado em 'once' para playback '${this.id}':`,
|
|
@@ -1576,9 +1589,14 @@ var Playbacks = class extends EventEmitter3 {
|
|
|
1576
1589
|
/**
|
|
1577
1590
|
* Inicializa uma nova instância de `PlaybackInstance`.
|
|
1578
1591
|
*/
|
|
1579
|
-
Playback(
|
|
1580
|
-
|
|
1581
|
-
|
|
1592
|
+
Playback({ id, app }) {
|
|
1593
|
+
if (!app) {
|
|
1594
|
+
throw new Error(
|
|
1595
|
+
"O nome do aplicativo (app) \xE9 obrigat\xF3rio para criar um Channel."
|
|
1596
|
+
);
|
|
1597
|
+
}
|
|
1598
|
+
const playbackId = id || `playback-${Date.now()}`;
|
|
1599
|
+
return new PlaybackInstance(this.client, this.baseClient, playbackId, app);
|
|
1582
1600
|
}
|
|
1583
1601
|
/**
|
|
1584
1602
|
* Obtém os clientes WebSocket disponíveis.
|
|
@@ -1841,28 +1859,36 @@ var WebSocketClient = class extends EventEmitter4 {
|
|
|
1841
1859
|
/**
|
|
1842
1860
|
* Adiciona um listener escopado ao evento "message".
|
|
1843
1861
|
* @param instanceId - Identificador único da instância que está registrando o listener.
|
|
1862
|
+
* @param app
|
|
1844
1863
|
* @param callback - Função de callback para o evento.
|
|
1845
1864
|
*/
|
|
1846
|
-
addScopedMessageListener(instanceId, callback) {
|
|
1847
|
-
|
|
1865
|
+
addScopedMessageListener(instanceId, app, callback) {
|
|
1866
|
+
const key = `${app}:${instanceId}`;
|
|
1867
|
+
if (this.scopedListeners.has(key)) {
|
|
1848
1868
|
console.warn(
|
|
1849
|
-
`Listener escopado para a inst\xE2ncia '${
|
|
1869
|
+
`Listener escopado para a inst\xE2ncia '${key}' j\xE1 existe. Ignorando.`
|
|
1850
1870
|
);
|
|
1851
1871
|
return;
|
|
1852
1872
|
}
|
|
1853
1873
|
const scopedListener = (data) => {
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1874
|
+
try {
|
|
1875
|
+
if (data.application === app && (data.type.startsWith("Channel") && "channel" in data && data.channel?.id === instanceId || data.type.startsWith("Playback") && "playbackId" in data && data.playbackId === instanceId)) {
|
|
1876
|
+
console.log(
|
|
1877
|
+
`Listener escopado ativado para inst\xE2ncia '${instanceId}' no app '${app}'.`
|
|
1878
|
+
);
|
|
1879
|
+
callback(data);
|
|
1880
|
+
}
|
|
1881
|
+
} catch (error) {
|
|
1882
|
+
console.error(
|
|
1883
|
+
`Erro no listener escopado para inst\xE2ncia '${instanceId}' no app '${app}':`,
|
|
1884
|
+
error
|
|
1858
1885
|
);
|
|
1859
|
-
callback(data);
|
|
1860
1886
|
}
|
|
1861
1887
|
};
|
|
1862
|
-
this.scopedListeners.set(
|
|
1888
|
+
this.scopedListeners.set(key, scopedListener);
|
|
1863
1889
|
this.on("message", scopedListener);
|
|
1864
1890
|
console.log(
|
|
1865
|
-
`Listener escopado adicionado para a inst\xE2ncia '${instanceId}'. Total de listeners: ${this.listenerCount(
|
|
1891
|
+
`Listener escopado adicionado para a inst\xE2ncia '${instanceId}' no app '${app}'. Total de listeners: ${this.listenerCount(
|
|
1866
1892
|
"message"
|
|
1867
1893
|
)}`
|
|
1868
1894
|
);
|
|
@@ -1870,23 +1896,25 @@ var WebSocketClient = class extends EventEmitter4 {
|
|
|
1870
1896
|
/**
|
|
1871
1897
|
* Remove todos os listeners associados a uma instância específica.
|
|
1872
1898
|
* @param instanceId - Identificador da instância cujos listeners serão removidos.
|
|
1899
|
+
* @param app
|
|
1873
1900
|
*/
|
|
1874
|
-
removeScopedMessageListeners(instanceId) {
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
);
|
|
1901
|
+
removeScopedMessageListeners(instanceId, app) {
|
|
1902
|
+
const key = `${app}:${instanceId}`;
|
|
1903
|
+
if (!this.scopedListeners.has(key)) {
|
|
1904
|
+
console.warn(`Nenhum listener encontrado para a inst\xE2ncia '${key}'.`);
|
|
1879
1905
|
return;
|
|
1880
1906
|
}
|
|
1881
|
-
const scopedListener = this.scopedListeners.get(
|
|
1907
|
+
const scopedListener = this.scopedListeners.get(key);
|
|
1882
1908
|
if (scopedListener) {
|
|
1883
1909
|
this.off("message", scopedListener);
|
|
1884
|
-
this.scopedListeners.delete(
|
|
1910
|
+
this.scopedListeners.delete(key);
|
|
1885
1911
|
console.log(
|
|
1886
|
-
`Listeners removidos para a inst\xE2ncia '${
|
|
1912
|
+
`Listeners removidos para a inst\xE2ncia '${key}'. Total de listeners restantes: ${this.listenerCount(
|
|
1887
1913
|
"message"
|
|
1888
1914
|
)}`
|
|
1889
1915
|
);
|
|
1916
|
+
} else {
|
|
1917
|
+
console.warn(`Listener j\xE1 foi removido para a inst\xE2ncia '${key}'.`);
|
|
1890
1918
|
}
|
|
1891
1919
|
}
|
|
1892
1920
|
/**
|
|
@@ -1896,13 +1924,14 @@ var WebSocketClient = class extends EventEmitter4 {
|
|
|
1896
1924
|
handleMessage(rawData) {
|
|
1897
1925
|
try {
|
|
1898
1926
|
const decodedData = JSON.parse(rawData.toString());
|
|
1899
|
-
if (decodedData?.type) {
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
this.emit("message", decodedData);
|
|
1903
|
-
}
|
|
1927
|
+
if (decodedData?.type && decodedData?.application) {
|
|
1928
|
+
console.log({ handleMessage: decodedData });
|
|
1929
|
+
this.emit(decodedData.application, decodedData);
|
|
1904
1930
|
} else {
|
|
1905
|
-
console.warn(
|
|
1931
|
+
console.warn(
|
|
1932
|
+
"Mensagem recebida sem tipo ou aplica\xE7\xE3o v\xE1lida:",
|
|
1933
|
+
decodedData
|
|
1934
|
+
);
|
|
1906
1935
|
}
|
|
1907
1936
|
} catch (err) {
|
|
1908
1937
|
console.error("Erro ao decodificar mensagem do WebSocket:", err);
|
|
@@ -2012,14 +2041,18 @@ var AriClient = class {
|
|
|
2012
2041
|
* Registra listeners globais para eventos de WebSocket.
|
|
2013
2042
|
*/
|
|
2014
2043
|
on(eventType, callback, app) {
|
|
2044
|
+
if (!app) {
|
|
2045
|
+
throw new Error(
|
|
2046
|
+
"O nome do app \xE9 obrigat\xF3rio para registrar um listener de evento."
|
|
2047
|
+
);
|
|
2048
|
+
}
|
|
2015
2049
|
console.log(
|
|
2016
|
-
|
|
2050
|
+
`Registrando listener para evento '${eventType}' no app '${app}'.`
|
|
2017
2051
|
);
|
|
2018
|
-
|
|
2019
|
-
const callbackKey = app ? `${eventType}-${app}` : eventType;
|
|
2052
|
+
const callbackKey = `${eventType}-${app}`;
|
|
2020
2053
|
if (this.eventListeners.has(callbackKey)) {
|
|
2021
2054
|
console.log(
|
|
2022
|
-
`Listener para evento '${eventType}' j\xE1 est\xE1 registrado
|
|
2055
|
+
`Listener para evento '${eventType}' j\xE1 est\xE1 registrado no app '${app}'. Ignorando duplicata.`
|
|
2023
2056
|
);
|
|
2024
2057
|
return;
|
|
2025
2058
|
}
|
|
@@ -2028,7 +2061,7 @@ var AriClient = class {
|
|
|
2028
2061
|
const channelId = event.channel.id;
|
|
2029
2062
|
if (channelId) {
|
|
2030
2063
|
if (!this.channelInstances.has(channelId)) {
|
|
2031
|
-
const channelInstance = this.createChannelInstance(channelId);
|
|
2064
|
+
const channelInstance = this.createChannelInstance(channelId, app);
|
|
2032
2065
|
this.channelInstances.set(channelId, channelInstance);
|
|
2033
2066
|
}
|
|
2034
2067
|
event.instanceChannel = this.channelInstances.get(channelId);
|
|
@@ -2037,19 +2070,12 @@ var AriClient = class {
|
|
|
2037
2070
|
}
|
|
2038
2071
|
callback(event);
|
|
2039
2072
|
};
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
wsClient.on(eventType, wrappedCallback);
|
|
2044
|
-
this.eventListeners.set(callbackKey, wrappedCallback);
|
|
2045
|
-
} else {
|
|
2046
|
-
console.warn(`WebSocket para o app '${app}' n\xE3o est\xE1 conectado.`);
|
|
2047
|
-
}
|
|
2048
|
-
} else {
|
|
2049
|
-
for (const [_app, wsClient] of this.wsClients.entries()) {
|
|
2050
|
-
wsClient.on(eventType, wrappedCallback);
|
|
2051
|
-
}
|
|
2073
|
+
const wsClient = this.wsClients.get(app);
|
|
2074
|
+
if (wsClient) {
|
|
2075
|
+
wsClient.on(`${app}:${eventType}`, wrappedCallback);
|
|
2052
2076
|
this.eventListeners.set(callbackKey, wrappedCallback);
|
|
2077
|
+
} else {
|
|
2078
|
+
console.warn(`WebSocket para o app '${app}' n\xE3o est\xE1 conectado.`);
|
|
2053
2079
|
}
|
|
2054
2080
|
}
|
|
2055
2081
|
removeListener(eventType, app) {
|
|
@@ -2092,17 +2118,20 @@ var AriClient = class {
|
|
|
2092
2118
|
return data?.channel?.id !== void 0;
|
|
2093
2119
|
}
|
|
2094
2120
|
// Método para criar uma instância de ChannelInstance
|
|
2095
|
-
createChannelInstance(channelId) {
|
|
2096
|
-
return this.channels.Channel(
|
|
2121
|
+
createChannelInstance(channelId, app) {
|
|
2122
|
+
return this.channels.Channel({
|
|
2123
|
+
id: channelId,
|
|
2124
|
+
app
|
|
2125
|
+
});
|
|
2097
2126
|
}
|
|
2098
|
-
handleWebSocketEvent(event) {
|
|
2127
|
+
handleWebSocketEvent(event, app) {
|
|
2099
2128
|
console.log("Evento recebido no WebSocket:", event.type, event);
|
|
2100
2129
|
const { type, ...data } = event;
|
|
2101
2130
|
if (this.hasChannel(data)) {
|
|
2102
2131
|
const channelId = data.channel.id;
|
|
2103
2132
|
if (channelId) {
|
|
2104
2133
|
if (!this.channelInstances.has(channelId)) {
|
|
2105
|
-
const channelInstance2 = this.createChannelInstance(channelId);
|
|
2134
|
+
const channelInstance2 = this.createChannelInstance(channelId, app);
|
|
2106
2135
|
this.channelInstances.set(channelId, channelInstance2);
|
|
2107
2136
|
}
|
|
2108
2137
|
const channelInstance = this.channelInstances.get(channelId);
|
|
@@ -2140,8 +2169,9 @@ var AriClient = class {
|
|
|
2140
2169
|
if (!Array.isArray(apps) || apps.length === 0) {
|
|
2141
2170
|
throw new Error("\xC9 necess\xE1rio fornecer pelo menos um aplicativo.");
|
|
2142
2171
|
}
|
|
2172
|
+
const uniqueApps = [...new Set(apps)];
|
|
2143
2173
|
return Promise.all(
|
|
2144
|
-
|
|
2174
|
+
uniqueApps.map(async (app) => {
|
|
2145
2175
|
if (this.wsClients.has(app)) {
|
|
2146
2176
|
console.log(`Conex\xE3o WebSocket para '${app}' j\xE1 existe. Ignorando.`);
|
|
2147
2177
|
return;
|
|
@@ -2331,19 +2361,31 @@ var AriClient = class {
|
|
|
2331
2361
|
* Inicializa uma nova instância de `ChannelInstance` para manipular canais localmente.
|
|
2332
2362
|
*
|
|
2333
2363
|
* @param channelId - O ID do canal, se disponível. Caso contrário, a instância será para um canal ainda não criado.
|
|
2364
|
+
* @param app
|
|
2334
2365
|
* @returns Uma instância de `ChannelInstance` vinculada ao cliente atual.
|
|
2335
2366
|
*/
|
|
2336
|
-
Channel(channelId) {
|
|
2337
|
-
|
|
2367
|
+
Channel(channelId, app) {
|
|
2368
|
+
if (!app) {
|
|
2369
|
+
throw new Error(
|
|
2370
|
+
"O nome do aplicativo (app) \xE9 obrigat\xF3rio para criar um Channel."
|
|
2371
|
+
);
|
|
2372
|
+
}
|
|
2373
|
+
return this.channels.Channel({ id: channelId, app });
|
|
2338
2374
|
}
|
|
2339
2375
|
/**
|
|
2340
2376
|
* Inicializa uma nova instância de `PlaybackInstance` para manipular playbacks.
|
|
2341
2377
|
*
|
|
2342
2378
|
* @param playbackId - O ID do playback, se disponível. Caso contrário, a instância será para um playback ainda não inicializado.
|
|
2379
|
+
* @param app
|
|
2343
2380
|
* @returns Uma instância de `PlaybackInstance` vinculada ao cliente atual.
|
|
2344
2381
|
*/
|
|
2345
|
-
Playback(playbackId) {
|
|
2346
|
-
|
|
2382
|
+
Playback(playbackId, app) {
|
|
2383
|
+
if (!app) {
|
|
2384
|
+
throw new Error(
|
|
2385
|
+
"O nome do aplicativo (app) \xE9 obrigat\xF3rio para criar um Channel."
|
|
2386
|
+
);
|
|
2387
|
+
}
|
|
2388
|
+
return this.playbacks.Playback({ id: playbackId, app });
|
|
2347
2389
|
}
|
|
2348
2390
|
};
|
|
2349
2391
|
export {
|