New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

nexmo-stitch

Package Overview
Dependencies
Maintainers
5
Versions
41
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

nexmo-stitch - npm Package Compare versions

Comparing version

to
2.1.0-beta.4

11

CHANGELOG.md

@@ -25,2 +25,4 @@ # Changelog

- Provide `minified`/`uglify` version of conversationClient.js in `dist/conversationClient.min.js`
### Fixes

@@ -32,3 +34,8 @@

- Call status now does not go to a previous status
- Switch to websocket protocol to fix disconnection issues
---
## 2.0.5

@@ -39,4 +46,4 @@

- Now you can listen to errors thrown at the application level:
- Let you listen to general errors
- Let you listen to specific errors
- Lets you listen to general errors
- Lets you listen to specific errors
for example, combined with `application.updateToken`, you can request to update the token.

@@ -43,0 +50,0 @@

20

dist/conversation.js

@@ -86,7 +86,14 @@ /*

params.members.map((m) => {
const member = new Member(this, m);
if (m.user_id === this.application.me.id) {
this.me = member;
if (this.members[m.member_id]) {
this.members[m.member_id]._normalise(m);
if (m.user_id === this.application.me.id && m.state !== "LEFT") {
this.me = this.members[m.member_id];
}
} else {
const member = new Member(this, m);
if (m.user_id === this.application.me.id && m.state !== "LEFT") {
this.me = member;
}
this.members[member.id] = member;
}
this.members[member.id] = member;
});

@@ -144,3 +151,3 @@ break;

const request_body = {};
const _normalizeParams = (params) => {
const _createDefaultValues = (params) => {
if (params) {

@@ -160,6 +167,7 @@ if (params.user_id) {

}
return request_body;
};
return new Promise((resolve, reject) => {
_normalizeParams(params);
const request_body = _createDefaultValues(params);
this.application.session.sendRequest({

@@ -166,0 +174,0 @@ type: 'conversation:join',

@@ -28,2 +28,3 @@ /*

* @property {Call.MEMBER_CALL_STATES} MEMBER_CALL_STATES - the available member call states
* @property {Call.STATUS_PERMITTED_FLOW} STATUS_PERMITTED_FLOW - the permitted call status transition map, describes the "from" and allowed "to" transitions
* @emits Application#member:call

@@ -81,3 +82,2 @@ * @emits Call#member:call:state

/**

@@ -109,2 +109,3 @@ * Enum for Call status.

};
/**

@@ -117,3 +118,3 @@ * Enum for Call direction.

this.CALL_DIRECTION = {
/** The Call started form another end */
/** The Call started from another end */
INBOUND: 'inbound',

@@ -124,2 +125,3 @@ /** The Call started from this client */

Object.freeze(this.CALL_DIRECTION);
/**

@@ -142,3 +144,38 @@ * Enum for Call Member states.

Object.freeze(this.MEMBER_CALL_STATES);
this.status = this.CALL_STATUS.STARTED;
/**
* Enum for the permitted call status transition.
* @readonly
* @alias Call.STATUS_PERMITTED_FLOW
* @enum {Map<string, Array<Call.CALL_STATUS>}
*/
this.STATUS_PERMITTED_FLOW = new Map([
/** Permitted transition array from STARTED */
["STARTED", [
this.CALL_STATUS.RINGING,
this.CALL_STATUS.ANSWERED,
this.CALL_STATUS.FAILED,
this.CALL_STATUS.TIMEOUT,
this.CALL_STATUS.UNANSWERED,
this.CALL_STATUS.REJECTED,
this.CALL_STATUS.BUSY
]],
/** Permitted transition array from RINGING */
["RINGING", [
this.CALL_STATUS.ANSWERED,
this.CALL_STATUS.FAILED,
this.CALL_STATUS.TIMEOUT,
this.CALL_STATUS.UNANSWERED,
this.CALL_STATUS.REJECTED,
this.CALL_STATUS.BUSY
]],
/** Permitted transition set from ANSWERED */
["ANSWERED", [
this.CALL_STATUS.COMPLETED,
this.CALL_STATUS.FAILED
]]
]);
Object.freeze(this.STATUS_PERMITTED_FLOW);
this.status = null;
this.direction = this.CALL_DIRECTION.INBOUND;

