UNPKG

@twilio/rtc-diagnostics

Version:

Various diagnostics functions to help analyze connections to Twilio

269 lines 13.4 kB
"use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; 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()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; Object.defineProperty(exports, "__esModule", { value: true }); var polyfills_1 = require("../polyfills"); /** * @internalapi * Return a function that validates an audio device by ID. It will returns a * `string` representing why the ID is invalid, or nothing if it is valid. Will * throw if `enumerateDevices` is not supported by the system. * @param options Options to pass to the validator. A mock `enumerateDevices` * may be passed here, as well as a `kind` may be passed here if there is a * desire to check the `kind` of audio device. * @returns A function that takes a `string` representing the audio device ID to * be validated and returns a Promise resolving a `string` representing the * invalid message or `undefined` if the audio device is valid. */ function createAudioDeviceValidator(options) { var _this = this; if (options === void 0) { options = {}; } var opts = __assign({ enumerateDevices: polyfills_1.enumerateDevices }, options); /** * The audio device validator that will be returned. * @param deviceId The device ID to be validated. * @returns A Promise that resolves with a `string` representing why the * device ID is invalid, or `undefined` if it is valid. */ return function (deviceId) { return __awaiter(_this, void 0, void 0, function () { var devices, _a, matchingDevicesKind, matchingDevicesId, matchingDevicesIdAndKind; return __generator(this, function (_b) { switch (_b.label) { case 0: _a = opts.enumerateDevices; if (!_a) return [3 /*break*/, 2]; return [4 /*yield*/, opts.enumerateDevices()]; case 1: _a = (_b.sent()); _b.label = 2; case 2: devices = _a; if (!devices) { throw polyfills_1.EnumerateDevicesUnsupportedError; } if (!devices.length) { return [2 /*return*/, 'No audio devices available.']; } // `deviceId` as `undefined` is a valid value as this will cause // `getUserMedia` to just get the default device if (deviceId === undefined) { if (opts.kind) { matchingDevicesKind = devices.filter(function (device) { return device.kind === opts.kind; }); if (!matchingDevicesKind.length) { return [2 /*return*/, "No devices found with the correct kind \"" + opts.kind + "\"."]; } } return [2 /*return*/]; } matchingDevicesId = devices.filter(function (device) { return device.deviceId === deviceId; }); if (!matchingDevicesId.length) { return [2 /*return*/, "Device ID \"" + deviceId + "\" not found within list of available devices."]; } if (opts.kind) { matchingDevicesIdAndKind = matchingDevicesId.filter(function (device) { return device.kind === opts.kind; }); if (!matchingDevicesIdAndKind.length) { return [2 /*return*/, "Device ID \"" + deviceId + "\" is not the correct \"kind\"," + (" expected \"" + opts.kind + "\".")]; } } return [2 /*return*/]; } }); }); }; } exports.createAudioDeviceValidator = createAudioDeviceValidator; /** * @internalapi * Validate that an option is a valid device ID to pass to `getUserMedia` or * `setSinkId`. * @param option The option to check is a valid device ID to pass to * `getUserMedia` or `setSinkId`. * @returns If the option is not valid, return a string that describes why, * otherwise `undefined`. */ function validateDeviceId(option) { if (!(['string', 'undefined'].includes(typeof option) || option === null)) { return 'If "deviceId" is defined, it must be a "string".'; } } exports.validateDeviceId = validateDeviceId; /** * @internalapi * Validate that an option is a valid string. * @param option The option to check is a valid string. * @returns If the option is not valid, return a string that describes why it is * invalid, otherwise return `undefined`. */ function validateString(option) { var type = typeof option; if (type !== 'string') { return "Option cannot have type \"" + type + "\", must be \"string\"."; } } exports.validateString = validateString; /** * @internalapi * Validate a time-based parameter, i.e. duration or interval. * @param option The duration of time to validate * @returns A possibly undefined string, if the time is valid it will return * undefined, otherwise an error message */ function validateTime(option) { var doesNotExistMessage = validateExists(option); if (doesNotExistMessage) { return doesNotExistMessage; } if (typeof option !== 'number') { return 'Time must be a number.'; } if (option < 0) { return 'Time must always be non-negative.'; } } exports.validateTime = validateTime; /** * @internalapi * Validate that an option is neither `undefined` nor `null`. * @param option The option to check exists. * @returns A possibly undefined string, if the option exists it will return * `undefined`, otherwise a string representing why the option is invalid */ function validateExists(option) { if (option === undefined || option === null) { return "Option cannot be \"" + String(option) + "\"."; } } exports.validateExists = validateExists; /** * @internalapi * Validate that an option is a `boolean`. * @param option The option to check. * @returns A possibly undefined string, if the option is valid it will return * `undefined`, otherwise a string representing why the option is invalid */ function validateBoolean(option) { if (typeof option !== 'boolean') { return "Option must be \"boolean\"."; } } exports.validateBoolean = validateBoolean; /** * @internalapi * Validate input options to the [[AudioInputTest]]. * @param inputOptions The options to validate. * @param config A record of option names to either a single * [[ValidatorFunction]] or an array of [[ValidatorFunctions]]. * @returns A Promise that resolves either with a [[InvalidityRecord]] describing * which options are invalid and why, or `undefined` if all options are vaild. */ function validateOptions(inputOptions, config) { return __awaiter(this, void 0, void 0, function () { var validity; var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: validity = {}; return [4 /*yield*/, Promise.all(Object.entries(config).map(function (_a) { var optionKey = _a[0], validatorFunctions = _a[1]; return __awaiter(_this, void 0, void 0, function () { var optionValue, validators; var _this = this; return __generator(this, function (_b) { switch (_b.label) { case 0: if (!validatorFunctions) { return [2 /*return*/]; } optionValue = inputOptions[optionKey]; validators = Array.isArray(validatorFunctions) ? validatorFunctions : [validatorFunctions]; return [4 /*yield*/, Promise.all(validators.map(function (validator) { return __awaiter(_this, void 0, void 0, function () { var invalidReason, invalidReasons; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, validator(optionValue)]; case 1: invalidReason = _a.sent(); if (invalidReason) { invalidReasons = validity[optionKey]; if (invalidReasons) { invalidReasons.push(invalidReason); } else { validity[optionKey] = [invalidReason]; } } return [2 /*return*/]; } }); }); }))]; case 1: _b.sent(); return [2 /*return*/]; } }); }); }))]; case 1: _a.sent(); if (Object.keys(validity).length) { return [2 /*return*/, validity]; } return [2 /*return*/]; } }); }); } exports.validateOptions = validateOptions; //# sourceMappingURL=optionValidation.js.map