Socket
Socket
Sign inDemoInstall

twilio-chat

Package Overview
Dependencies
Maintainers
1
Versions
367
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

twilio-chat - npm Package Compare versions

Comparing version 4.1.1-rc9 to 5.0.0-rc3

browser/commandexecutor.js

84

browser/channeldescriptor.js

@@ -14,2 +14,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.ChannelDescriptor = void 0;
var logger_1 = require("./logger");

@@ -39,54 +40,43 @@ var util_1 = require("./util");

var ChannelDescriptor = function () {
/**
* @param {Client} client Chat client instance
* @param {Object} descriptor Channel descriptor data object
* @private
*/
function ChannelDescriptor(client, descriptor) {
(0, _classCallCheck3.default)(this, ChannelDescriptor);
/**
* @param {Client} client Chat client instance
* @param {Object} descriptor Channel descriptor data object
* @private
*/
function ChannelDescriptor(client, descriptor) {
(0, _classCallCheck3.default)(this, ChannelDescriptor);
this.client = client;
this.descriptor = descriptor;
if (descriptor.sid) {
this.sid = descriptor.sid;
this.channel = descriptor.sid + '.channel';
} else {
this.sid = descriptor.channel_sid;
this.channel = descriptor.channel_sid + '.channel';
}
this.uniqueName = descriptor.unique_name;
this.friendlyName = descriptor.friendly_name;
this.attributes = util_1.parseAttributes(descriptor.attributes, 'Failed to parse channel attributes', log);
this.createdBy = descriptor.created_by;
this.dateCreated = util_1.parseTime(descriptor.date_created);
this.dateUpdated = util_1.parseTime(descriptor.date_updated);
this.messagesCount = descriptor.messages_count;
this.membersCount = descriptor.members_count;
this.type = descriptor.type;
this.isPrivate = descriptor.type == 'private' ? true : false;
this.lastConsumedMessageIndex = descriptor.last_consumed_message_index;
if (descriptor.notification_level) {
this.notificationLevel = descriptor.notification_level;
}
if (descriptor.status) {
this.status = descriptor.status;
} else {
this.status = 'unknown';
}
}
/**
* Get channel object from descriptor.
* @returns {Promise<Channel>}
*/
this.client = client;
this.descriptor = descriptor;
this.sid = descriptor.sid || descriptor.conversation_sid;
this.channel = this.sid + ".channel";
this.uniqueName = descriptor.unique_name;
this.friendlyName = descriptor.friendly_name;
this.attributes = util_1.parseAttributes(descriptor.attributes, 'Failed to parse channel attributes', log);
this.createdBy = descriptor.created_by;
this.dateCreated = util_1.parseTime(descriptor.date_created);
this.dateUpdated = util_1.parseTime(descriptor.date_updated);
this.messagesCount = descriptor.messages_count;
this.membersCount = descriptor.members_count;
this.type = descriptor.type;
this.isPrivate = descriptor.type === 'private';
this.lastConsumedMessageIndex = descriptor.last_consumed_message_index;
this.notificationLevel = descriptor.notification_level || undefined;
this.status = descriptor.status || 'unknown';
}
/**
* Get channel object from descriptor.
* @returns {Promise<Channel>}
*/
(0, _createClass3.default)(ChannelDescriptor, [{
key: "getChannel",
value: function getChannel() {
return this.client.getChannelBySid(this.sid);
}
}]);
return ChannelDescriptor;
(0, _createClass3.default)(ChannelDescriptor, [{
key: "getChannel",
value: function getChannel() {
return this.client.getChannelBySid(this.sid);
}
}]);
return ChannelDescriptor;
}();
exports.ChannelDescriptor = ChannelDescriptor;
"use strict";
var _getIterator2 = require("babel-runtime/core-js/get-iterator");
var _getIterator3 = _interopRequireDefault(_getIterator2);
var _slicedToArray2 = require("babel-runtime/helpers/slicedToArray");
var _slicedToArray3 = _interopRequireDefault(_slicedToArray2);
var _map = require("babel-runtime/core-js/map");
var _map2 = _interopRequireDefault(_map);
var _regenerator = require("babel-runtime/regenerator");

@@ -81,2 +69,3 @@

Object.defineProperty(exports, "__esModule", { value: true });
exports.PushNotification = exports.Client = exports.User = void 0;
var events_1 = require("events");

@@ -86,7 +75,8 @@ var logger_1 = require("./logger");

var user_1 = require("./user");
exports.User = user_1.User;
Object.defineProperty(exports, "User", { enumerable: true, get: function get() {
return user_1.User;
} });
var publicchannels_1 = require("./data/publicchannels");
var network_1 = require("./services/network");
var notificationtypes_1 = require("./interfaces/notificationtypes");
var synclist_1 = require("./synclist");
var twilsock_1 = require("twilsock");

@@ -96,12 +86,13 @@ var twilio_notifications_1 = require("twilio-notifications");

var twilio_mcs_client_1 = require("twilio-mcs-client");
var session_1 = require("./session");
var channels_1 = require("./data/channels");
var users_1 = require("./data/users");
var typingindicator_1 = require("./services/typingindicator");
var consumptionhorizon_1 = require("./services/consumptionhorizon");
var userchannels_1 = require("./data/userchannels");
var pushnotification_1 = require("./pushnotification");
exports.PushNotification = pushnotification_1.PushNotification;
Object.defineProperty(exports, "PushNotification", { enumerable: true, get: function get() {
return pushnotification_1.PushNotification;
} });
var util_1 = require("./util");
var typecheck_1 = require("./util/typecheck");
var twilio_sdk_type_validator_1 = require("twilio-sdk-type-validator");
var commandexecutor_1 = require("./commandexecutor");
var log = logger_1.Logger.scope('Client');

@@ -149,41 +140,16 @@ var SDK_VERSION = require('./../package.json').version;

