sinch-rtc
Version:
RTC JavaScript/Web SDK
253 lines • 12.1 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DefaultSinchClient = void 0;
const calling_1 = require("./calling");
const models_1 = require("./models");
const api_1 = require("./ocra/api");
const InstanceController_1 = require("./instance/InstanceController");
const fsm_1 = require("./session/fsm");
const push_1 = require("./push");
const ClientEventFanout_1 = require("./calling/listeners/ClientEventFanout");
const CallReporter_1 = require("./calling/reporting/CallReporter");
const ApiClient_1 = require("./ocra/ApiClient");
const utils_1 = require("./utils");
const Features_1 = require("./features/Features");
const StorageFactory_1 = require("./storage/StorageFactory");
const IceServer_1 = require("./rtc/IceServer");
class DefaultSinchClient {
/**
* @param config -
* config.applicationKey - application unique key from Sinch portal
* config.userId - userId for whom instance is created
* [config.ttl] TODO: TTL param for setting lifetime of Ocra instance
*/
constructor(config) {
this.ServiceWorkerName = "sw.js";
this.isClientStarted = false;
this.useRelayIceCandidatesOnly = false;
this.isUsingManagedPush = false;
this.processExternalPushNotification = (json) => {
const payload = {
sinch: json,
name: "ForSmokeTests",
};
this.relayRemotePushNotification(payload);
};
this.onPush = (message) => {
this.relayRemotePushNotification(message.data);
};
this.clientEvent = new ClientEventFanout_1.ClientEventFanout(this);
this.features = Features_1.FeaturesFactory.create(StorageFactory_1.StorageFactory.createFeatureStorage());
if (!config || !config.applicationKey) {
throw new Error("Parameter appKey is required");
}
this.applicationKey = config.applicationKey;
this.userId = config.userId;
this.callerIdentifier = config.callerIdentifier;
this.apiClient = ApiClient_1.ApiClientFactory.create(new api_1.Configuration({
basePath: this.getBaseUrl(config.baseUrl),
fetchApi: config.fetchApi,
}));
this.instanceController = new InstanceController_1.InstanceController(this.applicationKey, this.userId, this.clientEvent, this.apiClient);
this.pushService = push_1.PushFactory.createPushService(this.userId, this.apiClient);
this.defaultCallClient = calling_1.CallClientFactory.create(this.userId, this.applicationKey, config.mediaManager);
this.onStartedAction = new Array();
this.addTurnListener = (0, utils_1.pipe)(IceServer_1.onTurnFeatureFlagChanged, this.features.addListener.bind(this.features));
}
set pushNotificationDisplayName(displayName) {
if (displayName && displayName.length > 255)
throw new fsm_1.ArgumentError("displayName must not exceed 255 bytes", (0, utils_1.nameof)(displayName));
this.pushService.pushNotificationDisplayName = displayName;
}
get pushNotificationDisplayName() {
return this.pushService.pushNotificationDisplayName;
}
setUseRelayIceCandidatesOnly(useRelayIceCandidatesOnly) {
this.useRelayIceCandidatesOnly = useRelayIceCandidatesOnly;
}
getBaseUrl(url) {
return ((!this.isUrl(url) ? "https://" : "") + url + DefaultSinchClient.OCRA_PATH);
}
isUrl(urlOrHost) {
return urlOrHost.startsWith("http://") || urlOrHost.startsWith("https://");
}
start(instanceConfig) {
return __awaiter(this, void 0, void 0, function* () {
try {
this.started(yield this.instanceController.start(), instanceConfig);
}
catch (ex) {
this.isClientStarted = false;
console.error(ex);
this.failed("Unable to create instance!");
}
});
}
setSupportManagedPush(serviceWorker) {
return __awaiter(this, void 0, void 0, function* () {
this.instanceController.toggleCapability(models_1.Capability.PushV4, true);
this.isUsingManagedPush = true;
this.pushWorker = push_1.PushFactory.createPushWorker(serviceWorker !== null && serviceWorker !== void 0 ? serviceWorker : this.ServiceWorkerName, this.pushService);
yield this.pushWorker.register();
this.pushWorker.addEventListener(this.onPush);
});
}
disableManagedPushSupport() {
return __awaiter(this, void 0, void 0, function* () {
var _a;
this.instanceController.toggleCapability(models_1.Capability.PushV4, false);
this.isUsingManagedPush = false;
yield ((_a = this.pushWorker) === null || _a === void 0 ? void 0 : _a.unregister());
this.pushWorker = undefined;
});
}
failed(reason) {
return __awaiter(this, void 0, void 0, function* () {
this.clientEvent.onEvent({ eventType: "failed", context: reason });
});
}
setupPush(instance, applicationServerKey) {
return __awaiter(this, void 0, void 0, function* () {
if (!applicationServerKey)
throw new fsm_1.InvalidOperationError("Missing public VAPID key");
if (this.pushWorker) {
// todo: this key should be populated from the instanceConfig once the push backend is ready, for now fallback on hardcoded.
yield this.pushWorker.start(applicationServerKey, instance);
}
});
}
createAndSetUpCallReporter(instance) {
return new CallReporter_1.CallReporter(this.userId, instance, this.apiClient);
}
started(instance, config) {
return __awaiter(this, void 0, void 0, function* () {
var _a;
try {
if (this.instanceController.authentication) {
const instanceConfig = config !== null && config !== void 0 ? config : (yield this.apiClient.getConfig({
instanceId: instance.id,
userId: this.userId,
}));
this.instanceConfigJson = JSON.stringify(instanceConfig);
this.setupConfigCheck(instance, instanceConfig);
this.instanceController.setUpdateInstanceTtlWindow(instanceConfig.updateInstanceTtlWindowDays);
this.apiClient.setUpdateInstanceTtlWindow(instanceConfig.updateInstanceTtlWindowDays);
yield this.instanceController.prolongInstanceIfNeeded();
this.addTurnListener(this.instanceController);
const fetchIceServers = (0, IceServer_1.createIceServerFetcher)(this.apiClient, this.userId, instance.id);
this.features.setUserInstance(this.userId, instance.id, this.applicationKey);
const callReporter = this.createAndSetUpCallReporter(instance);
if (this.features.shouldRefresh()) {
yield this.features.refresh(this.apiClient);
}
if (this.isUsingManagedPush) {
yield this.setupPush(instance, (_a = instanceConfig.pushConfig) === null || _a === void 0 ? void 0 : _a.w3cApplicationServerKey);
}
this.defaultCallClient.init(this, instanceConfig.rtcProfile, instanceConfig.rtcConfig, fetchIceServers, callReporter, this.pushService, this.useRelayIceCandidatesOnly, this.features, instance.id, this.callerIdentifier);
this.isClientStarted = true;
this.onStartedAction.splice(0).forEach((a) => a());
this.clientEvent.onEvent({ eventType: "started" });
}
}
catch (error) {
this.failed(error).catch(() => {
console.error(error);
});
}
});
}
setupConfigCheck(instance, instanceConfig) {
var _a, _b;
const configUpdater = () => __awaiter(this, void 0, void 0, function* () {
var _a;
const newInstanceConfig = yield this.apiClient.getConfig({
instanceId: instance.id,
userId: this.userId,
});
const newInstanceConfigJson = JSON.stringify(newInstanceConfig);
if (this.instanceConfigJson !== newInstanceConfigJson) {
this.clearInstanceConfigUpdateInterval();
// eslint-disable-next-line no-constant-condition
while (true) {
if (!((_a = this.defaultCallClient.getInstance()) === null || _a === void 0 ? void 0 : _a.hasActiveCall())) {
console.log("New instance config - restarting client");
this.terminate();
this.start(newInstanceConfig);
break;
}
yield utils_1.PromiseHelper.sleep(1000);
}
}
});
const interval = setInterval(configUpdater, instanceConfig.configRefreshIntervalMs);
this.instanceConfigUpdateInterval = (_b = (_a = interval.unref) === null || _a === void 0 ? void 0 : _a.call(interval)) !== null && _b !== void 0 ? _b : interval;
}
clearInstanceConfigUpdateInterval() {
if (this.instanceConfigUpdateInterval != null) {
clearInterval(this.instanceConfigUpdateInterval);
this.instanceConfigUpdateInterval = undefined;
}
}
addListener(listener) {
this.clientEvent.addListener(listener);
}
removeListener(listener) {
this.clientEvent.removeListener(listener);
}
initiateCall(request) {
if (this.isClientStarted) {
return this.apiClient.initiateCall(request);
}
else {
throw new fsm_1.InvalidOperationError("Can not initiate a call before authentication");
}
}
get callClient() {
return this.defaultCallClient;
}
terminate() {
this.isClientStarted = false;
this.instanceController.terminate();
this.clearInstanceConfigUpdateInterval();
this.features.resetListeners();
this.clientEvent.onEvent({ eventType: "terminated" });
}
get localUserId() {
return this.userId;
}
isStarted() {
return this.isClientStarted;
}
relayRemotePushNotification(payload) {
const result = new push_1.DefaultNotificationResult(payload.sinch, payload.name);
if (result.isValid()) {
if (this.isStarted()) {
this.defaultCallClient.handleCallPushPayload(result);
}
else {
this.onStartedAction.push(() => this.defaultCallClient.handleCallPushPayload(result));
this.start();
}
}
return result;
}
showPushNotification(title, options) {
var _a;
(_a = this.pushWorker) === null || _a === void 0 ? void 0 : _a.showNotification(title, options);
}
}
exports.DefaultSinchClient = DefaultSinchClient;
DefaultSinchClient.OCRA_PATH = "/ocra";
// Export as standalone to global scope
if (typeof window !== "undefined")
window.SinchClient = DefaultSinchClient;
//# sourceMappingURL=DefaultSinchClient.js.map