@roomservice/browser
Advanced tools
Comparing version 3.0.0 to 3.0.1-0
@@ -764,3 +764,3 @@ 'use strict'; | ||
var _ListInterpreter$newL = core.ListInterpreter.newList(props.docID, props.listID, props.actor), | ||
var _ListInterpreter$newL = core.ListInterpreter.newList(props.docID, props.listID), | ||
meta = _ListInterpreter$newL.meta, | ||
@@ -798,5 +798,5 @@ store = _ListInterpreter$newL.store; | ||
_proto.dangerouslyUpdateClientDirectly = function dangerouslyUpdateClientDirectly(cmd) { | ||
_proto.dangerouslyUpdateClientDirectly = function dangerouslyUpdateClientDirectly(cmd, versionstamp, ack) { | ||
core.ListInterpreter.validateCommand(this.meta, cmd); | ||
core.ListInterpreter.applyCommand(this.store, cmd); | ||
core.ListInterpreter.applyCommand(this.store, cmd, versionstamp, ack); | ||
return this.clone(); | ||
@@ -860,2 +860,7 @@ }; | ||
return core.ListInterpreter.toArray(this.store); | ||
} // exposed for testing | ||
; | ||
_proto.session = function session() { | ||
return this.store.rt.session; | ||
}; | ||
@@ -905,5 +910,5 @@ | ||
_proto.dangerouslyUpdateClientDirectly = function dangerouslyUpdateClientDirectly(cmd) { | ||
_proto.dangerouslyUpdateClientDirectly = function dangerouslyUpdateClientDirectly(cmd, versionstamp, ack) { | ||
core.MapInterpreter.validateCommand(this.meta, cmd); | ||
core.MapInterpreter.applyCommand(this.store, cmd); | ||
core.MapInterpreter.applyCommand(this.store, cmd, versionstamp, ack); | ||
return this.clone(); | ||
@@ -913,3 +918,5 @@ }; | ||
_proto.get = function get(key) { | ||
return this.store[key]; | ||
var _this$store$kv$get; | ||
return (_this$store$kv$get = this.store.kv.get(key)) === null || _this$store$kv$get === void 0 ? void 0 : _this$store$kv$get.value; | ||
}; | ||
@@ -950,3 +957,3 @@ | ||
get: function get() { | ||
return Object.keys(this.store); | ||
return Array.from(this.store.kv.keys()); | ||
} | ||
@@ -1083,5 +1090,22 @@ }]); | ||
_proto.set = function set(value, exp) { | ||
var _this2 = this; | ||
var addition = exp ? exp : 60; // Convert to unix + add seconds | ||
var expAt = Math.round(new Date().getTime() / 1000) + addition; | ||
if (this.myExpirationHandle) { | ||
clearTimeout(this.myExpirationHandle); | ||
this.myExpirationHandle = undefined; | ||
} | ||
this.myExpirationHandle = setTimeout(function () { | ||
// TODO: this should be revisited when presence ACKs are added | ||
delete _this2.cache[_this2.actor]; | ||
_this2.bus.publish({ | ||
key: _this2.key, | ||
valuesByUser: _this2.withoutExpired() | ||
}); | ||
}, addition * 1000); | ||
this.sendPres(this.key, { | ||
@@ -1115,5 +1139,6 @@ room: this.roomID, | ||
if (body.room !== this.roomID) return false; | ||
if (body.from === this.actor) return false; // ignore validation msgs | ||
if (body.room !== this.roomID) return false; // ignore validation msgs | ||
// TODO: use same ack logic as doc cmds | ||
if (body.from === this.actor) return false; | ||
var obj = { | ||
@@ -1215,3 +1240,3 @@ expAt: new Date(body.expAt * 1000), | ||
this.mapClients = {}; | ||
this.expires = {}; | ||
this.expiresByActorByKey = {}; | ||
this.queueIncomingCmds = true; | ||
@@ -1326,9 +1351,4 @@ this.cmdQueue = []; | ||
if (core.vsReader(atob).isOlderVS(body.vs, this.bootstrapState.document.vs)) { | ||
if (core.isOlderVS(body.vs, this.bootstrapState.document.vs)) { | ||
return; | ||
} // Ignore validated commands | ||
if (body.from === this.actor) { | ||
return; | ||
} | ||
@@ -1374,3 +1394,3 @@ | ||
var client = this.mapClients[objID]; | ||
var updatedClient = client.dangerouslyUpdateClientDirectly(body.args); | ||
var updatedClient = client.dangerouslyUpdateClientDirectly(body.args, body.vs, body.ack); | ||
@@ -1389,3 +1409,3 @@ for (var _iterator3 = _createForOfIteratorHelperLoose(this.mapCallbacksByObjID[objID] || []), _step3; !(_step3 = _iterator3()).done;) { | ||
var client = this.listClients[objID]; | ||
var updatedClient = client.dangerouslyUpdateClientDirectly(body.args); | ||
var updatedClient = client.dangerouslyUpdateClientDirectly(body.args, body.vs, body.ack); | ||
@@ -1401,3 +1421,4 @@ for (var _iterator4 = _createForOfIteratorHelperLoose(this.listCallbacksByObjID[objID] || []), _step4; !(_step4 = _iterator4()).done;) { | ||
if (body.room !== this.roomID) return; | ||
if (body.room !== this.roomID) return; // TODO: use same ack logic as doc cmds | ||
if (body.from === this.actor) return; | ||
@@ -1416,4 +1437,7 @@ var key = body.key; | ||
if (secondsTillTimeout < 60 * 60 * 12) { | ||
if (this.expires[key]) { | ||
clearTimeout(this.expires[key]); | ||
var expiresByActor = this.expiresByActorByKey[key] || {}; | ||
var actor = body.from; | ||
if (expiresByActor[actor]) { | ||
clearTimeout(expiresByActor[actor]); | ||
} | ||
@@ -1434,3 +1458,4 @@ | ||
}, secondsTillTimeout * 1000); | ||
this.expires[key] = timeout; | ||
expiresByActor[actor] = timeout; | ||
this.expiresByActorByKey[key] = expiresByActor; | ||
} | ||
@@ -1437,0 +1462,0 @@ |
@@ -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"),n="https://super.roomservice.dev/docs",o="https://super.roomservice.dev/presence";function s(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&&s(e.prototype,t),r&&s(e,r),e}function c(){return(c=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var n in r)Object.prototype.hasOwnProperty.call(r,n)&&(e[n]=r[n])}return e}).apply(this,arguments)}function u(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 a(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 u(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)?u(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 h=function(){function e(){}return e.prototype.then=function(t,r){const n=new e,o=this.s;if(o){const e=1&o?t:r;if(e){try{l(n,1,e(this.v))}catch(e){l(n,2,e)}return n}return this}return this.o=function(e){try{const o=e.v;1&e.s?l(n,1,t?t(o):o):r?l(n,1,r(o)):l(n,2,o)}catch(e){l(n,2,e)}},n},e}();function l(e,t,r){if(!e.s){if(r instanceof h){if(!r.s)return void(r.o=l.bind(null,e,t));1&t&&(t=r.s),r=r.v}if(r&&r.then)return void r.then(l.bind(null,e,t),l.bind(null,e,2));e.s=t,e.v=r;const n=e.o;n&&n(e)}}function d(e){return e instanceof h&&1&e.s}function m(e,t,r){for(var n;;){var o=e();if(d(o)&&(o=o.v),!o)return s;if(o.then){n=0;break}var s=r();if(s&&s.then){if(!d(s)){n=1;break}s=s.s}if(t){var i=t();if(i&&i.then&&!d(i)){n=2;break}}}var c=new h,u=l.bind(null,c,2);return(0===n?o.then(m):1===n?s.then(a):i.then(f)).then(void 0,u),c;function a(n){s=n;do{if(t&&(i=t())&&i.then&&!d(i))return void i.then(f).then(void 0,u);if(!(o=e())||d(o)&&!o.v)return void l(c,1,s);if(o.then)return void o.then(m).then(void 0,u);d(s=r())&&(s=s.v)}while(!s||!s.then);s.then(a).then(void 0,u)}function m(e){e?(s=r())&&s.then?s.then(a).then(void 0,u):a(s):l(c,1,s)}function f(){(o=e())?o.then?o.then(m).then(void 0,u):m(o):l(c,1,s)}}"undefined"!=typeof Symbol&&(Symbol.iterator||(Symbol.iterator=Symbol("Symbol.iterator"))),"undefined"!=typeof Symbol&&(Symbol.asyncIterator||(Symbol.asyncIterator=Symbol("Symbol.asyncIterator")));var f=function(e){try{var t=function(e){return r?e:Promise.resolve(fetch(o,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({resources:[{object:"document",reference:c,permission:"read_write",room:i},{object:"room",reference:i,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}}))}))},r=!1,n=e.authBundle,o=n.strategy,s=n.ctx,i=e.room,c=e.document,u=function(){if("function"==typeof o)return Promise.resolve(o({room:i,ctx:s})).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,n=e.resources.find((function(e){return"room"===e.object})).id;return r=!0,{token:e.token,guestReference:e.user,docID:t,roomID:n}}))}();return Promise.resolve(u&&u.then?u.then(t):t(u))}catch(e){return Promise.reject(e)}},p=function(e,t,r){try{return Promise.resolve(fetch(e+"/"+r,{headers:{Authorization:"Bearer: "+t}})).then((function(e){return Promise.resolve(e.json()).then((function(e){return e.body}))}))}catch(e){return Promise.reject(e)}},v=function(e,t,r){try{return Promise.resolve(fetch(e+"/"+r,{headers:{Authorization:"Bearer: "+t}})).then((function(e){return Promise.resolve(e.json()).then((function(e){for(var t=0,r=Object.keys(e);t<r.length;t++)for(var n=r[t],o=0,s=Object.keys(e[n]);o<s.length;o++){var i=s[o];if("string"==typeof e[n][i].value){var c=void 0;try{c=JSON.parse(e[n][i].value)}catch(e){}c&&(e[n][i].value=c)}}return e}))}))}catch(e){return Promise.reject(e)}},b=function(e){try{return Promise.resolve(Promise.all([v(e.presenceURL,e.token,e.roomID),p(e.docsURL,e.token,e.docID)])).then((function(e){return{presence:e[0],document:e[1]}}))}catch(e){return Promise.reject(e)}};function y(e){return new Promise((function(t){return setTimeout(t,e)}))}var C=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)}},I=["doc:fwd","presence:fwd","room:rm_guest"],g=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.presenceURL=e.presenceURL,this.room=e.room,this.document=e.document,this.authBundle=e.authBundle,this.wsFactory=e.wsFactory||C,this.bootstrapFetch=e.bootstrapFetch||b,this.sessionFetch=e.sessionFetch||f,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=function(){var e=t.session;return Promise.resolve(t.wsFactory(t.wsURL)).then((function(r){return r.onmessage=function(e){var r=JSON.parse(e.data);t.dispatch(r.type,r.body)},r.onclose=function(){return t.close()},Promise.resolve(r).then((function(r){try{return r.send(t.serializeMsg("guest:authenticate",e.token)),Promise.resolve(t.once("guest:authenticated")).then((function(){return r.send(t.serializeMsg("room:join",e.roomID)),Promise.resolve(t.once("room:joined")).then((function(){return Promise.resolve(t.bootstrapFetch({docID:e.docID,roomID:e.roomID,docsURL:t.docsURL,presenceURL:t.presenceURL,token:e.token})).then((function(n){return t.dispatcher.bootstrap(e.guestReference,n),r}))}))}))}catch(e){return Promise.reject(e)}}))}))},t=this,r=function(){if(!t.session)return Promise.resolve(t.sessionFetch({authBundle:t.authBundle,room:t.room,document:t.document})).then((function(e){t.session=e}))}();return Promise.resolve(r&&r.then?r.then(e):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(m((function(){return!t}),void 0,(function(){var n=r*(Math.random()+1)/2;return Promise.resolve(y(n)).then((function(){return r=Math.min(2*r+100,6e4),function(r,n){try{var o=Promise.resolve(e.connectAndAuth()).then((function(r){return e.currentConn=r,e.pendingConn=void 0,t=!0,r}))}catch(e){return n(e)}return o&&o.then?o.then(void 0,n):o}(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=m((function(){return!0}),void 0,(function(){return Promise.resolve(e.conn()).then((function(){return e.processSendQueue(),Promise.resolve(y(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";this.docCmdSendQueue.push(t)}"presence:cmd"==e&&this.presenceCmdSendQueue.set(t.key,t),this.processSendQueue()},t.processSendQueue=function(){if(this.currentConn&&this.session)try{for(;this.presenceCmdSendQueue.size>0;){var e=this.presenceCmdSendQueue.entries().next();if(e){var t=e.value,r=t[0],n=this.serializeMsg("presence:cmd",t[1]);this.currentConn.send(n),this.presenceCmdSendQueue.delete(r)}}for(;this.docCmdSendQueue.length>0;){var o=this.serializeMsg("doc:cmd",this.docCmdSendQueue[0]);this.currentConn.send(o),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);I.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}(),D=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),o=n.store;this.meta=n.meta,this.store=o,e.checkpoint.lists[e.listID]||t(!1),r.ListInterpreter.importFromRawCheckpoint(this.store,this.actor,e.checkpoint,this.meta.listID)}var n=e.prototype;return n.bootstrap=function(e,t){this.actor=e,r.ListInterpreter.importFromRawCheckpoint(this.store,this.actor,t.document,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 o,s=r.ListInterpreter.runPush.apply(r.ListInterpreter,[this.store,this.meta].concat(t)),i=a(s);!(o=i()).done;){var c=o.value;this.sendCmd(c)}return this},n.map=function(e){return r.ListInterpreter.map(this.store,e)},n.toArray=function(){return r.ListInterpreter.toArray(this.store)},e}(),w=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,t){this.actor=e,r.MapInterpreter.importFromRawCheckpoint(this.store,t.document,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=a(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}(),k=function(){function e(e){var t=this;this.roomID=e.roomID,this.ws=e.ws,this.actor=e.actor,this.key=e.key,this.cache={},this.bus=e.bus,this.sendPres=function(e,t,r){void 0===r&&(r=!1);var n={},o=!0;return function(){var t=arguments,s=this,i=r&&o,c=function(){e.apply(s,t),n[t[0]]=null};i&&(o=!1,c()),n[arguments[0]]||(n[arguments[0]]=setTimeout(c,40))}}((function(e,r){t.ws.send("presence:cmd",r)})),this.bootstrap(this.actor,e.checkpoint)}var t=e.prototype;return t.bootstrap=function(e,t){this.actor=e,this.cache=c({},this.cache,t.presence[this.key]||{})},t.getAll=function(){return this.withoutExpired()},t.getMine=function(){var e;return null===(e=(this.cache||{})[this.actor])||void 0===e?void 0:e.value},t.withoutExpired=function(){var e={};for(var t in this.cache){var r=this.cache[t];new Date>r.expAt?delete this.cache[t]:e[t]=r.value}return e},t.withoutActorOrExpired=function(e){var t={};for(var r in this.cache){var n=this.cache[r];n&&(r===e&&this.cache[r]||new Date>n.expAt?delete this.cache[r]:t[r]=n.value)}return t},t.set=function(e,t){var r=t||60,n=Math.round((new Date).getTime()/1e3)+r;this.sendPres(this.key,{room:this.roomID,key:this.key,value:JSON.stringify(e),expAt:n}),this.cache[this.actor]={value:e,expAt:new Date(1e3*n)};var o=this.withoutExpired();return this.bus.publish({key:this.key,valuesByUser:o}),o},t.dangerouslyUpdateClientDirectly=function(e,t){if("room:rm_guest"===e)return this.withoutActorOrExpired(t.guest);if("presence:expire"===e)return this.withoutExpired();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.from]=r,this.withoutExpired()},e}(),j=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}(),P=["mcreate","mput","mputref","mdel"],S=["lcreate","lins","linsref","lput","lputref","ldel"],L=function(){function e(e){this.presenceClients={},this.listClients={},this.mapClients={},this.expires={},this.queueIncomingCmds=!0,this.cmdQueue=[],this.mapCallbacksByObjID={},this.listCallbacksByObjID={},this.presenceCallbacksByKey={},this.ws=new g({dispatcher:this,wsURL:e.wsURL,docsURL:e.docsURL,presenceURL:e.presenceURL,room:e.room,document:e.document,authBundle:{strategy:e.auth,ctx:e.authCtx},sessionFetch:function(t){return Promise.resolve(e.session)}}),this.roomID=e.session.roomID,this.docID=e.bootstrapState.document.id,this.actor=e.actor,this.bootstrapState=e.bootstrapState}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,t){this.actor=e,this.bootstrapState=t;for(var r=0,n=Object.entries(this.listClients);r<n.length;r++)n[r][1].bootstrap(e,t);for(var o=0,s=Object.entries(this.mapClients);o<s.length;o++)s[o][1].bootstrap(e,t);for(var i=0,c=Object.entries(this.presenceClients);i<c.length;i++)c[i][1].bootstrap(e,t);this.queueIncomingCmds=!1;for(var u,h=a(this.cmdQueue);!(u=h()).done;){var l=u.value;this.processCmd(l[0],l[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.bootstrapState.document.vs)&&e.from!==this.actor){var t=[e.args[0],e.args[1],e.args[2]],n=t[0],o=t[2];t[1]===this.docID&&(P.includes(n)?this.dispatchMapCmd(o,e):S.includes(n)?this.dispatchListCmd(o,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=0,r=Object.entries(this.presenceClients);t<r.length;t++){var n=r[t],o=n[0],s=n[1].dangerouslyUpdateClientDirectly("room:rm_guest",e);if(!s)return;for(var i,c=a(this.presenceCallbacksByKey[o]||[]);!(i=c()).done;)(0,i.value)(s,e.guest)}},n.dispatchMapCmd=function(e,t){this.mapClients[e]||this.createMapLocally(e);for(var r,n=this.mapClients[e].dangerouslyUpdateClientDirectly(t.args),o=a(this.mapCallbacksByObjID[e]||[]);!(r=o()).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),o=a(this.listCallbacksByObjID[e]||[]);!(r=o()).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=e.key,n=this.presence(r),o=(new Date).getTime()/1e3,s=e.expAt-o;if(!(s<0)){if(s<43200){this.expires[r]&&clearTimeout(this.expires[r]);var i=setTimeout((function(){var o=n.dangerouslyUpdateClientDirectly("presence:expire",{key:e.key});if(o)for(var s,i=a(null!==(c=t.presenceCallbacksByKey[r])&&void 0!==c?c:[]);!(s=i()).done;){var c;(0,s.value)(o,e.from)}}),1e3*s);this.expires[r]=i}var c=n.dangerouslyUpdateClientDirectly("presence:fwd",e);if(c)for(var u,h=a(null!==(l=this.presenceCallbacksByKey[r])&&void 0!==l?l:[]);!(u=h()).done;){var l;(0,u.value)(c,e.from)}}}},n.createListLocally=function(e){var t=this,r=new j;r.subscribe((function(r){for(var n,o=t.listClients[e],s=a(t.listCallbacksByObjID[e]||[]);!(n=s()).done;)(0,n.value)(o.toArray(),r.from)}));var n=new D({checkpoint:this.bootstrapState.document,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.bootstrapState.document.lists[e]||(this.ws.send("doc:cmd",{args:["lcreate",this.docID,e],room:this.roomID}),this.bootstrapState.document.lists[e]={afters:[],ids:[],values:[]}),this.createListLocally(e))},n.createMapLocally=function(e){var t=this,r=new j;r.subscribe((function(r){for(var n,o=t.mapClients[e],s=a(t.mapCallbacksByObjID[e]||[]);!(n=s()).done;)(0,n.value)(o.toObject(),r.from)}));var n=new w({checkpoint:this.bootstrapState.document,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.bootstrapState.document.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.presenceClients[e])return this.presenceClients[e];var r=new j;r.subscribe((function(e){for(var r,n=a(t.presenceCallbacksByKey[e.key]||[]);!(r=n()).done;)(0,r.value)(e.valuesByUser,t.actor)}));var n=new k({checkpoint:this.bootstrapState,roomID:this.roomID,actor:this.actor,ws:this.ws,key:e,bus:r});try{this.presenceClients[e]=n}catch(e){throw new Error("Don't Freeze State. See more: https://err.sh/getroomservice/browser/dont-freeze")}return this.presenceClients[e]},n.subscribe=function(e,t){if(e instanceof k)return this.subscribePresence(e,t);var r,n=function(e,r){t(e,r)};return e instanceof w&&(this.mapCallbacksByObjID[r=e.id]=this.mapCallbacksByObjID[r]||[],this.mapCallbacksByObjID[r].push(n)),e instanceof D&&(this.listCallbacksByObjID[r=e.id]=this.listCallbacksByObjID[r]||[],this.listCallbacksByObjID[r].push(n)),[{objID:r,fn:n}]},n.subscribePresence=function(e,r){e||t(!1);var n=function(e,t){r&&r(e,t)},o=e.key;return this.presenceCallbacksByKey[o]=this.presenceCallbacksByKey[o]||[],this.presenceCallbacksByKey[o].push(n),[{objID:o,fn:n}]},n.unsubscribe=function(e){for(var t,r=a(e);!(t=r()).done;){var n=t.value;n.objID&&(this.mapCallbacksByObjID[n.objID]=O(this.mapCallbacksByObjID[n.objID],n.fn),this.listCallbacksByObjID[n.objID]=O(this.listCallbacksByObjID[n.objID],n.fn),this.presenceCallbacksByKey[n.objID]=O(this.presenceCallbacksByKey[n.objID],n.fn))}},i(e,[{key:"me",get:function(){return this.actor}}]),e}();function O(e,t){return e?e.filter((function(e){return e!==t})):[]}var R=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(f({authBundle:{strategy:e.authStrategy,ctx:e.authCtx},room:e.room,document:e.document})).then((function(t){return Promise.resolve(b({docsURL:e.docsURL,presenceURL:e.presenceURL,token:t.token,docID:t.docID,roomID:t.roomID})).then((function(r){return new L({actor:t.guestReference,bootstrapState:r,token:t.token,room:e.room,document:e.document,auth:e.authStrategy,authCtx:e.authCtx,wsURL:"wss://super.roomservice.dev/ws",docsURL:n,presenceURL:o,session:t})}))}))}catch(e){return Promise.reject(e)}}({docsURL:n,presenceURL:o,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=L,exports.RoomService=R,exports.default=R; | ||
"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",o="https://super.roomservice.dev/presence";function s(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&&s(e.prototype,t),r&&s(e,r),e}function c(){return(c=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var n in r)Object.prototype.hasOwnProperty.call(r,n)&&(e[n]=r[n])}return e}).apply(this,arguments)}function u(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 a(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 u(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)?u(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 h=function(){function e(){}return e.prototype.then=function(t,r){const n=new e,o=this.s;if(o){const e=1&o?t:r;if(e){try{l(n,1,e(this.v))}catch(e){l(n,2,e)}return n}return this}return this.o=function(e){try{const o=e.v;1&e.s?l(n,1,t?t(o):o):r?l(n,1,r(o)):l(n,2,o)}catch(e){l(n,2,e)}},n},e}();function l(e,t,r){if(!e.s){if(r instanceof h){if(!r.s)return void(r.o=l.bind(null,e,t));1&t&&(t=r.s),r=r.v}if(r&&r.then)return void r.then(l.bind(null,e,t),l.bind(null,e,2));e.s=t,e.v=r;const n=e.o;n&&n(e)}}function d(e){return e instanceof h&&1&e.s}function m(e,t,r){for(var n;;){var o=e();if(d(o)&&(o=o.v),!o)return s;if(o.then){n=0;break}var s=r();if(s&&s.then){if(!d(s)){n=1;break}s=s.s}if(t){var i=t();if(i&&i.then&&!d(i)){n=2;break}}}var c=new h,u=l.bind(null,c,2);return(0===n?o.then(m):1===n?s.then(a):i.then(f)).then(void 0,u),c;function a(n){s=n;do{if(t&&(i=t())&&i.then&&!d(i))return void i.then(f).then(void 0,u);if(!(o=e())||d(o)&&!o.v)return void l(c,1,s);if(o.then)return void o.then(m).then(void 0,u);d(s=r())&&(s=s.v)}while(!s||!s.then);s.then(a).then(void 0,u)}function m(e){e?(s=r())&&s.then?s.then(a).then(void 0,u):a(s):l(c,1,s)}function f(){(o=e())?o.then?o.then(m).then(void 0,u):m(o):l(c,1,s)}}"undefined"!=typeof Symbol&&(Symbol.iterator||(Symbol.iterator=Symbol("Symbol.iterator"))),"undefined"!=typeof Symbol&&(Symbol.asyncIterator||(Symbol.asyncIterator=Symbol("Symbol.asyncIterator")));var f=function(e){try{var t=function(e){return r?e:Promise.resolve(fetch(o,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({resources:[{object:"document",reference:c,permission:"read_write",room:i},{object:"room",reference:i,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}}))}))},r=!1,n=e.authBundle,o=n.strategy,s=n.ctx,i=e.room,c=e.document,u=function(){if("function"==typeof o)return Promise.resolve(o({room:i,ctx:s})).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,n=e.resources.find((function(e){return"room"===e.object})).id;return r=!0,{token:e.token,guestReference:e.user,docID:t,roomID:n}}))}();return Promise.resolve(u&&u.then?u.then(t):t(u))}catch(e){return Promise.reject(e)}},p=function(e,t,r){try{return Promise.resolve(fetch(e+"/"+r,{headers:{Authorization:"Bearer: "+t}})).then((function(e){return Promise.resolve(e.json()).then((function(e){return e.body}))}))}catch(e){return Promise.reject(e)}},v=function(e,t,r){try{return Promise.resolve(fetch(e+"/"+r,{headers:{Authorization:"Bearer: "+t}})).then((function(e){return Promise.resolve(e.json()).then((function(e){for(var t=0,r=Object.keys(e);t<r.length;t++)for(var n=r[t],o=0,s=Object.keys(e[n]);o<s.length;o++){var i=s[o];if("string"==typeof e[n][i].value){var c=void 0;try{c=JSON.parse(e[n][i].value)}catch(e){}c&&(e[n][i].value=c)}}return e}))}))}catch(e){return Promise.reject(e)}},y=function(e){try{return Promise.resolve(Promise.all([v(e.presenceURL,e.token,e.roomID),p(e.docsURL,e.token,e.docID)])).then((function(e){return{presence:e[0],document:e[1]}}))}catch(e){return Promise.reject(e)}};function b(e){return new Promise((function(t){return setTimeout(t,e)}))}var C=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)}},g=["doc:fwd","presence:fwd","room:rm_guest"],I=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.presenceURL=e.presenceURL,this.room=e.room,this.document=e.document,this.authBundle=e.authBundle,this.wsFactory=e.wsFactory||C,this.bootstrapFetch=e.bootstrapFetch||y,this.sessionFetch=e.sessionFetch||f,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=function(){var e=t.session;return Promise.resolve(t.wsFactory(t.wsURL)).then((function(r){return r.onmessage=function(e){var r=JSON.parse(e.data);t.dispatch(r.type,r.body)},r.onclose=function(){return t.close()},Promise.resolve(r).then((function(r){try{return r.send(t.serializeMsg("guest:authenticate",e.token)),Promise.resolve(t.once("guest:authenticated")).then((function(){return r.send(t.serializeMsg("room:join",e.roomID)),Promise.resolve(t.once("room:joined")).then((function(){return Promise.resolve(t.bootstrapFetch({docID:e.docID,roomID:e.roomID,docsURL:t.docsURL,presenceURL:t.presenceURL,token:e.token})).then((function(n){return t.dispatcher.bootstrap(e.guestReference,n),r}))}))}))}catch(e){return Promise.reject(e)}}))}))},t=this,r=function(){if(!t.session)return Promise.resolve(t.sessionFetch({authBundle:t.authBundle,room:t.room,document:t.document})).then((function(e){t.session=e}))}();return Promise.resolve(r&&r.then?r.then(e):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(m((function(){return!t}),void 0,(function(){var n=r*(Math.random()+1)/2;return Promise.resolve(b(n)).then((function(){return r=Math.min(2*r+100,6e4),function(r,n){try{var o=Promise.resolve(e.connectAndAuth()).then((function(r){return e.currentConn=r,e.pendingConn=void 0,t=!0,r}))}catch(e){return n(e)}return o&&o.then?o.then(void 0,n):o}(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=m((function(){return!0}),void 0,(function(){return Promise.resolve(e.conn()).then((function(){return e.processSendQueue(),Promise.resolve(b(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";this.docCmdSendQueue.push(t)}"presence:cmd"==e&&this.presenceCmdSendQueue.set(t.key,t),this.processSendQueue()},t.processSendQueue=function(){if(this.currentConn&&this.session)try{for(;this.presenceCmdSendQueue.size>0;){var e=this.presenceCmdSendQueue.entries().next();if(e){var t=e.value,r=t[0],n=this.serializeMsg("presence:cmd",t[1]);this.currentConn.send(n),this.presenceCmdSendQueue.delete(r)}}for(;this.docCmdSendQueue.length>0;){var o=this.serializeMsg("doc:cmd",this.docCmdSendQueue[0]);this.currentConn.send(o),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);g.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}(),w=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),o=n.store;this.meta=n.meta,this.store=o,e.checkpoint.lists[e.listID]||t(!1),r.ListInterpreter.importFromRawCheckpoint(this.store,this.actor,e.checkpoint,this.meta.listID)}var n=e.prototype;return n.bootstrap=function(e,t){this.actor=e,r.ListInterpreter.importFromRawCheckpoint(this.store,this.actor,t.document,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,t,n){return r.ListInterpreter.validateCommand(this.meta,e),r.ListInterpreter.applyCommand(this.store,e,t,n),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 o,s=r.ListInterpreter.runPush.apply(r.ListInterpreter,[this.store,this.meta].concat(t)),i=a(s);!(o=i()).done;){var c=o.value;this.sendCmd(c)}return this},n.map=function(e){return r.ListInterpreter.map(this.store,e)},n.toArray=function(){return r.ListInterpreter.toArray(this.store)},n.session=function(){return this.store.rt.session},e}(),D=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,t){this.actor=e,r.MapInterpreter.importFromRawCheckpoint(this.store,t.document,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,t,n){return r.MapInterpreter.validateCommand(this.meta,e),r.MapInterpreter.applyCommand(this.store,e,t,n),this.clone()},t.get=function(e){var t;return null===(t=this.store.kv.get(e))||void 0===t?void 0:t.value},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=a(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 Array.from(this.store.kv.keys())}}]),e}(),k=function(){function e(e){var t=this;this.roomID=e.roomID,this.ws=e.ws,this.actor=e.actor,this.key=e.key,this.cache={},this.bus=e.bus,this.sendPres=function(e,t,r){void 0===r&&(r=!1);var n={},o=!0;return function(){var t=arguments,s=this,i=r&&o,c=function(){e.apply(s,t),n[t[0]]=null};i&&(o=!1,c()),n[arguments[0]]||(n[arguments[0]]=setTimeout(c,40))}}((function(e,r){t.ws.send("presence:cmd",r)})),this.bootstrap(this.actor,e.checkpoint)}var t=e.prototype;return t.bootstrap=function(e,t){this.actor=e,this.cache=c({},this.cache,t.presence[this.key]||{})},t.getAll=function(){return this.withoutExpired()},t.getMine=function(){var e;return null===(e=(this.cache||{})[this.actor])||void 0===e?void 0:e.value},t.withoutExpired=function(){var e={};for(var t in this.cache){var r=this.cache[t];new Date>r.expAt?delete this.cache[t]:e[t]=r.value}return e},t.withoutActorOrExpired=function(e){var t={};for(var r in this.cache){var n=this.cache[r];n&&(r===e&&this.cache[r]||new Date>n.expAt?delete this.cache[r]:t[r]=n.value)}return t},t.set=function(e,t){var r=this,n=t||60,o=Math.round((new Date).getTime()/1e3)+n;this.myExpirationHandle&&(clearTimeout(this.myExpirationHandle),this.myExpirationHandle=void 0),this.myExpirationHandle=setTimeout((function(){delete r.cache[r.actor],r.bus.publish({key:r.key,valuesByUser:r.withoutExpired()})}),1e3*n),this.sendPres(this.key,{room:this.roomID,key:this.key,value:JSON.stringify(e),expAt:o}),this.cache[this.actor]={value:e,expAt:new Date(1e3*o)};var s=this.withoutExpired();return this.bus.publish({key:this.key,valuesByUser:s}),s},t.dangerouslyUpdateClientDirectly=function(e,t){if("room:rm_guest"===e)return this.withoutActorOrExpired(t.guest);if("presence:expire"===e)return this.withoutExpired();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.from]=r,this.withoutExpired()},e}(),j=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}(),P=["mcreate","mput","mputref","mdel"],S=["lcreate","lins","linsref","lput","lputref","ldel"],L=function(){function e(e){this.presenceClients={},this.listClients={},this.mapClients={},this.expiresByActorByKey={},this.queueIncomingCmds=!0,this.cmdQueue=[],this.mapCallbacksByObjID={},this.listCallbacksByObjID={},this.presenceCallbacksByKey={},this.ws=new I({dispatcher:this,wsURL:e.wsURL,docsURL:e.docsURL,presenceURL:e.presenceURL,room:e.room,document:e.document,authBundle:{strategy:e.auth,ctx:e.authCtx},sessionFetch:function(t){return Promise.resolve(e.session)}}),this.roomID=e.session.roomID,this.docID=e.bootstrapState.document.id,this.actor=e.actor,this.bootstrapState=e.bootstrapState}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,t){this.actor=e,this.bootstrapState=t;for(var r=0,n=Object.entries(this.listClients);r<n.length;r++)n[r][1].bootstrap(e,t);for(var o=0,s=Object.entries(this.mapClients);o<s.length;o++)s[o][1].bootstrap(e,t);for(var i=0,c=Object.entries(this.presenceClients);i<c.length;i++)c[i][1].bootstrap(e,t);this.queueIncomingCmds=!1;for(var u,h=a(this.cmdQueue);!(u=h()).done;){var l=u.value;this.processCmd(l[0],l[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.isOlderVS(e.vs,this.bootstrapState.document.vs)){var t=[e.args[0],e.args[1],e.args[2]],n=t[0],o=t[2];t[1]===this.docID&&(P.includes(n)?this.dispatchMapCmd(o,e):S.includes(n)?this.dispatchListCmd(o,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=0,r=Object.entries(this.presenceClients);t<r.length;t++){var n=r[t],o=n[0],s=n[1].dangerouslyUpdateClientDirectly("room:rm_guest",e);if(!s)return;for(var i,c=a(this.presenceCallbacksByKey[o]||[]);!(i=c()).done;)(0,i.value)(s,e.guest)}},n.dispatchMapCmd=function(e,t){this.mapClients[e]||this.createMapLocally(e);for(var r,n=this.mapClients[e].dangerouslyUpdateClientDirectly(t.args,t.vs,t.ack),o=a(this.mapCallbacksByObjID[e]||[]);!(r=o()).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,t.vs,t.ack),o=a(this.listCallbacksByObjID[e]||[]);!(r=o()).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=e.key,n=this.presence(r),o=(new Date).getTime()/1e3,s=e.expAt-o;if(!(s<0)){if(s<43200){var i=this.expiresByActorByKey[r]||{},c=e.from;i[c]&&clearTimeout(i[c]);var u=setTimeout((function(){var o=n.dangerouslyUpdateClientDirectly("presence:expire",{key:e.key});if(o)for(var s,i=a(null!==(c=t.presenceCallbacksByKey[r])&&void 0!==c?c:[]);!(s=i()).done;){var c;(0,s.value)(o,e.from)}}),1e3*s);i[c]=u,this.expiresByActorByKey[r]=i}var h=n.dangerouslyUpdateClientDirectly("presence:fwd",e);if(h)for(var l,d=a(null!==(m=this.presenceCallbacksByKey[r])&&void 0!==m?m:[]);!(l=d()).done;){var m;(0,l.value)(h,e.from)}}}},n.createListLocally=function(e){var t=this,r=new j;r.subscribe((function(r){for(var n,o=t.listClients[e],s=a(t.listCallbacksByObjID[e]||[]);!(n=s()).done;)(0,n.value)(o.toArray(),r.from)}));var n=new w({checkpoint:this.bootstrapState.document,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.bootstrapState.document.lists[e]||(this.ws.send("doc:cmd",{args:["lcreate",this.docID,e],room:this.roomID}),this.bootstrapState.document.lists[e]={afters:[],ids:[],values:[]}),this.createListLocally(e))},n.createMapLocally=function(e){var t=this,r=new j;r.subscribe((function(r){for(var n,o=t.mapClients[e],s=a(t.mapCallbacksByObjID[e]||[]);!(n=s()).done;)(0,n.value)(o.toObject(),r.from)}));var n=new D({checkpoint:this.bootstrapState.document,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.bootstrapState.document.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.presenceClients[e])return this.presenceClients[e];var r=new j;r.subscribe((function(e){for(var r,n=a(t.presenceCallbacksByKey[e.key]||[]);!(r=n()).done;)(0,r.value)(e.valuesByUser,t.actor)}));var n=new k({checkpoint:this.bootstrapState,roomID:this.roomID,actor:this.actor,ws:this.ws,key:e,bus:r});try{this.presenceClients[e]=n}catch(e){throw new Error("Don't Freeze State. See more: https://err.sh/getroomservice/browser/dont-freeze")}return this.presenceClients[e]},n.subscribe=function(e,t){if(e instanceof k)return this.subscribePresence(e,t);var r,n=function(e,r){t(e,r)};return e instanceof D&&(this.mapCallbacksByObjID[r=e.id]=this.mapCallbacksByObjID[r]||[],this.mapCallbacksByObjID[r].push(n)),e instanceof w&&(this.listCallbacksByObjID[r=e.id]=this.listCallbacksByObjID[r]||[],this.listCallbacksByObjID[r].push(n)),[{objID:r,fn:n}]},n.subscribePresence=function(e,r){e||t(!1);var n=function(e,t){r&&r(e,t)},o=e.key;return this.presenceCallbacksByKey[o]=this.presenceCallbacksByKey[o]||[],this.presenceCallbacksByKey[o].push(n),[{objID:o,fn:n}]},n.unsubscribe=function(e){for(var t,r=a(e);!(t=r()).done;){var n=t.value;n.objID&&(this.mapCallbacksByObjID[n.objID]=O(this.mapCallbacksByObjID[n.objID],n.fn),this.listCallbacksByObjID[n.objID]=O(this.listCallbacksByObjID[n.objID],n.fn),this.presenceCallbacksByKey[n.objID]=O(this.presenceCallbacksByKey[n.objID],n.fn))}},i(e,[{key:"me",get:function(){return this.actor}}]),e}();function O(e,t){return e?e.filter((function(e){return e!==t})):[]}var x=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(f({authBundle:{strategy:e.authStrategy,ctx:e.authCtx},room:e.room,document:e.document})).then((function(t){return Promise.resolve(y({docsURL:e.docsURL,presenceURL:e.presenceURL,token:t.token,docID:t.docID,roomID:t.roomID})).then((function(r){return new L({actor:t.guestReference,bootstrapState:r,token:t.token,room:e.room,document:e.document,auth:e.authStrategy,authCtx:e.authCtx,wsURL:"wss://super.roomservice.dev/ws",docsURL:n,presenceURL:o,session:t})}))}))}catch(e){return Promise.reject(e)}}({docsURL:n,presenceURL:o,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=L,exports.RoomService=x,exports.default=x; | ||
//# sourceMappingURL=browser.cjs.production.min.js.map |
import invariant from 'tiny-invariant'; | ||
import { ListInterpreter, MapInterpreter, vsReader } from '@roomservice/core'; | ||
import { ListInterpreter, MapInterpreter, isOlderVS } from '@roomservice/core'; | ||
@@ -758,3 +758,3 @@ // export const WS_URL = 'ws://localhost:3452'; | ||
var _ListInterpreter$newL = ListInterpreter.newList(props.docID, props.listID, props.actor), | ||
var _ListInterpreter$newL = ListInterpreter.newList(props.docID, props.listID), | ||
meta = _ListInterpreter$newL.meta, | ||
@@ -792,5 +792,5 @@ store = _ListInterpreter$newL.store; | ||
_proto.dangerouslyUpdateClientDirectly = function dangerouslyUpdateClientDirectly(cmd) { | ||
_proto.dangerouslyUpdateClientDirectly = function dangerouslyUpdateClientDirectly(cmd, versionstamp, ack) { | ||
ListInterpreter.validateCommand(this.meta, cmd); | ||
ListInterpreter.applyCommand(this.store, cmd); | ||
ListInterpreter.applyCommand(this.store, cmd, versionstamp, ack); | ||
return this.clone(); | ||
@@ -854,2 +854,7 @@ }; | ||
return ListInterpreter.toArray(this.store); | ||
} // exposed for testing | ||
; | ||
_proto.session = function session() { | ||
return this.store.rt.session; | ||
}; | ||
@@ -899,5 +904,5 @@ | ||
_proto.dangerouslyUpdateClientDirectly = function dangerouslyUpdateClientDirectly(cmd) { | ||
_proto.dangerouslyUpdateClientDirectly = function dangerouslyUpdateClientDirectly(cmd, versionstamp, ack) { | ||
MapInterpreter.validateCommand(this.meta, cmd); | ||
MapInterpreter.applyCommand(this.store, cmd); | ||
MapInterpreter.applyCommand(this.store, cmd, versionstamp, ack); | ||
return this.clone(); | ||
@@ -907,3 +912,5 @@ }; | ||
_proto.get = function get(key) { | ||
return this.store[key]; | ||
var _this$store$kv$get; | ||
return (_this$store$kv$get = this.store.kv.get(key)) === null || _this$store$kv$get === void 0 ? void 0 : _this$store$kv$get.value; | ||
}; | ||
@@ -944,3 +951,3 @@ | ||
get: function get() { | ||
return Object.keys(this.store); | ||
return Array.from(this.store.kv.keys()); | ||
} | ||
@@ -1077,5 +1084,22 @@ }]); | ||
_proto.set = function set(value, exp) { | ||
var _this2 = this; | ||
var addition = exp ? exp : 60; // Convert to unix + add seconds | ||
var expAt = Math.round(new Date().getTime() / 1000) + addition; | ||
if (this.myExpirationHandle) { | ||
clearTimeout(this.myExpirationHandle); | ||
this.myExpirationHandle = undefined; | ||
} | ||
this.myExpirationHandle = setTimeout(function () { | ||
// TODO: this should be revisited when presence ACKs are added | ||
delete _this2.cache[_this2.actor]; | ||
_this2.bus.publish({ | ||
key: _this2.key, | ||
valuesByUser: _this2.withoutExpired() | ||
}); | ||
}, addition * 1000); | ||
this.sendPres(this.key, { | ||
@@ -1109,5 +1133,6 @@ room: this.roomID, | ||
if (body.room !== this.roomID) return false; | ||
if (body.from === this.actor) return false; // ignore validation msgs | ||
if (body.room !== this.roomID) return false; // ignore validation msgs | ||
// TODO: use same ack logic as doc cmds | ||
if (body.from === this.actor) return false; | ||
var obj = { | ||
@@ -1209,3 +1234,3 @@ expAt: new Date(body.expAt * 1000), | ||
this.mapClients = {}; | ||
this.expires = {}; | ||
this.expiresByActorByKey = {}; | ||
this.queueIncomingCmds = true; | ||
@@ -1320,9 +1345,4 @@ this.cmdQueue = []; | ||
if (vsReader(atob).isOlderVS(body.vs, this.bootstrapState.document.vs)) { | ||
if (isOlderVS(body.vs, this.bootstrapState.document.vs)) { | ||
return; | ||
} // Ignore validated commands | ||
if (body.from === this.actor) { | ||
return; | ||
} | ||
@@ -1368,3 +1388,3 @@ | ||
var client = this.mapClients[objID]; | ||
var updatedClient = client.dangerouslyUpdateClientDirectly(body.args); | ||
var updatedClient = client.dangerouslyUpdateClientDirectly(body.args, body.vs, body.ack); | ||
@@ -1383,3 +1403,3 @@ for (var _iterator3 = _createForOfIteratorHelperLoose(this.mapCallbacksByObjID[objID] || []), _step3; !(_step3 = _iterator3()).done;) { | ||
var client = this.listClients[objID]; | ||
var updatedClient = client.dangerouslyUpdateClientDirectly(body.args); | ||
var updatedClient = client.dangerouslyUpdateClientDirectly(body.args, body.vs, body.ack); | ||
@@ -1395,3 +1415,4 @@ for (var _iterator4 = _createForOfIteratorHelperLoose(this.listCallbacksByObjID[objID] || []), _step4; !(_step4 = _iterator4()).done;) { | ||
if (body.room !== this.roomID) return; | ||
if (body.room !== this.roomID) return; // TODO: use same ack logic as doc cmds | ||
if (body.from === this.actor) return; | ||
@@ -1410,4 +1431,7 @@ var key = body.key; | ||
if (secondsTillTimeout < 60 * 60 * 12) { | ||
if (this.expires[key]) { | ||
clearTimeout(this.expires[key]); | ||
var expiresByActor = this.expiresByActorByKey[key] || {}; | ||
var actor = body.from; | ||
if (expiresByActor[actor]) { | ||
clearTimeout(expiresByActor[actor]); | ||
} | ||
@@ -1428,3 +1452,4 @@ | ||
}, secondsTillTimeout * 1000); | ||
this.expires[key] = timeout; | ||
expiresByActor[actor] = timeout; | ||
this.expiresByActorByKey[key] = expiresByActor; | ||
} | ||
@@ -1431,0 +1456,0 @@ |
@@ -29,3 +29,3 @@ import { SuperlumeSend } from './ws'; | ||
private clone; | ||
dangerouslyUpdateClientDirectly(cmd: string[]): InnerListClient<T>; | ||
dangerouslyUpdateClientDirectly(cmd: string[], versionstamp: string, ack: boolean): InnerListClient<T>; | ||
get<K extends number>(index: K): T[K] | undefined; | ||
@@ -39,2 +39,3 @@ set<K extends number>(index: K, val: T[K]): InnerListClient<T>; | ||
toArray(): T[number][]; | ||
session(): string; | ||
} |
@@ -32,5 +32,5 @@ import { ObjectClient } from './types'; | ||
private clone; | ||
dangerouslyUpdateClientDirectly(cmd: string[]): InnerMapClient<T>; | ||
dangerouslyUpdateClientDirectly(cmd: string[], versionstamp: string, ack: boolean): InnerMapClient<T>; | ||
get keys(): string[]; | ||
get<K extends keyof T>(key: K): T[K]; | ||
get<K extends keyof T>(key: K): T[K] | undefined; | ||
set<K extends keyof T>(key: K, value: T[K]): InnerMapClient<T>; | ||
@@ -37,0 +37,0 @@ toObject(): T; |
@@ -43,2 +43,3 @@ import { SuperlumeSend } from './ws'; | ||
private withoutActorOrExpired; | ||
private myExpirationHandle?; | ||
/** | ||
@@ -45,0 +46,0 @@ * @param value Any arbitrary object, string, boolean, or number. |
@@ -25,3 +25,3 @@ import { ForwardedMessageBody, WebsocketDispatch } from './ws'; | ||
private mapClients; | ||
private expires; | ||
private expiresByActorByKey; | ||
private ws; | ||
@@ -28,0 +28,0 @@ constructor(params: { |
@@ -93,3 +93,3 @@ import { ReverseTree } from '@roomservice/core/dist/ReverseTree'; | ||
id: string; | ||
dangerouslyUpdateClientDirectly(msg: any): ObjectClient; | ||
dangerouslyUpdateClientDirectly(msg: any, versionstamp: string, ack: boolean): ObjectClient; | ||
} | ||
@@ -96,0 +96,0 @@ export interface Resource { |
@@ -40,2 +40,3 @@ export interface WebSocketAuthenticateMessage { | ||
args: string[]; | ||
ack: boolean; | ||
}; | ||
@@ -42,0 +43,0 @@ } |
{ | ||
"version": "3.0.0", | ||
"version": "3.0.1-0", | ||
"license": "MIT", | ||
@@ -43,5 +43,5 @@ "main": "dist/index.js", | ||
"dependencies": { | ||
"@roomservice/core": "0.3.1", | ||
"@roomservice/core": "0.3.2", | ||
"tiny-invariant": "^1.1.0" | ||
} | ||
} |
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
SPDX disjunction
LicenseSPDX disjunction for an artifact's license information
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
SPDX disjunction
LicenseSPDX disjunction for an artifact's license information
Found 1 instance in 1 package
455489
3527
3
+ Added@roomservice/core@0.3.2(transitive)
- Removed@roomservice/core@0.3.1(transitive)
Updated@roomservice/core@0.3.2