/**
* These options can be passed to Client constructor.
* @typedef {Object} Client#ClientOptions
* @property {String} [logLevel='error'] - The level of logging to enable. Valid options
* (from strictest to broadest): ['silent', 'error', 'warn', 'info', 'debug', 'trace']
*/
/**
* These options can be passed to {@link Client#createChannel}.
* @typedef {Object} Client#CreateChannelOptions
* @property {any} [attributes] - Any custom attributes to attach to the Channel
* @property {String} [friendlyName] - The non-unique display name of the Channel
* @property {Boolean} [isPrivate] - Whether or not this Channel should be visible to uninvited Clients
* @property {String} [uniqueName] - The unique identity name of the Channel
*/
/**
* Connection state of Client.
* @typedef {('connecting'|'connected'|'disconnecting'|'disconnected'|'denied')} Client#ConnectionState
*/
/**
* Notifications channel type.
* @typedef {('gcm'|'fcm'|'apn')} Client#NotificationsChannelType
*/
/**
* These options can be passed to {@link Client#getLocalChannels}.
* @typedef {Object} Client#ChannelSortingOptions
* @property {('lastMessage'|'friendlyName'|'uniqueName')} [criteria] - Sorting criteria for Channels array
* @property {('ascending'|'descending')} [order] - Sorting order. If not present, then default is <code>ascending</code>
*/
function Client(token, options) {
function Client(token) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
(0, _classCallCheck3.default)(this, Client);
var _a;
var _this = (0, _possibleConstructorReturn3.default)(this, (Client.__proto__ || (0, _getPrototypeOf2.default)(Client)).call(this));
_this.options = options;
_this.connectionState = 'connecting';
_this.sessionPromise = null;
_this.channelsPromise = null;
_this.configurationPromise = null;
_this.version = SDK_VERSION;
_this.parsePushNotification = Client.parsePushNotification;
_this.options = options || {};
if (!_this.options.disableDeepClone) {

@@ -210,3 +176,3 @@ var _options = (0, _assign2.default)((0, _assign2.default)({}, _this.options), { transport: undefined, twilsockClient: undefined });

_this.options.Sync = _this.options.Sync || {};
if (typeof _this.options.Sync.enableSessionStorage === 'undefined') {
if (!((_a = _this.options.Sync) === null || _a === void 0 ? void 0 : _a.enableSessionStorage)) {
_this.options.Sync.enableSessionStorage = true;

@@ -221,3 +187,2 @@ }

_this.services = new ClientServices();
_this.config = new configuration_1.Configuration(_this.options);
_this.options.twilsockClient = _this.options.twilsockClient || new twilsock_1.Twilsock(token, productId, _this.options);

@@ -231,35 +196,30 @@ _this.options.transport = _this.options.transport || _this.options.twilsockClient;

_this.services.notificationClient = _this.options.notificationsClient;
_this.services.session = new session_1.Session(_this.services, _this.config);
_this.sessionPromise = _this.services.session.initialize();
_this.services.network = new network_1.Network(_this.config, _this.services);
_this.services.users = new users_1.Users({
session: _this.services.session,
network: _this.services.network,
syncClient: _this.services.syncClient
});
_this.services.users.on('userSubscribed', _this.emit.bind(_this, 'userSubscribed'));
_this.services.users.on('userUpdated', function (args) {
return _this.emit('userUpdated', args);
});
_this.services.users.on('userUnsubscribed', _this.emit.bind(_this, 'userUnsubscribed'));
_this.services.twilsockClient.on('tokenAboutToExpire', function (ttl) {
return _this.emit('tokenAboutToExpire', ttl);
});
_this.services.twilsockClient.on('tokenExpired', function () {
return _this.emit('tokenExpired');
});
_this.services.twilsockClient.on('connectionError', function (error) {
return _this.emit('connectionError', error);
});
_this.services.consumptionHorizon = new consumptionhorizon_1.ConsumptionHorizon(_this.services);
_this.services.typingIndicator = new typingindicator_1.TypingIndicator(_this.config, {
transport: _this.services.twilsockClient,
notificationClient: _this.services.notificationClient
}, _this.getChannelBySid.bind(_this));
_this.services.syncList = new synclist_1.SyncList(_this.services);
_this.channels = new channels_1.Channels(_this.services);
_this.channelsPromise = _this.sessionPromise.then(function () {
var configurationOptions = options.Chat || options.IPMessaging || options || {};
var region = configurationOptions.region || options.region;
var baseUrl = configurationOptions.apiUri || configurationOptions.typingUri || "https://aim." + (region || 'us1') + ".twilio.com";
_this.services.commandExecutor = new commandexecutor_1.CommandExecutor(baseUrl, { transport: _this.options.transport }, productId);
_this.configurationPromise = _this.services.commandExecutor.fetchResource('Client/v1/Configuration');
_this.configurationPromise.then(function (configurationResponse) {
_this.configuration = new configuration_1.Configuration(_this.options, configurationResponse, log);
_this.services.typingIndicator = new typingindicator_1.TypingIndicator(_this.getChannelBySid.bind(_this), _this.configuration, _this.services);
_this.services.network = new network_1.Network(_this.configuration, _this.services);
_this.services.users = new users_1.Users(_this.configuration, _this.services);
_this.services.users.on('userSubscribed', _this.emit.bind(_this, 'userSubscribed'));
_this.services.users.on('userUpdated', function (args) {
return _this.emit('userUpdated', args);
});
_this.services.users.on('userUnsubscribed', _this.emit.bind(_this, 'userUnsubscribed'));
_this.services.twilsockClient.on('tokenAboutToExpire', function (ttl) {
return _this.emit('tokenAboutToExpire', ttl);
});
_this.services.twilsockClient.on('tokenExpired', function () {
return _this.emit('tokenExpired');
});
_this.services.twilsockClient.on('connectionError', function (error) {
return _this.emit('connectionError', error);
});
_this.channels = new channels_1.Channels(_this.configuration, _this.services);
_this.channels.on('channelAdded', _this.emit.bind(_this, 'channelAdded'));
_this.channels.on('channelInvited', _this.emit.bind(_this, 'channelInvited'));
_this.channels.on('channelRemoved', _this.emit.bind(_this, 'channelRemoved'));
_this.channels.on('channelInvited', _this.emit.bind(_this, 'channelInvited'));
_this.channels.on('channelJoined', _this.emit.bind(_this, 'channelJoined'));

@@ -282,2 +242,4 @@ _this.channels.on('channelLeft', _this.emit.bind(_this, 'channelLeft'));

_this.channels.on('typingEnded', _this.emit.bind(_this, 'typingEnded'));
});
_this.channelsPromise = _this.configurationPromise.then(function () {
return _this.channels.fetchChannels();

@@ -314,2 +276,30 @@ }).then(function () {

/**
* These options can be passed to {@link Client#getLocalChannels}.
* @typedef {Object} Client#ChannelSortingOptions
* @property {('lastMessage'|'friendlyName'|'uniqueName')} [criteria] - Sorting criteria for Channels array
* @property {('ascending'|'descending')} [order] - Sorting order. If not present, then default is <code>ascending</code>
*/
/**
* These options can be passed to Client constructor.
* @typedef {Object} Client#ClientOptions
* @property {String} [logLevel='error'] - The level of logging to enable. Valid options
* (from strictest to broadest): ['silent', 'error', 'warn', 'info', 'debug', 'trace']
*/
/**
* These options can be passed to {@link Client#createChannel}.
* @typedef {Object} Client#CreateChannelOptions
* @property {any} [attributes] - Any custom attributes to attach to the Channel
* @property {String} [friendlyName] - The non-unique display name of the Channel
* @property {Boolean} [isPrivate] - Whether or not this Channel should be visible to uninvited Clients
* @property {String} [uniqueName] - The unique identity name of the Channel
*/
/**
* Connection state of Client.
* @typedef {('connecting'|'connected'|'disconnecting'|'disconnected'|'denied')} Client#ConnectionState
*/
/**
* Notifications channel type.
* @typedef {('gcm'|'fcm'|'apn')} Client#NotificationsChannelType
*/
/**
* Factory method to create Chat client instance.

@@ -351,3 +341,3 @@ *

var links, options;
var options;
return _regenerator2.default.wrap(function _callee$(_context) {

@@ -358,3 +348,3 @@ while (1) {

_context.next = 2;
return this.sessionPromise;
return this.configurationPromise;

@@ -365,18 +355,12 @@ case 2:

});
_context.next = 5;
return this.services.session.getSessionLinks();
case 5:
links = _context.sent;
this.services.publicChannels = new publicchannels_1.PublicChannels(this, this.services, links.publicChannelsUrl);
this.services.userChannels = new userchannels_1.UserChannels(this, this.services, links.myChannelsUrl);
this.services.publicChannels = new publicchannels_1.PublicChannels(this, this.services, this.configuration.links.conversations);
this.services.userChannels = new userchannels_1.UserChannels(this, this.services, this.configuration.links.myConversations);
options = (0, _assign2.default)(this.options);
options.transport = null;
this.services.mcsClient = new twilio_mcs_client_1.McsClient(this.fpaToken, links.mediaServiceUrl, options);
_context.next = 13;
this.services.mcsClient = new twilio_mcs_client_1.McsClient(this.fpaToken, this.configuration.links.mediaService, options);
_context.next = 10;
return this.services.typingIndicator.initialize();
case 13:
case 10:
case "end":

@@ -459,3 +443,3 @@ return _context.stop();

}).then(function () {
return _this5.sessionPromise;
return _this5.configurationPromise;
});

@@ -474,3 +458,3 @@

function updateToken(_x) {
function updateToken(_x2) {
return _ref3.apply(this, arguments);

@@ -497,3 +481,3 @@ }

case 0:
return _context4.abrupt("return", this.channels.syncListRead.promise.then(function () {
return _context4.abrupt("return", this.channels.myChannelsRead.promise.then(function () {
return _this6.channels.getChannel(channelSid).then(function (channel) {

@@ -514,3 +498,3 @@ return channel || _this6.services.publicChannels.getChannelBySid(channelSid).then(function (x) {

function getChannelBySid(_x2) {
function getChannelBySid(_x3) {
return _ref4.apply(this, arguments);

@@ -537,3 +521,3 @@ }

case 0:
return _context5.abrupt("return", this.channels.syncListRead.promise.then(function () {
return _context5.abrupt("return", this.channels.myChannelsRead.promise.then(function () {
return _this7.services.publicChannels.getChannelByUniqueName(uniqueName).then(function (x) {

@@ -552,3 +536,3 @@ return _this7.channels.pushChannel(x);

function getChannelByUniqueName(_x3) {
function getChannelByUniqueName(_x4) {
return _ref5.apply(this, arguments);

@@ -584,3 +568,2 @@ }

return this.channelsPromise.then(function (channels) {
var _a;
var result = [];

@@ -590,3 +573,3 @@ channels.channels.forEach(function (value) {

});
var sortingOrder = ((_a = sortingOptions) === null || _a === void 0 ? void 0 : _a.order) || 'ascending';
var sortingOrder = (sortingOptions === null || sortingOptions === void 0 ? void 0 : sortingOptions.order) || 'ascending';
if (sortingOptions && sortingOptions.criteria) {

@@ -675,3 +658,3 @@ if (sortingOptions.criteria === 'lastMessage') {

function setPushRegistrationId(_x4, _x5) {
function setPushRegistrationId(_x5, _x6) {
return _ref6.apply(this, arguments);

@@ -715,3 +698,3 @@ }

function unsetPushRegistrationId(_x6) {
function unsetPushRegistrationId(_x7) {
return _ref7.apply(this, arguments);

@@ -747,3 +730,3 @@ }

function handlePushNotification(_x7) {
function handlePushNotification(_x8) {
return _ref8.apply(this, arguments);

@@ -790,3 +773,3 @@ }

function getUserDescriptor(_x8) {
function getUserDescriptor(_x9) {
return _ref9.apply(this, arguments);

@@ -833,3 +816,3 @@ }

get: function get() {
return this.services.session.reachabilityEnabled;
return this.configuration.reachabilityEnabled;
}

@@ -865,3 +848,3 @@ }, {

function create(_x9, _x10) {
function create(_x10, _x11) {
return _ref11.apply(this, arguments);

@@ -991,92 +974,21 @@ }

};
__decorate([typecheck_1.asyncTypeCheck(typecheck_1.nonEmptyString), __metadata("design:type", Function), __metadata("design:paramtypes", [String]), __metadata("design:returntype", _promise2.default)], Client.prototype, "updateToken", null);
__decorate([typecheck_1.asyncTypeCheck(typecheck_1.nonEmptyString), __metadata("design:type", Function), __metadata("design:paramtypes", [String]), __metadata("design:returntype", _promise2.default)], Client.prototype, "getChannelBySid", null);
__decorate([typecheck_1.asyncTypeCheck('string'), __metadata("design:type", Function), __metadata("design:paramtypes", [String]), __metadata("design:returntype", _promise2.default)], Client.prototype, "getChannelByUniqueName", null);
__decorate([typecheck_1.asyncTypeCheck(['undefined', typecheck_1.custom(function (value) {
var baseDescription = 'valid sorting options';
if ((typeof value === "undefined" ? "undefined" : (0, _typeof3.default)(value)) !== 'object' || value === null || Array.isArray(value)) {
return [false, baseDescription + " (should be a pure object)"];
}
var literalMap = new _map2.default([['criteria', ['lastMessage', 'friendlyName', 'uniqueName']], ['order', ['ascending', 'descending']]]);
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = (0, _getIterator3.default)(literalMap.entries()), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var _ref12 = _step.value;
var _ref13 = (0, _slicedToArray3.default)(_ref12, 2);
var field = _ref13[0];
var literals = _ref13[1];
if (value[field] !== undefined && !literals.includes(value[field])) {
return [false, baseDescription + " (sortingOptions." + field + " should be one of: \"" + literals.join('", "') + "\")", "malformed sorting options (sortingOptions." + field + " is " + typecheck_1.stringifyReceivedType(value[field]) + ")"];
}
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
return [true];
__decorate([twilio_sdk_type_validator_1.validateTypesAsync(twilio_sdk_type_validator_1.nonEmptyString), __metadata("design:type", Function), __metadata("design:paramtypes", [String]), __metadata("design:returntype", _promise2.default)], Client.prototype, "updateToken", null);
__decorate([twilio_sdk_type_validator_1.validateTypesAsync(twilio_sdk_type_validator_1.nonEmptyString), __metadata("design:type", Function), __metadata("design:paramtypes", [String]), __metadata("design:returntype", _promise2.default)], Client.prototype, "getChannelBySid", null);
__decorate([twilio_sdk_type_validator_1.validateTypesAsync(twilio_sdk_type_validator_1.nonEmptyString), __metadata("design:type", Function), __metadata("design:paramtypes", [String]), __metadata("design:returntype", _promise2.default)], Client.prototype, "getChannelByUniqueName", null);
__decorate([twilio_sdk_type_validator_1.validateTypesAsync(['undefined', twilio_sdk_type_validator_1.objectSchema('sorting options', {
criteria: [twilio_sdk_type_validator_1.literal('lastMessage', 'friendlyName', 'uniqueName'), 'undefined'],
order: [twilio_sdk_type_validator_1.literal('ascending', 'descending'), 'undefined']
})]), __metadata("design:type", Function), __metadata("design:paramtypes", [Object]), __metadata("design:returntype", _promise2.default)], Client.prototype, "getLocalChannels", null);
__decorate([typecheck_1.asyncTypeCheck(['undefined', typecheck_1.custom(function (value) {
var baseDescription = 'valid channel options';
if ((typeof value === "undefined" ? "undefined" : (0, _typeof3.default)(value)) !== 'object' || value === null || Array.isArray(value)) {
return [false, baseDescription + " (should be a pure object)"];
}
var typeCheckMap = new _map2.default([['friendlyName', 'string'], ['isPrivate', 'boolean'], ['uniqueName', 'string']]);
var _iteratorNormalCompletion2 = true;
var _didIteratorError2 = false;
var _iteratorError2 = undefined;
try {
for (var _iterator2 = (0, _getIterator3.default)(typeCheckMap.entries()), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
var _ref14 = _step2.value;
var _ref15 = (0, _slicedToArray3.default)(_ref14, 2);
var field = _ref15[0];
var type = _ref15[1];
if (value[field] !== undefined && (0, _typeof3.default)(value[field]) !== type) {
return [false, baseDescription + " (options." + field + " should be of type " + type + ")", "malformed channel options (options." + field + " is " + typecheck_1.stringifyReceivedType(value[field]) + ")"];
}
}
} catch (err) {
_didIteratorError2 = true;
_iteratorError2 = err;
} finally {
try {
if (!_iteratorNormalCompletion2 && _iterator2.return) {
_iterator2.return();
}
} finally {
if (_didIteratorError2) {
throw _iteratorError2;
}
}
}
return [true];
__decorate([twilio_sdk_type_validator_1.validateTypesAsync(['undefined', twilio_sdk_type_validator_1.objectSchema('channel options', {
friendlyName: ['string', 'undefined'],
isPrivate: ['boolean', 'undefined'],
uniqueName: ['string', 'undefined']
})]), __metadata("design:type", Function), __metadata("design:paramtypes", [Object]), __metadata("design:returntype", _promise2.default)], Client.prototype, "createChannel", null);
__decorate([typecheck_1.asyncTypeCheck(typecheck_1.literal('gcm', 'fcm', 'apn'), 'string'), __metadata("design:type", Function), __metadata("design:paramtypes", [String, String]), __metadata("design:returntype", _promise2.default)], Client.prototype, "setPushRegistrationId", null);
__decorate([typecheck_1.asyncTypeCheck(typecheck_1.literal('gcm', 'fcm', 'apn')), __metadata("design:type", Function), __metadata("design:paramtypes", [String]), __metadata("design:returntype", _promise2.default)], Client.prototype, "unsetPushRegistrationId", null);
__decorate([typecheck_1.asyncTypeCheck(typecheck_1.pureObject), __metadata("design:type", Function), __metadata("design:paramtypes", [Object]), __metadata("design:returntype", _promise2.default)], Client.prototype, "handlePushNotification", null);
__decorate([typecheck_1.asyncTypeCheck(typecheck_1.nonEmptyString), __metadata("design:type", Function), __metadata("design:paramtypes", [String]), __metadata("design:returntype", _promise2.default)], Client.prototype, "getUser", null);
__decorate([typecheck_1.typeCheck(typecheck_1.nonEmptyString), __metadata("design:type", Function), __metadata("design:paramtypes", [String]), __metadata("design:returntype", _promise2.default)], Client.prototype, "getUserDescriptor", null);
__decorate([typecheck_1.asyncTypeCheck('string', ['undefined', typecheck_1.pureObject]), __metadata("design:type", Function), __metadata("design:paramtypes", [String, Object]), __metadata("design:returntype", _promise2.default)], Client, "create", null);
__decorate([typecheck_1.typeCheck(typecheck_1.pureObject), __metadata("design:type", Function), __metadata("design:paramtypes", [Object]), __metadata("design:returntype", pushnotification_1.PushNotification)], Client, "parsePushNotification", null);
__decorate([twilio_sdk_type_validator_1.validateTypesAsync(twilio_sdk_type_validator_1.literal('gcm', 'fcm', 'apn'), 'string'), __metadata("design:type", Function), __metadata("design:paramtypes", [String, String]), __metadata("design:returntype", _promise2.default)], Client.prototype, "setPushRegistrationId", null);
__decorate([twilio_sdk_type_validator_1.validateTypesAsync(twilio_sdk_type_validator_1.literal('gcm', 'fcm', 'apn')), __metadata("design:type", Function), __metadata("design:paramtypes", [String]), __metadata("design:returntype", _promise2.default)], Client.prototype, "unsetPushRegistrationId", null);
__decorate([twilio_sdk_type_validator_1.validateTypesAsync(twilio_sdk_type_validator_1.pureObject), __metadata("design:type", Function), __metadata("design:paramtypes", [Object]), __metadata("design:returntype", _promise2.default)], Client.prototype, "handlePushNotification", null);
__decorate([twilio_sdk_type_validator_1.validateTypesAsync(twilio_sdk_type_validator_1.nonEmptyString), __metadata("design:type", Function), __metadata("design:paramtypes", [String]), __metadata("design:returntype", _promise2.default)], Client.prototype, "getUser", null);
__decorate([twilio_sdk_type_validator_1.validateTypesAsync(twilio_sdk_type_validator_1.nonEmptyString), __metadata("design:type", Function), __metadata("design:paramtypes", [String]), __metadata("design:returntype", _promise2.default)], Client.prototype, "getUserDescriptor", null);
__decorate([twilio_sdk_type_validator_1.validateTypesAsync('string', ['undefined', twilio_sdk_type_validator_1.pureObject]), __metadata("design:type", Function), __metadata("design:paramtypes", [String, Object]), __metadata("design:returntype", _promise2.default)], Client, "create", null);
__decorate([twilio_sdk_type_validator_1.validateTypes(twilio_sdk_type_validator_1.pureObject), __metadata("design:type", Function), __metadata("design:paramtypes", [Object]), __metadata("design:returntype", pushnotification_1.PushNotification)], Client, "parsePushNotification", null);
exports.Client = Client;

@@ -1083,0 +995,0 @@ exports.default = Client;

"use strict";
var _assign = require("babel-runtime/core-js/object/assign");
var _assign2 = _interopRequireDefault(_assign);
var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck");

@@ -7,10 +11,7 @@

var _createClass2 = require("babel-runtime/helpers/createClass");
var _createClass3 = _interopRequireDefault(_createClass2);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
Object.defineProperty(exports, "__esModule", { value: true });
var TYPING_PATH = '/v1/typing';
exports.Configuration = void 0;
var iso8601_duration_1 = require("iso8601-duration");
var TYPING_TIMEOUT = 5;

@@ -25,58 +26,44 @@ var HTTP_CACHE_LIFETIME = 'PT5S';

var Configuration = function () {
function Configuration(options) {
(0, _classCallCheck3.default)(this, Configuration);
var Configuration = function Configuration() {
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var configurationResponse = arguments[1];
var logger = arguments[2];
(0, _classCallCheck3.default)(this, Configuration);
options = options || {};
var constructorOptions = options.Chat || options.IPMessaging || options || {};
this.region = constructorOptions.region || options.region;
this.baseUrl = constructorOptions.apiUri || constructorOptions.typingUri || (!this.region || this.region === 'us1' ? 'https://aim.twilio.com' : "https://aim." + this.region + ".twilio.com");
this.typingIndicatorUri = this.baseUrl + TYPING_PATH;
this.typingIndicatorTimeoutOverride = constructorOptions.typingIndicatorTimeoutOverride;
this.httpCacheIntervalOverride = constructorOptions.httpCacheIntervalOverride;
this.consumptionReportIntervalOverride = constructorOptions.consumptionReportIntervalOverride;
this.userInfosToSubscribeOverride = constructorOptions.userInfosToSubscribeOverride;
this.retryWhenThrottledOverride = constructorOptions.retryWhenThrottledOverride;
this.backoffConfigOverride = constructorOptions.backoffConfigOverride;
this.productId = options.productId;
this.typingIndicatorTimeoutDefault = TYPING_TIMEOUT * 1000;
var constructorOptions = options.Chat || options.IPMessaging || options || {};
this.productId = constructorOptions.productId;
this.links = {
myConversations: configurationResponse.links.my_conversations,
conversations: configurationResponse.links.conversations,
users: configurationResponse.links.users,
currentUser: configurationResponse.links.current_user,
typing: configurationResponse.links.typing,
mediaService: configurationResponse.links.media_service,
messagesReceipts: configurationResponse.links.messages_receipts
};
this.typingIndicatorTimeoutOverride = constructorOptions.typingIndicatorTimeoutOverride;
this.backoffConfiguration = (0, _assign2.default)({ min: MINIMUM_RETRY_DELAY, max: MAXIMUM_RETRY_DELAY, maxAttemptsCount: MAXIMUM_ATTEMPTS_COUNT }, constructorOptions.backoffConfigOverride);
this.retryWhenThrottled = constructorOptions.retryWhenThrottledOverride !== undefined ? constructorOptions.retryWhenThrottledOverride : RETRY_WHEN_THROTTLED;
this.userInfosToSubscribe = constructorOptions.userInfosToSubscribeOverride || configurationResponse.options.user_infos_to_subscribe || USER_INFOS_TO_SUBSCRIBE;
this.reachabilityEnabled = configurationResponse.options.reachability_enabled;
this.userIdentity = configurationResponse.identity;
this.userInfo = configurationResponse.sync_objects.my_user_info;
this.myConversations = configurationResponse.sync_objects.my_conversations;
var httpCacheInterval = constructorOptions.httpCacheIntervalOverride || configurationResponse.options.http_cache_interval || HTTP_CACHE_LIFETIME;
try {
this.httpCacheInterval = iso8601_duration_1.toSeconds(iso8601_duration_1.parse(httpCacheInterval));
} catch (_a) {
logger.error("Failed to parse http cache interval " + httpCacheInterval + ", using default value " + HTTP_CACHE_LIFETIME);
this.httpCacheInterval = iso8601_duration_1.toSeconds(iso8601_duration_1.parse(HTTP_CACHE_LIFETIME));
}
var consumptionReportInterval = constructorOptions.consumptionReportIntervalOverride || configurationResponse.options.consumption_report_interval || CONSUMPTION_HORIZON_SENDING_INTERVAL;
try {
this.consumptionReportInterval = iso8601_duration_1.toSeconds(iso8601_duration_1.parse(consumptionReportInterval));
} catch (_b) {
logger.error("Failed to parse consumption report interval " + consumptionReportInterval + ", using default value " + CONSUMPTION_HORIZON_SENDING_INTERVAL);
this.consumptionReportInterval = iso8601_duration_1.toSeconds(iso8601_duration_1.parse(CONSUMPTION_HORIZON_SENDING_INTERVAL));
}
};
(0, _createClass3.default)(Configuration, [{
key: "typingIndicatorTimeoutDefault",
get: function get() {
return TYPING_TIMEOUT * 1000;
}
}, {
key: "httpCacheIntervalDefault",
get: function get() {
return HTTP_CACHE_LIFETIME;
}
}, {
key: "consumptionReportIntervalDefault",
get: function get() {
return CONSUMPTION_HORIZON_SENDING_INTERVAL;
}
}, {
key: "userInfosToSubscribeDefault",
get: function get() {
return USER_INFOS_TO_SUBSCRIBE;
}
}, {
key: "retryWhenThrottledDefault",
get: function get() {
return RETRY_WHEN_THROTTLED;
}
}, {
key: "backoffConfigDefault",
get: function get() {
return {
min: MINIMUM_RETRY_DELAY,
max: MAXIMUM_RETRY_DELAY,
maxAttemptsCount: MAXIMUM_ATTEMPTS_COUNT
};
}
}]);
return Configuration;
}();
exports.Configuration = Configuration;
"use strict";
var _toConsumableArray2 = require("babel-runtime/helpers/toConsumableArray");
var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2);
var _getIterator2 = require("babel-runtime/core-js/get-iterator");
var _getIterator3 = _interopRequireDefault(_getIterator2);
var _promise = require("babel-runtime/core-js/promise");

@@ -7,5 +15,5 @@

var _regenerator = require("babel-runtime/regenerator");
var _assign = require("babel-runtime/core-js/object/assign");
var _regenerator2 = _interopRequireDefault(_regenerator);
var _assign2 = _interopRequireDefault(_assign);

@@ -16,2 +24,6 @@ var _stringify = require("babel-runtime/core-js/json/stringify");

var _regenerator = require("babel-runtime/regenerator");
var _regenerator2 = _interopRequireDefault(_regenerator);
var _asyncToGenerator2 = require("babel-runtime/helpers/asyncToGenerator");

@@ -52,6 +64,9 @@

Object.defineProperty(exports, "__esModule", { value: true });
exports.Channels = exports.Channel = void 0;
var events_1 = require("events");
var logger_1 = require("../logger");
var channel_1 = require("../channel");
exports.Channel = channel_1.Channel;
Object.defineProperty(exports, "Channel", { enumerable: true, get: function get() {
return channel_1.Channel;
} });
var deferred_1 = require("../util/deferred");

@@ -68,3 +83,3 @@ var util_1 = require("../util");

function Channels(services) {
function Channels(configuration, services) {
(0, _classCallCheck3.default)(this, Channels);

@@ -74,7 +89,8 @@

_this.configuration = configuration;
_this.services = services;
_this.channels = new _map2.default();
_this.thumbstones = new _set2.default();
_this.syncListFetched = false;
_this.syncListRead = new deferred_1.Deferred();
_this.tombstones = new _set2.default();
_this.myChannelsFetched = false;
_this.myChannelsRead = new deferred_1.Deferred();
return _this;

@@ -85,9 +101,31 @@ }

key: "getMap",
value: function getMap() {
var _this2 = this;
value: function () {
var _ref = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee() {
return _regenerator2.default.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_context.next = 2;
return this.services.syncClient.map({
id: this.configuration.myConversations,
mode: 'open_existing'
});
return this.services.session.getMyChannelsId().then(function (name) {
return _this2.services.syncClient.map({ id: name, mode: 'open_existing' });
});
}
case 2:
return _context.abrupt("return", _context.sent);
case 3:
case "end":
return _context.stop();
}
}
}, _callee, this);
}));
function getMap() {
return _ref.apply(this, arguments);
}
return getMap;
}()
/**

@@ -102,7 +140,7 @@ * Add channel to server

value: function () {
var _ref = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee(options) {
var attributes, response, channelSid, channelDocument, existingChannel, channel;
return _regenerator2.default.wrap(function _callee$(_context) {
var _ref2 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee2(options) {
var attributes, response, channelSid, channelDocument, links, existingChannel, channel;
return _regenerator2.default.wrap(function _callee2$(_context2) {
while (1) {
switch (_context.prev = _context.next) {
switch (_context2.prev = _context2.next) {
case 0:

@@ -116,29 +154,30 @@ attributes = void 0;

}
_context.next = 4;
return this.services.session.addCommand('createChannel', {
friendlyName: options.friendlyName,
uniqueName: options.uniqueName,
_context2.next = 4;
return this.services.commandExecutor.mutateResource('post', this.configuration.links.conversations, {
type: options.isPrivate ? 'private' : 'public',
attributes: (0, _stringify2.default)(attributes)
unique_name: options.uniqueName,
friendly_name: options.friendlyName,
attributes: attributes !== undefined ? (0, _stringify2.default)(attributes) : undefined
});
case 4:
response = _context.sent;
channelSid = 'channelSid' in response ? response['channelSid'] : null;
channelDocument = 'channel' in response ? response['channel'] : null;
response = _context2.sent;
channelSid = response.sid || null;
channelDocument = response.sync_objects.conversation || null;
links = (0, _assign2.default)({ self: response.url }, response.links);
existingChannel = this.channels.get(channelSid);
if (!existingChannel) {
_context.next = 12;
_context2.next = 13;
break;
}
_context.next = 11;
_context2.next = 12;
return existingChannel._subscribe();
case 11:
return _context.abrupt("return", existingChannel);
case 12:
return _context2.abrupt("return", existingChannel);
case 12:
channel = new channel_1.Channel(this.services, {
case 13:
channel = new channel_1.Channel({
channel: channelDocument,

@@ -154,23 +193,23 @@ entityName: null,

dateUpdated: null
}, channelSid);
}, channelSid, links, this.configuration, this.services);
this.channels.set(channel.sid, channel);
this.registerForEvents(channel);
_context.next = 17;
_context2.next = 18;
return channel._subscribe();
case 17:
case 18:
this.emit('channelAdded', channel);
return _context.abrupt("return", channel);
return _context2.abrupt("return", channel);
case 19:
case 20:
case "end":
return _context.stop();
return _context2.stop();
}
}
}, _callee, this);
}, _callee2, this);
}));
function addChannel(_x) {
return _ref.apply(this, arguments);
return _ref2.apply(this, arguments);
}

@@ -186,102 +225,136 @@

key: "fetchChannels",
value: function fetchChannels() {
var _this3 = this;
value: function () {
var _ref3 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee3() {
var _this2 = this;
this.getMap().then(function () {
var _ref2 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee2(map) {
var upserts, paginator, items;
return _regenerator2.default.wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
map.on('itemAdded', function (args) {
log.debug('itemAdded: ' + args.item.key);
_this3.upsertChannel('sync', args.item.key, args.item.value);
});
map.on('itemRemoved', function (args) {
log.debug('itemRemoved: ' + args.key);
var sid = args.key;
if (!_this3.syncListFetched) {
_this3.thumbstones.add(sid);
}
var channel = _this3.channels.get(sid);
if (channel) {
if (channel.status === 'joined' || channel.status === 'invited') {
channel._setStatus('notParticipating', 'sync');
_this3.emit('channelLeft', channel);
}
if (channel.isPrivate) {
_this3.channels.delete(sid);
_this3.emit('channelRemoved', channel);
channel.emit('removed', channel);
}
}
});
map.on('itemUpdated', function (args) {
log.debug('itemUpdated: ' + args.item.key);
_this3.upsertChannel('sync', args.item.key, args.item.value);
});
upserts = [];
_context2.next = 6;
return _this3.services.syncList.getPage();
var map, myChannels, upserts, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, channel, errorMessage;
case 6:
paginator = _context2.sent;
items = paginator.items;
return _regenerator2.default.wrap(function _callee3$(_context3) {
while (1) {
switch (_context3.prev = _context3.next) {
case 0:
_context3.prev = 0;
_context3.next = 3;
return this.getMap();
items.forEach(function (item) {
upserts.push(_this3.upsertChannel('synclist', item.channel_sid, item));
});
case 3:
map = _context3.sent;
case 9:
if (!paginator.hasNextPage) {
_context2.next = 16;
break;
map.on('itemAdded', function (args) {
log.debug("itemAdded: " + args.item.key);
_this2.upsertChannel('sync', args.item.key, args.item.data);
});
map.on('itemRemoved', function (args) {
log.debug("itemRemoved: " + args.key);
var sid = args.key;
if (!_this2.myChannelsFetched) {
_this2.tombstones.add(sid);
}
var channel = _this2.channels.get(sid);
if (!channel) {
return;
}
if (channel.status === 'joined' || channel.status === 'invited') {
channel._setStatus('notParticipating', 'sync');
_this2.emit('channelLeft', channel);
}
if (channel.isPrivate) {
_this2.channels.delete(sid);
_this2.emit('channelRemoved', channel);
channel.emit('removed', channel);
}
});
map.on('itemUpdated', function (args) {
log.debug("itemUpdated: " + args.item.key);
_this2.upsertChannel('sync', args.item.key, args.item.data);
});
_context3.next = 9;
return this._fetchMyChannels();
_context2.next = 12;
return paginator.nextPage();
case 9:
myChannels = _context3.sent;
upserts = [];
_iteratorNormalCompletion = true;
_didIteratorError = false;
_iteratorError = undefined;
_context3.prev = 14;
case 12:
paginator = _context2.sent;
for (_iterator = (0, _getIterator3.default)(myChannels); !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
channel = _step.value;
paginator.items.forEach(function (item) {
upserts.push(_this3.upsertChannel('synclist', item.channel_sid, item));
});
_context2.next = 9;
upserts.push(this.upsertChannel('rest', channel.channel_sid, channel));
}
_context3.next = 22;
break;
case 18:
_context3.prev = 18;
_context3.t0 = _context3["catch"](14);
_didIteratorError = true;
_iteratorError = _context3.t0;
case 22:
_context3.prev = 22;
_context3.prev = 23;
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
case 25:
_context3.prev = 25;
if (!_didIteratorError) {
_context3.next = 28;
break;
}
case 16:
_this3.syncListRead.set(true);
return _context2.abrupt("return", _promise2.default.all(upserts));
throw _iteratorError;
case 18:
case "end":
return _context2.stop();
}
case 28:
return _context3.finish(25);
case 29:
return _context3.finish(22);
case 30:
this.myChannelsRead.set(true);
_context3.next = 33;
return _promise2.default.all(upserts);
case 33:
this.myChannelsFetched = true;
this.tombstones.clear();
log.debug('The channels list has been successfully fetched');
return _context3.abrupt("return", this);
case 39:
_context3.prev = 39;
_context3.t1 = _context3["catch"](0);
errorMessage = 'Failed to fetch the channels list';
if (this.services.syncClient.connectionState !== 'disconnected') {
log.error(errorMessage, _context3.t1);
}
log.debug("ERROR: " + errorMessage, _context3.t1);
throw _context3.t1;
case 45:
case "end":
return _context3.stop();
}
}, _callee2, _this3);
}));
}
}, _callee3, this, [[0, 39], [14, 18, 22, 30], [23,, 25, 29]]);
}));
return function (_x2) {
return _ref2.apply(this, arguments);
};
}()).then(function () {
_this3.syncListFetched = true;
_this3.thumbstones.clear();
log.debug('Channels list fetched');
}).then(function () {
return _this3;
}).catch(function (e) {
if (_this3.services.syncClient.connectionState != 'disconnected') {
log.error('Failed to get channels list', e);
}
log.debug('ERROR: Failed to get channels list', e);
throw e;
});
}
function fetchChannels() {
return _ref3.apply(this, arguments);
}
return fetchChannels;
}()
}, {
key: "_wrapPaginator",
value: function _wrapPaginator(page, op) {
var _this4 = this;
var _this3 = this;

@@ -295,3 +368,3 @@ return op(page.items).then(function (items) {

return page.nextPage().then(function (x) {
return _this4._wrapPaginator(x, op);
return _this3._wrapPaginator(x, op);
});

@@ -301,3 +374,3 @@ },

return page.prevPage().then(function (x) {
return _this4._wrapPaginator(x, op);
return _this3._wrapPaginator(x, op);
});

@@ -311,3 +384,3 @@ }

value: function getChannels(args) {
var _this5 = this;
var _this4 = this;

@@ -317,5 +390,5 @@ return this.getMap().then(function (channelsMap) {

}).then(function (page) {
return _this5._wrapPaginator(page, function (items) {
return _this4._wrapPaginator(page, function (items) {
return _promise2.default.all(items.map(function (item) {
return _this5.upsertChannel('sync', item.key, item.value);
return _this4.upsertChannel('sync', item.key, item.data);
}));

@@ -328,3 +401,3 @@ });

value: function getChannel(sid) {
var _this6 = this;
var _this5 = this;

@@ -335,3 +408,3 @@ return this.getMap().then(function (channelsMap) {

return page.items.map(function (item) {
return _this6.upsertChannel('sync', item.key, item.value);
return _this5.upsertChannel('sync', item.key, item.data);
});

@@ -364,2 +437,48 @@ }).then(function (items) {

}, {
key: "_updateChannel",
value: function _updateChannel(source, channel, data) {
var _this6 = this;
var areSourcesDifferent = channel._statusSource() !== undefined && source !== channel._statusSource();
var isChannelSourceSync = source !== 'rest' || channel._statusSource() === 'sync';
if (areSourcesDifferent && isChannelSourceSync && source !== 'sync') {
log.trace('upsertChannel: the channel is known from sync and it came from chat, ignoring', {
sid: channel.sid,
data: data.status,
channel: channel.status
});
return;
}
if (['joined', 'invited'].includes(data.status) && channel.status !== data.status) {
channel._setStatus(data.status, source);
var updateData = {};
if (data.notificationLevel !== undefined) {
updateData.notificationLevel = data.notificationLevel;
}
if (data.lastConsumedMessageIndex !== undefined) {
updateData.lastConsumedMessageIndex = data.lastConsumedMessageIndex;
}
if (!util_1.isDeepEqual(updateData, {})) {
channel._update(updateData);
}
channel._subscribe().then(function () {
_this6.emit(data.status === 'joined' ? 'channelJoined' : 'channelInvited', channel);
});
return;
}
if (['joined', 'invited'].includes(channel.status) && data.status === 'notParticipating') {
channel._setStatus('notParticipating', source);
channel._update(data);
channel._subscribe().then(function () {
_this6.emit('channelLeft', channel);
});
return;
}
if (data.type === 'private' && data.status === 'notParticipating') {
channel._subscribe();
return;
}
channel._update(data);
}
}, {
key: "upsertChannel",

@@ -369,56 +488,8 @@ value: function upsertChannel(source, sid, data) {

log.trace('upsertChannel(sid=' + sid + ', data=', data);
log.trace("upsertChannel called for " + sid, data);
var channel = this.channels.get(sid);
// Update the Channel's status if we know about it
// If the channel is known, update it
if (channel) {
log.trace('upsertChannel: channel ' + sid + ' is known and it\'s' + ' status is known from source ' + channel._statusSource() + ' and update came from source ' + source, channel);
if (typeof channel._statusSource() === 'undefined' || source === channel._statusSource() || source === 'synclist' && channel._statusSource() !== 'sync' || source === 'sync') {
if (data.status === 'joined' && channel.status !== 'joined') {
channel._setStatus('joined', source);
var updateData = {};
if (typeof data.notificationLevel !== 'undefined') {
updateData.notificationLevel = data.notificationLevel;
}
if (typeof data.lastConsumedMessageIndex !== 'undefined') {
updateData.lastConsumedMessageIndex = data.lastConsumedMessageIndex;
}
if (!util_1.isDeepEqual(updateData, {})) {
channel._update(updateData);
}
channel._subscribe().then(function () {
_this7.emit('channelJoined', channel);
});
} else if (data.status === 'invited' && channel.status !== 'invited') {
channel._setStatus('invited', source);
var _updateData = {};
if (typeof data.notificationLevel !== 'undefined') {
_updateData.notificationLevel = data.notificationLevel;
}
if (typeof data.lastConsumedMessageIndex !== 'undefined') {
_updateData.lastConsumedMessageIndex = data.lastConsumedMessageIndex;
}
if (!util_1.isDeepEqual(_updateData, {})) {
channel._update(_updateData);
}
channel._subscribe().then(function () {
_this7.emit('channelInvited', channel);
});
} else if (data.status === 'notParticipating' && (channel.status === 'invited' || channel.status === 'joined')) {
channel._setStatus('notParticipating', source);
channel._update(data);
channel._subscribe().then(function () {
_this7.emit('channelLeft', channel);
});
} else if (data.status === 'notParticipating' && data.type === 'private') {
channel._subscribe();
} else {
channel._update(data);
}
} else {
log.trace('upsertChannel: channel is known from sync and came from chat, ignoring', {
sid: sid,
data: data.status,
channel: channel.status
});
}
log.trace("upsertChannel: the channel " + channel.sid + " is known;" + ("its status is known from source " + channel._statusSource() + " ") + ("and the update came from source " + source), channel);
this._updateChannel(source, channel, data);
return channel._subscribe().then(function () {

@@ -428,22 +499,26 @@ return channel;

}
if ((source === 'chat' || source === 'synclist') && this.thumbstones.has(sid)) {
// if channel was deleted, we ignore it
log.trace('upsertChannel: channel is deleted and came again from chat, ignoring', sid);
// If the channel is deleted, ignore it
if (['chat', 'rest'].includes(source) && this.tombstones.has(sid)) {
log.trace('upsertChannel: the channel is deleted but reappeared again from chat, ignoring', sid);
return;
}
// Fetch the Channel if we don't know about it
log.trace('upsertChannel: creating local channel object with sid ' + sid, data);
channel = new channel_1.Channel(this.services, data, sid);
this.channels.set(sid, channel);
return channel._subscribe().then(function () {
_this7.registerForEvents(channel);
_this7.emit('channelAdded', channel);
if (data.status === 'joined') {
channel._setStatus('joined', source);
_this7.emit('channelJoined', channel);
} else if (data.status === 'invited') {
channel._setStatus('invited', source);
_this7.emit('channelInvited', channel);
// If the channel is unknown, fetch it
log.trace("upsertChannel: creating a local channel object with sid " + sid, data);
var baseLink = this.configuration.links.conversations + "/" + sid;
var links = {
self: baseLink,
messages: baseLink + "/Messages",
participants: baseLink + "/Participants",
invites: baseLink + "/Invites"
};
var newChannel = new channel_1.Channel(data, sid, links, this.configuration, this.services);
this.channels.set(sid, newChannel);
return newChannel._subscribe().then(function () {
_this7.registerForEvents(newChannel);
_this7.emit('channelAdded', newChannel);
if (['joined', 'invited'].includes(data.status)) {
newChannel._setStatus(data.status, source);
_this7.emit(data.status === 'joined' ? 'channelJoined' : 'channelInvited', newChannel);
}
return channel;
return newChannel;
});

@@ -484,2 +559,64 @@ }

}
}, {
key: "_fetchMyChannels",
value: function () {
var _ref4 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee4() {
var channels, pageToken, url, response, preProcessedChannels;
return _regenerator2.default.wrap(function _callee4$(_context4) {
while (1) {
switch (_context4.prev = _context4.next) {
case 0:
channels = [];
pageToken = null;
case 2:
url = new util_1.UriBuilder(this.configuration.links.myConversations);
if (pageToken) {
url.arg('PageToken', pageToken);
}
_context4.next = 6;
return this.services.network.get(url.build());
case 6:
response = _context4.sent;
preProcessedChannels = response.body.conversations.map(function (channelDescriptor) {
return {
descriptor: channelDescriptor,
channel_sid: channelDescriptor.conversation_sid,
status: channelDescriptor.status,
channel: channelDescriptor.sync_objects.conversation,
messages: channelDescriptor.sync_objects.messages,
roster: channelDescriptor.conversation_sid + ".roster",
lastConsumedMessageIndex: channelDescriptor.last_consumed_message_index,
notificationLevel: channelDescriptor.notification_level
};
});
pageToken = response.body.meta.next_token;
channels = [].concat((0, _toConsumableArray3.default)(channels), (0, _toConsumableArray3.default)(preProcessedChannels));
case 10:
if (pageToken) {
_context4.next = 2;
break;
}
case 11:
return _context4.abrupt("return", channels);
case 12:
case "end":
return _context4.stop();
}
}
}, _callee4, this);
}));
function _fetchMyChannels() {
return _ref4.apply(this, arguments);
}
return _fetchMyChannels;
}()
}]);

@@ -486,0 +623,0 @@ return Channels;

@@ -38,2 +38,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.Members = void 0;
var events_1 = require("events");

@@ -53,3 +54,3 @@ var member_1 = require("../member");

function Members(channel, services, members) {
function Members(channel, members, links, configuration, services) {
(0, _classCallCheck3.default)(this, Members);

@@ -59,5 +60,7 @@

_this.services = services;
_this.channel = channel;
_this.members = members;
_this.links = links;
_this.configuration = configuration;
_this.services = services;
return _this;

@@ -111,3 +114,3 @@ }

log.debug(_this2.channel.sid + ' itemAdded: ' + args.item.key);
_this2.upsertMember(args.item.key, args.item.value).then(function (member) {
_this2.upsertMember(args.item.key, args.item.data).then(function (member) {
_this2.emit('memberJoined', member);

@@ -128,3 +131,3 @@ });

log.debug(_this2.channel.sid + ' itemUpdated: ' + args.item.key);
_this2.upsertMember(args.item.key, args.item.value);
_this2.upsertMember(args.item.key, args.item.data);
});

@@ -135,3 +138,3 @@ var membersPromises = [];

paginator.items.forEach(function (item) {
membersPromises.push(that.upsertMember(item.key, item.value));
membersPromises.push(that.upsertMember(item.key, item.data));
});

@@ -160,3 +163,3 @@ return paginator.hasNextPage ? paginator.nextPage().then(rosterMapHandler) : null;

var member;
var member, links;
return _regenerator2.default.wrap(function _callee2$(_context2) {

@@ -176,3 +179,7 @@ while (1) {

case 3:
member = new member_1.Member(this.services, this.channel, data, memberSid);
links = {
self: this.links.participants + "/" + memberSid
};
member = new member_1.Member(data, memberSid, this.channel, links, this.services);
this.members.set(memberSid, member);

@@ -184,3 +191,3 @@ member.on('updated', function (args) {

case 7:
case 8:
case "end":

@@ -303,8 +310,30 @@ return _context2.stop();

key: "add",
value: function add(identity) {
return this.services.session.addCommand('addMemberV2', {
channelSid: this.channel.sid,
username: identity
});
}
value: function () {
var _ref5 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee5(identity) {
return _regenerator2.default.wrap(function _callee5$(_context5) {
while (1) {
switch (_context5.prev = _context5.next) {
case 0:
_context5.next = 2;
return this.services.commandExecutor.mutateResource('post', this.links.participants, {
identity: identity
});
case 2:
return _context5.abrupt("return", _context5.sent);
case 3:
case "end":
return _context5.stop();
}
}
}, _callee5, this);
}));
function add(_x5) {
return _ref5.apply(this, arguments);
}
return add;
}()
/**

@@ -318,10 +347,32 @@ * Invites user to the channel

key: "invite",
value: function invite(identity) {
return this.services.session.addCommand('inviteMember', {
channelSid: this.channel.sid,
username: identity
});
}
value: function () {
var _ref6 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee6(identity) {
return _regenerator2.default.wrap(function _callee6$(_context6) {
while (1) {
switch (_context6.prev = _context6.next) {
case 0:
_context6.next = 2;
return this.services.commandExecutor.mutateResource('post', this.channel.links.invites, {
identity: identity
});
case 2:
return _context6.abrupt("return", _context6.sent);
case 3:
case "end":
return _context6.stop();
}
}
}, _callee6, this);
}));
function invite(_x6) {
return _ref6.apply(this, arguments);
}
return invite;
}()
/**
* Remove member from channel by Identity
* Remove member from channel
* @returns {Promise<any>}

@@ -331,22 +382,29 @@ */

}, {
key: "removeByIdentity",
value: function removeByIdentity(identity) {
return this.services.session.addCommand('removeMember', {
channelSid: this.channel.sid,
username: identity
});
}
/**
* Remove member from channel by sid
* @returns {Promise<any>}
*/
key: "remove",
value: function () {
var _ref7 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee7(identity) {
return _regenerator2.default.wrap(function _callee7$(_context7) {
while (1) {
switch (_context7.prev = _context7.next) {
case 0:
_context7.next = 2;
return this.services.commandExecutor.mutateResource('delete', this.links.participants + "/" + identity);
}, {
key: "removeBySid",
value: function removeBySid(sid) {
return this.services.session.addCommand('removeMember', {
channelSid: this.channel.sid,
memberSid: sid
});
}
case 2:
return _context7.abrupt("return", _context7.sent);
case 3:
case "end":
return _context7.stop();
}
}
}, _callee7, this);
}));
function remove(_x7) {
return _ref7.apply(this, arguments);
}
return remove;
}()
}]);

@@ -353,0 +411,0 @@ return Members;

@@ -46,2 +46,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.Messages = void 0;
var events_1 = require("events");

@@ -58,3 +59,3 @@ var logger_1 = require("../logger");

function Messages(channel, services) {
function Messages(channel, configuration, services) {
(0, _classCallCheck3.default)(this, Messages);

@@ -65,2 +66,3 @@

_this.channel = channel;
_this.configuration = configuration;
_this.services = services;

@@ -86,3 +88,8 @@ _this.messagesByIndex = new _map2.default();

log.debug(_this2.channel.sid + ' itemAdded: ' + args.item.index);
var message = new message_1.Message(_this2.channel, _this2.services, args.item.index, args.item.value);
var links = {
self: _this2.channel.links.messages + "/" + args.item.data.sid,
conversation: _this2.channel.links.self,
messages_receipts: _this2.channel.links.messages + "/" + args.item.data.sid + "/Receipts"
};
var message = new message_1.Message(args.item.index, args.item.data, _this2.channel, links, _this2.configuration, _this2.services);
if (_this2.messagesByIndex.has(message.index)) {

@@ -112,3 +119,3 @@ log.debug('Message arrived, but already known and ignored', _this2.channel.sid, message.index);

if (message) {
message._update(args.item.value);
message._update(args.item.data);
}

@@ -180,9 +187,12 @@ });

log.debug('Sending text message', message, attributes);
return _context2.abrupt("return", this.services.session.addCommand('sendMessage', {
channelSid: this.channel.sid,
text: message,
attributes: (0, _stringify2.default)(attributes)
}));
_context2.next = 3;
return this.services.commandExecutor.mutateResource('post', this.channel.links.messages, {
body: message || '',
attributes: attributes !== undefined ? (0, _stringify2.default)(attributes) : undefined
});
case 2:
case 3:
return _context2.abrupt("return", _context2.sent);
case 4:
case "end":

@@ -254,9 +264,12 @@ return _context2.stop();

case 16:
return _context3.abrupt("return", this.services.session.addCommand('sendMediaMessage', {
channelSid: this.channel.sid,
mediaSid: media.sid,
attributes: (0, _stringify2.default)(attributes)
}));
_context3.next = 18;
return this.services.commandExecutor.mutateResource('post', this.channel.links.messages, {
media_sid: media.sid,
attributes: attributes !== undefined ? (0, _stringify2.default)(attributes) : undefined
});
case 17:
case 18:
return _context3.abrupt("return", _context3.sent);
case 19:
case "end":

@@ -328,3 +341,8 @@ return _context3.stop();

}
var message = new message_1.Message(this.channel, this.services, index, value);
var links = {
self: this.channel.links.messages + "/" + value.sid,
conversation: this.channel.links.self,
messages_receipts: this.channel.links.messages + "/" + value.sid + "/Receipts"
};
var message = new message_1.Message(index, value, this.channel, links, this.configuration, this.services);
this.messagesByIndex.set(message.index, message);

@@ -362,3 +380,3 @@ message.on('updated', function (args) {

return _promise2.default.all(items.map(function (item) {
return _this5._upsertMessage(item.index, item.value);
return _this5._upsertMessage(item.index, item.data);
}));

@@ -365,0 +383,0 @@ });

@@ -22,2 +22,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.PublicChannels = void 0;
var index_1 = require("../util/index");

@@ -58,3 +59,3 @@ var restpaginator_1 = require("../restpaginator");

response = _context.sent;
return _context.abrupt("return", new restpaginator_1.RestPaginator(response.body.channels.map(function (x) {
return _context.abrupt("return", new restpaginator_1.RestPaginator(response.body.conversations.map(function (x) {
return new channeldescriptor_1.ChannelDescriptor(_this.client, x);

@@ -61,0 +62,0 @@ }), function (pageToken) {

@@ -22,2 +22,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.UserChannels = void 0;
var index_1 = require("../util/index");

@@ -58,3 +59,3 @@ var restpaginator_1 = require("../restpaginator");

response = _context.sent;
return _context.abrupt("return", new restpaginator_1.RestPaginator(response.body.channels.map(function (x) {
return _context.abrupt("return", new restpaginator_1.RestPaginator(response.body.conversations.map(function (x) {
return new channeldescriptor_1.ChannelDescriptor(_this.client, x);

@@ -61,0 +62,0 @@ }), function (pageToken) {

@@ -22,2 +22,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.UserDescriptors = void 0;
var index_1 = require("../util/index");

@@ -28,7 +29,7 @@ var restpaginator_1 = require("../restpaginator");

var UserDescriptors = function () {
function UserDescriptors(services, url) {
function UserDescriptors(configuration, services) {
(0, _classCallCheck3.default)(this, UserDescriptors);
this.configuration = configuration;
this.services = services;
this.url = url;
}

@@ -45,3 +46,3 @@

case 0:
url = new index_1.UriBuilder(this.url).path(identity).build();
url = new index_1.UriBuilder(this.configuration.links.users).path(identity).build();
_context.next = 3;

@@ -80,3 +81,3 @@ return this.services.network.get(url);

case 0:
url = new index_1.UriBuilder(this.url).arg('ChannelSid', channelSid).arg('PageToken', args.pageToken).build();
url = new index_1.UriBuilder(this.configuration.links.users).arg('ConversationSid', channelSid).arg('PageToken', args.pageToken).build();
_context2.next = 3;

@@ -83,0 +84,0 @@ return this.services.network.get(url);

@@ -11,2 +11,6 @@ "use strict";

var _assign = require("babel-runtime/core-js/object/assign");
var _assign2 = _interopRequireDefault(_assign);
var _map = require("babel-runtime/core-js/map");

@@ -39,2 +43,3 @@

Object.defineProperty(exports, "__esModule", { value: true });
exports.Users = void 0;
var events_1 = require("events");

@@ -51,3 +56,3 @@ var user_1 = require("../user");

function Users(services) {
function Users(configuration, services) {
(0, _classCallCheck3.default)(this, Users);

@@ -57,6 +62,9 @@

_this.configuration = configuration;
_this.services = services;
var userLinks = {
self: configuration.links.users + "/" + configuration.userIdentity
};
_this.fifoStack = [];
_this.fifoStackMaxLength = 100;
_this.myself = new user_1.User(null, null, _this.services);
_this.myself = new user_1.User(_this.configuration.userIdentity, _this.configuration.userInfo, userLinks, _this.configuration, _this.services);
_this.myself.on('updated', function (args) {

@@ -72,19 +80,4 @@ return _this.emit('userUpdated', args);

});
_this.services = services;
_this.subscribedUsers = new _map2.default();
_this.userDescriptorsPromise = _this.services.session.getSessionLinks().then(function (links) {
_this.userDescriptors = new userdescriptors_1.UserDescriptors({
users: _this,
network: _this.services.network
}, links.usersUrl);
return _this.userDescriptors;
});
_this.services.session.getMaxUserInfosToSubscribe().then(function (maxUserInfosToSubscribe) {
_this.fifoStackMaxLength = maxUserInfosToSubscribe;
});
_this.services.session.getUsersData().then(function (data) {
_this.myself.identity = data.identity;
_this.myself.entityName = data.user;
return _this.myself._ensureFetched();
});
_this.userDescriptors = new userdescriptors_1.UserDescriptors(_this.configuration, (0, _assign2.default)((0, _assign2.default)({}, _this.services), { users: _this }));
return _this;

@@ -118,3 +111,3 @@ }

}
if (this.fifoStack.length >= this.fifoStackMaxLength) {
if (this.fifoStack.length >= this.configuration.userInfosToSubscribe) {
this.subscribedUsers.get(this.fifoStack.shift()).unsubscribe();

@@ -139,3 +132,3 @@ }

var entityName = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
var user, userDescriptor;
var user, userDescriptor, userLinks;
return _regenerator2.default.wrap(function _callee$(_context) {

@@ -146,11 +139,7 @@ while (1) {

_context.next = 2;
return this.services.session.getUsersData();
return this.myself._ensureFetched();
case 2:
_context.next = 4;
return this.myself._ensureFetched();
case 4:
if (!(identity == this.myself.identity)) {
_context.next = 6;
_context.next = 4;
break;

@@ -161,7 +150,7 @@ }

case 6:
case 4:
user = this.subscribedUsers.get(identity);
if (user) {
_context.next = 19;
_context.next = 18;
break;

@@ -171,16 +160,20 @@ }

if (entityName) {
_context.next = 13;
_context.next = 11;
break;
}
_context.next = 11;
_context.next = 9;
return this.getUserDescriptor(identity);
case 11:
case 9:
userDescriptor = _context.sent;
entityName = userDescriptor._getDescriptor().sync_unique_name;
entityName = userDescriptor._getDescriptor().sync_objects.user_info_map;
case 13:
user = new user_1.User(identity, entityName, this.services);
case 11:
userLinks = {
self: this.configuration.links.users + "/" + identity
};
user = new user_1.User(identity, entityName, userLinks, this.configuration, this.services);
user.on('updated', function (args) {

@@ -195,9 +188,9 @@ return _this2.emit('userUpdated', args);

});
_context.next = 19;
_context.next = 18;
return user._ensureFetched();
case 19:
case 18:
return _context.abrupt("return", user);
case 20:
case 19:
case "end":

@@ -228,9 +221,5 @@ return _context.stop();

case 0:
_context2.next = 2;
return this.userDescriptorsPromise;
case 2:
return _context2.abrupt("return", this.userDescriptors.getUserDescriptor(identity));
case 3:
case 1:
case "end":

@@ -261,9 +250,5 @@ return _context2.stop();

case 0:
_context3.next = 2;
return this.userDescriptorsPromise;
case 2:
return _context3.abrupt("return", this.userDescriptors.getChannelUserDescriptors(channelSid));
case 3:
case 1:
case "end":

@@ -296,9 +281,5 @@ return _context3.stop();

_context4.next = 2;
return this.services.session.getUsersData();
return this.myself._ensureFetched();
case 2:
_context4.next = 4;
return this.myself._ensureFetched();
case 4:
users = [this.myself];

@@ -311,3 +292,3 @@

case 7:
case 5:
case "end":

@@ -314,0 +295,0 @@ return _context4.stop();

@@ -10,2 +10,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.NotificationTypes = void 0;

@@ -12,0 +13,0 @@ var NotificationTypes = function NotificationTypes() {

@@ -14,2 +14,3 @@ 'use strict';

Object.defineProperty(exports, "__esModule", { value: true });
exports.SamplePaginator = void 0;
/**

@@ -16,0 +17,0 @@ * @classdesc Pagination helper class.

@@ -10,2 +10,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.ResponseCodes = void 0;

@@ -12,0 +13,0 @@ var ResponseCodes = function ResponseCodes() {

@@ -18,2 +18,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.Logger = void 0;
var loglevelLog = require("loglevel");

@@ -20,0 +21,0 @@ function prepareLine(prefix, args) {

@@ -22,2 +22,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.Media = void 0;
/**

@@ -24,0 +25,0 @@ * @classdesc A Media represents a media information for Message in a Channel.

@@ -73,6 +73,7 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.Member = void 0;
var events_1 = require("events");
var util_1 = require("./util");
var logger_1 = require("./logger");
var typecheck_1 = require("./util/typecheck");
var twilio_sdk_type_validator_1 = require("twilio-sdk-type-validator");
var log = logger_1.Logger.scope('Member');

@@ -91,3 +92,3 @@ /**

* to find out how to mark messages as consumed.
* @property {Date} lastConsumptionTimestamp - Date when Member has updated his consumption horizon
* @property {Date} lastConsumptionTimestamp - Date when Member has updated their consumption horizon
* @property {String} sid - The server-assigned unique identifier for the Member

@@ -103,12 +104,3 @@ * @property {Member#Type} type - The type of Member

/**
* The update reason for <code>updated</code> event emitted on Member
* @typedef {('attributes' | 'dateCreated' | 'dateUpdated' | 'roleSid' |
'lastConsumedMessageIndex' | 'lastConsumptionTimestamp')} Member#UpdateReason
*/
/**
* The type of Member
* @typedef {('chat' | 'sms' | 'whatsapp')} Member#Type
*/
function Member(services, channel, data, sid) {
function Member(data, sid, channel, links, services) {
(0, _classCallCheck3.default)(this, Member);

@@ -119,3 +111,5 @@

_this.channel = channel;
_this.links = links;
_this.services = services;
_this.services = services;
_this.state = {

@@ -140,3 +134,13 @@ attributes: util_1.parseAttributes(data.attributes, 'Retrieved malformed attributes from the server for member: ' + sid, log),

}
/**
* The update reason for <code>updated</code> event emitted on Member
* @typedef {('attributes' | 'dateCreated' | 'dateUpdated' | 'roleSid' |
'lastConsumedMessageIndex' | 'lastConsumptionTimestamp')} Member#UpdateReason
*/
/**
* The type of Member
* @typedef {('chat' | 'sms' | 'whatsapp')} Member#Type
*/
(0, _createClass3.default)(Member, [{

@@ -340,6 +344,4 @@ key: "_startTyping",

_context4.next = 2;
return this.services.session.addCommand('editMemberAttributes', {
channelSid: this.channel.sid,
memberSid: this.sid,
attributes: (0, _stringify2.default)(attributes)
return this.services.commandExecutor.mutateResource('post', this.links.self, {
attributes: attributes !== undefined ? (0, _stringify2.default)(attributes) : undefined
});

@@ -418,3 +420,3 @@

__decorate([typecheck_1.asyncTypeCheck(['string', 'number', 'boolean', 'object', typecheck_1.literal(null)]), __metadata("design:type", Function), __metadata("design:paramtypes", [Object]), __metadata("design:returntype", _promise2.default)], Member.prototype, "updateAttributes", null);
__decorate([twilio_sdk_type_validator_1.validateTypesAsync(['string', 'number', 'boolean', 'object', twilio_sdk_type_validator_1.literal(null)]), __metadata("design:type", Function), __metadata("design:paramtypes", [Object]), __metadata("design:returntype", _promise2.default)], Member.prototype, "updateAttributes", null);
exports.Member = Member;

@@ -421,0 +423,0 @@ /**

@@ -69,2 +69,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.Message = void 0;
var events_1 = require("events");

@@ -74,3 +75,3 @@ var util_1 = require("./util");

var media_1 = require("./media");
var typecheck_1 = require("./util/typecheck");
var twilio_sdk_type_validator_1 = require("twilio-sdk-type-validator");
var log = logger_1.Logger.scope('Message');

@@ -97,7 +98,3 @@ /**

/**
* The update reason for <code>updated</code> event emitted on Message
* @typedef {('body' | 'lastUpdatedBy' | 'dateCreated' | 'dateUpdated' | 'attributes' | 'author')} Message#UpdateReason
*/
function Message(channel, services, index, data) {
function Message(index, data, channel, links, configuration, services) {
(0, _classCallCheck3.default)(this, Message);

@@ -108,2 +105,4 @@

_this.channel = channel;
_this.links = links;
_this.configuration = configuration;
_this.services = services;

@@ -125,3 +124,8 @@ _this.state = {

}
/**
* The update reason for <code>updated</code> event emitted on Message
* @typedef {('body' | 'lastUpdatedBy' | 'dateCreated' | 'dateUpdated' | 'attributes' | 'author')} Message#UpdateReason
*/
(0, _createClass3.default)(Message, [{

@@ -261,6 +265,3 @@ key: "_update",

_context2.next = 2;
return this.services.session.addCommand('deleteMessage', {
channelSid: this.channel.sid,
messageIdx: this.index.toString()
});
return this.services.commandExecutor.mutateResource('delete', this.links.self);

@@ -299,6 +300,4 @@ case 2:

_context3.next = 2;
return this.services.session.addCommand('editMessage', {
channelSid: this.channel.sid,
messageIdx: this.index.toString(),
text: body
return this.services.commandExecutor.mutateResource('post', this.links.self, {
body: body
});

@@ -338,6 +337,4 @@

_context4.next = 2;
return this.services.session.addCommand('editMessageAttributes', {
channelSid: this.channel.sid,
messageIdx: this.index,
attributes: (0, _stringify2.default)(attributes)
return this.services.commandExecutor.mutateResource('post', this.links.self, {
attributes: attributes !== undefined ? (0, _stringify2.default)(attributes) : undefined
});

@@ -424,4 +421,4 @@

__decorate([typecheck_1.asyncTypeCheck('string'), __metadata("design:type", Function), __metadata("design:paramtypes", [String]), __metadata("design:returntype", _promise2.default)], Message.prototype, "updateBody", null);
__decorate([typecheck_1.asyncTypeCheck(['string', 'number', 'boolean', 'object', typecheck_1.literal(null)]), __metadata("design:type", Function), __metadata("design:paramtypes", [Object]), __metadata("design:returntype", _promise2.default)], Message.prototype, "updateAttributes", null);
__decorate([twilio_sdk_type_validator_1.validateTypesAsync('string'), __metadata("design:type", Function), __metadata("design:paramtypes", [String]), __metadata("design:returntype", _promise2.default)], Message.prototype, "updateBody", null);
__decorate([twilio_sdk_type_validator_1.validateTypesAsync(['string', 'number', 'boolean', 'object', twilio_sdk_type_validator_1.literal(null)]), __metadata("design:type", Function), __metadata("design:paramtypes", [Object]), __metadata("design:returntype", _promise2.default)], Message.prototype, "updateAttributes", null);
exports.Message = Message;

@@ -428,0 +425,0 @@ /**

@@ -10,2 +10,3 @@ 'use strict';

Object.defineProperty(exports, "__esModule", { value: true });
exports.PushNotification = void 0;
/**

@@ -12,0 +13,0 @@ * @classdesc Push notification representation within Chat Client

@@ -18,2 +18,3 @@ 'use strict';

Object.defineProperty(exports, "__esModule", { value: true });
exports.RestPaginator = void 0;
/**

@@ -20,0 +21,0 @@ * @class Paginator

@@ -23,6 +23,2 @@ "use strict";

var _assign = require("babel-runtime/core-js/object/assign");
var _assign2 = _interopRequireDefault(_assign);
var _map = require("babel-runtime/core-js/map");

@@ -43,37 +39,17 @@

Object.defineProperty(exports, "__esModule", { value: true });
exports.Network = void 0;
var operation_retrier_1 = require("operation-retrier");
var Network = function () {
function Network(config, services) {
var _this = this;
function Network(configuration, services) {
(0, _classCallCheck3.default)(this, Network);
this.config = config;
this.configuration = configuration;
this.services = services;
this.cache = new _map2.default();
this.cacheLifetime = 0;
this.services.session.getHttpCacheInterval().then(function (seconds) {
_this.cacheLifetime = seconds * 1000;
_this.cleanupCache();
});
this.cacheLifetime = this.configuration.httpCacheInterval * 100;
this.cleanupCache();
}
(0, _createClass3.default)(Network, [{
key: "backoffConfig",
value: function backoffConfig() {
return (0, _assign2.default)(this.config.backoffConfigDefault, this.config.backoffConfigOverride);
}
}, {
key: "retryWhenThrottled",
value: function retryWhenThrottled() {
if (typeof this.config.retryWhenThrottledOverride !== 'undefined') {
return this.config.retryWhenThrottledOverride;
}
if (typeof this.config.retryWhenThrottledDefault !== 'undefined') {
return this.config.retryWhenThrottledDefault;
}
return false;
}
}, {
key: "isExpired",

@@ -125,6 +101,6 @@ value: function isExpired(timestamp) {

value: function pokeTimer() {
var _this2 = this;
var _this = this;
this.timer = this.timer || setInterval(function () {
return _this2.cleanupCache();
return _this.cleanupCache();
}, this.cacheLifetime * 2);

@@ -135,3 +111,3 @@ }

value: function executeWithRetry(request) {
var _this3 = this;
var _this2 = this;

@@ -145,3 +121,3 @@ var retryWhenThrottled = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;

}
var retrier = new operation_retrier_1.Retrier(_this3.backoffConfig());
var retrier = new operation_retrier_1.Retrier(_this2.configuration.backoffConfiguration);
retrier.on('attempt', function () {

@@ -180,3 +156,3 @@ request().then(function (result) {

var _ref3 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee(url) {
var _this4 = this;
var _this3 = this;

@@ -201,4 +177,4 @@ var cacheEntry, headers, response;

return this.executeWithRetry(function () {
return _this4.services.transport.get(url, headers, _this4.config.productId);
}, this.retryWhenThrottled());
return _this3.services.transport.get(url, headers, _this3.configuration.productId);
}, this.configuration.retryWhenThrottled);

@@ -205,0 +181,0 @@ case 6:

@@ -22,2 +22,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.TypingIndicator = void 0;
var logger_1 = require("../logger");

@@ -44,8 +45,8 @@ var notificationtypes_1 = require("../interfaces/notificationtypes");

var TypingIndicator = function () {
function TypingIndicator(config, services, getChannel) {
function TypingIndicator(getChannel, configuration, services) {
(0, _classCallCheck3.default)(this, TypingIndicator);
this.config = config;
this.getChannel = getChannel;
this.configuration = configuration;
this.services = services;
this.getChannel = getChannel;
this.serviceTypingTimeout = null;

@@ -92,3 +93,3 @@ this.sentUpdates = new _map2.default();

}
var timeout = _this2.config.typingIndicatorTimeoutOverride + 1000 || message.typing_timeout * 1000;
var timeout = _this2.configuration.typingIndicatorTimeoutOverride + 1000 || message.typing_timeout * 1000;
member._startTyping(timeout);

@@ -122,3 +123,3 @@ });

log.trace('Sending typing indicator');
var url = this.config.typingIndicatorUri;
var url = this.configuration.links.typing;
var headers = {

@@ -128,3 +129,3 @@ 'Content-Type': 'application/x-www-form-urlencoded'

var body = 'ChannelSid=' + channelSid;
return this.services.transport.post(url, headers, body, this.config.productId).then(function (response) {
return this.services.transport.post(url, headers, body, this.configuration.productId).then(function (response) {
if (response.body.hasOwnProperty('typing_timeout')) {

@@ -141,3 +142,3 @@ _this3.serviceTypingTimeout = response.body.typing_timeout * 1000;

get: function get() {
return this.config.typingIndicatorTimeoutOverride || this.serviceTypingTimeout || this.config.typingIndicatorTimeoutDefault;
return this.configuration.typingIndicatorTimeoutOverride || this.serviceTypingTimeout || this.configuration.typingIndicatorTimeoutDefault;
}

@@ -144,0 +145,0 @@ }]);

@@ -18,2 +18,3 @@ 'use strict';

Object.defineProperty(exports, "__esModule", { value: true });
exports.SyncPaginator = void 0;
/**

@@ -20,0 +21,0 @@ * @classdesc Pagination helper class for Sync

@@ -11,2 +11,6 @@ "use strict";

var _promise = require("babel-runtime/core-js/promise");
var _promise2 = _interopRequireDefault(_promise);
var _asyncToGenerator2 = require("babel-runtime/helpers/asyncToGenerator");

@@ -16,6 +20,2 @@

var _promise = require("babel-runtime/core-js/promise");
var _promise2 = _interopRequireDefault(_promise);
var _getPrototypeOf = require("babel-runtime/core-js/object/get-prototype-of");

@@ -71,6 +71,7 @@

Object.defineProperty(exports, "__esModule", { value: true });
exports.User = void 0;
var events_1 = require("events");
var logger_1 = require("./logger");
var util_1 = require("./util");
var typecheck_1 = require("./util/typecheck");
var twilio_sdk_type_validator_1 = require("twilio-sdk-type-validator");
var log = logger_1.Logger.scope('User');

@@ -98,3 +99,2 @@ /**

* @param {Object} datasync - datasync service
* @param {Object} session - session service
*/

@@ -105,7 +105,3 @@

/**
* The update reason for <code>updated</code> event emitted on User
* @typedef {('friendlyName' | 'attributes' | 'online' | 'notifiable')} User#UpdateReason
*/
function User(identity, entityName, services) {
function User(identity, entityName, links, configuration, services) {
(0, _classCallCheck3.default)(this, User);

@@ -115,5 +111,7 @@

_this.links = links;
_this.configuration = configuration;
_this.services = services;
_this.subscribed = 'initializing';
_this.setMaxListeners(0);
_this.services = services;
_this.state = {

@@ -129,3 +127,8 @@ identity: identity,

}
/**
* The update reason for <code>updated</code> event emitted on User
* @typedef {('friendlyName' | 'attributes' | 'online' | 'notifiable')} User#UpdateReason
*/
(0, _createClass3.default)(User, [{

@@ -173,12 +176,36 @@ key: "_update",

key: "_updateReachabilityInfo",
value: function _updateReachabilityInfo(map, update) {
var _this2 = this;
value: function () {
var _ref = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee(map, update) {
var _this2 = this;
if (!this.services.session.reachabilityEnabled) {
return _promise2.default.resolve();
return _regenerator2.default.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
if (this.configuration.reachabilityEnabled) {
_context.next = 2;
break;
}
return _context.abrupt("return", _promise2.default.resolve());
case 2:
return _context.abrupt("return", map.get('reachability').then(update).catch(function (err) {
log.warn('Failed to get reachability info for ', _this2.state.identity, err);
}));
case 3:
case "end":
return _context.stop();
}
}
}, _callee, this);
}));
function _updateReachabilityInfo(_x, _x2) {
return _ref.apply(this, arguments);
}
return map.get('reachability').then(update).catch(function (err) {
log.warn('Failed to get reachability info for ', _this2.state.identity, err);
});
}
return _updateReachabilityInfo;
}()
// Fetch user

@@ -189,15 +216,15 @@

value: function () {
var _ref = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee() {
var _ref2 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee2() {
var _this3 = this;
return _regenerator2.default.wrap(function _callee$(_context) {
return _regenerator2.default.wrap(function _callee2$(_context2) {
while (1) {
switch (_context.prev = _context.next) {
switch (_context2.prev = _context2.next) {
case 0:
if (this.state.entityName) {
_context.next = 2;
_context2.next = 2;
break;
}
return _context.abrupt("return", this);
return _context2.abrupt("return", this);

@@ -209,10 +236,10 @@ case 2:

log.debug(_this3.state.entityName + ' (' + _this3.state.identity + ') itemUpdated: ' + args.item.key);
return _this3._update(args.item.key, args.item.value);
return _this3._update(args.item.key, args.item.data);
});
return _promise2.default.all([map.get('friendlyName').then(function (item) {
return _this3._update(item.key, item.value);
return _this3._update(item.key, item.data);
}), map.get('attributes').then(function (item) {
return _this3._update(item.key, item.value);
return _this3._update(item.key, item.data);
}), _this3._updateReachabilityInfo(map, function (item) {
return _this3._update(item.key, item.value);
return _this3._update(item.key, item.data);
})]);

@@ -228,14 +255,14 @@ }).then(function () {

});
return _context.abrupt("return", this.promiseToFetch);
return _context2.abrupt("return", this.promiseToFetch);
case 4:
case "end":
return _context.stop();
return _context2.stop();
}
}
}, _callee, this);
}, _callee2, this);
}));
function _fetch() {
return _ref.apply(this, arguments);
return _ref2.apply(this, arguments);
}

@@ -259,9 +286,9 @@

value: function () {
var _ref2 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee2(attributes) {
return _regenerator2.default.wrap(function _callee2$(_context2) {
var _ref3 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee3(attributes) {
return _regenerator2.default.wrap(function _callee3$(_context3) {
while (1) {
switch (_context2.prev = _context2.next) {
switch (_context3.prev = _context3.next) {
case 0:
if (!(this.subscribed == 'unsubscribed')) {
_context2.next = 2;
_context3.next = 2;
break;

@@ -273,5 +300,4 @@ }

case 2:
_context2.next = 4;
return this.services.session.addCommand('editUserAttributes', {
username: this.state.identity,
_context3.next = 4;
return this.services.commandExecutor.mutateResource('post', this.links.self, {
attributes: (0, _stringify2.default)(attributes)

@@ -281,14 +307,14 @@ });

case 4:
return _context2.abrupt("return", this);
return _context3.abrupt("return", this);
case 5:
case "end":
return _context2.stop();
return _context3.stop();
}
}
}, _callee2, this);
}, _callee3, this);
}));
function updateAttributes(_x) {
return _ref2.apply(this, arguments);
function updateAttributes(_x3) {
return _ref3.apply(this, arguments);
}

@@ -300,3 +326,3 @@

* Update Users friendlyName.
* @param {String|null} friendlyName - Updated friendlyName
* @param {String} friendlyName - Updated friendlyName
* @returns {Promise<User>}

@@ -308,9 +334,9 @@ */

value: function () {
var _ref3 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee3(friendlyName) {
return _regenerator2.default.wrap(function _callee3$(_context3) {
var _ref4 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee4(friendlyName) {
return _regenerator2.default.wrap(function _callee4$(_context4) {
while (1) {
switch (_context3.prev = _context3.next) {
switch (_context4.prev = _context4.next) {
case 0:
if (!(this.subscribed == 'unsubscribed')) {
_context3.next = 2;
_context4.next = 2;
break;

@@ -322,21 +348,20 @@ }

case 2:
_context3.next = 4;
return this.services.session.addCommand('editUserFriendlyName', {
username: this.state.identity,
friendlyName: friendlyName
_context4.next = 4;
return this.services.commandExecutor.mutateResource('post', this.links.self, {
friendly_name: friendlyName
});
case 4:
return _context3.abrupt("return", this);
return _context4.abrupt("return", this);
case 5:
case "end":
return _context3.stop();
return _context4.stop();
}
}
}, _callee3, this);
}, _callee4, this);
}));
function updateFriendlyName(_x2) {
return _ref3.apply(this, arguments);
function updateFriendlyName(_x4) {
return _ref4.apply(this, arguments);
}

@@ -354,13 +379,13 @@

value: function () {
var _ref4 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee4() {
return _regenerator2.default.wrap(function _callee4$(_context4) {
var _ref5 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee5() {
return _regenerator2.default.wrap(function _callee5$(_context5) {
while (1) {
switch (_context4.prev = _context4.next) {
switch (_context5.prev = _context5.next) {
case 0:
if (!this.promiseToFetch) {
_context4.next = 7;
_context5.next = 7;
break;
}
_context4.next = 3;
_context5.next = 3;
return this.promiseToFetch;

@@ -376,10 +401,10 @@

case "end":
return _context4.stop();
return _context5.stop();
}
}
}, _callee4, this);
}, _callee5, this);
}));
function unsubscribe() {
return _ref4.apply(this, arguments);
return _ref5.apply(this, arguments);
}

@@ -431,4 +456,4 @@

__decorate([typecheck_1.asyncTypeCheck(['string', 'number', 'boolean', 'object', typecheck_1.literal(null)]), __metadata("design:type", Function), __metadata("design:paramtypes", [Object]), __metadata("design:returntype", _promise2.default)], User.prototype, "updateAttributes", null);
__decorate([typecheck_1.asyncTypeCheck(['string', typecheck_1.literal(null)]), __metadata("design:type", Function), __metadata("design:paramtypes", [Object]), __metadata("design:returntype", _promise2.default)], User.prototype, "updateFriendlyName", null);
__decorate([twilio_sdk_type_validator_1.validateTypesAsync(['string', 'number', 'boolean', 'object', twilio_sdk_type_validator_1.literal(null)]), __metadata("design:type", Function), __metadata("design:paramtypes", [Object]), __metadata("design:returntype", _promise2.default)], User.prototype, "updateAttributes", null);
__decorate([twilio_sdk_type_validator_1.validateTypesAsync(['string']), __metadata("design:type", Function), __metadata("design:paramtypes", [Object]), __metadata("design:returntype", _promise2.default)], User.prototype, "updateFriendlyName", null);
exports.User = User;

@@ -435,0 +460,0 @@ /**

@@ -14,2 +14,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.UserDescriptor = void 0;
var logger_1 = require("./logger");

@@ -16,0 +17,0 @@ var util_1 = require("./util");

@@ -18,2 +18,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.Deferred = void 0;

@@ -20,0 +21,0 @@ var Deferred = function () {

@@ -18,2 +18,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.parseAttributes = exports.parseTime = exports.parseToNumber = exports.UriBuilder = exports.deepClone = exports.isDeepEqual = void 0;
var JsonDiff = require("rfc6902");

@@ -20,0 +21,0 @@ /**

@@ -11,14 +11,13 @@ /// <reference types="node" />

import { SyncClient } from 'twilio-sync';
import { Session } from './session';
import { ConsumptionHorizon } from './services/consumptionhorizon';
import { TypingIndicator } from './services/typingindicator';
import { Network } from './services/network';
import { Configuration } from './configuration';
import { CommandExecutor } from './commandexecutor';
export interface ChannelServices {
session: Session;
users: Users;
typingIndicator: TypingIndicator;
consumptionHorizon: ConsumptionHorizon;
network: Network;
mcsClient: McsClient;
syncClient: SyncClient;
commandExecutor: CommandExecutor;
}

@@ -38,2 +37,8 @@ interface ChannelDescriptor {

}
interface ChannelLinks {
self: string;
messages: string;
participants: string;
invites: string;
}
declare namespace Channel {

@@ -90,3 +95,5 @@ type UpdateReason = 'attributes' | 'createdBy' | 'dateCreated' | 'dateUpdated' | 'friendlyName' | 'lastConsumedMessageIndex' | 'state' | 'status' | 'uniqueName' | 'lastMessage' | 'notificationLevel';

readonly sid: string;
private services;
readonly links: ChannelLinks;
private readonly configuration;
private readonly services;
private channelState;

@@ -100,3 +107,10 @@ private statusSource;

private members;
constructor(descriptor: ChannelDescriptor, sid: string, links: ChannelLinks, configuration: Configuration, services: ChannelServices);
/**
* The Channel's state. Set to undefined if the channel is not a conversation.
* @typedef {Object | undefined} Channel#State
* @property {('active' | 'inactive' | 'closed')} current - the current state
* @property {Date} dateUpdated - date at which the latest channel state update happened
*/
/**
* These options can be passed to {@link Channel#sendMessage}.

@@ -129,9 +143,2 @@ * @typedef {Object} Channel#SendMediaOptions

*/
/**
* The Channel's state. Set to undefined if the channel is not a conversation.
* @typedef {Object | undefined} Channel#State
* @property {('active' | 'inactive' | 'closed')} current - the current state
* @property {Date} dateUpdated - date at which the latest channel state update happened
*/
constructor(services: ChannelServices, descriptor: ChannelDescriptor, sid: string);
get status(): Channel.Status;

@@ -146,3 +153,3 @@ get type(): Channel.Type;

get attributes(): Object;
get lastConsumedMessageIndex(): number;
get lastConsumedMessageIndex(): number | null;
get lastMessage(): Channel.LastMessage;

@@ -199,2 +206,3 @@ get notificationLevel(): Channel.NotificationLevel;

private _onMessageAdded;
private _setLastConsumedMessageIndex;
/**

@@ -312,6 +320,6 @@ * Add a participant to the Channel by its Identity.

* Remove a Member from the Channel.
* @param {String} member - identity of member to remove
* @param {String|Member} member - Member to remove. Could either be an identity string or a Member instance.
* @returns {Promise<void>}
*/
removeMember(member: any): Promise<void>;
removeMember(member: string | Member): Promise<void>;
/**

@@ -355,6 +363,6 @@ * Send a Message in the Channel.

* Update the Channel's friendlyName.
* @param {String|null} name - The new Channel friendlyName
* @param {String|null} friendlyName - The new Channel friendlyName
* @returns {Promise<Channel>}
*/
updateFriendlyName(name: string | null): Promise<Channel>;
updateFriendlyName(friendlyName: string | null): Promise<Channel>;
/**

@@ -369,6 +377,6 @@ * Set last consumed Channel's Message index to current consumption horizon.

* Update the Channel's unique name.
* @param {String} uniqueName - The new Channel uniqueName
* @param {String|null} uniqueName - New unique name for the Channel. Setting unique name to null removes it.
* @returns {Promise<Channel>}
*/
updateUniqueName(uniqueName: string): Promise<Channel>;
updateUniqueName(uniqueName: string | null): Promise<Channel>;
/**

@@ -375,0 +383,0 @@ * Gets User Descriptors for this channel.

@@ -12,2 +12,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.Channel = void 0;
const events_1 = require("events");

@@ -19,3 +20,3 @@ const logger_1 = require("./logger");

const util_1 = require("./util");
const typecheck_1 = require("./util/typecheck");
const twilio_sdk_type_validator_1 = require("twilio-sdk-type-validator");
const log = logger_1.Logger.scope('Channel');

@@ -73,38 +74,8 @@ const fieldMappings = {

class Channel extends events_1.EventEmitter {
/**
* These options can be passed to {@link Channel#sendMessage}.
* @typedef {Object} Channel#SendMediaOptions
* @property {String} contentType - content type of media
* @property {String | Buffer} media - content to post
*/
/**
* The update reason for <code>updated</code> event emitted on Channel
* @typedef {('attributes' | 'createdBy' | 'dateCreated' | 'dateUpdated' |
'friendlyName' | 'lastConsumedMessageIndex' | 'state' | 'status' | 'uniqueName' | 'lastMessage' |
'notificationLevel' )} Channel#UpdateReason
*/
/**
* The status of the Channel, relative to the Client: whether the Channel
* is <code>notParticipating</code> to local Client, Client is <code>invited</code> to or
* is <code>joined</code> to this Channel
* @typedef {('unknown' | 'notParticipating' | 'invited' | 'joined')} Channel#Status
*/
/**
* The type of Channel (<code>public</code> or <code>private</code>).
* @typedef {('public' | 'private')} Channel#Type
*/
/**
* The User's Notification level for Channel, determines whether the currently logged-in User will receive
* pushes for events in this Channel. Can be either <code>muted</code> or <code>default</code>,
* where <code>default</code> defers to global Service push configuration.
* @typedef {('default' | 'muted')} Channel#NotificationLevel
*/
/**
* The Channel's state. Set to undefined if the channel is not a conversation.
* @typedef {Object | undefined} Channel#State
* @property {('active' | 'inactive' | 'closed')} current - the current state
* @property {Date} dateUpdated - date at which the latest channel state update happened
*/
constructor(services, descriptor, sid) {
constructor(descriptor, sid, links, configuration, services) {
super();
this.sid = sid;
this.links = links;
this.configuration = configuration;
this.services = services;
let attributes = descriptor.attributes || {};

@@ -123,4 +94,2 @@ let createdBy = descriptor.createdBy;

}
this.services = services;
this.sid = sid;
this.entityName = descriptor.channel;

@@ -141,8 +110,11 @@ this.channelState = {

}
const membersLinks = {
participants: this.links.participants
};
this.members = new Map();
this.membersEntity = new members_1.Members(this, this.services, this.members);
this.membersEntity = new members_1.Members(this, this.members, membersLinks, this.configuration, this.services);
this.membersEntity.on('memberJoined', this.emit.bind(this, 'memberJoined'));
this.membersEntity.on('memberLeft', this.emit.bind(this, 'memberLeft'));
this.membersEntity.on('memberUpdated', (args) => this.emit('memberUpdated', args));
this.messagesEntity = new messages_1.Messages(this, services);
this.messagesEntity = new messages_1.Messages(this, this.configuration, services);
this.messagesEntity.on('messageAdded', message => this._onMessageAdded(message));

@@ -152,2 +124,36 @@ this.messagesEntity.on('messageUpdated', (args) => this.emit('messageUpdated', args));

}
/**
* The Channel's state. Set to undefined if the channel is not a conversation.
* @typedef {Object | undefined} Channel#State
* @property {('active' | 'inactive' | 'closed')} current - the current state
* @property {Date} dateUpdated - date at which the latest channel state update happened
*/
/**
* These options can be passed to {@link Channel#sendMessage}.
* @typedef {Object} Channel#SendMediaOptions
* @property {String} contentType - content type of media
* @property {String | Buffer} media - content to post
*/
/**
* The update reason for <code>updated</code> event emitted on Channel
* @typedef {('attributes' | 'createdBy' | 'dateCreated' | 'dateUpdated' |
'friendlyName' | 'lastConsumedMessageIndex' | 'state' | 'status' | 'uniqueName' | 'lastMessage' |
'notificationLevel' )} Channel#UpdateReason
*/
/**
* The status of the Channel, relative to the Client: whether the Channel
* is <code>notParticipating</code> to local Client, Client is <code>invited</code> to or
* is <code>joined</code> to this Channel
* @typedef {('unknown' | 'notParticipating' | 'invited' | 'joined')} Channel#Status
*/
/**
* The type of Channel (<code>public</code> or <code>private</code>).
* @typedef {('public' | 'private')} Channel#Type
*/
/**
* The User's Notification level for Channel, determines whether the currently logged-in User will receive
* pushes for events in this Channel. Can be either <code>muted</code> or <code>default</code>,
* where <code>default</code> defers to global Service push configuration.
* @typedef {('default' | 'muted')} Channel#NotificationLevel
*/
get status() { return this.channelState.status; }

@@ -186,5 +192,5 @@ get type() { return this.channelState.type; }

this.entity = entity;
this.entity.on('updated', args => { this._update(args.value); });
this.entity.on('updated', args => { this._update(args.data); });
this.entity.on('removed', () => this.emit('removed', this));
this._update(this.entity.value);
this._update(this.entity.data);
return entity;

@@ -212,5 +218,5 @@ })

await this._subscribe();
log.trace('_subscribeStreams, this.entity.value=', this.entity.value);
const messagesObjectName = this.entity.value.messages;
const rosterObjectName = this.entity.value.roster;
log.trace('_subscribeStreams, this.entity.data=', this.entity.data);
const messagesObjectName = this.entity.data.messages;
const rosterObjectName = this.entity.data.roster;
await Promise.all([

@@ -429,2 +435,8 @@ this.messagesEntity.subscribe(messagesObjectName),

}
async _setLastConsumedMessageIndex(index) {
const result = await this.services.commandExecutor.mutateResource('post', `${this.configuration.links.myConversations}/${this.sid}`, {
last_consumed_message_index: index
});
return result.unread_messages_count;
}
/**

@@ -436,3 +448,3 @@ * Add a participant to the Channel by its Identity.

async add(identity) {
return this.membersEntity.add(identity);
await this.membersEntity.add(identity);
}

@@ -448,3 +460,6 @@ /**

await this._subscribeStreams();
return this.services.consumptionHorizon.advanceLastConsumedMessageIndexForChannel(this.sid, index, this.lastConsumedMessageIndex);
if (index < this.lastConsumedMessageIndex) {
return await this._setLastConsumedMessageIndex(this.lastConsumedMessageIndex);
}
return await this._setLastConsumedMessageIndex(index);
}

@@ -456,5 +471,3 @@ /**

async decline() {
await this.services.session.addCommand('declineInvitation', {
channelSid: this.sid
});
await this.services.commandExecutor.mutateResource('delete', `${this.links.invites}/${this.configuration.userIdentity}`);
return this;

@@ -467,5 +480,3 @@ }

async delete() {
await this.services.session.addCommand('destroyChannel', {
channelSid: this.sid
});
await this.services.commandExecutor.mutateResource('delete', this.links.self);
return this;

@@ -515,6 +526,5 @@ }

async getMembersCount() {
let links = await this.services.session.getSessionLinks();
let url = new util_1.UriBuilder(links.publicChannelsUrl).path(this.sid).build();
let response = await this.services.network.get(url);
return response.body.members_count;
const url = new util_1.UriBuilder(this.configuration.links.conversations).path(this.sid).build();
const response = await this.services.network.get(url);
return response.body.participants_count;
}

@@ -549,5 +559,4 @@ /**

async getMessagesCount() {
let links = await this.services.session.getSessionLinks();
let url = new util_1.UriBuilder(links.publicChannelsUrl).path(this.sid).build();
let response = await this.services.network.get(url);
const url = new util_1.UriBuilder(this.configuration.links.conversations).path(this.sid).build();
const response = await this.services.network.get(url);
return response.body.messages_count;

@@ -568,12 +577,12 @@ }

async getUnconsumedMessagesCount() {
let links = await this.services.session.getSessionLinks();
let url = new util_1.UriBuilder(links.myChannelsUrl).arg('ChannelSid', this.sid).build();
let response = await this.services.network.get(url);
if (response.body.channels.length && response.body.channels[0].channel_sid == this.sid) {
if ((typeof response.body.channels[0].unread_messages_count !== 'undefined') && response.body.channels[0].unread_messages_count != null) {
return response.body.channels[0].unread_messages_count;
}
return null;
const url = new util_1.UriBuilder(this.configuration.links.myConversations).path(this.sid).build();
const response = await this.services.network.get(url);
if (response.body.conversation_sid !== this.sid) {
throw new Error('Channel was not found in the user channels list');
}
throw new Error('Channel is not in user channels list');
const unreadMessageCount = response.body.unread_messages_count;
if (typeof unreadMessageCount === 'number') {
return unreadMessageCount;
}
return null;
}

@@ -593,3 +602,5 @@ /**

async join() {
await this.services.session.addCommand('joinChannelV2', { channelSid: this.sid });
await this.services.commandExecutor.mutateResource('post', this.links.participants, {
identity: this.configuration.userIdentity
});
return this;

@@ -603,3 +614,3 @@ }

if (this.channelState.status === 'joined') {
await this.services.session.addCommand('leaveChannel', { channelSid: this.sid });
await this.services.commandExecutor.mutateResource('delete', `${this.links.participants}/${this.configuration.userIdentity}`);
}

@@ -610,11 +621,7 @@ return this;

* Remove a Member from the Channel.
* @param {String} member - identity of member to remove
* @param {String|Member} member - Member to remove. Could either be an identity string or a Member instance.
* @returns {Promise<void>}
*/
async removeMember(member) {
if (member instanceof member_1.Member) {
await this.membersEntity.removeBySid(member.sid);
return;
}
await this.membersEntity.removeByIdentity(member);
await this.membersEntity.remove(typeof member === 'string' ? member : member.sid);
}

@@ -630,7 +637,7 @@ /**

if (typeof message === 'string' || message === null) {
let response = await this.messagesEntity.send(message, messageAttributes);
return util_1.parseToNumber(response.messageId);
const response = await this.messagesEntity.send(message, messageAttributes);
return util_1.parseToNumber(response.index);
}
let response = await this.messagesEntity.sendMedia(message, messageAttributes);
return util_1.parseToNumber(response.messageId);
const response = await this.messagesEntity.sendMedia(message, messageAttributes);
return util_1.parseToNumber(response.index);
}

@@ -655,3 +662,3 @@ /**

await this._subscribeStreams();
return this.services.consumptionHorizon.updateLastConsumedMessageIndexForChannel(this.sid, null);
return await this._setLastConsumedMessageIndex(null);
}

@@ -664,3 +671,5 @@ /**

async setUserNotificationLevel(notificationLevel) {
await this.services.session.addCommand('editNotificationLevel', { channelSid: this.sid, notificationLevel: notificationLevel });
await this.services.commandExecutor.mutateResource('post', `${this.configuration.links.myConversations}/${this.sid}`, {
notification_level: notificationLevel
});
}

@@ -681,6 +690,3 @@ /**

async updateAttributes(attributes) {
await this.services.session.addCommand('editAttributes', {
channelSid: this.sid,
attributes: JSON.stringify(attributes)
});
await this.services.commandExecutor.mutateResource('post', this.links.self, { attributes: attributes !== undefined ? JSON.stringify(attributes) : undefined });
return this;

@@ -690,11 +696,8 @@ }

* Update the Channel's friendlyName.
* @param {String|null} name - The new Channel friendlyName
* @param {String|null} friendlyName - The new Channel friendlyName
* @returns {Promise<Channel>}
*/
async updateFriendlyName(name) {
if (this.channelState.friendlyName !== name) {
await this.services.session.addCommand('editFriendlyName', {
channelSid: this.sid,
friendlyName: name
});
async updateFriendlyName(friendlyName) {
if (this.channelState.friendlyName !== friendlyName) {
await this.services.commandExecutor.mutateResource('post', this.links.self, { friendly_name: friendlyName });
}

@@ -711,7 +714,7 @@ return this;

await this._subscribeStreams();
return this.services.consumptionHorizon.updateLastConsumedMessageIndexForChannel(this.sid, index);
return this._setLastConsumedMessageIndex(index);
}
/**
* Update the Channel's unique name.
* @param {String} uniqueName - The new Channel uniqueName
* @param {String|null} uniqueName - New unique name for the Channel. Setting unique name to null removes it.
* @returns {Promise<Channel>}

@@ -724,6 +727,3 @@ */

}
await this.services.session.addCommand('editUniqueName', {
channelSid: this.sid,
uniqueName: uniqueName
});
await this.services.commandExecutor.mutateResource('post', this.links.self, { unique_name: uniqueName });
}

@@ -741,3 +741,3 @@ return this;

__decorate([
typecheck_1.asyncTypeCheck(typecheck_1.nonEmptyString),
twilio_sdk_type_validator_1.validateTypesAsync(twilio_sdk_type_validator_1.nonEmptyString),
__metadata("design:type", Function),

@@ -748,3 +748,3 @@ __metadata("design:paramtypes", [String]),

__decorate([
typecheck_1.asyncTypeCheck(typecheck_1.nonNegativeInteger),
twilio_sdk_type_validator_1.validateTypesAsync(twilio_sdk_type_validator_1.nonNegativeInteger),
__metadata("design:type", Function),

@@ -755,3 +755,3 @@ __metadata("design:paramtypes", [Number]),

__decorate([
typecheck_1.asyncTypeCheck(['undefined', typecheck_1.nonNegativeInteger], ['undefined', typecheck_1.nonNegativeInteger], ['undefined', typecheck_1.literal('backwards', 'forward')]),
twilio_sdk_type_validator_1.validateTypesAsync(['undefined', twilio_sdk_type_validator_1.nonNegativeInteger], ['undefined', twilio_sdk_type_validator_1.nonNegativeInteger], ['undefined', twilio_sdk_type_validator_1.literal('backwards', 'forward')]),
__metadata("design:type", Function),

@@ -762,3 +762,3 @@ __metadata("design:paramtypes", [Number, Number, String]),

__decorate([
typecheck_1.asyncTypeCheck(typecheck_1.nonEmptyString),
twilio_sdk_type_validator_1.validateTypesAsync(twilio_sdk_type_validator_1.nonEmptyString),
__metadata("design:type", Function),

@@ -769,3 +769,3 @@ __metadata("design:paramtypes", [String]),

__decorate([
typecheck_1.asyncTypeCheck(typecheck_1.nonEmptyString),
twilio_sdk_type_validator_1.validateTypesAsync(twilio_sdk_type_validator_1.nonEmptyString),
__metadata("design:type", Function),

@@ -776,3 +776,3 @@ __metadata("design:paramtypes", [String]),

__decorate([
typecheck_1.asyncTypeCheck(typecheck_1.nonEmptyString),
twilio_sdk_type_validator_1.validateTypesAsync(twilio_sdk_type_validator_1.nonEmptyString),
__metadata("design:type", Function),

@@ -783,3 +783,3 @@ __metadata("design:paramtypes", [String]),

__decorate([
typecheck_1.asyncTypeCheck([typecheck_1.nonEmptyString, member_1.Member]),
twilio_sdk_type_validator_1.validateTypesAsync([twilio_sdk_type_validator_1.nonEmptyString, member_1.Member]),
__metadata("design:type", Function),

@@ -790,3 +790,21 @@ __metadata("design:paramtypes", [Object]),

__decorate([
typecheck_1.asyncTypeCheck(['string', 'object', typecheck_1.literal(null)], ['undefined', 'string', 'number', 'boolean', 'object', typecheck_1.literal(null)]),
twilio_sdk_type_validator_1.validateTypesAsync([
'string',
twilio_sdk_type_validator_1.literal(null),
// Wrapping it into a custom rule is necessary because the FormData class is not available on initialization.
twilio_sdk_type_validator_1.custom((value) => [value instanceof FormData, 'an instance of FormData']),
twilio_sdk_type_validator_1.objectSchema('media options', {
contentType: [twilio_sdk_type_validator_1.nonEmptyString, 'undefined'],
media: twilio_sdk_type_validator_1.custom((value) => {
let isValid = (typeof value === 'string' && value.length > 0) || value instanceof Uint8Array || value instanceof ArrayBuffer;
if (typeof Blob === 'function') {
isValid = isValid || value instanceof Blob;
}
return [
isValid,
'a non-empty string, an instance of Buffer or an instance of Blob'
];
})
})
], ['undefined', 'string', 'number', 'boolean', 'object', twilio_sdk_type_validator_1.literal(null)]),
__metadata("design:type", Function),

@@ -797,3 +815,3 @@ __metadata("design:paramtypes", [Object, Object]),

__decorate([
typecheck_1.asyncTypeCheck(typecheck_1.literal('default', 'muted')),
twilio_sdk_type_validator_1.validateTypesAsync(twilio_sdk_type_validator_1.literal('default', 'muted')),
__metadata("design:type", Function),

@@ -804,3 +822,3 @@ __metadata("design:paramtypes", [String]),

__decorate([
typecheck_1.asyncTypeCheck(['string', 'number', 'boolean', 'object', typecheck_1.literal(null)]),
twilio_sdk_type_validator_1.validateTypesAsync(['string', 'number', 'boolean', 'object', twilio_sdk_type_validator_1.literal(null)]),
__metadata("design:type", Function),

@@ -811,3 +829,3 @@ __metadata("design:paramtypes", [Object]),

__decorate([
typecheck_1.asyncTypeCheck(['string', typecheck_1.literal(null)]),
twilio_sdk_type_validator_1.validateTypesAsync(['string', twilio_sdk_type_validator_1.literal(null)]),
__metadata("design:type", Function),

@@ -818,3 +836,3 @@ __metadata("design:paramtypes", [String]),

__decorate([
typecheck_1.asyncTypeCheck([typecheck_1.literal(null), typecheck_1.nonNegativeInteger]),
twilio_sdk_type_validator_1.validateTypesAsync([twilio_sdk_type_validator_1.literal(null), twilio_sdk_type_validator_1.nonNegativeInteger]),
__metadata("design:type", Function),

@@ -825,3 +843,3 @@ __metadata("design:paramtypes", [Number]),

__decorate([
typecheck_1.asyncTypeCheck(['string', 'undefined', typecheck_1.literal(null)]),
twilio_sdk_type_validator_1.validateTypesAsync(['string', twilio_sdk_type_validator_1.literal(null)]),
__metadata("design:type", Function),

@@ -828,0 +846,0 @@ __metadata("design:paramtypes", [String]),

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ChannelDescriptor = void 0;
const logger_1 = require("./logger");

@@ -34,10 +35,4 @@ const util_1 = require("./util");

this.descriptor = descriptor;
if (descriptor.sid) {
this.sid = descriptor.sid;
this.channel = descriptor.sid + '.channel';
}
else {
this.sid = descriptor.channel_sid;
this.channel = descriptor.channel_sid + '.channel';
}
this.sid = descriptor.sid || descriptor.conversation_sid;
this.channel = `${this.sid}.channel`;
this.uniqueName = descriptor.unique_name;

@@ -52,13 +47,6 @@ this.friendlyName = descriptor.friendly_name;

this.type = descriptor.type;
this.isPrivate = descriptor.type == 'private' ? true : false;
this.isPrivate = descriptor.type === 'private';
this.lastConsumedMessageIndex = descriptor.last_consumed_message_index;
if (descriptor.notification_level) {
this.notificationLevel = descriptor.notification_level;
}
if (descriptor.status) {
this.status = descriptor.status;
}
else {
this.status = 'unknown';
}
this.notificationLevel = descriptor.notification_level || undefined;
this.status = descriptor.status || 'unknown';
}

@@ -65,0 +53,0 @@ /**

@@ -32,2 +32,3 @@ /// <reference types="node" />

Chat?: any;
IPMessaging?: any;
Sync?: any;

@@ -37,2 +38,3 @@ Notification?: any;

clientMetadata?: any;
disableDeepClone?: boolean;
}

@@ -84,9 +86,9 @@ interface CreateChannelOptions {

declare class Client extends EventEmitter {
private readonly options;
connectionState: Client.ConnectionState;
private sessionPromise;
private channelsPromise;
private configurationPromise;
private fpaToken;
private config;
private configuration;
private channels;
private options;
private services;

@@ -97,3 +99,10 @@ static readonly version: string;

private static readonly supportedPushDataFields;
private constructor();
/**
* These options can be passed to {@link Client#getLocalChannels}.
* @typedef {Object} Client#ChannelSortingOptions
* @property {('lastMessage'|'friendlyName'|'uniqueName')} [criteria] - Sorting criteria for Channels array
* @property {('ascending'|'descending')} [order] - Sorting order. If not present, then default is <code>ascending</code>
*/
/**
* These options can be passed to Client constructor.

@@ -121,9 +130,2 @@ * @typedef {Object} Client#ClientOptions

/**
* These options can be passed to {@link Client#getLocalChannels}.
* @typedef {Object} Client#ChannelSortingOptions
* @property {('lastMessage'|'friendlyName'|'uniqueName')} [criteria] - Sorting criteria for Channels array
* @property {('ascending'|'descending')} [order] - Sorting order. If not present, then default is <code>ascending</code>
*/
private constructor();
/**
* Factory method to create Chat client instance.

@@ -130,0 +132,0 @@ *

@@ -12,2 +12,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.PushNotification = exports.Client = exports.User = void 0;
const events_1 = require("events");

@@ -17,7 +18,6 @@ const logger_1 = require("./logger");

const user_1 = require("./user");
exports.User = user_1.User;
Object.defineProperty(exports, "User", { enumerable: true, get: function () { return user_1.User; } });
const publicchannels_1 = require("./data/publicchannels");
const network_1 = require("./services/network");
const notificationtypes_1 = require("./interfaces/notificationtypes");
const synclist_1 = require("./synclist");
const twilsock_1 = require("twilsock");

@@ -27,12 +27,11 @@ const twilio_notifications_1 = require("twilio-notifications");

const twilio_mcs_client_1 = require("twilio-mcs-client");
const session_1 = require("./session");
const channels_1 = require("./data/channels");
const users_1 = require("./data/users");
const typingindicator_1 = require("./services/typingindicator");
const consumptionhorizon_1 = require("./services/consumptionhorizon");
const userchannels_1 = require("./data/userchannels");
const pushnotification_1 = require("./pushnotification");
exports.PushNotification = pushnotification_1.PushNotification;
Object.defineProperty(exports, "PushNotification", { enumerable: true, get: function () { return pushnotification_1.PushNotification; } });
const util_1 = require("./util");
const typecheck_1 = require("./util/typecheck");
const twilio_sdk_type_validator_1 = require("twilio-sdk-type-validator");
const commandexecutor_1 = require("./commandexecutor");
const log = logger_1.Logger.scope('Client');

@@ -74,38 +73,11 @@ const SDK_VERSION = require('./../package.json').version;

class Client extends events_1.EventEmitter {
/**
* These options can be passed to Client constructor.
* @typedef {Object} Client#ClientOptions
* @property {String} [logLevel='error'] - The level of logging to enable. Valid options
* (from strictest to broadest): ['silent', 'error', 'warn', 'info', 'debug', 'trace']
*/
/**
* These options can be passed to {@link Client#createChannel}.
* @typedef {Object} Client#CreateChannelOptions
* @property {any} [attributes] - Any custom attributes to attach to the Channel
* @property {String} [friendlyName] - The non-unique display name of the Channel
* @property {Boolean} [isPrivate] - Whether or not this Channel should be visible to uninvited Clients
* @property {String} [uniqueName] - The unique identity name of the Channel
*/
/**
* Connection state of Client.
* @typedef {('connecting'|'connected'|'disconnecting'|'disconnected'|'denied')} Client#ConnectionState
*/
/**
* Notifications channel type.
* @typedef {('gcm'|'fcm'|'apn')} Client#NotificationsChannelType
*/
/**
* These options can be passed to {@link Client#getLocalChannels}.
* @typedef {Object} Client#ChannelSortingOptions
* @property {('lastMessage'|'friendlyName'|'uniqueName')} [criteria] - Sorting criteria for Channels array
* @property {('ascending'|'descending')} [order] - Sorting order. If not present, then default is <code>ascending</code>
*/
constructor(token, options) {
constructor(token, options = {}) {
var _a;
super();
this.options = options;
this.connectionState = 'connecting';
this.sessionPromise = null;
this.channelsPromise = null;
this.configurationPromise = null;
this.version = SDK_VERSION;
this.parsePushNotification = Client.parsePushNotification;
this.options = (options || {});
if (!this.options.disableDeepClone) {

@@ -132,3 +104,3 @@ let options = Object.assign(Object.assign({}, this.options), { transport: undefined, twilsockClient: undefined });

this.options.Sync = this.options.Sync || {};
if (typeof this.options.Sync.enableSessionStorage === 'undefined') {
if (!((_a = this.options.Sync) === null || _a === void 0 ? void 0 : _a.enableSessionStorage)) {
this.options.Sync.enableSessionStorage = true;

@@ -143,3 +115,2 @@ }

this.services = new ClientServices();
this.config = new configuration_1.Configuration(this.options);
this.options.twilsockClient = this.options.twilsockClient || new twilsock_1.Twilsock(token, productId, this.options);

@@ -153,27 +124,25 @@ this.options.transport = this.options.transport || this.options.twilsockClient;

this.services.notificationClient = this.options.notificationsClient;
this.services.session = new session_1.Session(this.services, this.config);
this.sessionPromise = this.services.session.initialize();
this.services.network = new network_1.Network(this.config, this.services);
this.services.users = new users_1.Users({
session: this.services.session,
network: this.services.network,
syncClient: this.services.syncClient
});
this.services.users.on('userSubscribed', this.emit.bind(this, 'userSubscribed'));
this.services.users.on('userUpdated', (args) => this.emit('userUpdated', args));
this.services.users.on('userUnsubscribed', this.emit.bind(this, 'userUnsubscribed'));
this.services.twilsockClient.on('tokenAboutToExpire', ttl => this.emit('tokenAboutToExpire', ttl));
this.services.twilsockClient.on('tokenExpired', () => this.emit('tokenExpired'));
this.services.twilsockClient.on('connectionError', (error) => this.emit('connectionError', error));
this.services.consumptionHorizon = new consumptionhorizon_1.ConsumptionHorizon(this.services);
this.services.typingIndicator = new typingindicator_1.TypingIndicator(this.config, {
transport: this.services.twilsockClient,
notificationClient: this.services.notificationClient
}, this.getChannelBySid.bind(this));
this.services.syncList = new synclist_1.SyncList(this.services);
this.channels = new channels_1.Channels(this.services);
this.channelsPromise = this.sessionPromise.then(() => {
const configurationOptions = options.Chat || options.IPMessaging || options || {};
const region = configurationOptions.region || options.region;
const baseUrl = configurationOptions.apiUri
|| configurationOptions.typingUri
|| `https://aim.${region || 'us1'}.twilio.com`;
this.services.commandExecutor = new commandexecutor_1.CommandExecutor(baseUrl, { transport: this.options.transport }, productId);
this.configurationPromise = this.services.commandExecutor.fetchResource('Client/v1/Configuration');
this.configurationPromise
.then((configurationResponse) => {
this.configuration = new configuration_1.Configuration(this.options, configurationResponse, log);
this.services.typingIndicator = new typingindicator_1.TypingIndicator(this.getChannelBySid.bind(this), this.configuration, this.services);
this.services.network = new network_1.Network(this.configuration, this.services);
this.services.users = new users_1.Users(this.configuration, this.services);
this.services.users.on('userSubscribed', this.emit.bind(this, 'userSubscribed'));
this.services.users.on('userUpdated', (args) => this.emit('userUpdated', args));
this.services.users.on('userUnsubscribed', this.emit.bind(this, 'userUnsubscribed'));
this.services.twilsockClient.on('tokenAboutToExpire', ttl => this.emit('tokenAboutToExpire', ttl));
this.services.twilsockClient.on('tokenExpired', () => this.emit('tokenExpired'));
this.services.twilsockClient.on('connectionError', (error) => this.emit('connectionError', error));
this.channels = new channels_1.Channels(this.configuration, this.services);
this.channels.on('channelAdded', this.emit.bind(this, 'channelAdded'));
this.channels.on('channelInvited', this.emit.bind(this, 'channelInvited'));
this.channels.on('channelRemoved', this.emit.bind(this, 'channelRemoved'));
this.channels.on('channelInvited', this.emit.bind(this, 'channelInvited'));
this.channels.on('channelJoined', this.emit.bind(this, 'channelJoined'));

@@ -190,4 +159,6 @@ this.channels.on('channelLeft', this.emit.bind(this, 'channelLeft'));

this.channels.on('typingEnded', this.emit.bind(this, 'typingEnded'));
return this.channels.fetchChannels();
}).then(() => this.channels);
});
this.channelsPromise = this.configurationPromise
.then(() => this.channels.fetchChannels())
.then(() => this.channels);
this.services.notificationClient.on('connectionStateChanged', (state) => {

@@ -219,2 +190,30 @@ let changedConnectionState = null;

/**
* These options can be passed to {@link Client#getLocalChannels}.
* @typedef {Object} Client#ChannelSortingOptions
* @property {('lastMessage'|'friendlyName'|'uniqueName')} [criteria] - Sorting criteria for Channels array
* @property {('ascending'|'descending')} [order] - Sorting order. If not present, then default is <code>ascending</code>
*/
/**
* These options can be passed to Client constructor.
* @typedef {Object} Client#ClientOptions
* @property {String} [logLevel='error'] - The level of logging to enable. Valid options
* (from strictest to broadest): ['silent', 'error', 'warn', 'info', 'debug', 'trace']
*/
/**
* These options can be passed to {@link Client#createChannel}.
* @typedef {Object} Client#CreateChannelOptions
* @property {any} [attributes] - Any custom attributes to attach to the Channel
* @property {String} [friendlyName] - The non-unique display name of the Channel
* @property {Boolean} [isPrivate] - Whether or not this Channel should be visible to uninvited Clients
* @property {String} [uniqueName] - The unique identity name of the Channel
*/
/**
* Connection state of Client.
* @typedef {('connecting'|'connected'|'disconnecting'|'disconnected'|'denied')} Client#ConnectionState
*/
/**
* Notifications channel type.
* @typedef {('gcm'|'fcm'|'apn')} Client#NotificationsChannelType
*/
/**
* Factory method to create Chat client instance.

@@ -232,3 +231,3 @@ *

get user() { return this.services.users.myself; }
get reachabilityEnabled() { return this.services.session.reachabilityEnabled; }
get reachabilityEnabled() { return this.configuration.reachabilityEnabled; }
get token() { return this.fpaToken; }

@@ -262,10 +261,9 @@ subscribeToPushNotifications(channelType) {

async initialize() {
await this.sessionPromise;
await this.configurationPromise;
Client.supportedPushChannels.forEach(channelType => this.subscribeToPushNotifications(channelType));
let links = await this.services.session.getSessionLinks();
this.services.publicChannels = new publicchannels_1.PublicChannels(this, this.services, links.publicChannelsUrl);
this.services.userChannels = new userchannels_1.UserChannels(this, this.services, links.myChannelsUrl);
let options = Object.assign(this.options);
this.services.publicChannels = new publicchannels_1.PublicChannels(this, this.services, this.configuration.links.conversations);
this.services.userChannels = new userchannels_1.UserChannels(this, this.services, this.configuration.links.myConversations);
const options = Object.assign(this.options);
options.transport = null;
this.services.mcsClient = new twilio_mcs_client_1.McsClient(this.fpaToken, links.mediaServiceUrl, options);
this.services.mcsClient = new twilio_mcs_client_1.McsClient(this.fpaToken, this.configuration.links.mediaService, options);
await this.services.typingIndicator.initialize();

@@ -295,3 +293,3 @@ }

.then(() => this.services.mcsClient.updateToken(token))
.then(() => this.sessionPromise);
.then(() => this.configurationPromise);
return this;

@@ -305,3 +303,3 @@ }

async getChannelBySid(channelSid) {
return this.channels.syncListRead.promise.then(() => this.channels.getChannel(channelSid)
return this.channels.myChannelsRead.promise.then(() => this.channels.getChannel(channelSid)
.then(channel => channel || this.services.publicChannels.getChannelBySid(channelSid).then(x => this.channels.pushChannel(x))));

@@ -315,3 +313,3 @@ }

async getChannelByUniqueName(uniqueName) {
return this.channels.syncListRead.promise.then(() => this.services.publicChannels.getChannelByUniqueName(uniqueName).then(x => this.channels.pushChannel(x)));
return this.channels.myChannelsRead.promise.then(() => this.services.publicChannels.getChannelByUniqueName(uniqueName).then(x => this.channels.pushChannel(x)));
}

@@ -335,3 +333,2 @@ /**

return this.channelsPromise.then(channels => {
var _a;
let result = [];

@@ -341,3 +338,3 @@ channels.channels.forEach(value => {

});
const sortingOrder = ((_a = sortingOptions) === null || _a === void 0 ? void 0 : _a.order) || 'ascending';
const sortingOrder = (sortingOptions === null || sortingOptions === void 0 ? void 0 : sortingOptions.order) || 'ascending';
if (sortingOptions && sortingOptions.criteria) {

@@ -552,3 +549,3 @@ if (sortingOptions.criteria === 'lastMessage') {

__decorate([
typecheck_1.asyncTypeCheck(typecheck_1.nonEmptyString),
twilio_sdk_type_validator_1.validateTypesAsync(twilio_sdk_type_validator_1.nonEmptyString),
__metadata("design:type", Function),

@@ -559,3 +556,3 @@ __metadata("design:paramtypes", [String]),

__decorate([
typecheck_1.asyncTypeCheck(typecheck_1.nonEmptyString),
twilio_sdk_type_validator_1.validateTypesAsync(twilio_sdk_type_validator_1.nonEmptyString),
__metadata("design:type", Function),

@@ -566,3 +563,3 @@ __metadata("design:paramtypes", [String]),

__decorate([
typecheck_1.asyncTypeCheck('string'),
twilio_sdk_type_validator_1.validateTypesAsync(twilio_sdk_type_validator_1.nonEmptyString),
__metadata("design:type", Function),

@@ -573,23 +570,7 @@ __metadata("design:paramtypes", [String]),

__decorate([
typecheck_1.asyncTypeCheck([
twilio_sdk_type_validator_1.validateTypesAsync([
'undefined',
typecheck_1.custom((value) => {
const baseDescription = 'valid sorting options';
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
return [false, `${baseDescription} (should be a pure object)`];
}
const literalMap = new Map([
['criteria', ['lastMessage', 'friendlyName', 'uniqueName']],
['order', ['ascending', 'descending']]
]);
for (const [field, literals] of literalMap.entries()) {
if (value[field] !== undefined && !literals.includes(value[field])) {
return [
false,
`${baseDescription} (sortingOptions.${field} should be one of: "${literals.join('", "')}")`,
`malformed sorting options (sortingOptions.${field} is ${typecheck_1.stringifyReceivedType(value[field])})`
];
}
}
return [true];
twilio_sdk_type_validator_1.objectSchema('sorting options', {
criteria: [twilio_sdk_type_validator_1.literal('lastMessage', 'friendlyName', 'uniqueName'), 'undefined'],
order: [twilio_sdk_type_validator_1.literal('ascending', 'descending'), 'undefined']
})

@@ -602,24 +583,8 @@ ]),

__decorate([
typecheck_1.asyncTypeCheck([
twilio_sdk_type_validator_1.validateTypesAsync([
'undefined',
typecheck_1.custom((value) => {
const baseDescription = 'valid channel options';
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
return [false, `${baseDescription} (should be a pure object)`];
}
const typeCheckMap = new Map([
['friendlyName', 'string'],
['isPrivate', 'boolean'],
['uniqueName', 'string']
]);
for (const [field, type] of typeCheckMap.entries()) {
if (value[field] !== undefined && typeof value[field] !== type) {
return [
false,
`${baseDescription} (options.${field} should be of type ${type})`,
`malformed channel options (options.${field} is ${typecheck_1.stringifyReceivedType(value[field])})`
];
}
}
return [true];
twilio_sdk_type_validator_1.objectSchema('channel options', {
friendlyName: ['string', 'undefined'],
isPrivate: ['boolean', 'undefined'],
uniqueName: ['string', 'undefined']
})

@@ -632,3 +597,3 @@ ]),

__decorate([
typecheck_1.asyncTypeCheck(typecheck_1.literal('gcm', 'fcm', 'apn'), 'string'),
twilio_sdk_type_validator_1.validateTypesAsync(twilio_sdk_type_validator_1.literal('gcm', 'fcm', 'apn'), 'string'),
__metadata("design:type", Function),

@@ -639,3 +604,3 @@ __metadata("design:paramtypes", [String, String]),

__decorate([
typecheck_1.asyncTypeCheck(typecheck_1.literal('gcm', 'fcm', 'apn')),
twilio_sdk_type_validator_1.validateTypesAsync(twilio_sdk_type_validator_1.literal('gcm', 'fcm', 'apn')),
__metadata("design:type", Function),

@@ -646,3 +611,3 @@ __metadata("design:paramtypes", [String]),

__decorate([
typecheck_1.asyncTypeCheck(typecheck_1.pureObject),
twilio_sdk_type_validator_1.validateTypesAsync(twilio_sdk_type_validator_1.pureObject),
__metadata("design:type", Function),

@@ -653,3 +618,3 @@ __metadata("design:paramtypes", [Object]),

__decorate([
typecheck_1.asyncTypeCheck(typecheck_1.nonEmptyString),
twilio_sdk_type_validator_1.validateTypesAsync(twilio_sdk_type_validator_1.nonEmptyString),
__metadata("design:type", Function),

@@ -660,3 +625,3 @@ __metadata("design:paramtypes", [String]),

__decorate([
typecheck_1.typeCheck(typecheck_1.nonEmptyString),
twilio_sdk_type_validator_1.validateTypesAsync(twilio_sdk_type_validator_1.nonEmptyString),
__metadata("design:type", Function),

@@ -667,3 +632,3 @@ __metadata("design:paramtypes", [String]),

__decorate([
typecheck_1.asyncTypeCheck('string', ['undefined', typecheck_1.pureObject]),
twilio_sdk_type_validator_1.validateTypesAsync('string', ['undefined', twilio_sdk_type_validator_1.pureObject]),
__metadata("design:type", Function),

@@ -674,3 +639,3 @@ __metadata("design:paramtypes", [String, Object]),

__decorate([
typecheck_1.typeCheck(typecheck_1.pureObject),
twilio_sdk_type_validator_1.validateTypes(twilio_sdk_type_validator_1.pureObject),
__metadata("design:type", Function),

@@ -677,0 +642,0 @@ __metadata("design:paramtypes", [Object]),

@@ -0,21 +1,32 @@

import { ConfigurationResponse } from './interfaces/commands/configuration';
import { Logger } from './logger';
interface BackoffConfiguration {
min: number;
max: number;
maxAttemptsCount: number;
}
declare class Configuration {
token: string;
readonly links: {
myConversations: string;
conversations: string;
users: string;
currentUser: string;
typing: string;
mediaService: string;
messagesReceipts: string;
};
readonly productId?: string;
readonly typingIndicatorTimeoutOverride?: number;
readonly httpCacheIntervalOverride?: string;
readonly consumptionReportIntervalOverride?: number;
readonly userInfosToSubscribeOverride?: number;
readonly retryWhenThrottledOverride?: boolean;
readonly backoffConfigOverride?: any;
readonly typingIndicatorUri: string;
readonly productId: string;
private baseUrl;
private region;
constructor(options: any);
get typingIndicatorTimeoutDefault(): number;
get httpCacheIntervalDefault(): string;
get consumptionReportIntervalDefault(): string;
get userInfosToSubscribeDefault(): number;
get retryWhenThrottledDefault(): boolean;
get backoffConfigDefault(): any;
readonly typingIndicatorTimeoutDefault: number;
readonly backoffConfiguration: BackoffConfiguration;
readonly retryWhenThrottled: boolean;
readonly consumptionReportInterval: number;
readonly userInfosToSubscribe: number;
readonly httpCacheInterval: number;
readonly reachabilityEnabled: boolean;
readonly userIdentity: string;
readonly userInfo: string;
readonly myConversations: string;
constructor(options: Record<string, any>, configurationResponse: ConfigurationResponse, logger: Logger);
}
export { Configuration };
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const TYPING_PATH = '/v1/typing';
exports.Configuration = void 0;
const iso8601_duration_1 = require("iso8601-duration");
const TYPING_TIMEOUT = 5;

@@ -13,30 +14,49 @@ const HTTP_CACHE_LIFETIME = 'PT5S';

class Configuration {
constructor(options) {
options = options || {};
let constructorOptions = options.Chat || options.IPMessaging || options || {};
this.region = constructorOptions.region || options.region;
this.baseUrl = constructorOptions.apiUri || constructorOptions.typingUri ||
((!this.region || this.region === 'us1') ? 'https://aim.twilio.com' : `https://aim.${this.region}.twilio.com`);
this.typingIndicatorUri = this.baseUrl + TYPING_PATH;
constructor(options = {}, configurationResponse, logger) {
this.typingIndicatorTimeoutDefault = TYPING_TIMEOUT * 1000;
const constructorOptions = options.Chat || options.IPMessaging || options || {};
this.productId = constructorOptions.productId;
this.links = {
myConversations: configurationResponse.links.my_conversations,
conversations: configurationResponse.links.conversations,
users: configurationResponse.links.users,
currentUser: configurationResponse.links.current_user,
typing: configurationResponse.links.typing,
mediaService: configurationResponse.links.media_service,
messagesReceipts: configurationResponse.links.messages_receipts
};
this.typingIndicatorTimeoutOverride = constructorOptions.typingIndicatorTimeoutOverride;
this.httpCacheIntervalOverride = constructorOptions.httpCacheIntervalOverride;
this.consumptionReportIntervalOverride = constructorOptions.consumptionReportIntervalOverride;
this.userInfosToSubscribeOverride = constructorOptions.userInfosToSubscribeOverride;
this.retryWhenThrottledOverride = constructorOptions.retryWhenThrottledOverride;
this.backoffConfigOverride = constructorOptions.backoffConfigOverride;
this.productId = options.productId;
this.backoffConfiguration = Object.assign({ min: MINIMUM_RETRY_DELAY, max: MAXIMUM_RETRY_DELAY, maxAttemptsCount: MAXIMUM_ATTEMPTS_COUNT }, constructorOptions.backoffConfigOverride);
this.retryWhenThrottled = constructorOptions.retryWhenThrottledOverride !== undefined
? constructorOptions.retryWhenThrottledOverride
: RETRY_WHEN_THROTTLED;
this.userInfosToSubscribe = constructorOptions.userInfosToSubscribeOverride
|| configurationResponse.options.user_infos_to_subscribe
|| USER_INFOS_TO_SUBSCRIBE;
this.reachabilityEnabled = configurationResponse.options.reachability_enabled;
this.userIdentity = configurationResponse.identity;
this.userInfo = configurationResponse.sync_objects.my_user_info;
this.myConversations = configurationResponse.sync_objects.my_conversations;
const httpCacheInterval = constructorOptions.httpCacheIntervalOverride
|| configurationResponse.options.http_cache_interval
|| HTTP_CACHE_LIFETIME;
try {
this.httpCacheInterval = iso8601_duration_1.toSeconds(iso8601_duration_1.parse(httpCacheInterval));
}
catch (_a) {
logger.error(`Failed to parse http cache interval ${httpCacheInterval}, using default value ${HTTP_CACHE_LIFETIME}`);
this.httpCacheInterval = iso8601_duration_1.toSeconds(iso8601_duration_1.parse(HTTP_CACHE_LIFETIME));
}
const consumptionReportInterval = constructorOptions.consumptionReportIntervalOverride
|| configurationResponse.options.consumption_report_interval
|| CONSUMPTION_HORIZON_SENDING_INTERVAL;
try {
this.consumptionReportInterval = iso8601_duration_1.toSeconds(iso8601_duration_1.parse(consumptionReportInterval));
}
catch (_b) {
logger.error(`Failed to parse consumption report interval ${consumptionReportInterval}, using default value ${CONSUMPTION_HORIZON_SENDING_INTERVAL}`);
this.consumptionReportInterval = iso8601_duration_1.toSeconds(iso8601_duration_1.parse(CONSUMPTION_HORIZON_SENDING_INTERVAL));
}
}
get typingIndicatorTimeoutDefault() { return TYPING_TIMEOUT * 1000; }
get httpCacheIntervalDefault() { return HTTP_CACHE_LIFETIME; }
get consumptionReportIntervalDefault() { return CONSUMPTION_HORIZON_SENDING_INTERVAL; }
get userInfosToSubscribeDefault() { return USER_INFOS_TO_SUBSCRIBE; }
get retryWhenThrottledDefault() { return RETRY_WHEN_THROTTLED; }
get backoffConfigDefault() {
return {
min: MINIMUM_RETRY_DELAY,
max: MAXIMUM_RETRY_DELAY,
maxAttemptsCount: MAXIMUM_ATTEMPTS_COUNT
};
}
}
exports.Configuration = Configuration;

@@ -6,19 +6,15 @@ /// <reference types="node" />

import { ChannelDescriptor } from '../channeldescriptor';
import { Session } from '../session';
import { SyncList } from '../synclist';
import { Users } from './users';
import { Network } from '../services/network';
import { TypingIndicator } from '../services/typingindicator';
import { ConsumptionHorizon } from '../services/consumptionhorizon';
import { McsClient } from 'twilio-mcs-client';
import { Deferred } from '../util/deferred';
import { Configuration } from '../configuration';
import { CommandExecutor } from '../commandexecutor';
export interface ChannelsServices {
session: Session;
syncClient: SyncClient;
syncList: SyncList;
users: Users;
typingIndicator: TypingIndicator;
consumptionHorizon: ConsumptionHorizon;
network: Network;
mcsClient: McsClient;
commandExecutor: CommandExecutor;
}

@@ -30,8 +26,9 @@ /**

declare class Channels extends EventEmitter {
private services;
private readonly configuration;
private readonly services;
readonly channels: Map<string, Channel>;
private readonly thumbstones;
private syncListFetched;
readonly syncListRead: Deferred<boolean>;
constructor(services: ChannelsServices);
private readonly tombstones;
private myChannelsFetched;
private myChannelsRead;
constructor(configuration: Configuration, services: ChannelsServices);
private getMap;

@@ -47,3 +44,3 @@ /**

*/
fetchChannels(): void;
fetchChannels(): Promise<this>;
private _wrapPaginator;

@@ -53,9 +50,11 @@ getChannels(args: any): Promise<any>;

pushChannel(descriptor: ChannelDescriptor): Promise<Channel>;
private _updateChannel;
private upsertChannel;
private onChannelRemoved;
private registerForEvents;
private _fetchMyChannels;
}
declare namespace Channels {
type DataSource = 'sync' | 'chat' | 'synclist';
type DataSource = 'sync' | 'chat' | 'rest';
}
export { Channel, Channels };
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Channels = exports.Channel = void 0;
const events_1 = require("events");
const logger_1 = require("../logger");
const channel_1 = require("../channel");
exports.Channel = channel_1.Channel;
Object.defineProperty(exports, "Channel", { enumerable: true, get: function () { return channel_1.Channel; } });
const deferred_1 = require("../util/deferred");

@@ -15,13 +16,16 @@ const util_1 = require("../util");

class Channels extends events_1.EventEmitter {
constructor(services) {
constructor(configuration, services) {
super();
this.configuration = configuration;
this.services = services;
this.channels = new Map();
this.thumbstones = new Set();
this.syncListFetched = false;
this.syncListRead = new deferred_1.Deferred();
this.tombstones = new Set();
this.myChannelsFetched = false;
this.myChannelsRead = new deferred_1.Deferred();
}
getMap() {
return this.services.session.getMyChannelsId()
.then(name => this.services.syncClient.map({ id: name, mode: 'open_existing' }));
async getMap() {
return await this.services.syncClient.map({
id: this.configuration.myConversations,
mode: 'open_existing'
});
}

@@ -41,10 +45,11 @@ /**

}
let response = await this.services.session.addCommand('createChannel', {
friendlyName: options.friendlyName,
uniqueName: options.uniqueName,
const response = await this.services.commandExecutor.mutateResource('post', this.configuration.links.conversations, {
type: options.isPrivate ? 'private' : 'public',
attributes: JSON.stringify(attributes)
unique_name: options.uniqueName,
friendly_name: options.friendlyName,
attributes: attributes !== undefined ? JSON.stringify(attributes) : undefined,
});
let channelSid = 'channelSid' in response ? response['channelSid'] : null;
let channelDocument = 'channel' in response ? response['channel'] : null;
const channelSid = response.sid || null;
const channelDocument = response.sync_objects.conversation || null;
const links = Object.assign({ self: response.url }, response.links);
let existingChannel = this.channels.get(channelSid);

@@ -55,3 +60,3 @@ if (existingChannel) {

}
let channel = new channel_1.Channel(this.services, {
let channel = new channel_1.Channel({
channel: channelDocument,

@@ -67,3 +72,3 @@ entityName: null,

dateUpdated: null
}, channelSid);
}, channelSid, links, this.configuration, this.services);
this.channels.set(channel.sid, channel);

@@ -78,60 +83,53 @@ this.registerForEvents(channel);

*/
fetchChannels() {
this.getMap()
.then(async (map) => {
async fetchChannels() {
try {
const map = await this.getMap();
map.on('itemAdded', args => {
log.debug('itemAdded: ' + args.item.key);
this.upsertChannel('sync', args.item.key, args.item.value);
log.debug(`itemAdded: ${args.item.key}`);
this.upsertChannel('sync', args.item.key, args.item.data);
});
map.on('itemRemoved', args => {
log.debug('itemRemoved: ' + args.key);
let sid = args.key;
if (!this.syncListFetched) {
this.thumbstones.add(sid);
log.debug(`itemRemoved: ${args.key}`);
const sid = args.key;
if (!this.myChannelsFetched) {
this.tombstones.add(sid);
}
let channel = this.channels.get(sid);
if (channel) {
if (channel.status === 'joined' || channel.status === 'invited') {
channel._setStatus('notParticipating', 'sync');
this.emit('channelLeft', channel);
}
if (channel.isPrivate) {
this.channels.delete(sid);
this.emit('channelRemoved', channel);
channel.emit('removed', channel);
}
const channel = this.channels.get(sid);
if (!channel) {
return;
}
if (channel.status === 'joined' || channel.status === 'invited') {
channel._setStatus('notParticipating', 'sync');
this.emit('channelLeft', channel);
}
if (channel.isPrivate) {
this.channels.delete(sid);
this.emit('channelRemoved', channel);
channel.emit('removed', channel);
}
});
map.on('itemUpdated', args => {
log.debug('itemUpdated: ' + args.item.key);
this.upsertChannel('sync', args.item.key, args.item.value);
log.debug(`itemUpdated: ${args.item.key}`);
this.upsertChannel('sync', args.item.key, args.item.data);
});
let upserts = [];
let paginator = await this.services.syncList.getPage();
let items = paginator.items;
items.forEach(item => {
upserts.push(this.upsertChannel('synclist', item.channel_sid, item));
});
while (paginator.hasNextPage) {
paginator = await paginator.nextPage();
paginator.items.forEach(item => {
upserts.push(this.upsertChannel('synclist', item.channel_sid, item));
});
const myChannels = await this._fetchMyChannels();
const upserts = [];
for (const channel of myChannels) {
upserts.push(this.upsertChannel('rest', channel.channel_sid, channel));
}
this.syncListRead.set(true);
return Promise.all(upserts);
})
.then(() => {
this.syncListFetched = true;
this.thumbstones.clear();
log.debug('Channels list fetched');
})
.then(() => this)
.catch(e => {
if (this.services.syncClient.connectionState != 'disconnected') {
log.error('Failed to get channels list', e);
this.myChannelsRead.set(true);
await Promise.all(upserts);
this.myChannelsFetched = true;
this.tombstones.clear();
log.debug('The channels list has been successfully fetched');
return this;
}
catch (error) {
const errorMessage = 'Failed to fetch the channels list';
if (this.services.syncClient.connectionState !== 'disconnected') {
log.error(errorMessage, error);
}
log.debug('ERROR: Failed to get channels list', e);
throw e;
});
log.debug(`ERROR: ${errorMessage}`, error);
throw error;
}
}

@@ -151,3 +149,3 @@ _wrapPaginator(page, op) {

.then(channelsMap => channelsMap.getItems(args))
.then(page => this._wrapPaginator(page, items => Promise.all(items.map(item => this.upsertChannel('sync', item.key, item.value)))));
.then(page => this._wrapPaginator(page, items => Promise.all(items.map(item => this.upsertChannel('sync', item.key, item.data)))));
}

@@ -157,3 +155,3 @@ getChannel(sid) {

.then(channelsMap => channelsMap.getItems({ key: sid }))
.then(page => page.items.map(item => this.upsertChannel('sync', item.key, item.value)))
.then(page => page.items.map(item => this.upsertChannel('sync', item.key, item.data)))
.then(items => items.length > 0 ? items[0] : null);

@@ -180,85 +178,79 @@ }

}
_updateChannel(source, channel, data) {
const areSourcesDifferent = channel._statusSource() !== undefined && source !== channel._statusSource();
const isChannelSourceSync = source !== 'rest' || channel._statusSource() === 'sync';
if (areSourcesDifferent && isChannelSourceSync && source !== 'sync') {
log.trace('upsertChannel: the channel is known from sync and it came from chat, ignoring', {
sid: channel.sid,
data: data.status,
channel: channel.status
});
return;
}
if (['joined', 'invited'].includes(data.status) && channel.status !== data.status) {
channel._setStatus(data.status, source);
let updateData = {};
if (data.notificationLevel !== undefined) {
updateData.notificationLevel = data.notificationLevel;
}
if (data.lastConsumedMessageIndex !== undefined) {
updateData.lastConsumedMessageIndex = data.lastConsumedMessageIndex;
}
if (!util_1.isDeepEqual(updateData, {})) {
channel._update(updateData);
}
channel._subscribe().then(() => {
this.emit(data.status === 'joined' ? 'channelJoined' : 'channelInvited', channel);
});
return;
}
if (['joined', 'invited'].includes(channel.status) && data.status === 'notParticipating') {
channel._setStatus('notParticipating', source);
channel._update(data);
channel._subscribe().then(() => {
this.emit('channelLeft', channel);
});
return;
}
if (data.type === 'private' && data.status === 'notParticipating') {
channel._subscribe();
return;
}
channel._update(data);
}
upsertChannel(source, sid, data) {
log.trace('upsertChannel(sid=' + sid + ', data=', data);
let channel = this.channels.get(sid);
// Update the Channel's status if we know about it
log.trace(`upsertChannel called for ${sid}`, data);
const channel = this.channels.get(sid);
// If the channel is known, update it
if (channel) {
log.trace('upsertChannel: channel ' + sid + ' is known and it\'s' +
' status is known from source ' + channel._statusSource() +
' and update came from source ' + source, channel);
if (typeof channel._statusSource() === 'undefined'
|| source === channel._statusSource()
|| (source === 'synclist' && channel._statusSource() !== 'sync')
|| source === 'sync') {
if (data.status === 'joined' && channel.status !== 'joined') {
channel._setStatus('joined', source);
let updateData = {};
if (typeof data.notificationLevel !== 'undefined') {
updateData.notificationLevel = data.notificationLevel;
}
if (typeof data.lastConsumedMessageIndex !== 'undefined') {
updateData.lastConsumedMessageIndex = data.lastConsumedMessageIndex;
}
if (!util_1.isDeepEqual(updateData, {})) {
channel._update(updateData);
}
channel._subscribe().then(() => { this.emit('channelJoined', channel); });
}
else if (data.status === 'invited' && channel.status !== 'invited') {
channel._setStatus('invited', source);
let updateData = {};
if (typeof data.notificationLevel !== 'undefined') {
updateData.notificationLevel = data.notificationLevel;
}
if (typeof data.lastConsumedMessageIndex !== 'undefined') {
updateData.lastConsumedMessageIndex = data.lastConsumedMessageIndex;
}
if (!util_1.isDeepEqual(updateData, {})) {
channel._update(updateData);
}
channel._subscribe().then(() => { this.emit('channelInvited', channel); });
}
else if (data.status === 'notParticipating' &&
(channel.status === 'invited' || channel.status === 'joined')) {
channel._setStatus('notParticipating', source);
channel._update(data);
channel._subscribe().then(() => { this.emit('channelLeft', channel); });
}
else if (data.status === 'notParticipating' && data.type === 'private') {
channel._subscribe();
}
else {
channel._update(data);
}
}
else {
log.trace('upsertChannel: channel is known from sync and came from chat, ignoring', {
sid: sid,
data: data.status,
channel: channel.status
});
}
log.trace(`upsertChannel: the channel ${channel.sid} is known;` +
`its status is known from source ${channel._statusSource()} ` +
`and the update came from source ${source}`, channel);
this._updateChannel(source, channel, data);
return channel._subscribe().then(() => channel);
}
if ((source === 'chat' || source === 'synclist') && this.thumbstones.has(sid)) {
// if channel was deleted, we ignore it
log.trace('upsertChannel: channel is deleted and came again from chat, ignoring', sid);
// If the channel is deleted, ignore it
if (['chat', 'rest'].includes(source) && this.tombstones.has(sid)) {
log.trace('upsertChannel: the channel is deleted but reappeared again from chat, ignoring', sid);
return;
}
// Fetch the Channel if we don't know about it
log.trace('upsertChannel: creating local channel object with sid ' + sid, data);
channel = new channel_1.Channel(this.services, data, sid);
this.channels.set(sid, channel);
return channel._subscribe().then(() => {
this.registerForEvents(channel);
this.emit('channelAdded', channel);
if (data.status === 'joined') {
channel._setStatus('joined', source);
this.emit('channelJoined', channel);
// If the channel is unknown, fetch it
log.trace(`upsertChannel: creating a local channel object with sid ${sid}`, data);
const baseLink = `${this.configuration.links.conversations}/${sid}`;
const links = {
self: baseLink,
messages: `${baseLink}/Messages`,
participants: `${baseLink}/Participants`,
invites: `${baseLink}/Invites`
};
const newChannel = new channel_1.Channel(data, sid, links, this.configuration, this.services);
this.channels.set(sid, newChannel);
return newChannel._subscribe().then(() => {
this.registerForEvents(newChannel);
this.emit('channelAdded', newChannel);
if (['joined', 'invited'].includes(data.status)) {
newChannel._setStatus(data.status, source);
this.emit(data.status === 'joined' ? 'channelJoined' : 'channelInvited', newChannel);
}
else if (data.status === 'invited') {
channel._setStatus('invited', source);
this.emit('channelInvited', channel);
}
return channel;
return newChannel;
});

@@ -285,3 +277,27 @@ }

}
async _fetchMyChannels() {
let channels = [];
let pageToken = null;
do {
const url = new util_1.UriBuilder(this.configuration.links.myConversations);
if (pageToken) {
url.arg('PageToken', pageToken);
}
const response = await this.services.network.get(url.build());
const preProcessedChannels = response.body.conversations.map((channelDescriptor) => ({
descriptor: channelDescriptor,
channel_sid: channelDescriptor.conversation_sid,
status: channelDescriptor.status,
channel: channelDescriptor.sync_objects.conversation,
messages: channelDescriptor.sync_objects.messages,
roster: `${channelDescriptor.conversation_sid}.roster`,
lastConsumedMessageIndex: channelDescriptor.last_consumed_message_index,
notificationLevel: channelDescriptor.notification_level
}));
pageToken = response.body.meta.next_token;
channels = [...channels, ...preProcessedChannels];
} while (pageToken);
return channels;
}
}
exports.Channels = Channels;

@@ -7,8 +7,13 @@ /// <reference types="node" />

import { Users } from './users';
import { Session } from '../session';
import { CommandExecutor } from '../commandexecutor';
import { JoinChannelResponse } from '../interfaces/commands/joinchannel';
import { Configuration } from '../configuration';
export interface MembersServices {
session: Session;
syncClient: SyncClient;
users: Users;
commandExecutor: CommandExecutor;
}
interface MembersLinks {
participants: string;
}
/**

@@ -21,7 +26,9 @@ * @classdesc Represents the collection of members for the channel

declare class Members extends EventEmitter {
services: MembersServices;
rosterEntityPromise: Promise<SyncMap>;
readonly channel: Channel;
readonly members: Map<string, Member>;
constructor(channel: Channel, services: MembersServices, members: Map<string, Member>);
private readonly links;
private readonly configuration;
private readonly services;
rosterEntityPromise: Promise<SyncMap>;
constructor(channel: Channel, members: Map<string, Member>, links: MembersLinks, configuration: Configuration, services: MembersServices);
unsubscribe(): Promise<void>;

@@ -48,3 +55,3 @@ subscribe(rosterObjectName: string): Promise<SyncMap>;

*/
add(identity: string): Promise<any>;
add(identity: string): Promise<JoinChannelResponse>;
/**

@@ -57,11 +64,6 @@ * Invites user to the channel

/**
* Remove member from channel by Identity
* Remove member from channel
* @returns {Promise<any>}
*/
removeByIdentity(identity: string): Promise<any>;
/**
* Remove member from channel by sid
* @returns {Promise<any>}
*/
removeBySid(sid: string): Promise<any>;
remove(identity: string): Promise<void>;
}

@@ -68,0 +70,0 @@ export { Members };

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Members = void 0;
const events_1 = require("events");

@@ -14,7 +15,9 @@ const member_1 = require("../member");

class Members extends events_1.EventEmitter {
constructor(channel, services, members) {
constructor(channel, members, links, configuration, services) {
super();
this.services = services;
this.channel = channel;
this.members = members;
this.links = links;
this.configuration = configuration;
this.services = services;
}

@@ -34,3 +37,3 @@ async unsubscribe() {

log.debug(this.channel.sid + ' itemAdded: ' + args.item.key);
this.upsertMember(args.item.key, args.item.value)
this.upsertMember(args.item.key, args.item.data)
.then(member => {

@@ -52,3 +55,3 @@ this.emit('memberJoined', member);

log.debug(this.channel.sid + ' itemUpdated: ' + args.item.key);
this.upsertMember(args.item.key, args.item.value);
this.upsertMember(args.item.key, args.item.data);
});

@@ -58,3 +61,3 @@ let membersPromises = [];

const rosterMapHandler = function (paginator) {
paginator.items.forEach(item => { membersPromises.push(that.upsertMember(item.key, item.value)); });
paginator.items.forEach(item => { membersPromises.push(that.upsertMember(item.key, item.data)); });
return paginator.hasNextPage ? paginator.nextPage().then(rosterMapHandler) : null;

@@ -82,3 +85,6 @@ };

}
member = new member_1.Member(this.services, this.channel, data, memberSid);
const links = {
self: `${this.links.participants}/${memberSid}`
};
member = new member_1.Member(data, memberSid, this.channel, links, this.services);
this.members.set(memberSid, member);

@@ -133,6 +139,5 @@ member.on('updated', (args) => this.emit('memberUpdated', args));

*/
add(identity) {
return this.services.session.addCommand('addMemberV2', {
channelSid: this.channel.sid,
username: identity
async add(identity) {
return await this.services.commandExecutor.mutateResource('post', this.links.participants, {
identity
});

@@ -145,28 +150,14 @@ }

*/
invite(identity) {
return this.services.session.addCommand('inviteMember', {
channelSid: this.channel.sid,
username: identity
async invite(identity) {
return await this.services.commandExecutor.mutateResource('post', this.channel.links.invites, {
identity
});
}
/**
* Remove member from channel by Identity
* Remove member from channel
* @returns {Promise<any>}
*/
removeByIdentity(identity) {
return this.services.session.addCommand('removeMember', {
channelSid: this.channel.sid,
username: identity
});
async remove(identity) {
return await this.services.commandExecutor.mutateResource('delete', `${this.links.participants}/${identity}`);
}
/**
* Remove member from channel by sid
* @returns {Promise<any>}
*/
removeBySid(sid) {
return this.services.session.addCommand('removeMember', {
channelSid: this.channel.sid,
memberSid: sid
});
}
}

@@ -173,0 +164,0 @@ exports.Members = Members;

@@ -7,8 +7,10 @@ /// <reference types="node" />

import { SyncPaginator } from '../syncpaginator';
import { Session } from '../session';
import { McsClient } from 'twilio-mcs-client';
import { Configuration } from '../configuration';
import { CommandExecutor } from '../commandexecutor';
import { MessageResponse } from '../interfaces/commands/messageresponse';
export interface MessagesServices {
session: Session;
mcsClient: McsClient;
syncClient: SyncClient;
commandExecutor: CommandExecutor;
}

@@ -19,7 +21,8 @@ /**

declare class Messages extends EventEmitter {
readonly channel: Channel;
private readonly configuration;
private readonly services;
private readonly messagesByIndex;
private messagesListPromise;
readonly channel: Channel;
constructor(channel: Channel, services: MessagesServices);
constructor(channel: Channel, configuration: Configuration, services: MessagesServices);
/**

@@ -38,3 +41,3 @@ * Subscribe to the Messages Event Stream

*/
send(message: string, attributes?: any): Promise<unknown>;
send(message: string | null, attributes?: any): Promise<MessageResponse>;
/**

@@ -46,3 +49,3 @@ * Send Media Message to the channel

*/
sendMedia(mediaContent: FormData | Channel.SendMediaOptions, attributes?: any): Promise<unknown>;
sendMedia(mediaContent: FormData | Channel.SendMediaOptions, attributes?: any): Promise<MessageResponse>;
/**

@@ -49,0 +52,0 @@ * Returns messages from channel using paginator interface

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Messages = void 0;
const events_1 = require("events");

@@ -11,5 +12,6 @@ const logger_1 = require("../logger");

class Messages extends events_1.EventEmitter {
constructor(channel, services) {
constructor(channel, configuration, services) {
super();
this.channel = channel;
this.configuration = configuration;
this.services = services;

@@ -31,3 +33,8 @@ this.messagesByIndex = new Map();

log.debug(this.channel.sid + ' itemAdded: ' + args.item.index);
let message = new message_1.Message(this.channel, this.services, args.item.index, args.item.value);
const links = {
self: `${this.channel.links.messages}/${args.item.data.sid}`,
conversation: this.channel.links.self,
messages_receipts: `${this.channel.links.messages}/${args.item.data.sid}/Receipts`,
};
const message = new message_1.Message(args.item.index, args.item.data, this.channel, links, this.configuration, this.services);
if (this.messagesByIndex.has(message.index)) {

@@ -55,3 +62,3 @@ log.debug('Message arrived, but already known and ignored', this.channel.sid, message.index);

if (message) {
message._update(args.item.value);
message._update(args.item.data);
}

@@ -85,6 +92,5 @@ });

log.debug('Sending text message', message, attributes);
return this.services.session.addCommand('sendMessage', {
channelSid: this.channel.sid,
text: message,
attributes: JSON.stringify(attributes)
return await this.services.commandExecutor.mutateResource('post', this.channel.links.messages, {
body: message || '',
attributes: attributes !== undefined ? JSON.stringify(attributes) : undefined,
});

@@ -113,6 +119,5 @@ }

}
return this.services.session.addCommand('sendMediaMessage', {
channelSid: this.channel.sid,
mediaSid: media.sid,
attributes: JSON.stringify(attributes)
return await this.services.commandExecutor.mutateResource('post', this.channel.links.messages, {
media_sid: media.sid,
attributes: attributes !== undefined ? JSON.stringify(attributes) : undefined
});

@@ -146,7 +151,12 @@ }

_upsertMessage(index, value) {
let cachedMessage = this.messagesByIndex.get(index);
const cachedMessage = this.messagesByIndex.get(index);
if (cachedMessage) {
return cachedMessage;
}
let message = new message_1.Message(this.channel, this.services, index, value);
const links = {
self: `${this.channel.links.messages}/${value.sid}`,
conversation: this.channel.links.self,
messages_receipts: `${this.channel.links.messages}/${value.sid}/Receipts`,
};
const message = new message_1.Message(index, value, this.channel, links, this.configuration, this.services);
this.messagesByIndex.set(message.index, message);

@@ -174,5 +184,5 @@ message.on('updated', (args) => this.emit('messageUpdated', args));

}))
.then(page => this.wrapPaginator(order, page, items => Promise.all(items.map(item => this._upsertMessage(item.index, item.value)))));
.then(page => this.wrapPaginator(order, page, items => Promise.all(items.map(item => this._upsertMessage(item.index, item.data)))));
}
}
exports.Messages = Messages;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PublicChannels = void 0;
const index_1 = require("../util/index");

@@ -19,3 +20,3 @@ const restpaginator_1 = require("../restpaginator");

let response = await this.services.network.get(url);
return new restpaginator_1.RestPaginator(response.body.channels.map(x => new channeldescriptor_1.ChannelDescriptor(this.client, x)), pageToken => this.getChannels({ pageToken }), response.body.meta.previous_token, response.body.meta.next_token);
return new restpaginator_1.RestPaginator(response.body.conversations.map(x => new channeldescriptor_1.ChannelDescriptor(this.client, x)), pageToken => this.getChannels({ pageToken }), response.body.meta.previous_token, response.body.meta.next_token);
}

@@ -22,0 +23,0 @@ async getChannelBySid(sid) {

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.UserChannels = void 0;
const index_1 = require("../util/index");

@@ -19,5 +20,5 @@ const restpaginator_1 = require("../restpaginator");

let response = await this.services.network.get(url);
return new restpaginator_1.RestPaginator(response.body.channels.map(x => new channeldescriptor_1.ChannelDescriptor(this.client, x)), pageToken => this.getChannels({ pageToken }), response.body.meta.previous_token, response.body.meta.next_token);
return new restpaginator_1.RestPaginator(response.body.conversations.map(x => new channeldescriptor_1.ChannelDescriptor(this.client, x)), pageToken => this.getChannels({ pageToken }), response.body.meta.previous_token, response.body.meta.next_token);
}
}
exports.UserChannels = UserChannels;

@@ -5,2 +5,3 @@ import { RestPaginator } from '../restpaginator';

import { Network } from '../services/network';
import { Configuration } from '../configuration';
export interface UserDescriptorsServices {

@@ -11,5 +12,5 @@ users: Users;

declare class UserDescriptors {
private services;
private url;
constructor(services: UserDescriptorsServices, url: string);
private readonly configuration;
private readonly services;
constructor(configuration: Configuration, services: UserDescriptorsServices);
getUserDescriptor(identity: string): Promise<UserDescriptor>;

@@ -16,0 +17,0 @@ getChannelUserDescriptors(channelSid: string, args?: any): Promise<RestPaginator<UserDescriptor>>;

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.UserDescriptors = void 0;
const index_1 = require("../util/index");

@@ -7,8 +8,8 @@ const restpaginator_1 = require("../restpaginator");

class UserDescriptors {
constructor(services, url) {
constructor(configuration, services) {
this.configuration = configuration;
this.services = services;
this.url = url;
}
async getUserDescriptor(identity) {
const url = new index_1.UriBuilder(this.url).path(identity).build();
const url = new index_1.UriBuilder(this.configuration.links.users).path(identity).build();
let response = await this.services.network.get(url);

@@ -18,4 +19,4 @@ return new userdescriptor_1.UserDescriptor(this.services, response.body);

async getChannelUserDescriptors(channelSid, args = {}) {
const url = new index_1.UriBuilder(this.url)
.arg('ChannelSid', channelSid).arg('PageToken', args.pageToken)
const url = new index_1.UriBuilder(this.configuration.links.users)
.arg('ConversationSid', channelSid).arg('PageToken', args.pageToken)
.build();

@@ -22,0 +23,0 @@ let response = await this.services.network.get(url);

@@ -7,8 +7,9 @@ /// <reference types="node" />

import { Network } from '../services/network';
import { Session } from '../session';
import { SyncClient } from 'twilio-sync';
import { Configuration } from '../configuration';
import { CommandExecutor } from '../commandexecutor';
export interface UsersServices {
session: Session;
network: Network;
syncClient: SyncClient;
commandExecutor: CommandExecutor;
}

@@ -20,10 +21,9 @@ /**

declare class Users extends EventEmitter {
private services;
private readonly configuration;
private readonly services;
private userDescriptors;
private subscribedUsers;
private fifoStack;
private fifoStackMaxLength;
private userDescriptorsPromise;
readonly myself: User;
constructor(services: UsersServices);
constructor(configuration: Configuration, services: UsersServices);
private handleUnsubscribeUser;

@@ -30,0 +30,0 @@ private handleSubscribeUser;

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Users = void 0;
const events_1 = require("events");

@@ -11,8 +12,11 @@ const user_1 = require("../user");

class Users extends events_1.EventEmitter {
constructor(services) {
constructor(configuration, services) {
super();
this.configuration = configuration;
this.services = services;
const userLinks = {
self: `${configuration.links.users}/${configuration.userIdentity}`
};
this.fifoStack = [];
this.fifoStackMaxLength = 100;
this.myself = new user_1.User(null, null, this.services);
this.myself = new user_1.User(this.configuration.userIdentity, this.configuration.userInfo, userLinks, this.configuration, this.services);
this.myself.on('updated', (args) => this.emit('userUpdated', args));

@@ -24,23 +28,4 @@ this.myself.on('userSubscribed', () => this.emit('userSubscribed', this.myself));

});
this.services = services;
this.subscribedUsers = new Map();
this.userDescriptorsPromise =
this.services.session.getSessionLinks()
.then((links) => {
this.userDescriptors = new userdescriptors_1.UserDescriptors({
users: this,
network: this.services.network
}, links.usersUrl);
return this.userDescriptors;
});
this.services.session.getMaxUserInfosToSubscribe()
.then(maxUserInfosToSubscribe => {
this.fifoStackMaxLength = maxUserInfosToSubscribe;
});
this.services.session.getUsersData()
.then(data => {
this.myself.identity = data.identity;
this.myself.entityName = data.user;
return this.myself._ensureFetched();
});
this.userDescriptors = new userdescriptors_1.UserDescriptors(this.configuration, Object.assign(Object.assign({}, this.services), { users: this }));
}

@@ -68,3 +53,3 @@ handleUnsubscribeUser(user) {

}
if (this.fifoStack.length >= this.fifoStackMaxLength) {
if (this.fifoStack.length >= this.configuration.userInfosToSubscribe) {
this.subscribedUsers.get(this.fifoStack.shift()).unsubscribe();

@@ -82,3 +67,2 @@ }

async getUser(identity, entityName = null) {
await this.services.session.getUsersData();
await this.myself._ensureFetched();

@@ -92,5 +76,8 @@ if (identity == this.myself.identity) {

let userDescriptor = await this.getUserDescriptor(identity);
entityName = userDescriptor._getDescriptor().sync_unique_name;
entityName = userDescriptor._getDescriptor().sync_objects.user_info_map;
}
user = new user_1.User(identity, entityName, this.services);
const userLinks = {
self: `${this.configuration.links.users}/${identity}`
};
user = new user_1.User(identity, entityName, userLinks, this.configuration, this.services);
user.on('updated', (args) => this.emit('userUpdated', args));

@@ -107,3 +94,2 @@ user.on('userSubscribed', () => this.handleSubscribeUser(user));

async getUserDescriptor(identity) {
await this.userDescriptorsPromise;
return this.userDescriptors.getUserDescriptor(identity);

@@ -115,3 +101,2 @@ }

async getChannelUserDescriptors(channelSid) {
await this.userDescriptorsPromise;
return this.userDescriptors.getChannelUserDescriptors(channelSid);

@@ -123,5 +108,4 @@ }

async getSubscribedUsers() {
await this.services.session.getUsersData();
await this.myself._ensureFetched();
let users = [this.myself];
const users = [this.myself];
this.subscribedUsers.forEach((user) => users.push(user));

@@ -128,0 +112,0 @@ return users;

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.NotificationTypes = void 0;
class NotificationTypes {

@@ -4,0 +5,0 @@ }

'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
exports.SamplePaginator = void 0;
/**

@@ -4,0 +5,0 @@ * @classdesc Pagination helper class.

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ResponseCodes = void 0;
class ResponseCodes {

@@ -4,0 +5,0 @@ }

/// <reference types="node" />
import { EventEmitter } from 'events';
interface Result {
interface Result<T> {
status: {
code: number;
status: string;
};
headers: {
[id: string]: string;
};
body?: T;
}

@@ -8,7 +16,7 @@ interface Transport extends EventEmitter {

readonly state: string;
get(url: string, headers: any, grant?: string): Promise<Result>;
post(url: string, headers: any, body: any, grant?: string): Promise<Result>;
put(url: string, headers: any, body: any, grant?: string): Promise<Result>;
delete(url: string, headers: any, grant?: string): Promise<Result>;
get<T>(url: string, headers: any, grant?: string): Promise<Result<T>>;
post<T>(url: string, headers: any, body: any, grant?: string): Promise<Result<T>>;
put<T>(url: string, headers: any, body: any, grant?: string): Promise<Result<T>>;
delete<T>(url: string, headers: any, grant?: string): Promise<Result<T>>;
}
export { Result, Transport };
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Logger = void 0;
const loglevelLog = require("loglevel");

@@ -4,0 +5,0 @@ function prepareLine(prefix, args) {

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Media = void 0;
/**

@@ -4,0 +5,0 @@ * @classdesc A Media represents a media information for Message in a Channel.

@@ -6,4 +6,4 @@ /// <reference types="node" />

import { User } from './user';
import { Session } from './session';
import { Channel } from './channel';
import { CommandExecutor } from './commandexecutor';
interface MemberDescriptor {

@@ -22,4 +22,7 @@ attributes?: Object;

users: Users;
session: Session;
commandExecutor: CommandExecutor;
}
interface MemberLinks {
self: string;
}
declare namespace Member {

@@ -45,3 +48,3 @@ type UpdateReason = 'attributes' | 'dateCreated' | 'dateUpdated' | 'roleSid' | 'lastConsumedMessageIndex' | 'lastConsumptionTimestamp';

* to find out how to mark messages as consumed.
* @property {Date} lastConsumptionTimestamp - Date when Member has updated his consumption horizon
* @property {Date} lastConsumptionTimestamp - Date when Member has updated their consumption horizon
* @property {String} sid - The server-assigned unique identifier for the Member

@@ -54,5 +57,16 @@ * @property {Member#Type} type - The type of Member

declare class Member extends EventEmitter {
readonly channel: Channel;
private readonly links;
private readonly services;
private state;
private services;
readonly channel: Channel;
constructor(data: MemberDescriptor, sid: string, channel: Channel, links: MemberLinks, services: MemberServices);
/**
* The update reason for <code>updated</code> event emitted on Member
* @typedef {('attributes' | 'dateCreated' | 'dateUpdated' | 'roleSid' |
'lastConsumedMessageIndex' | 'lastConsumptionTimestamp')} Member#UpdateReason
*/
/**
* The type of Member
* @typedef {('chat' | 'sms' | 'whatsapp')} Member#Type
*/
get sid(): string;

@@ -64,3 +78,3 @@ get attributes(): Object;

get isTyping(): boolean;
get lastConsumedMessageIndex(): number;
get lastConsumedMessageIndex(): number | null;
get lastConsumptionTimestamp(): Date;

@@ -70,12 +84,2 @@ get roleSid(): string;

/**
* The update reason for <code>updated</code> event emitted on Member
* @typedef {('attributes' | 'dateCreated' | 'dateUpdated' | 'roleSid' |
'lastConsumedMessageIndex' | 'lastConsumptionTimestamp')} Member#UpdateReason
*/
/**
* The type of Member
* @typedef {('chat' | 'sms' | 'whatsapp')} Member#Type
*/
constructor(services: MemberServices, channel: Channel, data: MemberDescriptor, sid: string);
/**
* Private method used to start or reset the typing indicator timeout (with event emitting)

@@ -82,0 +86,0 @@ * @private

@@ -12,6 +12,7 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.Member = void 0;
const events_1 = require("events");
const util_1 = require("./util");
const logger_1 = require("./logger");
const typecheck_1 = require("./util/typecheck");
const twilio_sdk_type_validator_1 = require("twilio-sdk-type-validator");
const log = logger_1.Logger.scope('Member');

@@ -30,3 +31,3 @@ /**

* to find out how to mark messages as consumed.
* @property {Date} lastConsumptionTimestamp - Date when Member has updated his consumption horizon
* @property {Date} lastConsumptionTimestamp - Date when Member has updated their consumption horizon
* @property {String} sid - The server-assigned unique identifier for the Member

@@ -39,15 +40,8 @@ * @property {Member#Type} type - The type of Member

class Member extends events_1.EventEmitter {
/**
* The update reason for <code>updated</code> event emitted on Member
* @typedef {('attributes' | 'dateCreated' | 'dateUpdated' | 'roleSid' |
'lastConsumedMessageIndex' | 'lastConsumptionTimestamp')} Member#UpdateReason
*/
/**
* The type of Member
* @typedef {('chat' | 'sms' | 'whatsapp')} Member#Type
*/
constructor(services, channel, data, sid) {
constructor(data, sid, channel, links, services) {
super();
this.channel = channel;
this.links = links;
this.services = services;
this.services = services;
this.state = {

@@ -71,2 +65,11 @@ attributes: util_1.parseAttributes(data.attributes, 'Retrieved malformed attributes from the server for member: ' + sid, log),

}
/**
* The update reason for <code>updated</code> event emitted on Member
* @typedef {('attributes' | 'dateCreated' | 'dateUpdated' | 'roleSid' |
'lastConsumedMessageIndex' | 'lastConsumptionTimestamp')} Member#UpdateReason
*/
/**
* The type of Member
* @typedef {('chat' | 'sms' | 'whatsapp')} Member#Type
*/
get sid() { return this.state.sid; }

@@ -186,6 +189,4 @@ get attributes() { return this.state.attributes; }

async updateAttributes(attributes) {
await this.services.session.addCommand('editMemberAttributes', {
channelSid: this.channel.sid,
memberSid: this.sid,
attributes: JSON.stringify(attributes)
await this.services.commandExecutor.mutateResource('post', this.links.self, {
attributes: attributes !== undefined ? JSON.stringify(attributes) : undefined
});

@@ -196,3 +197,3 @@ return this;

__decorate([
typecheck_1.asyncTypeCheck(['string', 'number', 'boolean', 'object', typecheck_1.literal(null)]),
twilio_sdk_type_validator_1.validateTypesAsync(['string', 'number', 'boolean', 'object', twilio_sdk_type_validator_1.literal(null)]),
__metadata("design:type", Function),

@@ -199,0 +200,0 @@ __metadata("design:paramtypes", [Object]),

/// <reference types="node" />
import { EventEmitter } from 'events';
import { Channel } from './channel';
import { Session } from './session';
import { McsClient } from 'twilio-mcs-client';
import { Media } from './media';
import { Member } from './member';
import { Configuration } from './configuration';
import { CommandExecutor } from './commandexecutor';
declare namespace Message {

@@ -12,5 +13,10 @@ type Type = 'text' | 'media';

export interface MessageServices {
session: Session;
mcsClient: McsClient;
commandExecutor: CommandExecutor;
}
interface MessageLinks {
self: string;
conversation: string;
messages_receipts: string;
}
declare namespace Message {

@@ -41,4 +47,7 @@ type UpdateReason = 'body' | 'lastUpdatedBy' | 'dateCreated' | 'dateUpdated' | 'attributes' | 'author';

readonly channel: Channel;
private services;
private readonly links;
private readonly configuration;
private readonly services;
private state;
constructor(index: number, data: any, channel: Channel, links: MessageLinks, configuration: Configuration, services: MessageServices);
/**

@@ -48,3 +57,2 @@ * The update reason for <code>updated</code> event emitted on Message

*/
constructor(channel: Channel, services: MessageServices, index: number, data: any);
get sid(): string;

@@ -51,0 +59,0 @@ get author(): string;

@@ -12,2 +12,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.Message = void 0;
const events_1 = require("events");

@@ -17,3 +18,3 @@ const util_1 = require("./util");

const media_1 = require("./media");
const typecheck_1 = require("./util/typecheck");
const twilio_sdk_type_validator_1 = require("twilio-sdk-type-validator");
const log = logger_1.Logger.scope('Message');

@@ -37,9 +38,7 @@ /**

class Message extends events_1.EventEmitter {
/**
* The update reason for <code>updated</code> event emitted on Message
* @typedef {('body' | 'lastUpdatedBy' | 'dateCreated' | 'dateUpdated' | 'attributes' | 'author')} Message#UpdateReason
*/
constructor(channel, services, index, data) {
constructor(index, data, channel, links, configuration, services) {
super();
this.channel = channel;
this.links = links;
this.configuration = configuration;
this.services = services;

@@ -61,2 +60,6 @@ this.state = {

}
/**
* The update reason for <code>updated</code> event emitted on Message
* @typedef {('body' | 'lastUpdatedBy' | 'dateCreated' | 'dateUpdated' | 'attributes' | 'author')} Message#UpdateReason
*/
get sid() { return this.state.sid; }

@@ -155,6 +158,3 @@ get author() { return this.state.author; }

async remove() {
await this.services.session.addCommand('deleteMessage', {
channelSid: this.channel.sid,
messageIdx: this.index.toString()
});
await this.services.commandExecutor.mutateResource('delete', this.links.self);
return this;

@@ -168,6 +168,4 @@ }

async updateBody(body) {
await this.services.session.addCommand('editMessage', {
channelSid: this.channel.sid,
messageIdx: this.index.toString(),
text: body
await this.services.commandExecutor.mutateResource('post', this.links.self, {
body
});

@@ -182,6 +180,4 @@ return this;

async updateAttributes(attributes) {
await this.services.session.addCommand('editMessageAttributes', {
channelSid: this.channel.sid,
messageIdx: this.index,
attributes: JSON.stringify(attributes)
await this.services.commandExecutor.mutateResource('post', this.links.self, {
attributes: attributes !== undefined ? JSON.stringify(attributes) : undefined
});

@@ -192,3 +188,3 @@ return this;

__decorate([
typecheck_1.asyncTypeCheck('string'),
twilio_sdk_type_validator_1.validateTypesAsync('string'),
__metadata("design:type", Function),

@@ -199,3 +195,3 @@ __metadata("design:paramtypes", [String]),

__decorate([
typecheck_1.asyncTypeCheck(['string', 'number', 'boolean', 'object', typecheck_1.literal(null)]),
twilio_sdk_type_validator_1.validateTypesAsync(['string', 'number', 'boolean', 'object', twilio_sdk_type_validator_1.literal(null)]),
__metadata("design:type", Function),

@@ -202,0 +198,0 @@ __metadata("design:paramtypes", [Object]),

'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
exports.PushNotification = void 0;
/**

@@ -4,0 +5,0 @@ * @classdesc Push notification representation within Chat Client

'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
exports.RestPaginator = void 0;
/**

@@ -4,0 +5,0 @@ * @class Paginator

@@ -1,16 +0,13 @@

import { Session } from '../session';
import { Transport } from '../interfaces/transport';
import { Configuration } from '../configuration';
export interface NetworkServices {
session: Session;
transport: Transport;
}
declare class Network {
private readonly config;
private readonly configuration;
private readonly services;
private cacheLifetime;
private readonly cacheLifetime;
private readonly cache;
private timer;
constructor(config: any, services: any);
private backoffConfig;
private retryWhenThrottled;
constructor(configuration: Configuration, services: NetworkServices);
private isExpired;

@@ -17,0 +14,0 @@ private cleanupCache;

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Network = void 0;
const operation_retrier_1 = require("operation-retrier");
class Network {
constructor(config, services) {
this.config = config;
constructor(configuration, services) {
this.configuration = configuration;
this.services = services;
this.cache = new Map();
this.cacheLifetime = 0;
this.services.session.getHttpCacheInterval().then(seconds => {
this.cacheLifetime = seconds * 1000;
this.cleanupCache();
});
this.cacheLifetime = this.configuration.httpCacheInterval * 100;
this.cleanupCache();
}
backoffConfig() {
return Object.assign(this.config.backoffConfigDefault, this.config.backoffConfigOverride);
}
retryWhenThrottled() {
if (typeof this.config.retryWhenThrottledOverride !== 'undefined') {
return this.config.retryWhenThrottledOverride;
}
if (typeof this.config.retryWhenThrottledDefault !== 'undefined') {
return this.config.retryWhenThrottledDefault;
}
return false;
}
isExpired(timestamp) {

@@ -49,3 +35,3 @@ return !this.cacheLifetime || (Date.now() - timestamp) > this.cacheLifetime;

}
let retrier = new operation_retrier_1.Retrier(this.backoffConfig());
let retrier = new operation_retrier_1.Retrier(this.configuration.backoffConfiguration);
retrier.on('attempt', () => {

@@ -82,3 +68,3 @@ request()

const headers = {};
let response = await this.executeWithRetry(() => this.services.transport.get(url, headers, this.config.productId), this.retryWhenThrottled());
let response = await this.executeWithRetry(() => this.services.transport.get(url, headers, this.configuration.productId), this.configuration.retryWhenThrottled);
this.cache.set(url, { response, timestamp: Date.now() });

@@ -85,0 +71,0 @@ this.pokeTimer();

@@ -25,8 +25,8 @@ import { Notifications } from 'twilio-notifications';

declare class TypingIndicator {
private readonly getChannel;
private readonly configuration;
private readonly services;
private readonly config;
private sentUpdates;
private getChannel;
private serviceTypingTimeout;
constructor(config: Configuration, services: TypingIndicatorServices, getChannel: any);
constructor(getChannel: any, configuration: Configuration, services: TypingIndicatorServices);
get typingTimeout(): number;

@@ -48,5 +48,5 @@ /**

*/
send(channelSid: string): any;
send(channelSid: string): Promise<void>;
private _send;
}
export { TypingIndicator };
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TypingIndicator = void 0;
const logger_1 = require("../logger");

@@ -23,6 +24,6 @@ const notificationtypes_1 = require("../interfaces/notificationtypes");

class TypingIndicator {
constructor(config, services, getChannel) {
this.config = config;
constructor(getChannel, configuration, services) {
this.getChannel = getChannel;
this.configuration = configuration;
this.services = services;
this.getChannel = getChannel;
this.serviceTypingTimeout = null;

@@ -32,5 +33,5 @@ this.sentUpdates = new Map();

get typingTimeout() {
return this.config.typingIndicatorTimeoutOverride
return this.configuration.typingIndicatorTimeoutOverride
|| this.serviceTypingTimeout
|| this.config.typingIndicatorTimeoutDefault;
|| this.configuration.typingIndicatorTimeoutDefault;
}

@@ -65,3 +66,3 @@ /**

}
const timeout = this.config.typingIndicatorTimeoutOverride + 1000 || message.typing_timeout * 1000;
const timeout = this.configuration.typingIndicatorTimeoutOverride + 1000 || message.typing_timeout * 1000;
member._startTyping(timeout);

@@ -89,3 +90,3 @@ });

log.trace('Sending typing indicator');
const url = this.config.typingIndicatorUri;
const url = this.configuration.links.typing;
const headers = {

@@ -95,3 +96,3 @@ 'Content-Type': 'application/x-www-form-urlencoded'

const body = 'ChannelSid=' + channelSid;
return this.services.transport.post(url, headers, body, this.config.productId)
return this.services.transport.post(url, headers, body, this.configuration.productId)
.then(response => {

@@ -98,0 +99,0 @@ if (response.body.hasOwnProperty('typing_timeout')) {

'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
exports.SyncPaginator = void 0;
/**

@@ -4,0 +5,0 @@ * @classdesc Pagination helper class for Sync

/// <reference types="node" />
import { EventEmitter } from 'events';
import { Session } from './session';
import { SyncClient } from 'twilio-sync';
import { Configuration } from './configuration';
import { CommandExecutor } from './commandexecutor';
export interface UserServices {
session: Session;
syncClient: SyncClient;
commandExecutor: CommandExecutor;
}
interface UserLinks {
self: string;
}
declare namespace User {

@@ -38,10 +42,12 @@ type SubscriptionState = 'initializing' | 'subscribed' | 'unsubscribed';

* @param {Object} datasync - datasync service
* @param {Object} session - session service
*/
declare class User extends EventEmitter {
private readonly links;
private readonly configuration;
private readonly services;
private entity;
private services;
private state;
private promiseToFetch;
private subscribed;
constructor(identity: string, entityName: string, links: UserLinks, configuration: Configuration, services: UserServices);
/**

@@ -51,3 +57,2 @@ * The update reason for <code>updated</code> event emitted on User

*/
constructor(identity: string, entityName: string, services: UserServices);
get identity(): string;

@@ -62,3 +67,3 @@ set identity(identity: string);

_update(key: string, value: any): void;
_updateReachabilityInfo(map: any, update: any): any;
private _updateReachabilityInfo;
_fetch(): Promise<User>;

@@ -74,3 +79,3 @@ _ensureFetched(): Promise<User>;

* Update Users friendlyName.
* @param {String|null} friendlyName - Updated friendlyName
* @param {String} friendlyName - Updated friendlyName
* @returns {Promise<User>}

@@ -77,0 +82,0 @@ */

@@ -12,6 +12,7 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.User = void 0;
const events_1 = require("events");
const logger_1 = require("./logger");
const util_1 = require("./util");
const typecheck_1 = require("./util/typecheck");
const twilio_sdk_type_validator_1 = require("twilio-sdk-type-validator");
const log = logger_1.Logger.scope('User');

@@ -39,17 +40,14 @@ /**

* @param {Object} datasync - datasync service
* @param {Object} session - session service
*/
class User extends events_1.EventEmitter {
/**
* The update reason for <code>updated</code> event emitted on User
* @typedef {('friendlyName' | 'attributes' | 'online' | 'notifiable')} User#UpdateReason
*/
constructor(identity, entityName, services) {
constructor(identity, entityName, links, configuration, services) {
super();
this.links = links;
this.configuration = configuration;
this.services = services;
this.subscribed = 'initializing';
this.setMaxListeners(0);
this.services = services;
this.state = {
identity: identity,
entityName: entityName,
identity,
entityName,
friendlyName: null,

@@ -61,2 +59,6 @@ attributes: {},

}
/**
* The update reason for <code>updated</code> event emitted on User
* @typedef {('friendlyName' | 'attributes' | 'online' | 'notifiable')} User#UpdateReason
*/
get identity() { return this.state.identity; }

@@ -106,4 +108,4 @@ set identity(identity) { this.state.identity = identity; }

// Fetch reachability info
_updateReachabilityInfo(map, update) {
if (!this.services.session.reachabilityEnabled) {
async _updateReachabilityInfo(map, update) {
if (!this.configuration.reachabilityEnabled) {
return Promise.resolve();

@@ -125,10 +127,10 @@ }

log.debug(this.state.entityName + ' (' + this.state.identity + ') itemUpdated: ' + args.item.key);
return this._update(args.item.key, args.item.value);
return this._update(args.item.key, args.item.data);
});
return Promise.all([
map.get('friendlyName')
.then(item => this._update(item.key, item.value)),
.then(item => this._update(item.key, item.data)),
map.get('attributes')
.then(item => this._update(item.key, item.value)),
this._updateReachabilityInfo(map, item => this._update(item.key, item.value))
.then(item => this._update(item.key, item.data)),
this._updateReachabilityInfo(map, item => this._update(item.key, item.data))
]);

@@ -160,4 +162,3 @@ })

}
await this.services.session.addCommand('editUserAttributes', {
username: this.state.identity,
await this.services.commandExecutor.mutateResource('post', this.links.self, {
attributes: JSON.stringify(attributes)

@@ -169,3 +170,3 @@ });

* Update Users friendlyName.
* @param {String|null} friendlyName - Updated friendlyName
* @param {String} friendlyName - Updated friendlyName
* @returns {Promise<User>}

@@ -177,5 +178,4 @@ */

}
await this.services.session.addCommand('editUserFriendlyName', {
username: this.state.identity,
friendlyName: friendlyName
await this.services.commandExecutor.mutateResource('post', this.links.self, {
friendly_name: friendlyName
});

@@ -199,3 +199,3 @@ return this;

__decorate([
typecheck_1.asyncTypeCheck(['string', 'number', 'boolean', 'object', typecheck_1.literal(null)]),
twilio_sdk_type_validator_1.validateTypesAsync(['string', 'number', 'boolean', 'object', twilio_sdk_type_validator_1.literal(null)]),
__metadata("design:type", Function),

@@ -206,3 +206,3 @@ __metadata("design:paramtypes", [Object]),

__decorate([
typecheck_1.asyncTypeCheck(['string', typecheck_1.literal(null)]),
twilio_sdk_type_validator_1.validateTypesAsync(['string']),
__metadata("design:type", Function),

@@ -209,0 +209,0 @@ __metadata("design:paramtypes", [Object]),

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.UserDescriptor = void 0;
const logger_1 = require("./logger");

@@ -4,0 +5,0 @@ const util_1 = require("./util");

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Deferred = void 0;
class Deferred {

@@ -4,0 +5,0 @@ constructor() {

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseAttributes = exports.parseTime = exports.parseToNumber = exports.UriBuilder = exports.deepClone = exports.isDeepEqual = void 0;
const JsonDiff = require("rfc6902");

@@ -4,0 +5,0 @@ /**

{
"name": "twilio-chat",
"version": "4.1.1-rc9",
"version": "5.0.0-rc3",
"description": "Twilio Chat service client library",

@@ -11,13 +11,14 @@ "main": "lib/index.js",

"dependencies": {
"twilio-mcs-client": "^0.3.3",
"twilio-notifications": "^0.5.9",
"twilio-sync": "^0.13.0-rc1",
"twilsock": "^0.6.0",
"twilio-mcs-client": "^0.4.1",
"twilio-notifications": "^0.5.11",
"twilio-sdk-type-validator": "0.1.0",
"twilio-sync": "^1.0.0",
"twilsock": "^0.6.1",
"babel-runtime": "^6.26.0",
"iso8601-duration": "^1.2.0",
"loglevel": "^1.6.6",
"operation-retrier": "^3.0.0",
"operation-retrier": "^3.0.1",
"platform": "^1.3.6",
"rfc6902": "^3.0.2",
"uuid": "^3.3.2"
"uuid": "^3.4.0"
},

@@ -31,3 +32,3 @@ "devDependencies": {

"@types/node": "^12.12.12",
"@types/sinon": "^7.5.1",
"@types/sinon": "^10.0.0",
"@types/sinon-chai": "^3.2.2",

@@ -70,6 +71,6 @@ "async": "^3.0.1",

"mocha.parallel": "^0.15.6",
"node-fetch": "^2.6.0",
"node-fetch": "^2.6.1",
"nyc": "^14.1.1",
"path": "^0.12.7",
"sinon": "^7.5.0",
"sinon": "^9.2.4",
"sinon-chai": "^3.3.0",

@@ -76,0 +77,0 @@ "ts-node": "^8.5.2",

@@ -35,3 +35,3 @@ Twilio Chat client library

```html
<script src="https://media.twiliocdn.com/sdk/js/chat/v4.0/twilio-chat.min.js"></script>
<script src="https://media.twiliocdn.com/sdk/js/chat/v4.1/twilio-chat.min.js"></script>
```

@@ -38,0 +38,0 @@ Using this method, `twilio-chat.js` will set a browser global `Twilio.Chat` through which you can use the client :

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc