@testrtc/watchrtc-sdk
Advanced tools
Comparing version 1.30.5 to 1.30.6
@@ -38,2 +38,3 @@ export interface RTCPeerConnectionInformation { | ||
type: EventType; | ||
parameters?: any; | ||
} |
531
lib/sdk.js
@@ -21,139 +21,155 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.setUserRating = exports.initSDK = void 0; | ||
exports.mapStream = exports.addEvent = exports.enableDataCollection = exports.disableDataCollection = exports.addKeys = exports.setUserRating = exports.setConfig = exports.initSDK = void 0; | ||
var watchrtcsocket_1 = require("./watchrtcsocket"); | ||
var watchrtchttp_1 = require("./watchrtchttp"); | ||
var utils_1 = require("./utils"); | ||
var version_1 = require("./version"); | ||
var utils_1 = require("./utils"); | ||
var standardGetstats = true; | ||
// transforms a maplike to an object. Mostly for getStats + | ||
// JSON.parse(JSON.stringify()) | ||
var map2obj = function (m) { | ||
if (!m.entries) { | ||
return m; | ||
} | ||
var o = {}; | ||
m.forEach(function (v, k) { | ||
o[k] = v; | ||
}); | ||
return o; | ||
var isFirefox = !!window.mozRTCPeerConnection; | ||
var isEdge = !!window.RTCIceGatherer; | ||
var isSafari = !isFirefox && window.RTCPeerConnection && !window.navigator.webkitGetUserMedia; | ||
// Data structure for RTCPeerConnection related stuff we need | ||
var openChannels = {}; | ||
var watchrtcIdentifiers = { | ||
rtcRoomId: undefined, | ||
rtcPeerId: undefined, | ||
projectId: undefined, | ||
}; | ||
// apply a delta compression to the stats report. Reduces size by ~90%. | ||
// To reduce further, report keys could be compressed. | ||
var deltaCompression = function (oldStats, newStats) { | ||
newStats = JSON.parse(JSON.stringify(newStats)); | ||
Object.keys(newStats).forEach(function (id) { | ||
var report = newStats[id]; | ||
delete report.id; | ||
if (!oldStats[id]) { | ||
var watchrtcConfig = null; | ||
var http = null; | ||
var socket = null; | ||
var trace; | ||
var lastConnectionOpen = 0; // so we know when was the last active connection seen | ||
var getStatsInterval; | ||
var tryingToConnectSocket = false; | ||
var hardwareInfo; | ||
var maybeOpenWebsocketConnection = function (forceRecreate) { | ||
var _a; | ||
if (forceRecreate === void 0) { forceRecreate = false; } | ||
var opened = ((_a = socket === null || socket === void 0 ? void 0 : socket.connection) === null || _a === void 0 ? void 0 : _a.readyState) === WebSocket.OPEN; | ||
if (opened) { | ||
var roomIdOrPeerIdChanged = utils_1.isRoomIdOrPeerIdChanged(watchrtcIdentifiers, watchrtcConfig); | ||
if (roomIdOrPeerIdChanged && forceRecreate) { | ||
if (watchrtcConfig === null || watchrtcConfig === void 0 ? void 0 : watchrtcConfig.debug) { | ||
console.log.apply(console, __spreadArrays(utils_1.logPrefix("info"), ["maybeOpenWebsocketConnection. Closing WS connection"])); | ||
} | ||
socket === null || socket === void 0 ? void 0 : socket.close(); | ||
} | ||
else { | ||
if (watchrtcConfig === null || watchrtcConfig === void 0 ? void 0 : watchrtcConfig.debug) { | ||
console.log.apply(console, __spreadArrays(utils_1.logPrefix("info"), ["maybeOpenWebsocketConnection. WS connection already opened"])); | ||
} | ||
return; | ||
} | ||
Object.keys(report).forEach(function (name) { | ||
if (report[name] === oldStats[id][name]) { | ||
delete newStats[id][name]; | ||
} | ||
var connectionCount = utils_1.countOfValidConnections(openChannels); | ||
if (connectionCount > 0 && !tryingToConnectSocket) { | ||
var canConnect = utils_1.validateConfig(watchrtcConfig); | ||
var id_1 = Object.keys(openChannels)[connectionCount - 1]; // not very critical, but for consistency with trace | ||
if (canConnect) { | ||
if (watchrtcConfig.keys) { | ||
Object.keys(watchrtcConfig.keys || {}).forEach(function (k) { | ||
if (typeof watchrtcConfig.keys[k] === "string") { | ||
watchrtcConfig.keys[k] = [watchrtcConfig.keys[k]]; | ||
} | ||
}); | ||
} | ||
if (Object.keys(report).length === 0) { | ||
delete newStats[id]; | ||
} | ||
else if (Object.keys(report).length === 1 && report.timestamp) { | ||
delete newStats[id]; | ||
} | ||
}); | ||
}); | ||
var timestamp = -Infinity; | ||
Object.keys(newStats).forEach(function (id) { | ||
var report = newStats[id]; | ||
if (report.timestamp > timestamp) { | ||
timestamp = report.timestamp; | ||
var useToken = !!watchrtcConfig.rtcToken; | ||
var wsConnectionData = utils_1.getConnectionData("ws", useToken ? watchrtcConfig.rtcToken : watchrtcConfig.rtcApiKey, watchrtcConfig.proxyUrl || watchrtcConfig.wsUrl); | ||
tryingToConnectSocket = true; | ||
lastConnectionOpen = Date.now(); | ||
socket === null || socket === void 0 ? void 0 : socket.connect(wsConnectionData.url + "?" + (useToken ? "token" : "apiKey") + "=" + wsConnectionData.key + "×tamp=" + Date.now(), function (data) { | ||
watchrtcIdentifiers.rtcRoomId = watchrtcConfig.rtcRoomId; | ||
watchrtcIdentifiers.rtcPeerId = watchrtcConfig.rtcPeerId; | ||
watchrtcIdentifiers.projectId = data.projectId; | ||
tryingToConnectSocket = false; | ||
console.info.apply(console, __spreadArrays(utils_1.logPrefix("info"), ["Connection established. watchRTCConnectionId: " + data.connectionId + " sdkVersion:" + version_1.default])); | ||
trace("watchrtc", id_1, __assign(__assign(__assign({}, watchrtcConfig), data), { sdkVersion: version_1.default })); | ||
if (hardwareInfo) { | ||
trace("hardware", null, hardwareInfo); | ||
} | ||
if (!isEdge) { | ||
window.clearInterval(getStatsInterval); | ||
getStatsInterval = window.setInterval(function () { | ||
if (utils_1.countOfValidConnections(openChannels) === 0) { | ||
// if we don't have any connection for 20 sec we can close the socket | ||
if (lastConnectionOpen && lastConnectionOpen + 20000 < Date.now()) { | ||
window.clearInterval(getStatsInterval); | ||
socket === null || socket === void 0 ? void 0 : socket.close(); | ||
console.info.apply(console, __spreadArrays(utils_1.logPrefix("info"), ["Last connection closed. watchRTCConnectionId: " + data.connectionId + " sdkVersion: " + version_1.default])); | ||
} | ||
} | ||
else { | ||
lastConnectionOpen = Date.now(); | ||
Object.values(openChannels).forEach(function (pcInfo) { | ||
if (pcInfo.pc.signalingState !== "closed") { | ||
getStats(pcInfo); | ||
} | ||
}); | ||
} | ||
}, data.interval); | ||
} | ||
}, function () { | ||
tryingToConnectSocket = false; | ||
lastConnectionOpen = 0; | ||
}); | ||
} | ||
}); | ||
Object.keys(newStats).forEach(function (id) { | ||
var report = newStats[id]; | ||
if (report.timestamp === timestamp) { | ||
report.timestamp = 0; | ||
else { | ||
tryingToConnectSocket = false; | ||
} | ||
}); | ||
newStats.timestamp = timestamp; | ||
return newStats; | ||
} | ||
}; | ||
var mangleChromeStats = function (pc, response) { | ||
var standardReport = {}; | ||
var reports = response.result(); | ||
reports.forEach(function (report) { | ||
var standardStats = { | ||
id: report.id, | ||
timestamp: report.timestamp.getTime(), | ||
type: report.type, | ||
}; | ||
report.names().forEach(function (name) { | ||
standardStats[name] = report.stat(name); | ||
var getStats = function (pcInfo) { | ||
if (pcInfo) { | ||
var id_2 = pcInfo.id, pc_1 = pcInfo.pc, prev_1 = pcInfo.prev; | ||
if (standardGetstats || isFirefox || isSafari) { | ||
pc_1.getStats(null).then(function (res) { | ||
var now = {}; | ||
if (isFirefox) { | ||
res.forEach(function (report) { | ||
now[report.type + "_" + report.id] = report; | ||
}); | ||
} | ||
else { | ||
now = utils_1.map2obj(res); | ||
} | ||
var base = JSON.parse(JSON.stringify(now)); // our new prev | ||
var data = utils_1.deltaCompression(prev_1, now); | ||
if ((data === null || data === void 0 ? void 0 : data.timestamp) !== null && (data === null || data === void 0 ? void 0 : data.timestamp) !== -Infinity) { | ||
trace("getstats", id_2, data); | ||
} | ||
pcInfo.prev = base; | ||
}); | ||
} | ||
else { | ||
pc_1.getStats(function (res) { | ||
var now = utils_1.mangleChromeStats(pc_1, res); | ||
var base = JSON.parse(JSON.stringify(now)); // our new prev | ||
var data = utils_1.deltaCompression(prev_1, now); | ||
if ((data === null || data === void 0 ? void 0 : data.timestamp) !== null && (data === null || data === void 0 ? void 0 : data.timestamp) !== -Infinity) { | ||
trace("getstats", id_2, data); | ||
} | ||
pcInfo.prev = base; | ||
}); | ||
} | ||
} | ||
}; | ||
var getHardware = function () { | ||
setImmediate(function () { | ||
// if get hardware take more than 50 ms then do not save it | ||
var getHardwareStartTime = Date.now(); | ||
utils_1.getHardwareInfo() | ||
.then(function (hwInfo) { | ||
var getHardwareTime = Date.now() - getHardwareStartTime; | ||
if (getHardwareTime <= 50000) { | ||
hardwareInfo = hwInfo; | ||
} | ||
}) | ||
.catch(function (err) { | ||
console.error("Error. Get hardware info: " + err.message); | ||
}); | ||
standardReport[standardStats.id] = standardStats; | ||
}); | ||
return standardReport; | ||
}; | ||
var dumpStream = function (stream) { | ||
return { | ||
id: stream.id, | ||
tracks: stream.getTracks().map(function (track) { | ||
return { | ||
id: track.id, | ||
kind: track.kind, | ||
label: track.label, | ||
enabled: track.enabled, | ||
muted: track.muted, | ||
readyState: track.readyState, | ||
}; | ||
}), | ||
}; | ||
}; | ||
var getWSConnectionData = function (rtcApiKey, overriddenWsUrl) { | ||
var localUrl = "ws://localhost:9101"; | ||
var stagingUrl = "wss://watchrtc-staging2.testrtc.com"; | ||
var productionUrl = "wss://watchrtc.testrtc.com"; | ||
var splitted = rtcApiKey.split(":"); | ||
if (rtcApiKey.indexOf("local") !== -1) { | ||
return { | ||
url: overriddenWsUrl || localUrl, | ||
apiKey: splitted[1], | ||
}; | ||
} | ||
else if (rtcApiKey.indexOf("staging") !== -1) { | ||
return { | ||
url: overriddenWsUrl || stagingUrl, | ||
apiKey: splitted[1], | ||
}; | ||
} | ||
else if (rtcApiKey.indexOf("production") !== -1) { | ||
return { | ||
url: overriddenWsUrl || productionUrl, | ||
apiKey: splitted[1], | ||
}; | ||
} | ||
else { | ||
return { | ||
url: overriddenWsUrl || productionUrl, | ||
apiKey: splitted[0], | ||
}; | ||
} | ||
}; | ||
var validateConfig = function (config) { | ||
if (!config) { | ||
console.info.apply(console, __spreadArrays(utils_1.logPrefix("error"), ["config is required."])); | ||
return false; | ||
} | ||
else if (!config.rtcApiKey) { | ||
console.info.apply(console, __spreadArrays(utils_1.logPrefix("error"), ["config.rtcApiKey is required."])); | ||
return false; | ||
} | ||
else if (!config.rtcRoomId) { | ||
console.info.apply(console, __spreadArrays(utils_1.logPrefix("error"), ["config.rtcRoomId is required."])); | ||
return false; | ||
} | ||
else if (!config.rtcPeerId) { | ||
console.info.apply(console, __spreadArrays(utils_1.logPrefix("error"), ["config.rtcPeerId is required."])); | ||
return false; | ||
} | ||
return true; | ||
}; | ||
/** | ||
* Initialize SDK. Can be called multiple times but it will be initialized only at the first time. | ||
* Initialize SDK. | ||
* @param watchrtc | ||
@@ -169,9 +185,9 @@ * @param prefixesToWrap | ||
window.watchRTCInitialized = true; | ||
getHardware(); | ||
} | ||
var peerconnectioncounter = 0; | ||
var isFirefox = !!window.mozRTCPeerConnection; | ||
var isEdge = !!window.RTCIceGatherer; | ||
var isSafari = !isFirefox && window.RTCPeerConnection && !window.navigator.webkitGetUserMedia; | ||
var socket = new watchrtcsocket_1.default(); | ||
var trace = socket.trace; | ||
socket = new watchrtcsocket_1.default({ debug: watchrtc === null || watchrtc === void 0 ? void 0 : watchrtc.debug }); | ||
http = new watchrtchttp_1.default({ debug: watchrtc === null || watchrtc === void 0 ? void 0 : watchrtc.debug }); | ||
watchrtcConfig = watchrtc; | ||
trace = socket.trace; | ||
prefixesToWrap.forEach(function (prefix) { | ||
@@ -187,36 +203,19 @@ if (!window[prefix + "RTCPeerConnection"]) { | ||
var peerconnection = function (config, constraints) { | ||
var interval; | ||
if (config === null || config === void 0 ? void 0 : config.watchrtc) { | ||
watchrtcConfig = __assign(__assign({}, watchrtcConfig), config.watchrtc); | ||
} | ||
if (watchrtcConfig === null || watchrtcConfig === void 0 ? void 0 : watchrtcConfig.debug) { | ||
console.info.apply(console, __spreadArrays(utils_1.logPrefix("info"), ["new RTCPeerConnection called.", { | ||
config: config, | ||
constraints: constraints, | ||
}])); | ||
} | ||
var pc = new origPeerConnection(config, constraints); | ||
var id = "PC_" + peerconnectioncounter++; | ||
pc.__rtcStatsId = id; | ||
var watchrtcConfig = watchrtc || (config === null || config === void 0 ? void 0 : config.watchrtc); | ||
var canConnect = validateConfig(watchrtcConfig); | ||
if (canConnect) { | ||
if (watchrtcConfig.rtcTags && !Array.isArray(watchrtcConfig.rtcTags)) { | ||
console.info.apply(console, __spreadArrays(utils_1.logPrefix("info"), ["config.rtcTags must be an array."])); | ||
watchrtcConfig.rtcTags = undefined; | ||
} | ||
var wsConnectionData = getWSConnectionData(watchrtcConfig.rtcApiKey, watchrtcConfig.proxyUrl || watchrtcConfig.wsUrl); | ||
socket.connect(id, wsConnectionData.url + "?apiKey=" + wsConnectionData.apiKey, function (data) { | ||
console.info.apply(console, __spreadArrays(utils_1.logPrefix("info"), ["Connection established. watchRTCConnectionId: " + data.connectionId + " sdkVersion:" + version_1.default])); | ||
trace("watchrtc", id, __assign(__assign(__assign({}, watchrtcConfig), data), { sdkVersion: version_1.default })); | ||
if (!isEdge) { | ||
window.clearInterval(interval); | ||
interval = window.setInterval(function () { | ||
if (pc.signalingState === "closed") { | ||
window.clearInterval(interval); | ||
setTimeout(function () { | ||
if (socket.clients.length === 0 || | ||
(socket.clients.length === 1 && socket.clients.find(function (x) { return x === id; }))) { | ||
socket.close(); | ||
console.info.apply(console, __spreadArrays(utils_1.logPrefix("info"), ["Last connection closed. watchRTCConnectionId: " + data.connectionId + " sdkVersion: " + version_1.default])); | ||
} | ||
}, 1000); | ||
return; | ||
} | ||
getStats(); | ||
}, data.interval); | ||
} | ||
}); | ||
} | ||
openChannels[id] = { | ||
id: id, | ||
pc: pc, | ||
validConnection: false, | ||
}; | ||
if (!config) { | ||
@@ -248,5 +247,17 @@ config = { nullConfig: true }; | ||
} | ||
// wrap RTCRtpSender.setParameters | ||
if ("RTCRtpSender" in window && "setParameters" in window.RTCRtpSender.prototype) { | ||
var origRTCRtpSender = window.RTCRtpSender; | ||
var nativeMethod_1 = origRTCRtpSender.prototype.setParameters; | ||
origRTCRtpSender.prototype.setParameters = function () { | ||
trace("setParameters", id, arguments); | ||
return nativeMethod_1.apply(this, arguments); | ||
}; | ||
} | ||
pc.addEventListener("icecandidate", function (e) { | ||
trace("onicecandidate", id, e.candidate); | ||
}); | ||
pc.addEventListener("icecandidateerror", function (e) { | ||
trace("onicecandidateerror", id, e); | ||
}); | ||
pc.addEventListener("addstream", function (e) { | ||
@@ -276,2 +287,8 @@ trace("onaddstream", id, e.stream.id + | ||
pc.addEventListener("signalingstatechange", function () { | ||
if (openChannels[id] && !openChannels[id].validConnection) { | ||
openChannels[id].validConnection = true; | ||
setTimeout(function () { | ||
maybeOpenWebsocketConnection(true); | ||
}, 5000); | ||
} | ||
trace("onsignalingstatechange", id, pc.signalingState); | ||
@@ -294,31 +311,6 @@ }); | ||
}); | ||
var prev = {}; | ||
var getStats = function () { | ||
if (standardGetstats || isFirefox || isSafari) { | ||
pc.getStats(null).then(function (res) { | ||
var now = map2obj(res); | ||
var base = JSON.parse(JSON.stringify(now)); // our new prev | ||
var data = deltaCompression(prev, now); | ||
if ((data === null || data === void 0 ? void 0 : data.timestamp) !== null && (data === null || data === void 0 ? void 0 : data.timestamp) !== -Infinity) { | ||
trace("getstats", id, deltaCompression(prev, now)); | ||
} | ||
prev = base; | ||
}); | ||
} | ||
else { | ||
pc.getStats(function (res) { | ||
var now = mangleChromeStats(pc, res); | ||
var base = JSON.parse(JSON.stringify(now)); // our new prev | ||
var data = deltaCompression(prev, now); | ||
if ((data === null || data === void 0 ? void 0 : data.timestamp) !== null && (data === null || data === void 0 ? void 0 : data.timestamp) !== -Infinity) { | ||
trace("getstats", id, deltaCompression(prev, now)); | ||
} | ||
prev = base; | ||
}); | ||
} | ||
}; | ||
if (!isEdge) { | ||
pc.addEventListener("iceconnectionstatechange", function () { | ||
if (pc.iceConnectionState === "connected") { | ||
getStats(); | ||
getStats(openChannels[id]); | ||
} | ||
@@ -329,3 +321,3 @@ }); | ||
}; | ||
["createDataChannel", "close"].forEach(function (method) { | ||
["createDataChannel"].forEach(function (method) { | ||
var nativeMethod = origPeerConnection.prototype[method]; | ||
@@ -339,2 +331,12 @@ if (nativeMethod) { | ||
}); | ||
["close"].forEach(function (method) { | ||
var nativeMethod = origPeerConnection.prototype[method]; | ||
if (nativeMethod) { | ||
origPeerConnection.prototype[method] = function () { | ||
trace(method, this.__rtcStatsId, arguments); | ||
delete openChannels[this.__rtcStatsId]; | ||
return nativeMethod.apply(this, arguments); | ||
}; | ||
} | ||
}); | ||
["addStream", "removeStream"].forEach(function (method) { | ||
@@ -423,5 +425,9 @@ var nativeMethod = origPeerConnection.prototype[method]; | ||
var args = arguments; | ||
trace(method, this.__rtcStatsId, args[0]); | ||
var _this = this; | ||
// because of setLocalDescription(null) sometimes we don't have SDP value | ||
// fippo suggested: Access pc.localDescription.sdp in the successcallback | ||
var needToHandleSDPInSuccessCallback = method === "setLocalDescription" && (!args[0] || (args[0] && !args[0].sdp)); | ||
trace(method, this.__rtcStatsId, needToHandleSDPInSuccessCallback ? { parameterless: true } : args[0]); | ||
return nativeMethod.apply(this, [args[0]]).then(function () { | ||
trace(method + "OnSuccess", rtcStatsId, undefined); | ||
trace(method + "OnSuccess", rtcStatsId, needToHandleSDPInSuccessCallback ? _this === null || _this === void 0 ? void 0 : _this.localDescription : undefined); | ||
if (args.length >= 2 && typeof args[1] === "function") { | ||
@@ -470,3 +476,3 @@ args[1].apply(null, []); | ||
// to acquire the cam (in chrome) | ||
trace("getUserMediaOnSuccess", null, dumpStream(stream)); | ||
trace("getUserMediaOnSuccess", null, utils_1.dumpStream(stream)); | ||
if (cb) { | ||
@@ -489,3 +495,3 @@ cb(stream); | ||
return origGetUserMedia_1.apply(navigator.mediaDevices, arguments).then(function (stream) { | ||
trace("navigator.mediaDevices.getUserMediaOnSuccess", null, dumpStream(stream)); | ||
trace("navigator.mediaDevices.getUserMediaOnSuccess", null, utils_1.dumpStream(stream)); | ||
return stream; | ||
@@ -505,3 +511,3 @@ }, function (err) { | ||
return origGetDisplayMedia_1.apply(navigator.mediaDevices, arguments).then(function (stream) { | ||
trace("navigator.mediaDevices.getDisplayMediaOnSuccess", null, dumpStream(stream)); | ||
trace("navigator.mediaDevices.getDisplayMediaOnSuccess", null, utils_1.dumpStream(stream)); | ||
return stream; | ||
@@ -516,13 +522,140 @@ }, function (err) { | ||
}; | ||
exports.setUserRating = function (rate, rateReason) { | ||
exports.setConfig = function (newWatchrtcConfig) { | ||
var initialized = window.watchRTCInitialized; | ||
if (!initialized) { | ||
console.info.apply(console, __spreadArrays(utils_1.logPrefix("error"), ["SDK is not initialized. Use 'init' function fisrt."])); | ||
return; | ||
} | ||
// if debug mode changed | ||
// change it in socket service too | ||
if (newWatchrtcConfig.debug !== undefined && newWatchrtcConfig.debug !== watchrtcConfig.debug) { | ||
socket === null || socket === void 0 ? void 0 : socket.toggleDebug(newWatchrtcConfig.debug); | ||
} | ||
watchrtcConfig = __assign(__assign({}, watchrtcConfig), newWatchrtcConfig); | ||
maybeOpenWebsocketConnection(); | ||
}; | ||
/** | ||
* Set user rating and/or comment for peer session | ||
* @param rating number from 1 to 5 | ||
* @param comment string | ||
*/ | ||
exports.setUserRating = function ( | ||
/** 1 | 2 | 3 | 4 | 5 */ | ||
rating, ratingComment) { | ||
var _a; | ||
if (rate) { | ||
if (watchrtcsocket_1.default._instance && | ||
((_a = watchrtcsocket_1.default._instance.connection) === null || _a === void 0 ? void 0 : _a.readyState) === WebSocket.OPEN) { | ||
watchrtcsocket_1.default._instance.trace("userRating", "", { rate: rate, rateReason: rateReason }); | ||
var initialized = window.watchRTCInitialized; | ||
if (!initialized) { | ||
console.info.apply(console, __spreadArrays(utils_1.logPrefix("error"), ["SDK is not initialized. Use 'init' function fisrt."])); | ||
return; | ||
} | ||
var isValidRating = utils_1.validateRating(rating); | ||
if (!isValidRating) { | ||
return; | ||
} | ||
var opened = ((_a = socket === null || socket === void 0 ? void 0 : socket.connection) === null || _a === void 0 ? void 0 : _a.readyState) === WebSocket.OPEN; | ||
var data = ["userRating", null, { rating: rating, ratingComment: ratingComment }]; | ||
if (opened) { | ||
trace.apply(void 0, data); | ||
} | ||
else { | ||
httpTrace.apply(void 0, data); | ||
} | ||
}; | ||
/** | ||
* Add keys for peer session | ||
* @param keys | ||
*/ | ||
exports.addKeys = function ( | ||
/** { "key1": "value1", "key2": ["value2_1", "value2_2"]} */ | ||
keys) { | ||
var _a; | ||
var initialized = window.watchRTCInitialized; | ||
if (!initialized) { | ||
console.info.apply(console, __spreadArrays(utils_1.logPrefix("error"), ["SDK is not initialized. Use 'init' function fisrt."])); | ||
return; | ||
} | ||
Object.keys(keys || {}).forEach(function (k) { | ||
if (typeof keys[k] === "string") { | ||
keys[k] = [keys[k]]; | ||
} | ||
else { | ||
console.info.apply(console, __spreadArrays(utils_1.logPrefix("error"), ["Please set user rating before websocket connection is closed."])); | ||
} | ||
}); | ||
var data = ["keys", null, keys]; | ||
var opened = ((_a = socket === null || socket === void 0 ? void 0 : socket.connection) === null || _a === void 0 ? void 0 : _a.readyState) === WebSocket.OPEN; | ||
var wasConnected = socket === null || socket === void 0 ? void 0 : socket.wasConnected; | ||
if (opened) { | ||
trace.apply(void 0, data); | ||
} | ||
else if (!wasConnected) { | ||
trace.apply(void 0, data); | ||
} | ||
else { | ||
httpTrace.apply(void 0, data); | ||
} | ||
}; | ||
exports.disableDataCollection = function () { | ||
var initialized = window.watchRTCInitialized; | ||
if (!initialized) { | ||
console.info.apply(console, __spreadArrays(utils_1.logPrefix("error"), ["SDK is not initialized. Use 'init' function fisrt."])); | ||
return; | ||
} | ||
socket === null || socket === void 0 ? void 0 : socket.disableDataCollection(); | ||
}; | ||
exports.enableDataCollection = function () { | ||
var initialized = window.watchRTCInitialized; | ||
if (!initialized) { | ||
console.info.apply(console, __spreadArrays(utils_1.logPrefix("error"), ["SDK is not initialized. Use 'init' function fisrt."])); | ||
return; | ||
} | ||
socket === null || socket === void 0 ? void 0 : socket.enableDataCollection(); | ||
}; | ||
exports.addEvent = function (event) { | ||
var _a; | ||
var initialized = window.watchRTCInitialized; | ||
if (!initialized) { | ||
console.info.apply(console, __spreadArrays(utils_1.logPrefix("error"), ["addEvent error. SDK is not initialized. Use 'init' function fisrt."])); | ||
return; | ||
} | ||
var opened = ((_a = socket === null || socket === void 0 ? void 0 : socket.connection) === null || _a === void 0 ? void 0 : _a.readyState) === WebSocket.OPEN; | ||
if (!opened) { | ||
console.info.apply(console, __spreadArrays(utils_1.logPrefix("error"), ["addEvent error. Connection has been closed."])); | ||
return; | ||
} | ||
var isEventValid = utils_1.validateEvent(event); | ||
if (!isEventValid) { | ||
return; | ||
} | ||
var data = ["event", null, event]; | ||
trace.apply(void 0, data); | ||
}; | ||
exports.mapStream = function (id, name) { | ||
var initialized = window.watchRTCInitialized; | ||
if (!initialized) { | ||
console.info.apply(console, __spreadArrays(utils_1.logPrefix("error"), ["mapStream error. SDK is not initialized. Use 'init' function fisrt."])); | ||
return; | ||
} | ||
var isDataValid = !!id && !!name; | ||
if (!isDataValid) { | ||
return; | ||
} | ||
var data = ["mapStream", null, { id: id, name: name }]; | ||
trace.apply(void 0, data); | ||
}; | ||
var httpTrace = function () { | ||
var data = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
data[_i] = arguments[_i]; | ||
} | ||
if (!watchrtcIdentifiers.rtcRoomId || !watchrtcIdentifiers.rtcPeerId || !watchrtcIdentifiers.projectId) { | ||
console.log.apply(console, __spreadArrays(utils_1.logPrefix("info"), ["Cannot do http trace before connection established"])); | ||
return; | ||
} | ||
var httpConnectionData = utils_1.getConnectionData("http", watchrtcConfig.rtcApiKey); | ||
http === null || http === void 0 ? void 0 : http.trace.apply(http, __spreadArrays([httpConnectionData.url + "/trace", watchrtcIdentifiers.projectId, | ||
watchrtcIdentifiers.rtcRoomId, | ||
watchrtcIdentifiers.rtcPeerId], data)); | ||
}; | ||
// (window as any).setUserRating = setUserRating; | ||
// (window as any).addTags = addTags; | ||
// (window as any).addKeys = addKeys; | ||
// (window as any).init = initSDK; | ||
// (window as any).addEvent = addEvent; |
288
lib/utils.js
"use strict"; | ||
var __assign = (this && this.__assign) || function () { | ||
__assign = Object.assign || function(t) { | ||
for (var s, i = 1, n = arguments.length; i < n; i++) { | ||
s = arguments[i]; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) | ||
t[p] = s[p]; | ||
} | ||
return t; | ||
}; | ||
return __assign.apply(this, arguments); | ||
}; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
var __generator = (this && this.__generator) || function (thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [op[0] & 2, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
} | ||
}; | ||
var __spreadArrays = (this && this.__spreadArrays) || function () { | ||
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; | ||
for (var r = Array(s), k = 0, i = 0; i < il; i++) | ||
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) | ||
r[k] = a[j]; | ||
return r; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.logPrefix = void 0; | ||
exports.getHardwareInfo = exports.validateEvent = exports.validateRating = exports.isRoomIdOrPeerIdChanged = exports.countOfValidConnections = exports.validateConfig = exports.getConnectionData = exports.dumpStream = exports.map2obj = exports.mangleChromeStats = exports.deltaCompression = exports.logPrefix = void 0; | ||
var GPU = require("./detect-gpu"); | ||
exports.logPrefix = function (type) { | ||
@@ -12,6 +67,229 @@ if (type === void 0) { type = "info"; } | ||
] | ||
: [ | ||
"%cwatchRTC", | ||
"background: " + "gold" + "; color: black; padding: 2px 0.5em; border-radius: 0.5em;", | ||
]; | ||
: ["%cwatchRTC", "background: " + "gold" + "; color: black; padding: 2px 0.5em; border-radius: 0.5em;"]; | ||
}; | ||
// apply a delta compression to the stats report. Reduces size by ~90%. | ||
// To reduce further, report keys could be compressed. | ||
// Muly: maybe can improve using https://github.com/AsyncBanana/microdiff?utm_source=tldrnewsletter | ||
exports.deltaCompression = function (oldStats, newStats) { | ||
oldStats = oldStats || {}; | ||
newStats = newStats || {}; | ||
newStats = JSON.parse(JSON.stringify(newStats)); | ||
Object.keys(newStats).forEach(function (id) { | ||
var report = newStats[id]; | ||
delete report.id; | ||
if (!oldStats[id]) { | ||
return; | ||
} | ||
Object.keys(report).forEach(function (name) { | ||
if (report[name] === oldStats[id][name]) { | ||
delete newStats[id][name]; | ||
} | ||
if (Object.keys(report).length === 0) { | ||
delete newStats[id]; | ||
} | ||
else if (Object.keys(report).length === 1 && report.timestamp) { | ||
delete newStats[id]; | ||
} | ||
}); | ||
}); | ||
var timestamp = -Infinity; | ||
Object.keys(newStats).forEach(function (id) { | ||
var report = newStats[id]; | ||
if (report.timestamp > timestamp) { | ||
timestamp = report.timestamp; | ||
} | ||
}); | ||
Object.keys(newStats).forEach(function (id) { | ||
var report = newStats[id]; | ||
if (report.timestamp === timestamp) { | ||
report.timestamp = 0; | ||
} | ||
}); | ||
newStats.timestamp = timestamp; | ||
return newStats; | ||
}; | ||
exports.mangleChromeStats = function (pc, response) { | ||
var standardReport = {}; | ||
var reports = response.result(); | ||
reports.forEach(function (report) { | ||
var standardStats = { | ||
id: report.id, | ||
timestamp: report.timestamp.getTime(), | ||
type: report.type, | ||
}; | ||
report.names().forEach(function (name) { | ||
standardStats[name] = report.stat(name); | ||
}); | ||
standardReport[standardStats.id] = standardStats; | ||
}); | ||
return standardReport; | ||
}; | ||
// transforms a maplike to an object. Mostly for getStats + | ||
// JSON.parse(JSON.stringify()) | ||
exports.map2obj = function (m) { | ||
if (!m.entries) { | ||
return m; | ||
} | ||
var o = {}; | ||
m.forEach(function (v, k) { | ||
o[k] = v; | ||
}); | ||
return o; | ||
}; | ||
exports.dumpStream = function (stream) { | ||
return { | ||
id: stream.id, | ||
tracks: stream.getTracks().map(function (track) { | ||
return { | ||
id: track.id, | ||
kind: track.kind, | ||
label: track.label, | ||
enabled: track.enabled, | ||
muted: track.muted, | ||
readyState: track.readyState, | ||
}; | ||
}), | ||
}; | ||
}; | ||
exports.getConnectionData = function (type, key, overriddenWsUrl) { | ||
var localUrl = (type == "ws" ? "ws" : "http") + "://localhost:9101"; | ||
var stagingUrl = (type == "ws" ? "wss" : "https") + "://watchrtc-staging2.testrtc.com"; | ||
var productionUrl = (type == "ws" ? "wss" : "https") + "://watchrtc.testrtc.com"; | ||
var splitted = key.split(":"); | ||
if (key.indexOf("local") !== -1) { | ||
return { | ||
url: overriddenWsUrl || localUrl, | ||
key: splitted[1], | ||
}; | ||
} | ||
else if (key.indexOf("staging") !== -1) { | ||
return { | ||
url: overriddenWsUrl || stagingUrl, | ||
key: splitted[1], | ||
}; | ||
} | ||
else if (key.indexOf("production") !== -1) { | ||
return { | ||
url: overriddenWsUrl || productionUrl, | ||
key: splitted[1], | ||
}; | ||
} | ||
else { | ||
return { | ||
url: overriddenWsUrl || productionUrl, | ||
key: splitted[0], | ||
}; | ||
} | ||
}; | ||
exports.validateConfig = function (config) { | ||
if (!(config === null || config === void 0 ? void 0 : config.rtcApiKey)) { | ||
if (config === null || config === void 0 ? void 0 : config.debug) { | ||
console.info.apply(console, __spreadArrays(exports.logPrefix("error"), ["config.rtcApiKey or config.rtcToken need to be provided."])); | ||
return false; | ||
} | ||
} | ||
if (!(config === null || config === void 0 ? void 0 : config.rtcRoomId) || !(config === null || config === void 0 ? void 0 : config.rtcPeerId)) { | ||
if (config === null || config === void 0 ? void 0 : config.debug) { | ||
console.info.apply(console, __spreadArrays(exports.logPrefix("info"), ["rtcRoomId or rtcPeerId is empty."])); | ||
} | ||
return false; | ||
} | ||
return true; | ||
}; | ||
exports.countOfValidConnections = function (openChannels) { | ||
return Object.keys(openChannels).filter(function (id) { return openChannels[id].validConnection; }).length; | ||
}; | ||
exports.isRoomIdOrPeerIdChanged = function (watchrtcIdentifiers, watchrtcConfig) { | ||
var changed = false; | ||
if (watchrtcConfig.rtcRoomId && | ||
watchrtcIdentifiers.rtcRoomId && | ||
watchrtcIdentifiers.rtcRoomId !== watchrtcConfig.rtcRoomId) { | ||
changed = true; | ||
} | ||
if (watchrtcConfig.rtcPeerId && | ||
watchrtcIdentifiers.rtcPeerId && | ||
watchrtcIdentifiers.rtcPeerId !== watchrtcConfig.rtcPeerId) { | ||
changed = true; | ||
} | ||
if (changed && watchrtcConfig.debug) { | ||
console.log.apply(console, __spreadArrays(exports.logPrefix("info"), ["maybeOpenWebsocketConnection. rtcRoomId or rtcPeerId has been changed", { | ||
old: { | ||
rtcRoomId: watchrtcIdentifiers.rtcRoomId, | ||
rtcPeerId: watchrtcIdentifiers.rtcPeerId, | ||
}, | ||
new: { | ||
rtcRoomId: watchrtcConfig.rtcRoomId, | ||
rtcPeerId: watchrtcConfig.rtcPeerId, | ||
}, | ||
}])); | ||
} | ||
return changed; | ||
}; | ||
exports.validateRating = function (rating) { | ||
if (!rating) { | ||
console.info.apply(console, __spreadArrays(exports.logPrefix("error"), ["rating parameter is required"])); | ||
return false; | ||
} | ||
if (typeof rating !== "number" || rating < 1 || rating > 5) { | ||
console.info.apply(console, __spreadArrays(exports.logPrefix("error"), ["rating parameter should be number from 1 to 5"])); | ||
return false; | ||
} | ||
return true; | ||
}; | ||
exports.validateEvent = function (event) { | ||
if (!event) { | ||
console.info.apply(console, __spreadArrays(exports.logPrefix("error"), ["event parameter is required"])); | ||
return false; | ||
} | ||
if (event.type !== "global" && event.type !== "local" && event.type !== "log") { | ||
console.info.apply(console, __spreadArrays(exports.logPrefix("error"), ["event.type should be either \"global\" or \"local\" or \"log\""])); | ||
return false; | ||
} | ||
if (event.parameters && typeof event.parameters !== "object") { | ||
console.info.apply(console, __spreadArrays(exports.logPrefix("error"), ["event.parameters should be JSON object\""])); | ||
return false; | ||
} | ||
return true; | ||
}; | ||
exports.getHardwareInfo = function () { return __awaiter(void 0, void 0, void 0, function () { | ||
function number_format(num) { | ||
return (Math.round(num * 100) / 100).toFixed(2); | ||
} | ||
var loadBenchmarks, gpuInfo, result, memory; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
loadBenchmarks = function (fileName) { return __awaiter(void 0, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, new Promise(function (resolve) { | ||
try { | ||
var data = require("./gpu-benchmarks/" + fileName); | ||
data.shift(); | ||
return resolve(data); | ||
} | ||
catch (err) { | ||
console.error("Error. getHardwareInfo. loadBenchmarks", { err: err.stack, fileName: fileName }); | ||
resolve([]); | ||
} | ||
})]; | ||
case 1: return [2 /*return*/, _a.sent()]; | ||
} | ||
}); | ||
}); }; | ||
return [4 /*yield*/, GPU.getGPUTier({ | ||
override: { loadBenchmarks: loadBenchmarks }, | ||
})]; | ||
case 1: | ||
gpuInfo = _a.sent(); | ||
result = __assign(__assign({}, gpuInfo), { cores_count: window.navigator.hardwareConcurrency }); | ||
memory = window.performance["memory"]; | ||
if (memory) { | ||
result.jsHeapSizeLimit = number_format(memory.jsHeapSizeLimit / 1048576); | ||
result.totalJSHeapSize = number_format(memory.totalJSHeapSize / 1048576); | ||
result.usedJSHeapSize = number_format(memory.usedJSHeapSize / 1048576); | ||
} | ||
return [2 /*return*/, result]; | ||
} | ||
}); | ||
}); }; |
@@ -1,2 +0,2 @@ | ||
declare const _default: "1.30.5"; | ||
declare const _default: "1.30.6"; | ||
export default _default; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.default = "1.29.3"; | ||
exports.default = "1.30.6"; |
@@ -47,5 +47,3 @@ "use strict"; | ||
}); | ||
response | ||
.then() | ||
.catch(function (err) { return console.log.apply(console, __spreadArrays(utils_1.logPrefix("error"), [err.message, { err: err.stack }])); }); | ||
response.then().catch(function (err) { return console.log.apply(console, __spreadArrays(utils_1.logPrefix("error"), [err.message, { err: err.stack }])); }); | ||
}; | ||
@@ -52,0 +50,0 @@ return WatchRTCHttp; |
@@ -11,10 +11,13 @@ "use strict"; | ||
var utils_1 = require("./utils"); | ||
var LZString = require("./lz-string"); | ||
var PROTOCOL_VERSION = "2.0"; | ||
var WatchRTCSocket = /** @class */ (function () { | ||
function WatchRTCSocket() { | ||
function WatchRTCSocket(options) { | ||
this.connection = null; | ||
this.clients = []; | ||
this.wasConnected = false; | ||
this.buffer = []; | ||
this.sendInterval = 1; | ||
this.onClose = function () { }; | ||
this.debug = false; | ||
this.dataCollection = true; | ||
if (WatchRTCSocket._instance) { | ||
@@ -25,13 +28,13 @@ console.info.apply(console, __spreadArrays(utils_1.logPrefix("info"), ["WatchRTCSocket instance already created"])); | ||
WatchRTCSocket._instance = this; | ||
this.debug = !!options.debug; | ||
} | ||
} | ||
WatchRTCSocket.prototype.connect = function (id, url, onMessage) { | ||
WatchRTCSocket.prototype.connect = function (url, onData, onError) { | ||
if (WatchRTCSocket._instance.connection) { | ||
WatchRTCSocket._instance.connection.close(); | ||
} | ||
var _this = WatchRTCSocket._instance; | ||
WatchRTCSocket._instance.connection = new WebSocket(url, PROTOCOL_VERSION); | ||
var _this = WatchRTCSocket._instance; | ||
WatchRTCSocket._instance.connection.onopen = function (_e) { | ||
_this.clients.push(id); | ||
}; | ||
WatchRTCSocket._instance.connection.onopen = function (_e) { }; | ||
WatchRTCSocket._instance.connection.onclose = function (_e) { }; | ||
WatchRTCSocket._instance.connection.onmessage = function (e) { | ||
@@ -42,24 +45,23 @@ var _a; | ||
if (data.error) { | ||
(_a = _this === null || _this === void 0 ? void 0 : _this.connection) === null || _a === void 0 ? void 0 : _a.close(); | ||
_this.connection = null; | ||
console.info.apply(console, __spreadArrays(utils_1.logPrefix("error"), ["\n" + data.error])); | ||
(_a = _this === null || _this === void 0 ? void 0 : _this.connection) === null || _a === void 0 ? void 0 : _a.close(); | ||
return; | ||
onError(data.error); | ||
} | ||
else { | ||
if (onMessage) { | ||
onMessage(data); | ||
} | ||
if (data.sendInterval) { | ||
WatchRTCSocket._instance.sendInterval = data.sendInterval; | ||
} | ||
onData(data); | ||
WatchRTCSocket._instance.wasConnected = true; | ||
} | ||
} | ||
catch (err) { | ||
console.info.apply(console, __spreadArrays(utils_1.logPrefix("error"), [e])); | ||
console.info.apply(console, __spreadArrays(utils_1.logPrefix("error"), [{ err: err.stack }])); | ||
onError(err.message); | ||
} | ||
}; | ||
WatchRTCSocket._instance.connection.onclose = function (_e) { | ||
_this.clients = _this.clients.filter(function (x) { return x !== id; }); | ||
}; | ||
WatchRTCSocket._instance.connection.onerror = function (e) { | ||
console.info.apply(console, __spreadArrays(utils_1.logPrefix("error"), ["\n", e])); | ||
onError(e); | ||
}; | ||
@@ -77,2 +79,5 @@ }; | ||
} | ||
if (!WatchRTCSocket._instance.dataCollection) { | ||
return; | ||
} | ||
if (!WatchRTCSocket._instance.connection) { | ||
@@ -89,4 +94,9 @@ if (WatchRTCSocket._instance.buffer.length > 1000) { | ||
var lines = JSON.stringify(WatchRTCSocket._instance.buffer); | ||
var compressedMessage = LZString.compressToEncodedURIComponent(lines); | ||
if (WatchRTCSocket._instance.debug) { | ||
console.log.apply(console, __spreadArrays(utils_1.logPrefix("info"), ["lines: " + lines.length])); | ||
console.log.apply(console, __spreadArrays(utils_1.logPrefix("info"), ["compressedMessage: " + compressedMessage.length])); | ||
} | ||
WatchRTCSocket._instance.buffer = []; | ||
WatchRTCSocket._instance.connection.send(lines); | ||
WatchRTCSocket._instance.connection.send(compressedMessage); | ||
} | ||
@@ -100,6 +110,22 @@ } | ||
WatchRTCSocket._instance.onClose(); | ||
WatchRTCSocket._instance.connection = null; | ||
} | ||
}; | ||
WatchRTCSocket.prototype.disableDataCollection = function () { | ||
if (WatchRTCSocket._instance.debug) { | ||
console.log.apply(console, __spreadArrays(utils_1.logPrefix("info"), ["Data collection disabled."])); | ||
} | ||
WatchRTCSocket._instance.dataCollection = false; | ||
}; | ||
WatchRTCSocket.prototype.enableDataCollection = function () { | ||
if (WatchRTCSocket._instance.debug) { | ||
console.log.apply(console, __spreadArrays(utils_1.logPrefix("info"), ["Data collection enabled."])); | ||
} | ||
WatchRTCSocket._instance.dataCollection = true; | ||
}; | ||
WatchRTCSocket.prototype.toggleDebug = function (debug) { | ||
WatchRTCSocket._instance.debug = debug; | ||
}; | ||
return WatchRTCSocket; | ||
}()); | ||
exports.default = WatchRTCSocket; |
{ | ||
"name": "@testrtc/watchrtc-sdk", | ||
"version": "1.30.5", | ||
"version": "1.30.6", | ||
"description": "Monitor your WebRTC application by collecting WebRTC statistics from end users", | ||
@@ -5,0 +5,0 @@ "main": "lib/index.js", |
@@ -170,5 +170,6 @@ # watchRTC JS SDK | ||
- "global" - the event will be in the event log, peer level charts and on the room level charts | ||
- parameters - (optional) JSON object to attach to the event. This will appear in the event log | ||
```javascript | ||
watchRTC.addEvent("Screen sharing", "global"); | ||
watchRTC.addEvent({ name: "my event", type: "global", parameters: { param1: "value1" } }); | ||
``` | ||
@@ -232,1 +233,13 @@ | ||
- Added support for parameterless setLocalDescription() calls | ||
### 1.30.6 (November 19, 2021) | ||
#### New features | ||
- Added support for custom keys with multiple values | ||
### 1.30.7 (TBD, 2022) | ||
#### New features | ||
- `watchRTC.addEvent()` now also supports parameters |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
465331
2287
244
2