@twilio/mcs-client
Version:
Twilio Media Content Service client library
1,378 lines (1,169 loc) • 53.8 kB
JavaScript
/*
@license
Copyright (c) 2018, Twilio, Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
require('core-js/modules/es.reflect.to-string-tag.js');
require('core-js/modules/es.reflect.construct.js');
var _classCallCheck = require('@babel/runtime/helpers/classCallCheck');
var _createClass = require('@babel/runtime/helpers/createClass');
var _inherits = require('@babel/runtime/helpers/inherits');
var _possibleConstructorReturn = require('@babel/runtime/helpers/possibleConstructorReturn');
var _getPrototypeOf = require('@babel/runtime/helpers/getPrototypeOf');
var _wrapNativeSuper = require('@babel/runtime/helpers/wrapNativeSuper');
var _defineProperty = require('@babel/runtime/helpers/defineProperty');
require('core-js/modules/es.object.to-string.js');
require('core-js/modules/es.promise.js');
require('core-js/modules/es.array.iterator.js');
require('core-js/modules/es.map.js');
require('core-js/modules/es.string.iterator.js');
require('core-js/modules/web.dom-collections.iterator.js');
var require$$0 = require('crypto');
var _asyncToGenerator = require('@babel/runtime/helpers/asyncToGenerator');
var _regeneratorRuntime = require('@babel/runtime/regenerator');
require('core-js/modules/es.array.concat.js');
require('core-js/modules/es.array.map.js');
require('core-js/modules/web.dom-collections.for-each.js');
var _typeof = require('@babel/runtime/helpers/typeof');
require('core-js/modules/es.array.from.js');
var log$2 = require('loglevel');
require('core-js/modules/es.string.starts-with.js');
require('core-js/modules/es.array.filter.js');
require('core-js/modules/es.regexp.exec.js');
require('core-js/modules/es.string.split.js');
require('core-js/modules/es.string.replace.js');
require('core-js/modules/es.array.join.js');
require('core-js/modules/es.array.slice.js');
require('core-js/modules/es.json.stringify.js');
require('core-js/modules/es.object.assign.js');
require('core-js/modules/web.url.js');
require('core-js/modules/web.url-search-params.js');
var operationRetrier = require('@twilio/operation-retrier');
var declarativeTypeValidator = require('@twilio/declarative-type-validator');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
function _interopNamespace(e) {
if (e && e.__esModule) return e;
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n["default"] = e;
return Object.freeze(n);
}
var _classCallCheck__default = /*#__PURE__*/_interopDefaultLegacy(_classCallCheck);
var _createClass__default = /*#__PURE__*/_interopDefaultLegacy(_createClass);
var _inherits__default = /*#__PURE__*/_interopDefaultLegacy(_inherits);
var _possibleConstructorReturn__default = /*#__PURE__*/_interopDefaultLegacy(_possibleConstructorReturn);
var _getPrototypeOf__default = /*#__PURE__*/_interopDefaultLegacy(_getPrototypeOf);
var _wrapNativeSuper__default = /*#__PURE__*/_interopDefaultLegacy(_wrapNativeSuper);
var _defineProperty__default = /*#__PURE__*/_interopDefaultLegacy(_defineProperty);
var require$$0__default = /*#__PURE__*/_interopDefaultLegacy(require$$0);
var _asyncToGenerator__default = /*#__PURE__*/_interopDefaultLegacy(_asyncToGenerator);
var _regeneratorRuntime__default = /*#__PURE__*/_interopDefaultLegacy(_regeneratorRuntime);
var _typeof__default = /*#__PURE__*/_interopDefaultLegacy(_typeof);
var log__namespace = /*#__PURE__*/_interopNamespace(log$2);
// this is pretty straight-forward - we use the crypto API.
var crypto = require$$0__default["default"];
var rng$2 = function nodeRNG() {
return crypto.randomBytes(16);
};
/**
* Convert array of 16 byte values to UUID string format of the form:
* XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
*/
var byteToHex = [];
for (var i = 0; i < 256; ++i) {
byteToHex[i] = (i + 0x100).toString(16).substr(1);
}
function bytesToUuid$2(buf, offset) {
var i = offset || 0;
var bth = byteToHex; // join used to fix memory issue caused by concatenation: https://bugs.chromium.org/p/v8/issues/detail?id=3175#c4
return [bth[buf[i++]], bth[buf[i++]], bth[buf[i++]], bth[buf[i++]], '-', bth[buf[i++]], bth[buf[i++]], '-', bth[buf[i++]], bth[buf[i++]], '-', bth[buf[i++]], bth[buf[i++]], '-', bth[buf[i++]], bth[buf[i++]], bth[buf[i++]], bth[buf[i++]], bth[buf[i++]], bth[buf[i++]]].join('');
}
var bytesToUuid_1 = bytesToUuid$2;
var rng$1 = rng$2;
var bytesToUuid$1 = bytesToUuid_1; // **`v1()` - Generate time-based UUID**
//
// Inspired by https://github.com/LiosK/UUID.js
// and http://docs.python.org/library/uuid.html
var _nodeId;
var _clockseq; // Previous uuid creation time
var _lastMSecs = 0;
var _lastNSecs = 0; // See https://github.com/uuidjs/uuid for API details
function v1$1(options, buf, offset) {
var i = buf && offset || 0;
var b = buf || [];
options = options || {};
var node = options.node || _nodeId;
var clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq; // node and clockseq need to be initialized to random values if they're not
// specified. We do this lazily to minimize issues related to insufficient
// system entropy. See #189
if (node == null || clockseq == null) {
var seedBytes = rng$1();
if (node == null) {
// Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)
node = _nodeId = [seedBytes[0] | 0x01, seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5]];
}
if (clockseq == null) {
// Per 4.2.2, randomize (14 bit) clockseq
clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff;
}
} // UUID timestamps are 100 nano-second units since the Gregorian epoch,
// (1582-10-15 00:00). JSNumbers aren't precise enough for this, so
// time is handled internally as 'msecs' (integer milliseconds) and 'nsecs'
// (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00.
var msecs = options.msecs !== undefined ? options.msecs : new Date().getTime(); // Per 4.2.1.2, use count of uuid's generated during the current clock
// cycle to simulate higher resolution clock
var nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1; // Time since last uuid creation (in msecs)
var dt = msecs - _lastMSecs + (nsecs - _lastNSecs) / 10000; // Per 4.2.1.2, Bump clockseq on clock regression
if (dt < 0 && options.clockseq === undefined) {
clockseq = clockseq + 1 & 0x3fff;
} // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new
// time interval
if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) {
nsecs = 0;
} // Per 4.2.1.2 Throw error if too many uuids are requested
if (nsecs >= 10000) {
throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec');
}
_lastMSecs = msecs;
_lastNSecs = nsecs;
_clockseq = clockseq; // Per 4.1.4 - Convert from unix epoch to Gregorian epoch
msecs += 12219292800000; // `time_low`
var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;
b[i++] = tl >>> 24 & 0xff;
b[i++] = tl >>> 16 & 0xff;
b[i++] = tl >>> 8 & 0xff;
b[i++] = tl & 0xff; // `time_mid`
var tmh = msecs / 0x100000000 * 10000 & 0xfffffff;
b[i++] = tmh >>> 8 & 0xff;
b[i++] = tmh & 0xff; // `time_high_and_version`
b[i++] = tmh >>> 24 & 0xf | 0x10; // include version
b[i++] = tmh >>> 16 & 0xff; // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)
b[i++] = clockseq >>> 8 | 0x80; // `clock_seq_low`
b[i++] = clockseq & 0xff; // `node`
for (var n = 0; n < 6; ++n) {
b[i + n] = node[n];
}
return buf ? buf : bytesToUuid$1(b);
}
var v1_1 = v1$1;
var rng = rng$2;
var bytesToUuid = bytesToUuid_1;
function v4$1(options, buf, offset) {
var i = buf && offset || 0;
if (typeof options == 'string') {
buf = options === 'binary' ? new Array(16) : null;
options = null;
}
options = options || {};
var rnds = options.random || (options.rng || rng)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
rnds[6] = rnds[6] & 0x0f | 0x40;
rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided
if (buf) {
for (var ii = 0; ii < 16; ++ii) {
buf[i + ii] = rnds[ii];
}
}
return buf || bytesToUuid(rnds);
}
var v4_1 = v4$1;
var v1 = v1_1;
var v4 = v4_1;
var uuid = v4;
uuid.v1 = v1;
uuid.v4 = v4;
var uuid_1 = uuid;
function _createSuper$1(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct$1(); return function _createSuperInternal() { var Super = _getPrototypeOf__default["default"](Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf__default["default"](this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn__default["default"](this, result); }; }
function _isNativeReflectConstruct$1() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
/**
* Cancellable promise. Extends the functionality of the native Promise to include the cancel method.
*
* Example:
*
* ```ts
*
* const cancellableFetchPromise = new CancellablePromise(async (resolve, reject, onCancel) => {
* const request = fetch("https://example.com/");
*
* onCancel(() => request.cancel());
*
* try {
* const response = await request;
* resolve(response);
* } catch (err) {
* reject(err);
* }
* });
*
* cancellableFetchPromise.cancel();
* ```
*/
var CancellablePromise = /*#__PURE__*/function (_Promise) {
_inherits__default["default"](CancellablePromise, _Promise);
var _super = _createSuper$1(CancellablePromise);
/**
* Creates a new CancellablePromise.
* @param executor A callback used to initialize the promise. This callback is passed three arguments:
* a resolve callback used to resolve the promise with a value or the result of another promise,
* a reject callback used to reject the promise with a provided reason or error,
* and an onCancel callback used to define behavior of cancellation.
*/
function CancellablePromise(executor) {
var _this;
_classCallCheck__default["default"](this, CancellablePromise);
var outerId = uuid_1.v4();
var outerRejectPromise;
_this = _super.call(this, function (resolve, reject) {
outerRejectPromise = reject;
return executor(function (value) {
CancellablePromise.cancellationMap.delete(outerId);
resolve(value);
}, function (reason) {
CancellablePromise.cancellationMap.delete(outerId);
reject(reason);
}, function (cancellationFunction) {
CancellablePromise.cancellationMap.set(outerId, cancellationFunction);
});
});
_this.id = outerId;
_this.rejectPromise = outerRejectPromise;
return _this;
}
/**
* Cancels the promise and invokes the cancellation callback if it was defined during instantiation. Cancellation will result in the promise being rejected.
*/
_createClass__default["default"](CancellablePromise, [{
key: "cancel",
value: function cancel() {
var onCancel = CancellablePromise.cancellationMap.get(this.id);
onCancel === null || onCancel === void 0 ? void 0 : onCancel();
if (this.rejectPromise) {
this.catch(function () {
return void 0;
});
this.rejectPromise(new Error("Promise was cancelled"));
}
return this;
}
}]);
return CancellablePromise;
}( /*#__PURE__*/_wrapNativeSuper__default["default"](Promise));
_defineProperty__default["default"](CancellablePromise, "cancellationMap", new Map());
function __decorate(decorators, target, key, desc) {
var c = arguments.length,
r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc,
d;
if ((typeof Reflect === "undefined" ? "undefined" : _typeof__default["default"](Reflect)) === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);else for (var i = decorators.length - 1; i >= 0; i--) {
if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
}
return c > 3 && r && Object.defineProperty(target, key, r), r;
}
function __metadata(metadataKey, metadataValue) {
if ((typeof Reflect === "undefined" ? "undefined" : _typeof__default["default"](Reflect)) === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue);
}
function prepareLine(prefix, args) {
return ["".concat(new Date().toISOString(), " MCS Client ").concat(prefix, ":")].concat(Array.from(args));
}
var Logger = /*#__PURE__*/function () {
function Logger(prefix) {
_classCallCheck__default["default"](this, Logger);
_defineProperty__default["default"](this, "prefix", "");
this.prefix = prefix !== null && prefix !== undefined && prefix.length > 0 ? prefix + " " : "";
}
_createClass__default["default"](Logger, [{
key: "setLevel",
value: function setLevel(level) {
log__namespace.setLevel(level);
}
}, {
key: "trace",
value:
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
function trace() {
if (log__namespace.getLevel() == log__namespace.levels.TRACE) {
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
log__namespace.debug.apply(null, prepareLine(this.prefix + "T", args));
}
}
}, {
key: "debug",
value: function debug() {
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
args[_key2] = arguments[_key2];
}
log__namespace.debug.apply(null, prepareLine(this.prefix + "D", args));
}
}, {
key: "info",
value: function info() {
for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
args[_key3] = arguments[_key3];
}
log__namespace.info.apply(null, prepareLine(this.prefix + "I", args));
}
}, {
key: "warn",
value: function warn() {
for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
args[_key4] = arguments[_key4];
}
log__namespace.warn.apply(null, prepareLine(this.prefix + "W", args));
}
}, {
key: "error",
value: function error() {
for (var _len5 = arguments.length, args = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {
args[_key5] = arguments[_key5];
}
log__namespace.error.apply(null, prepareLine(this.prefix + "E", args));
}
}], [{
key: "scope",
value: function scope(prefix) {
return new Logger(prefix);
}
}, {
key: "setLevel",
value: function setLevel(level) {
log__namespace.setLevel(level);
}
}, {
key: "trace",
value: function trace() {
if (log__namespace.getLevel() == log__namespace.levels.TRACE) {
for (var _len6 = arguments.length, args = new Array(_len6), _key6 = 0; _key6 < _len6; _key6++) {
args[_key6] = arguments[_key6];
}
log__namespace.debug.apply(null, prepareLine("T", args));
}
}
}, {
key: "debug",
value: function debug() {
for (var _len7 = arguments.length, args = new Array(_len7), _key7 = 0; _key7 < _len7; _key7++) {
args[_key7] = arguments[_key7];
}
log__namespace.debug.apply(null, prepareLine("D", args));
}
}, {
key: "info",
value: function info() {
for (var _len8 = arguments.length, args = new Array(_len8), _key8 = 0; _key8 < _len8; _key8++) {
args[_key8] = arguments[_key8];
}
log__namespace.info.apply(null, prepareLine("I", args));
}
}, {
key: "warn",
value: function warn() {
for (var _len9 = arguments.length, args = new Array(_len9), _key9 = 0; _key9 < _len9; _key9++) {
args[_key9] = arguments[_key9];
}
log__namespace.warn.apply(null, prepareLine("W", args));
}
}, {
key: "error",
value: function error() {
for (var _len10 = arguments.length, args = new Array(_len10), _key10 = 0; _key10 < _len10; _key10++) {
args[_key10] = arguments[_key10];
}
log__namespace.error.apply(null, prepareLine("E", args));
}
}]);
return Logger;
}();
var MINIMUM_RETRY_DELAY = 1000;
var MAXIMUM_RETRY_DELAY = 4000;
var MAXIMUM_ATTEMPTS_COUNT = 3;
var RETRY_WHEN_THROTTLED = true;
var regionalMcsHost = function regionalMcsHost(region) {
return "https://mcs.".concat(region !== null && region !== void 0 ? region : "us1", ".twilio.com");
};
var isFullUrl = function isFullUrl(url) {
return url.startsWith("http");
};
var fullUrl = function fullUrl(partUrl, region) {
return "".concat(!isFullUrl(partUrl) ? regionalMcsHost(region) : "").concat(partUrl);
};
var Configuration = /*#__PURE__*/function () {
function Configuration(token, baseUrl, baseSetUrl, options) {
var _ref, _options$MCS, _ref2, _constructorOptions$r, _constructorOptions$r2, _constructorOptions$b;
_classCallCheck__default["default"](this, Configuration);
var constructorOptions = (_ref = (_options$MCS = options.MCS) !== null && _options$MCS !== void 0 ? _options$MCS : options) !== null && _ref !== void 0 ? _ref : {};
this.region = (_ref2 = (_constructorOptions$r = constructorOptions.region) !== null && _constructorOptions$r !== void 0 ? _constructorOptions$r : options.region) !== null && _ref2 !== void 0 ? _ref2 : 'us1';
this.mediaUrl = fullUrl(baseUrl, this.region);
this.mediaSetUrl = baseSetUrl ? fullUrl(baseSetUrl) : "".concat(this.mediaUrl, "Set");
this.token = token;
this.retryWhenThrottledOverride = (_constructorOptions$r2 = constructorOptions.retryWhenThrottledOverride) !== null && _constructorOptions$r2 !== void 0 ? _constructorOptions$r2 : RETRY_WHEN_THROTTLED;
this.backoffConfigOverride = (_constructorOptions$b = constructorOptions.backoffConfigOverride) !== null && _constructorOptions$b !== void 0 ? _constructorOptions$b : Configuration.backoffConfigDefault;
}
_createClass__default["default"](Configuration, [{
key: "updateToken",
value: function updateToken(token) {
this.token = token;
}
}], [{
key: "backoffConfigDefault",
get: function get() {
return {
min: MINIMUM_RETRY_DELAY,
max: MAXIMUM_RETRY_DELAY,
maxAttemptsCount: MAXIMUM_ATTEMPTS_COUNT
};
}
}, {
key: "retryWhenThrottledDefault",
get: function get() {
return RETRY_WHEN_THROTTLED;
}
}]);
return Configuration;
}();
/**
* @classdesc A Media represents a metadata information for the media upload
* @property {String} sid - The server-assigned unique identifier for Media
* @property {String} serviceSid - Service instance id which Media belongs/uploaded to
* @property {Date} dateCreated - When the Media was created
* @property {Date} dateUpdated - When the Media was updated
* @property {Number} size - Size of media, bytes
* @property {String} contentType - content type of media
* @property {String} fileName - file name, if present, null otherwise
* @property {MediaCategory} category - attachment category
*/
var Media = /*#__PURE__*/function () {
function Media(config, network, data) {
_classCallCheck__default["default"](this, Media);
this.config = config;
this.network = network;
this._update(data);
}
_createClass__default["default"](Media, [{
key: "sid",
get: function get() {
return this.state.sid;
}
}, {
key: "serviceSid",
get: function get() {
return this.state.serviceSid;
}
}, {
key: "dateCreated",
get: function get() {
return this.state.dateCreated;
}
}, {
key: "dateUpdated",
get: function get() {
return this.state.dateUpdated;
}
}, {
key: "contentType",
get: function get() {
return this.state.contentType;
}
}, {
key: "size",
get: function get() {
return this.state.size;
}
/** @deprecated Use filename instead */
}, {
key: "fileName",
get: function get() {
return this.state.filename;
}
}, {
key: "filename",
get: function get() {
return this.state.filename;
}
}, {
key: "category",
get: function get() {
return this.state.category;
}
/**
* Returns direct content URL to uploaded binary. This URL will expire after some time.
* This function gets a new URL every time, preventing it from expiring but putting additional load on backend.
* See getCachedContentUrl() for a function that reduces the amount of network requests.
*
* It is reasonable to build your own refresh logic upon these two functions: as soon as URL returned
* by getCachedContentUrl() returns 40x status you should call getContentUrl() to refresh it.
*/
}, {
key: "getContentUrl",
value: function getContentUrl() {
var _this = this;
return new CancellablePromise( /*#__PURE__*/function () {
var _ref = _asyncToGenerator__default["default"]( /*#__PURE__*/_regeneratorRuntime__default["default"].mark(function _callee(resolve, reject, onCancel) {
var request, response;
return _regeneratorRuntime__default["default"].wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
request = _this.network.get("".concat(_this.config.mediaUrl, "/").concat(_this.sid));
onCancel(function () {
return request.cancel();
});
_context.prev = 2;
_context.next = 5;
return request;
case 5:
response = _context.sent;
_this._update(response.body);
resolve(_this.state.contentDirectUrl);
_context.next = 13;
break;
case 10:
_context.prev = 10;
_context.t0 = _context["catch"](2);
reject(_context.t0);
case 13:
case "end":
return _context.stop();
}
}
}, _callee, null, [[2, 10]]);
}));
return function (_x, _x2, _x3) {
return _ref.apply(this, arguments);
};
}());
}
}, {
key: "_update",
value: function _update(data) {
var _data$links$content_d, _data$filename, _data$category, _data$is_multipart_up;
this.state = {
sid: data.sid,
serviceSid: data.service_sid,
channelSid: data.channel_sid,
messageSid: data.message_sid,
dateCreated: data.date_created ? new Date(data.date_created) : null,
dateUploadUpdated: data.date_upload_updated ? new Date(data.date_upload_updated) : null,
dateUpdated: data.date_updated ? new Date(data.date_updated) : null,
size: data.size,
contentType: data.content_type,
author: data.author,
url: data.url,
contentUrl: data.links.content,
contentDirectUrl: (_data$links$content_d = data.links.content_direct_temporary) !== null && _data$links$content_d !== void 0 ? _data$links$content_d : null,
filename: (_data$filename = data.filename) !== null && _data$filename !== void 0 ? _data$filename : null,
category: (_data$category = data.category) !== null && _data$category !== void 0 ? _data$category : "media",
isMultipartUpstream: (_data$is_multipart_up = data.is_multipart_upstream) !== null && _data$is_multipart_up !== void 0 ? _data$is_multipart_up : false
};
}
/**
* @internal
* This payload is compatible with Conversations' media object _state().
*/
}, {
key: "_state",
value: function _state() {
var _this$state$filename;
return {
sid: this.state.sid,
category: this.state.category,
filename: (_this$state$filename = this.state.filename) !== null && _this$state$filename !== void 0 ? _this$state$filename : null,
contentType: this.state.contentType,
size: this.state.size
};
}
}]);
return Media;
}();
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf__default["default"](Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf__default["default"](this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn__default["default"](this, result); }; }
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
var TransportError = /*#__PURE__*/function (_Error) {
_inherits__default["default"](TransportError, _Error);
var _super = _createSuper(TransportError);
function TransportError(message, code, body, status, headers) {
var _this;
_classCallCheck__default["default"](this, TransportError);
_this = _super.call(this, message);
_this.code = code;
_this.body = body;
_this.status = status;
_this.headers = headers;
return _this;
}
return _createClass__default["default"](TransportError);
}( /*#__PURE__*/_wrapNativeSuper__default["default"](Error));
var XHR = global["XMLHttpRequest"] || require("xmlhttprequest").XMLHttpRequest;
function parseResponseHeaders(headerString) {
if (!headerString) {
return {};
}
return headerString.split("\r\n").map(function (el) {
return el.split(": ");
}).filter(function (el) {
return el.length === 2 && el[1].length > 0;
}).reduce(function (prev, curr) {
prev[curr[0]] = curr[1];
return prev;
}, {});
}
function extractBody(xhr) {
var contentType = xhr.getResponseHeader("Content-Type");
if (!contentType || contentType.indexOf("application/json") !== 0 || xhr.responseText.length === 0) {
return xhr.responseText;
}
try {
return JSON.parse(xhr.responseText);
} catch (e) {
return xhr.responseText;
}
}
/**
* Provides generic network interface
*/
var Transport = /*#__PURE__*/function () {
function Transport() {
_classCallCheck__default["default"](this, Transport);
}
_createClass__default["default"](Transport, [{
key: "get",
value:
/**
* Make a GET request by given URL
*/
function get(url, headers) {
return Transport.request("GET", url, headers);
}
/**
* Make a POST request by given URL
*/
}, {
key: "post",
value: function post(url, headers, body) {
return Transport.request("POST", url, headers, body);
}
}], [{
key: "request",
value: function request(method, url, headers, body) {
return new CancellablePromise(function (resolve, reject, onCancel) {
var xhr = new XHR();
var isCancelled = false;
onCancel(function () {
xhr.abort();
isCancelled = true;
});
xhr.open(method, url, true);
xhr.onreadystatechange = function onreadystatechange() {
if (xhr.readyState !== 4 || isCancelled) {
return;
}
var responseHeaders = parseResponseHeaders(xhr.getAllResponseHeaders());
var body = extractBody(xhr);
if (200 <= xhr.status && xhr.status < 300) {
resolve({
status: xhr.status,
headers: responseHeaders,
body: body
});
} else {
var _xhr$statusText;
var status = (_xhr$statusText = xhr.statusText) !== null && _xhr$statusText !== void 0 ? _xhr$statusText : "NONE";
var bodyRepresentation;
if (typeof body === "string") {
if (body && body.split("\n", 2).length === 1) bodyRepresentation = body;else {
var _body$replace$split$f;
// TODO: RTDSDK-3716: investigate why body is HTML string
var errorInfo = (_body$replace$split$f = body.replace(/<.*?>/g, "").split(/\r\n/g).filter(function (str) {
return str.length;
})[0]) === null || _body$replace$split$f === void 0 ? void 0 : _body$replace$split$f.split(" ");
bodyRepresentation = (errorInfo === null || errorInfo === void 0 ? void 0 : errorInfo.length) > 2 ? errorInfo === null || errorInfo === void 0 ? void 0 : errorInfo.slice(1).join(" ") : "";
}
} else {
bodyRepresentation = JSON.stringify(body);
}
var message = "".concat(xhr.status, ": [").concat(status, "] ").concat(bodyRepresentation);
reject(new TransportError(message, xhr.status, body, status, responseHeaders));
}
};
for (var headerName in headers) {
xhr.setRequestHeader(headerName, headers[headerName]);
if (headerName === "Content-Type" && headers[headerName] === "application/json") {
body = JSON.stringify(body);
}
}
xhr.send(body);
});
}
}]);
return Transport;
}();
var log$1 = Logger.scope("Network");
var Network = /*#__PURE__*/function () {
function Network(config, transport) {
_classCallCheck__default["default"](this, Network);
this.config = config;
this.transport = transport;
}
_createClass__default["default"](Network, [{
key: "backoffConfig",
value: function backoffConfig() {
return Object.assign(Configuration.backoffConfigDefault, this.config.backoffConfigOverride);
}
}, {
key: "retryWhenThrottled",
value: function retryWhenThrottled() {
var _ref, _this$config$retryWhe;
return (_ref = (_this$config$retryWhe = this.config.retryWhenThrottledOverride) !== null && _this$config$retryWhe !== void 0 ? _this$config$retryWhe : Configuration.retryWhenThrottledDefault) !== null && _ref !== void 0 ? _ref : false;
}
}, {
key: "executeWithRetry",
value: function executeWithRetry(request, retryWhenThrottled) {
var _this = this;
return new CancellablePromise( /*#__PURE__*/function () {
var _ref2 = _asyncToGenerator__default["default"]( /*#__PURE__*/_regeneratorRuntime__default["default"].mark(function _callee2(resolve, reject, onCancel) {
var retrier, codesToRetryOn;
return _regeneratorRuntime__default["default"].wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
retrier = new operationRetrier.Retrier(_this.backoffConfig());
codesToRetryOn = [502, 503, 504];
if (retryWhenThrottled) {
codesToRetryOn.push(429);
}
onCancel(function () {
retrier.cancel();
retrier.removeAllListeners();
});
retrier.on("attempt", /*#__PURE__*/_asyncToGenerator__default["default"]( /*#__PURE__*/_regeneratorRuntime__default["default"].mark(function _callee() {
var requestPromise, result;
return _regeneratorRuntime__default["default"].wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_context.prev = 0;
requestPromise = request();
onCancel(function () {
requestPromise.cancel();
retrier.cancel();
retrier.removeAllListeners();
});
_context.next = 5;
return requestPromise;
case 5:
result = _context.sent;
retrier.succeeded(result);
_context.next = 12;
break;
case 9:
_context.prev = 9;
_context.t0 = _context["catch"](0);
if (codesToRetryOn.indexOf(_context.t0.status) > -1) {
retrier.failed(_context.t0);
} else if (_context.t0.message === "Twilsock disconnected") {
// Ugly hack. We must make a proper exceptions for twilsock
retrier.failed(_context.t0);
} else {
// Fatal error
retrier.removeAllListeners();
retrier.cancel();
reject(_context.t0);
}
case 12:
case "end":
return _context.stop();
}
}
}, _callee, null, [[0, 9]]);
})));
retrier.on("succeeded", function (result) {
resolve(result);
});
retrier.on("cancelled", function (err) {
return reject(err);
});
retrier.on("failed", function (err) {
return reject(err);
});
retrier.start();
case 9:
case "end":
return _context2.stop();
}
}
}, _callee2);
}));
return function (_x, _x2, _x3) {
return _ref2.apply(this, arguments);
};
}());
}
}, {
key: "get",
value: function get(url) {
var _this2 = this;
return new CancellablePromise( /*#__PURE__*/function () {
var _ref4 = _asyncToGenerator__default["default"]( /*#__PURE__*/_regeneratorRuntime__default["default"].mark(function _callee3(resolve, reject, onCancel) {
var headers, request, response;
return _regeneratorRuntime__default["default"].wrap(function _callee3$(_context3) {
while (1) {
switch (_context3.prev = _context3.next) {
case 0:
headers = {
"X-Twilio-Token": _this2.config.token
};
request = _this2.executeWithRetry(function () {
return _this2.transport.get(url, headers);
}, _this2.retryWhenThrottled());
log$1.trace("sending GET request to ", url, " headers ", headers);
onCancel(function () {
return request.cancel();
});
_context3.prev = 4;
_context3.next = 7;
return request;
case 7:
response = _context3.sent;
log$1.trace("response", response);
resolve(response);
_context3.next = 16;
break;
case 12:
_context3.prev = 12;
_context3.t0 = _context3["catch"](4);
log$1.debug("get() error ".concat(_context3.t0));
reject(_context3.t0);
case 16:
case "end":
return _context3.stop();
}
}
}, _callee3, null, [[4, 12]]);
}));
return function (_x4, _x5, _x6) {
return _ref4.apply(this, arguments);
};
}());
}
}, {
key: "post",
value: function post(url, category, media, contentType, filename) {
var _this3 = this;
var headers = {
"X-Twilio-Token": this.config.token
};
if ((typeof FormData === "undefined" || !(media instanceof FormData)) && contentType) {
Object.assign(headers, {
"Content-Type": contentType
});
}
var fullUrl = new URL(url);
if (category) {
fullUrl.searchParams.append("Category", category);
}
if (filename) {
fullUrl.searchParams.append("Filename", filename);
}
return new CancellablePromise( /*#__PURE__*/function () {
var _ref5 = _asyncToGenerator__default["default"]( /*#__PURE__*/_regeneratorRuntime__default["default"].mark(function _callee4(resolve, reject, onCancel) {
var request, response;
return _regeneratorRuntime__default["default"].wrap(function _callee4$(_context4) {
while (1) {
switch (_context4.prev = _context4.next) {
case 0:
request = _this3.transport.post(fullUrl.href, headers, media);
onCancel(function () {
return request.cancel();
});
log$1.trace("sending POST request to ".concat(url, " with headers ").concat(headers));
_context4.prev = 3;
_context4.next = 6;
return request;
case 6:
response = _context4.sent;
_context4.next = 17;
break;
case 9:
_context4.prev = 9;
_context4.t0 = _context4["catch"](3);
if (!(global["XMLHttpRequest"] === undefined && media instanceof FormData)) {
_context4.next = 14;
break;
}
reject(new TypeError("Posting FormData supported only with browser engine's FormData"));
return _context4.abrupt("return");
case 14:
log$1.debug("post() error ".concat(_context4.t0));
reject(_context4.t0);
return _context4.abrupt("return");
case 17:
log$1.trace("response", response);
resolve(response);
case 19:
case "end":
return _context4.stop();
}
}
}, _callee4, null, [[3, 9]]);
}));
return function (_x7, _x8, _x9) {
return _ref5.apply(this, arguments);
};
}());
}
}]);
return Network;
}();
var version = "0.6.10";
var _class;
var log = Logger.scope("");
/**
* @classdesc A Client provides an interface for Media Content Service
*/
exports["default"] = (_class = /*#__PURE__*/function () {
// eslint-disable-next-line
/**
* Base URLs must be full URLs with host. If host is not provided it will be generated from a default configuration
* template using options.region.
*
* @param {String} token - Access token
* @param {String} baseUrl - Base URL for Media Content Service Media resource, i.e. /v1/Services/{serviceSid}/Media
* @param {String} baseSetUrl - Base URL for Media Content Service MediaSet resource, i.e. /v1/Services/{serviceSid}/MediaSet
* @param {Client#ClientOptions} [options] - Options to customize the Client
*/
function Client(token, baseUrl, baseSetUrl) {
var _this$options$logLeve, _this$options$transpo;
var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
_classCallCheck__default["default"](this, Client);
this.options = options;
this.options.logLevel = (_this$options$logLeve = this.options.logLevel) !== null && _this$options$logLeve !== void 0 ? _this$options$logLeve : "silent";
this.config = new Configuration(token, baseUrl, baseSetUrl, this.options);
log.setLevel(this.options.logLevel);
this.options.transport = (_this$options$transpo = this.options.transport) !== null && _this$options$transpo !== void 0 ? _this$options$transpo : new Transport();
this.transport = this.options.transport;
this.network = new Network(this.config, this.transport);
}
/**
* These options can be passed to Client constructor
* @typedef {Object} Client#ClientOptions
* @property {String} [logLevel='silent'] - The level of logging to enable. Valid options
* (from strictest to broadest): ['silent', 'error', 'warn', 'info', 'debug', 'trace']
*/
/**
* Update the token used for Client operations
* @param {String} token - The JWT string of the new token
* @returns {void}
*/
_createClass__default["default"](Client, [{
key: "updateToken",
value: function updateToken(token) {
log.info("updateToken");
this.config.updateToken(token);
}
/**
* Gets media from media service
* @param {String} sid - Media's SID
*/
}, {
key: "get",
value: function get(sid) {
var _this = this;
return new CancellablePromise( /*#__PURE__*/function () {
var _ref = _asyncToGenerator__default["default"]( /*#__PURE__*/_regeneratorRuntime__default["default"].mark(function _callee(resolve, reject, onCancel) {
var request, response;
return _regeneratorRuntime__default["default"].wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
request = _this.network.get("".concat(_this.config.mediaUrl, "/").concat(sid));
onCancel(function () {
return request.cancel();
});
_context.prev = 2;
_context.next = 5;
return request;
case 5:
response = _context.sent;
resolve(new Media(_this.config, _this.network, response.body));
_context.next = 12;
break;
case 9:
_context.prev = 9;
_context.t0 = _context["catch"](2);
reject(_context.t0);
case 12:
case "end":
return _context.stop();
}
}
}, _callee, null, [[2, 9]]);
}));
return function (_x, _x2, _x3) {
return _ref.apply(this, arguments);
};
}());
}
/**
* Posts raw content to media service
* @param {String} contentType - content type of media
* @param {String|Buffer|Blob} media - content to post
* @param {MediaCategory|null} category - category for the media
*/
}, {
key: "post",
value: function post(contentType, media, category, filename) {
var _this2 = this;
return new CancellablePromise( /*#__PURE__*/function () {
var _ref2 = _asyncToGenerator__default["default"]( /*#__PURE__*/_regeneratorRuntime__default["default"].mark(function _callee2(resolve, reject, onCancel) {
var request, response;
return _regeneratorRuntime__default["default"].wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
request = _this2.network.post(_this2.config.mediaUrl, category !== null && category !== void 0 ? category : "media", media, contentType, filename);
onCancel(function () {
return request.cancel();
});
_context2.prev = 2;
_context2.next = 5;
return request;
case 5:
response = _context2.sent;
resolve(new Media(_this2.config, _this2.network, response.body));
_context2.next = 12;
break;
case 9:
_context2.prev = 9;
_context2.t0 = _context2["catch"](2);
reject(_context2.t0);
case 12:
case "end":
return _context2.stop();
}
}
}, _callee2, null, [[2, 9]]);
}));
return function (_x4, _x5, _x6) {
return _ref2.apply(this, arguments);
};
}());
}
/**
* Posts FormData to media service. Can be used only with browser engine's FormData.
* In non-browser FormData case the method will do promise reject with
* new TypeError("Posting FormData supported only with browser engine's FormData")
* @param {FormData} formData - form data to post
* @param {MediaCategory|null} category - category for the media
*/
}, {
key: "postFormData",
value: function postFormData(formData, category) {
var _this3 = this;
return new CancellablePromise( /*#__PURE__*/function () {
var _ref3 = _asyncToGenerator__default["default"]( /*#__PURE__*/_regeneratorRuntime__default["default"].mark(function _callee3(resolve, reject, onCancel) {
var request, response;
return _regeneratorRuntime__default["default"].wrap(function _callee3$(_context3) {
while (1) {
switch (_context3.prev = _context3.next) {
case 0:
request = _this3.network.post(_this3.config.mediaUrl, category !== null && category !== void 0 ? category : "media", formData);
onCancel(function () {
return request.cancel();
});
_context3.prev = 2;
_context3.next = 5;
return request;
case 5:
response = _context3.sent;
resolve(new Media(_this3.config, _this3.network, response.body));
_context3.next = 12;
break;
case 9:
_context3.prev = 9;
_context3.t0 = _context3["catch"](2);
reject(_context3.t0);
case 12:
case "end":
return _context3.stop();
}
}
}, _callee3, null, [[2, 9]]);
}));
return function (_x7, _x8, _x9) {
return _ref3.apply(this, arguments);
};
}());
}
/**
* Retrieve information about multiple media SIDs at the same time.
* @param mediaSids Array of Media SIDs to get information from.
*/
}, {
key: "mediaSetGet",
value: function mediaSetGet(mediaSids) {
var _this4 = this;
return new CancellablePromise( /*#__PURE__*/function () {
var _ref4 = _asyncToGenerator__default["default"]( /*#__PURE__*/_regeneratorRuntime__default["default"].mark(function _callee4(resolve, reject, onCancel) {
var query, request, response, media;
return _regeneratorRuntime__default["default"].wrap(function _callee4$(_context4) {
while (1) {
switch (_context4.prev = _context4.next) {
case 0:
query = {
command: "get",
list: mediaSids.map(function (sid) {
return {
media_sid: sid
};
})
};
request = _this4.network.post("".concat(_this4.config.mediaSetUrl), null, query, "application/json");
onCancel(function () {
return request.cancel();
});
_context4.prev = 3;
_context4.next = 6;
return request;
case 6:
response = _context4.sent;
media = response.body.map(function (item) {
if (item.code !== 200) {
reject("Failed to obtain detailed information about Media items (failed SID ".concat(item.media_record.sid, ")"));
return;
}
return new Media(_this4.config, _this4.network, item.media_record);
});
resolve(media);
_context4.next = 14;
break;
case 11:
_context4.prev = 11;
_context4.t0 = _context4["catch"](3);
reject(_context4.t0);
case 14:
case "end":
return _context4.stop();
}
}
}, _callee4, null, [[3, 11]]);
}));
return function (