@@ -193,2 +230,29 @@ this._setupConversationObject(conversation);

/**
* Validate the current call status transition
* If a transition is not defined, return false
* @param {string} status the status to validate
* @returns {boolean} false if the transition is not permitted
* @private
*/
_isValidStatusTransition(status) {
if (!status) {
throw new NexmoClientError(`Provide the status to validate the transition from '${this.status}'`);
}
// if the call object is just initialised allow any state
if (!this.status) {
return true;
}
const current_status = this.status.toUpperCase();
if (!this.STATUS_PERMITTED_FLOW.has(current_status)) {
return false;
}
if (this.status === status) {
return false;
}
return (this.STATUS_PERMITTED_FLOW.get(current_status)
.indexOf(status) !== -1)
}
/**
* Go through the members of the conversation and if .me is the only one (JOINED or INVITED)

@@ -258,5 +322,2 @@ * call call.hangUp().

}
} else {
this._setStatusAndEmit(this.CALL_STATUS.REJECTED);
return Promise.resolve();
}

@@ -322,3 +383,3 @@ } else {

if (!conversation.me) {
this.log.debug("missing own member object");
this.log.debug("missing own member object iin conversation");
} else {

@@ -349,2 +410,6 @@ this.to = Object.assign({}, conversation.members);

_setStatusAndEmit(status) {
if (!this._isValidStatusTransition(status)) {
this.log.warn(`status attempt switch from ${this.status} to ${status}`);
return;
}
this.status = status;

@@ -351,0 +416,0 @@ this.application.emit("call:status:changed", this);

@@ -1,3 +0,11 @@

const LISTENER_GROUP = 'Stitch-errors';
/*
* Nexmo Stitch SDK
* Errors Emitter
*
* Copyright (c) Nexmo Inc. 2018
*/
const logger = require('loglevel');
const NexmoClientError = require('../conversationClientError').NexmoClientError;
/**

@@ -7,24 +15,44 @@ * Class that can emit errors via any emitter passed to it.

* @param {Emitter} emitter - Any event emitter that implements "emit" and "releaseGroup". Basically object that is mixed with Wildemitter.
* @property {string} LISTENER_GROUP='Stitch-errors' - the group this emitter will register
* @emits Emitter#NXM-errors
* @private
*/
class ErrorsEmitter {
constructor(emitter) {
this.log = logger.getLogger(this.constructor.name);
if (!emitter) {
throw new NexmoClientError('no emitter object passed for the Error Emitter');
}
this.emitter = emitter;
this.LISTENER_GROUP = 'Stitch-errors';
}
emitResponseIfError(response) {
if (this._isTypeError(response.type)) {
this.emitter.emit(response.type, LISTENER_GROUP, response);
/**
* Detect if the param.type includes error and emit that payload in the LISTENER_GROUP
* @param param - the payload to forward in the LISTENER_GROUP
* @param param.type - the type of the event to check if it's an error
*/
emitResponseIfError(param) {
if (this._isTypeError(param.type)) {
return this.emitter.emit(param.type, this.LISTENER_GROUP, param);
}
return;
}
/**
* Release Group on the registered emitter (using the namespace LISTENER_GROUP that is set)
*/
cleanup() {
this.emitter.releaseGroup(LISTENER_GROUP);
return this.emitter.releaseGroup(this.LISTENER_GROUP);
}
_isTypeError(type) {
return type.indexOf('error') !== -1;
/**
* Returns true if the param includes 'error'
* @param {string} type - the error type to check
*/
_isTypeError(param) {
return param.indexOf('error') !== -1;
}
}
module.exports = ErrorsEmitter;
module.exports = ErrorsEmitter;

@@ -64,2 +64,3 @@ /*

this.parentConversation.rtcObjects = {};
this.rtcPromises = [];
this.streamIndex = 0;

@@ -327,8 +328,2 @@ this.rtcstats_enabled = (this.application.session.config && this.application.session.config.rtcstats_enabled);

this.streamIndex++;
this.parentConversation.me.emit("media:stream:on", {
type,
name: name,
index: index,
localStream
});
const p = new Promise((resolve, reject) => {

@@ -390,2 +385,9 @@ pc.createOffer()

});
this.rtcPromises.push(p);
this.parentConversation.me.emit("media:stream:on", {
type,
name: name,
index: index,
localStream
});
const promisesArray = [];

@@ -806,21 +808,36 @@ pc.onicecandidate = (event) => {

/**
* Mute our member
*
* @param {number} [streamIndex] stream id to set
* @param {boolean} [mute] true for mute, false for unmute
* @param {boolean} [audio=true] true for audio stream
* @param {boolean} [video=false] true for video stream
* @example <caption>Mute audio stream</caption>
* media.mute(true, true, false)
* @example <caption>Mute audio and video streams</caption>
* media.mute(true, true, true)
* @example <caption>Mute only video</caption>
* media.mute(true, false, true)
* @private
*/
mute(mute, audio = true, video = false, streamIndex) {
_setMediaTracksAndMute(rtc_id, tracks, mute, mediaType, mediaSuccess) {
this._enableMediaTracks(tracks, !mute);
return new Promise((resolve, reject) => {
this._sendMuteRequest(rtc_id, mediaType, (response) => {
if (response.type === mediaSuccess) {
resolve(response.body);
} else {
this._enableMediaTracks(tracks, mute);
reject(new NexmoApiError(response));
}
})
})
}
let tracks = [];
_waitForAllRtcObject() {
return Promise.all(this.rtcPromises);
}
/**
* Mute our member
*
* @param {number} [streamIndex] stream id to set
* @param {boolean} [mute] true for mute, false for unmute
* @param {boolean} [audio=true] true for audio stream
* @param {boolean} [video=false] true for video stream
* @example <caption>Mute audio stream</caption>
* media.mute(true, true, false)
* @example <caption>Mute audio and video streams</caption>
* media.mute(true, true, true)
* @example <caption>Mute only video</caption>
* media.mute(true, false, true)
* @private
*/
mute(mute, audio = true, video = false, streamIndex) {
const state = mute ? 'on' : 'off';

@@ -834,59 +851,39 @@ const audioType = 'audio:mute:' + state;

const self = this;
if (audio) {
let rtcObjects = [];
if (streamIndex !== undefined) {
const rtcObject = Object.values(this.parentConversation.rtcObjects).find((rtcObj => rtcObj.streamIndex === streamIndex));
if (rtcObject) {
rtcObjects.push(rtcObject);
}
} else {
rtcObjects = rtcObjects.concat(Object.values(this.parentConversation.rtcObjects));
}
rtcObjects.forEach((rtcObject) => {
let audioPromise = new Promise((resolve, reject) => {
tracks = tracks.concat(rtcObject.localStream.getAudioTracks());
this._sendMuteRequest(rtcObject.id, audioType, (response) => {
if (response.type === audioSuccess) {
resolve(response.body);
} else {
reject(new NexmoApiError(response));
const audioPromise = this._waitForAllRtcObject()
.then(() => {
const rtcObject = Object.values(this.parentConversation.rtcObjects).find((rtcObj => rtcObj.streamIndex === streamIndex));
if (rtcObject) {
const audioTracks = rtcObject.localStream.getAudioTracks();
return this._setMediaTracksAndMute(rtcObject.id, audioTracks, mute, audioType, audioSuccess);
}
})
});
});
promises.push(audioPromise);
});
}
}
if (this.application.activeStream && this.application.activeStream.rtc_id) {
const rtc_id = this.application.activeStream.rtc_id;
const audioTracks = this.parentConversation.localStream.getAudioTracks();
const audioPromise = this._setMediaTracksAndMute(rtc_id, audioTracks, mute, audioType, audioSuccess);
promises.push(audioPromise);
}
if (video) {
let rtcObjects = [];
if (streamIndex !== undefined) {
const rtcObject = Object.values(this.parentConversation.rtcObjects).find((rtcObj => rtcObj.streamIndex === streamIndex));
if (rtcObject) {
rtcObjects.push(rtcObject);
}
} else {
rtcObjects = rtcObjects.concat(Object.values(this.parentConversation.rtcObjects));
const audioPromise = this._waitForAllRtcObject()
.then(() => {
const rtcObject = Object.values(this.parentConversation.rtcObjects).find((rtcObj => rtcObj.streamIndex === streamIndex));
if (rtcObject) {
const videoTracks = rtcObject.localStream.getVideoTracks();
return this._setMediaTracksAndMute(rtcObject.id, videoTracks, mute, videoType, videoSuccess);
}
});
promises.push(audioPromise);
}
rtcObjects.forEach((rtcObject) => {
let videoPromise = new Promise((resolve, reject) => {
tracks = tracks.concat(rtcObject.localStream.getVideoTracks());
this._sendMuteRequest(rtcObject.id, videoType, (response) => {
if (response.type === videoSuccess) {
resolve(response.body);
} else {
reject(new NexmoApiError(response));
}
})
});
promises.push(videoPromise);
});
}
this._enableMediaTracks(tracks, !mute);
return Promise.all(promises).catch(function(response) {
self._enableMediaTracks(tracks, mute);
throw response;
});
return Promise.all(promises);
}

@@ -946,7 +943,7 @@

const media_div = document.createElement("div");
media.appendChild(source);
media_div.appendChild(media);
document.insertBefore(media_div);
// Older browsers may not have srcObject

@@ -959,3 +956,3 @@ if ("srcObject" in media) {

}
media.onloadedmetadata = (e) => {

@@ -1072,2 +1069,5 @@ media.play();

const do_gatherDone = () => {
if (!this.parentConversation.pc) {
return;
}
const event_to_emit = {

@@ -1074,0 +1074,0 @@ type: 'rtc:new',

@@ -79,3 +79,3 @@ /*

screenShareExtensionId: '',
SDK_version: '2.1.0-beta.3',
SDK_version: '2.1.0-beta.4',
url: 'https://ws.nexmo.com',

@@ -143,3 +143,4 @@ iceServers: [{

reconnection: config.reconnection,
autoConnect: config.autoConnect
autoConnect: config.autoConnect,
transports: ['websocket']
});

@@ -507,3 +508,2 @@

* logout from the cloud.
*
*/

@@ -519,6 +519,3 @@ logout() {

this.disconnect();
if (this.errorsEmitter) {
this.errorsEmitter.cleanup();
delete this.errorsEmitter;
}
delete this.errorsEmitter;
delete this.application;

@@ -570,11 +567,11 @@ delete this.cache;

_updateTokenInCache(token, username) {
if (this.cache) {
this.cache.updateToken({
token: token,
username: username
});
}
}
_updateTokenInCache(token, username) {
if (this.cache) {
this.cache.updateToken({
token: token,
username: username
});
}
}
}
module.exports = ConversationClient;

@@ -5,3 +5,3 @@ {

"repository": "https://github.com/Nexmo/conversation-js-sdk",
"version": "2.1.0-beta.3",
"version": "2.1.0-beta.4",
"keywords": [

@@ -48,2 +48,3 @@ "nexmo",

"grunt-string-replace": "^1.3.1",
"grunt-terser": "^0.1.0",
"grunt-umd": "^3.0.0",

@@ -50,0 +51,0 @@ "jsdoc": "latest",

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