Socket
Socket
Sign inDemoInstall

@roomservice/browser

Package Overview
Dependencies
Maintainers
2
Versions
126
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@roomservice/browser - npm Package Compare versions

Comparing version 3.0.0-1 to 3.0.0-2

868

dist/browser.cjs.development.js

@@ -75,79 +75,181 @@ 'use strict';

var SuperlumeWebSocket = /*#__PURE__*/function () {
function SuperlumeWebSocket(conn) {
var _this = this;
// A type of promise-like that resolves synchronously and supports only one observer
const _Pact = /*#__PURE__*/(function() {
function _Pact() {}
_Pact.prototype.then = function(onFulfilled, onRejected) {
const result = new _Pact();
const state = this.s;
if (state) {
const callback = state & 1 ? onFulfilled : onRejected;
if (callback) {
try {
_settle(result, 1, callback(this.v));
} catch (e) {
_settle(result, 2, e);
}
return result;
} else {
return this;
}
}
this.o = function(_this) {
try {
const value = _this.v;
if (_this.s & 1) {
_settle(result, 1, onFulfilled ? onFulfilled(value) : value);
} else if (onRejected) {
_settle(result, 1, onRejected(value));
} else {
_settle(result, 2, value);
}
} catch (e) {
_settle(result, 2, e);
}
};
return result;
};
return _Pact;
})();
this.callbacks = {};
this.lastTime = 0;
this.msgsThisMilisecond = 0;
this.conn = conn;
// Settles a pact synchronously
function _settle(pact, state, value) {
if (!pact.s) {
if (value instanceof _Pact) {
if (value.s) {
if (state & 1) {
state = value.s;
}
value = value.v;
} else {
value.o = _settle.bind(null, pact, state);
return;
}
}
if (value && value.then) {
value.then(_settle.bind(null, pact, state), _settle.bind(null, pact, 2));
return;
}
pact.s = state;
pact.v = value;
const observer = pact.o;
if (observer) {
observer(pact);
}
}
}
this.conn.onmessage = function (ev) {
var msg = JSON.parse(ev.data);
function _isSettledPact(thenable) {
return thenable instanceof _Pact && thenable.s & 1;
}
_this.dispatch(msg.type, msg.body);
};
}
const _iteratorSymbol = /*#__PURE__*/ typeof Symbol !== "undefined" ? (Symbol.iterator || (Symbol.iterator = Symbol("Symbol.iterator"))) : "@@iterator";
var _proto = SuperlumeWebSocket.prototype;
const _asyncIteratorSymbol = /*#__PURE__*/ typeof Symbol !== "undefined" ? (Symbol.asyncIterator || (Symbol.asyncIterator = Symbol("Symbol.asyncIterator"))) : "@@asyncIterator";
_proto.timestamp = function timestamp() {
var time = Date.now();
// Asynchronously implement a generic for loop
function _for(test, update, body) {
var stage;
for (;;) {
var shouldContinue = test();
if (_isSettledPact(shouldContinue)) {
shouldContinue = shouldContinue.v;
}
if (!shouldContinue) {
return result;
}
if (shouldContinue.then) {
stage = 0;
break;
}
var result = body();
if (result && result.then) {
if (_isSettledPact(result)) {
result = result.s;
} else {
stage = 1;
break;
}
}
if (update) {
var updateValue = update();
if (updateValue && updateValue.then && !_isSettledPact(updateValue)) {
stage = 2;
break;
}
}
}
var pact = new _Pact();
var reject = _settle.bind(null, pact, 2);
(stage === 0 ? shouldContinue.then(_resumeAfterTest) : stage === 1 ? result.then(_resumeAfterBody) : updateValue.then(_resumeAfterUpdate)).then(void 0, reject);
return pact;
function _resumeAfterBody(value) {
result = value;
do {
if (update) {
updateValue = update();
if (updateValue && updateValue.then && !_isSettledPact(updateValue)) {
updateValue.then(_resumeAfterUpdate).then(void 0, reject);
return;
}
}
shouldContinue = test();
if (!shouldContinue || (_isSettledPact(shouldContinue) && !shouldContinue.v)) {
_settle(pact, 1, result);
return;
}
if (shouldContinue.then) {
shouldContinue.then(_resumeAfterTest).then(void 0, reject);
return;
}
result = body();
if (_isSettledPact(result)) {
result = result.v;
}
} while (!result || !result.then);
result.then(_resumeAfterBody).then(void 0, reject);
}
function _resumeAfterTest(shouldContinue) {
if (shouldContinue) {
result = body();
if (result && result.then) {
result.then(_resumeAfterBody).then(void 0, reject);
} else {
_resumeAfterBody(result);
}
} else {
_settle(pact, 1, result);
}
}
function _resumeAfterUpdate() {
if (shouldContinue = test()) {
if (shouldContinue.then) {
shouldContinue.then(_resumeAfterTest).then(void 0, reject);
} else {
_resumeAfterTest(shouldContinue);
}
} else {
_settle(pact, 1, result);
}
}
}
if (time === this.lastTime) {
this.msgsThisMilisecond++;
} else {
this.lastTime = time;
this.msgsThisMilisecond = 0;
}
// Asynchronously call a function and send errors to recovery continuation
function _catch(body, recover) {
try {
var result = body();
} catch(e) {
return recover(e);
}
if (result && result.then) {
return result.then(void 0, recover);
}
return result;
}
return time + ":" + this.msgsThisMilisecond;
};
function delay(ms) {
return new Promise(function (resolve) {
return setTimeout(resolve, ms);
});
}
_proto.send = function send(msgType, body) {
var _this2 = this;
var ts = this.timestamp();
var msg = {
type: msgType,
ts: ts,
ver: 0,
body: body
}; // If the client is connecting, buffer a bit and retry
if (this.conn.readyState === this.conn.CONNECTING) {
setTimeout(function () {
// @ts-ignore
_this2.send(msgType, body);
}, 100 + Math.random() * 100);
return;
}
this.conn.send(JSON.stringify(msg));
};
_proto.bind = function bind(msgType, callback) {
this.callbacks[msgType] = this.callbacks[msgType] || [];
this.callbacks[msgType].push(callback);
return callback;
};
_proto.unbind = function unbind(msgType, callback) {
this.callbacks[msgType] = this.callbacks[msgType].filter(function (c) {
return c !== callback;
});
};
_proto.dispatch = function dispatch(msgType, body) {
var stack = this.callbacks[msgType];
if (!stack) return;
for (var i = 0; i < stack.length; i++) {
stack[i](body);
}
};
return SuperlumeWebSocket;
}();
var fetchSession = function fetchSession(strategy, ctx, room, document) {

@@ -293,2 +395,294 @@ try {

var openWS = function openWS(url) {
try {
return Promise.resolve(new Promise(function (resolve, reject) {
var ws = new WebSocket(url);
ws.onopen = function () {
resolve(ws);
};
ws.onerror = function (err) {
reject(err);
};
}));
} catch (e) {
return Promise.reject(e);
}
};
var WEBSOCKET_TIMEOUT = 1000 * 2;
var MAX_UNSENT_DOC_CMDS = 10000;
var FORWARDED_TYPES = ['doc:fwd', 'presence:fwd', 'room:rm_guest'];
var ReconnectingWebSocket = /*#__PURE__*/function () {
function ReconnectingWebSocket(params) {
this.callbacks = {};
this.lastTime = 0;
this.msgsThisMilisecond = 0;
this.docCmdSendQueue = []; // only most recent presence cmd per-key is kept
this.presenceCmdSendQueue = new Map();
this.dispatcher = params.dispatcher;
this.wsURL = params.wsURL;
this.docsURL = params.docsURL;
this.room = params.room;
this.session = params.session;
this.wsFactory = params.wsFactory || openWS;
this.documentFetch = params.documentFetch || fetchDocument;
this.wsLoop();
}
var _proto = ReconnectingWebSocket.prototype;
_proto.close = function close() {
if (this.currentConn) {
this.currentConn.onmessage = null;
this.currentConn.onclose = null;
this.currentConn.close();
this.currentConn = undefined;
}
if (this.pendingConn) {
this.pendingConn = undefined;
}
this.dispatcher.startQueueingCmds();
} // one-off attempt to connect and authenticate
;
_proto.connectAndAuth = function connectAndAuth() {
try {
var _this2 = this;
return Promise.resolve(_this2.wsFactory(_this2.wsURL)).then(function (ws) {
ws.onmessage = function (ev) {
var msg = JSON.parse(ev.data);
_this2.dispatch(msg.type, msg.body);
};
ws.onclose = function () {
return _this2.close();
};
return Promise.resolve(ws).then(function (ws) {
try {
ws.send(_this2.serializeMsg('guest:authenticate', _this2.session.token));
return Promise.resolve(_this2.once('guest:authenticated')).then(function () {
ws.send(_this2.serializeMsg('room:join', _this2.room));
return Promise.resolve(_this2.once('room:joined')).then(function () {
return Promise.resolve(_this2.documentFetch(_this2.docsURL, _this2.session.token, _this2.session.docID)).then(function (_ref) {
var body = _ref.body;
_this2.dispatcher.bootstrap(body);
return ws;
});
});
});
} catch (e) {
return Promise.reject(e);
}
});
});
} catch (e) {
return Promise.reject(e);
}
} // main logic to obtain an active and auth'd connection
;
_proto.conn = function conn() {
try {
var _this4 = this;
if (_this4.currentConn) {
return Promise.resolve(_this4.currentConn);
}
if (_this4.pendingConn) {
return Promise.resolve(_this4.pendingConn);
}
_this4.close();
_this4.pendingConn = function () {
try {
var _exit2 = false;
var delayMs = 0;
var maxDelayMs = 60 * 1000;
return Promise.resolve(_for(function () {
return !_exit2;
}, void 0, function () {
var jitteredDelay = delayMs * (Math.random() + 1) / 2;
return Promise.resolve(delay(jitteredDelay)).then(function () {
delayMs = Math.min(2 * delayMs + 100, maxDelayMs);
return _catch(function () {
return Promise.resolve(_this4.connectAndAuth()).then(function (ws) {
_this4.currentConn = ws;
_this4.pendingConn = undefined;
_exit2 = true;
return ws;
});
}, function (err) {
console.error('Connection to RoomService failed with', err, '\nRetrying...');
});
});
}));
} catch (e) {
return Promise.reject(e);
}
}();
return Promise.resolve(_this4.pendingConn);
} catch (e) {
return Promise.reject(e);
}
};
_proto.wsLoop = function wsLoop() {
try {
var _this6 = this;
var _temp2 = _for(function () {
return true;
}, void 0, function () {
return Promise.resolve(_this6.conn()).then(function () {
_this6.processSendQueue();
return Promise.resolve(delay(1000)).then(function () {});
});
});
return Promise.resolve(_temp2 && _temp2.then ? _temp2.then(function () {}) : void 0);
} catch (e) {
return Promise.reject(e);
}
};
_proto.timestamp = function timestamp() {
var time = Date.now();
if (time === this.lastTime) {
this.msgsThisMilisecond++;
} else {
this.lastTime = time;
this.msgsThisMilisecond = 0;
}
return time + ":" + this.msgsThisMilisecond;
};
_proto.serializeMsg = function serializeMsg(msgType, body) {
var ts = this.timestamp();
var msg = {
type: msgType,
ts: ts,
ver: 0,
body: body
};
return JSON.stringify(msg);
};
_proto.send = function send(msgType, body) {
if (msgType == 'doc:cmd') {
if (this.docCmdSendQueue.length >= MAX_UNSENT_DOC_CMDS) {
throw 'RoomService send queue full';
}
var msg = this.serializeMsg(msgType, body);
this.docCmdSendQueue.push(msg);
}
if (msgType == 'presence:cmd') {
var _msg = this.serializeMsg(msgType, body);
var presenceBody = body;
this.presenceCmdSendQueue.set(presenceBody.key, _msg);
}
this.processSendQueue();
};
_proto.processSendQueue = function processSendQueue() {
if (!this.currentConn) {
return;
}
try {
while (this.presenceCmdSendQueue.size > 0) {
var first = this.presenceCmdSendQueue.entries().next();
if (first) {
var _first$value = first.value,
key = _first$value[0],
msg = _first$value[1];
this.currentConn.send(msg);
this.presenceCmdSendQueue["delete"](key);
}
}
while (this.docCmdSendQueue.length > 0) {
var _msg2 = this.docCmdSendQueue[0];
this.currentConn.send(_msg2);
this.docCmdSendQueue.splice(0, 1);
}
} catch (e) {
console.error(e);
}
};
_proto.bind = function bind(msgType, callback) {
this.callbacks[msgType] = this.callbacks[msgType] || [];
this.callbacks[msgType].push(callback);
return callback;
};
_proto.unbind = function unbind(msgType, callback) {
this.callbacks[msgType] = this.callbacks[msgType].filter(function (c) {
return c !== callback;
});
};
_proto.dispatch = function dispatch(msgType, body) {
if (msgType == 'error') {
console.error(body);
}
var stack = this.callbacks[msgType];
if (stack) {
for (var i = 0; i < stack.length; i++) {
stack[i](body);
}
}
if (FORWARDED_TYPES.includes(msgType)) {
this.dispatcher.forwardCmd(msgType, body);
}
};
_proto.once = function once(msg) {
try {
var _this8 = this;
var off;
return Promise.race([new Promise(function (_, reject) {
return setTimeout(function () {
return reject('timeout');
}, WEBSOCKET_TIMEOUT);
}), new Promise(function (resolve) {
off = _this8.bind(msg, function (body) {
resolve(body);
});
})]).then(function () {
if (off) _this8.unbind(msg, off);
});
} catch (e) {
return Promise.reject(e);
}
};
return ReconnectingWebSocket;
}();
var InnerListClient = /*#__PURE__*/function () {

@@ -314,2 +708,6 @@ function InnerListClient(props) {

_proto.bootstrap = function bootstrap(checkpoint) {
core.ListInterpreter.importFromRawCheckpoint(this.store, checkpoint, this.meta.listID);
};
_proto.sendCmd = function sendCmd(cmd) {

@@ -409,3 +807,4 @@ this.ws.send('doc:cmd', {

this.store = store;
this.meta = meta;
this.meta = meta; //TODO: defer initial bootstrap?
core.MapInterpreter.importFromRawCheckpoint(this.store, props.checkpoint, this.meta.mapID);

@@ -416,2 +815,6 @@ }

_proto.bootstrap = function bootstrap(checkpoint) {
core.MapInterpreter.importFromRawCheckpoint(this.store, checkpoint, this.meta.mapID);
};
_proto.sendCmd = function sendCmd(cmd) {

@@ -525,3 +928,2 @@ this.ws.send('doc:cmd', {

this.bus = props.bus;
this.key = props.key;

@@ -542,9 +944,9 @@ var sendPres = function sendPres(_, args) {

_proto.getAll = function getAll() {
_proto.getAll = function getAll(key) {
try {
var _this3 = this;
return Promise.resolve(fetchPresence(PRESENCE_URL, _this3.token, _this3.roomID, _this3.key)).then(function (val) {
_this3.cache[_this3.key] = val;
return _this3.withoutExpiredAndSelf(_this3.key);
return Promise.resolve(fetchPresence(PRESENCE_URL, _this3.token, _this3.roomID, key)).then(function (val) {
_this3.cache[key] = val;
return _this3.withoutExpiredAndSelf(key);
});

@@ -605,7 +1007,7 @@ } catch (e) {

/**
*
* @param key
* @param value Any arbitrary object, string, boolean, or number.
* @param exp (Optional) Expiration time in seconds
*/
_proto.set = function set(value, exp) {
_proto.set = function set(key, value, exp) {
var addition = exp ? exp : 60; // Convert to unix + add seconds

@@ -615,9 +1017,9 @@

this.bus.publish({
key: this.key,
key: key,
value: value,
expAt: expAt
});
this.sendPres(this.key, {
this.sendPres(key, {
room: this.roomID,
key: this.key,
key: key,
value: JSON.stringify(value),

@@ -627,11 +1029,11 @@ expAt: expAt

if (!this.cache[this.key]) {
this.cache[this.key] = {};
if (!this.cache[key]) {
this.cache[key] = {};
}
this.cache[this.key][this.actor] = {
this.cache[key][this.actor] = {
value: value,
expAt: new Date(expAt * 1000)
};
return this.withoutExpiredAndSelf(this.key);
return this.withoutExpiredAndSelf(key);
};

@@ -719,15 +1121,18 @@

try {
return Promise.resolve(fetchSession(params.authStrategy, params.authCtx, params.room, params.document)).then(function (sess) {
return Promise.resolve(fetchDocument(params.docsURL, sess.token, sess.docID)).then(function (_ref2) {
return Promise.resolve(fetchSession(params.authStrategy, params.authCtx, params.room, params.document)).then(function (session) {
return Promise.resolve(fetchDocument(params.docsURL, session.token, session.docID)).then(function (_ref2) {
var body = _ref2.body;
var roomClient = new RoomClient({
conn: params.conn,
actor: sess.guestReference,
actor: session.guestReference,
checkpoint: body,
token: sess.token,
roomID: sess.roomID
token: session.token,
roomID: session.roomID,
docID: params.document,
auth: params.authStrategy,
authCtx: params.authCtx,
wsURL: WS_URL,
docsURL: DOCS_URL,
session: session
});
return Promise.resolve(roomClient.reconnect()).then(function () {
return roomClient;
});
return roomClient;
});

@@ -739,3 +1144,2 @@ });

};
var WEBSOCKET_TIMEOUT = 1000 * 2;
var MAP_CMDS = ['mcreate', 'mput', 'mputref', 'mdel'];

@@ -745,11 +1149,20 @@ var LIST_CMDS = ['lcreate', 'lins', 'linsref', 'lput', 'lputref', 'ldel'];

function RoomClient(params) {
var _this = this;
this.listClients = {};
this.mapClients = {};
this.expires = {};
this.queueIncomingCmds = true;
this.cmdQueue = [];
this.mapCallbacksByObjID = {};
this.listCallbacksByObjID = {};
this.presenceCallbacksByKey = {};
this.ws = new SuperlumeWebSocket(params.conn);
var wsURL = params.wsURL,
docsURL = params.docsURL,
roomID = params.roomID;
this.ws = new ReconnectingWebSocket({
dispatcher: this,
wsURL: wsURL,
docsURL: docsURL,
room: roomID,
session: params.session
});
this.token = params.token;

@@ -760,56 +1173,113 @@ this.roomID = params.roomID;

this.checkpoint = params.checkpoint;
this.InnerPresenceClient = undefined;
var vs = core.vsReader(window.atob);
this.ws.bind('doc:fwd', function (body) {
if (body.room !== _this.roomID) return;
} // impl WebsocketDispatch
if (!body.args || body.args.length < 3) {
// Potentially a network failure, we don't want to crash,
// but do want to warn people
console.error('Unexpected command: ', body.args);
return;
} // Ignore version stamps older than checkpoint
var _proto = RoomClient.prototype;
if (vs.isOlderVS(body.vs, _this.checkpoint.vs)) return; // Ignore validated commands
_proto.forwardCmd = function forwardCmd(msgType, body) {
if (this.queueIncomingCmds) {
this.cmdQueue.push([msgType, body]);
return;
}
if (body.from === _this.actor) return;
var _ref = [body.args[0], body.args[1], body.args[2]],
cmd = _ref[0],
docID = _ref[1],
objID = _ref[2];
if (docID !== _this.docID) return;
this.processCmd(msgType, body);
};
if (MAP_CMDS.includes(cmd)) {
_this.dispatchMapCmd(objID, body);
} else if (LIST_CMDS.includes(cmd)) {
_this.dispatchListCmd(objID, body);
} else {
console.warn('Unhandled Room Service doc:fwd command: ' + cmd + '. Consider updating the Room Service client.');
}
});
this.ws.bind('presence:fwd', function (body) {
_this.dispatchPresenceCmd(body);
});
this.ws.bind('room:rm_guest', function (body) {
if (body.room !== _this.roomID) return;
_proto.processCmd = function processCmd(msgType, body) {
if (msgType == 'doc:fwd' && 'args' in body) {
this.dispatchDocCmd(body);
}
var client = _this.presence('_____any');
if (msgType == 'presence:fwd' && 'expAt' in body) {
this.dispatchPresenceCmd(body);
}
var newClient = client.dangerouslyUpdateClientDirectly('room:rm_guest', body);
if (msgType == 'room:rm_guest' && 'guest' in body) {
this.dispatchRmGuest(body);
}
};
for (var _i = 0, _Object$entries = Object.entries(_this.presenceCallbacksByKey); _i < _Object$entries.length; _i++) {
var _Object$entries$_i = _Object$entries[_i],
cbs = _Object$entries$_i[1];
_proto.bootstrap = function bootstrap(checkpoint) {
this.checkpoint = checkpoint;
for (var _iterator = _createForOfIteratorHelperLoose(cbs), _step; !(_step = _iterator()).done;) {
var cb = _step.value;
cb(newClient, body.guest);
}
for (var _i = 0, _Object$entries = Object.entries(this.listClients); _i < _Object$entries.length; _i++) {
var _Object$entries$_i = _Object$entries[_i],
client = _Object$entries$_i[1];
client.bootstrap(checkpoint);
}
for (var _i2 = 0, _Object$entries2 = Object.entries(this.mapClients); _i2 < _Object$entries2.length; _i2++) {
var _Object$entries2$_i = _Object$entries2[_i2],
_client = _Object$entries2$_i[1];
_client.bootstrap(checkpoint);
}
this.queueIncomingCmds = false;
for (var _iterator = _createForOfIteratorHelperLoose(this.cmdQueue), _step; !(_step = _iterator()).done;) {
var _step$value = _step.value,
msgType = _step$value[0],
body = _step$value[1];
this.processCmd(msgType, body);
}
this.cmdQueue.length = 0;
};
_proto.startQueueingCmds = function startQueueingCmds() {
this.queueIncomingCmds = true;
};
_proto.dispatchDocCmd = function dispatchDocCmd(body) {
if (body.room !== this.roomID) return;
if (!body.args || body.args.length < 3) {
// Potentially a network failure, we don't want to crash,
// but do want to warn people
console.error('Unexpected command: ', body.args);
return;
} // Ignore version stamps older than checkpoint
if (core.vsReader(atob).isOlderVS(body.vs, this.checkpoint.vs)) {
return;
} // Ignore validated commands
if (body.from === this.actor) {
return;
}
var _ref = [body.args[0], body.args[1], body.args[2]],
cmd = _ref[0],
docID = _ref[1],
objID = _ref[2];
if (docID !== this.docID) return;
if (MAP_CMDS.includes(cmd)) {
this.dispatchMapCmd(objID, body);
} else if (LIST_CMDS.includes(cmd)) {
this.dispatchListCmd(objID, body);
} else {
console.warn('Unhandled Room Service doc:fwd command: ' + cmd + '. Consider updating the Room Service client.');
}
};
_proto.dispatchRmGuest = function dispatchRmGuest(body) {
if (body.room !== this.roomID) return;
var client = this.presence();
var newClient = client.dangerouslyUpdateClientDirectly('room:rm_guest', body);
for (var _i3 = 0, _Object$entries3 = Object.entries(this.presenceCallbacksByKey); _i3 < _Object$entries3.length; _i3++) {
var _Object$entries3$_i = _Object$entries3[_i3],
cbs = _Object$entries3$_i[1];
for (var _iterator2 = _createForOfIteratorHelperLoose(cbs), _step2; !(_step2 = _iterator2()).done;) {
var cb = _step2.value;
cb(newClient, body.guest);
}
});
}
}
};
var _proto = RoomClient.prototype;
_proto.dispatchMapCmd = function dispatchMapCmd(objID, body) {

@@ -823,4 +1293,4 @@ if (!this.mapClients[objID]) {

for (var _iterator2 = _createForOfIteratorHelperLoose(this.mapCallbacksByObjID[objID] || []), _step2; !(_step2 = _iterator2()).done;) {
var cb = _step2.value;
for (var _iterator3 = _createForOfIteratorHelperLoose(this.mapCallbacksByObjID[objID] || []), _step3; !(_step3 = _iterator3()).done;) {
var cb = _step3.value;
cb(updatedClient.toObject(), body.from);

@@ -838,4 +1308,4 @@ }

for (var _iterator3 = _createForOfIteratorHelperLoose(this.listCallbacksByObjID[objID] || []), _step3; !(_step3 = _iterator3()).done;) {
var cb = _step3.value;
for (var _iterator4 = _createForOfIteratorHelperLoose(this.listCallbacksByObjID[objID] || []), _step4; !(_step4 = _iterator4()).done;) {
var cb = _step4.value;
cb(updatedClient.toArray(), body.from);

@@ -846,7 +1316,7 @@ }

_proto.dispatchPresenceCmd = function dispatchPresenceCmd(body) {
var _this2 = this;
var _this = this;
if (body.room !== this.roomID) return;
if (body.from === this.actor) return;
var client = this.presence(body.key);
var client = this.presence();
var key = body.key;

@@ -873,6 +1343,6 @@ var now = new Date().getTime() / 1000;

for (var _iterator4 = _createForOfIteratorHelperLoose((_this2$presenceCallba = _this2.presenceCallbacksByKey[key]) !== null && _this2$presenceCallba !== void 0 ? _this2$presenceCallba : []), _step4; !(_step4 = _iterator4()).done;) {
var _this2$presenceCallba;
for (var _iterator5 = _createForOfIteratorHelperLoose((_this$presenceCallbac = _this.presenceCallbacksByKey[key]) !== null && _this$presenceCallbac !== void 0 ? _this$presenceCallbac : []), _step5; !(_step5 = _iterator5()).done;) {
var _this$presenceCallbac;
var cb = _step4.value;
var cb = _step5.value;
cb(newClient, body.from);

@@ -887,6 +1357,6 @@ }

for (var _iterator5 = _createForOfIteratorHelperLoose((_this$presenceCallbac = this.presenceCallbacksByKey[key]) !== null && _this$presenceCallbac !== void 0 ? _this$presenceCallbac : []), _step5; !(_step5 = _iterator5()).done;) {
var _this$presenceCallbac;
for (var _iterator6 = _createForOfIteratorHelperLoose((_this$presenceCallbac2 = this.presenceCallbacksByKey[key]) !== null && _this$presenceCallbac2 !== void 0 ? _this$presenceCallbac2 : []), _step6; !(_step6 = _iterator6()).done;) {
var _this$presenceCallbac2;
var cb = _step5.value;
var cb = _step6.value;
cb(newClient, body.from);

@@ -896,62 +1366,11 @@ }

_proto.once = function once(msg) {
try {
var _this4 = this;
var off;
return Promise.race([new Promise(function (_, reject) {
return setTimeout(function () {
return reject('timeout');
}, WEBSOCKET_TIMEOUT);
}), new Promise(function (resolve) {
off = _this4.ws.bind(msg, function (body) {
resolve(body);
});
})]).then(function () {
if (off) _this4.ws.unbind(msg, off);
});
} catch (e) {
return Promise.reject(e);
}
}
/**
* TODO: don't expose this function
*/
;
_proto.reconnect = function reconnect() {
try {
var _this6 = this;
if (!_this6.errorListener) {
_this6.errorListener = _this6.ws.bind('error', function (err) {
console.error('Room Service encountered a server-side error. If you see this, please let us know; this could be a bug.', err);
});
}
var authenticated = _this6.once('guest:authenticated');
_this6.ws.send('guest:authenticate', _this6.token);
return Promise.resolve(authenticated).then(function () {
var joined = _this6.once('room:joined');
_this6.ws.send('room:join', _this6.roomID);
return Promise.resolve(joined).then(function () {});
});
} catch (e) {
return Promise.reject(e);
}
};
_proto.createListLocally = function createListLocally(name) {
var _this7 = this;
var _this2 = this;
var bus = new LocalBus();
bus.subscribe(function (body) {
var client = _this7.listClients[name];
var client = _this2.listClients[name];
for (var _iterator6 = _createForOfIteratorHelperLoose(_this7.listCallbacksByObjID[name] || []), _step6; !(_step6 = _iterator6()).done;) {
var cb = _step6.value;
for (var _iterator7 = _createForOfIteratorHelperLoose(_this2.listCallbacksByObjID[name] || []), _step7; !(_step7 = _iterator7()).done;) {
var cb = _step7.value;
cb(client.toArray(), body.from);

@@ -996,10 +1415,10 @@ }

_proto.createMapLocally = function createMapLocally(name) {
var _this8 = this;
var _this3 = this;
var bus = new LocalBus();
bus.subscribe(function (body) {
var client = _this8.mapClients[name];
var client = _this3.mapClients[name];
for (var _iterator7 = _createForOfIteratorHelperLoose(_this8.mapCallbacksByObjID[name] || []), _step7; !(_step7 = _iterator7()).done;) {
var cb = _step7.value;
for (var _iterator8 = _createForOfIteratorHelperLoose(_this3.mapCallbacksByObjID[name] || []), _step8; !(_step8 = _iterator8()).done;) {
var cb = _step8.value;
cb(client.toObject(), body.from);

@@ -1037,4 +1456,4 @@ }

_proto.presence = function presence(key) {
var _this9 = this;
_proto.presence = function presence() {
var _this4 = this;

@@ -1047,8 +1466,8 @@ if (this.InnerPresenceClient) {

bus.subscribe(function (body) {
_this9.dispatchPresenceCmd({
_this4.dispatchPresenceCmd({
key: body.key,
value: body.value,
expAt: body.expAt,
from: _this9.actor,
room: _this9.roomID
from: _this4.actor,
room: _this4.roomID
});

@@ -1061,4 +1480,3 @@ });

token: this.token,
bus: bus,
key: key
bus: bus
});

@@ -1096,4 +1514,4 @@

if (obj instanceof InnerListClient) {
var _client = obj;
objID = _client.id;
var _client2 = obj;
objID = _client2.id;
this.listCallbacksByObjID[objID] = this.listCallbacksByObjID[objID] || [];

@@ -1127,4 +1545,4 @@ this.listCallbacksByObjID[objID].push(cb);

_proto.unsubscribe = function unsubscribe(listeners) {
for (var _iterator8 = _createForOfIteratorHelperLoose(listeners), _step8; !(_step8 = _iterator8()).done;) {
var l = _step8.value;
for (var _iterator9 = _createForOfIteratorHelperLoose(listeners), _step9; !(_step9 = _iterator9()).done;) {
var l = _step9.value;

@@ -1136,6 +1554,2 @@ if (l.objID) {

}
if (l.event) {
this.ws.unbind(l.event, l.fn);
}
}

@@ -1181,5 +1595,3 @@ };

var ws = new WebSocket(WS_URL);
return Promise.resolve(createRoom({
conn: ws,
docsURL: DOCS_URL,

@@ -1186,0 +1598,0 @@ authStrategy: _this2.auth,

@@ -1,2 +0,2 @@

"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e,t=(e=require("tiny-invariant"))&&"object"==typeof e&&"default"in e?e.default:e,r=require("@roomservice/core");function n(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}function i(e,t,r){return t&&n(e.prototype,t),r&&n(e,r),e}function s(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=new Array(t);r<t;r++)n[r]=e[r];return n}function o(e,t){var r;if("undefined"==typeof Symbol||null==e[Symbol.iterator]){if(Array.isArray(e)||(r=function(e,t){if(e){if("string"==typeof e)return s(e,void 0);var r=Object.prototype.toString.call(e).slice(8,-1);return"Object"===r&&e.constructor&&(r=e.constructor.name),"Map"===r||"Set"===r?Array.from(e):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?s(e,void 0):void 0}}(e))||t&&e&&"number"==typeof e.length){r&&(e=r);var n=0;return function(){return n>=e.length?{done:!0}:{done:!1,value:e[n++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}return(r=e[Symbol.iterator]()).next.bind(r)}var c=function(){function e(e){var t=this;this.callbacks={},this.lastTime=0,this.msgsThisMilisecond=0,this.conn=e,this.conn.onmessage=function(e){var r=JSON.parse(e.data);t.dispatch(r.type,r.body)}}var t=e.prototype;return t.timestamp=function(){var e=Date.now();return e===this.lastTime?this.msgsThisMilisecond++:(this.lastTime=e,this.msgsThisMilisecond=0),e+":"+this.msgsThisMilisecond},t.send=function(e,t){var r=this,n=this.timestamp();this.conn.readyState!==this.conn.CONNECTING?this.conn.send(JSON.stringify({type:e,ts:n,ver:0,body:t})):setTimeout((function(){r.send(e,t)}),100+100*Math.random())},t.bind=function(e,t){return this.callbacks[e]=this.callbacks[e]||[],this.callbacks[e].push(t),t},t.unbind=function(e,t){this.callbacks[e]=this.callbacks[e].filter((function(e){return e!==t}))},t.dispatch=function(e,t){var r=this.callbacks[e];if(r)for(var n=0;n<r.length;n++)r[n](t)},e}(),a=function(){function e(e){this.roomID=e.roomID,this.ws=e.ws,this.bus=e.bus,this.actor=e.actor,this.id=e.listID;var n=r.ListInterpreter.newList(e.docID,e.listID,e.actor),i=n.store;this.meta=n.meta,this.store=i,e.checkpoint.lists[e.listID]||t(!1),r.ListInterpreter.importFromRawCheckpoint(this.store,e.checkpoint,this.meta.listID)}var n=e.prototype;return n.sendCmd=function(e){this.ws.send("doc:cmd",{room:this.roomID,args:e}),this.bus.publish({args:e,from:this.actor})},n.clone=function(){return Object.assign(Object.create(Object.getPrototypeOf(this)),this)},n.dangerouslyUpdateClientDirectly=function(e){return r.ListInterpreter.validateCommand(this.meta,e),r.ListInterpreter.applyCommand(this.store,e),this.clone()},n.get=function(e){return r.ListInterpreter.get(this.store,e)},n.set=function(e,t){var n=r.ListInterpreter.runSet(this.store,this.meta,e,t);return this.sendCmd(n),this.clone()},n.delete=function(e){var t=r.ListInterpreter.runDelete(this.store,this.meta,e);return t?(this.sendCmd(t),this.clone()):this.clone()},n.insertAfter=function(e,t){return this.insertAt(e+1,t)},n.insertAt=function(e,t){var n=r.ListInterpreter.runInsertAt(this.store,this.meta,e,t);return this.sendCmd(n),this.clone()},n.push=function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];for(var i,s=r.ListInterpreter.runPush.apply(r.ListInterpreter,[this.store,this.meta].concat(t)),c=o(s);!(i=c()).done;){var a=i.value;this.sendCmd(a)}return this},n.map=function(e){return r.ListInterpreter.map(this.store,e)},n.toArray=function(){return r.ListInterpreter.toArray(this.store)},e}(),u=function(){function e(e){this.roomID=e.roomID,this.ws=e.ws,this.bus=e.bus,this.actor=e.actor;var t=r.MapInterpreter.newMap(e.docID,e.mapID),n=t.meta;this.store=t.store,this.meta=n,r.MapInterpreter.importFromRawCheckpoint(this.store,e.checkpoint,this.meta.mapID)}var t=e.prototype;return t.sendCmd=function(e){this.ws.send("doc:cmd",{room:this.roomID,args:e}),this.bus.publish({from:this.actor,args:e})},t.clone=function(){return Object.assign(Object.create(Object.getPrototypeOf(this)),this)},t.dangerouslyUpdateClientDirectly=function(e){return r.MapInterpreter.validateCommand(this.meta,e),r.MapInterpreter.applyCommand(this.store,e),this.clone()},t.get=function(e){return this.store[e]},t.set=function(e,t){var n=r.MapInterpreter.runSet(this.store,this.meta,e,t);return this.sendCmd(n),this.clone()},t.toObject=function(){for(var e,t={},r=o(this.keys);!(e=r()).done;){var n=e.value;t[n]=this.get(n)}return t},t.delete=function(e){var t=r.MapInterpreter.runDelete(this.store,this.meta,e);return this.sendCmd(t),this.clone()},i(e,[{key:"id",get:function(){return this.meta.mapID}},{key:"keys",get:function(){return Object.keys(this.store)}}]),e}(),h=function(){function e(e){var t=this;this.roomID=e.roomID,this.ws=e.ws,this.actor=e.actor,this.token=e.token,this.cache={},this.bus=e.bus,this.key=e.key,this.sendPres=function(e,t,r){void 0===r&&(r=!1);var n={},i=!0;return function(){var t=arguments,s=this,o=r&&i,c=function(){e.apply(s,t),n[t[0]]=null};o&&(i=!1,c()),n[arguments[0]]||(n[arguments[0]]=setTimeout(c,40))}}((function(e,r){t.ws.send("presence:cmd",r)}))}var t=e.prototype;return t.getAll=function(){try{var e=this;return Promise.resolve(function(e,t,r,n){try{return Promise.resolve(fetch("https://super.roomservice.dev/presence/"+r+"/"+encodeURIComponent(n),{headers:{Authorization:"Bearer: "+t}})).then((function(e){return Promise.resolve(e.json()).then((function(e){for(var t in e)if("string"==typeof e[t].value){var r=void 0;try{r=JSON.parse(e[t].value)}catch(e){}r&&(e[t].value=r)}return e}))}))}catch(e){return Promise.reject(e)}}(0,e.token,e.roomID,e.key)).then((function(t){return e.cache[e.key]=t,e.withoutExpiredAndSelf(e.key)}))}catch(e){return Promise.reject(e)}},t.withoutExpiredAndSelf=function(e){var t={};for(var r in this.cache[e]){var n=this.cache[e][r];r===this.actor&&delete this.cache[e][r],new Date>n.expAt?delete this.cache[e][r]:t[r]=n.value}return t},t.withoutActorOrExpired=function(e){var t={};for(var r in this.cache)for(var n in this.cache[r]){var i=this.cache[r][n];i&&(n===e&&this.cache[r][n]||new Date>i.expAt?delete this.cache[r][n]:t[n]=i.value)}return t},t.set=function(e,t){var r=t||60,n=Math.round((new Date).getTime()/1e3)+r;return this.bus.publish({key:this.key,value:e,expAt:n}),this.sendPres(this.key,{room:this.roomID,key:this.key,value:JSON.stringify(e),expAt:n}),this.cache[this.key]||(this.cache[this.key]={}),this.cache[this.key][this.actor]={value:e,expAt:new Date(1e3*n)},this.withoutExpiredAndSelf(this.key)},t.dangerouslyUpdateClientDirectly=function(e,t){if("room:rm_guest"===e)return this.withoutActorOrExpired(t.guest);if("presence:expire"===e)return this.withoutExpiredAndSelf(t.key);if(t.room!==this.roomID)return!1;if(t.from===this.actor)return!1;var r={expAt:new Date(1e3*t.expAt),value:JSON.parse(t.value)};return this.cache[t.key]||(this.cache[t.key]={}),this.cache[t.key][t.from]=r,this.withoutExpiredAndSelf(t.key)},i(e,[{key:"me",get:function(){return console.warn("presence.me() is deprecated and will be removed in a future version!"),this.actor}}]),e}(),l=function(){function e(){this.isPublishing=!1,this.subs=new Set}var t=e.prototype;return t.unsubscribe=function(e){this.subs.delete(e)},t.subscribe=function(e){return this.subs.add(e),e},t.publish=function(e){if(this.isPublishing)throw new Error("Infinite loop detected, see more: See more: https://err.sh/getroomservice/browser/infinite-loop");this.isPublishing=!0,this.subs.forEach((function(t){t(e)})),this.isPublishing=!1},e}(),f=["mcreate","mput","mputref","mdel"],m=["lcreate","lins","linsref","lput","lputref","ldel"],d=function(){function e(e){var t=this;this.listClients={},this.mapClients={},this.expires={},this.mapCallbacksByObjID={},this.listCallbacksByObjID={},this.presenceCallbacksByKey={},this.ws=new c(e.conn),this.token=e.token,this.roomID=e.roomID,this.docID=e.checkpoint.id,this.actor=e.actor,this.checkpoint=e.checkpoint,this.InnerPresenceClient=void 0;var n=r.vsReader(window.atob);this.ws.bind("doc:fwd",(function(e){if(e.room===t.roomID)if(!e.args||e.args.length<3)console.error("Unexpected command: ",e.args);else if(!n.isOlderVS(e.vs,t.checkpoint.vs)&&e.from!==t.actor){var r=[e.args[0],e.args[1],e.args[2]],i=r[0],s=r[2];r[1]===t.docID&&(f.includes(i)?t.dispatchMapCmd(s,e):m.includes(i)?t.dispatchListCmd(s,e):console.warn("Unhandled Room Service doc:fwd command: "+i+". Consider updating the Room Service client."))}})),this.ws.bind("presence:fwd",(function(e){t.dispatchPresenceCmd(e)})),this.ws.bind("room:rm_guest",(function(e){if(e.room===t.roomID)for(var r=t.presence("_____any").dangerouslyUpdateClientDirectly("room:rm_guest",e),n=0,i=Object.entries(t.presenceCallbacksByKey);n<i.length;n++)for(var s,c=o(i[n][1]);!(s=c()).done;)(0,s.value)(r,e.guest)}))}var n=e.prototype;return n.dispatchMapCmd=function(e,t){this.mapClients[e]||this.createMapLocally(e);for(var r,n=this.mapClients[e].dangerouslyUpdateClientDirectly(t.args),i=o(this.mapCallbacksByObjID[e]||[]);!(r=i()).done;)(0,r.value)(n.toObject(),t.from)},n.dispatchListCmd=function(e,t){this.listClients[e]||this.createListLocally(e);for(var r,n=this.listClients[e].dangerouslyUpdateClientDirectly(t.args),i=o(this.listCallbacksByObjID[e]||[]);!(r=i()).done;)(0,r.value)(n.toArray(),t.from)},n.dispatchPresenceCmd=function(e){var t=this;if(e.room===this.roomID&&e.from!==this.actor){var r=this.presence(e.key),n=e.key,i=(new Date).getTime()/1e3,s=e.expAt-i;if(!(s<0)){if(s<43200){this.expires[n]&&clearTimeout(this.expires[n]);var c=setTimeout((function(){var i=r.dangerouslyUpdateClientDirectly("presence:expire",{key:e.key});if(i)for(var s,c=o(null!==(a=t.presenceCallbacksByKey[n])&&void 0!==a?a:[]);!(s=c()).done;){var a;(0,s.value)(i,e.from)}}),1e3*s);this.expires[n]=c}var a=r.dangerouslyUpdateClientDirectly("presence:fwd",e);if(a)for(var u,h=o(null!==(l=this.presenceCallbacksByKey[n])&&void 0!==l?l:[]);!(u=h()).done;){var l;(0,u.value)(a,e.from)}}}},n.once=function(e){try{var t,r=this;return Promise.race([new Promise((function(e,t){return setTimeout((function(){return t("timeout")}),2e3)})),new Promise((function(n){t=r.ws.bind(e,(function(e){n(e)}))}))]).then((function(){t&&r.ws.unbind(e,t)}))}catch(e){return Promise.reject(e)}},n.reconnect=function(){try{var e=this;e.errorListener||(e.errorListener=e.ws.bind("error",(function(e){console.error("Room Service encountered a server-side error. If you see this, please let us know; this could be a bug.",e)})));var t=e.once("guest:authenticated");return e.ws.send("guest:authenticate",e.token),Promise.resolve(t).then((function(){var t=e.once("room:joined");return e.ws.send("room:join",e.roomID),Promise.resolve(t).then((function(){}))}))}catch(e){return Promise.reject(e)}},n.createListLocally=function(e){var t=this,r=new l;r.subscribe((function(r){for(var n,i=t.listClients[e],s=o(t.listCallbacksByObjID[e]||[]);!(n=s()).done;)(0,n.value)(i.toArray(),r.from)}));var n=new a({checkpoint:this.checkpoint,roomID:this.roomID,docID:this.docID,listID:e,ws:this.ws,actor:this.actor,bus:r});return this.listClients[e]=n,n},n.list=function(e){return this.listClients[e]?this.listClients[e]:(this.checkpoint.lists[e]||(this.ws.send("doc:cmd",{args:["lcreate",this.docID,e],room:this.roomID}),this.checkpoint.lists[e]={afters:[],ids:[],values:[]}),this.createListLocally(e))},n.createMapLocally=function(e){var t=this,r=new l;r.subscribe((function(r){for(var n,i=t.mapClients[e],s=o(t.mapCallbacksByObjID[e]||[]);!(n=s()).done;)(0,n.value)(i.toObject(),r.from)}));var n=new u({checkpoint:this.checkpoint,roomID:this.roomID,docID:this.docID,mapID:e,ws:this.ws,bus:r,actor:this.actor});return this.mapClients[e]=n,n},n.map=function(e){return this.mapClients[e]?this.mapClients[e]:(this.checkpoint.maps[e]||this.ws.send("doc:cmd",{args:["mcreate",this.docID,e],room:this.roomID}),this.createMapLocally(e))},n.presence=function(e){var t=this;if(this.InnerPresenceClient)return this.InnerPresenceClient;var r=new l;r.subscribe((function(e){t.dispatchPresenceCmd({key:e.key,value:e.value,expAt:e.expAt,from:t.actor,room:t.roomID})}));var n=new h({roomID:this.roomID,ws:this.ws,actor:this.actor,token:this.token,bus:r,key:e});try{this.InnerPresenceClient=n}catch(e){throw new Error("Don't Freeze State. See more: https://err.sh/getroomservice/browser/dont-freeze")}return this.InnerPresenceClient},n.subscribe=function(e,t,r){if("string"==typeof t)return this.subscribePresence(e,t,r);var n,i=function(e,r){t(e,r)};return e instanceof u&&(this.mapCallbacksByObjID[n=e.id]=this.mapCallbacksByObjID[n]||[],this.mapCallbacksByObjID[n].push(i)),e instanceof a&&(this.listCallbacksByObjID[n=e.id]=this.listCallbacksByObjID[n]||[],this.listCallbacksByObjID[n].push(i)),[{objID:n,fn:i}]},n.subscribePresence=function(e,r,n){e||t(!1);var i=function(e,t){n&&n(e,t)};return this.presenceCallbacksByKey[r]=this.presenceCallbacksByKey[r]||[],this.presenceCallbacksByKey[r].push(i),[{objID:r,fn:i}]},n.unsubscribe=function(e){for(var t,r=o(e);!(t=r()).done;){var n=t.value;n.objID&&(this.mapCallbacksByObjID[n.objID]=p(this.mapCallbacksByObjID[n.objID],n.fn),this.listCallbacksByObjID[n.objID]=p(this.listCallbacksByObjID[n.objID],n.fn),this.presenceCallbacksByKey[n.objID]=p(this.presenceCallbacksByKey[n.objID],n.fn)),n.event&&this.ws.unbind(n.event,n.fn)}},i(e,[{key:"me",get:function(){return this.actor}}]),e}();function p(e,t){return e?e.filter((function(e){return e!==t})):[]}var v=function(){function e(e){this.roomClients={},this.auth=e.auth,this.ctx=e.ctx||{}}return e.prototype.room=function(e){try{var t=this;if(t.roomClients[e])return Promise.resolve(t.roomClients[e]);var r=new WebSocket("wss://super.roomservice.dev/ws");return Promise.resolve(function(e){try{return Promise.resolve(function(e,t,r,n){try{var i=function(t){return s?t:Promise.resolve(fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({resources:[{object:"document",reference:n,permission:"read_write",room:r},{object:"room",reference:r,permission:"join"}]})})).then((function(e){if(401===e.status)throw new Error("The Auth Webhook returned unauthorized.");if(200!==e.status)throw new Error("The Auth Webhook returned a status code other than 200.");return Promise.resolve(e.json()).then((function(e){var t=e.resources,r=e.token,n=e.user;if(!t||!r||!n){if("Unauthorized"===e.body)throw new Error("The Auth Webhook unexpectedly return unauthorized. You may be using an invalid API key.");throw new Error("The Auth Webhook has an incorrectly formatted JSON response.")}return{token:r,guestReference:n,docID:t.find((function(e){return"document"===e.object})).id,roomID:t.find((function(e){return"room"===e.object})).id}}))}))},s=!1,o=function(){if("function"==typeof e)return Promise.resolve(e({room:r,ctx:t})).then((function(e){if(!e.user)throw new Error("The auth function must return a 'user' key.");var t=e.resources.find((function(e){return"document"===e.object})).id,r=e.resources.find((function(e){return"room"===e.object})).id;return s=!0,{token:e.token,guestReference:e.user,docID:t,roomID:r}}))}();return Promise.resolve(o&&o.then?o.then(i):i(o))}catch(e){return Promise.reject(e)}}(e.authStrategy,e.authCtx,e.room,e.document)).then((function(t){return Promise.resolve(function(e,t,r){try{return Promise.resolve(fetch(e+"/"+r,{headers:{Authorization:"Bearer: "+t}})).then((function(e){return Promise.resolve(e.json())}))}catch(e){return Promise.reject(e)}}(e.docsURL,t.token,t.docID)).then((function(r){var n=new d({conn:e.conn,actor:t.guestReference,checkpoint:r.body,token:t.token,roomID:t.roomID});return Promise.resolve(n.reconnect()).then((function(){return n}))}))}))}catch(e){return Promise.reject(e)}}({conn:r,docsURL:"https://super.roomservice.dev/docs",authStrategy:t.auth,authCtx:t.ctx,room:e,document:"default"})).then((function(r){return t.roomClients[e]=r,r}))}catch(e){return Promise.reject(e)}},e}();exports.RoomClient=d,exports.RoomService=v,exports.default=v;
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e,t=(e=require("tiny-invariant"))&&"object"==typeof e&&"default"in e?e.default:e,r=require("@roomservice/core"),n="https://super.roomservice.dev/docs";function i(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}function o(e,t,r){return t&&i(e.prototype,t),r&&i(e,r),e}function s(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=new Array(t);r<t;r++)n[r]=e[r];return n}function c(e,t){var r;if("undefined"==typeof Symbol||null==e[Symbol.iterator]){if(Array.isArray(e)||(r=function(e,t){if(e){if("string"==typeof e)return s(e,void 0);var r=Object.prototype.toString.call(e).slice(8,-1);return"Object"===r&&e.constructor&&(r=e.constructor.name),"Map"===r||"Set"===r?Array.from(e):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?s(e,void 0):void 0}}(e))||t&&e&&"number"==typeof e.length){r&&(e=r);var n=0;return function(){return n>=e.length?{done:!0}:{done:!1,value:e[n++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}return(r=e[Symbol.iterator]()).next.bind(r)}const u=function(){function e(){}return e.prototype.then=function(t,r){const n=new e,i=this.s;if(i){const e=1&i?t:r;if(e){try{a(n,1,e(this.v))}catch(e){a(n,2,e)}return n}return this}return this.o=function(e){try{const i=e.v;1&e.s?a(n,1,t?t(i):i):r?a(n,1,r(i)):a(n,2,i)}catch(e){a(n,2,e)}},n},e}();function a(e,t,r){if(!e.s){if(r instanceof u){if(!r.s)return void(r.o=a.bind(null,e,t));1&t&&(t=r.s),r=r.v}if(r&&r.then)return void r.then(a.bind(null,e,t),a.bind(null,e,2));e.s=t,e.v=r;const n=e.o;n&&n(e)}}function h(e){return e instanceof u&&1&e.s}function l(e,t,r){for(var n;;){var i=e();if(h(i)&&(i=i.v),!i)return o;if(i.then){n=0;break}var o=r();if(o&&o.then){if(!h(o)){n=1;break}o=o.s}if(t){var s=t();if(s&&s.then&&!h(s)){n=2;break}}}var c=new u,l=a.bind(null,c,2);return(0===n?i.then(m):1===n?o.then(d):s.then(f)).then(void 0,l),c;function d(n){o=n;do{if(t&&(s=t())&&s.then&&!h(s))return void s.then(f).then(void 0,l);if(!(i=e())||h(i)&&!i.v)return void a(c,1,o);if(i.then)return void i.then(m).then(void 0,l);h(o=r())&&(o=o.v)}while(!o||!o.then);o.then(d).then(void 0,l)}function m(e){e?(o=r())&&o.then?o.then(d).then(void 0,l):d(o):a(c,1,o)}function f(){(i=e())?i.then?i.then(m).then(void 0,l):m(i):a(c,1,o)}}function d(e){return new Promise((function(t){return setTimeout(t,e)}))}"undefined"!=typeof Symbol&&(Symbol.iterator||(Symbol.iterator=Symbol("Symbol.iterator"))),"undefined"!=typeof Symbol&&(Symbol.asyncIterator||(Symbol.asyncIterator=Symbol("Symbol.asyncIterator")));var m=function(e,t,r){try{return Promise.resolve(fetch(e+"/"+r,{headers:{Authorization:"Bearer: "+t}})).then((function(e){return Promise.resolve(e.json())}))}catch(e){return Promise.reject(e)}},f=function(e){try{return Promise.resolve(new Promise((function(t,r){var n=new WebSocket(e);n.onopen=function(){t(n)},n.onerror=function(e){r(e)}})))}catch(e){return Promise.reject(e)}},p=["doc:fwd","presence:fwd","room:rm_guest"],v=function(){function e(e){this.callbacks={},this.lastTime=0,this.msgsThisMilisecond=0,this.docCmdSendQueue=[],this.presenceCmdSendQueue=new Map,this.dispatcher=e.dispatcher,this.wsURL=e.wsURL,this.docsURL=e.docsURL,this.room=e.room,this.session=e.session,this.wsFactory=e.wsFactory||f,this.documentFetch=e.documentFetch||m,this.wsLoop()}var t=e.prototype;return t.close=function(){this.currentConn&&(this.currentConn.onmessage=null,this.currentConn.onclose=null,this.currentConn.close(),this.currentConn=void 0),this.pendingConn&&(this.pendingConn=void 0),this.dispatcher.startQueueingCmds()},t.connectAndAuth=function(){try{var e=this;return Promise.resolve(e.wsFactory(e.wsURL)).then((function(t){return t.onmessage=function(t){var r=JSON.parse(t.data);e.dispatch(r.type,r.body)},t.onclose=function(){return e.close()},Promise.resolve(t).then((function(t){try{return t.send(e.serializeMsg("guest:authenticate",e.session.token)),Promise.resolve(e.once("guest:authenticated")).then((function(){return t.send(e.serializeMsg("room:join",e.room)),Promise.resolve(e.once("room:joined")).then((function(){return Promise.resolve(e.documentFetch(e.docsURL,e.session.token,e.session.docID)).then((function(r){return e.dispatcher.bootstrap(r.body),t}))}))}))}catch(e){return Promise.reject(e)}}))}))}catch(e){return Promise.reject(e)}},t.conn=function(){try{var e=this;return e.currentConn?Promise.resolve(e.currentConn):(e.pendingConn||(e.close(),e.pendingConn=function(){try{var t=!1,r=0;return Promise.resolve(l((function(){return!t}),void 0,(function(){var n=r*(Math.random()+1)/2;return Promise.resolve(d(n)).then((function(){return r=Math.min(2*r+100,6e4),function(r,n){try{var i=Promise.resolve(e.connectAndAuth()).then((function(r){return e.currentConn=r,e.pendingConn=void 0,t=!0,r}))}catch(e){return n(e)}return i&&i.then?i.then(void 0,n):i}(0,(function(e){console.error("Connection to RoomService failed with",e,"\nRetrying...")}))}))})))}catch(e){return Promise.reject(e)}}()),Promise.resolve(e.pendingConn))}catch(e){return Promise.reject(e)}},t.wsLoop=function(){try{var e=this,t=l((function(){return!0}),void 0,(function(){return Promise.resolve(e.conn()).then((function(){return e.processSendQueue(),Promise.resolve(d(1e3)).then((function(){}))}))}));return Promise.resolve(t&&t.then?t.then((function(){})):void 0)}catch(e){return Promise.reject(e)}},t.timestamp=function(){var e=Date.now();return e===this.lastTime?this.msgsThisMilisecond++:(this.lastTime=e,this.msgsThisMilisecond=0),e+":"+this.msgsThisMilisecond},t.serializeMsg=function(e,t){var r=this.timestamp();return JSON.stringify({type:e,ts:r,ver:0,body:t})},t.send=function(e,t){if("doc:cmd"==e){if(this.docCmdSendQueue.length>=1e4)throw"RoomService send queue full";var r=this.serializeMsg(e,t);this.docCmdSendQueue.push(r)}if("presence:cmd"==e){var n=this.serializeMsg(e,t);this.presenceCmdSendQueue.set(t.key,n)}this.processSendQueue()},t.processSendQueue=function(){if(this.currentConn)try{for(;this.presenceCmdSendQueue.size>0;){var e=this.presenceCmdSendQueue.entries().next();if(e){var t=e.value,r=t[0];this.currentConn.send(t[1]),this.presenceCmdSendQueue.delete(r)}}for(;this.docCmdSendQueue.length>0;)this.currentConn.send(this.docCmdSendQueue[0]),this.docCmdSendQueue.splice(0,1)}catch(e){console.error(e)}},t.bind=function(e,t){return this.callbacks[e]=this.callbacks[e]||[],this.callbacks[e].push(t),t},t.unbind=function(e,t){this.callbacks[e]=this.callbacks[e].filter((function(e){return e!==t}))},t.dispatch=function(e,t){"error"==e&&console.error(t);var r=this.callbacks[e];if(r)for(var n=0;n<r.length;n++)r[n](t);p.includes(e)&&this.dispatcher.forwardCmd(e,t)},t.once=function(e){try{var t,r=this;return Promise.race([new Promise((function(e,t){return setTimeout((function(){return t("timeout")}),2e3)})),new Promise((function(n){t=r.bind(e,(function(e){n(e)}))}))]).then((function(){t&&r.unbind(e,t)}))}catch(e){return Promise.reject(e)}},e}(),b=function(){function e(e){this.roomID=e.roomID,this.ws=e.ws,this.bus=e.bus,this.actor=e.actor,this.id=e.listID;var n=r.ListInterpreter.newList(e.docID,e.listID,e.actor),i=n.store;this.meta=n.meta,this.store=i,e.checkpoint.lists[e.listID]||t(!1),r.ListInterpreter.importFromRawCheckpoint(this.store,e.checkpoint,this.meta.listID)}var n=e.prototype;return n.bootstrap=function(e){r.ListInterpreter.importFromRawCheckpoint(this.store,e,this.meta.listID)},n.sendCmd=function(e){this.ws.send("doc:cmd",{room:this.roomID,args:e}),this.bus.publish({args:e,from:this.actor})},n.clone=function(){return Object.assign(Object.create(Object.getPrototypeOf(this)),this)},n.dangerouslyUpdateClientDirectly=function(e){return r.ListInterpreter.validateCommand(this.meta,e),r.ListInterpreter.applyCommand(this.store,e),this.clone()},n.get=function(e){return r.ListInterpreter.get(this.store,e)},n.set=function(e,t){var n=r.ListInterpreter.runSet(this.store,this.meta,e,t);return this.sendCmd(n),this.clone()},n.delete=function(e){var t=r.ListInterpreter.runDelete(this.store,this.meta,e);return t?(this.sendCmd(t),this.clone()):this.clone()},n.insertAfter=function(e,t){return this.insertAt(e+1,t)},n.insertAt=function(e,t){var n=r.ListInterpreter.runInsertAt(this.store,this.meta,e,t);return this.sendCmd(n),this.clone()},n.push=function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];for(var i,o=r.ListInterpreter.runPush.apply(r.ListInterpreter,[this.store,this.meta].concat(t)),s=c(o);!(i=s()).done;){var u=i.value;this.sendCmd(u)}return this},n.map=function(e){return r.ListInterpreter.map(this.store,e)},n.toArray=function(){return r.ListInterpreter.toArray(this.store)},e}(),y=function(){function e(e){this.roomID=e.roomID,this.ws=e.ws,this.bus=e.bus,this.actor=e.actor;var t=r.MapInterpreter.newMap(e.docID,e.mapID),n=t.meta;this.store=t.store,this.meta=n,r.MapInterpreter.importFromRawCheckpoint(this.store,e.checkpoint,this.meta.mapID)}var t=e.prototype;return t.bootstrap=function(e){r.MapInterpreter.importFromRawCheckpoint(this.store,e,this.meta.mapID)},t.sendCmd=function(e){this.ws.send("doc:cmd",{room:this.roomID,args:e}),this.bus.publish({from:this.actor,args:e})},t.clone=function(){return Object.assign(Object.create(Object.getPrototypeOf(this)),this)},t.dangerouslyUpdateClientDirectly=function(e){return r.MapInterpreter.validateCommand(this.meta,e),r.MapInterpreter.applyCommand(this.store,e),this.clone()},t.get=function(e){return this.store[e]},t.set=function(e,t){var n=r.MapInterpreter.runSet(this.store,this.meta,e,t);return this.sendCmd(n),this.clone()},t.toObject=function(){for(var e,t={},r=c(this.keys);!(e=r()).done;){var n=e.value;t[n]=this.get(n)}return t},t.delete=function(e){var t=r.MapInterpreter.runDelete(this.store,this.meta,e);return this.sendCmd(t),this.clone()},o(e,[{key:"id",get:function(){return this.meta.mapID}},{key:"keys",get:function(){return Object.keys(this.store)}}]),e}(),C=function(){function e(e){var t=this;this.roomID=e.roomID,this.ws=e.ws,this.actor=e.actor,this.token=e.token,this.cache={},this.bus=e.bus,this.sendPres=function(e,t,r){void 0===r&&(r=!1);var n={},i=!0;return function(){var t=arguments,o=this,s=r&&i,c=function(){e.apply(o,t),n[t[0]]=null};s&&(i=!1,c()),n[arguments[0]]||(n[arguments[0]]=setTimeout(c,40))}}((function(e,r){t.ws.send("presence:cmd",r)}))}var t=e.prototype;return t.getAll=function(e){try{var t=this;return Promise.resolve(function(e,t,r,n){try{return Promise.resolve(fetch("https://super.roomservice.dev/presence/"+r+"/"+encodeURIComponent(n),{headers:{Authorization:"Bearer: "+t}})).then((function(e){return Promise.resolve(e.json()).then((function(e){for(var t in e)if("string"==typeof e[t].value){var r=void 0;try{r=JSON.parse(e[t].value)}catch(e){}r&&(e[t].value=r)}return e}))}))}catch(e){return Promise.reject(e)}}(0,t.token,t.roomID,e)).then((function(r){return t.cache[e]=r,t.withoutExpiredAndSelf(e)}))}catch(e){return Promise.reject(e)}},t.withoutExpiredAndSelf=function(e){var t={};for(var r in this.cache[e]){var n=this.cache[e][r];r===this.actor&&delete this.cache[e][r],new Date>n.expAt?delete this.cache[e][r]:t[r]=n.value}return t},t.withoutActorOrExpired=function(e){var t={};for(var r in this.cache)for(var n in this.cache[r]){var i=this.cache[r][n];i&&(n===e&&this.cache[r][n]||new Date>i.expAt?delete this.cache[r][n]:t[n]=i.value)}return t},t.set=function(e,t,r){var n=r||60,i=Math.round((new Date).getTime()/1e3)+n;return this.bus.publish({key:e,value:t,expAt:i}),this.sendPres(e,{room:this.roomID,key:e,value:JSON.stringify(t),expAt:i}),this.cache[e]||(this.cache[e]={}),this.cache[e][this.actor]={value:t,expAt:new Date(1e3*i)},this.withoutExpiredAndSelf(e)},t.dangerouslyUpdateClientDirectly=function(e,t){if("room:rm_guest"===e)return this.withoutActorOrExpired(t.guest);if("presence:expire"===e)return this.withoutExpiredAndSelf(t.key);if(t.room!==this.roomID)return!1;if(t.from===this.actor)return!1;var r={expAt:new Date(1e3*t.expAt),value:JSON.parse(t.value)};return this.cache[t.key]||(this.cache[t.key]={}),this.cache[t.key][t.from]=r,this.withoutExpiredAndSelf(t.key)},o(e,[{key:"me",get:function(){return console.warn("presence.me() is deprecated and will be removed in a future version!"),this.actor}}]),e}(),I=function(){function e(){this.isPublishing=!1,this.subs=new Set}var t=e.prototype;return t.unsubscribe=function(e){this.subs.delete(e)},t.subscribe=function(e){return this.subs.add(e),e},t.publish=function(e){if(this.isPublishing)throw new Error("Infinite loop detected, see more: See more: https://err.sh/getroomservice/browser/infinite-loop");this.isPublishing=!0,this.subs.forEach((function(t){t(e)})),this.isPublishing=!1},e}(),g=["mcreate","mput","mputref","mdel"],w=["lcreate","lins","linsref","lput","lputref","ldel"],D=function(){function e(e){this.listClients={},this.mapClients={},this.expires={},this.queueIncomingCmds=!0,this.cmdQueue=[],this.mapCallbacksByObjID={},this.listCallbacksByObjID={},this.presenceCallbacksByKey={},this.ws=new v({dispatcher:this,wsURL:e.wsURL,docsURL:e.docsURL,room:e.roomID,session:e.session}),this.token=e.token,this.roomID=e.roomID,this.docID=e.checkpoint.id,this.actor=e.actor,this.checkpoint=e.checkpoint}var n=e.prototype;return n.forwardCmd=function(e,t){this.queueIncomingCmds?this.cmdQueue.push([e,t]):this.processCmd(e,t)},n.processCmd=function(e,t){"doc:fwd"==e&&"args"in t&&this.dispatchDocCmd(t),"presence:fwd"==e&&"expAt"in t&&this.dispatchPresenceCmd(t),"room:rm_guest"==e&&"guest"in t&&this.dispatchRmGuest(t)},n.bootstrap=function(e){this.checkpoint=e;for(var t=0,r=Object.entries(this.listClients);t<r.length;t++)r[t][1].bootstrap(e);for(var n=0,i=Object.entries(this.mapClients);n<i.length;n++)i[n][1].bootstrap(e);this.queueIncomingCmds=!1;for(var o,s=c(this.cmdQueue);!(o=s()).done;){var u=o.value;this.processCmd(u[0],u[1])}this.cmdQueue.length=0},n.startQueueingCmds=function(){this.queueIncomingCmds=!0},n.dispatchDocCmd=function(e){if(e.room===this.roomID)if(!e.args||e.args.length<3)console.error("Unexpected command: ",e.args);else if(!r.vsReader(atob).isOlderVS(e.vs,this.checkpoint.vs)&&e.from!==this.actor){var t=[e.args[0],e.args[1],e.args[2]],n=t[0],i=t[2];t[1]===this.docID&&(g.includes(n)?this.dispatchMapCmd(i,e):w.includes(n)?this.dispatchListCmd(i,e):console.warn("Unhandled Room Service doc:fwd command: "+n+". Consider updating the Room Service client."))}},n.dispatchRmGuest=function(e){if(e.room===this.roomID)for(var t=this.presence().dangerouslyUpdateClientDirectly("room:rm_guest",e),r=0,n=Object.entries(this.presenceCallbacksByKey);r<n.length;r++)for(var i,o=c(n[r][1]);!(i=o()).done;)(0,i.value)(t,e.guest)},n.dispatchMapCmd=function(e,t){this.mapClients[e]||this.createMapLocally(e);for(var r,n=this.mapClients[e].dangerouslyUpdateClientDirectly(t.args),i=c(this.mapCallbacksByObjID[e]||[]);!(r=i()).done;)(0,r.value)(n.toObject(),t.from)},n.dispatchListCmd=function(e,t){this.listClients[e]||this.createListLocally(e);for(var r,n=this.listClients[e].dangerouslyUpdateClientDirectly(t.args),i=c(this.listCallbacksByObjID[e]||[]);!(r=i()).done;)(0,r.value)(n.toArray(),t.from)},n.dispatchPresenceCmd=function(e){var t=this;if(e.room===this.roomID&&e.from!==this.actor){var r=this.presence(),n=e.key,i=(new Date).getTime()/1e3,o=e.expAt-i;if(!(o<0)){if(o<43200){this.expires[n]&&clearTimeout(this.expires[n]);var s=setTimeout((function(){var i=r.dangerouslyUpdateClientDirectly("presence:expire",{key:e.key});if(i)for(var o,s=c(null!==(u=t.presenceCallbacksByKey[n])&&void 0!==u?u:[]);!(o=s()).done;){var u;(0,o.value)(i,e.from)}}),1e3*o);this.expires[n]=s}var u=r.dangerouslyUpdateClientDirectly("presence:fwd",e);if(u)for(var a,h=c(null!==(l=this.presenceCallbacksByKey[n])&&void 0!==l?l:[]);!(a=h()).done;){var l;(0,a.value)(u,e.from)}}}},n.createListLocally=function(e){var t=this,r=new I;r.subscribe((function(r){for(var n,i=t.listClients[e],o=c(t.listCallbacksByObjID[e]||[]);!(n=o()).done;)(0,n.value)(i.toArray(),r.from)}));var n=new b({checkpoint:this.checkpoint,roomID:this.roomID,docID:this.docID,listID:e,ws:this.ws,actor:this.actor,bus:r});return this.listClients[e]=n,n},n.list=function(e){return this.listClients[e]?this.listClients[e]:(this.checkpoint.lists[e]||(this.ws.send("doc:cmd",{args:["lcreate",this.docID,e],room:this.roomID}),this.checkpoint.lists[e]={afters:[],ids:[],values:[]}),this.createListLocally(e))},n.createMapLocally=function(e){var t=this,r=new I;r.subscribe((function(r){for(var n,i=t.mapClients[e],o=c(t.mapCallbacksByObjID[e]||[]);!(n=o()).done;)(0,n.value)(i.toObject(),r.from)}));var n=new y({checkpoint:this.checkpoint,roomID:this.roomID,docID:this.docID,mapID:e,ws:this.ws,bus:r,actor:this.actor});return this.mapClients[e]=n,n},n.map=function(e){return this.mapClients[e]?this.mapClients[e]:(this.checkpoint.maps[e]||this.ws.send("doc:cmd",{args:["mcreate",this.docID,e],room:this.roomID}),this.createMapLocally(e))},n.presence=function(){var e=this;if(this.InnerPresenceClient)return this.InnerPresenceClient;var t=new I;t.subscribe((function(t){e.dispatchPresenceCmd({key:t.key,value:t.value,expAt:t.expAt,from:e.actor,room:e.roomID})}));var r=new C({roomID:this.roomID,ws:this.ws,actor:this.actor,token:this.token,bus:t});try{this.InnerPresenceClient=r}catch(e){throw new Error("Don't Freeze State. See more: https://err.sh/getroomservice/browser/dont-freeze")}return this.InnerPresenceClient},n.subscribe=function(e,t,r){if("string"==typeof t)return this.subscribePresence(e,t,r);var n,i=function(e,r){t(e,r)};return e instanceof y&&(this.mapCallbacksByObjID[n=e.id]=this.mapCallbacksByObjID[n]||[],this.mapCallbacksByObjID[n].push(i)),e instanceof b&&(this.listCallbacksByObjID[n=e.id]=this.listCallbacksByObjID[n]||[],this.listCallbacksByObjID[n].push(i)),[{objID:n,fn:i}]},n.subscribePresence=function(e,r,n){e||t(!1);var i=function(e,t){n&&n(e,t)};return this.presenceCallbacksByKey[r]=this.presenceCallbacksByKey[r]||[],this.presenceCallbacksByKey[r].push(i),[{objID:r,fn:i}]},n.unsubscribe=function(e){for(var t,r=c(e);!(t=r()).done;){var n=t.value;n.objID&&(this.mapCallbacksByObjID[n.objID]=k(this.mapCallbacksByObjID[n.objID],n.fn),this.listCallbacksByObjID[n.objID]=k(this.listCallbacksByObjID[n.objID],n.fn),this.presenceCallbacksByKey[n.objID]=k(this.presenceCallbacksByKey[n.objID],n.fn))}},o(e,[{key:"me",get:function(){return this.actor}}]),e}();function k(e,t){return e?e.filter((function(e){return e!==t})):[]}var j=function(){function e(e){this.roomClients={},this.auth=e.auth,this.ctx=e.ctx||{}}return e.prototype.room=function(e){try{var t=this;return t.roomClients[e]?Promise.resolve(t.roomClients[e]):Promise.resolve(function(e){try{return Promise.resolve(function(e,t,r,n){try{var i=function(t){return o?t:Promise.resolve(fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({resources:[{object:"document",reference:n,permission:"read_write",room:r},{object:"room",reference:r,permission:"join"}]})})).then((function(e){if(401===e.status)throw new Error("The Auth Webhook returned unauthorized.");if(200!==e.status)throw new Error("The Auth Webhook returned a status code other than 200.");return Promise.resolve(e.json()).then((function(e){var t=e.resources,r=e.token,n=e.user;if(!t||!r||!n){if("Unauthorized"===e.body)throw new Error("The Auth Webhook unexpectedly return unauthorized. You may be using an invalid API key.");throw new Error("The Auth Webhook has an incorrectly formatted JSON response.")}return{token:r,guestReference:n,docID:t.find((function(e){return"document"===e.object})).id,roomID:t.find((function(e){return"room"===e.object})).id}}))}))},o=!1,s=function(){if("function"==typeof e)return Promise.resolve(e({room:r,ctx:t})).then((function(e){if(!e.user)throw new Error("The auth function must return a 'user' key.");var t=e.resources.find((function(e){return"document"===e.object})).id,r=e.resources.find((function(e){return"room"===e.object})).id;return o=!0,{token:e.token,guestReference:e.user,docID:t,roomID:r}}))}();return Promise.resolve(s&&s.then?s.then(i):i(s))}catch(e){return Promise.reject(e)}}(e.authStrategy,e.authCtx,e.room,e.document)).then((function(t){return Promise.resolve(m(e.docsURL,t.token,t.docID)).then((function(r){return new D({actor:t.guestReference,checkpoint:r.body,token:t.token,roomID:t.roomID,docID:e.document,auth:e.authStrategy,authCtx:e.authCtx,wsURL:"wss://super.roomservice.dev/ws",docsURL:n,session:t})}))}))}catch(e){return Promise.reject(e)}}({docsURL:n,authStrategy:t.auth,authCtx:t.ctx,room:e,document:"default"})).then((function(r){return t.roomClients[e]=r,r}))}catch(e){return Promise.reject(e)}},e}();exports.RoomClient=D,exports.RoomService=j,exports.default=j;
//# sourceMappingURL=browser.cjs.production.min.js.map

@@ -69,79 +69,181 @@ import invariant from 'tiny-invariant';

var SuperlumeWebSocket = /*#__PURE__*/function () {
function SuperlumeWebSocket(conn) {
var _this = this;
// A type of promise-like that resolves synchronously and supports only one observer
const _Pact = /*#__PURE__*/(function() {
function _Pact() {}
_Pact.prototype.then = function(onFulfilled, onRejected) {
const result = new _Pact();
const state = this.s;
if (state) {
const callback = state & 1 ? onFulfilled : onRejected;
if (callback) {
try {
_settle(result, 1, callback(this.v));
} catch (e) {
_settle(result, 2, e);
}
return result;
} else {
return this;
}
}
this.o = function(_this) {
try {
const value = _this.v;
if (_this.s & 1) {
_settle(result, 1, onFulfilled ? onFulfilled(value) : value);
} else if (onRejected) {
_settle(result, 1, onRejected(value));
} else {
_settle(result, 2, value);
}
} catch (e) {
_settle(result, 2, e);
}
};
return result;
};
return _Pact;
})();
this.callbacks = {};
this.lastTime = 0;
this.msgsThisMilisecond = 0;
this.conn = conn;
// Settles a pact synchronously
function _settle(pact, state, value) {
if (!pact.s) {
if (value instanceof _Pact) {
if (value.s) {
if (state & 1) {
state = value.s;
}
value = value.v;
} else {
value.o = _settle.bind(null, pact, state);
return;
}
}
if (value && value.then) {
value.then(_settle.bind(null, pact, state), _settle.bind(null, pact, 2));
return;
}
pact.s = state;
pact.v = value;
const observer = pact.o;
if (observer) {
observer(pact);
}
}
}
this.conn.onmessage = function (ev) {
var msg = JSON.parse(ev.data);
function _isSettledPact(thenable) {
return thenable instanceof _Pact && thenable.s & 1;
}
_this.dispatch(msg.type, msg.body);
};
}
const _iteratorSymbol = /*#__PURE__*/ typeof Symbol !== "undefined" ? (Symbol.iterator || (Symbol.iterator = Symbol("Symbol.iterator"))) : "@@iterator";
var _proto = SuperlumeWebSocket.prototype;
const _asyncIteratorSymbol = /*#__PURE__*/ typeof Symbol !== "undefined" ? (Symbol.asyncIterator || (Symbol.asyncIterator = Symbol("Symbol.asyncIterator"))) : "@@asyncIterator";
_proto.timestamp = function timestamp() {
var time = Date.now();
// Asynchronously implement a generic for loop
function _for(test, update, body) {
var stage;
for (;;) {
var shouldContinue = test();
if (_isSettledPact(shouldContinue)) {
shouldContinue = shouldContinue.v;
}
if (!shouldContinue) {
return result;
}
if (shouldContinue.then) {
stage = 0;
break;
}
var result = body();
if (result && result.then) {
if (_isSettledPact(result)) {
result = result.s;
} else {
stage = 1;
break;
}
}
if (update) {
var updateValue = update();
if (updateValue && updateValue.then && !_isSettledPact(updateValue)) {
stage = 2;
break;
}
}
}
var pact = new _Pact();
var reject = _settle.bind(null, pact, 2);
(stage === 0 ? shouldContinue.then(_resumeAfterTest) : stage === 1 ? result.then(_resumeAfterBody) : updateValue.then(_resumeAfterUpdate)).then(void 0, reject);
return pact;
function _resumeAfterBody(value) {
result = value;
do {
if (update) {
updateValue = update();
if (updateValue && updateValue.then && !_isSettledPact(updateValue)) {
updateValue.then(_resumeAfterUpdate).then(void 0, reject);
return;
}
}
shouldContinue = test();
if (!shouldContinue || (_isSettledPact(shouldContinue) && !shouldContinue.v)) {
_settle(pact, 1, result);
return;
}
if (shouldContinue.then) {
shouldContinue.then(_resumeAfterTest).then(void 0, reject);
return;
}
result = body();
if (_isSettledPact(result)) {
result = result.v;
}
} while (!result || !result.then);
result.then(_resumeAfterBody).then(void 0, reject);
}
function _resumeAfterTest(shouldContinue) {
if (shouldContinue) {
result = body();
if (result && result.then) {
result.then(_resumeAfterBody).then(void 0, reject);
} else {
_resumeAfterBody(result);
}
} else {
_settle(pact, 1, result);
}
}
function _resumeAfterUpdate() {
if (shouldContinue = test()) {
if (shouldContinue.then) {
shouldContinue.then(_resumeAfterTest).then(void 0, reject);
} else {
_resumeAfterTest(shouldContinue);
}
} else {
_settle(pact, 1, result);
}
}
}
if (time === this.lastTime) {
this.msgsThisMilisecond++;
} else {
this.lastTime = time;
this.msgsThisMilisecond = 0;
}
// Asynchronously call a function and send errors to recovery continuation
function _catch(body, recover) {
try {
var result = body();
} catch(e) {
return recover(e);
}
if (result && result.then) {
return result.then(void 0, recover);
}
return result;
}
return time + ":" + this.msgsThisMilisecond;
};
function delay(ms) {
return new Promise(function (resolve) {
return setTimeout(resolve, ms);
});
}
_proto.send = function send(msgType, body) {
var _this2 = this;
var ts = this.timestamp();
var msg = {
type: msgType,
ts: ts,
ver: 0,
body: body
}; // If the client is connecting, buffer a bit and retry
if (this.conn.readyState === this.conn.CONNECTING) {
setTimeout(function () {
// @ts-ignore
_this2.send(msgType, body);
}, 100 + Math.random() * 100);
return;
}
this.conn.send(JSON.stringify(msg));
};
_proto.bind = function bind(msgType, callback) {
this.callbacks[msgType] = this.callbacks[msgType] || [];
this.callbacks[msgType].push(callback);
return callback;
};
_proto.unbind = function unbind(msgType, callback) {
this.callbacks[msgType] = this.callbacks[msgType].filter(function (c) {
return c !== callback;
});
};
_proto.dispatch = function dispatch(msgType, body) {
var stack = this.callbacks[msgType];
if (!stack) return;
for (var i = 0; i < stack.length; i++) {
stack[i](body);
}
};
return SuperlumeWebSocket;
}();
var fetchSession = function fetchSession(strategy, ctx, room, document) {

@@ -287,2 +389,294 @@ try {

var openWS = function openWS(url) {
try {
return Promise.resolve(new Promise(function (resolve, reject) {
var ws = new WebSocket(url);
ws.onopen = function () {
resolve(ws);
};
ws.onerror = function (err) {
reject(err);
};
}));
} catch (e) {
return Promise.reject(e);
}
};
var WEBSOCKET_TIMEOUT = 1000 * 2;
var MAX_UNSENT_DOC_CMDS = 10000;
var FORWARDED_TYPES = ['doc:fwd', 'presence:fwd', 'room:rm_guest'];
var ReconnectingWebSocket = /*#__PURE__*/function () {
function ReconnectingWebSocket(params) {
this.callbacks = {};
this.lastTime = 0;
this.msgsThisMilisecond = 0;
this.docCmdSendQueue = []; // only most recent presence cmd per-key is kept
this.presenceCmdSendQueue = new Map();
this.dispatcher = params.dispatcher;
this.wsURL = params.wsURL;
this.docsURL = params.docsURL;
this.room = params.room;
this.session = params.session;
this.wsFactory = params.wsFactory || openWS;
this.documentFetch = params.documentFetch || fetchDocument;
this.wsLoop();
}
var _proto = ReconnectingWebSocket.prototype;
_proto.close = function close() {
if (this.currentConn) {
this.currentConn.onmessage = null;
this.currentConn.onclose = null;
this.currentConn.close();
this.currentConn = undefined;
}
if (this.pendingConn) {
this.pendingConn = undefined;
}
this.dispatcher.startQueueingCmds();
} // one-off attempt to connect and authenticate
;
_proto.connectAndAuth = function connectAndAuth() {
try {
var _this2 = this;
return Promise.resolve(_this2.wsFactory(_this2.wsURL)).then(function (ws) {
ws.onmessage = function (ev) {
var msg = JSON.parse(ev.data);
_this2.dispatch(msg.type, msg.body);
};
ws.onclose = function () {
return _this2.close();
};
return Promise.resolve(ws).then(function (ws) {
try {
ws.send(_this2.serializeMsg('guest:authenticate', _this2.session.token));
return Promise.resolve(_this2.once('guest:authenticated')).then(function () {
ws.send(_this2.serializeMsg('room:join', _this2.room));
return Promise.resolve(_this2.once('room:joined')).then(function () {
return Promise.resolve(_this2.documentFetch(_this2.docsURL, _this2.session.token, _this2.session.docID)).then(function (_ref) {
var body = _ref.body;
_this2.dispatcher.bootstrap(body);
return ws;
});
});
});
} catch (e) {
return Promise.reject(e);
}
});
});
} catch (e) {
return Promise.reject(e);
}
} // main logic to obtain an active and auth'd connection
;
_proto.conn = function conn() {
try {
var _this4 = this;
if (_this4.currentConn) {
return Promise.resolve(_this4.currentConn);
}
if (_this4.pendingConn) {
return Promise.resolve(_this4.pendingConn);
}
_this4.close();
_this4.pendingConn = function () {
try {
var _exit2 = false;
var delayMs = 0;
var maxDelayMs = 60 * 1000;
return Promise.resolve(_for(function () {
return !_exit2;
}, void 0, function () {
var jitteredDelay = delayMs * (Math.random() + 1) / 2;
return Promise.resolve(delay(jitteredDelay)).then(function () {
delayMs = Math.min(2 * delayMs + 100, maxDelayMs);
return _catch(function () {
return Promise.resolve(_this4.connectAndAuth()).then(function (ws) {
_this4.currentConn = ws;
_this4.pendingConn = undefined;
_exit2 = true;
return ws;
});
}, function (err) {
console.error('Connection to RoomService failed with', err, '\nRetrying...');
});
});
}));
} catch (e) {
return Promise.reject(e);
}
}();
return Promise.resolve(_this4.pendingConn);
} catch (e) {
return Promise.reject(e);
}
};
_proto.wsLoop = function wsLoop() {
try {
var _this6 = this;
var _temp2 = _for(function () {
return true;
}, void 0, function () {
return Promise.resolve(_this6.conn()).then(function () {
_this6.processSendQueue();
return Promise.resolve(delay(1000)).then(function () {});
});
});
return Promise.resolve(_temp2 && _temp2.then ? _temp2.then(function () {}) : void 0);
} catch (e) {
return Promise.reject(e);
}
};
_proto.timestamp = function timestamp() {
var time = Date.now();
if (time === this.lastTime) {
this.msgsThisMilisecond++;
} else {
this.lastTime = time;
this.msgsThisMilisecond = 0;
}
return time + ":" + this.msgsThisMilisecond;
};
_proto.serializeMsg = function serializeMsg(msgType, body) {
var ts = this.timestamp();
var msg = {
type: msgType,
ts: ts,
ver: 0,
body: body
};
return JSON.stringify(msg);
};
_proto.send = function send(msgType, body) {
if (msgType == 'doc:cmd') {
if (this.docCmdSendQueue.length >= MAX_UNSENT_DOC_CMDS) {
throw 'RoomService send queue full';
}
var msg = this.serializeMsg(msgType, body);
this.docCmdSendQueue.push(msg);
}
if (msgType == 'presence:cmd') {
var _msg = this.serializeMsg(msgType, body);
var presenceBody = body;
this.presenceCmdSendQueue.set(presenceBody.key, _msg);
}
this.processSendQueue();
};
_proto.processSendQueue = function processSendQueue() {
if (!this.currentConn) {
return;
}
try {
while (this.presenceCmdSendQueue.size > 0) {
var first = this.presenceCmdSendQueue.entries().next();
if (first) {
var _first$value = first.value,
key = _first$value[0],
msg = _first$value[1];
this.currentConn.send(msg);
this.presenceCmdSendQueue["delete"](key);
}
}
while (this.docCmdSendQueue.length > 0) {
var _msg2 = this.docCmdSendQueue[0];
this.currentConn.send(_msg2);
this.docCmdSendQueue.splice(0, 1);
}
} catch (e) {
console.error(e);
}
};
_proto.bind = function bind(msgType, callback) {
this.callbacks[msgType] = this.callbacks[msgType] || [];
this.callbacks[msgType].push(callback);
return callback;
};
_proto.unbind = function unbind(msgType, callback) {
this.callbacks[msgType] = this.callbacks[msgType].filter(function (c) {
return c !== callback;
});
};
_proto.dispatch = function dispatch(msgType, body) {
if (msgType == 'error') {
console.error(body);
}
var stack = this.callbacks[msgType];
if (stack) {
for (var i = 0; i < stack.length; i++) {
stack[i](body);
}
}
if (FORWARDED_TYPES.includes(msgType)) {
this.dispatcher.forwardCmd(msgType, body);
}
};
_proto.once = function once(msg) {
try {
var _this8 = this;
var off;
return Promise.race([new Promise(function (_, reject) {
return setTimeout(function () {
return reject('timeout');
}, WEBSOCKET_TIMEOUT);
}), new Promise(function (resolve) {
off = _this8.bind(msg, function (body) {
resolve(body);
});
})]).then(function () {
if (off) _this8.unbind(msg, off);
});
} catch (e) {
return Promise.reject(e);
}
};
return ReconnectingWebSocket;
}();
var InnerListClient = /*#__PURE__*/function () {

@@ -308,2 +702,6 @@ function InnerListClient(props) {

_proto.bootstrap = function bootstrap(checkpoint) {
ListInterpreter.importFromRawCheckpoint(this.store, checkpoint, this.meta.listID);
};
_proto.sendCmd = function sendCmd(cmd) {

@@ -403,3 +801,4 @@ this.ws.send('doc:cmd', {

this.store = store;
this.meta = meta;
this.meta = meta; //TODO: defer initial bootstrap?
MapInterpreter.importFromRawCheckpoint(this.store, props.checkpoint, this.meta.mapID);

@@ -410,2 +809,6 @@ }

_proto.bootstrap = function bootstrap(checkpoint) {
MapInterpreter.importFromRawCheckpoint(this.store, checkpoint, this.meta.mapID);
};
_proto.sendCmd = function sendCmd(cmd) {

@@ -519,3 +922,2 @@ this.ws.send('doc:cmd', {

this.bus = props.bus;
this.key = props.key;

@@ -536,9 +938,9 @@ var sendPres = function sendPres(_, args) {

_proto.getAll = function getAll() {
_proto.getAll = function getAll(key) {
try {
var _this3 = this;
return Promise.resolve(fetchPresence(PRESENCE_URL, _this3.token, _this3.roomID, _this3.key)).then(function (val) {
_this3.cache[_this3.key] = val;
return _this3.withoutExpiredAndSelf(_this3.key);
return Promise.resolve(fetchPresence(PRESENCE_URL, _this3.token, _this3.roomID, key)).then(function (val) {
_this3.cache[key] = val;
return _this3.withoutExpiredAndSelf(key);
});

@@ -599,7 +1001,7 @@ } catch (e) {

/**
*
* @param key
* @param value Any arbitrary object, string, boolean, or number.
* @param exp (Optional) Expiration time in seconds
*/
_proto.set = function set(value, exp) {
_proto.set = function set(key, value, exp) {
var addition = exp ? exp : 60; // Convert to unix + add seconds

@@ -609,9 +1011,9 @@

this.bus.publish({
key: this.key,
key: key,
value: value,
expAt: expAt
});
this.sendPres(this.key, {
this.sendPres(key, {
room: this.roomID,
key: this.key,
key: key,
value: JSON.stringify(value),

@@ -621,11 +1023,11 @@ expAt: expAt

if (!this.cache[this.key]) {
this.cache[this.key] = {};
if (!this.cache[key]) {
this.cache[key] = {};
}
this.cache[this.key][this.actor] = {
this.cache[key][this.actor] = {
value: value,
expAt: new Date(expAt * 1000)
};
return this.withoutExpiredAndSelf(this.key);
return this.withoutExpiredAndSelf(key);
};

@@ -713,15 +1115,18 @@

try {
return Promise.resolve(fetchSession(params.authStrategy, params.authCtx, params.room, params.document)).then(function (sess) {
return Promise.resolve(fetchDocument(params.docsURL, sess.token, sess.docID)).then(function (_ref2) {
return Promise.resolve(fetchSession(params.authStrategy, params.authCtx, params.room, params.document)).then(function (session) {
return Promise.resolve(fetchDocument(params.docsURL, session.token, session.docID)).then(function (_ref2) {
var body = _ref2.body;
var roomClient = new RoomClient({
conn: params.conn,
actor: sess.guestReference,
actor: session.guestReference,
checkpoint: body,
token: sess.token,
roomID: sess.roomID
token: session.token,
roomID: session.roomID,
docID: params.document,
auth: params.authStrategy,
authCtx: params.authCtx,
wsURL: WS_URL,
docsURL: DOCS_URL,
session: session
});
return Promise.resolve(roomClient.reconnect()).then(function () {
return roomClient;
});
return roomClient;
});

@@ -733,3 +1138,2 @@ });

};
var WEBSOCKET_TIMEOUT = 1000 * 2;
var MAP_CMDS = ['mcreate', 'mput', 'mputref', 'mdel'];

@@ -739,11 +1143,20 @@ var LIST_CMDS = ['lcreate', 'lins', 'linsref', 'lput', 'lputref', 'ldel'];

function RoomClient(params) {
var _this = this;
this.listClients = {};
this.mapClients = {};
this.expires = {};
this.queueIncomingCmds = true;
this.cmdQueue = [];
this.mapCallbacksByObjID = {};
this.listCallbacksByObjID = {};
this.presenceCallbacksByKey = {};
this.ws = new SuperlumeWebSocket(params.conn);
var wsURL = params.wsURL,
docsURL = params.docsURL,
roomID = params.roomID;
this.ws = new ReconnectingWebSocket({
dispatcher: this,
wsURL: wsURL,
docsURL: docsURL,
room: roomID,
session: params.session
});
this.token = params.token;

@@ -754,56 +1167,113 @@ this.roomID = params.roomID;

this.checkpoint = params.checkpoint;
this.InnerPresenceClient = undefined;
var vs = vsReader(window.atob);
this.ws.bind('doc:fwd', function (body) {
if (body.room !== _this.roomID) return;
} // impl WebsocketDispatch
if (!body.args || body.args.length < 3) {
// Potentially a network failure, we don't want to crash,
// but do want to warn people
console.error('Unexpected command: ', body.args);
return;
} // Ignore version stamps older than checkpoint
var _proto = RoomClient.prototype;
if (vs.isOlderVS(body.vs, _this.checkpoint.vs)) return; // Ignore validated commands
_proto.forwardCmd = function forwardCmd(msgType, body) {
if (this.queueIncomingCmds) {
this.cmdQueue.push([msgType, body]);
return;
}
if (body.from === _this.actor) return;
var _ref = [body.args[0], body.args[1], body.args[2]],
cmd = _ref[0],
docID = _ref[1],
objID = _ref[2];
if (docID !== _this.docID) return;
this.processCmd(msgType, body);
};
if (MAP_CMDS.includes(cmd)) {
_this.dispatchMapCmd(objID, body);
} else if (LIST_CMDS.includes(cmd)) {
_this.dispatchListCmd(objID, body);
} else {
console.warn('Unhandled Room Service doc:fwd command: ' + cmd + '. Consider updating the Room Service client.');
}
});
this.ws.bind('presence:fwd', function (body) {
_this.dispatchPresenceCmd(body);
});
this.ws.bind('room:rm_guest', function (body) {
if (body.room !== _this.roomID) return;
_proto.processCmd = function processCmd(msgType, body) {
if (msgType == 'doc:fwd' && 'args' in body) {
this.dispatchDocCmd(body);
}
var client = _this.presence('_____any');
if (msgType == 'presence:fwd' && 'expAt' in body) {
this.dispatchPresenceCmd(body);
}
var newClient = client.dangerouslyUpdateClientDirectly('room:rm_guest', body);
if (msgType == 'room:rm_guest' && 'guest' in body) {
this.dispatchRmGuest(body);
}
};
for (var _i = 0, _Object$entries = Object.entries(_this.presenceCallbacksByKey); _i < _Object$entries.length; _i++) {
var _Object$entries$_i = _Object$entries[_i],
cbs = _Object$entries$_i[1];
_proto.bootstrap = function bootstrap(checkpoint) {
this.checkpoint = checkpoint;
for (var _iterator = _createForOfIteratorHelperLoose(cbs), _step; !(_step = _iterator()).done;) {
var cb = _step.value;
cb(newClient, body.guest);
}
for (var _i = 0, _Object$entries = Object.entries(this.listClients); _i < _Object$entries.length; _i++) {
var _Object$entries$_i = _Object$entries[_i],
client = _Object$entries$_i[1];
client.bootstrap(checkpoint);
}
for (var _i2 = 0, _Object$entries2 = Object.entries(this.mapClients); _i2 < _Object$entries2.length; _i2++) {
var _Object$entries2$_i = _Object$entries2[_i2],
_client = _Object$entries2$_i[1];
_client.bootstrap(checkpoint);
}
this.queueIncomingCmds = false;
for (var _iterator = _createForOfIteratorHelperLoose(this.cmdQueue), _step; !(_step = _iterator()).done;) {
var _step$value = _step.value,
msgType = _step$value[0],
body = _step$value[1];
this.processCmd(msgType, body);
}
this.cmdQueue.length = 0;
};
_proto.startQueueingCmds = function startQueueingCmds() {
this.queueIncomingCmds = true;
};
_proto.dispatchDocCmd = function dispatchDocCmd(body) {
if (body.room !== this.roomID) return;
if (!body.args || body.args.length < 3) {
// Potentially a network failure, we don't want to crash,
// but do want to warn people
console.error('Unexpected command: ', body.args);
return;
} // Ignore version stamps older than checkpoint
if (vsReader(atob).isOlderVS(body.vs, this.checkpoint.vs)) {
return;
} // Ignore validated commands
if (body.from === this.actor) {
return;
}
var _ref = [body.args[0], body.args[1], body.args[2]],
cmd = _ref[0],
docID = _ref[1],
objID = _ref[2];
if (docID !== this.docID) return;
if (MAP_CMDS.includes(cmd)) {
this.dispatchMapCmd(objID, body);
} else if (LIST_CMDS.includes(cmd)) {
this.dispatchListCmd(objID, body);
} else {
console.warn('Unhandled Room Service doc:fwd command: ' + cmd + '. Consider updating the Room Service client.');
}
};
_proto.dispatchRmGuest = function dispatchRmGuest(body) {
if (body.room !== this.roomID) return;
var client = this.presence();
var newClient = client.dangerouslyUpdateClientDirectly('room:rm_guest', body);
for (var _i3 = 0, _Object$entries3 = Object.entries(this.presenceCallbacksByKey); _i3 < _Object$entries3.length; _i3++) {
var _Object$entries3$_i = _Object$entries3[_i3],
cbs = _Object$entries3$_i[1];
for (var _iterator2 = _createForOfIteratorHelperLoose(cbs), _step2; !(_step2 = _iterator2()).done;) {
var cb = _step2.value;
cb(newClient, body.guest);
}
});
}
}
};
var _proto = RoomClient.prototype;
_proto.dispatchMapCmd = function dispatchMapCmd(objID, body) {

@@ -817,4 +1287,4 @@ if (!this.mapClients[objID]) {

for (var _iterator2 = _createForOfIteratorHelperLoose(this.mapCallbacksByObjID[objID] || []), _step2; !(_step2 = _iterator2()).done;) {
var cb = _step2.value;
for (var _iterator3 = _createForOfIteratorHelperLoose(this.mapCallbacksByObjID[objID] || []), _step3; !(_step3 = _iterator3()).done;) {
var cb = _step3.value;
cb(updatedClient.toObject(), body.from);

@@ -832,4 +1302,4 @@ }

for (var _iterator3 = _createForOfIteratorHelperLoose(this.listCallbacksByObjID[objID] || []), _step3; !(_step3 = _iterator3()).done;) {
var cb = _step3.value;
for (var _iterator4 = _createForOfIteratorHelperLoose(this.listCallbacksByObjID[objID] || []), _step4; !(_step4 = _iterator4()).done;) {
var cb = _step4.value;
cb(updatedClient.toArray(), body.from);

@@ -840,7 +1310,7 @@ }

_proto.dispatchPresenceCmd = function dispatchPresenceCmd(body) {
var _this2 = this;
var _this = this;
if (body.room !== this.roomID) return;
if (body.from === this.actor) return;
var client = this.presence(body.key);
var client = this.presence();
var key = body.key;

@@ -867,6 +1337,6 @@ var now = new Date().getTime() / 1000;

for (var _iterator4 = _createForOfIteratorHelperLoose((_this2$presenceCallba = _this2.presenceCallbacksByKey[key]) !== null && _this2$presenceCallba !== void 0 ? _this2$presenceCallba : []), _step4; !(_step4 = _iterator4()).done;) {
var _this2$presenceCallba;
for (var _iterator5 = _createForOfIteratorHelperLoose((_this$presenceCallbac = _this.presenceCallbacksByKey[key]) !== null && _this$presenceCallbac !== void 0 ? _this$presenceCallbac : []), _step5; !(_step5 = _iterator5()).done;) {
var _this$presenceCallbac;
var cb = _step4.value;
var cb = _step5.value;
cb(newClient, body.from);

@@ -881,6 +1351,6 @@ }

for (var _iterator5 = _createForOfIteratorHelperLoose((_this$presenceCallbac = this.presenceCallbacksByKey[key]) !== null && _this$presenceCallbac !== void 0 ? _this$presenceCallbac : []), _step5; !(_step5 = _iterator5()).done;) {
var _this$presenceCallbac;
for (var _iterator6 = _createForOfIteratorHelperLoose((_this$presenceCallbac2 = this.presenceCallbacksByKey[key]) !== null && _this$presenceCallbac2 !== void 0 ? _this$presenceCallbac2 : []), _step6; !(_step6 = _iterator6()).done;) {
var _this$presenceCallbac2;
var cb = _step5.value;
var cb = _step6.value;
cb(newClient, body.from);

@@ -890,62 +1360,11 @@ }

_proto.once = function once(msg) {
try {
var _this4 = this;
var off;
return Promise.race([new Promise(function (_, reject) {
return setTimeout(function () {
return reject('timeout');
}, WEBSOCKET_TIMEOUT);
}), new Promise(function (resolve) {
off = _this4.ws.bind(msg, function (body) {
resolve(body);
});
})]).then(function () {
if (off) _this4.ws.unbind(msg, off);
});
} catch (e) {
return Promise.reject(e);
}
}
/**
* TODO: don't expose this function
*/
;
_proto.reconnect = function reconnect() {
try {
var _this6 = this;
if (!_this6.errorListener) {
_this6.errorListener = _this6.ws.bind('error', function (err) {
console.error('Room Service encountered a server-side error. If you see this, please let us know; this could be a bug.', err);
});
}
var authenticated = _this6.once('guest:authenticated');
_this6.ws.send('guest:authenticate', _this6.token);
return Promise.resolve(authenticated).then(function () {
var joined = _this6.once('room:joined');
_this6.ws.send('room:join', _this6.roomID);
return Promise.resolve(joined).then(function () {});
});
} catch (e) {
return Promise.reject(e);
}
};
_proto.createListLocally = function createListLocally(name) {
var _this7 = this;
var _this2 = this;
var bus = new LocalBus();
bus.subscribe(function (body) {
var client = _this7.listClients[name];
var client = _this2.listClients[name];
for (var _iterator6 = _createForOfIteratorHelperLoose(_this7.listCallbacksByObjID[name] || []), _step6; !(_step6 = _iterator6()).done;) {
var cb = _step6.value;
for (var _iterator7 = _createForOfIteratorHelperLoose(_this2.listCallbacksByObjID[name] || []), _step7; !(_step7 = _iterator7()).done;) {
var cb = _step7.value;
cb(client.toArray(), body.from);

@@ -990,10 +1409,10 @@ }

_proto.createMapLocally = function createMapLocally(name) {
var _this8 = this;
var _this3 = this;
var bus = new LocalBus();
bus.subscribe(function (body) {
var client = _this8.mapClients[name];
var client = _this3.mapClients[name];
for (var _iterator7 = _createForOfIteratorHelperLoose(_this8.mapCallbacksByObjID[name] || []), _step7; !(_step7 = _iterator7()).done;) {
var cb = _step7.value;
for (var _iterator8 = _createForOfIteratorHelperLoose(_this3.mapCallbacksByObjID[name] || []), _step8; !(_step8 = _iterator8()).done;) {
var cb = _step8.value;
cb(client.toObject(), body.from);

@@ -1031,4 +1450,4 @@ }

_proto.presence = function presence(key) {
var _this9 = this;
_proto.presence = function presence() {
var _this4 = this;

@@ -1041,8 +1460,8 @@ if (this.InnerPresenceClient) {

bus.subscribe(function (body) {
_this9.dispatchPresenceCmd({
_this4.dispatchPresenceCmd({
key: body.key,
value: body.value,
expAt: body.expAt,
from: _this9.actor,
room: _this9.roomID
from: _this4.actor,
room: _this4.roomID
});

@@ -1055,4 +1474,3 @@ });

token: this.token,
bus: bus,
key: key
bus: bus
});

@@ -1090,4 +1508,4 @@

if (obj instanceof InnerListClient) {
var _client = obj;
objID = _client.id;
var _client2 = obj;
objID = _client2.id;
this.listCallbacksByObjID[objID] = this.listCallbacksByObjID[objID] || [];

@@ -1121,4 +1539,4 @@ this.listCallbacksByObjID[objID].push(cb);

_proto.unsubscribe = function unsubscribe(listeners) {
for (var _iterator8 = _createForOfIteratorHelperLoose(listeners), _step8; !(_step8 = _iterator8()).done;) {
var l = _step8.value;
for (var _iterator9 = _createForOfIteratorHelperLoose(listeners), _step9; !(_step9 = _iterator9()).done;) {
var l = _step9.value;

@@ -1130,6 +1548,2 @@ if (l.objID) {

}
if (l.event) {
this.ws.unbind(l.event, l.fn);
}
}

@@ -1175,5 +1589,3 @@ };

var ws = new WebSocket(WS_URL);
return Promise.resolve(createRoom({
conn: ws,
docsURL: DOCS_URL,

@@ -1180,0 +1592,0 @@ authStrategy: _this2.auth,

@@ -1,2 +0,2 @@

import SuperlumeWebSocket from './ws';
import { SuperlumeSend } from './ws';
import { ObjectClient, DocumentCheckpoint } from './types';

@@ -18,3 +18,3 @@ import { LocalBus } from './localbus';

listID: string;
ws: SuperlumeWebSocket;
ws: SuperlumeSend;
actor: string;

@@ -26,2 +26,3 @@ bus: LocalBus<{

});
bootstrap(checkpoint: DocumentCheckpoint): void;
private sendCmd;

@@ -36,4 +37,4 @@ private clone;

push<K extends number>(...args: Array<T[K]>): InnerListClient<T>;
map<K extends keyof T, V extends T[K]>(fn: (val: V, index: K, key: string) => Array<T[K]>): Array<T[K]>;
toArray(): T[];
map<K extends number>(fn: (val: T[K], index: number, key: string) => Array<T[number]>): Array<T[K]>;
toArray(): T[number][];
}
import { ObjectClient } from './types';
import SuperlumeWebSocket from './ws';
import { SuperlumeSend } from './ws';
import { LocalBus } from './localbus';

@@ -21,3 +21,3 @@ import { DocumentCheckpoint } from '@roomservice/core';

actor: string;
ws: SuperlumeWebSocket;
ws: SuperlumeSend;
bus: LocalBus<{

@@ -28,2 +28,3 @@ from: string;

});
bootstrap(checkpoint: DocumentCheckpoint): void;
get id(): string;

@@ -34,8 +35,6 @@ private sendCmd;

get keys(): string[];
get<K extends keyof T>(key: K): T;
get<K extends keyof T>(key: K): T[K];
set<K extends keyof T>(key: K, value: T[K]): InnerMapClient<T>;
toObject(): {
[key: string]: T;
};
toObject(): T;
delete<K extends keyof T>(key: K): InnerMapClient<T>;
}

@@ -1,2 +0,2 @@

import SuperlumeWebSocket from './ws';
import { SuperlumeSend } from './ws';
import { Prop } from './types';

@@ -10,3 +10,2 @@ import { WebSocketPresenceFwdMessage, WebSocketLeaveMessage } from './wsMessages';

private token;
private key;
private cache;

@@ -17,4 +16,3 @@ private sendPres;

roomID: string;
key: string;
ws: SuperlumeWebSocket;
ws: SuperlumeSend;
actor: string;

@@ -32,3 +30,3 @@ token: string;

*/
getAll<T extends any>(): Promise<{
getAll<T extends any>(key: string): Promise<{
[key: string]: T;

@@ -40,7 +38,7 @@ }>;

/**
*
* @param key
* @param value Any arbitrary object, string, boolean, or number.
* @param exp (Optional) Expiration time in seconds
*/
set<T extends any>(value: T, exp?: number): {
set<T extends any>(key: string, value: T, exp?: number): {
[key: string]: T;

@@ -47,0 +45,0 @@ };

@@ -1,6 +0,8 @@

import { WebSocketLikeConnection, DocumentCheckpoint, AuthStrategy, Prop } from './types';
import { ForwardedMessageBody, WebsocketDispatch } from './ws';
import { DocumentCheckpoint, AuthStrategy, Prop } from './types';
import { LocalSession } from './remote';
import { InnerListClient, ListObject } from './ListClient';
import { InnerMapClient, MapObject } from './MapClient';
import { InnerPresenceClient } from './PresenceClient';
import { WebSocketServerMessage } from './wsMessages';
import { WebSocketDocFwdMessage, WebSocketLeaveMessage, WebSocketServerMessage } from './wsMessages';
declare type Listener = {

@@ -17,4 +19,3 @@ event?: Prop<WebSocketServerMessage, 'type'>;

export declare type PresenceClient = Omit<InnerPresenceClient, 'dangerouslyUpdateClientDirectly'>;
export declare class RoomClient {
private ws;
export declare class RoomClient implements WebsocketDispatch {
private token;

@@ -25,3 +26,2 @@ private roomID;

private checkpoint;
private errorListener;
private InnerPresenceClient?;

@@ -31,4 +31,9 @@ private listClients;

private expires;
private ws;
constructor(params: {
conn: WebSocketLikeConnection;
auth: AuthStrategy<any>;
authCtx: any;
session: LocalSession;
wsURL: string;
docsURL: string;
actor: string;

@@ -38,11 +43,15 @@ checkpoint: DocumentCheckpoint;

roomID: string;
docID: string;
});
forwardCmd(msgType: string, body: ForwardedMessageBody): void;
processCmd(msgType: string, body: ForwardedMessageBody): void;
bootstrap(checkpoint: DocumentCheckpoint): void;
private queueIncomingCmds;
private cmdQueue;
startQueueingCmds(): void;
dispatchDocCmd(body: Prop<WebSocketDocFwdMessage, 'body'>): void;
dispatchRmGuest(body: Prop<WebSocketLeaveMessage, 'body'>): void;
private dispatchMapCmd;
private dispatchListCmd;
private dispatchPresenceCmd;
private once;
/**
* TODO: don't expose this function
*/
reconnect(): Promise<void>;
get me(): string;

@@ -53,3 +62,3 @@ private createListLocally;

map<T extends MapObject>(name: string): MapClient<T>;
presence(key: string): PresenceClient;
presence(): PresenceClient;
private mapCallbacksByObjID;

@@ -68,7 +77,6 @@ private listCallbacksByObjID;

}
export declare function createRoom<T extends object>(params: {
conn: WebSocketLikeConnection;
export declare function createRoom<A extends object>(params: {
docsURL: string;
authStrategy: AuthStrategy<T>;
authCtx: T;
authStrategy: AuthStrategy<A>;
authCtx: A;
room: string;

@@ -75,0 +83,0 @@ document: string;

@@ -1,1 +0,4 @@

export {};
import { DocumentCheckpoint } from './types';
import { LocalSession } from 'remote';
export declare function mockSession(): LocalSession;
export declare function mockCheckpoint(): DocumentCheckpoint;

@@ -76,3 +76,3 @@ import ReverseTree from './ReverseTree';

declare type RequireSome<T, K extends keyof T> = Partial<Omit<T, K>> & Required<Pick<T, K>>;
export declare type WebSocketLikeConnection = RequireSome<WebSocket, 'send' | 'onmessage'>;
export declare type WebSocketLikeConnection = RequireSome<WebSocket, 'send' | 'onmessage' | 'close'>;
export interface DocumentContext {

@@ -79,0 +79,0 @@ lists: {

import { DocumentCheckpoint } from 'types';
export declare function unescapeID(checkpoint: DocumentCheckpoint, id: string): string;
export declare function delay(ms: number): Promise<unknown>;

@@ -1,24 +0,58 @@

import { WebSocketDocFwdMessage, WebSocketDocCmdMessage, WebSocketPresenceCmdMessage, WebSocketPresenceFwdMessage, WebSocketLeaveMessage, WebSocketJoinMessage } from './wsMessages';
import { WebSocketLikeConnection, Prop } from 'types';
declare type Cb = (body: any) => void;
export default class SuperlumeWebSocket {
import { WebSocketDocFwdMessage, WebSocketClientMessage, WebSocketDocCmdMessage, WebSocketPresenceCmdMessage, WebSocketPresenceFwdMessage, WebSocketLeaveMessage, WebSocketJoinMessage } from './wsMessages';
import { Prop, DocumentCheckpoint, Message } from 'types';
import { LocalSession } from './remote';
export declare class ReconnectingWebSocket implements SuperlumeSend {
private wsURL;
private docsURL;
private room;
private session;
private wsFactory;
private documentFetch;
private currentConn?;
private pendingConn?;
private dispatcher;
private callbacks;
constructor(params: {
dispatcher: WebsocketDispatch;
wsURL: string;
docsURL: string;
room: string;
session: LocalSession;
wsFactory?: WebSocketFactory;
documentFetch?: DocumentFetch;
});
close(): void;
private connectAndAuth;
private conn;
private callbacks;
constructor(conn: WebSocketLikeConnection);
private wsLoop;
private lastTime;
private msgsThisMilisecond;
private timestamp;
send(msgType: 'room:join', room: Prop<WebSocketJoinMessage, 'body'>): void;
send(msgType: 'guest:authenticate', token: string): void;
serializeMsg(msgType: 'room:join', room: Prop<WebSocketJoinMessage, 'body'>): string;
serializeMsg(msgType: 'guest:authenticate', token: string): string;
serializeMsg(msgType: 'doc:cmd', body: Prop<WebSocketDocCmdMessage, 'body'>): string;
serializeMsg(msgType: 'presence:cmd', body: Prop<WebSocketPresenceCmdMessage, 'body'>): string;
private docCmdSendQueue;
private presenceCmdSendQueue;
send(msgType: 'doc:cmd', body: Prop<WebSocketDocCmdMessage, 'body'>): void;
send(msgType: 'presence:cmd', body: Prop<WebSocketPresenceCmdMessage, 'body'>): void;
bind(msgType: 'room:rm_guest', callback: (body: Prop<WebSocketLeaveMessage, 'body'>) => void): Cb;
bind(msgType: 'room:joined', callback: (body: string) => void): Cb;
bind(msgType: 'doc:fwd', callback: (body: Prop<WebSocketDocFwdMessage, 'body'>) => void): Cb;
bind(msgType: 'presence:fwd', callback: (body: Prop<WebSocketPresenceFwdMessage, 'body'>) => void): Cb;
bind(msgType: 'guest:authenticated', callback: (body: string) => void): Cb;
bind(msgType: 'error', callback: (body: string) => void): Cb;
unbind(msgType: string, callback: Cb): void;
private processSendQueue;
private bind;
private unbind;
private dispatch;
private once;
}
export {};
export declare type ForwardedMessageBody = Prop<WebSocketDocFwdMessage, 'body'> | Prop<WebSocketPresenceFwdMessage, 'body'> | Prop<WebSocketLeaveMessage, 'body'>;
export interface WebsocketDispatch {
forwardCmd(type: string, body: ForwardedMessageBody): void;
bootstrap(checkpoint: DocumentCheckpoint): void;
startQueueingCmds(): void;
}
export interface SuperlumeSend {
send(msgType: 'doc:cmd', body: Prop<WebSocketDocCmdMessage, 'body'>): void;
send(msgType: 'presence:cmd', body: Prop<WebSocketPresenceCmdMessage, 'body'>): void;
send(msgType: Prop<WebSocketClientMessage, 'type'>, body: any): void;
}
export declare type WebSocketFactory = (url: string) => Promise<WebSocketTransport>;
export declare type WebSocketTransport = Pick<WebSocket, 'send' | 'onclose' | 'onmessage' | 'onerror' | 'close'>;
export declare type DocumentFetch = (url: string, token: string, docID: string) => Promise<Message<DocumentCheckpoint>>;
{
"version": "3.0.0-1",
"version": "3.0.0-2",
"license": "MIT",

@@ -43,5 +43,5 @@ "main": "dist/index.js",

"dependencies": {
"@roomservice/core": "0.2.0",
"@roomservice/core": "0.2.1-0",
"tiny-invariant": "^1.1.0"
}
}

@@ -9,3 +9,3 @@ <p align="center">

This is the official, javascript SDK.
This is the official, ~javascript~ typescript SDK.

@@ -12,0 +12,0 @@ ## Install

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