@graffiti-garden/wrapper-synchronize 0.2.2 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import{c as v,d as w,e as S}from"./chunk-POQWWD2G.js";v();S();w();v();S();w();var W=class{},se={type:"object",properties:{value:{type:"object"},channels:{type:"array",items:{type:"string"}},allowed:{type:"array",items:{type:"string"},nullable:!0},url:{type:"string"},actor:{type:"string"},lastModified:{type:"number"}},additionalProperties:!1,required:["value","channels","actor","url","lastModified"]},be={...se,required:["value","channels"]};var L=class H extends Error{constructor(r){super(r),this.name="GraffitiErrorInvalidSchema",Object.setPrototypeOf(this,H.prototype)}};var Q=class X extends Error{constructor(r){super(r),this.name="GraffitiErrorPatchTestFailed",Object.setPrototypeOf(this,X.prototype)}},$=class K extends Error{constructor(r){super(r),this.name="GraffitiErrorPatchError",Object.setPrototypeOf(this,K.prototype)}};v();S();w();var F=function(t,r){return F=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,n){e.__proto__=n}||function(e,n){for(var o in n)n.hasOwnProperty(o)&&(e[o]=n[o])},F(t,r)};function ce(t,r){F(t,r);function e(){this.constructor=t}t.prototype=r===null?Object.create(r):(e.prototype=r.prototype,new e)}function x(t,r,e,n){function o(i){return i instanceof e?i:new e(function(c){c(i)})}return new(e||(e=Promise))(function(i,c){function f(u){try{a(n.next(u))}catch(d){c(d)}}function l(u){try{a(n.throw(u))}catch(d){c(d)}}function a(u){u.done?i(u.value):o(u.value).then(f,l)}a((n=n.apply(t,r||[])).next())})}function O(t,r){var e={label:0,sent:function(){if(i[0]&1)throw i[1];return i[1]},trys:[],ops:[]},n,o,i,c;return c={next:f(0),throw:f(1),return:f(2)},typeof Symbol=="function"&&(c[Symbol.iterator]=function(){return this}),c;function f(a){return function(u){return l([a,u])}}function l(a){if(n)throw new TypeError("Generator is already executing.");for(;e;)try{if(n=1,o&&(i=a[0]&2?o.return:a[0]?o.throw||((i=o.return)&&i.call(o),0):o.next)&&!(i=i.call(o,a[1])).done)return i;switch(o=0,i&&(a=[a[0]&2,i.value]),a[0]){case 0:case 1:i=a;break;case 4:return e.label++,{value:a[1],done:!1};case 5:e.label++,o=a[1],a=[0];continue;case 7:a=e.ops.pop(),e.trys.pop();continue;default:if(i=e.trys,!(i=i.length>0&&i[i.length-1])&&(a[0]===6||a[0]===2)){e=0;continue}if(a[0]===3&&(!i||a[1]>i[0]&&a[1]<i[3])){e.label=a[1];break}if(a[0]===6&&e.label<i[1]){e.label=i[1],i=a;break}if(i&&e.label<i[2]){e.label=i[2],e.ops.push(a);break}i[2]&&e.ops.pop(),e.trys.pop();continue}a=r.call(t,e)}catch(u){a=[6,u],o=0}finally{n=i=0}if(a[0]&5)throw a[1];return{value:a[0]?a[1]:void 0,done:!0}}}function P(t){var r=typeof Symbol=="function"&&Symbol.iterator,e=r&&t[r],n=0;if(e)return e.call(t);if(t&&typeof t.length=="number")return{next:function(){return t&&n>=t.length&&(t=void 0),{value:t&&t[n++],done:!t}}};throw new TypeError(r?"Object is not iterable.":"Symbol.iterator is not defined.")}function C(t){return this instanceof C?(this.v=t,this):new C(t)}function fe(t,r,e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var n=e.apply(t,r||[]),o,i=[];return o={},c("next"),c("throw"),c("return"),o[Symbol.asyncIterator]=function(){return this},o;function c(s){n[s]&&(o[s]=function(h){return new Promise(function(p,y){i.push([s,h,p,y])>1||f(s,h)})})}function f(s,h){try{l(n[s](h))}catch(p){d(i[0][3],p)}}function l(s){s.value instanceof C?Promise.resolve(s.value.v).then(a,u):d(i[0][2],s)}function a(s){f("next",s)}function u(s){f("throw",s)}function d(s,h){s(h),i.shift(),i.length&&f(i[0][0],i[0][1])}}var ee=function(t){ce(r,t);function r(e){var n=t.call(this,e)||this;return Object.defineProperty(n,"name",{value:"RepeaterOverflowError",enumerable:!1}),typeof Object.setPrototypeOf=="function"?Object.setPrototypeOf(n,n.constructor.prototype):n.__proto__=n.constructor.prototype,typeof Error.captureStackTrace=="function"&&Error.captureStackTrace(n,n.constructor),n}return r}(Error),je=function(){function t(r){if(r<0)throw new RangeError("Capacity may not be less than 0");this._c=r,this._q=[]}return Object.defineProperty(t.prototype,"empty",{get:function(){return this._q.length===0},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"full",{get:function(){return this._q.length>=this._c},enumerable:!1,configurable:!0}),t.prototype.add=function(r){if(this.full)throw new Error("Buffer full");this._q.push(r)},t.prototype.remove=function(){if(this.empty)throw new Error("Buffer empty");return this._q.shift()},t}(),Ge=function(){function t(r){if(r<1)throw new RangeError("Capacity may not be less than 1");this._c=r,this._q=[]}return Object.defineProperty(t.prototype,"empty",{get:function(){return this._q.length===0},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"full",{get:function(){return!1},enumerable:!1,configurable:!0}),t.prototype.add=function(r){for(;this._q.length>=this._c;)this._q.shift();this._q.push(r)},t.prototype.remove=function(){if(this.empty)throw new Error("Buffer empty");return this._q.shift()},t}(),xe=function(){function t(r){if(r<1)throw new RangeError("Capacity may not be less than 1");this._c=r,this._q=[]}return Object.defineProperty(t.prototype,"empty",{get:function(){return this._q.length===0},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"full",{get:function(){return!1},enumerable:!1,configurable:!0}),t.prototype.add=function(r){this._q.length<this._c&&this._q.push(r)},t.prototype.remove=function(){if(this.empty)throw new Error("Buffer empty");return this._q.shift()},t}();function J(t){t!=null&&typeof t.then=="function"&&t.then(N,N)}var _=0,Y=1,j=2,q=3,M=4,B=1024,N=function(){};function G(t){var r=t.err,e=Promise.resolve(t.execution).then(function(n){if(r!=null)throw r;return n});return t.err=void 0,t.execution=e.then(function(){},function(){}),t.pending===void 0?e:t.pending.then(function(){return e})}function g(t,r){var e=t.state>=q;return Promise.resolve(r).then(function(n){return!e&&t.state>=M?G(t).then(function(o){return{value:o,done:!0}}):{value:n,done:e}})}function V(t,r){var e,n;if(!(t.state>=j))if(t.state=j,t.onnext(),t.onstop(),t.err==null&&(t.err=r),t.pushes.length===0&&(typeof t.buffer>"u"||t.buffer.empty))z(t);else try{for(var o=P(t.pushes),i=o.next();!i.done;i=o.next()){var c=i.value;c.resolve()}}catch(f){e={error:f}}finally{try{i&&!i.done&&(n=o.return)&&n.call(o)}finally{if(e)throw e.error}}}function z(t){var r,e;if(!(t.state>=q)){t.state<j&&V(t),t.state=q,t.buffer=void 0;try{for(var n=P(t.nexts),o=n.next();!o.done;o=n.next()){var i=o.value,c=t.pending===void 0?G(t):t.pending.then(function(){return G(t)});i.resolve(g(t,c))}}catch(f){r={error:f}}finally{try{o&&!o.done&&(e=n.return)&&e.call(n)}finally{if(r)throw r.error}}t.pushes=[],t.nexts=[]}}function Z(t){t.state>=M||(t.state<q&&z(t),t.state=M)}function ue(t,r){if(J(r),t.pushes.length>=B)throw new ee("No more than "+B+" pending calls to push are allowed on a single repeater.");if(t.state>=j)return Promise.resolve(void 0);var e=t.pending===void 0?Promise.resolve(r):t.pending.then(function(){return r});e=e.catch(function(l){t.state<j&&(t.err=l),Z(t)});var n;if(t.nexts.length){var o=t.nexts.shift();o.resolve(g(t,e)),t.nexts.length?n=Promise.resolve(t.nexts[0].value):typeof t.buffer<"u"&&!t.buffer.full?n=Promise.resolve(void 0):n=new Promise(function(l){return t.onnext=l})}else typeof t.buffer<"u"&&!t.buffer.full?(t.buffer.add(e),n=Promise.resolve(void 0)):n=new Promise(function(l){return t.pushes.push({resolve:l,value:e})});var i=!0,c={},f=n.catch(function(l){if(i)throw l});return c.then=function(l,a){return i=!1,Promise.prototype.then.call(n,l,a)},c.catch=function(l){return i=!1,Promise.prototype.catch.call(n,l)},c.finally=n.finally.bind(n),t.pending=e.then(function(){return f}).catch(function(l){t.err=l,Z(t)}),c}function le(t){var r=V.bind(null,t),e=new Promise(function(n){return t.onstop=n});return r.then=e.then.bind(e),r.catch=e.catch.bind(e),r.finally=e.finally.bind(e),r}function he(t){if(!(t.state>=Y)){t.state=Y;var r=ue.bind(null,t),e=le(t);t.execution=new Promise(function(n){return n(t.executor(r,e))}),t.execution.catch(function(){return V(t)})}}var I=new WeakMap,E=function(){function t(r,e){I.set(this,{executor:r,buffer:e,err:void 0,state:_,pushes:[],nexts:[],pending:void 0,execution:void 0,onnext:N,onstop:N})}return t.prototype.next=function(r){J(r);var e=I.get(this);if(e===void 0)throw new Error("WeakMap error");if(e.nexts.length>=B)throw new ee("No more than "+B+" pending calls to next are allowed on a single repeater.");if(e.state<=_&&he(e),e.onnext(r),typeof e.buffer<"u"&&!e.buffer.empty){var n=g(e,e.buffer.remove());if(e.pushes.length){var o=e.pushes.shift();e.buffer.add(o.value),e.onnext=o.resolve}return n}else if(e.pushes.length){var i=e.pushes.shift();return e.onnext=i.resolve,g(e,i.value)}else if(e.state>=j)return z(e),g(e,G(e));return new Promise(function(c){return e.nexts.push({resolve:c,value:r})})},t.prototype.return=function(r){J(r);var e=I.get(this);if(e===void 0)throw new Error("WeakMap error");return z(e),e.execution=Promise.resolve(e.execution).then(function(){return r}),g(e,G(e))},t.prototype.throw=function(r){var e=I.get(this);if(e===void 0)throw new Error("WeakMap error");return e.state<=_||e.state>=j||typeof e.buffer<"u"&&!e.buffer.empty?(z(e),e.err==null&&(e.err=r),g(e,G(e))):this.next(Promise.reject(r))},t.prototype[Symbol.asyncIterator]=function(){return this},t.race=pe,t.merge=de,t.zip=ye,t.latest=me,t}();function T(t,r){var e,n,o=[],i=function(a){a!=null&&typeof a[Symbol.asyncIterator]=="function"?o.push(a[Symbol.asyncIterator]()):a!=null&&typeof a[Symbol.iterator]=="function"?o.push(a[Symbol.iterator]()):o.push(function(){return fe(this,arguments,function(){return O(this,function(s){switch(s.label){case 0:return r.yieldValues?[4,C(a)]:[3,3];case 1:return[4,s.sent()];case 2:s.sent(),s.label=3;case 3:return r.returnValues?[4,C(a)]:[3,5];case 4:return[2,s.sent()];case 5:return[2]}})})}())};try{for(var c=P(t),f=c.next();!f.done;f=c.next()){var l=f.value;i(l)}}catch(a){e={error:a}}finally{try{f&&!f.done&&(n=c.return)&&n.call(c)}finally{if(e)throw e.error}}return o}function pe(t){var r=this,e=T(t,{returnValues:!0});return new E(function(n,o){return x(r,void 0,void 0,function(){var i,c,f,l,a,u;return O(this,function(d){switch(d.label){case 0:if(!e.length)return o(),[2];c=!1,o.then(function(){i(),c=!0}),d.label=1;case 1:d.trys.push([1,,5,7]),l=void 0,a=0,u=function(){var s,h,p,y,m,k;return O(this,function(A){switch(A.label){case 0:s=a;try{for(h=(m=void 0,P(e)),p=h.next();!p.done;p=h.next())y=p.value,Promise.resolve(y.next()).then(function(b){b.done?(o(),f===void 0&&(f=b)):a===s&&(a++,i(b))},function(b){return o(b)})}catch(b){m={error:b}}finally{try{p&&!p.done&&(k=h.return)&&k.call(h)}finally{if(m)throw m.error}}return[4,new Promise(function(b){return i=b})];case 1:return l=A.sent(),l===void 0?[3,3]:[4,n(l.value)];case 2:A.sent(),A.label=3;case 3:return[2]}})},d.label=2;case 2:return c?[3,4]:[5,u()];case 3:return d.sent(),[3,2];case 4:return[2,f&&f.value];case 5:return o(),[4,Promise.race(e.map(function(s){return s.return&&s.return()}))];case 6:return d.sent(),[7];case 7:return[2]}})})})}function de(t){var r=this,e=T(t,{yieldValues:!0});return new E(function(n,o){return x(r,void 0,void 0,function(){var i,c,f,l=this;return O(this,function(a){switch(a.label){case 0:if(!e.length)return o(),[2];i=[],c=!1,o.then(function(){var u,d;c=!0;try{for(var s=P(i),h=s.next();!h.done;h=s.next()){var p=h.value;p()}}catch(y){u={error:y}}finally{try{h&&!h.done&&(d=s.return)&&d.call(s)}finally{if(u)throw u.error}}}),a.label=1;case 1:return a.trys.push([1,,3,4]),[4,Promise.all(e.map(function(u,d){return x(l,void 0,void 0,function(){var s,h;return O(this,function(p){switch(p.label){case 0:p.trys.push([0,,6,9]),p.label=1;case 1:return c?[3,5]:(Promise.resolve(u.next()).then(function(y){return i[d](y)},function(y){return o(y)}),[4,new Promise(function(y){i[d]=y})]);case 2:return s=p.sent(),s===void 0?[3,4]:s.done?(f=s,[2]):[4,n(s.value)];case 3:p.sent(),p.label=4;case 4:return[3,1];case 5:return[3,9];case 6:return h=u.return,h?[4,u.return()]:[3,8];case 7:h=p.sent(),p.label=8;case 8:return[7];case 9:return[2]}})})}))];case 2:return a.sent(),[2,f&&f.value];case 3:return o(),[7];case 4:return[2]}})})})}function ye(t){var r=this,e=T(t,{returnValues:!0});return new E(function(n,o){return x(r,void 0,void 0,function(){var i,c,f,l;return O(this,function(a){switch(a.label){case 0:if(!e.length)return o(),[2,[]];c=!1,o.then(function(){i(),c=!0}),a.label=1;case 1:a.trys.push([1,,6,8]),a.label=2;case 2:return c?[3,5]:(Promise.all(e.map(function(u){return u.next()})).then(function(u){return i(u)},function(u){return o(u)}),[4,new Promise(function(u){return i=u})]);case 3:return f=a.sent(),f===void 0?[2]:(l=f.map(function(u){return u.value}),f.some(function(u){return u.done})?[2,l]:[4,n(l)]);case 4:return a.sent(),[3,2];case 5:return[3,8];case 6:return o(),[4,Promise.all(e.map(function(u){return u.return&&u.return()}))];case 7:return a.sent(),[7];case 8:return[2]}})})})}function me(t){var r=this,e=T(t,{yieldValues:!0,returnValues:!0});return new E(function(n,o){return x(r,void 0,void 0,function(){var i,c,f,l,a,u=this;return O(this,function(d){switch(d.label){case 0:if(!e.length)return o(),[2,[]];c=[],f=!1,o.then(function(){var s,h;i();try{for(var p=P(c),y=p.next();!y.done;y=p.next()){var m=y.value;m()}}catch(k){s={error:k}}finally{try{y&&!y.done&&(h=p.return)&&h.call(p)}finally{if(s)throw s.error}}f=!0}),d.label=1;case 1:return d.trys.push([1,,5,7]),Promise.all(e.map(function(s){return s.next()})).then(function(s){return i(s)},function(s){return o(s)}),[4,new Promise(function(s){return i=s})];case 2:return l=d.sent(),l===void 0?[2]:(a=l.map(function(s){return s.value}),l.every(function(s){return s.done})?[2,a]:[4,n(a.slice())]);case 3:return d.sent(),[4,Promise.all(e.map(function(s,h){return x(u,void 0,void 0,function(){var p;return O(this,function(y){switch(y.label){case 0:if(l[h].done)return[2,l[h].value];y.label=1;case 1:return f?[3,4]:(Promise.resolve(s.next()).then(function(m){return c[h](m)},function(m){return o(m)}),[4,new Promise(function(m){return c[h]=m})]);case 2:return p=y.sent(),p===void 0?[2,l[h].value]:p.done?[2,p.value]:(a[h]=p.value,[4,n(a.slice())]);case 3:return y.sent(),[3,1];case 4:return[2]}})})}))];case 4:return[2,d.sent()];case 5:return o(),[4,Promise.all(e.map(function(s){return s.return&&s.return()}))];case 6:return d.sent(),[7];case 7:return[2]}})})})}v();S();w();function te(t){return typeof t=="string"?t:t.url}function re(t,r,e,n){let o=e[r];if(!(!o||!o.length))try{n[r]=t(n[r],o,!0,!1).newDocument}catch(i){throw typeof i=="object"&&i&&"name"in i&&typeof i.name=="string"&&"message"in i&&typeof i.message=="string"?i.name==="TEST_OPERATION_FAILED"?new Q(i.message):new $(i.name+": "+i.message):i}}function ne(t,r){try{return t.compile(r)}catch(e){throw new L(e instanceof Error?e.message:void 0)}}function ie(t,r,e){t.actor!==e?.actor&&(t.allowed=t.allowed&&e?[e.actor]:void 0,t.channels=t.channels.filter(n=>r.includes(n)))}function oe(t,r){return t.allowed===void 0||t.allowed===null||!!r?.actor&&(t.actor===r.actor||t.allowed.includes(r.actor))}var ae=class extends W{ajv_;applyPatch_;graffiti;callbacks=new Set;options;channelStats;login;logout;sessionEvents;get ajv(){return this.ajv_||(this.ajv_=(async()=>{let{default:r}=await import("./ajv-65NGXB2O.js");return new r({strict:!1})})()),this.ajv_}get applyPatch(){return this.applyPatch_||(this.applyPatch_=(async()=>{let{applyPatch:r}=await import("./fast-json-patch-RVBYS6DB.js");return r})()),this.applyPatch_}constructor(r,e){super(),this.options=e??{},this.graffiti=r,this.channelStats=r.channelStats.bind(r),this.login=r.login.bind(r),this.logout=r.logout.bind(r),this.sessionEvents=r.sessionEvents}synchronize(r,e,n,o){let i=new Set;return new E(async(f,l)=>{let a=ne(await this.ajv,n),u=(d,s)=>{for(let h of[s,d])if(h?.tombstone)i.has(h.object.url)&&f(h);else if(h&&r(h.object)&&(this.options.omniscient||oe(h.object,o))){let p={...h.object};if(this.options.omniscient||ie(p,e,o),a(p)){f({object:p}),i.add(p.url);break}}};this.callbacks.add(u),await l,this.callbacks.delete(u)})}synchronizeDiscover(...r){let[e,n,o]=r;function i(c){return c.channels.some(f=>e.includes(f))}return this.synchronize(i,e,n,o)}synchronizeGet(...r){let[e,n,o]=r,i=te(e);function c(f){return f.url===i}return this.synchronize(c,[],n,o)}synchronizeRecoverOrphans(...r){let[e,n]=r;function o(i){return i.actor===n.actor&&i.channels.length===0}return this.synchronize(o,[],e,n)}synchronizeAll(r,e){return this.synchronize(()=>!0,[],r,e)}async synchronizeDispatch(r,e,n=!1){for(let o of this.callbacks)o(r,e);n&&await new Promise(o=>setTimeout(o,0))}get=async(...r)=>{let e=await this.graffiti.get(...r);return this.synchronizeDispatch({object:e}),e};put=async(...r)=>{let e=await this.graffiti.put(...r),n=r[0],o={...e,value:n.value,channels:n.channels,allowed:n.allowed};return await this.synchronizeDispatch({tombstone:!0,object:e},{object:o},!0),e};patch=async(...r)=>{let e=await this.graffiti.patch(...r),n={...e};for(let o of["value","channels","allowed"])re(await this.applyPatch,o,r[0],n);return await this.synchronizeDispatch({tombstone:!0,object:e},{object:n},!0),e};delete=async(...r)=>{let e=await this.graffiti.delete(...r);return await this.synchronizeDispatch({tombstone:!0,object:e},void 0,!0),e};objectStreamContinue(r){let e=this;return async function*(){for(;;){let n=await r.next();if(n.done){let{continue:o,cursor:i}=n.value;return{continue:()=>e.objectStreamContinue(o()),cursor:i}}n.value.error||e.synchronizeDispatch(n.value),yield n.value}}()}objectStream(r){let e=this.objectStreamContinue(r);return async function*(){for(;;){let n=await e.next();if(n.done)return n.value;(n.value.error||!n.value.tombstone)&&(yield n.value)}}()}discover=(...r)=>{let e=this.graffiti.discover(...r);return this.objectStream(e)};recoverOrphans=(...r)=>{let e=this.graffiti.recoverOrphans(...r);return this.objectStream(e)};continueObjectStream=(...r)=>this.graffiti.continueObjectStream(...r)};export{ae as GraffitiSynchronize};
1
+ import{c as v,d as w,e as S}from"./chunk-POQWWD2G.js";v();S();w();v();S();w();var W=class{},se={type:"object",properties:{value:{type:"object"},channels:{type:"array",items:{type:"string"}},allowed:{type:"array",items:{type:"string"},nullable:!0},url:{type:"string"},actor:{type:"string"},lastModified:{type:"number"}},additionalProperties:!1,required:["value","channels","actor","url","lastModified"]},be={...se,required:["value","channels"]};var L=class H extends Error{constructor(r){super(r),this.name="GraffitiErrorInvalidSchema",Object.setPrototypeOf(this,H.prototype)}};var Q=class X extends Error{constructor(r){super(r),this.name="GraffitiErrorPatchTestFailed",Object.setPrototypeOf(this,X.prototype)}},$=class K extends Error{constructor(r){super(r),this.name="GraffitiErrorPatchError",Object.setPrototypeOf(this,K.prototype)}};v();S();w();var _=function(t,r){return _=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,n){e.__proto__=n}||function(e,n){for(var o in n)n.hasOwnProperty(o)&&(e[o]=n[o])},_(t,r)};function ce(t,r){_(t,r);function e(){this.constructor=t}t.prototype=r===null?Object.create(r):(e.prototype=r.prototype,new e)}function x(t,r,e,n){function o(i){return i instanceof e?i:new e(function(c){c(i)})}return new(e||(e=Promise))(function(i,c){function f(u){try{a(n.next(u))}catch(d){c(d)}}function l(u){try{a(n.throw(u))}catch(d){c(d)}}function a(u){u.done?i(u.value):o(u.value).then(f,l)}a((n=n.apply(t,r||[])).next())})}function O(t,r){var e={label:0,sent:function(){if(i[0]&1)throw i[1];return i[1]},trys:[],ops:[]},n,o,i,c;return c={next:f(0),throw:f(1),return:f(2)},typeof Symbol=="function"&&(c[Symbol.iterator]=function(){return this}),c;function f(a){return function(u){return l([a,u])}}function l(a){if(n)throw new TypeError("Generator is already executing.");for(;e;)try{if(n=1,o&&(i=a[0]&2?o.return:a[0]?o.throw||((i=o.return)&&i.call(o),0):o.next)&&!(i=i.call(o,a[1])).done)return i;switch(o=0,i&&(a=[a[0]&2,i.value]),a[0]){case 0:case 1:i=a;break;case 4:return e.label++,{value:a[1],done:!1};case 5:e.label++,o=a[1],a=[0];continue;case 7:a=e.ops.pop(),e.trys.pop();continue;default:if(i=e.trys,!(i=i.length>0&&i[i.length-1])&&(a[0]===6||a[0]===2)){e=0;continue}if(a[0]===3&&(!i||a[1]>i[0]&&a[1]<i[3])){e.label=a[1];break}if(a[0]===6&&e.label<i[1]){e.label=i[1],i=a;break}if(i&&e.label<i[2]){e.label=i[2],e.ops.push(a);break}i[2]&&e.ops.pop(),e.trys.pop();continue}a=r.call(t,e)}catch(u){a=[6,u],o=0}finally{n=i=0}if(a[0]&5)throw a[1];return{value:a[0]?a[1]:void 0,done:!0}}}function P(t){var r=typeof Symbol=="function"&&Symbol.iterator,e=r&&t[r],n=0;if(e)return e.call(t);if(t&&typeof t.length=="number")return{next:function(){return t&&n>=t.length&&(t=void 0),{value:t&&t[n++],done:!t}}};throw new TypeError(r?"Object is not iterable.":"Symbol.iterator is not defined.")}function C(t){return this instanceof C?(this.v=t,this):new C(t)}function fe(t,r,e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var n=e.apply(t,r||[]),o,i=[];return o={},c("next"),c("throw"),c("return"),o[Symbol.asyncIterator]=function(){return this},o;function c(s){n[s]&&(o[s]=function(h){return new Promise(function(p,y){i.push([s,h,p,y])>1||f(s,h)})})}function f(s,h){try{l(n[s](h))}catch(p){d(i[0][3],p)}}function l(s){s.value instanceof C?Promise.resolve(s.value.v).then(a,u):d(i[0][2],s)}function a(s){f("next",s)}function u(s){f("throw",s)}function d(s,h){s(h),i.shift(),i.length&&f(i[0][0],i[0][1])}}var ee=function(t){ce(r,t);function r(e){var n=t.call(this,e)||this;return Object.defineProperty(n,"name",{value:"RepeaterOverflowError",enumerable:!1}),typeof Object.setPrototypeOf=="function"?Object.setPrototypeOf(n,n.constructor.prototype):n.__proto__=n.constructor.prototype,typeof Error.captureStackTrace=="function"&&Error.captureStackTrace(n,n.constructor),n}return r}(Error),je=function(){function t(r){if(r<0)throw new RangeError("Capacity may not be less than 0");this._c=r,this._q=[]}return Object.defineProperty(t.prototype,"empty",{get:function(){return this._q.length===0},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"full",{get:function(){return this._q.length>=this._c},enumerable:!1,configurable:!0}),t.prototype.add=function(r){if(this.full)throw new Error("Buffer full");this._q.push(r)},t.prototype.remove=function(){if(this.empty)throw new Error("Buffer empty");return this._q.shift()},t}(),Ge=function(){function t(r){if(r<1)throw new RangeError("Capacity may not be less than 1");this._c=r,this._q=[]}return Object.defineProperty(t.prototype,"empty",{get:function(){return this._q.length===0},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"full",{get:function(){return!1},enumerable:!1,configurable:!0}),t.prototype.add=function(r){for(;this._q.length>=this._c;)this._q.shift();this._q.push(r)},t.prototype.remove=function(){if(this.empty)throw new Error("Buffer empty");return this._q.shift()},t}(),xe=function(){function t(r){if(r<1)throw new RangeError("Capacity may not be less than 1");this._c=r,this._q=[]}return Object.defineProperty(t.prototype,"empty",{get:function(){return this._q.length===0},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"full",{get:function(){return!1},enumerable:!1,configurable:!0}),t.prototype.add=function(r){this._q.length<this._c&&this._q.push(r)},t.prototype.remove=function(){if(this.empty)throw new Error("Buffer empty");return this._q.shift()},t}();function F(t){t!=null&&typeof t.then=="function"&&t.then(B,B)}var J=0,Y=1,j=2,q=3,M=4,N=1024,B=function(){};function G(t){var r=t.err,e=Promise.resolve(t.execution).then(function(n){if(r!=null)throw r;return n});return t.err=void 0,t.execution=e.then(function(){},function(){}),t.pending===void 0?e:t.pending.then(function(){return e})}function g(t,r){var e=t.state>=q;return Promise.resolve(r).then(function(n){return!e&&t.state>=M?G(t).then(function(o){return{value:o,done:!0}}):{value:n,done:e}})}function V(t,r){var e,n;if(!(t.state>=j))if(t.state=j,t.onnext(),t.onstop(),t.err==null&&(t.err=r),t.pushes.length===0&&(typeof t.buffer>"u"||t.buffer.empty))z(t);else try{for(var o=P(t.pushes),i=o.next();!i.done;i=o.next()){var c=i.value;c.resolve()}}catch(f){e={error:f}}finally{try{i&&!i.done&&(n=o.return)&&n.call(o)}finally{if(e)throw e.error}}}function z(t){var r,e;if(!(t.state>=q)){t.state<j&&V(t),t.state=q,t.buffer=void 0;try{for(var n=P(t.nexts),o=n.next();!o.done;o=n.next()){var i=o.value,c=t.pending===void 0?G(t):t.pending.then(function(){return G(t)});i.resolve(g(t,c))}}catch(f){r={error:f}}finally{try{o&&!o.done&&(e=n.return)&&e.call(n)}finally{if(r)throw r.error}}t.pushes=[],t.nexts=[]}}function Z(t){t.state>=M||(t.state<q&&z(t),t.state=M)}function ue(t,r){if(F(r),t.pushes.length>=N)throw new ee("No more than "+N+" pending calls to push are allowed on a single repeater.");if(t.state>=j)return Promise.resolve(void 0);var e=t.pending===void 0?Promise.resolve(r):t.pending.then(function(){return r});e=e.catch(function(l){t.state<j&&(t.err=l),Z(t)});var n;if(t.nexts.length){var o=t.nexts.shift();o.resolve(g(t,e)),t.nexts.length?n=Promise.resolve(t.nexts[0].value):typeof t.buffer<"u"&&!t.buffer.full?n=Promise.resolve(void 0):n=new Promise(function(l){return t.onnext=l})}else typeof t.buffer<"u"&&!t.buffer.full?(t.buffer.add(e),n=Promise.resolve(void 0)):n=new Promise(function(l){return t.pushes.push({resolve:l,value:e})});var i=!0,c={},f=n.catch(function(l){if(i)throw l});return c.then=function(l,a){return i=!1,Promise.prototype.then.call(n,l,a)},c.catch=function(l){return i=!1,Promise.prototype.catch.call(n,l)},c.finally=n.finally.bind(n),t.pending=e.then(function(){return f}).catch(function(l){t.err=l,Z(t)}),c}function le(t){var r=V.bind(null,t),e=new Promise(function(n){return t.onstop=n});return r.then=e.then.bind(e),r.catch=e.catch.bind(e),r.finally=e.finally.bind(e),r}function he(t){if(!(t.state>=Y)){t.state=Y;var r=ue.bind(null,t),e=le(t);t.execution=new Promise(function(n){return n(t.executor(r,e))}),t.execution.catch(function(){return V(t)})}}var I=new WeakMap,E=function(){function t(r,e){I.set(this,{executor:r,buffer:e,err:void 0,state:J,pushes:[],nexts:[],pending:void 0,execution:void 0,onnext:B,onstop:B})}return t.prototype.next=function(r){F(r);var e=I.get(this);if(e===void 0)throw new Error("WeakMap error");if(e.nexts.length>=N)throw new ee("No more than "+N+" pending calls to next are allowed on a single repeater.");if(e.state<=J&&he(e),e.onnext(r),typeof e.buffer<"u"&&!e.buffer.empty){var n=g(e,e.buffer.remove());if(e.pushes.length){var o=e.pushes.shift();e.buffer.add(o.value),e.onnext=o.resolve}return n}else if(e.pushes.length){var i=e.pushes.shift();return e.onnext=i.resolve,g(e,i.value)}else if(e.state>=j)return z(e),g(e,G(e));return new Promise(function(c){return e.nexts.push({resolve:c,value:r})})},t.prototype.return=function(r){F(r);var e=I.get(this);if(e===void 0)throw new Error("WeakMap error");return z(e),e.execution=Promise.resolve(e.execution).then(function(){return r}),g(e,G(e))},t.prototype.throw=function(r){var e=I.get(this);if(e===void 0)throw new Error("WeakMap error");return e.state<=J||e.state>=j||typeof e.buffer<"u"&&!e.buffer.empty?(z(e),e.err==null&&(e.err=r),g(e,G(e))):this.next(Promise.reject(r))},t.prototype[Symbol.asyncIterator]=function(){return this},t.race=pe,t.merge=de,t.zip=ye,t.latest=me,t}();function T(t,r){var e,n,o=[],i=function(a){a!=null&&typeof a[Symbol.asyncIterator]=="function"?o.push(a[Symbol.asyncIterator]()):a!=null&&typeof a[Symbol.iterator]=="function"?o.push(a[Symbol.iterator]()):o.push(function(){return fe(this,arguments,function(){return O(this,function(s){switch(s.label){case 0:return r.yieldValues?[4,C(a)]:[3,3];case 1:return[4,s.sent()];case 2:s.sent(),s.label=3;case 3:return r.returnValues?[4,C(a)]:[3,5];case 4:return[2,s.sent()];case 5:return[2]}})})}())};try{for(var c=P(t),f=c.next();!f.done;f=c.next()){var l=f.value;i(l)}}catch(a){e={error:a}}finally{try{f&&!f.done&&(n=c.return)&&n.call(c)}finally{if(e)throw e.error}}return o}function pe(t){var r=this,e=T(t,{returnValues:!0});return new E(function(n,o){return x(r,void 0,void 0,function(){var i,c,f,l,a,u;return O(this,function(d){switch(d.label){case 0:if(!e.length)return o(),[2];c=!1,o.then(function(){i(),c=!0}),d.label=1;case 1:d.trys.push([1,,5,7]),l=void 0,a=0,u=function(){var s,h,p,y,m,k;return O(this,function(A){switch(A.label){case 0:s=a;try{for(h=(m=void 0,P(e)),p=h.next();!p.done;p=h.next())y=p.value,Promise.resolve(y.next()).then(function(b){b.done?(o(),f===void 0&&(f=b)):a===s&&(a++,i(b))},function(b){return o(b)})}catch(b){m={error:b}}finally{try{p&&!p.done&&(k=h.return)&&k.call(h)}finally{if(m)throw m.error}}return[4,new Promise(function(b){return i=b})];case 1:return l=A.sent(),l===void 0?[3,3]:[4,n(l.value)];case 2:A.sent(),A.label=3;case 3:return[2]}})},d.label=2;case 2:return c?[3,4]:[5,u()];case 3:return d.sent(),[3,2];case 4:return[2,f&&f.value];case 5:return o(),[4,Promise.race(e.map(function(s){return s.return&&s.return()}))];case 6:return d.sent(),[7];case 7:return[2]}})})})}function de(t){var r=this,e=T(t,{yieldValues:!0});return new E(function(n,o){return x(r,void 0,void 0,function(){var i,c,f,l=this;return O(this,function(a){switch(a.label){case 0:if(!e.length)return o(),[2];i=[],c=!1,o.then(function(){var u,d;c=!0;try{for(var s=P(i),h=s.next();!h.done;h=s.next()){var p=h.value;p()}}catch(y){u={error:y}}finally{try{h&&!h.done&&(d=s.return)&&d.call(s)}finally{if(u)throw u.error}}}),a.label=1;case 1:return a.trys.push([1,,3,4]),[4,Promise.all(e.map(function(u,d){return x(l,void 0,void 0,function(){var s,h;return O(this,function(p){switch(p.label){case 0:p.trys.push([0,,6,9]),p.label=1;case 1:return c?[3,5]:(Promise.resolve(u.next()).then(function(y){return i[d](y)},function(y){return o(y)}),[4,new Promise(function(y){i[d]=y})]);case 2:return s=p.sent(),s===void 0?[3,4]:s.done?(f=s,[2]):[4,n(s.value)];case 3:p.sent(),p.label=4;case 4:return[3,1];case 5:return[3,9];case 6:return h=u.return,h?[4,u.return()]:[3,8];case 7:h=p.sent(),p.label=8;case 8:return[7];case 9:return[2]}})})}))];case 2:return a.sent(),[2,f&&f.value];case 3:return o(),[7];case 4:return[2]}})})})}function ye(t){var r=this,e=T(t,{returnValues:!0});return new E(function(n,o){return x(r,void 0,void 0,function(){var i,c,f,l;return O(this,function(a){switch(a.label){case 0:if(!e.length)return o(),[2,[]];c=!1,o.then(function(){i(),c=!0}),a.label=1;case 1:a.trys.push([1,,6,8]),a.label=2;case 2:return c?[3,5]:(Promise.all(e.map(function(u){return u.next()})).then(function(u){return i(u)},function(u){return o(u)}),[4,new Promise(function(u){return i=u})]);case 3:return f=a.sent(),f===void 0?[2]:(l=f.map(function(u){return u.value}),f.some(function(u){return u.done})?[2,l]:[4,n(l)]);case 4:return a.sent(),[3,2];case 5:return[3,8];case 6:return o(),[4,Promise.all(e.map(function(u){return u.return&&u.return()}))];case 7:return a.sent(),[7];case 8:return[2]}})})})}function me(t){var r=this,e=T(t,{yieldValues:!0,returnValues:!0});return new E(function(n,o){return x(r,void 0,void 0,function(){var i,c,f,l,a,u=this;return O(this,function(d){switch(d.label){case 0:if(!e.length)return o(),[2,[]];c=[],f=!1,o.then(function(){var s,h;i();try{for(var p=P(c),y=p.next();!y.done;y=p.next()){var m=y.value;m()}}catch(k){s={error:k}}finally{try{y&&!y.done&&(h=p.return)&&h.call(p)}finally{if(s)throw s.error}}f=!0}),d.label=1;case 1:return d.trys.push([1,,5,7]),Promise.all(e.map(function(s){return s.next()})).then(function(s){return i(s)},function(s){return o(s)}),[4,new Promise(function(s){return i=s})];case 2:return l=d.sent(),l===void 0?[2]:(a=l.map(function(s){return s.value}),l.every(function(s){return s.done})?[2,a]:[4,n(a.slice())]);case 3:return d.sent(),[4,Promise.all(e.map(function(s,h){return x(u,void 0,void 0,function(){var p;return O(this,function(y){switch(y.label){case 0:if(l[h].done)return[2,l[h].value];y.label=1;case 1:return f?[3,4]:(Promise.resolve(s.next()).then(function(m){return c[h](m)},function(m){return o(m)}),[4,new Promise(function(m){return c[h]=m})]);case 2:return p=y.sent(),p===void 0?[2,l[h].value]:p.done?[2,p.value]:(a[h]=p.value,[4,n(a.slice())]);case 3:return y.sent(),[3,1];case 4:return[2]}})})}))];case 4:return[2,d.sent()];case 5:return o(),[4,Promise.all(e.map(function(s){return s.return&&s.return()}))];case 6:return d.sent(),[7];case 7:return[2]}})})})}v();S();w();function te(t){return typeof t=="string"?t:t.url}function re(t,r,e,n){let o=e[r];if(!(!o||!o.length))try{n[r]=t(n[r],o,!0,!1).newDocument}catch(i){throw typeof i=="object"&&i&&"name"in i&&typeof i.name=="string"&&"message"in i&&typeof i.message=="string"?i.name==="TEST_OPERATION_FAILED"?new Q(i.message):new $(i.name+": "+i.message):i}}function ne(t,r){try{return t.compile(r)}catch(e){throw new L(e instanceof Error?e.message:void 0)}}function ie(t,r,e){t.actor!==e?.actor&&(t.allowed=t.allowed&&e?[e.actor]:void 0,t.channels=t.channels.filter(n=>r.includes(n)))}function oe(t,r){return t.allowed===void 0||t.allowed===null||!!r?.actor&&(t.actor===r.actor||t.allowed.includes(r.actor))}var ae=class extends W{ajv_;applyPatch_;graffiti;callbacks=new Set;options;channelStats;login;logout;sessionEvents;get ajv(){return this.ajv_||(this.ajv_=(async()=>{let{default:r}=await import("./ajv-65NGXB2O.js");return new r({strict:!1})})()),this.ajv_}get applyPatch(){return this.applyPatch_||(this.applyPatch_=(async()=>{let{applyPatch:r}=await import("./fast-json-patch-RVBYS6DB.js");return r})()),this.applyPatch_}constructor(r,e){super(),this.options=e??{},this.graffiti=r,this.channelStats=r.channelStats.bind(r),this.login=r.login.bind(r),this.logout=r.logout.bind(r),this.sessionEvents=r.sessionEvents}synchronize(r,e,n,o){let i=new Set;return new E(async(f,l)=>{let a=ne(await this.ajv,n),u=(d,s)=>{for(let h of[s,d])if(h?.tombstone)i.has(h.object.url)&&f(h);else if(h&&r(h.object)&&(this.options.omniscient||oe(h.object,o))){let p=JSON.parse(JSON.stringify(h.object));if(this.options.omniscient||ie(p,e,o),a(p)){f({object:p}),i.add(p.url);break}}};this.callbacks.add(u),await l,this.callbacks.delete(u)})}synchronizeDiscover(...r){let[e,n,o]=r;function i(c){return c.channels.some(f=>e.includes(f))}return this.synchronize(i,e,n,o)}synchronizeGet(...r){let[e,n,o]=r,i=te(e);function c(f){return f.url===i}return this.synchronize(c,[],n,o)}synchronizeRecoverOrphans(...r){let[e,n]=r;function o(i){return i.actor===n.actor&&i.channels.length===0}return this.synchronize(o,[],e,n)}synchronizeAll(r,e){return this.synchronize(()=>!0,[],r,e)}async synchronizeDispatch(r,e,n=!1){for(let o of this.callbacks)o(r,e);n&&await new Promise(o=>setTimeout(o,0))}get=async(...r)=>{let e=await this.graffiti.get(...r);return this.synchronizeDispatch({object:e}),e};put=async(...r)=>{let e=await this.graffiti.put(...r),n=r[0],o={...e,value:n.value,channels:n.channels,allowed:n.allowed};return await this.synchronizeDispatch({tombstone:!0,object:e},{object:o},!0),e};patch=async(...r)=>{let e=await this.graffiti.patch(...r),n={...e};for(let o of["value","channels","allowed"])re(await this.applyPatch,o,r[0],n);return await this.synchronizeDispatch({tombstone:!0,object:e},{object:n},!0),e};delete=async(...r)=>{let e=await this.graffiti.delete(...r);return await this.synchronizeDispatch({tombstone:!0,object:e},void 0,!0),e};objectStreamContinue(r){let e=this;return async function*(){for(;;){let n=await r.next();if(n.done){let{continue:o,cursor:i}=n.value;return{continue:()=>e.objectStreamContinue(o()),cursor:i}}n.value.error||e.synchronizeDispatch(n.value),yield n.value}}()}objectStream(r){let e=this.objectStreamContinue(r);return async function*(){for(;;){let n=await e.next();if(n.done)return n.value;(n.value.error||!n.value.tombstone)&&(yield n.value)}}()}discover=(...r)=>{let e=this.graffiti.discover(...r);return this.objectStream(e)};recoverOrphans=(...r)=>{let e=this.graffiti.recoverOrphans(...r);return this.objectStream(e)};continueObjectStream=(...r)=>this.graffiti.continueObjectStream(...r)};export{ae as GraffitiSynchronize};
2
2
  /*! Bundled license information:
3
3
 
4
4
  @repeaterjs/repeater/repeater.js:
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/index.ts", "../../node_modules/@graffiti-garden/api/src/1-api.ts", "../../node_modules/@graffiti-garden/api/src/2-types.ts", "../../node_modules/@graffiti-garden/api/src/3-errors.ts", "../../node_modules/@repeaterjs/repeater/repeater.js", "../../node_modules/@graffiti-garden/implementation-local/src/utilities.ts"],
4
- "sourcesContent": ["import type Ajv from \"ajv\";\nimport { Graffiti } from \"@graffiti-garden/api\";\nimport type {\n GraffitiSession,\n JSONSchema,\n GraffitiObjectStream,\n GraffitiObjectStreamContinueEntry,\n GraffitiObjectStreamContinue,\n} from \"@graffiti-garden/api\";\nimport type { GraffitiObjectBase } from \"@graffiti-garden/api\";\nimport { Repeater } from \"@repeaterjs/repeater\";\nimport type { applyPatch } from \"fast-json-patch\";\nimport {\n applyGraffitiPatch,\n compileGraffitiObjectSchema,\n isActorAllowedGraffitiObject,\n maskGraffitiObject,\n unpackObjectUrl,\n} from \"@graffiti-garden/implementation-local/utilities\";\nexport type * from \"@graffiti-garden/api\";\n\nexport type GraffitiSynchronizeCallback = (\n oldObject: GraffitiObjectStreamContinueEntry<{}>,\n newObject?: GraffitiObjectStreamContinueEntry<{}>,\n) => void;\n\nexport interface GraffitiSynchronizeOptions {\n /**\n * Allows synchronize to listen to all objects, not just those\n * that the session is allowed to see. This is useful to get a\n * global view of all Graffiti objects passsing through the system,\n * for example to build a client-side cache. Additional mechanisms\n * should be in place to ensure that users do not see objects or\n * properties they are not allowed to see.\n *\n * Default: `false`\n */\n omniscient?: boolean;\n}\n\n/**\n * Wraps the [Graffiti API](https://api.graffiti.garden/classes/Graffiti.html)\n * so that changes made or received in one part of an application\n * are automatically routed to other parts of the application.\n * This is an important tool for building responsive\n * and consistent user interfaces, and is built upon to make\n * the [Graffiti Vue Plugin](https://vue.graffiti.garden/variables/GraffitiPlugin.html)\n * and possibly other front-end libraries in the future.\n *\n * Specifically, it provides the following *synchronize*\n * methods for each of the following API methods:\n *\n * | API Method | Synchronize Method |\n * |------------|--------------------|\n * | {@link get} | {@link synchronizeGet} |\n * | {@link discover} | {@link synchronizeDiscover} |\n * | {@link recoverOrphans} | {@link synchronizeRecoverOrphans} |\n *\n * Whenever a change is made via {@link put}, {@link patch}, and {@link delete} or\n * received from {@link get}, {@link discover}, and {@link recoverOrphans},\n * those changes are forwarded to the appropriate synchronize method.\n * Each synchronize method returns an iterator that streams these changes\n * continually until the user calls `return` on the iterator or `break`s out of the loop,\n * allowing for live updates without additional polling.\n *\n * Example 1: Suppose a user publishes a post using {@link put}. If the feed\n * displaying that user's posts is using {@link synchronizeDiscover} to listen for changes,\n * then the user's new post will instantly appear in their feed, giving the UI a\n * responsive feel.\n *\n * Example 2: Suppose one of a user's friends changes their name. As soon as the\n * user's application receives one notice of that change (using {@link get}\n * or {@link discover}), then {@link synchronizeDiscover} listeners can be used to update\n * all instance's of that friend's name in the user's application instantly,\n * providing a consistent user experience.\n *\n * @groupDescription Synchronize Methods\n * This group contains methods that listen for changes made via\n * {@link put}, {@link patch}, and {@link delete} or fetched from\n * {@link get}, {@link discover}, and {@link recoverOrphans} and then\n * streams appropriate changes to provide a responsive and consistent user experience.\n */\nexport class GraffitiSynchronize extends Graffiti {\n protected ajv_: Promise<Ajv> | undefined;\n protected applyPatch_: Promise<typeof applyPatch> | undefined;\n protected readonly graffiti: Graffiti;\n protected readonly callbacks = new Set<GraffitiSynchronizeCallback>();\n protected readonly options: GraffitiSynchronizeOptions;\n\n channelStats: Graffiti[\"channelStats\"];\n login: Graffiti[\"login\"];\n logout: Graffiti[\"logout\"];\n sessionEvents: Graffiti[\"sessionEvents\"];\n\n get ajv() {\n if (!this.ajv_) {\n this.ajv_ = (async () => {\n const { default: Ajv } = await import(\"ajv\");\n return new Ajv({ strict: false });\n })();\n }\n return this.ajv_;\n }\n\n get applyPatch() {\n if (!this.applyPatch_) {\n this.applyPatch_ = (async () => {\n const { applyPatch } = await import(\"fast-json-patch\");\n return applyPatch;\n })();\n }\n return this.applyPatch_;\n }\n\n /**\n * Wraps a Graffiti API instance to provide the synchronize methods.\n * The GraffitiSyncrhonize class rather than the Graffiti class\n * must be used for all functions for the synchronize methods to work.\n */\n constructor(\n /**\n * The [Graffiti API](https://api.graffiti.garden/classes/Graffiti.html)\n * instance to wrap.\n */\n graffiti: Graffiti,\n options?: GraffitiSynchronizeOptions,\n ) {\n super();\n this.options = options ?? {};\n this.graffiti = graffiti;\n this.channelStats = graffiti.channelStats.bind(graffiti);\n this.login = graffiti.login.bind(graffiti);\n this.logout = graffiti.logout.bind(graffiti);\n this.sessionEvents = graffiti.sessionEvents;\n }\n\n protected synchronize<Schema extends JSONSchema>(\n matchObject: (object: GraffitiObjectBase) => boolean,\n channels: string[],\n schema: Schema,\n session?: GraffitiSession | null,\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\n const seenUrls = new Set<string>();\n\n const repeater = new Repeater<GraffitiObjectStreamContinueEntry<Schema>>(\n async (push, stop) => {\n const validate = compileGraffitiObjectSchema(await this.ajv, schema);\n const callback: GraffitiSynchronizeCallback = (\n oldObjectRaw,\n newObjectRaw,\n ) => {\n for (const objectRaw of [newObjectRaw, oldObjectRaw]) {\n if (objectRaw?.tombstone) {\n if (seenUrls.has(objectRaw.object.url)) {\n push(objectRaw);\n }\n } else if (\n objectRaw &&\n matchObject(objectRaw.object) &&\n (this.options.omniscient ||\n isActorAllowedGraffitiObject(objectRaw.object, session))\n ) {\n const object = { ...objectRaw.object };\n if (!this.options.omniscient) {\n maskGraffitiObject(object, channels, session);\n }\n if (validate(object)) {\n push({ object });\n seenUrls.add(object.url);\n break;\n }\n }\n }\n };\n\n this.callbacks.add(callback);\n await stop;\n this.callbacks.delete(callback);\n },\n );\n\n return repeater;\n }\n\n /**\n * This method has the same signature as {@link discover} but listens for\n * changes made via {@link put}, {@link patch}, and {@link delete} or\n * fetched from {@link get}, {@link discover}, and {@link recoverOrphans}\n * and then streams appropriate changes to provide a responsive and\n * consistent user experience.\n *\n * Unlike {@link discover}, this method continuously listens for changes\n * and will not terminate unless the user calls the `return` method on the iterator\n * or `break`s out of the loop.\n *\n * @group Synchronize Methods\n */\n synchronizeDiscover<Schema extends JSONSchema>(\n ...args: Parameters<typeof Graffiti.prototype.discover<Schema>>\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\n const [channels, schema, session] = args;\n function matchObject(object: GraffitiObjectBase) {\n return object.channels.some((channel) => channels.includes(channel));\n }\n return this.synchronize<Schema>(matchObject, channels, schema, session);\n }\n\n /**\n * This method has the same signature as {@link get} but\n * listens for changes made via {@link put}, {@link patch}, and {@link delete} or\n * fetched from {@link get}, {@link discover}, and {@link recoverOrphans} and then\n * streams appropriate changes to provide a responsive and consistent user experience.\n *\n * Unlike {@link get}, which returns a single result, this method continuously\n * listens for changes which are output as an asynchronous stream, similar\n * to {@link discover}.\n *\n * @group Synchronize Methods\n */\n synchronizeGet<Schema extends JSONSchema>(\n ...args: Parameters<typeof Graffiti.prototype.get<Schema>>\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\n const [objectUrl, schema, session] = args;\n const url = unpackObjectUrl(objectUrl);\n function matchObject(object: GraffitiObjectBase) {\n return object.url === url;\n }\n return this.synchronize<Schema>(matchObject, [], schema, session);\n }\n\n /**\n * This method has the same signature as {@link recoverOrphans} but\n * listens for changes made via\n * {@link put}, {@link patch}, and {@link delete} or fetched from\n * {@link get}, {@link discover}, and {@link recoverOrphans} and then\n * streams appropriate changes to provide a responsive and consistent user experience.\n *\n * Unlike {@link recoverOrphans}, this method continuously listens for changes\n * and will not terminate unless the user calls the `return` method on the iterator\n * or `break`s out of the loop.\n *\n * @group Synchronize Methods\n */\n synchronizeRecoverOrphans<Schema extends JSONSchema>(\n ...args: Parameters<typeof Graffiti.prototype.recoverOrphans<Schema>>\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\n const [schema, session] = args;\n function matchObject(object: GraffitiObjectBase) {\n return object.actor === session.actor && object.channels.length === 0;\n }\n return this.synchronize<Schema>(matchObject, [], schema, session);\n }\n\n /**\n * Streams changes made to *any* object in *any* channel\n * and made by *any* user. You may want to use it in conjuction with\n * {@link GraffitiSynchronizeOptions.omniscient} to get a global view\n * of all Graffiti objects passing through the system. This is useful\n * for building a client-side cache, for example.\n *\n * Be careful using this method. Without additional filters it can\n * expose the user to content out of context.\n */\n synchronizeAll<Schema extends JSONSchema>(\n schema: Schema,\n session?: GraffitiSession | null,\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\n return this.synchronize<Schema>(() => true, [], schema, session);\n }\n\n protected async synchronizeDispatch(\n oldObject: GraffitiObjectStreamContinueEntry<{}>,\n newObject?: GraffitiObjectStreamContinueEntry<{}>,\n waitForListeners = false,\n ) {\n for (const callback of this.callbacks) {\n callback(oldObject, newObject);\n }\n if (waitForListeners) {\n // Wait for the listeners to receive\n // their objects, before returning the operation\n // that triggered them.\n //\n // This is important for mutators (put, patch, delete)\n // to ensure the application state has been updated\n // everywhere before returning, giving consistent\n // feedback to the user that the operation has completed.\n //\n // The opposite is true for accessors (get, discover, recoverOrphans),\n // where it is a weird user experience to call `get`\n // in one place and have the application update\n // somewhere else first. It is also less efficient.\n //\n // The hack is simply to await one \"macro task cycle\".\n // We need to wait for this cycle rather than using\n // `await push` in the callback, because it turns out\n // that `await push` won't resolve until the following\n // .next() call of the iterator, so if only\n // one .next() is called, this dispatch will hang.\n await new Promise((resolve) => setTimeout(resolve, 0));\n }\n }\n\n get: Graffiti[\"get\"] = async (...args) => {\n const object = await this.graffiti.get(...args);\n this.synchronizeDispatch({ object });\n return object;\n };\n\n put: Graffiti[\"put\"] = async (...args) => {\n const oldObject = await this.graffiti.put<{}>(...args);\n const partialObject = args[0];\n const newObject: GraffitiObjectBase = {\n ...oldObject,\n value: partialObject.value,\n channels: partialObject.channels,\n allowed: partialObject.allowed,\n };\n await this.synchronizeDispatch(\n {\n tombstone: true,\n object: oldObject,\n },\n {\n object: newObject,\n },\n true,\n );\n return oldObject;\n };\n\n patch: Graffiti[\"patch\"] = async (...args) => {\n const oldObject = await this.graffiti.patch(...args);\n const newObject: GraffitiObjectBase = { ...oldObject };\n for (const prop of [\"value\", \"channels\", \"allowed\"] as const) {\n applyGraffitiPatch(await this.applyPatch, prop, args[0], newObject);\n }\n await this.synchronizeDispatch(\n {\n tombstone: true,\n object: oldObject,\n },\n {\n object: newObject,\n },\n true,\n );\n return oldObject;\n };\n\n delete: Graffiti[\"delete\"] = async (...args) => {\n const oldObject = await this.graffiti.delete(...args);\n await this.synchronizeDispatch(\n {\n tombstone: true,\n object: oldObject,\n },\n undefined,\n true,\n );\n return oldObject;\n };\n\n protected objectStreamContinue<Schema extends JSONSchema>(\n iterator: GraffitiObjectStreamContinue<Schema>,\n ): GraffitiObjectStreamContinue<Schema> {\n const this_ = this;\n return (async function* () {\n while (true) {\n const result = await iterator.next();\n if (result.done) {\n const { continue: continue_, cursor } = result.value;\n return {\n continue: () => this_.objectStreamContinue<Schema>(continue_()),\n cursor,\n };\n }\n if (!result.value.error) {\n this_.synchronizeDispatch(\n result.value as GraffitiObjectStreamContinueEntry<{}>,\n );\n }\n yield result.value;\n }\n })();\n }\n\n protected objectStream<Schema extends JSONSchema>(\n iterator: GraffitiObjectStream<Schema>,\n ): GraffitiObjectStream<Schema> {\n const wrapped = this.objectStreamContinue<Schema>(iterator);\n return (async function* () {\n // Filter out the tombstones for type safety\n while (true) {\n const result = await wrapped.next();\n if (result.done) return result.value;\n if (result.value.error || !result.value.tombstone) yield result.value;\n }\n })();\n }\n\n discover: Graffiti[\"discover\"] = (...args) => {\n const iterator = this.graffiti.discover(...args);\n return this.objectStream<(typeof args)[1]>(iterator);\n };\n\n recoverOrphans: Graffiti[\"recoverOrphans\"] = (...args) => {\n const iterator = this.graffiti.recoverOrphans(...args);\n return this.objectStream<(typeof args)[0]>(iterator);\n };\n\n continueObjectStream: Graffiti[\"continueObjectStream\"] = (...args) => {\n // TODO!!\n return this.graffiti.continueObjectStream(...args);\n };\n}\n", "import type {\n GraffitiObjectUrl,\n GraffitiObject,\n GraffitiObjectBase,\n GraffitiPatch,\n GraffitiSession,\n GraffitiPutObject,\n GraffitiObjectStream,\n ChannelStats,\n GraffitiChannelStatsStream,\n GraffitiObjectStreamContinue,\n} from \"./2-types\";\nimport type { JSONSchema } from \"json-schema-to-ts\";\n\n/**\n * This API describes a small but powerful set of methods that\n * can be used to create many different kinds of social media applications,\n * all of which can interoperate.\n * These methods should satisfy all of an application's needs for\n * the communication, storage, and access management of social data.\n * The rest of the application can be built with standard client-side\n * user interface tools to present and interact with the data \u2014\n * no server code necessary.\n * The Typescript source for this API is available at\n * [graffiti-garden/api](https://github.com/graffiti-garden/api).\n *\n * There are several different implementations of this Graffiti API available,\n * including a [federated implementation](https://github.com/graffiti-garden/implementation-federated),\n * that lets users choose where their data is stored,\n * and a [local implementation](https://github.com/graffiti-garden/implementation-local)\n * that can be used for testing and development. In our design of Graffiti, this API is our\n * primary focus as it is the layer that shapes the experience\n * of developing applications. While different implementations can provide tradeoffs between\n * other important properties (e.g. privacy, security, scalability), those properties\n * are useless if the system as a whole doesn't expose useful functionality to developers.\n *\n * On the other side of the stack, there is [Vue plugin](https://github.com/graffiti-garden/wrapper-vue/)\n * that wraps around this API to provide reactivity. Other high-level libraries\n * will be available in the future.\n *\n * ## Overview\n *\n * Graffiti provides applications with methods to create and store data\n * on behalf of their users using standard CRUD operations:\n * {@link put}, {@link get}, {@link patch}, and {@link delete}.\n * This data can represent both social artifacts (e.g. posts, profiles) and\n * activities (e.g. likes, follows) and is stored as JSON.\n *\n * The social aspect of Graffiti comes from the {@link discover} method\n * which allows applications to find objects that other users made.\n * It is a lot like a traditional query operation, but it only\n * returns objects that have been placed in particular\n * {@link GraffitiObjectBase.channels | `channels`}\n * specified by the discovering application.\n *\n * Graffiti builds on well known concepts and standards wherever possible.\n * JSON Objects can be typed with [JSON Schema](https://json-schema.org/) and patches\n * can be applied with [JSON Patch](https://jsonpatch.com).\n * For interoperability between Graffiti applications, we recommend that\n * objects use established properties from the\n * [Activity Vocabulary](https://www.w3.org/TR/activitystreams-vocabulary/) when available,\n * however it is always possible to create additional properties, contributing\n * to the broader [folksonomy](https://en.wikipedia.org/wiki/Folksonomy).\n *\n * {@link GraffitiObjectBase.channels | `channels`} are one of the major concepts\n * unique to Graffiti along with *interaction relativity*, defined below.\n * Channels create boundaries between public spaces and work to prevent\n * [context collapse](https://en.wikipedia.org/wiki/Context_collapse)\n * even in a highly interoperable environment.\n * Interaction relativity means that all interactions between users are\n * actually atomic single-user operations that can be interpreted in different ways,\n * which also supports interoperability and pluralism.\n *\n * ### Channels\n *\n * {@link GraffitiObjectBase.channels | `channels`}\n * are a way for the creators of social data to express the intended audience of their\n * data. When a user creates data using the {@link put} method, they\n * can place their data in one or more channels.\n * Content consumers using the {@link discover} method will only see data\n * contained in one of the channels they specify.\n *\n * While many channels may be public, they partition\n * the public into different \"contexts\", mitigating the\n * phenomenon of [context collapse](https://en.wikipedia.org/wiki/Context_collapse) or the \"flattening of multiple audiences.\"\n * Any [URI](https://en.wikipedia.org/wiki/Uniform_Resource_Identifier) can be used as a channel, and so channels can represent people,\n * comment threads, topics, places (real or virtual), pieces of media, and more.\n *\n * For example, consider a comment on a post. If we place that comment in the channel\n * represented by the post's URL, then only people viewing the post will know to\n * look in that channel, giving it visibility akin to a comment on a blog post\n * or comment on Instagram ([since 2019](https://www.buzzfeednews.com/article/katienotopoulos/instagrams-following-activity-tab-is-going-away)).\n * If we also place the comment in the channel represented by the commenter's URI (their\n * {@link GraffitiObjectBase.actor | `actor` URI}), then people viewing the commenter's profile\n * will also see the comment, giving it more visibility, like a reply on Twitter.\n * If we *only* place the comment in the channel represented by the commenter's URI, then\n * it becomes like a quote tweet ([prior to 2020](https://x.com/Support/status/1300555325750292480)),\n * where the comment is only visible to the commenter's followers but not the audience\n * of the original post.\n *\n * The channel model differs from other models of communication such as the\n * [actor model](https://www.w3.org/TR/activitypub/#Overview) used by ActivityPub,\n * the protocol underlying Mastodon, or the [firehose model](https://bsky.social/about/blog/5-5-2023-federation-architecture)\n * used by the AT Protocol, the protocol underlying BlueSky.\n * The actor model is a fusion of direct messaging (like Email) and broadcasting\n * (like RSS) and works well for follow-based communication but struggles\n * to pass information via other rendez-vous.\n * In the actor model, even something as simple as comments can be\n * [very tricky and require server \"side effects\"](https://seb.jambor.dev/posts/understanding-activitypub-part-3-the-state-of-mastodon/).\n * The firehose model dumps all user data into one public database,\n * which doesn't allow for the carving out of different contexts that we did in our comment\n * example above. In the firehose model a comment will always be visible to *both* the original post's audience and\n * the commenter's followers.\n *\n * In some sense, channels provide a sort of \"social access control\" by forming\n * expectations about the audiences of different online spaces.\n * As a real world analogy, oftentimes support groups, such as alcoholics\n * anonymous, are open to the public but people in those spaces feel comfortable sharing intimate details\n * because they have expectations about the other people attending.\n * If someone malicious went to support groups just to spread people's secrets,\n * they would be shamed for violating these norms.\n * Similarly, in Graffiti, while you could spider public channels like a search engine\n * to find content about a person, revealing that you've done such a thing\n * would be shameful.\n *\n * Still, social access control is not perfect and so in situations where privacy is important,\n * objects can also be given\n * an {@link GraffitiObjectBase.allowed | `allowed`} list.\n * For example, to send someone a direct message you should put an object representing\n * that message in the channel that represents them (their {@link GraffitiObjectBase.actor | `actor` URI}),\n * so they can find it, *and* set the `allowed` field to only include the recipient,\n * so only they can read it.\n *\n * ### Interaction relativity\n *\n * Interaction relativity posits that \"interaction between two individuals only\n * exists relative to an observer,\" or equivalently, all interaction is [reified](https://en.wikipedia.org/wiki/Reification_(computer_science)).\n * For example, if one user creates a post and another user wants to \"like\" that post,\n * their like is not modifying the original post, it is simply another data object that points\n * to the post being liked, via its {@link GraffitiObjectBase.url | URL}.\n *\n * ```json\n * {\n * activity: 'like',\n * target: 'url-of-the-post-i-like',\n * actor: 'my-user-id'\n * }\n * ```\n *\n * In Graffiti, all interactions including *moderation* and *collaboration* are relative.\n * This means that applications can freely choose which interactions\n * they want to express to their users and how.\n * For example, one application could have a single fixed moderator,\n * another could allow users to choose which moderators they would like filter their content\n * like [Bluesky's stackable moderation](https://bsky.social/about/blog/03-12-2024-stackable-moderation),\n * and another could implement a fully democratic system like [PolicyKit](https://policykit.org/).\n * Each of these applications is one interpretation of the underlying refieid user interactions and\n * users can freely switch between them.\n *\n * Interaction relativy also allows applications to introduce new sorts of interactions\n * without having to coordinate with all the other existing applications,\n * keeping the ecosystem flexible and interoperable.\n * For example, an application could [add a \"Trust\" button to posts](https://social.cs.washington.edu/pub_details.html?id=trustnet)\n * and use it assess the truthfulness of posts made on applications across Graffiti.\n * New sorts of interactions like these can be smoothly absorbed by the broader ecosystem\n * as a [folksonomy](https://en.wikipedia.org/wiki/Folksonomy).\n *\n * Interactivy relativity is realized in Graffiti through two design decisions:\n * 1. The creators of objects can only modify their own objects. It is important for\n * users to be able to change and delete their own content to respect their\n * [right to be forgotten](https://en.wikipedia.org/wiki/Right_to_be_forgotten),\n * but beyond self-correction and self-censorship all other interaction is reified.\n * Many interactions can be reified via pointers, as in the \"like\" example above, and collaborative\n * edits can be refieid via [CRDTs](https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type).\n * 2. No one owns channels. Unlike IRC/Slack channels or [Matrix rooms](https://matrix.org/docs/matrix-concepts/rooms_and_events/),\n * anyone can post to any channel, so long as they know the URI of that channel.\n * It is up to applications to hide content from channels either according to manual\n * filters or in response to user action.\n * For example, a user may create a post with the flag `disableReplies`.\n * Applications could then filter out any content from the replies channel\n * that the original poster has not specifically approved.\n *\n * @groupDescription CRUD Methods\n * Methods for {@link put | creating}, {@link get | reading}, {@link patch | updating},\n * and {@link delete | deleting} {@link GraffitiObjectBase | Graffiti objects}.\n * @groupDescription Query Methods\n * Methods that retrieve or accumulate information about multiple {@link GraffitiObjectBase | Graffiti objects} at a time.\n * @groupDescription Session Management\n * Methods and properties for logging in and out of a Graffiti implementation.\n */\nexport abstract class Graffiti {\n /**\n * Creates a new {@link GraffitiObjectBase | object} or replaces an existing object.\n * An object can only be replaced by the same {@link GraffitiObjectBase.actor | `actor`}\n * that created it.\n *\n * Replacement occurs when the {@link GraffitiObjectBase.url | `url`} of\n * the replaced object exactly matches an existing object's URL.\n *\n * @throws {@link GraffitiErrorNotFound} if a {@link GraffitiObjectBase.url | `url`}\n * is provided that has not been created yet or the {@link GraffitiObjectBase.actor | `actor`}\n * is not {@link GraffitiObjectBase.allowed | `allowed`} to see it.\n *\n * @throws {@link GraffitiErrorForbidden} if the {@link GraffitiObjectBase.actor | `actor`}\n * is not the same `actor` as the one who created the object.\n *\n * @returns The object that was replaced if one one exists, otherwise an object with\n * with an empty {@link GraffitiObjectBase.value | `value`},\n * {@link GraffitiObjectBase.channels | `channels`}, and {@link GraffitiObjectBase.allowed | `allowed`}\n * list.\n * The {@link GraffitiObjectBase.lastModified | `lastModified`} property of the returned object\n * will be updated to the time of replacement/creation.\n *\n * @group CRUD Methods\n */\n abstract put<Schema extends JSONSchema>(\n /**\n * The object to be put. This object is statically type-checked against the [JSON schema](https://json-schema.org/) that can be optionally provided\n * as the generic type parameter. We highly recommend providing a schema to\n * ensure that the PUT object matches subsequent {@link get} or {@link discover}\n * methods.\n */\n object: GraffitiPutObject<Schema>,\n /**\n * An implementation-specific object with information to authenticate the\n * {@link GraffitiObjectBase.actor | `actor`}.\n */\n session: GraffitiSession,\n ): Promise<GraffitiObjectBase>;\n\n /**\n * Retrieves an object from a given {@link GraffitiObjectBase.url | `url`}.\n *\n * The retrieved object is type-checked against the provided [JSON schema](https://json-schema.org/)\n * otherwise a {@link GraffitiErrorSchemaMismatch} is thrown.\n *\n * If the retreiving {@link GraffitiObjectBase.actor | `actor`} is not\n * the object's `actor`,\n * the object's {@link GraffitiObjectBase.allowed | `allowed`} and\n * {@link GraffitiObjectBase.channels | `channels`} properties are\n * not revealed, similar to a BCC.\n *\n * @throws {@link GraffitiErrorNotFound} if the object does not exist, has been deleted, or the user is not\n * {@link GraffitiObjectBase.allowed | `allowed`} to access it.\n *\n * @throws {@link GraffitiErrorSchemaMismatch} if the retrieved object does not match the provided schema.\n *\n * @group CRUD Methods\n */\n abstract get<Schema extends JSONSchema>(\n /**\n * The location of the object to get.\n */\n url: string | GraffitiObjectUrl,\n /**\n * The JSON schema to validate the retrieved object against.\n */\n schema: Schema,\n /**\n * An implementation-specific object with information to authenticate the\n * {@link GraffitiObjectBase.actor | `actor`}. If no `session` is provided,\n * the retrieved object's {@link GraffitiObjectBase.allowed | `allowed`}\n * property must be `undefined`.\n */\n session?: GraffitiSession | null,\n ): Promise<GraffitiObject<Schema>>;\n\n /**\n * Patches an existing object at a given {@link GraffitiObjectBase.url | `url`}.\n * The patching {@link GraffitiObjectBase.actor | `actor`} must be the same as the\n * `actor` that created the object.\n *\n * @returns The original object prior to the patch with its\n * {@link GraffitiObjectBase.lastModified | `lastModified`}\n * property updated to the time of deletion.\n *\n * @throws {@link GraffitiErrorNotFound} if the object does not exist, has already been deleted,\n * or the user is not {@link GraffitiObjectBase.allowed | `allowed`} to access it.\n *\n * @throws {@link GraffitiErrorForbidden} if the {@link GraffitiObjectBase.actor | `actor`}\n * is not the same `actor` as the one who created the object.\n *\n * @group CRUD Methods\n */\n abstract patch(\n /**\n * A collection of [JSON Patch](https://jsonpatch.com) operations\n * to apply to the object. See {@link GraffitiPatch} for more information.\n */\n patch: GraffitiPatch,\n /**\n * The location of the object to patch.\n */\n url: string | GraffitiObjectUrl,\n /**\n * An implementation-specific object with information to authenticate the\n * {@link GraffitiObjectBase.actor | `actor`}.\n */\n session: GraffitiSession,\n ): Promise<GraffitiObjectBase>;\n\n /**\n * Deletes an object from a given {@link GraffitiObjectBase.url | `url`}.\n * The deleting {@link GraffitiObjectBase.actor | `actor`} must be the same as the\n * `actor` that created the object.\n *\n * It is not possible to re-{@link put} an object that has been deleted\n * to ensure a user's [right to be forgotten](https://en.wikipedia.org/wiki/Right_to_be_forgotten).\n * In cases where deleting and restoring an object is useful, an object's\n * {@link GraffitiObjectBase.allowed | `allowed`} property can be set to\n * an empty list to hide it from all users except the creator.\n *\n * @returns The object that was deleted with its\n * {@link GraffitiObjectBase.lastModified | `lastModified`}\n * property updated to the time of deletion.\n *\n * @throws {@link GraffitiErrorNotFound} if the object does not exist, has already been deleted,\n * or the user is not {@link GraffitiObjectBase.allowed | `allowed`} to access it.\n *\n * @throws {@link GraffitiErrorForbidden} if the {@link GraffitiObjectBase.actor | `actor`}\n * is not the same `actor` as the one who created the object.\n *\n * @group CRUD Methods\n */\n abstract delete(\n /**\n * The location of the object to delete.\n */\n url: string | GraffitiObjectUrl,\n /**\n * An implementation-specific object with information to authenticate the\n * {@link GraffitiObjectBase.actor | `actor`}.\n */\n session: GraffitiSession,\n ): Promise<GraffitiObjectBase>;\n\n /**\n * Discovers objects created by any user that are contained\n * in at least one of the given {@link GraffitiObjectBase.channels | `channels`}\n * and match the given [JSON Schema](https://json-schema.org).\n *\n * Objects are returned asynchronously as they are discovered but the stream\n * will end once all leads have been exhausted.\n * The {@link GraffitiObjectStream} ends by returning a\n * {@link GraffitiObjectStreamReturn.continue | `continue`} method and a\n * {@link GraffitiObjectStreamReturn.cursor | `cursor`} string,\n * each of which can be be used to poll for new objects.\n * The `continue` method preserves the type safety of the stream and the `cursor`\n * string can be serialized to continue the stream after an application is closed\n * and reopened.\n *\n * `discover` will not return objects that the {@link GraffitiObjectBase.actor | `actor`}\n * is not {@link GraffitiObjectBase.allowed | `allowed`} to access.\n * If the `actor` is not the creator of a discovered object,\n * the allowed list will be masked to only contain the querying actor if the\n * allowed list is not `undefined` (public). Additionally, if the actor is not the\n * creator of a discovered object, any {@link GraffitiObjectBase.channels | `channels`}\n * not specified by the `discover` method will not be revealed. This masking happens\n * before the object is validated against the supplied `schema`.\n *\n * Since different implementations may fetch data from multiple sources there is\n * no guarentee on the order that objects are returned in.\n * It is also possible that duplicate objects are returned and their\n * {@link GraffitiObjectBase.lastModified | `lastModified`} fields must be used\n * to determine which object is the most recent.\n *\n * @returns A stream of objects that match the given {@link GraffitiObjectBase.channels | `channels`}\n * and [JSON Schema](https://json-schema.org).\n *\n * @group Query Methods\n */\n abstract discover<Schema extends JSONSchema>(\n /**\n * The {@link GraffitiObjectBase.channels | `channels`} that objects must be associated with.\n */\n channels: string[],\n /**\n * A [JSON Schema](https://json-schema.org) that objects must satisfy.\n */\n schema: Schema,\n /**\n * An implementation-specific object with information to authenticate the\n * {@link GraffitiObjectBase.actor | `actor`}. If no `session` is provided,\n * only objects that have no {@link GraffitiObjectBase.allowed | `allowed`}\n * property will be returned.\n */\n session?: GraffitiSession | null,\n ): GraffitiObjectStream<Schema>;\n\n /**\n * Discovers objects **not** contained in any\n * {@link GraffitiObjectBase.channels | `channels`}\n * that were created by the querying {@link GraffitiObjectBase.actor | `actor`}\n * and match the given [JSON Schema](https://json-schema.org).\n * Unlike {@link discover}, this method will not return objects created by other users.\n *\n * This method is not useful for most applications, but necessary for\n * getting a global view of all a user's Graffiti data or debugging\n * channel usage.\n *\n * Like {@link discover}, objects are returned asynchronously as they are discovered,\n * the stream will end once all leads have been exhausted, and the stream\n * can be continued using the {@link GraffitiObjectStreamReturn.continue | `continue`}\n * method or {@link GraffitiObjectStreamReturn.cursor | `cursor`} string.\n *\n * @returns A stream of objects created by the querying {@link GraffitiObjectBase.actor | `actor`}\n * that do not belong to any {@link GraffitiObjectBase.channels | `channels`}\n * and match the given [JSON Schema](https://json-schema.org).\n *\n * @group Query Methods\n */\n abstract recoverOrphans<Schema extends JSONSchema>(\n /**\n * A [JSON Schema](https://json-schema.org) that orphaned objects must satisfy.\n */\n schema: Schema,\n /**\n * An implementation-specific object with information to authenticate the\n * {@link GraffitiObjectBase.actor | `actor`}.\n */\n session: GraffitiSession,\n ): GraffitiObjectStream<Schema>;\n\n /**\n * Returns statistics about all the {@link GraffitiObjectBase.channels | `channels`}\n * that an {@link GraffitiObjectBase.actor | `actor`} has posted to.\n * This is not very useful for most applications, but\n * necessary for certain applications where a user wants a\n * global view of all their Graffiti data or to debug\n * channel usage.\n *\n * Like {@link discover}, objects are returned asynchronously as they are discovered,\n * the stream will end once all leads have been exhausted.\n *\n * @group Query Methods\n *\n * @returns A stream of statistics for each {@link GraffitiObjectBase.channels | `channel`}\n * that the {@link GraffitiObjectBase.actor | `actor`} has posted to.\n */\n abstract channelStats(\n /**\n * An implementation-specific object with information to authenticate the\n * {@link GraffitiObjectBase.actor | `actor`}.\n */\n session: GraffitiSession,\n ): GraffitiChannelStatsStream;\n\n /**\n * Continues a {@link GraffitiObjectStream} from a given\n * {@link GraffitiObjectStreamReturn.cursor | `cursor`} string.\n * The continuation will return new objects that have been created\n * that match the original stream, and also returns the\n * {@link GraffitiObjectBase.url | `url`}s of objects that\n * have been deleted, as marked by a `tombstone`.\n *\n * The continuation may also include duplicates of objects that\n * were already returned by the original stream. This is dependent\n * on how much state the underlying implementation maintains.\n *\n * The `cursor` allows the client to\n * serialize the state of the stream and continue it later.\n * However this method loses any typing information that was\n * present in the original stream. For better type safety\n * and when serializing is not necessary, use the\n * {@link GraffitiObjectStreamReturn.continue | `continue`} method\n * instead, which is returned along with the `cursor` at the\n * end of the original stream.\n *\n * @throws {@link GraffitiErrorForbidden} if the {@link GraffitiObjectBase.actor | `actor`}\n * provided in the `session` is not the same as the `actor`\n * that initiated the original stream.\n *\n * @group Query Methods\n */\n abstract continueObjectStream(\n cursor: string,\n session?: GraffitiSession | null,\n ): GraffitiObjectStreamContinue<{}>;\n\n /**\n * Begins the login process. Depending on the implementation, this may\n * involve redirecting the user to a login page or opening a popup,\n * so it should always be called in response to a user action.\n *\n * The {@link GraffitiSession | session} object is returned\n * asynchronously via {@link Graffiti.sessionEvents | sessionEvents}\n * as a {@link GraffitiLoginEvent} with event type `login`.\n *\n * @group Session Management\n */\n abstract login(\n /**\n * Suggestions for the permissions that the\n * login process should grant. The login process may not\n * provide the exact proposed permissions.\n */\n proposal?: {\n /**\n * A suggested actor to login as. For example, if a user tries to\n * edit a post but are not logged in, the interface can infer that\n * they might want to log in as the actor who created the post\n * they are attempting to edit.\n *\n * Even if provided, the implementation should allow the user\n * to log in as a different actor if they choose.\n */\n actor?: string;\n /**\n * A yet to be defined permissions scope. An application may use\n * this to indicate the minimum necessary scope needed to\n * operate. For example, it may need to be able read private\n * messages from a certain set of channels, or write messages that\n * follow a particular schema.\n *\n * The login process should make it clear what scope an application\n * is requesting and allow the user to enhance or reduce that\n * scope as necessary.\n */\n scope?: {};\n },\n ): Promise<void>;\n\n /**\n * Begins the logout process. Depending on the implementation, this may\n * involve redirecting the user to a logout page or opening a popup,\n * so it should always be called in response to a user action.\n *\n * A confirmation will be returned asynchronously via\n * {@link Graffiti.sessionEvents | sessionEvents}\n * as a {@link GraffitiLogoutEvent} as event type `logout`.\n *\n * @group Session Management\n */\n abstract logout(\n /**\n * The {@link GraffitiSession | session} object to logout.\n */\n session: GraffitiSession,\n ): Promise<void>;\n\n /**\n * An event target that can be used to listen for the following\n * events and they're corresponding event types:\n * - `login` - {@link GraffitiLoginEvent}\n * - `logout` - {@link GraffitiLogoutEvent}\n * - `initialized` - {@link GraffitiSessionInitializedEvent}\n *\n * @group Session Management\n */\n abstract readonly sessionEvents: EventTarget;\n}\n", "import type { JSONSchema, FromSchema } from \"json-schema-to-ts\";\nimport type { Operation as JSONPatchOperation } from \"fast-json-patch\";\n\n/**\n * Objects are the atomic unit in Graffiti that can represent both data (*e.g.* a social media post or profile)\n * and activities (*e.g.* a like or follow).\n * Objects are created and modified by a single {@link actor | `actor`}.\n *\n * Most of an object's content is stored in its {@link value | `value`} property, which can be any JSON\n * object. However, we recommend using properties from the\n * [Activity Vocabulary](https://www.w3.org/TR/activitystreams-vocabulary/)\n * or properties that emerge in the Graffiti [folksonomy](https://en.wikipedia.org/wiki/Folksonomy)\n * to promote interoperability.\n *\n * The object is globally addressable via its {@link url | `url`}.\n *\n * The {@link channels | `channels`} and {@link allowed | `allowed`} properties\n * enable the object's creator to shape the visibility of and access to their object.\n *\n * The {@link lastModified | `lastModified`} property can be used to compare object versions.\n */\nexport interface GraffitiObjectBase {\n /**\n * The object's content as freeform JSON. We recommend using properties from the\n * [Activity Vocabulary](https://www.w3.org/TR/activitystreams-vocabulary/)\n * or properties that emerge in the Graffiti [folksonomy](https://en.wikipedia.org/wiki/Folksonomy)\n * to promote interoperability.\n */\n value: {};\n\n /**\n * An array of URIs the creator associates with the object. Objects can only be found by querying\n * one of the object's channels using the\n * {@link Graffiti.discover} method. This allows creators to express the intended audience of their object\n * which helps to prevent [context collapse](https://en.wikipedia.org/wiki/Context_collapse) even\n * in the highly interoperable ecosystem that Graffiti envisions. For example, channel URIs may be:\n * - A user's own {@link actor | `actor`} URI. Putting an object in this channel is a way to broadcast\n * the object to the user's followers, like posting a tweet.\n * - The URL of a Graffiti post. Putting an object in this channel is a way to broadcast to anyone viewing\n * the post, like commenting on a tweet.\n * - A URI representing a topic. Putting an object in this channel is a way to broadcast to anyone interested\n * in that topic, like posting in a subreddit.\n */\n channels: string[];\n\n /**\n * An optional array of {@link actor | `actor`} URIs that the creator allows to access the object.\n * If no `allowed` array is provided, the object can be accessed by anyone (so long as they\n * also know the right {@link channels | `channel` } to look in). An object can always be accessed by its creator, even if\n * the `allowed` array is empty.\n *\n * The `allowed` array is not revealed to users other than the creator, like\n * a BCC email. A user may choose to add a `to` property to the object's {@link value | `value`} to indicate\n * other recipients, however this is not enforced by Graffiti and may not accurately reflect the actual `allowed` array.\n *\n * `allowed` can be combined with {@link channels | `channels`}. For example, to send someone a direct message\n * the sender should put their object in the channel of the recipient's {@link actor | `actor`} URI to notify them of the message and also add\n * the recipient's {@link actor | `actor`} URI to the `allowed` array to prevent others from seeing the message.\n */\n allowed?: string[] | null;\n\n /**\n * The URI of the `actor` that {@link Graffiti.put | created } the object. This `actor` also has the unique permission to\n * {@link Graffiti.patch | modify} or {@link Graffiti.delete | delete} the object.\n *\n * We borrow the term actor from the ActivityPub because\n * [like in ActivityPub](https://www.w3.org/TR/activitypub/#h-note-0)\n * there is not necessarily a one-to-one mapping between actors and people/users.\n * Multiple people can share the same actor or one person can have multiple actors.\n * Actors can also be bots.\n *\n * In Graffiti, actors are always globally unique URIs which\n * allows them to also function as {@link channels | `channels`}.\n */\n actor: string;\n\n /**\n * A globally unique identifier and locator for the object. It can be used to point to\n * an object or to retrieve the object directly with {@link Graffiti.get}.\n * If an object is {@link Graffiti.put | put} with the same URL\n * as an existing object, the existing object will be replaced with the new object.\n *\n * An object's URL is generated when the object is first created and\n * should include sufficient randomness to prevent collisions\n * and guessing. The URL starts with a \"scheme,\" just like web URLs start with `http` or `https`, to indicate\n * to indicate the particular Graffiti implementation. This allows for applications\n * to pull from multiple coexisting Graffiti implementations without collision.\n * Existing schemes include `graffiti:local:` for objects stored locally\n * (see the [local implementation](https://github.com/graffiti-garden/implementation-local))\n * and `graffiti:remote:` for objects stored on Graffiti-specific web servers (see the\n * [remote implementation](https://github.com/graffiti-garden/implementation-remote)).\n * Options available in the future might include `graffiti:solid:` for objects stored on Solid servers\n * or `graffiti:p2p:` for objects stored on a peer-to-peer network.\n */\n url: string;\n\n /**\n * The time the object was last modified, measured in milliseconds since January 1, 1970.\n * It can be used to compare object versions.\n * A number, rather than an ISO string or Date object, is used for easy comparison, sorting,\n * and JSON Schema [range queries](https://json-schema.org/understanding-json-schema/reference/numeric#range).\n *\n * It is possible to use this value to sort objects in a user's interface but in many cases it would be better to\n * use a [`published`](https://www.w3.org/TR/activitystreams-vocabulary/#dfn-published)\n * property in the object's {@link value | `value`} to indicate when the object was created\n * rather than when it was modified.\n */\n lastModified: number;\n}\n\n/**\n * This type constrains the {@link GraffitiObjectBase} type to adhere to a\n * particular [JSON schema](https://json-schema.org/).\n * This allows for static type-checking of an object's {@link GraffitiObjectBase.value | `value`}\n * which is otherwise a freeform JSON object.\n *\n * Schema-aware objects are returned by {@link Graffiti.get} and {@link Graffiti.discover}.\n */\nexport type GraffitiObject<Schema extends JSONSchema> = GraffitiObjectBase &\n FromSchema<Schema & typeof GraffitiObjectJSONSchema>;\n\n/**\n * A JSON Schema equivalent to the {@link GraffitiObjectBase} type.\n * Needed internally for type inference of JSON Schemas, but can\n * be used by implementations to validate objects.\n */\nexport const GraffitiObjectJSONSchema = {\n type: \"object\",\n properties: {\n value: { type: \"object\" },\n channels: { type: \"array\", items: { type: \"string\" } },\n allowed: { type: \"array\", items: { type: \"string\" }, nullable: true },\n url: { type: \"string\" },\n actor: { type: \"string\" },\n lastModified: { type: \"number\" },\n },\n additionalProperties: false,\n required: [\"value\", \"channels\", \"actor\", \"url\", \"lastModified\"],\n} as const satisfies JSONSchema;\n\n/**\n * This is an object containing only the {@link GraffitiObjectBase.url | `url`}\n * property of a {@link GraffitiObjectBase | GraffitiObject}.\n * It is used as a utility type so that users can call {@link Graffiti.get},\n * {@link Graffiti.patch}, or {@link Graffiti.delete} directly on an object\n * rather than on `object.url`.\n */\nexport type GraffitiObjectUrl = Pick<GraffitiObjectBase, \"url\">;\n\n/**\n * This object is a subset of {@link GraffitiObjectBase} that a user must construct locally before calling {@link Graffiti.put}.\n * This local copy does not require system-generated properties and may be statically typed with\n * a [JSON schema](https://json-schema.org/) to prevent the accidental creation of erroneous objects.\n *\n * This local object must have a {@link GraffitiObjectBase.value | `value`} and {@link GraffitiObjectBase.channels | `channels`}\n * and may optionally have an {@link GraffitiObjectBase.allowed | `allowed`} property.\n *\n * It may also include a {@link GraffitiObjectBase.url | `url`} property to specify the\n * URL of an existing object to replace. If no `url` is provided, one will be generated during object creation.\n *\n * This object does not need a {@link GraffitiObjectBase.lastModified | `lastModified`}\n * property since it will be automatically generated by the Graffiti system.\n */\nexport type GraffitiPutObject<Schema extends JSONSchema> = Pick<\n GraffitiObjectBase,\n \"value\" | \"channels\" | \"allowed\"\n> &\n Partial<GraffitiObjectBase> &\n FromSchema<Schema & typeof GraffitiPutObjectJSONSchema>;\n\n/**\n * A JSON Schema equivalent to the {@link GraffitiPutObject} type.\n * Needed internally for type inference of JSON Schemas, but can\n * be used by implementations to validate objects.\n */\nexport const GraffitiPutObjectJSONSchema = {\n ...GraffitiObjectJSONSchema,\n required: [\"value\", \"channels\"],\n} as const satisfies JSONSchema;\n\n/**\n * This object contains information that the underlying implementation can\n * use to verify that a user has permission to operate a\n * particular {@link GraffitiObjectBase.actor | `actor`}.\n * This object is required of all {@link Graffiti} methods\n * that modify objects and is optional for methods that read objects.\n *\n * At a minimum the `session` object must contain the\n * {@link GraffitiSession.actor | `actor`} URI the user wants to authenticate with.\n * However it is likely that the `session` object must contain other\n * implementation-specific properties.\n * For example, a Solid implementation might include a\n * [`fetch`](https://docs.inrupt.com/developer-tools/api/javascript/solid-client-authn-browser/functions.html#fetch)\n * function. A distributed implementation may include\n * a cryptographic signature.\n *\n * As to why the `session` object is passed as an argument to every method\n * rather than being an internal property of the {@link Graffiti} instance,\n * this is primarily for type-checking to catch bugs related to login state.\n * Graffiti applications can expose some functionality to users who are not logged in\n * with {@link Graffiti.get} and {@link Graffiti.discover} but without type-checking\n * the `session` it can be easy to forget to hide buttons that trigger\n * other methods that require login.\n * In the future, `session` object may be updated to include scope information\n * and passing the `session` to each method can type-check whether the session provides the\n * necessary permissions.\n *\n * Passing the `session` object per-method also allows for multiple sessions\n * to be used within the same application, like an Email client fetching from\n * multiple accounts.\n */\nexport interface GraffitiSession {\n /**\n * The {@link GraffitiObjectBase.actor | `actor`} a user wants to authenticate with.\n */\n actor: string;\n /**\n * A yet undefined property detailing what operations the session\n * grants the user to perform. For example, to allow a user to\n * read private messages from a particular set of channels or\n * to allow the user to write object matching a particular schema.\n */\n scope?: {};\n}\n\n/**\n * This is the format for patches that modify {@link GraffitiObjectBase} objects\n * using the {@link Graffiti.patch} method. The patches must\n * be an array of [JSON Patch](https://jsonpatch.com) operations.\n * Patches can only be applied to the\n * {@link GraffitiObjectBase.value | `value`}, {@link GraffitiObjectBase.channels | `channels`},\n * and {@link GraffitiObjectBase.allowed | `allowed`} properties since the other\n * properties either describe the object's location or are automatically generated.\n * (See also {@link GraffitiPutObject}).\n */\nexport interface GraffitiPatch {\n /**\n * An array of [JSON Patch](https://jsonpatch.com) operations to\n * modify the object's {@link GraffitiObjectBase.value | `value`}. The resulting\n * `value` must still be a JSON object.\n */\n value?: JSONPatchOperation[];\n\n /**\n * An array of [JSON Patch](https://jsonpatch.com) operations to\n * modify the object's {@link GraffitiObjectBase.channels | `channels`}. The resulting\n * `channels` must still be an array of strings.\n */\n channels?: JSONPatchOperation[];\n\n /**\n * An array of [JSON Patch](https://jsonpatch.com) operations to\n * modify the object's {@link GraffitiObjectBase.allowed | `allowed`} property. The resulting\n * `allowed` property must still be an array of strings or `undefined`.\n */\n allowed?: JSONPatchOperation[];\n}\n\n/**\n * A stream of data that are returned by Graffiti's query-like operations\n * {@link Graffiti.discover} and {@link Graffiti.recoverOrphans}.\n *\n * Errors are returned within the stream rather than as\n * exceptions that would halt the entire stream. This is because\n * some implementations may pull data from multiple sources\n * including some that may be unreliable. In many cases,\n * these errors can be safely ignored.\n * See {@link GraffitiStreamError}.\n *\n * The stream is an [`AsyncGenerator`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function)\n * that can be iterated over using `for await` loops or calling `next` on the generator.\n * The stream can be terminated by breaking out of a loop calling `return` on the generator.\n *\n * The stream ends by returning a {@link GraffitiObjectStreamReturn.continue | `continue`}\n * function and a {@link GraffitiObjectStreamReturn.cursor | `cursor`} string,\n * each of which can be used to resume the stream from where it left off.\n */\nexport type GraffitiObjectStream<Schema extends JSONSchema> = AsyncGenerator<\n GraffitiStreamError | GraffitiObjectStreamEntry<Schema>,\n GraffitiObjectStreamReturn<Schema>\n>;\n\n/**\n * An error that can occur in either the\n * {@link GraffitiObjectStream} or {@link GraffitiChannelStatsStream}.\n *\n * @internal\n */\nexport interface GraffitiStreamError {\n /**\n * The error that occurred while streaming data.\n */\n error: Error;\n /**\n * The origin that the error occurred. It will include\n * the scheme of the Graffiti implementation used and other\n * implementation-specific information like a hostname.\n */\n origin: string;\n}\n\n/**\n * A successful result from a {@link GraffitiObjectStream} or\n * {@link GraffitiObjectStreamContinue} that includes an object.\n *\n * @internal\n */\nexport interface GraffitiObjectStreamEntry<Schema extends JSONSchema> {\n /**\n * Empty property for compatibility with {@link GraffitiStreamError}\n */\n error?: undefined;\n /**\n * Empty property for compatibility with {@link GraffitiObjectStreamContinueTombstone}\n */\n tombstone?: undefined;\n /**\n * The object returned by the stream.\n */\n object: GraffitiObject<Schema>;\n}\n\n/**\n * A result from a {@link GraffitiObjectStreamContinue} that indicated\n * an object has been deleted since the original stream was run.\n * Only sparse metadata about the deleted object is returned to respect\n * the deleting user's privacy.\n *\n * @internal\n */\nexport interface GraffitiObjectStreamContinueTombstone {\n /**\n * Empty property for compatibility with {@link GraffitiStreamError}\n */\n error?: undefined;\n /**\n * Use this property to differentiate a tombstone from a\n * {@link GraffitiObjectStreamEntry}.\n */\n tombstone: true;\n /**\n * Sparse metadata about the deleted object. The full object is not returned\n * to respect a user's privacy.\n */\n object: {\n /**\n * The {@link GraffitiObjectBase.url | `url`} of the deleted object.\n */\n url: string;\n /**\n * The time at which the object was deleted, comparable to\n * {@link GraffitiObjectBase.lastModified | `lastModified`}.\n *\n * While it is not possible to re-{@link Graffiti.put | put} objects that have been\n * {@link Graffiti.delete | deleted}, objects may appear deleted if\n * an {@link GraffitiObjectBase.actor | `actor`} is no longer\n * {@link GraffitiObjectBase.allowed | `allowed`} to access them.\n * Therefore the {@link GraffitiObjectBase.lastModified | `lastModified`} property\n * is necessary to compare object versions.\n */\n lastModified: number;\n };\n}\n\n/**\n * A continuation of the {@link GraffitiObjectStream} type can include\n * both objects and tombstones of deleted objects.\n *\n * @internal\n */\nexport type GraffitiObjectStreamContinueEntry<Schema extends JSONSchema> =\n | GraffitiObjectStreamEntry<Schema>\n | GraffitiObjectStreamContinueTombstone;\n\n/**\n * The output of a {@link GraffitiObjectStream} or a {@link GraffitiObjectStreamContinue}\n * that allows the stream to be continued from where it left off.\n *\n * The {@link continue} function preserves the typing of the original stream,\n * where as the {@link cursor} string can be serialized for use after a user\n * has closed and reopened an application.\n *\n * The continued stream may include `tombstone`s of objects that have been\n * deleted since the original stream was run. See {@link GraffitiObjectStreamContinueTombstone}.\n * The continued stream may also return some objects that were already\n * returned by the original stream, depending on how much state the\n * underlying implementation is able to preserve.\n *\n * @internal\n */\nexport interface GraffitiObjectStreamReturn<Schema extends JSONSchema> {\n /**\n * @returns A function that creates new stream that continues from where the original stream left off.\n * It preserves the typing of the original stream.\n */\n continue: () => GraffitiObjectStreamContinue<Schema>;\n /**\n * A string that can be serialized and stored to resume the stream later.\n * It must be passed to the {@link Graffiti.continueObjectStream} method\n * to resume the stream.\n */\n cursor: string;\n}\n\n/**\n * A continutation of the {@link GraffitiObjectStream} type, as returned by\n * the {@link GraffitiObjectStreamReturn.continue} or by using\n * {@link GraffitiObjectStreamReturn.cursor} with {@link Graffiti.continueObjectStream}.\n *\n * The continued stream may include `tombstone`s of objects that have been\n * deleted since the original stream was run. See {@link GraffitiObjectStreamContinueTombstone}.\n *\n * @internal\n */\nexport type GraffitiObjectStreamContinue<Schema extends JSONSchema> =\n AsyncGenerator<\n GraffitiStreamError | GraffitiObjectStreamContinueEntry<Schema>,\n GraffitiObjectStreamReturn<Schema>\n >;\n\n/**\n * Statistic about single channel returned by {@link Graffiti.channelStats}.\n * These statistics only account for contributions made by the\n * querying actor.\n */\nexport type ChannelStats = {\n /**\n * The URI of the channel.\n */\n channel: string;\n /**\n * The number of objects that the actor has {@link Graffiti.put | put}\n * and not {@link Graffiti.delete | deleted} in the channel.\n */\n count: number;\n /**\n * The time that the actor {@link GraffitiObjectBase.lastModified | last modified} an object in the channel,\n * measured in milliseconds since January 1, 1970.\n * {@link Graffiti.delete | Deleted} objects do not effect this modification time.\n */\n lastModified: number;\n};\n\n/**\n * A stream of data that are returned by Graffiti's {@link Graffiti.channelStats} method.\n * See {@link GraffitiObjectStream} for more information on streams.\n */\nexport type GraffitiChannelStatsStream = AsyncGenerator<\n | GraffitiStreamError\n | {\n error?: undefined;\n value: ChannelStats;\n }\n>;\n\n/**\n * The event type produced in {@link Graffiti.sessionEvents}\n * when a user logs in manually from {@link Graffiti.login}\n * or when their session is restored from a previous login.\n * The event name to listen for is `login`.\n */\nexport type GraffitiLoginEvent = CustomEvent<\n | {\n error: Error;\n session?: undefined;\n }\n | {\n error?: undefined;\n session: GraffitiSession;\n }\n>;\n\n/**\n * The event type produced in {@link Graffiti.sessionEvents}\n * when a user logs out either manually with {@link Graffiti.logout}\n * or when their session times out or otherwise becomes invalid.\n * The event name to listen for is `logout`.\n */\nexport type GraffitiLogoutEvent = CustomEvent<\n | {\n error: Error;\n actor?: string;\n }\n | {\n error?: undefined;\n actor: string;\n }\n>;\n\n/**\n * The event type produced in {@link Graffiti.sessionEvents}\n * after an application has attempted to complete any login redirects\n * and restore any previously active sessions.\n * Successful session restores will be returned in parallel as\n * their own {@link GraffitiLoginEvent} events.\n *\n * This event optionally returns an `href` property\n * representing the URL the user originated a login request\n * from, which may be useful for redirecting the user back to\n * the page they were on after login.\n * The event name to listen for is `initialized`.\n */\nexport type GraffitiSessionInitializedEvent = CustomEvent<\n | {\n error?: Error;\n href?: string;\n }\n | null\n | undefined\n>;\n", "export class GraffitiErrorUnauthorized extends Error {\n constructor(message?: string) {\n super(message);\n this.name = \"GraffitiErrorUnauthorized\";\n Object.setPrototypeOf(this, GraffitiErrorUnauthorized.prototype);\n }\n}\n\nexport class GraffitiErrorForbidden extends Error {\n constructor(message?: string) {\n super(message);\n this.name = \"GraffitiErrorForbidden\";\n Object.setPrototypeOf(this, GraffitiErrorForbidden.prototype);\n }\n}\n\nexport class GraffitiErrorNotFound extends Error {\n constructor(message?: string) {\n super(message);\n this.name = \"GraffitiErrorNotFound\";\n Object.setPrototypeOf(this, GraffitiErrorNotFound.prototype);\n }\n}\n\nexport class GraffitiErrorInvalidSchema extends Error {\n constructor(message?: string) {\n super(message);\n this.name = \"GraffitiErrorInvalidSchema\";\n Object.setPrototypeOf(this, GraffitiErrorInvalidSchema.prototype);\n }\n}\n\nexport class GraffitiErrorSchemaMismatch extends Error {\n constructor(message?: string) {\n super(message);\n this.name = \"GraffitiErrorSchemaMismatch\";\n Object.setPrototypeOf(this, GraffitiErrorSchemaMismatch.prototype);\n }\n}\n\nexport class GraffitiErrorPatchTestFailed extends Error {\n constructor(message?: string) {\n super(message);\n this.name = \"GraffitiErrorPatchTestFailed\";\n Object.setPrototypeOf(this, GraffitiErrorPatchTestFailed.prototype);\n }\n}\n\nexport class GraffitiErrorPatchError extends Error {\n constructor(message?: string) {\n super(message);\n this.name = \"GraffitiErrorPatchError\";\n Object.setPrototypeOf(this, GraffitiErrorPatchError.prototype);\n }\n}\n\nexport class GraffitiErrorInvalidUrl extends Error {\n constructor(message?: string) {\n super(message);\n this.name = \"GraffitiErrorInvalidUrl\";\n Object.setPrototypeOf(this, GraffitiErrorInvalidUrl.prototype);\n }\n}\n\nexport class GraffitiErrorUnrecognizedUrlScheme extends Error {\n constructor(message?: string) {\n super(message);\n this.name = \"GraffitiErrorUnrecognizedUriScheme\";\n Object.setPrototypeOf(this, GraffitiErrorUnrecognizedUrlScheme.prototype);\n }\n}\n", "/// <reference types=\"./repeater.d.ts\" />\n/*! *****************************************************************************\r\nCopyright (c) Microsoft Corporation.\r\n\r\nPermission to use, copy, modify, and/or distribute this software for any\r\npurpose with or without fee is hereby granted.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\r\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\r\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\r\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\r\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\r\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\r\nPERFORMANCE OF THIS SOFTWARE.\r\n***************************************************************************** */\r\n/* global Reflect, Promise */\r\n\r\nvar extendStatics = function(d, b) {\r\n extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\r\n return extendStatics(d, b);\r\n};\r\n\r\nfunction __extends(d, b) {\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n}\r\n\r\nfunction __awaiter(thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n}\r\n\r\nfunction __generator(thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n}\r\n\r\nfunction __values(o) {\r\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\r\n if (m) return m.call(o);\r\n if (o && typeof o.length === \"number\") return {\r\n next: function () {\r\n if (o && i >= o.length) o = void 0;\r\n return { value: o && o[i++], done: !o };\r\n }\r\n };\r\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\r\n}\r\n\r\nfunction __await(v) {\r\n return this instanceof __await ? (this.v = v, this) : new __await(v);\r\n}\r\n\r\nfunction __asyncGenerator(thisArg, _arguments, generator) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\r\n return i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i;\r\n function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }\r\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\r\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\r\n function fulfill(value) { resume(\"next\", value); }\r\n function reject(value) { resume(\"throw\", value); }\r\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\r\n}\n\n/** An error subclass which is thrown when there are too many pending push or next operations on a single repeater. */\r\nvar RepeaterOverflowError = /** @class */ (function (_super) {\r\n __extends(RepeaterOverflowError, _super);\r\n function RepeaterOverflowError(message) {\r\n var _this = _super.call(this, message) || this;\r\n Object.defineProperty(_this, \"name\", {\r\n value: \"RepeaterOverflowError\",\r\n enumerable: false,\r\n });\r\n if (typeof Object.setPrototypeOf === \"function\") {\r\n Object.setPrototypeOf(_this, _this.constructor.prototype);\r\n }\r\n else {\r\n _this.__proto__ = _this.constructor.prototype;\r\n }\r\n if (typeof Error.captureStackTrace === \"function\") {\r\n Error.captureStackTrace(_this, _this.constructor);\r\n }\r\n return _this;\r\n }\r\n return RepeaterOverflowError;\r\n}(Error));\r\n/** A buffer which allows you to push a set amount of values to the repeater without pushes waiting or throwing errors. */\r\nvar FixedBuffer = /** @class */ (function () {\r\n function FixedBuffer(capacity) {\r\n if (capacity < 0) {\r\n throw new RangeError(\"Capacity may not be less than 0\");\r\n }\r\n this._c = capacity;\r\n this._q = [];\r\n }\r\n Object.defineProperty(FixedBuffer.prototype, \"empty\", {\r\n get: function () {\r\n return this._q.length === 0;\r\n },\r\n enumerable: false,\r\n configurable: true\r\n });\r\n Object.defineProperty(FixedBuffer.prototype, \"full\", {\r\n get: function () {\r\n return this._q.length >= this._c;\r\n },\r\n enumerable: false,\r\n configurable: true\r\n });\r\n FixedBuffer.prototype.add = function (value) {\r\n if (this.full) {\r\n throw new Error(\"Buffer full\");\r\n }\r\n else {\r\n this._q.push(value);\r\n }\r\n };\r\n FixedBuffer.prototype.remove = function () {\r\n if (this.empty) {\r\n throw new Error(\"Buffer empty\");\r\n }\r\n return this._q.shift();\r\n };\r\n return FixedBuffer;\r\n}());\r\n// TODO: Use a circular buffer here.\r\n/** Sliding buffers allow you to push a set amount of values to the repeater without pushes waiting or throwing errors. If the number of values exceeds the capacity set in the constructor, the buffer will discard the earliest values added. */\r\nvar SlidingBuffer = /** @class */ (function () {\r\n function SlidingBuffer(capacity) {\r\n if (capacity < 1) {\r\n throw new RangeError(\"Capacity may not be less than 1\");\r\n }\r\n this._c = capacity;\r\n this._q = [];\r\n }\r\n Object.defineProperty(SlidingBuffer.prototype, \"empty\", {\r\n get: function () {\r\n return this._q.length === 0;\r\n },\r\n enumerable: false,\r\n configurable: true\r\n });\r\n Object.defineProperty(SlidingBuffer.prototype, \"full\", {\r\n get: function () {\r\n return false;\r\n },\r\n enumerable: false,\r\n configurable: true\r\n });\r\n SlidingBuffer.prototype.add = function (value) {\r\n while (this._q.length >= this._c) {\r\n this._q.shift();\r\n }\r\n this._q.push(value);\r\n };\r\n SlidingBuffer.prototype.remove = function () {\r\n if (this.empty) {\r\n throw new Error(\"Buffer empty\");\r\n }\r\n return this._q.shift();\r\n };\r\n return SlidingBuffer;\r\n}());\r\n/** Dropping buffers allow you to push a set amount of values to the repeater without the push function waiting or throwing errors. If the number of values exceeds the capacity set in the constructor, the buffer will discard the latest values added. */\r\nvar DroppingBuffer = /** @class */ (function () {\r\n function DroppingBuffer(capacity) {\r\n if (capacity < 1) {\r\n throw new RangeError(\"Capacity may not be less than 1\");\r\n }\r\n this._c = capacity;\r\n this._q = [];\r\n }\r\n Object.defineProperty(DroppingBuffer.prototype, \"empty\", {\r\n get: function () {\r\n return this._q.length === 0;\r\n },\r\n enumerable: false,\r\n configurable: true\r\n });\r\n Object.defineProperty(DroppingBuffer.prototype, \"full\", {\r\n get: function () {\r\n return false;\r\n },\r\n enumerable: false,\r\n configurable: true\r\n });\r\n DroppingBuffer.prototype.add = function (value) {\r\n if (this._q.length < this._c) {\r\n this._q.push(value);\r\n }\r\n };\r\n DroppingBuffer.prototype.remove = function () {\r\n if (this.empty) {\r\n throw new Error(\"Buffer empty\");\r\n }\r\n return this._q.shift();\r\n };\r\n return DroppingBuffer;\r\n}());\r\n/** Makes sure promise-likes don\u2019t cause unhandled rejections. */\r\nfunction swallow(value) {\r\n if (value != null && typeof value.then === \"function\") {\r\n value.then(NOOP, NOOP);\r\n }\r\n}\r\n/*** REPEATER STATES ***/\r\n/** The following is an enumeration of all possible repeater states. These states are ordered, and a repeater may only advance to higher states. */\r\n/** The initial state of the repeater. */\r\nvar Initial = 0;\r\n/** Repeaters advance to this state the first time the next method is called on the repeater. */\r\nvar Started = 1;\r\n/** Repeaters advance to this state when the stop function is called. */\r\nvar Stopped = 2;\r\n/** Repeaters advance to this state when there are no values left to be pulled from the repeater. */\r\nvar Done = 3;\r\n/** Repeaters advance to this state if an error is thrown into the repeater. */\r\nvar Rejected = 4;\r\n/** The maximum number of push or next operations which may exist on a single repeater. */\r\nvar MAX_QUEUE_LENGTH = 1024;\r\nvar NOOP = function () { };\r\n/** A helper function used to mimic the behavior of async generators where the final iteration is consumed. */\r\nfunction consumeExecution(r) {\r\n var err = r.err;\r\n var execution = Promise.resolve(r.execution).then(function (value) {\r\n if (err != null) {\r\n throw err;\r\n }\r\n return value;\r\n });\r\n r.err = undefined;\r\n r.execution = execution.then(function () { return undefined; }, function () { return undefined; });\r\n return r.pending === undefined ? execution : r.pending.then(function () { return execution; });\r\n}\r\n/** A helper function for building iterations from values. Promises are unwrapped, so that iterations never have their value property set to a promise. */\r\nfunction createIteration(r, value) {\r\n var done = r.state >= Done;\r\n return Promise.resolve(value).then(function (value) {\r\n if (!done && r.state >= Rejected) {\r\n return consumeExecution(r).then(function (value) { return ({\r\n value: value,\r\n done: true,\r\n }); });\r\n }\r\n return { value: value, done: done };\r\n });\r\n}\r\n/**\r\n * This function is bound and passed to the executor as the stop argument.\r\n *\r\n * Advances state to Stopped.\r\n */\r\nfunction stop(r, err) {\r\n var e_1, _a;\r\n if (r.state >= Stopped) {\r\n return;\r\n }\r\n r.state = Stopped;\r\n r.onnext();\r\n r.onstop();\r\n if (r.err == null) {\r\n r.err = err;\r\n }\r\n if (r.pushes.length === 0 &&\r\n (typeof r.buffer === \"undefined\" || r.buffer.empty)) {\r\n finish(r);\r\n }\r\n else {\r\n try {\r\n for (var _b = __values(r.pushes), _d = _b.next(); !_d.done; _d = _b.next()) {\r\n var push_1 = _d.value;\r\n push_1.resolve();\r\n }\r\n }\r\n catch (e_1_1) { e_1 = { error: e_1_1 }; }\r\n finally {\r\n try {\r\n if (_d && !_d.done && (_a = _b.return)) _a.call(_b);\r\n }\r\n finally { if (e_1) throw e_1.error; }\r\n }\r\n }\r\n}\r\n/**\r\n * The difference between stopping a repeater vs finishing a repeater is that stopping a repeater allows next to continue to drain values from the push queue and buffer, while finishing a repeater will clear all pending values and end iteration immediately. Once, a repeater is finished, all iterations will have the done property set to true.\r\n *\r\n * Advances state to Done.\r\n */\r\nfunction finish(r) {\r\n var e_2, _a;\r\n if (r.state >= Done) {\r\n return;\r\n }\r\n if (r.state < Stopped) {\r\n stop(r);\r\n }\r\n r.state = Done;\r\n r.buffer = undefined;\r\n try {\r\n for (var _b = __values(r.nexts), _d = _b.next(); !_d.done; _d = _b.next()) {\r\n var next = _d.value;\r\n var execution = r.pending === undefined\r\n ? consumeExecution(r)\r\n : r.pending.then(function () { return consumeExecution(r); });\r\n next.resolve(createIteration(r, execution));\r\n }\r\n }\r\n catch (e_2_1) { e_2 = { error: e_2_1 }; }\r\n finally {\r\n try {\r\n if (_d && !_d.done && (_a = _b.return)) _a.call(_b);\r\n }\r\n finally { if (e_2) throw e_2.error; }\r\n }\r\n r.pushes = [];\r\n r.nexts = [];\r\n}\r\n/**\r\n * Called when a promise passed to push rejects, or when a push call is unhandled.\r\n *\r\n * Advances state to Rejected.\r\n */\r\nfunction reject(r) {\r\n if (r.state >= Rejected) {\r\n return;\r\n }\r\n if (r.state < Done) {\r\n finish(r);\r\n }\r\n r.state = Rejected;\r\n}\r\n/** This function is bound and passed to the executor as the push argument. */\r\nfunction push(r, value) {\r\n swallow(value);\r\n if (r.pushes.length >= MAX_QUEUE_LENGTH) {\r\n throw new RepeaterOverflowError(\"No more than \" + MAX_QUEUE_LENGTH + \" pending calls to push are allowed on a single repeater.\");\r\n }\r\n else if (r.state >= Stopped) {\r\n return Promise.resolve(undefined);\r\n }\r\n var valueP = r.pending === undefined\r\n ? Promise.resolve(value)\r\n : r.pending.then(function () { return value; });\r\n valueP = valueP.catch(function (err) {\r\n if (r.state < Stopped) {\r\n r.err = err;\r\n }\r\n reject(r);\r\n return undefined; // void :(\r\n });\r\n var nextP;\r\n if (r.nexts.length) {\r\n var next_1 = r.nexts.shift();\r\n next_1.resolve(createIteration(r, valueP));\r\n if (r.nexts.length) {\r\n nextP = Promise.resolve(r.nexts[0].value);\r\n }\r\n else if (typeof r.buffer !== \"undefined\" && !r.buffer.full) {\r\n nextP = Promise.resolve(undefined);\r\n }\r\n else {\r\n nextP = new Promise(function (resolve) { return (r.onnext = resolve); });\r\n }\r\n }\r\n else if (typeof r.buffer !== \"undefined\" && !r.buffer.full) {\r\n r.buffer.add(valueP);\r\n nextP = Promise.resolve(undefined);\r\n }\r\n else {\r\n nextP = new Promise(function (resolve) { return r.pushes.push({ resolve: resolve, value: valueP }); });\r\n }\r\n // If an error is thrown into the repeater via the next or throw methods, we give the repeater a chance to handle this by rejecting the promise returned from push. If the push call is not immediately handled we throw the next iteration of the repeater.\r\n // To check that the promise returned from push is floating, we modify the then and catch methods of the returned promise so that they flip the floating flag. The push function actually does not return a promise, because modern engines do not call the then and catch methods on native promises. By making next a plain old javascript object, we ensure that the then and catch methods will be called.\r\n var floating = true;\r\n var next = {};\r\n var unhandled = nextP.catch(function (err) {\r\n if (floating) {\r\n throw err;\r\n }\r\n return undefined; // void :(\r\n });\r\n next.then = function (onfulfilled, onrejected) {\r\n floating = false;\r\n return Promise.prototype.then.call(nextP, onfulfilled, onrejected);\r\n };\r\n next.catch = function (onrejected) {\r\n floating = false;\r\n return Promise.prototype.catch.call(nextP, onrejected);\r\n };\r\n next.finally = nextP.finally.bind(nextP);\r\n r.pending = valueP\r\n .then(function () { return unhandled; })\r\n .catch(function (err) {\r\n r.err = err;\r\n reject(r);\r\n });\r\n return next;\r\n}\r\n/**\r\n * Creates the stop callable promise which is passed to the executor\r\n */\r\nfunction createStop(r) {\r\n var stop1 = stop.bind(null, r);\r\n var stopP = new Promise(function (resolve) { return (r.onstop = resolve); });\r\n stop1.then = stopP.then.bind(stopP);\r\n stop1.catch = stopP.catch.bind(stopP);\r\n stop1.finally = stopP.finally.bind(stopP);\r\n return stop1;\r\n}\r\n/**\r\n * Calls the executor passed into the constructor. This function is called the first time the next method is called on the repeater.\r\n *\r\n * Advances state to Started.\r\n */\r\nfunction execute(r) {\r\n if (r.state >= Started) {\r\n return;\r\n }\r\n r.state = Started;\r\n var push1 = push.bind(null, r);\r\n var stop1 = createStop(r);\r\n r.execution = new Promise(function (resolve) { return resolve(r.executor(push1, stop1)); });\r\n // TODO: We should consider stopping all repeaters when the executor settles.\r\n r.execution.catch(function () { return stop(r); });\r\n}\r\nvar records = new WeakMap();\r\n// NOTE: While repeaters implement and are assignable to the AsyncGenerator interface, and you can use the types interchangeably, we don\u2019t use typescript\u2019s implements syntax here because this would make supporting earlier versions of typescript trickier. This is because TypeScript version 3.6 changed the iterator types by adding the TReturn and TNext type parameters.\r\nvar Repeater = /** @class */ (function () {\r\n function Repeater(executor, buffer) {\r\n records.set(this, {\r\n executor: executor,\r\n buffer: buffer,\r\n err: undefined,\r\n state: Initial,\r\n pushes: [],\r\n nexts: [],\r\n pending: undefined,\r\n execution: undefined,\r\n onnext: NOOP,\r\n onstop: NOOP,\r\n });\r\n }\r\n Repeater.prototype.next = function (value) {\r\n swallow(value);\r\n var r = records.get(this);\r\n if (r === undefined) {\r\n throw new Error(\"WeakMap error\");\r\n }\r\n if (r.nexts.length >= MAX_QUEUE_LENGTH) {\r\n throw new RepeaterOverflowError(\"No more than \" + MAX_QUEUE_LENGTH + \" pending calls to next are allowed on a single repeater.\");\r\n }\r\n if (r.state <= Initial) {\r\n execute(r);\r\n }\r\n r.onnext(value);\r\n if (typeof r.buffer !== \"undefined\" && !r.buffer.empty) {\r\n var result = createIteration(r, r.buffer.remove());\r\n if (r.pushes.length) {\r\n var push_2 = r.pushes.shift();\r\n r.buffer.add(push_2.value);\r\n r.onnext = push_2.resolve;\r\n }\r\n return result;\r\n }\r\n else if (r.pushes.length) {\r\n var push_3 = r.pushes.shift();\r\n r.onnext = push_3.resolve;\r\n return createIteration(r, push_3.value);\r\n }\r\n else if (r.state >= Stopped) {\r\n finish(r);\r\n return createIteration(r, consumeExecution(r));\r\n }\r\n return new Promise(function (resolve) { return r.nexts.push({ resolve: resolve, value: value }); });\r\n };\r\n Repeater.prototype.return = function (value) {\r\n swallow(value);\r\n var r = records.get(this);\r\n if (r === undefined) {\r\n throw new Error(\"WeakMap error\");\r\n }\r\n finish(r);\r\n // We override the execution because return should always return the value passed in.\r\n r.execution = Promise.resolve(r.execution).then(function () { return value; });\r\n return createIteration(r, consumeExecution(r));\r\n };\r\n Repeater.prototype.throw = function (err) {\r\n var r = records.get(this);\r\n if (r === undefined) {\r\n throw new Error(\"WeakMap error\");\r\n }\r\n if (r.state <= Initial ||\r\n r.state >= Stopped ||\r\n (typeof r.buffer !== \"undefined\" && !r.buffer.empty)) {\r\n finish(r);\r\n // If r.err is already set, that mean the repeater has already produced an error, so we throw that error rather than the error passed in, because doing so might be more informative for the caller.\r\n if (r.err == null) {\r\n r.err = err;\r\n }\r\n return createIteration(r, consumeExecution(r));\r\n }\r\n return this.next(Promise.reject(err));\r\n };\r\n Repeater.prototype[Symbol.asyncIterator] = function () {\r\n return this;\r\n };\r\n // TODO: Remove these static methods from the class.\r\n Repeater.race = race;\r\n Repeater.merge = merge;\r\n Repeater.zip = zip;\r\n Repeater.latest = latest;\r\n return Repeater;\r\n}());\r\n/*** COMBINATOR FUNCTIONS ***/\r\n// TODO: move these combinators to their own file.\r\nfunction getIterators(values, options) {\r\n var e_3, _a;\r\n var iters = [];\r\n var _loop_1 = function (value) {\r\n if (value != null && typeof value[Symbol.asyncIterator] === \"function\") {\r\n iters.push(value[Symbol.asyncIterator]());\r\n }\r\n else if (value != null && typeof value[Symbol.iterator] === \"function\") {\r\n iters.push(value[Symbol.iterator]());\r\n }\r\n else {\r\n iters.push((function valueToAsyncIterator() {\r\n return __asyncGenerator(this, arguments, function valueToAsyncIterator_1() {\r\n return __generator(this, function (_a) {\r\n switch (_a.label) {\r\n case 0:\r\n if (!options.yieldValues) return [3 /*break*/, 3];\r\n return [4 /*yield*/, __await(value)];\r\n case 1: return [4 /*yield*/, _a.sent()];\r\n case 2:\r\n _a.sent();\r\n _a.label = 3;\r\n case 3:\r\n if (!options.returnValues) return [3 /*break*/, 5];\r\n return [4 /*yield*/, __await(value)];\r\n case 4: return [2 /*return*/, _a.sent()];\r\n case 5: return [2 /*return*/];\r\n }\r\n });\r\n });\r\n })());\r\n }\r\n };\r\n try {\r\n for (var values_1 = __values(values), values_1_1 = values_1.next(); !values_1_1.done; values_1_1 = values_1.next()) {\r\n var value = values_1_1.value;\r\n _loop_1(value);\r\n }\r\n }\r\n catch (e_3_1) { e_3 = { error: e_3_1 }; }\r\n finally {\r\n try {\r\n if (values_1_1 && !values_1_1.done && (_a = values_1.return)) _a.call(values_1);\r\n }\r\n finally { if (e_3) throw e_3.error; }\r\n }\r\n return iters;\r\n}\r\n// NOTE: whenever you see any variables called `advance` or `advances`, know that it is a hack to get around the fact that `Promise.race` leaks memory. These variables are intended to be set to the resolve function of a promise which is constructed and awaited as an alternative to Promise.race. For more information, see this comment in the Node.js issue tracker: https://github.com/nodejs/node/issues/17469#issuecomment-685216777.\r\nfunction race(contenders) {\r\n var _this = this;\r\n var iters = getIterators(contenders, { returnValues: true });\r\n return new Repeater(function (push, stop) { return __awaiter(_this, void 0, void 0, function () {\r\n var advance, stopped, finalIteration, iteration, i_1, _loop_2;\r\n return __generator(this, function (_a) {\r\n switch (_a.label) {\r\n case 0:\r\n if (!iters.length) {\r\n stop();\r\n return [2 /*return*/];\r\n }\r\n stopped = false;\r\n stop.then(function () {\r\n advance();\r\n stopped = true;\r\n });\r\n _a.label = 1;\r\n case 1:\r\n _a.trys.push([1, , 5, 7]);\r\n iteration = void 0;\r\n i_1 = 0;\r\n _loop_2 = function () {\r\n var j, iters_1, iters_1_1, iter;\r\n var e_4, _a;\r\n return __generator(this, function (_b) {\r\n switch (_b.label) {\r\n case 0:\r\n j = i_1;\r\n try {\r\n for (iters_1 = (e_4 = void 0, __values(iters)), iters_1_1 = iters_1.next(); !iters_1_1.done; iters_1_1 = iters_1.next()) {\r\n iter = iters_1_1.value;\r\n Promise.resolve(iter.next()).then(function (iteration) {\r\n if (iteration.done) {\r\n stop();\r\n if (finalIteration === undefined) {\r\n finalIteration = iteration;\r\n }\r\n }\r\n else if (i_1 === j) {\r\n // This iterator has won, advance i and resolve the promise.\r\n i_1++;\r\n advance(iteration);\r\n }\r\n }, function (err) { return stop(err); });\r\n }\r\n }\r\n catch (e_4_1) { e_4 = { error: e_4_1 }; }\r\n finally {\r\n try {\r\n if (iters_1_1 && !iters_1_1.done && (_a = iters_1.return)) _a.call(iters_1);\r\n }\r\n finally { if (e_4) throw e_4.error; }\r\n }\r\n return [4 /*yield*/, new Promise(function (resolve) { return (advance = resolve); })];\r\n case 1:\r\n iteration = _b.sent();\r\n if (!(iteration !== undefined)) return [3 /*break*/, 3];\r\n return [4 /*yield*/, push(iteration.value)];\r\n case 2:\r\n _b.sent();\r\n _b.label = 3;\r\n case 3: return [2 /*return*/];\r\n }\r\n });\r\n };\r\n _a.label = 2;\r\n case 2:\r\n if (!!stopped) return [3 /*break*/, 4];\r\n return [5 /*yield**/, _loop_2()];\r\n case 3:\r\n _a.sent();\r\n return [3 /*break*/, 2];\r\n case 4: return [2 /*return*/, finalIteration && finalIteration.value];\r\n case 5:\r\n stop();\r\n return [4 /*yield*/, Promise.race(iters.map(function (iter) { return iter.return && iter.return(); }))];\r\n case 6:\r\n _a.sent();\r\n return [7 /*endfinally*/];\r\n case 7: return [2 /*return*/];\r\n }\r\n });\r\n }); });\r\n}\r\nfunction merge(contenders) {\r\n var _this = this;\r\n var iters = getIterators(contenders, { yieldValues: true });\r\n return new Repeater(function (push, stop) { return __awaiter(_this, void 0, void 0, function () {\r\n var advances, stopped, finalIteration;\r\n var _this = this;\r\n return __generator(this, function (_a) {\r\n switch (_a.label) {\r\n case 0:\r\n if (!iters.length) {\r\n stop();\r\n return [2 /*return*/];\r\n }\r\n advances = [];\r\n stopped = false;\r\n stop.then(function () {\r\n var e_5, _a;\r\n stopped = true;\r\n try {\r\n for (var advances_1 = __values(advances), advances_1_1 = advances_1.next(); !advances_1_1.done; advances_1_1 = advances_1.next()) {\r\n var advance = advances_1_1.value;\r\n advance();\r\n }\r\n }\r\n catch (e_5_1) { e_5 = { error: e_5_1 }; }\r\n finally {\r\n try {\r\n if (advances_1_1 && !advances_1_1.done && (_a = advances_1.return)) _a.call(advances_1);\r\n }\r\n finally { if (e_5) throw e_5.error; }\r\n }\r\n });\r\n _a.label = 1;\r\n case 1:\r\n _a.trys.push([1, , 3, 4]);\r\n return [4 /*yield*/, Promise.all(iters.map(function (iter, i) { return __awaiter(_this, void 0, void 0, function () {\r\n var iteration, _a;\r\n return __generator(this, function (_b) {\r\n switch (_b.label) {\r\n case 0:\r\n _b.trys.push([0, , 6, 9]);\r\n _b.label = 1;\r\n case 1:\r\n if (!!stopped) return [3 /*break*/, 5];\r\n Promise.resolve(iter.next()).then(function (iteration) { return advances[i](iteration); }, function (err) { return stop(err); });\r\n return [4 /*yield*/, new Promise(function (resolve) {\r\n advances[i] = resolve;\r\n })];\r\n case 2:\r\n iteration = _b.sent();\r\n if (!(iteration !== undefined)) return [3 /*break*/, 4];\r\n if (iteration.done) {\r\n finalIteration = iteration;\r\n return [2 /*return*/];\r\n }\r\n return [4 /*yield*/, push(iteration.value)];\r\n case 3:\r\n _b.sent();\r\n _b.label = 4;\r\n case 4: return [3 /*break*/, 1];\r\n case 5: return [3 /*break*/, 9];\r\n case 6:\r\n _a = iter.return;\r\n if (!_a) return [3 /*break*/, 8];\r\n return [4 /*yield*/, iter.return()];\r\n case 7:\r\n _a = (_b.sent());\r\n _b.label = 8;\r\n case 8:\r\n return [7 /*endfinally*/];\r\n case 9: return [2 /*return*/];\r\n }\r\n });\r\n }); }))];\r\n case 2:\r\n _a.sent();\r\n return [2 /*return*/, finalIteration && finalIteration.value];\r\n case 3:\r\n stop();\r\n return [7 /*endfinally*/];\r\n case 4: return [2 /*return*/];\r\n }\r\n });\r\n }); });\r\n}\r\nfunction zip(contenders) {\r\n var _this = this;\r\n var iters = getIterators(contenders, { returnValues: true });\r\n return new Repeater(function (push, stop) { return __awaiter(_this, void 0, void 0, function () {\r\n var advance, stopped, iterations, values;\r\n return __generator(this, function (_a) {\r\n switch (_a.label) {\r\n case 0:\r\n if (!iters.length) {\r\n stop();\r\n return [2 /*return*/, []];\r\n }\r\n stopped = false;\r\n stop.then(function () {\r\n advance();\r\n stopped = true;\r\n });\r\n _a.label = 1;\r\n case 1:\r\n _a.trys.push([1, , 6, 8]);\r\n _a.label = 2;\r\n case 2:\r\n if (!!stopped) return [3 /*break*/, 5];\r\n Promise.all(iters.map(function (iter) { return iter.next(); })).then(function (iterations) { return advance(iterations); }, function (err) { return stop(err); });\r\n return [4 /*yield*/, new Promise(function (resolve) { return (advance = resolve); })];\r\n case 3:\r\n iterations = _a.sent();\r\n if (iterations === undefined) {\r\n return [2 /*return*/];\r\n }\r\n values = iterations.map(function (iteration) { return iteration.value; });\r\n if (iterations.some(function (iteration) { return iteration.done; })) {\r\n return [2 /*return*/, values];\r\n }\r\n return [4 /*yield*/, push(values)];\r\n case 4:\r\n _a.sent();\r\n return [3 /*break*/, 2];\r\n case 5: return [3 /*break*/, 8];\r\n case 6:\r\n stop();\r\n return [4 /*yield*/, Promise.all(iters.map(function (iter) { return iter.return && iter.return(); }))];\r\n case 7:\r\n _a.sent();\r\n return [7 /*endfinally*/];\r\n case 8: return [2 /*return*/];\r\n }\r\n });\r\n }); });\r\n}\r\nfunction latest(contenders) {\r\n var _this = this;\r\n var iters = getIterators(contenders, {\r\n yieldValues: true,\r\n returnValues: true,\r\n });\r\n return new Repeater(function (push, stop) { return __awaiter(_this, void 0, void 0, function () {\r\n var advance, advances, stopped, iterations_1, values_2;\r\n var _this = this;\r\n return __generator(this, function (_a) {\r\n switch (_a.label) {\r\n case 0:\r\n if (!iters.length) {\r\n stop();\r\n return [2 /*return*/, []];\r\n }\r\n advances = [];\r\n stopped = false;\r\n stop.then(function () {\r\n var e_6, _a;\r\n advance();\r\n try {\r\n for (var advances_2 = __values(advances), advances_2_1 = advances_2.next(); !advances_2_1.done; advances_2_1 = advances_2.next()) {\r\n var advance1 = advances_2_1.value;\r\n advance1();\r\n }\r\n }\r\n catch (e_6_1) { e_6 = { error: e_6_1 }; }\r\n finally {\r\n try {\r\n if (advances_2_1 && !advances_2_1.done && (_a = advances_2.return)) _a.call(advances_2);\r\n }\r\n finally { if (e_6) throw e_6.error; }\r\n }\r\n stopped = true;\r\n });\r\n _a.label = 1;\r\n case 1:\r\n _a.trys.push([1, , 5, 7]);\r\n Promise.all(iters.map(function (iter) { return iter.next(); })).then(function (iterations) { return advance(iterations); }, function (err) { return stop(err); });\r\n return [4 /*yield*/, new Promise(function (resolve) { return (advance = resolve); })];\r\n case 2:\r\n iterations_1 = _a.sent();\r\n if (iterations_1 === undefined) {\r\n return [2 /*return*/];\r\n }\r\n values_2 = iterations_1.map(function (iteration) { return iteration.value; });\r\n if (iterations_1.every(function (iteration) { return iteration.done; })) {\r\n return [2 /*return*/, values_2];\r\n }\r\n // We continuously yield and mutate the same values array so we shallow copy it each time it is pushed.\r\n return [4 /*yield*/, push(values_2.slice())];\r\n case 3:\r\n // We continuously yield and mutate the same values array so we shallow copy it each time it is pushed.\r\n _a.sent();\r\n return [4 /*yield*/, Promise.all(iters.map(function (iter, i) { return __awaiter(_this, void 0, void 0, function () {\r\n var iteration;\r\n return __generator(this, function (_a) {\r\n switch (_a.label) {\r\n case 0:\r\n if (iterations_1[i].done) {\r\n return [2 /*return*/, iterations_1[i].value];\r\n }\r\n _a.label = 1;\r\n case 1:\r\n if (!!stopped) return [3 /*break*/, 4];\r\n Promise.resolve(iter.next()).then(function (iteration) { return advances[i](iteration); }, function (err) { return stop(err); });\r\n return [4 /*yield*/, new Promise(function (resolve) { return (advances[i] = resolve); })];\r\n case 2:\r\n iteration = _a.sent();\r\n if (iteration === undefined) {\r\n return [2 /*return*/, iterations_1[i].value];\r\n }\r\n else if (iteration.done) {\r\n return [2 /*return*/, iteration.value];\r\n }\r\n values_2[i] = iteration.value;\r\n return [4 /*yield*/, push(values_2.slice())];\r\n case 3:\r\n _a.sent();\r\n return [3 /*break*/, 1];\r\n case 4: return [2 /*return*/];\r\n }\r\n });\r\n }); }))];\r\n case 4: return [2 /*return*/, _a.sent()];\r\n case 5:\r\n stop();\r\n return [4 /*yield*/, Promise.all(iters.map(function (iter) { return iter.return && iter.return(); }))];\r\n case 6:\r\n _a.sent();\r\n return [7 /*endfinally*/];\r\n case 7: return [2 /*return*/];\r\n }\r\n });\r\n }); });\r\n}\n\nexport { DroppingBuffer, FixedBuffer, MAX_QUEUE_LENGTH, Repeater, RepeaterOverflowError, SlidingBuffer };\n//# sourceMappingURL=repeater.js.map\n", "import {\n GraffitiErrorInvalidSchema,\n GraffitiErrorPatchError,\n GraffitiErrorPatchTestFailed,\n} from \"@graffiti-garden/api\";\nimport type {\n GraffitiObject,\n GraffitiObjectBase,\n GraffitiPatch,\n JSONSchema,\n GraffitiSession,\n GraffitiObjectUrl,\n} from \"@graffiti-garden/api\";\nimport type { Ajv } from \"ajv\";\nimport type { applyPatch } from \"fast-json-patch\";\n\nexport function unpackObjectUrl(url: string | GraffitiObjectUrl) {\n return typeof url === \"string\" ? url : url.url;\n}\n\nexport function randomBase64(numBytes: number = 24) {\n const bytes = new Uint8Array(numBytes);\n crypto.getRandomValues(bytes);\n // Convert it to base64\n const base64 = btoa(String.fromCodePoint(...bytes));\n // Make sure it is url safe\n return base64.replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/\\=+$/, \"\");\n}\n\nexport function applyGraffitiPatch<Prop extends keyof GraffitiPatch>(\n apply: typeof applyPatch,\n prop: Prop,\n patch: GraffitiPatch,\n object: GraffitiObjectBase,\n): void {\n const ops = patch[prop];\n if (!ops || !ops.length) return;\n try {\n object[prop] = apply(object[prop], ops, true, false).newDocument;\n } catch (e) {\n if (\n typeof e === \"object\" &&\n e &&\n \"name\" in e &&\n typeof e.name === \"string\" &&\n \"message\" in e &&\n typeof e.message === \"string\"\n ) {\n if (e.name === \"TEST_OPERATION_FAILED\") {\n throw new GraffitiErrorPatchTestFailed(e.message);\n } else {\n throw new GraffitiErrorPatchError(e.name + \": \" + e.message);\n }\n } else {\n throw e;\n }\n }\n}\n\nexport function compileGraffitiObjectSchema<Schema extends JSONSchema>(\n ajv: Ajv,\n schema: Schema,\n) {\n try {\n // Force the validation guard because\n // it is too big for the type checker.\n // Fortunately json-schema-to-ts is\n // well tested against ajv.\n return ajv.compile(schema) as (\n data: GraffitiObjectBase,\n ) => data is GraffitiObject<Schema>;\n } catch (error) {\n throw new GraffitiErrorInvalidSchema(\n error instanceof Error ? error.message : undefined,\n );\n }\n}\n\nexport function maskGraffitiObject(\n object: GraffitiObjectBase,\n channels: string[],\n session?: GraffitiSession | null,\n): void {\n if (object.actor !== session?.actor) {\n object.allowed = object.allowed && session ? [session.actor] : undefined;\n object.channels = object.channels.filter((channel) =>\n channels.includes(channel),\n );\n }\n}\nexport function isActorAllowedGraffitiObject(\n object: GraffitiObjectBase,\n session?: GraffitiSession | null,\n) {\n return (\n object.allowed === undefined ||\n object.allowed === null ||\n (!!session?.actor &&\n (object.actor === session.actor ||\n object.allowed.includes(session.actor)))\n );\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type Ajv from \"ajv\";\nimport { Graffiti } from \"@graffiti-garden/api\";\nimport type {\n GraffitiSession,\n JSONSchema,\n GraffitiObjectStream,\n GraffitiObjectStreamContinueEntry,\n GraffitiObjectStreamContinue,\n GraffitiObject,\n} from \"@graffiti-garden/api\";\nimport type { GraffitiObjectBase } from \"@graffiti-garden/api\";\nimport { Repeater } from \"@repeaterjs/repeater\";\nimport type { applyPatch } from \"fast-json-patch\";\nimport {\n applyGraffitiPatch,\n compileGraffitiObjectSchema,\n isActorAllowedGraffitiObject,\n maskGraffitiObject,\n unpackObjectUrl,\n} from \"@graffiti-garden/implementation-local/utilities\";\nexport type * from \"@graffiti-garden/api\";\n\nexport type GraffitiSynchronizeCallback = (\n oldObject: GraffitiObjectStreamContinueEntry<{}>,\n newObject?: GraffitiObjectStreamContinueEntry<{}>,\n) => void;\n\nexport interface GraffitiSynchronizeOptions {\n /**\n * Allows synchronize to listen to all objects, not just those\n * that the session is allowed to see. This is useful to get a\n * global view of all Graffiti objects passsing through the system,\n * for example to build a client-side cache. Additional mechanisms\n * should be in place to ensure that users do not see objects or\n * properties they are not allowed to see.\n *\n * Default: `false`\n */\n omniscient?: boolean;\n}\n\n/**\n * Wraps the [Graffiti API](https://api.graffiti.garden/classes/Graffiti.html)\n * so that changes made or received in one part of an application\n * are automatically routed to other parts of the application.\n * This is an important tool for building responsive\n * and consistent user interfaces, and is built upon to make\n * the [Graffiti Vue Plugin](https://vue.graffiti.garden/variables/GraffitiPlugin.html)\n * and possibly other front-end libraries in the future.\n *\n * Specifically, it provides the following *synchronize*\n * methods for each of the following API methods:\n *\n * | API Method | Synchronize Method |\n * |------------|--------------------|\n * | {@link get} | {@link synchronizeGet} |\n * | {@link discover} | {@link synchronizeDiscover} |\n * | {@link recoverOrphans} | {@link synchronizeRecoverOrphans} |\n *\n * Whenever a change is made via {@link put}, {@link patch}, and {@link delete} or\n * received from {@link get}, {@link discover}, and {@link recoverOrphans},\n * those changes are forwarded to the appropriate synchronize method.\n * Each synchronize method returns an iterator that streams these changes\n * continually until the user calls `return` on the iterator or `break`s out of the loop,\n * allowing for live updates without additional polling.\n *\n * Example 1: Suppose a user publishes a post using {@link put}. If the feed\n * displaying that user's posts is using {@link synchronizeDiscover} to listen for changes,\n * then the user's new post will instantly appear in their feed, giving the UI a\n * responsive feel.\n *\n * Example 2: Suppose one of a user's friends changes their name. As soon as the\n * user's application receives one notice of that change (using {@link get}\n * or {@link discover}), then {@link synchronizeDiscover} listeners can be used to update\n * all instance's of that friend's name in the user's application instantly,\n * providing a consistent user experience.\n *\n * @groupDescription Synchronize Methods\n * This group contains methods that listen for changes made via\n * {@link put}, {@link patch}, and {@link delete} or fetched from\n * {@link get}, {@link discover}, and {@link recoverOrphans} and then\n * streams appropriate changes to provide a responsive and consistent user experience.\n */\nexport class GraffitiSynchronize extends Graffiti {\n protected ajv_: Promise<Ajv> | undefined;\n protected applyPatch_: Promise<typeof applyPatch> | undefined;\n protected readonly graffiti: Graffiti;\n protected readonly callbacks = new Set<GraffitiSynchronizeCallback>();\n protected readonly options: GraffitiSynchronizeOptions;\n\n channelStats: Graffiti[\"channelStats\"];\n login: Graffiti[\"login\"];\n logout: Graffiti[\"logout\"];\n sessionEvents: Graffiti[\"sessionEvents\"];\n\n get ajv() {\n if (!this.ajv_) {\n this.ajv_ = (async () => {\n const { default: Ajv } = await import(\"ajv\");\n return new Ajv({ strict: false });\n })();\n }\n return this.ajv_;\n }\n\n get applyPatch() {\n if (!this.applyPatch_) {\n this.applyPatch_ = (async () => {\n const { applyPatch } = await import(\"fast-json-patch\");\n return applyPatch;\n })();\n }\n return this.applyPatch_;\n }\n\n /**\n * Wraps a Graffiti API instance to provide the synchronize methods.\n * The GraffitiSyncrhonize class rather than the Graffiti class\n * must be used for all functions for the synchronize methods to work.\n */\n constructor(\n /**\n * The [Graffiti API](https://api.graffiti.garden/classes/Graffiti.html)\n * instance to wrap.\n */\n graffiti: Graffiti,\n options?: GraffitiSynchronizeOptions,\n ) {\n super();\n this.options = options ?? {};\n this.graffiti = graffiti;\n this.channelStats = graffiti.channelStats.bind(graffiti);\n this.login = graffiti.login.bind(graffiti);\n this.logout = graffiti.logout.bind(graffiti);\n this.sessionEvents = graffiti.sessionEvents;\n }\n\n protected synchronize<Schema extends JSONSchema>(\n matchObject: (object: GraffitiObjectBase) => boolean,\n channels: string[],\n schema: Schema,\n session?: GraffitiSession | null,\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\n const seenUrls = new Set<string>();\n\n const repeater = new Repeater<GraffitiObjectStreamContinueEntry<Schema>>(\n async (push, stop) => {\n const validate = compileGraffitiObjectSchema(await this.ajv, schema);\n const callback: GraffitiSynchronizeCallback = (\n oldObjectRaw,\n newObjectRaw,\n ) => {\n for (const objectRaw of [newObjectRaw, oldObjectRaw]) {\n if (objectRaw?.tombstone) {\n if (seenUrls.has(objectRaw.object.url)) {\n push(objectRaw);\n }\n } else if (\n objectRaw &&\n matchObject(objectRaw.object) &&\n (this.options.omniscient ||\n isActorAllowedGraffitiObject(objectRaw.object, session))\n ) {\n // Deep clone the object to prevent mutation\n const object = JSON.parse(\n JSON.stringify(objectRaw.object),\n ) as GraffitiObject<{}>;\n if (!this.options.omniscient) {\n maskGraffitiObject(object, channels, session);\n }\n if (validate(object)) {\n push({ object });\n seenUrls.add(object.url);\n break;\n }\n }\n }\n };\n\n this.callbacks.add(callback);\n await stop;\n this.callbacks.delete(callback);\n },\n );\n\n return repeater;\n }\n\n /**\n * This method has the same signature as {@link discover} but listens for\n * changes made via {@link put}, {@link patch}, and {@link delete} or\n * fetched from {@link get}, {@link discover}, and {@link recoverOrphans}\n * and then streams appropriate changes to provide a responsive and\n * consistent user experience.\n *\n * Unlike {@link discover}, this method continuously listens for changes\n * and will not terminate unless the user calls the `return` method on the iterator\n * or `break`s out of the loop.\n *\n * @group Synchronize Methods\n */\n synchronizeDiscover<Schema extends JSONSchema>(\n ...args: Parameters<typeof Graffiti.prototype.discover<Schema>>\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\n const [channels, schema, session] = args;\n function matchObject(object: GraffitiObjectBase) {\n return object.channels.some((channel) => channels.includes(channel));\n }\n return this.synchronize<Schema>(matchObject, channels, schema, session);\n }\n\n /**\n * This method has the same signature as {@link get} but\n * listens for changes made via {@link put}, {@link patch}, and {@link delete} or\n * fetched from {@link get}, {@link discover}, and {@link recoverOrphans} and then\n * streams appropriate changes to provide a responsive and consistent user experience.\n *\n * Unlike {@link get}, which returns a single result, this method continuously\n * listens for changes which are output as an asynchronous stream, similar\n * to {@link discover}.\n *\n * @group Synchronize Methods\n */\n synchronizeGet<Schema extends JSONSchema>(\n ...args: Parameters<typeof Graffiti.prototype.get<Schema>>\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\n const [objectUrl, schema, session] = args;\n const url = unpackObjectUrl(objectUrl);\n function matchObject(object: GraffitiObjectBase) {\n return object.url === url;\n }\n return this.synchronize<Schema>(matchObject, [], schema, session);\n }\n\n /**\n * This method has the same signature as {@link recoverOrphans} but\n * listens for changes made via\n * {@link put}, {@link patch}, and {@link delete} or fetched from\n * {@link get}, {@link discover}, and {@link recoverOrphans} and then\n * streams appropriate changes to provide a responsive and consistent user experience.\n *\n * Unlike {@link recoverOrphans}, this method continuously listens for changes\n * and will not terminate unless the user calls the `return` method on the iterator\n * or `break`s out of the loop.\n *\n * @group Synchronize Methods\n */\n synchronizeRecoverOrphans<Schema extends JSONSchema>(\n ...args: Parameters<typeof Graffiti.prototype.recoverOrphans<Schema>>\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\n const [schema, session] = args;\n function matchObject(object: GraffitiObjectBase) {\n return object.actor === session.actor && object.channels.length === 0;\n }\n return this.synchronize<Schema>(matchObject, [], schema, session);\n }\n\n /**\n * Streams changes made to *any* object in *any* channel\n * and made by *any* user. You may want to use it in conjuction with\n * {@link GraffitiSynchronizeOptions.omniscient} to get a global view\n * of all Graffiti objects passing through the system. This is useful\n * for building a client-side cache, for example.\n *\n * Be careful using this method. Without additional filters it can\n * expose the user to content out of context.\n */\n synchronizeAll<Schema extends JSONSchema>(\n schema: Schema,\n session?: GraffitiSession | null,\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\n return this.synchronize<Schema>(() => true, [], schema, session);\n }\n\n protected async synchronizeDispatch(\n oldObject: GraffitiObjectStreamContinueEntry<{}>,\n newObject?: GraffitiObjectStreamContinueEntry<{}>,\n waitForListeners = false,\n ) {\n for (const callback of this.callbacks) {\n callback(oldObject, newObject);\n }\n if (waitForListeners) {\n // Wait for the listeners to receive\n // their objects, before returning the operation\n // that triggered them.\n //\n // This is important for mutators (put, patch, delete)\n // to ensure the application state has been updated\n // everywhere before returning, giving consistent\n // feedback to the user that the operation has completed.\n //\n // The opposite is true for accessors (get, discover, recoverOrphans),\n // where it is a weird user experience to call `get`\n // in one place and have the application update\n // somewhere else first. It is also less efficient.\n //\n // The hack is simply to await one \"macro task cycle\".\n // We need to wait for this cycle rather than using\n // `await push` in the callback, because it turns out\n // that `await push` won't resolve until the following\n // .next() call of the iterator, so if only\n // one .next() is called, this dispatch will hang.\n await new Promise((resolve) => setTimeout(resolve, 0));\n }\n }\n\n get: Graffiti[\"get\"] = async (...args) => {\n const object = await this.graffiti.get(...args);\n this.synchronizeDispatch({ object });\n return object;\n };\n\n put: Graffiti[\"put\"] = async (...args) => {\n const oldObject = await this.graffiti.put<{}>(...args);\n const partialObject = args[0];\n const newObject: GraffitiObjectBase = {\n ...oldObject,\n value: partialObject.value,\n channels: partialObject.channels,\n allowed: partialObject.allowed,\n };\n await this.synchronizeDispatch(\n {\n tombstone: true,\n object: oldObject,\n },\n {\n object: newObject,\n },\n true,\n );\n return oldObject;\n };\n\n patch: Graffiti[\"patch\"] = async (...args) => {\n const oldObject = await this.graffiti.patch(...args);\n const newObject: GraffitiObjectBase = { ...oldObject };\n for (const prop of [\"value\", \"channels\", \"allowed\"] as const) {\n applyGraffitiPatch(await this.applyPatch, prop, args[0], newObject);\n }\n await this.synchronizeDispatch(\n {\n tombstone: true,\n object: oldObject,\n },\n {\n object: newObject,\n },\n true,\n );\n return oldObject;\n };\n\n delete: Graffiti[\"delete\"] = async (...args) => {\n const oldObject = await this.graffiti.delete(...args);\n await this.synchronizeDispatch(\n {\n tombstone: true,\n object: oldObject,\n },\n undefined,\n true,\n );\n return oldObject;\n };\n\n protected objectStreamContinue<Schema extends JSONSchema>(\n iterator: GraffitiObjectStreamContinue<Schema>,\n ): GraffitiObjectStreamContinue<Schema> {\n const this_ = this;\n return (async function* () {\n while (true) {\n const result = await iterator.next();\n if (result.done) {\n const { continue: continue_, cursor } = result.value;\n return {\n continue: () => this_.objectStreamContinue<Schema>(continue_()),\n cursor,\n };\n }\n if (!result.value.error) {\n this_.synchronizeDispatch(\n result.value as GraffitiObjectStreamContinueEntry<{}>,\n );\n }\n yield result.value;\n }\n })();\n }\n\n protected objectStream<Schema extends JSONSchema>(\n iterator: GraffitiObjectStream<Schema>,\n ): GraffitiObjectStream<Schema> {\n const wrapped = this.objectStreamContinue<Schema>(iterator);\n return (async function* () {\n // Filter out the tombstones for type safety\n while (true) {\n const result = await wrapped.next();\n if (result.done) return result.value;\n if (result.value.error || !result.value.tombstone) yield result.value;\n }\n })();\n }\n\n discover: Graffiti[\"discover\"] = (...args) => {\n const iterator = this.graffiti.discover(...args);\n return this.objectStream<(typeof args)[1]>(iterator);\n };\n\n recoverOrphans: Graffiti[\"recoverOrphans\"] = (...args) => {\n const iterator = this.graffiti.recoverOrphans(...args);\n return this.objectStream<(typeof args)[0]>(iterator);\n };\n\n continueObjectStream: Graffiti[\"continueObjectStream\"] = (...args) => {\n // TODO!!\n return this.graffiti.continueObjectStream(...args);\n };\n}\n", "import type {\n GraffitiObjectUrl,\n GraffitiObject,\n GraffitiObjectBase,\n GraffitiPatch,\n GraffitiSession,\n GraffitiPutObject,\n GraffitiObjectStream,\n ChannelStats,\n GraffitiChannelStatsStream,\n GraffitiObjectStreamContinue,\n} from \"./2-types\";\nimport type { JSONSchema } from \"json-schema-to-ts\";\n\n/**\n * This API describes a small but powerful set of methods that\n * can be used to create many different kinds of social media applications,\n * all of which can interoperate.\n * These methods should satisfy all of an application's needs for\n * the communication, storage, and access management of social data.\n * The rest of the application can be built with standard client-side\n * user interface tools to present and interact with the data \u2014\n * no server code necessary.\n * The Typescript source for this API is available at\n * [graffiti-garden/api](https://github.com/graffiti-garden/api).\n *\n * There are several different implementations of this Graffiti API available,\n * including a [federated implementation](https://github.com/graffiti-garden/implementation-federated),\n * that lets users choose where their data is stored,\n * and a [local implementation](https://github.com/graffiti-garden/implementation-local)\n * that can be used for testing and development. In our design of Graffiti, this API is our\n * primary focus as it is the layer that shapes the experience\n * of developing applications. While different implementations can provide tradeoffs between\n * other important properties (e.g. privacy, security, scalability), those properties\n * are useless if the system as a whole doesn't expose useful functionality to developers.\n *\n * On the other side of the stack, there is [Vue plugin](https://github.com/graffiti-garden/wrapper-vue/)\n * that wraps around this API to provide reactivity. Other high-level libraries\n * will be available in the future.\n *\n * ## Overview\n *\n * Graffiti provides applications with methods to create and store data\n * on behalf of their users using standard CRUD operations:\n * {@link put}, {@link get}, {@link patch}, and {@link delete}.\n * This data can represent both social artifacts (e.g. posts, profiles) and\n * activities (e.g. likes, follows) and is stored as JSON.\n *\n * The social aspect of Graffiti comes from the {@link discover} method\n * which allows applications to find objects that other users made.\n * It is a lot like a traditional query operation, but it only\n * returns objects that have been placed in particular\n * {@link GraffitiObjectBase.channels | `channels`}\n * specified by the discovering application.\n *\n * Graffiti builds on well known concepts and standards wherever possible.\n * JSON Objects can be typed with [JSON Schema](https://json-schema.org/) and patches\n * can be applied with [JSON Patch](https://jsonpatch.com).\n * For interoperability between Graffiti applications, we recommend that\n * objects use established properties from the\n * [Activity Vocabulary](https://www.w3.org/TR/activitystreams-vocabulary/) when available,\n * however it is always possible to create additional properties, contributing\n * to the broader [folksonomy](https://en.wikipedia.org/wiki/Folksonomy).\n *\n * {@link GraffitiObjectBase.channels | `channels`} are one of the major concepts\n * unique to Graffiti along with *interaction relativity*, defined below.\n * Channels create boundaries between public spaces and work to prevent\n * [context collapse](https://en.wikipedia.org/wiki/Context_collapse)\n * even in a highly interoperable environment.\n * Interaction relativity means that all interactions between users are\n * actually atomic single-user operations that can be interpreted in different ways,\n * which also supports interoperability and pluralism.\n *\n * ### Channels\n *\n * {@link GraffitiObjectBase.channels | `channels`}\n * are a way for the creators of social data to express the intended audience of their\n * data. When a user creates data using the {@link put} method, they\n * can place their data in one or more channels.\n * Content consumers using the {@link discover} method will only see data\n * contained in one of the channels they specify.\n *\n * While many channels may be public, they partition\n * the public into different \"contexts\", mitigating the\n * phenomenon of [context collapse](https://en.wikipedia.org/wiki/Context_collapse) or the \"flattening of multiple audiences.\"\n * Any [URI](https://en.wikipedia.org/wiki/Uniform_Resource_Identifier) can be used as a channel, and so channels can represent people,\n * comment threads, topics, places (real or virtual), pieces of media, and more.\n *\n * For example, consider a comment on a post. If we place that comment in the channel\n * represented by the post's URL, then only people viewing the post will know to\n * look in that channel, giving it visibility akin to a comment on a blog post\n * or comment on Instagram ([since 2019](https://www.buzzfeednews.com/article/katienotopoulos/instagrams-following-activity-tab-is-going-away)).\n * If we also place the comment in the channel represented by the commenter's URI (their\n * {@link GraffitiObjectBase.actor | `actor` URI}), then people viewing the commenter's profile\n * will also see the comment, giving it more visibility, like a reply on Twitter.\n * If we *only* place the comment in the channel represented by the commenter's URI, then\n * it becomes like a quote tweet ([prior to 2020](https://x.com/Support/status/1300555325750292480)),\n * where the comment is only visible to the commenter's followers but not the audience\n * of the original post.\n *\n * The channel model differs from other models of communication such as the\n * [actor model](https://www.w3.org/TR/activitypub/#Overview) used by ActivityPub,\n * the protocol underlying Mastodon, or the [firehose model](https://bsky.social/about/blog/5-5-2023-federation-architecture)\n * used by the AT Protocol, the protocol underlying BlueSky.\n * The actor model is a fusion of direct messaging (like Email) and broadcasting\n * (like RSS) and works well for follow-based communication but struggles\n * to pass information via other rendez-vous.\n * In the actor model, even something as simple as comments can be\n * [very tricky and require server \"side effects\"](https://seb.jambor.dev/posts/understanding-activitypub-part-3-the-state-of-mastodon/).\n * The firehose model dumps all user data into one public database,\n * which doesn't allow for the carving out of different contexts that we did in our comment\n * example above. In the firehose model a comment will always be visible to *both* the original post's audience and\n * the commenter's followers.\n *\n * In some sense, channels provide a sort of \"social access control\" by forming\n * expectations about the audiences of different online spaces.\n * As a real world analogy, oftentimes support groups, such as alcoholics\n * anonymous, are open to the public but people in those spaces feel comfortable sharing intimate details\n * because they have expectations about the other people attending.\n * If someone malicious went to support groups just to spread people's secrets,\n * they would be shamed for violating these norms.\n * Similarly, in Graffiti, while you could spider public channels like a search engine\n * to find content about a person, revealing that you've done such a thing\n * would be shameful.\n *\n * Still, social access control is not perfect and so in situations where privacy is important,\n * objects can also be given\n * an {@link GraffitiObjectBase.allowed | `allowed`} list.\n * For example, to send someone a direct message you should put an object representing\n * that message in the channel that represents them (their {@link GraffitiObjectBase.actor | `actor` URI}),\n * so they can find it, *and* set the `allowed` field to only include the recipient,\n * so only they can read it.\n *\n * ### Interaction relativity\n *\n * Interaction relativity posits that \"interaction between two individuals only\n * exists relative to an observer,\" or equivalently, all interaction is [reified](https://en.wikipedia.org/wiki/Reification_(computer_science)).\n * For example, if one user creates a post and another user wants to \"like\" that post,\n * their like is not modifying the original post, it is simply another data object that points\n * to the post being liked, via its {@link GraffitiObjectBase.url | URL}.\n *\n * ```json\n * {\n * activity: 'like',\n * target: 'url-of-the-post-i-like',\n * actor: 'my-user-id'\n * }\n * ```\n *\n * In Graffiti, all interactions including *moderation* and *collaboration* are relative.\n * This means that applications can freely choose which interactions\n * they want to express to their users and how.\n * For example, one application could have a single fixed moderator,\n * another could allow users to choose which moderators they would like filter their content\n * like [Bluesky's stackable moderation](https://bsky.social/about/blog/03-12-2024-stackable-moderation),\n * and another could implement a fully democratic system like [PolicyKit](https://policykit.org/).\n * Each of these applications is one interpretation of the underlying refieid user interactions and\n * users can freely switch between them.\n *\n * Interaction relativy also allows applications to introduce new sorts of interactions\n * without having to coordinate with all the other existing applications,\n * keeping the ecosystem flexible and interoperable.\n * For example, an application could [add a \"Trust\" button to posts](https://social.cs.washington.edu/pub_details.html?id=trustnet)\n * and use it assess the truthfulness of posts made on applications across Graffiti.\n * New sorts of interactions like these can be smoothly absorbed by the broader ecosystem\n * as a [folksonomy](https://en.wikipedia.org/wiki/Folksonomy).\n *\n * Interactivy relativity is realized in Graffiti through two design decisions:\n * 1. The creators of objects can only modify their own objects. It is important for\n * users to be able to change and delete their own content to respect their\n * [right to be forgotten](https://en.wikipedia.org/wiki/Right_to_be_forgotten),\n * but beyond self-correction and self-censorship all other interaction is reified.\n * Many interactions can be reified via pointers, as in the \"like\" example above, and collaborative\n * edits can be refieid via [CRDTs](https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type).\n * 2. No one owns channels. Unlike IRC/Slack channels or [Matrix rooms](https://matrix.org/docs/matrix-concepts/rooms_and_events/),\n * anyone can post to any channel, so long as they know the URI of that channel.\n * It is up to applications to hide content from channels either according to manual\n * filters or in response to user action.\n * For example, a user may create a post with the flag `disableReplies`.\n * Applications could then filter out any content from the replies channel\n * that the original poster has not specifically approved.\n *\n * @groupDescription CRUD Methods\n * Methods for {@link put | creating}, {@link get | reading}, {@link patch | updating},\n * and {@link delete | deleting} {@link GraffitiObjectBase | Graffiti objects}.\n * @groupDescription Query Methods\n * Methods that retrieve or accumulate information about multiple {@link GraffitiObjectBase | Graffiti objects} at a time.\n * @groupDescription Session Management\n * Methods and properties for logging in and out of a Graffiti implementation.\n */\nexport abstract class Graffiti {\n /**\n * Creates a new {@link GraffitiObjectBase | object} or replaces an existing object.\n * An object can only be replaced by the same {@link GraffitiObjectBase.actor | `actor`}\n * that created it.\n *\n * Replacement occurs when the {@link GraffitiObjectBase.url | `url`} of\n * the replaced object exactly matches an existing object's URL.\n *\n * @throws {@link GraffitiErrorNotFound} if a {@link GraffitiObjectBase.url | `url`}\n * is provided that has not been created yet or the {@link GraffitiObjectBase.actor | `actor`}\n * is not {@link GraffitiObjectBase.allowed | `allowed`} to see it.\n *\n * @throws {@link GraffitiErrorForbidden} if the {@link GraffitiObjectBase.actor | `actor`}\n * is not the same `actor` as the one who created the object.\n *\n * @returns The object that was replaced if one one exists, otherwise an object with\n * with an empty {@link GraffitiObjectBase.value | `value`},\n * {@link GraffitiObjectBase.channels | `channels`}, and {@link GraffitiObjectBase.allowed | `allowed`}\n * list.\n * The {@link GraffitiObjectBase.lastModified | `lastModified`} property of the returned object\n * will be updated to the time of replacement/creation.\n *\n * @group CRUD Methods\n */\n abstract put<Schema extends JSONSchema>(\n /**\n * The object to be put. This object is statically type-checked against the [JSON schema](https://json-schema.org/) that can be optionally provided\n * as the generic type parameter. We highly recommend providing a schema to\n * ensure that the PUT object matches subsequent {@link get} or {@link discover}\n * methods.\n */\n object: GraffitiPutObject<Schema>,\n /**\n * An implementation-specific object with information to authenticate the\n * {@link GraffitiObjectBase.actor | `actor`}.\n */\n session: GraffitiSession,\n ): Promise<GraffitiObjectBase>;\n\n /**\n * Retrieves an object from a given {@link GraffitiObjectBase.url | `url`}.\n *\n * The retrieved object is type-checked against the provided [JSON schema](https://json-schema.org/)\n * otherwise a {@link GraffitiErrorSchemaMismatch} is thrown.\n *\n * If the retreiving {@link GraffitiObjectBase.actor | `actor`} is not\n * the object's `actor`,\n * the object's {@link GraffitiObjectBase.allowed | `allowed`} and\n * {@link GraffitiObjectBase.channels | `channels`} properties are\n * not revealed, similar to a BCC.\n *\n * @throws {@link GraffitiErrorNotFound} if the object does not exist, has been deleted, or the user is not\n * {@link GraffitiObjectBase.allowed | `allowed`} to access it.\n *\n * @throws {@link GraffitiErrorSchemaMismatch} if the retrieved object does not match the provided schema.\n *\n * @group CRUD Methods\n */\n abstract get<Schema extends JSONSchema>(\n /**\n * The location of the object to get.\n */\n url: string | GraffitiObjectUrl,\n /**\n * The JSON schema to validate the retrieved object against.\n */\n schema: Schema,\n /**\n * An implementation-specific object with information to authenticate the\n * {@link GraffitiObjectBase.actor | `actor`}. If no `session` is provided,\n * the retrieved object's {@link GraffitiObjectBase.allowed | `allowed`}\n * property must be `undefined`.\n */\n session?: GraffitiSession | null,\n ): Promise<GraffitiObject<Schema>>;\n\n /**\n * Patches an existing object at a given {@link GraffitiObjectBase.url | `url`}.\n * The patching {@link GraffitiObjectBase.actor | `actor`} must be the same as the\n * `actor` that created the object.\n *\n * @returns The original object prior to the patch with its\n * {@link GraffitiObjectBase.lastModified | `lastModified`}\n * property updated to the time of deletion.\n *\n * @throws {@link GraffitiErrorNotFound} if the object does not exist, has already been deleted,\n * or the user is not {@link GraffitiObjectBase.allowed | `allowed`} to access it.\n *\n * @throws {@link GraffitiErrorForbidden} if the {@link GraffitiObjectBase.actor | `actor`}\n * is not the same `actor` as the one who created the object.\n *\n * @group CRUD Methods\n */\n abstract patch(\n /**\n * A collection of [JSON Patch](https://jsonpatch.com) operations\n * to apply to the object. See {@link GraffitiPatch} for more information.\n */\n patch: GraffitiPatch,\n /**\n * The location of the object to patch.\n */\n url: string | GraffitiObjectUrl,\n /**\n * An implementation-specific object with information to authenticate the\n * {@link GraffitiObjectBase.actor | `actor`}.\n */\n session: GraffitiSession,\n ): Promise<GraffitiObjectBase>;\n\n /**\n * Deletes an object from a given {@link GraffitiObjectBase.url | `url`}.\n * The deleting {@link GraffitiObjectBase.actor | `actor`} must be the same as the\n * `actor` that created the object.\n *\n * It is not possible to re-{@link put} an object that has been deleted\n * to ensure a user's [right to be forgotten](https://en.wikipedia.org/wiki/Right_to_be_forgotten).\n * In cases where deleting and restoring an object is useful, an object's\n * {@link GraffitiObjectBase.allowed | `allowed`} property can be set to\n * an empty list to hide it from all users except the creator.\n *\n * @returns The object that was deleted with its\n * {@link GraffitiObjectBase.lastModified | `lastModified`}\n * property updated to the time of deletion.\n *\n * @throws {@link GraffitiErrorNotFound} if the object does not exist, has already been deleted,\n * or the user is not {@link GraffitiObjectBase.allowed | `allowed`} to access it.\n *\n * @throws {@link GraffitiErrorForbidden} if the {@link GraffitiObjectBase.actor | `actor`}\n * is not the same `actor` as the one who created the object.\n *\n * @group CRUD Methods\n */\n abstract delete(\n /**\n * The location of the object to delete.\n */\n url: string | GraffitiObjectUrl,\n /**\n * An implementation-specific object with information to authenticate the\n * {@link GraffitiObjectBase.actor | `actor`}.\n */\n session: GraffitiSession,\n ): Promise<GraffitiObjectBase>;\n\n /**\n * Discovers objects created by any user that are contained\n * in at least one of the given {@link GraffitiObjectBase.channels | `channels`}\n * and match the given [JSON Schema](https://json-schema.org).\n *\n * Objects are returned asynchronously as they are discovered but the stream\n * will end once all leads have been exhausted.\n * The {@link GraffitiObjectStream} ends by returning a\n * {@link GraffitiObjectStreamReturn.continue | `continue`} method and a\n * {@link GraffitiObjectStreamReturn.cursor | `cursor`} string,\n * each of which can be be used to poll for new objects.\n * The `continue` method preserves the type safety of the stream and the `cursor`\n * string can be serialized to continue the stream after an application is closed\n * and reopened.\n *\n * `discover` will not return objects that the {@link GraffitiObjectBase.actor | `actor`}\n * is not {@link GraffitiObjectBase.allowed | `allowed`} to access.\n * If the `actor` is not the creator of a discovered object,\n * the allowed list will be masked to only contain the querying actor if the\n * allowed list is not `undefined` (public). Additionally, if the actor is not the\n * creator of a discovered object, any {@link GraffitiObjectBase.channels | `channels`}\n * not specified by the `discover` method will not be revealed. This masking happens\n * before the object is validated against the supplied `schema`.\n *\n * Since different implementations may fetch data from multiple sources there is\n * no guarentee on the order that objects are returned in.\n * It is also possible that duplicate objects are returned and their\n * {@link GraffitiObjectBase.lastModified | `lastModified`} fields must be used\n * to determine which object is the most recent.\n *\n * @returns A stream of objects that match the given {@link GraffitiObjectBase.channels | `channels`}\n * and [JSON Schema](https://json-schema.org).\n *\n * @group Query Methods\n */\n abstract discover<Schema extends JSONSchema>(\n /**\n * The {@link GraffitiObjectBase.channels | `channels`} that objects must be associated with.\n */\n channels: string[],\n /**\n * A [JSON Schema](https://json-schema.org) that objects must satisfy.\n */\n schema: Schema,\n /**\n * An implementation-specific object with information to authenticate the\n * {@link GraffitiObjectBase.actor | `actor`}. If no `session` is provided,\n * only objects that have no {@link GraffitiObjectBase.allowed | `allowed`}\n * property will be returned.\n */\n session?: GraffitiSession | null,\n ): GraffitiObjectStream<Schema>;\n\n /**\n * Discovers objects **not** contained in any\n * {@link GraffitiObjectBase.channels | `channels`}\n * that were created by the querying {@link GraffitiObjectBase.actor | `actor`}\n * and match the given [JSON Schema](https://json-schema.org).\n * Unlike {@link discover}, this method will not return objects created by other users.\n *\n * This method is not useful for most applications, but necessary for\n * getting a global view of all a user's Graffiti data or debugging\n * channel usage.\n *\n * Like {@link discover}, objects are returned asynchronously as they are discovered,\n * the stream will end once all leads have been exhausted, and the stream\n * can be continued using the {@link GraffitiObjectStreamReturn.continue | `continue`}\n * method or {@link GraffitiObjectStreamReturn.cursor | `cursor`} string.\n *\n * @returns A stream of objects created by the querying {@link GraffitiObjectBase.actor | `actor`}\n * that do not belong to any {@link GraffitiObjectBase.channels | `channels`}\n * and match the given [JSON Schema](https://json-schema.org).\n *\n * @group Query Methods\n */\n abstract recoverOrphans<Schema extends JSONSchema>(\n /**\n * A [JSON Schema](https://json-schema.org) that orphaned objects must satisfy.\n */\n schema: Schema,\n /**\n * An implementation-specific object with information to authenticate the\n * {@link GraffitiObjectBase.actor | `actor`}.\n */\n session: GraffitiSession,\n ): GraffitiObjectStream<Schema>;\n\n /**\n * Returns statistics about all the {@link GraffitiObjectBase.channels | `channels`}\n * that an {@link GraffitiObjectBase.actor | `actor`} has posted to.\n * This is not very useful for most applications, but\n * necessary for certain applications where a user wants a\n * global view of all their Graffiti data or to debug\n * channel usage.\n *\n * Like {@link discover}, objects are returned asynchronously as they are discovered,\n * the stream will end once all leads have been exhausted.\n *\n * @group Query Methods\n *\n * @returns A stream of statistics for each {@link GraffitiObjectBase.channels | `channel`}\n * that the {@link GraffitiObjectBase.actor | `actor`} has posted to.\n */\n abstract channelStats(\n /**\n * An implementation-specific object with information to authenticate the\n * {@link GraffitiObjectBase.actor | `actor`}.\n */\n session: GraffitiSession,\n ): GraffitiChannelStatsStream;\n\n /**\n * Continues a {@link GraffitiObjectStream} from a given\n * {@link GraffitiObjectStreamReturn.cursor | `cursor`} string.\n * The continuation will return new objects that have been created\n * that match the original stream, and also returns the\n * {@link GraffitiObjectBase.url | `url`}s of objects that\n * have been deleted, as marked by a `tombstone`.\n *\n * The continuation may also include duplicates of objects that\n * were already returned by the original stream. This is dependent\n * on how much state the underlying implementation maintains.\n *\n * The `cursor` allows the client to\n * serialize the state of the stream and continue it later.\n * However this method loses any typing information that was\n * present in the original stream. For better type safety\n * and when serializing is not necessary, use the\n * {@link GraffitiObjectStreamReturn.continue | `continue`} method\n * instead, which is returned along with the `cursor` at the\n * end of the original stream.\n *\n * @throws {@link GraffitiErrorForbidden} if the {@link GraffitiObjectBase.actor | `actor`}\n * provided in the `session` is not the same as the `actor`\n * that initiated the original stream.\n *\n * @group Query Methods\n */\n abstract continueObjectStream(\n cursor: string,\n session?: GraffitiSession | null,\n ): GraffitiObjectStreamContinue<{}>;\n\n /**\n * Begins the login process. Depending on the implementation, this may\n * involve redirecting the user to a login page or opening a popup,\n * so it should always be called in response to a user action.\n *\n * The {@link GraffitiSession | session} object is returned\n * asynchronously via {@link Graffiti.sessionEvents | sessionEvents}\n * as a {@link GraffitiLoginEvent} with event type `login`.\n *\n * @group Session Management\n */\n abstract login(\n /**\n * Suggestions for the permissions that the\n * login process should grant. The login process may not\n * provide the exact proposed permissions.\n */\n proposal?: {\n /**\n * A suggested actor to login as. For example, if a user tries to\n * edit a post but are not logged in, the interface can infer that\n * they might want to log in as the actor who created the post\n * they are attempting to edit.\n *\n * Even if provided, the implementation should allow the user\n * to log in as a different actor if they choose.\n */\n actor?: string;\n /**\n * A yet to be defined permissions scope. An application may use\n * this to indicate the minimum necessary scope needed to\n * operate. For example, it may need to be able read private\n * messages from a certain set of channels, or write messages that\n * follow a particular schema.\n *\n * The login process should make it clear what scope an application\n * is requesting and allow the user to enhance or reduce that\n * scope as necessary.\n */\n scope?: {};\n },\n ): Promise<void>;\n\n /**\n * Begins the logout process. Depending on the implementation, this may\n * involve redirecting the user to a logout page or opening a popup,\n * so it should always be called in response to a user action.\n *\n * A confirmation will be returned asynchronously via\n * {@link Graffiti.sessionEvents | sessionEvents}\n * as a {@link GraffitiLogoutEvent} as event type `logout`.\n *\n * @group Session Management\n */\n abstract logout(\n /**\n * The {@link GraffitiSession | session} object to logout.\n */\n session: GraffitiSession,\n ): Promise<void>;\n\n /**\n * An event target that can be used to listen for the following\n * events and they're corresponding event types:\n * - `login` - {@link GraffitiLoginEvent}\n * - `logout` - {@link GraffitiLogoutEvent}\n * - `initialized` - {@link GraffitiSessionInitializedEvent}\n *\n * @group Session Management\n */\n abstract readonly sessionEvents: EventTarget;\n}\n", "import type { JSONSchema, FromSchema } from \"json-schema-to-ts\";\nimport type { Operation as JSONPatchOperation } from \"fast-json-patch\";\n\n/**\n * Objects are the atomic unit in Graffiti that can represent both data (*e.g.* a social media post or profile)\n * and activities (*e.g.* a like or follow).\n * Objects are created and modified by a single {@link actor | `actor`}.\n *\n * Most of an object's content is stored in its {@link value | `value`} property, which can be any JSON\n * object. However, we recommend using properties from the\n * [Activity Vocabulary](https://www.w3.org/TR/activitystreams-vocabulary/)\n * or properties that emerge in the Graffiti [folksonomy](https://en.wikipedia.org/wiki/Folksonomy)\n * to promote interoperability.\n *\n * The object is globally addressable via its {@link url | `url`}.\n *\n * The {@link channels | `channels`} and {@link allowed | `allowed`} properties\n * enable the object's creator to shape the visibility of and access to their object.\n *\n * The {@link lastModified | `lastModified`} property can be used to compare object versions.\n */\nexport interface GraffitiObjectBase {\n /**\n * The object's content as freeform JSON. We recommend using properties from the\n * [Activity Vocabulary](https://www.w3.org/TR/activitystreams-vocabulary/)\n * or properties that emerge in the Graffiti [folksonomy](https://en.wikipedia.org/wiki/Folksonomy)\n * to promote interoperability.\n */\n value: {};\n\n /**\n * An array of URIs the creator associates with the object. Objects can only be found by querying\n * one of the object's channels using the\n * {@link Graffiti.discover} method. This allows creators to express the intended audience of their object\n * which helps to prevent [context collapse](https://en.wikipedia.org/wiki/Context_collapse) even\n * in the highly interoperable ecosystem that Graffiti envisions. For example, channel URIs may be:\n * - A user's own {@link actor | `actor`} URI. Putting an object in this channel is a way to broadcast\n * the object to the user's followers, like posting a tweet.\n * - The URL of a Graffiti post. Putting an object in this channel is a way to broadcast to anyone viewing\n * the post, like commenting on a tweet.\n * - A URI representing a topic. Putting an object in this channel is a way to broadcast to anyone interested\n * in that topic, like posting in a subreddit.\n */\n channels: string[];\n\n /**\n * An optional array of {@link actor | `actor`} URIs that the creator allows to access the object.\n * If no `allowed` array is provided, the object can be accessed by anyone (so long as they\n * also know the right {@link channels | `channel` } to look in). An object can always be accessed by its creator, even if\n * the `allowed` array is empty.\n *\n * The `allowed` array is not revealed to users other than the creator, like\n * a BCC email. A user may choose to add a `to` property to the object's {@link value | `value`} to indicate\n * other recipients, however this is not enforced by Graffiti and may not accurately reflect the actual `allowed` array.\n *\n * `allowed` can be combined with {@link channels | `channels`}. For example, to send someone a direct message\n * the sender should put their object in the channel of the recipient's {@link actor | `actor`} URI to notify them of the message and also add\n * the recipient's {@link actor | `actor`} URI to the `allowed` array to prevent others from seeing the message.\n */\n allowed?: string[] | null;\n\n /**\n * The URI of the `actor` that {@link Graffiti.put | created } the object. This `actor` also has the unique permission to\n * {@link Graffiti.patch | modify} or {@link Graffiti.delete | delete} the object.\n *\n * We borrow the term actor from the ActivityPub because\n * [like in ActivityPub](https://www.w3.org/TR/activitypub/#h-note-0)\n * there is not necessarily a one-to-one mapping between actors and people/users.\n * Multiple people can share the same actor or one person can have multiple actors.\n * Actors can also be bots.\n *\n * In Graffiti, actors are always globally unique URIs which\n * allows them to also function as {@link channels | `channels`}.\n */\n actor: string;\n\n /**\n * A globally unique identifier and locator for the object. It can be used to point to\n * an object or to retrieve the object directly with {@link Graffiti.get}.\n * If an object is {@link Graffiti.put | put} with the same URL\n * as an existing object, the existing object will be replaced with the new object.\n *\n * An object's URL is generated when the object is first created and\n * should include sufficient randomness to prevent collisions\n * and guessing. The URL starts with a \"scheme,\" just like web URLs start with `http` or `https`, to indicate\n * to indicate the particular Graffiti implementation. This allows for applications\n * to pull from multiple coexisting Graffiti implementations without collision.\n * Existing schemes include `graffiti:local:` for objects stored locally\n * (see the [local implementation](https://github.com/graffiti-garden/implementation-local))\n * and `graffiti:remote:` for objects stored on Graffiti-specific web servers (see the\n * [remote implementation](https://github.com/graffiti-garden/implementation-remote)).\n * Options available in the future might include `graffiti:solid:` for objects stored on Solid servers\n * or `graffiti:p2p:` for objects stored on a peer-to-peer network.\n */\n url: string;\n\n /**\n * The time the object was last modified, measured in milliseconds since January 1, 1970.\n * It can be used to compare object versions.\n * A number, rather than an ISO string or Date object, is used for easy comparison, sorting,\n * and JSON Schema [range queries](https://json-schema.org/understanding-json-schema/reference/numeric#range).\n *\n * It is possible to use this value to sort objects in a user's interface but in many cases it would be better to\n * use a [`published`](https://www.w3.org/TR/activitystreams-vocabulary/#dfn-published)\n * property in the object's {@link value | `value`} to indicate when the object was created\n * rather than when it was modified.\n */\n lastModified: number;\n}\n\n/**\n * This type constrains the {@link GraffitiObjectBase} type to adhere to a\n * particular [JSON schema](https://json-schema.org/).\n * This allows for static type-checking of an object's {@link GraffitiObjectBase.value | `value`}\n * which is otherwise a freeform JSON object.\n *\n * Schema-aware objects are returned by {@link Graffiti.get} and {@link Graffiti.discover}.\n */\nexport type GraffitiObject<Schema extends JSONSchema> = GraffitiObjectBase &\n FromSchema<Schema & typeof GraffitiObjectJSONSchema>;\n\n/**\n * A JSON Schema equivalent to the {@link GraffitiObjectBase} type.\n * Needed internally for type inference of JSON Schemas, but can\n * be used by implementations to validate objects.\n */\nexport const GraffitiObjectJSONSchema = {\n type: \"object\",\n properties: {\n value: { type: \"object\" },\n channels: { type: \"array\", items: { type: \"string\" } },\n allowed: { type: \"array\", items: { type: \"string\" }, nullable: true },\n url: { type: \"string\" },\n actor: { type: \"string\" },\n lastModified: { type: \"number\" },\n },\n additionalProperties: false,\n required: [\"value\", \"channels\", \"actor\", \"url\", \"lastModified\"],\n} as const satisfies JSONSchema;\n\n/**\n * This is an object containing only the {@link GraffitiObjectBase.url | `url`}\n * property of a {@link GraffitiObjectBase | GraffitiObject}.\n * It is used as a utility type so that users can call {@link Graffiti.get},\n * {@link Graffiti.patch}, or {@link Graffiti.delete} directly on an object\n * rather than on `object.url`.\n */\nexport type GraffitiObjectUrl = Pick<GraffitiObjectBase, \"url\">;\n\n/**\n * This object is a subset of {@link GraffitiObjectBase} that a user must construct locally before calling {@link Graffiti.put}.\n * This local copy does not require system-generated properties and may be statically typed with\n * a [JSON schema](https://json-schema.org/) to prevent the accidental creation of erroneous objects.\n *\n * This local object must have a {@link GraffitiObjectBase.value | `value`} and {@link GraffitiObjectBase.channels | `channels`}\n * and may optionally have an {@link GraffitiObjectBase.allowed | `allowed`} property.\n *\n * It may also include a {@link GraffitiObjectBase.url | `url`} property to specify the\n * URL of an existing object to replace. If no `url` is provided, one will be generated during object creation.\n *\n * This object does not need a {@link GraffitiObjectBase.lastModified | `lastModified`}\n * property since it will be automatically generated by the Graffiti system.\n */\nexport type GraffitiPutObject<Schema extends JSONSchema> = Pick<\n GraffitiObjectBase,\n \"value\" | \"channels\" | \"allowed\"\n> &\n Partial<GraffitiObjectBase> &\n FromSchema<Schema & typeof GraffitiPutObjectJSONSchema>;\n\n/**\n * A JSON Schema equivalent to the {@link GraffitiPutObject} type.\n * Needed internally for type inference of JSON Schemas, but can\n * be used by implementations to validate objects.\n */\nexport const GraffitiPutObjectJSONSchema = {\n ...GraffitiObjectJSONSchema,\n required: [\"value\", \"channels\"],\n} as const satisfies JSONSchema;\n\n/**\n * This object contains information that the underlying implementation can\n * use to verify that a user has permission to operate a\n * particular {@link GraffitiObjectBase.actor | `actor`}.\n * This object is required of all {@link Graffiti} methods\n * that modify objects and is optional for methods that read objects.\n *\n * At a minimum the `session` object must contain the\n * {@link GraffitiSession.actor | `actor`} URI the user wants to authenticate with.\n * However it is likely that the `session` object must contain other\n * implementation-specific properties.\n * For example, a Solid implementation might include a\n * [`fetch`](https://docs.inrupt.com/developer-tools/api/javascript/solid-client-authn-browser/functions.html#fetch)\n * function. A distributed implementation may include\n * a cryptographic signature.\n *\n * As to why the `session` object is passed as an argument to every method\n * rather than being an internal property of the {@link Graffiti} instance,\n * this is primarily for type-checking to catch bugs related to login state.\n * Graffiti applications can expose some functionality to users who are not logged in\n * with {@link Graffiti.get} and {@link Graffiti.discover} but without type-checking\n * the `session` it can be easy to forget to hide buttons that trigger\n * other methods that require login.\n * In the future, `session` object may be updated to include scope information\n * and passing the `session` to each method can type-check whether the session provides the\n * necessary permissions.\n *\n * Passing the `session` object per-method also allows for multiple sessions\n * to be used within the same application, like an Email client fetching from\n * multiple accounts.\n */\nexport interface GraffitiSession {\n /**\n * The {@link GraffitiObjectBase.actor | `actor`} a user wants to authenticate with.\n */\n actor: string;\n /**\n * A yet undefined property detailing what operations the session\n * grants the user to perform. For example, to allow a user to\n * read private messages from a particular set of channels or\n * to allow the user to write object matching a particular schema.\n */\n scope?: {};\n}\n\n/**\n * This is the format for patches that modify {@link GraffitiObjectBase} objects\n * using the {@link Graffiti.patch} method. The patches must\n * be an array of [JSON Patch](https://jsonpatch.com) operations.\n * Patches can only be applied to the\n * {@link GraffitiObjectBase.value | `value`}, {@link GraffitiObjectBase.channels | `channels`},\n * and {@link GraffitiObjectBase.allowed | `allowed`} properties since the other\n * properties either describe the object's location or are automatically generated.\n * (See also {@link GraffitiPutObject}).\n */\nexport interface GraffitiPatch {\n /**\n * An array of [JSON Patch](https://jsonpatch.com) operations to\n * modify the object's {@link GraffitiObjectBase.value | `value`}. The resulting\n * `value` must still be a JSON object.\n */\n value?: JSONPatchOperation[];\n\n /**\n * An array of [JSON Patch](https://jsonpatch.com) operations to\n * modify the object's {@link GraffitiObjectBase.channels | `channels`}. The resulting\n * `channels` must still be an array of strings.\n */\n channels?: JSONPatchOperation[];\n\n /**\n * An array of [JSON Patch](https://jsonpatch.com) operations to\n * modify the object's {@link GraffitiObjectBase.allowed | `allowed`} property. The resulting\n * `allowed` property must still be an array of strings or `undefined`.\n */\n allowed?: JSONPatchOperation[];\n}\n\n/**\n * A stream of data that are returned by Graffiti's query-like operations\n * {@link Graffiti.discover} and {@link Graffiti.recoverOrphans}.\n *\n * Errors are returned within the stream rather than as\n * exceptions that would halt the entire stream. This is because\n * some implementations may pull data from multiple sources\n * including some that may be unreliable. In many cases,\n * these errors can be safely ignored.\n * See {@link GraffitiStreamError}.\n *\n * The stream is an [`AsyncGenerator`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function)\n * that can be iterated over using `for await` loops or calling `next` on the generator.\n * The stream can be terminated by breaking out of a loop calling `return` on the generator.\n *\n * The stream ends by returning a {@link GraffitiObjectStreamReturn.continue | `continue`}\n * function and a {@link GraffitiObjectStreamReturn.cursor | `cursor`} string,\n * each of which can be used to resume the stream from where it left off.\n */\nexport type GraffitiObjectStream<Schema extends JSONSchema> = AsyncGenerator<\n GraffitiStreamError | GraffitiObjectStreamEntry<Schema>,\n GraffitiObjectStreamReturn<Schema>\n>;\n\n/**\n * An error that can occur in either the\n * {@link GraffitiObjectStream} or {@link GraffitiChannelStatsStream}.\n *\n * @internal\n */\nexport interface GraffitiStreamError {\n /**\n * The error that occurred while streaming data.\n */\n error: Error;\n /**\n * The origin that the error occurred. It will include\n * the scheme of the Graffiti implementation used and other\n * implementation-specific information like a hostname.\n */\n origin: string;\n}\n\n/**\n * A successful result from a {@link GraffitiObjectStream} or\n * {@link GraffitiObjectStreamContinue} that includes an object.\n *\n * @internal\n */\nexport interface GraffitiObjectStreamEntry<Schema extends JSONSchema> {\n /**\n * Empty property for compatibility with {@link GraffitiStreamError}\n */\n error?: undefined;\n /**\n * Empty property for compatibility with {@link GraffitiObjectStreamContinueTombstone}\n */\n tombstone?: undefined;\n /**\n * The object returned by the stream.\n */\n object: GraffitiObject<Schema>;\n}\n\n/**\n * A result from a {@link GraffitiObjectStreamContinue} that indicated\n * an object has been deleted since the original stream was run.\n * Only sparse metadata about the deleted object is returned to respect\n * the deleting user's privacy.\n *\n * @internal\n */\nexport interface GraffitiObjectStreamContinueTombstone {\n /**\n * Empty property for compatibility with {@link GraffitiStreamError}\n */\n error?: undefined;\n /**\n * Use this property to differentiate a tombstone from a\n * {@link GraffitiObjectStreamEntry}.\n */\n tombstone: true;\n /**\n * Sparse metadata about the deleted object. The full object is not returned\n * to respect a user's privacy.\n */\n object: {\n /**\n * The {@link GraffitiObjectBase.url | `url`} of the deleted object.\n */\n url: string;\n /**\n * The time at which the object was deleted, comparable to\n * {@link GraffitiObjectBase.lastModified | `lastModified`}.\n *\n * While it is not possible to re-{@link Graffiti.put | put} objects that have been\n * {@link Graffiti.delete | deleted}, objects may appear deleted if\n * an {@link GraffitiObjectBase.actor | `actor`} is no longer\n * {@link GraffitiObjectBase.allowed | `allowed`} to access them.\n * Therefore the {@link GraffitiObjectBase.lastModified | `lastModified`} property\n * is necessary to compare object versions.\n */\n lastModified: number;\n };\n}\n\n/**\n * A continuation of the {@link GraffitiObjectStream} type can include\n * both objects and tombstones of deleted objects.\n *\n * @internal\n */\nexport type GraffitiObjectStreamContinueEntry<Schema extends JSONSchema> =\n | GraffitiObjectStreamEntry<Schema>\n | GraffitiObjectStreamContinueTombstone;\n\n/**\n * The output of a {@link GraffitiObjectStream} or a {@link GraffitiObjectStreamContinue}\n * that allows the stream to be continued from where it left off.\n *\n * The {@link continue} function preserves the typing of the original stream,\n * where as the {@link cursor} string can be serialized for use after a user\n * has closed and reopened an application.\n *\n * The continued stream may include `tombstone`s of objects that have been\n * deleted since the original stream was run. See {@link GraffitiObjectStreamContinueTombstone}.\n * The continued stream may also return some objects that were already\n * returned by the original stream, depending on how much state the\n * underlying implementation is able to preserve.\n *\n * @internal\n */\nexport interface GraffitiObjectStreamReturn<Schema extends JSONSchema> {\n /**\n * @returns A function that creates new stream that continues from where the original stream left off.\n * It preserves the typing of the original stream.\n */\n continue: () => GraffitiObjectStreamContinue<Schema>;\n /**\n * A string that can be serialized and stored to resume the stream later.\n * It must be passed to the {@link Graffiti.continueObjectStream} method\n * to resume the stream.\n */\n cursor: string;\n}\n\n/**\n * A continutation of the {@link GraffitiObjectStream} type, as returned by\n * the {@link GraffitiObjectStreamReturn.continue} or by using\n * {@link GraffitiObjectStreamReturn.cursor} with {@link Graffiti.continueObjectStream}.\n *\n * The continued stream may include `tombstone`s of objects that have been\n * deleted since the original stream was run. See {@link GraffitiObjectStreamContinueTombstone}.\n *\n * @internal\n */\nexport type GraffitiObjectStreamContinue<Schema extends JSONSchema> =\n AsyncGenerator<\n GraffitiStreamError | GraffitiObjectStreamContinueEntry<Schema>,\n GraffitiObjectStreamReturn<Schema>\n >;\n\n/**\n * Statistic about single channel returned by {@link Graffiti.channelStats}.\n * These statistics only account for contributions made by the\n * querying actor.\n */\nexport type ChannelStats = {\n /**\n * The URI of the channel.\n */\n channel: string;\n /**\n * The number of objects that the actor has {@link Graffiti.put | put}\n * and not {@link Graffiti.delete | deleted} in the channel.\n */\n count: number;\n /**\n * The time that the actor {@link GraffitiObjectBase.lastModified | last modified} an object in the channel,\n * measured in milliseconds since January 1, 1970.\n * {@link Graffiti.delete | Deleted} objects do not effect this modification time.\n */\n lastModified: number;\n};\n\n/**\n * A stream of data that are returned by Graffiti's {@link Graffiti.channelStats} method.\n * See {@link GraffitiObjectStream} for more information on streams.\n */\nexport type GraffitiChannelStatsStream = AsyncGenerator<\n | GraffitiStreamError\n | {\n error?: undefined;\n value: ChannelStats;\n }\n>;\n\n/**\n * The event type produced in {@link Graffiti.sessionEvents}\n * when a user logs in manually from {@link Graffiti.login}\n * or when their session is restored from a previous login.\n * The event name to listen for is `login`.\n */\nexport type GraffitiLoginEvent = CustomEvent<\n | {\n error: Error;\n session?: undefined;\n }\n | {\n error?: undefined;\n session: GraffitiSession;\n }\n>;\n\n/**\n * The event type produced in {@link Graffiti.sessionEvents}\n * when a user logs out either manually with {@link Graffiti.logout}\n * or when their session times out or otherwise becomes invalid.\n * The event name to listen for is `logout`.\n */\nexport type GraffitiLogoutEvent = CustomEvent<\n | {\n error: Error;\n actor?: string;\n }\n | {\n error?: undefined;\n actor: string;\n }\n>;\n\n/**\n * The event type produced in {@link Graffiti.sessionEvents}\n * after an application has attempted to complete any login redirects\n * and restore any previously active sessions.\n * Successful session restores will be returned in parallel as\n * their own {@link GraffitiLoginEvent} events.\n *\n * This event optionally returns an `href` property\n * representing the URL the user originated a login request\n * from, which may be useful for redirecting the user back to\n * the page they were on after login.\n * The event name to listen for is `initialized`.\n */\nexport type GraffitiSessionInitializedEvent = CustomEvent<\n | {\n error?: Error;\n href?: string;\n }\n | null\n | undefined\n>;\n", "export class GraffitiErrorUnauthorized extends Error {\n constructor(message?: string) {\n super(message);\n this.name = \"GraffitiErrorUnauthorized\";\n Object.setPrototypeOf(this, GraffitiErrorUnauthorized.prototype);\n }\n}\n\nexport class GraffitiErrorForbidden extends Error {\n constructor(message?: string) {\n super(message);\n this.name = \"GraffitiErrorForbidden\";\n Object.setPrototypeOf(this, GraffitiErrorForbidden.prototype);\n }\n}\n\nexport class GraffitiErrorNotFound extends Error {\n constructor(message?: string) {\n super(message);\n this.name = \"GraffitiErrorNotFound\";\n Object.setPrototypeOf(this, GraffitiErrorNotFound.prototype);\n }\n}\n\nexport class GraffitiErrorInvalidSchema extends Error {\n constructor(message?: string) {\n super(message);\n this.name = \"GraffitiErrorInvalidSchema\";\n Object.setPrototypeOf(this, GraffitiErrorInvalidSchema.prototype);\n }\n}\n\nexport class GraffitiErrorSchemaMismatch extends Error {\n constructor(message?: string) {\n super(message);\n this.name = \"GraffitiErrorSchemaMismatch\";\n Object.setPrototypeOf(this, GraffitiErrorSchemaMismatch.prototype);\n }\n}\n\nexport class GraffitiErrorPatchTestFailed extends Error {\n constructor(message?: string) {\n super(message);\n this.name = \"GraffitiErrorPatchTestFailed\";\n Object.setPrototypeOf(this, GraffitiErrorPatchTestFailed.prototype);\n }\n}\n\nexport class GraffitiErrorPatchError extends Error {\n constructor(message?: string) {\n super(message);\n this.name = \"GraffitiErrorPatchError\";\n Object.setPrototypeOf(this, GraffitiErrorPatchError.prototype);\n }\n}\n\nexport class GraffitiErrorInvalidUrl extends Error {\n constructor(message?: string) {\n super(message);\n this.name = \"GraffitiErrorInvalidUrl\";\n Object.setPrototypeOf(this, GraffitiErrorInvalidUrl.prototype);\n }\n}\n\nexport class GraffitiErrorUnrecognizedUrlScheme extends Error {\n constructor(message?: string) {\n super(message);\n this.name = \"GraffitiErrorUnrecognizedUriScheme\";\n Object.setPrototypeOf(this, GraffitiErrorUnrecognizedUrlScheme.prototype);\n }\n}\n", "/// <reference types=\"./repeater.d.ts\" />\n/*! *****************************************************************************\r\nCopyright (c) Microsoft Corporation.\r\n\r\nPermission to use, copy, modify, and/or distribute this software for any\r\npurpose with or without fee is hereby granted.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\r\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\r\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\r\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\r\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\r\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\r\nPERFORMANCE OF THIS SOFTWARE.\r\n***************************************************************************** */\r\n/* global Reflect, Promise */\r\n\r\nvar extendStatics = function(d, b) {\r\n extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\r\n return extendStatics(d, b);\r\n};\r\n\r\nfunction __extends(d, b) {\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n}\r\n\r\nfunction __awaiter(thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n}\r\n\r\nfunction __generator(thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n}\r\n\r\nfunction __values(o) {\r\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\r\n if (m) return m.call(o);\r\n if (o && typeof o.length === \"number\") return {\r\n next: function () {\r\n if (o && i >= o.length) o = void 0;\r\n return { value: o && o[i++], done: !o };\r\n }\r\n };\r\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\r\n}\r\n\r\nfunction __await(v) {\r\n return this instanceof __await ? (this.v = v, this) : new __await(v);\r\n}\r\n\r\nfunction __asyncGenerator(thisArg, _arguments, generator) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\r\n return i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i;\r\n function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }\r\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\r\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\r\n function fulfill(value) { resume(\"next\", value); }\r\n function reject(value) { resume(\"throw\", value); }\r\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\r\n}\n\n/** An error subclass which is thrown when there are too many pending push or next operations on a single repeater. */\r\nvar RepeaterOverflowError = /** @class */ (function (_super) {\r\n __extends(RepeaterOverflowError, _super);\r\n function RepeaterOverflowError(message) {\r\n var _this = _super.call(this, message) || this;\r\n Object.defineProperty(_this, \"name\", {\r\n value: \"RepeaterOverflowError\",\r\n enumerable: false,\r\n });\r\n if (typeof Object.setPrototypeOf === \"function\") {\r\n Object.setPrototypeOf(_this, _this.constructor.prototype);\r\n }\r\n else {\r\n _this.__proto__ = _this.constructor.prototype;\r\n }\r\n if (typeof Error.captureStackTrace === \"function\") {\r\n Error.captureStackTrace(_this, _this.constructor);\r\n }\r\n return _this;\r\n }\r\n return RepeaterOverflowError;\r\n}(Error));\r\n/** A buffer which allows you to push a set amount of values to the repeater without pushes waiting or throwing errors. */\r\nvar FixedBuffer = /** @class */ (function () {\r\n function FixedBuffer(capacity) {\r\n if (capacity < 0) {\r\n throw new RangeError(\"Capacity may not be less than 0\");\r\n }\r\n this._c = capacity;\r\n this._q = [];\r\n }\r\n Object.defineProperty(FixedBuffer.prototype, \"empty\", {\r\n get: function () {\r\n return this._q.length === 0;\r\n },\r\n enumerable: false,\r\n configurable: true\r\n });\r\n Object.defineProperty(FixedBuffer.prototype, \"full\", {\r\n get: function () {\r\n return this._q.length >= this._c;\r\n },\r\n enumerable: false,\r\n configurable: true\r\n });\r\n FixedBuffer.prototype.add = function (value) {\r\n if (this.full) {\r\n throw new Error(\"Buffer full\");\r\n }\r\n else {\r\n this._q.push(value);\r\n }\r\n };\r\n FixedBuffer.prototype.remove = function () {\r\n if (this.empty) {\r\n throw new Error(\"Buffer empty\");\r\n }\r\n return this._q.shift();\r\n };\r\n return FixedBuffer;\r\n}());\r\n// TODO: Use a circular buffer here.\r\n/** Sliding buffers allow you to push a set amount of values to the repeater without pushes waiting or throwing errors. If the number of values exceeds the capacity set in the constructor, the buffer will discard the earliest values added. */\r\nvar SlidingBuffer = /** @class */ (function () {\r\n function SlidingBuffer(capacity) {\r\n if (capacity < 1) {\r\n throw new RangeError(\"Capacity may not be less than 1\");\r\n }\r\n this._c = capacity;\r\n this._q = [];\r\n }\r\n Object.defineProperty(SlidingBuffer.prototype, \"empty\", {\r\n get: function () {\r\n return this._q.length === 0;\r\n },\r\n enumerable: false,\r\n configurable: true\r\n });\r\n Object.defineProperty(SlidingBuffer.prototype, \"full\", {\r\n get: function () {\r\n return false;\r\n },\r\n enumerable: false,\r\n configurable: true\r\n });\r\n SlidingBuffer.prototype.add = function (value) {\r\n while (this._q.length >= this._c) {\r\n this._q.shift();\r\n }\r\n this._q.push(value);\r\n };\r\n SlidingBuffer.prototype.remove = function () {\r\n if (this.empty) {\r\n throw new Error(\"Buffer empty\");\r\n }\r\n return this._q.shift();\r\n };\r\n return SlidingBuffer;\r\n}());\r\n/** Dropping buffers allow you to push a set amount of values to the repeater without the push function waiting or throwing errors. If the number of values exceeds the capacity set in the constructor, the buffer will discard the latest values added. */\r\nvar DroppingBuffer = /** @class */ (function () {\r\n function DroppingBuffer(capacity) {\r\n if (capacity < 1) {\r\n throw new RangeError(\"Capacity may not be less than 1\");\r\n }\r\n this._c = capacity;\r\n this._q = [];\r\n }\r\n Object.defineProperty(DroppingBuffer.prototype, \"empty\", {\r\n get: function () {\r\n return this._q.length === 0;\r\n },\r\n enumerable: false,\r\n configurable: true\r\n });\r\n Object.defineProperty(DroppingBuffer.prototype, \"full\", {\r\n get: function () {\r\n return false;\r\n },\r\n enumerable: false,\r\n configurable: true\r\n });\r\n DroppingBuffer.prototype.add = function (value) {\r\n if (this._q.length < this._c) {\r\n this._q.push(value);\r\n }\r\n };\r\n DroppingBuffer.prototype.remove = function () {\r\n if (this.empty) {\r\n throw new Error(\"Buffer empty\");\r\n }\r\n return this._q.shift();\r\n };\r\n return DroppingBuffer;\r\n}());\r\n/** Makes sure promise-likes don\u2019t cause unhandled rejections. */\r\nfunction swallow(value) {\r\n if (value != null && typeof value.then === \"function\") {\r\n value.then(NOOP, NOOP);\r\n }\r\n}\r\n/*** REPEATER STATES ***/\r\n/** The following is an enumeration of all possible repeater states. These states are ordered, and a repeater may only advance to higher states. */\r\n/** The initial state of the repeater. */\r\nvar Initial = 0;\r\n/** Repeaters advance to this state the first time the next method is called on the repeater. */\r\nvar Started = 1;\r\n/** Repeaters advance to this state when the stop function is called. */\r\nvar Stopped = 2;\r\n/** Repeaters advance to this state when there are no values left to be pulled from the repeater. */\r\nvar Done = 3;\r\n/** Repeaters advance to this state if an error is thrown into the repeater. */\r\nvar Rejected = 4;\r\n/** The maximum number of push or next operations which may exist on a single repeater. */\r\nvar MAX_QUEUE_LENGTH = 1024;\r\nvar NOOP = function () { };\r\n/** A helper function used to mimic the behavior of async generators where the final iteration is consumed. */\r\nfunction consumeExecution(r) {\r\n var err = r.err;\r\n var execution = Promise.resolve(r.execution).then(function (value) {\r\n if (err != null) {\r\n throw err;\r\n }\r\n return value;\r\n });\r\n r.err = undefined;\r\n r.execution = execution.then(function () { return undefined; }, function () { return undefined; });\r\n return r.pending === undefined ? execution : r.pending.then(function () { return execution; });\r\n}\r\n/** A helper function for building iterations from values. Promises are unwrapped, so that iterations never have their value property set to a promise. */\r\nfunction createIteration(r, value) {\r\n var done = r.state >= Done;\r\n return Promise.resolve(value).then(function (value) {\r\n if (!done && r.state >= Rejected) {\r\n return consumeExecution(r).then(function (value) { return ({\r\n value: value,\r\n done: true,\r\n }); });\r\n }\r\n return { value: value, done: done };\r\n });\r\n}\r\n/**\r\n * This function is bound and passed to the executor as the stop argument.\r\n *\r\n * Advances state to Stopped.\r\n */\r\nfunction stop(r, err) {\r\n var e_1, _a;\r\n if (r.state >= Stopped) {\r\n return;\r\n }\r\n r.state = Stopped;\r\n r.onnext();\r\n r.onstop();\r\n if (r.err == null) {\r\n r.err = err;\r\n }\r\n if (r.pushes.length === 0 &&\r\n (typeof r.buffer === \"undefined\" || r.buffer.empty)) {\r\n finish(r);\r\n }\r\n else {\r\n try {\r\n for (var _b = __values(r.pushes), _d = _b.next(); !_d.done; _d = _b.next()) {\r\n var push_1 = _d.value;\r\n push_1.resolve();\r\n }\r\n }\r\n catch (e_1_1) { e_1 = { error: e_1_1 }; }\r\n finally {\r\n try {\r\n if (_d && !_d.done && (_a = _b.return)) _a.call(_b);\r\n }\r\n finally { if (e_1) throw e_1.error; }\r\n }\r\n }\r\n}\r\n/**\r\n * The difference between stopping a repeater vs finishing a repeater is that stopping a repeater allows next to continue to drain values from the push queue and buffer, while finishing a repeater will clear all pending values and end iteration immediately. Once, a repeater is finished, all iterations will have the done property set to true.\r\n *\r\n * Advances state to Done.\r\n */\r\nfunction finish(r) {\r\n var e_2, _a;\r\n if (r.state >= Done) {\r\n return;\r\n }\r\n if (r.state < Stopped) {\r\n stop(r);\r\n }\r\n r.state = Done;\r\n r.buffer = undefined;\r\n try {\r\n for (var _b = __values(r.nexts), _d = _b.next(); !_d.done; _d = _b.next()) {\r\n var next = _d.value;\r\n var execution = r.pending === undefined\r\n ? consumeExecution(r)\r\n : r.pending.then(function () { return consumeExecution(r); });\r\n next.resolve(createIteration(r, execution));\r\n }\r\n }\r\n catch (e_2_1) { e_2 = { error: e_2_1 }; }\r\n finally {\r\n try {\r\n if (_d && !_d.done && (_a = _b.return)) _a.call(_b);\r\n }\r\n finally { if (e_2) throw e_2.error; }\r\n }\r\n r.pushes = [];\r\n r.nexts = [];\r\n}\r\n/**\r\n * Called when a promise passed to push rejects, or when a push call is unhandled.\r\n *\r\n * Advances state to Rejected.\r\n */\r\nfunction reject(r) {\r\n if (r.state >= Rejected) {\r\n return;\r\n }\r\n if (r.state < Done) {\r\n finish(r);\r\n }\r\n r.state = Rejected;\r\n}\r\n/** This function is bound and passed to the executor as the push argument. */\r\nfunction push(r, value) {\r\n swallow(value);\r\n if (r.pushes.length >= MAX_QUEUE_LENGTH) {\r\n throw new RepeaterOverflowError(\"No more than \" + MAX_QUEUE_LENGTH + \" pending calls to push are allowed on a single repeater.\");\r\n }\r\n else if (r.state >= Stopped) {\r\n return Promise.resolve(undefined);\r\n }\r\n var valueP = r.pending === undefined\r\n ? Promise.resolve(value)\r\n : r.pending.then(function () { return value; });\r\n valueP = valueP.catch(function (err) {\r\n if (r.state < Stopped) {\r\n r.err = err;\r\n }\r\n reject(r);\r\n return undefined; // void :(\r\n });\r\n var nextP;\r\n if (r.nexts.length) {\r\n var next_1 = r.nexts.shift();\r\n next_1.resolve(createIteration(r, valueP));\r\n if (r.nexts.length) {\r\n nextP = Promise.resolve(r.nexts[0].value);\r\n }\r\n else if (typeof r.buffer !== \"undefined\" && !r.buffer.full) {\r\n nextP = Promise.resolve(undefined);\r\n }\r\n else {\r\n nextP = new Promise(function (resolve) { return (r.onnext = resolve); });\r\n }\r\n }\r\n else if (typeof r.buffer !== \"undefined\" && !r.buffer.full) {\r\n r.buffer.add(valueP);\r\n nextP = Promise.resolve(undefined);\r\n }\r\n else {\r\n nextP = new Promise(function (resolve) { return r.pushes.push({ resolve: resolve, value: valueP }); });\r\n }\r\n // If an error is thrown into the repeater via the next or throw methods, we give the repeater a chance to handle this by rejecting the promise returned from push. If the push call is not immediately handled we throw the next iteration of the repeater.\r\n // To check that the promise returned from push is floating, we modify the then and catch methods of the returned promise so that they flip the floating flag. The push function actually does not return a promise, because modern engines do not call the then and catch methods on native promises. By making next a plain old javascript object, we ensure that the then and catch methods will be called.\r\n var floating = true;\r\n var next = {};\r\n var unhandled = nextP.catch(function (err) {\r\n if (floating) {\r\n throw err;\r\n }\r\n return undefined; // void :(\r\n });\r\n next.then = function (onfulfilled, onrejected) {\r\n floating = false;\r\n return Promise.prototype.then.call(nextP, onfulfilled, onrejected);\r\n };\r\n next.catch = function (onrejected) {\r\n floating = false;\r\n return Promise.prototype.catch.call(nextP, onrejected);\r\n };\r\n next.finally = nextP.finally.bind(nextP);\r\n r.pending = valueP\r\n .then(function () { return unhandled; })\r\n .catch(function (err) {\r\n r.err = err;\r\n reject(r);\r\n });\r\n return next;\r\n}\r\n/**\r\n * Creates the stop callable promise which is passed to the executor\r\n */\r\nfunction createStop(r) {\r\n var stop1 = stop.bind(null, r);\r\n var stopP = new Promise(function (resolve) { return (r.onstop = resolve); });\r\n stop1.then = stopP.then.bind(stopP);\r\n stop1.catch = stopP.catch.bind(stopP);\r\n stop1.finally = stopP.finally.bind(stopP);\r\n return stop1;\r\n}\r\n/**\r\n * Calls the executor passed into the constructor. This function is called the first time the next method is called on the repeater.\r\n *\r\n * Advances state to Started.\r\n */\r\nfunction execute(r) {\r\n if (r.state >= Started) {\r\n return;\r\n }\r\n r.state = Started;\r\n var push1 = push.bind(null, r);\r\n var stop1 = createStop(r);\r\n r.execution = new Promise(function (resolve) { return resolve(r.executor(push1, stop1)); });\r\n // TODO: We should consider stopping all repeaters when the executor settles.\r\n r.execution.catch(function () { return stop(r); });\r\n}\r\nvar records = new WeakMap();\r\n// NOTE: While repeaters implement and are assignable to the AsyncGenerator interface, and you can use the types interchangeably, we don\u2019t use typescript\u2019s implements syntax here because this would make supporting earlier versions of typescript trickier. This is because TypeScript version 3.6 changed the iterator types by adding the TReturn and TNext type parameters.\r\nvar Repeater = /** @class */ (function () {\r\n function Repeater(executor, buffer) {\r\n records.set(this, {\r\n executor: executor,\r\n buffer: buffer,\r\n err: undefined,\r\n state: Initial,\r\n pushes: [],\r\n nexts: [],\r\n pending: undefined,\r\n execution: undefined,\r\n onnext: NOOP,\r\n onstop: NOOP,\r\n });\r\n }\r\n Repeater.prototype.next = function (value) {\r\n swallow(value);\r\n var r = records.get(this);\r\n if (r === undefined) {\r\n throw new Error(\"WeakMap error\");\r\n }\r\n if (r.nexts.length >= MAX_QUEUE_LENGTH) {\r\n throw new RepeaterOverflowError(\"No more than \" + MAX_QUEUE_LENGTH + \" pending calls to next are allowed on a single repeater.\");\r\n }\r\n if (r.state <= Initial) {\r\n execute(r);\r\n }\r\n r.onnext(value);\r\n if (typeof r.buffer !== \"undefined\" && !r.buffer.empty) {\r\n var result = createIteration(r, r.buffer.remove());\r\n if (r.pushes.length) {\r\n var push_2 = r.pushes.shift();\r\n r.buffer.add(push_2.value);\r\n r.onnext = push_2.resolve;\r\n }\r\n return result;\r\n }\r\n else if (r.pushes.length) {\r\n var push_3 = r.pushes.shift();\r\n r.onnext = push_3.resolve;\r\n return createIteration(r, push_3.value);\r\n }\r\n else if (r.state >= Stopped) {\r\n finish(r);\r\n return createIteration(r, consumeExecution(r));\r\n }\r\n return new Promise(function (resolve) { return r.nexts.push({ resolve: resolve, value: value }); });\r\n };\r\n Repeater.prototype.return = function (value) {\r\n swallow(value);\r\n var r = records.get(this);\r\n if (r === undefined) {\r\n throw new Error(\"WeakMap error\");\r\n }\r\n finish(r);\r\n // We override the execution because return should always return the value passed in.\r\n r.execution = Promise.resolve(r.execution).then(function () { return value; });\r\n return createIteration(r, consumeExecution(r));\r\n };\r\n Repeater.prototype.throw = function (err) {\r\n var r = records.get(this);\r\n if (r === undefined) {\r\n throw new Error(\"WeakMap error\");\r\n }\r\n if (r.state <= Initial ||\r\n r.state >= Stopped ||\r\n (typeof r.buffer !== \"undefined\" && !r.buffer.empty)) {\r\n finish(r);\r\n // If r.err is already set, that mean the repeater has already produced an error, so we throw that error rather than the error passed in, because doing so might be more informative for the caller.\r\n if (r.err == null) {\r\n r.err = err;\r\n }\r\n return createIteration(r, consumeExecution(r));\r\n }\r\n return this.next(Promise.reject(err));\r\n };\r\n Repeater.prototype[Symbol.asyncIterator] = function () {\r\n return this;\r\n };\r\n // TODO: Remove these static methods from the class.\r\n Repeater.race = race;\r\n Repeater.merge = merge;\r\n Repeater.zip = zip;\r\n Repeater.latest = latest;\r\n return Repeater;\r\n}());\r\n/*** COMBINATOR FUNCTIONS ***/\r\n// TODO: move these combinators to their own file.\r\nfunction getIterators(values, options) {\r\n var e_3, _a;\r\n var iters = [];\r\n var _loop_1 = function (value) {\r\n if (value != null && typeof value[Symbol.asyncIterator] === \"function\") {\r\n iters.push(value[Symbol.asyncIterator]());\r\n }\r\n else if (value != null && typeof value[Symbol.iterator] === \"function\") {\r\n iters.push(value[Symbol.iterator]());\r\n }\r\n else {\r\n iters.push((function valueToAsyncIterator() {\r\n return __asyncGenerator(this, arguments, function valueToAsyncIterator_1() {\r\n return __generator(this, function (_a) {\r\n switch (_a.label) {\r\n case 0:\r\n if (!options.yieldValues) return [3 /*break*/, 3];\r\n return [4 /*yield*/, __await(value)];\r\n case 1: return [4 /*yield*/, _a.sent()];\r\n case 2:\r\n _a.sent();\r\n _a.label = 3;\r\n case 3:\r\n if (!options.returnValues) return [3 /*break*/, 5];\r\n return [4 /*yield*/, __await(value)];\r\n case 4: return [2 /*return*/, _a.sent()];\r\n case 5: return [2 /*return*/];\r\n }\r\n });\r\n });\r\n })());\r\n }\r\n };\r\n try {\r\n for (var values_1 = __values(values), values_1_1 = values_1.next(); !values_1_1.done; values_1_1 = values_1.next()) {\r\n var value = values_1_1.value;\r\n _loop_1(value);\r\n }\r\n }\r\n catch (e_3_1) { e_3 = { error: e_3_1 }; }\r\n finally {\r\n try {\r\n if (values_1_1 && !values_1_1.done && (_a = values_1.return)) _a.call(values_1);\r\n }\r\n finally { if (e_3) throw e_3.error; }\r\n }\r\n return iters;\r\n}\r\n// NOTE: whenever you see any variables called `advance` or `advances`, know that it is a hack to get around the fact that `Promise.race` leaks memory. These variables are intended to be set to the resolve function of a promise which is constructed and awaited as an alternative to Promise.race. For more information, see this comment in the Node.js issue tracker: https://github.com/nodejs/node/issues/17469#issuecomment-685216777.\r\nfunction race(contenders) {\r\n var _this = this;\r\n var iters = getIterators(contenders, { returnValues: true });\r\n return new Repeater(function (push, stop) { return __awaiter(_this, void 0, void 0, function () {\r\n var advance, stopped, finalIteration, iteration, i_1, _loop_2;\r\n return __generator(this, function (_a) {\r\n switch (_a.label) {\r\n case 0:\r\n if (!iters.length) {\r\n stop();\r\n return [2 /*return*/];\r\n }\r\n stopped = false;\r\n stop.then(function () {\r\n advance();\r\n stopped = true;\r\n });\r\n _a.label = 1;\r\n case 1:\r\n _a.trys.push([1, , 5, 7]);\r\n iteration = void 0;\r\n i_1 = 0;\r\n _loop_2 = function () {\r\n var j, iters_1, iters_1_1, iter;\r\n var e_4, _a;\r\n return __generator(this, function (_b) {\r\n switch (_b.label) {\r\n case 0:\r\n j = i_1;\r\n try {\r\n for (iters_1 = (e_4 = void 0, __values(iters)), iters_1_1 = iters_1.next(); !iters_1_1.done; iters_1_1 = iters_1.next()) {\r\n iter = iters_1_1.value;\r\n Promise.resolve(iter.next()).then(function (iteration) {\r\n if (iteration.done) {\r\n stop();\r\n if (finalIteration === undefined) {\r\n finalIteration = iteration;\r\n }\r\n }\r\n else if (i_1 === j) {\r\n // This iterator has won, advance i and resolve the promise.\r\n i_1++;\r\n advance(iteration);\r\n }\r\n }, function (err) { return stop(err); });\r\n }\r\n }\r\n catch (e_4_1) { e_4 = { error: e_4_1 }; }\r\n finally {\r\n try {\r\n if (iters_1_1 && !iters_1_1.done && (_a = iters_1.return)) _a.call(iters_1);\r\n }\r\n finally { if (e_4) throw e_4.error; }\r\n }\r\n return [4 /*yield*/, new Promise(function (resolve) { return (advance = resolve); })];\r\n case 1:\r\n iteration = _b.sent();\r\n if (!(iteration !== undefined)) return [3 /*break*/, 3];\r\n return [4 /*yield*/, push(iteration.value)];\r\n case 2:\r\n _b.sent();\r\n _b.label = 3;\r\n case 3: return [2 /*return*/];\r\n }\r\n });\r\n };\r\n _a.label = 2;\r\n case 2:\r\n if (!!stopped) return [3 /*break*/, 4];\r\n return [5 /*yield**/, _loop_2()];\r\n case 3:\r\n _a.sent();\r\n return [3 /*break*/, 2];\r\n case 4: return [2 /*return*/, finalIteration && finalIteration.value];\r\n case 5:\r\n stop();\r\n return [4 /*yield*/, Promise.race(iters.map(function (iter) { return iter.return && iter.return(); }))];\r\n case 6:\r\n _a.sent();\r\n return [7 /*endfinally*/];\r\n case 7: return [2 /*return*/];\r\n }\r\n });\r\n }); });\r\n}\r\nfunction merge(contenders) {\r\n var _this = this;\r\n var iters = getIterators(contenders, { yieldValues: true });\r\n return new Repeater(function (push, stop) { return __awaiter(_this, void 0, void 0, function () {\r\n var advances, stopped, finalIteration;\r\n var _this = this;\r\n return __generator(this, function (_a) {\r\n switch (_a.label) {\r\n case 0:\r\n if (!iters.length) {\r\n stop();\r\n return [2 /*return*/];\r\n }\r\n advances = [];\r\n stopped = false;\r\n stop.then(function () {\r\n var e_5, _a;\r\n stopped = true;\r\n try {\r\n for (var advances_1 = __values(advances), advances_1_1 = advances_1.next(); !advances_1_1.done; advances_1_1 = advances_1.next()) {\r\n var advance = advances_1_1.value;\r\n advance();\r\n }\r\n }\r\n catch (e_5_1) { e_5 = { error: e_5_1 }; }\r\n finally {\r\n try {\r\n if (advances_1_1 && !advances_1_1.done && (_a = advances_1.return)) _a.call(advances_1);\r\n }\r\n finally { if (e_5) throw e_5.error; }\r\n }\r\n });\r\n _a.label = 1;\r\n case 1:\r\n _a.trys.push([1, , 3, 4]);\r\n return [4 /*yield*/, Promise.all(iters.map(function (iter, i) { return __awaiter(_this, void 0, void 0, function () {\r\n var iteration, _a;\r\n return __generator(this, function (_b) {\r\n switch (_b.label) {\r\n case 0:\r\n _b.trys.push([0, , 6, 9]);\r\n _b.label = 1;\r\n case 1:\r\n if (!!stopped) return [3 /*break*/, 5];\r\n Promise.resolve(iter.next()).then(function (iteration) { return advances[i](iteration); }, function (err) { return stop(err); });\r\n return [4 /*yield*/, new Promise(function (resolve) {\r\n advances[i] = resolve;\r\n })];\r\n case 2:\r\n iteration = _b.sent();\r\n if (!(iteration !== undefined)) return [3 /*break*/, 4];\r\n if (iteration.done) {\r\n finalIteration = iteration;\r\n return [2 /*return*/];\r\n }\r\n return [4 /*yield*/, push(iteration.value)];\r\n case 3:\r\n _b.sent();\r\n _b.label = 4;\r\n case 4: return [3 /*break*/, 1];\r\n case 5: return [3 /*break*/, 9];\r\n case 6:\r\n _a = iter.return;\r\n if (!_a) return [3 /*break*/, 8];\r\n return [4 /*yield*/, iter.return()];\r\n case 7:\r\n _a = (_b.sent());\r\n _b.label = 8;\r\n case 8:\r\n return [7 /*endfinally*/];\r\n case 9: return [2 /*return*/];\r\n }\r\n });\r\n }); }))];\r\n case 2:\r\n _a.sent();\r\n return [2 /*return*/, finalIteration && finalIteration.value];\r\n case 3:\r\n stop();\r\n return [7 /*endfinally*/];\r\n case 4: return [2 /*return*/];\r\n }\r\n });\r\n }); });\r\n}\r\nfunction zip(contenders) {\r\n var _this = this;\r\n var iters = getIterators(contenders, { returnValues: true });\r\n return new Repeater(function (push, stop) { return __awaiter(_this, void 0, void 0, function () {\r\n var advance, stopped, iterations, values;\r\n return __generator(this, function (_a) {\r\n switch (_a.label) {\r\n case 0:\r\n if (!iters.length) {\r\n stop();\r\n return [2 /*return*/, []];\r\n }\r\n stopped = false;\r\n stop.then(function () {\r\n advance();\r\n stopped = true;\r\n });\r\n _a.label = 1;\r\n case 1:\r\n _a.trys.push([1, , 6, 8]);\r\n _a.label = 2;\r\n case 2:\r\n if (!!stopped) return [3 /*break*/, 5];\r\n Promise.all(iters.map(function (iter) { return iter.next(); })).then(function (iterations) { return advance(iterations); }, function (err) { return stop(err); });\r\n return [4 /*yield*/, new Promise(function (resolve) { return (advance = resolve); })];\r\n case 3:\r\n iterations = _a.sent();\r\n if (iterations === undefined) {\r\n return [2 /*return*/];\r\n }\r\n values = iterations.map(function (iteration) { return iteration.value; });\r\n if (iterations.some(function (iteration) { return iteration.done; })) {\r\n return [2 /*return*/, values];\r\n }\r\n return [4 /*yield*/, push(values)];\r\n case 4:\r\n _a.sent();\r\n return [3 /*break*/, 2];\r\n case 5: return [3 /*break*/, 8];\r\n case 6:\r\n stop();\r\n return [4 /*yield*/, Promise.all(iters.map(function (iter) { return iter.return && iter.return(); }))];\r\n case 7:\r\n _a.sent();\r\n return [7 /*endfinally*/];\r\n case 8: return [2 /*return*/];\r\n }\r\n });\r\n }); });\r\n}\r\nfunction latest(contenders) {\r\n var _this = this;\r\n var iters = getIterators(contenders, {\r\n yieldValues: true,\r\n returnValues: true,\r\n });\r\n return new Repeater(function (push, stop) { return __awaiter(_this, void 0, void 0, function () {\r\n var advance, advances, stopped, iterations_1, values_2;\r\n var _this = this;\r\n return __generator(this, function (_a) {\r\n switch (_a.label) {\r\n case 0:\r\n if (!iters.length) {\r\n stop();\r\n return [2 /*return*/, []];\r\n }\r\n advances = [];\r\n stopped = false;\r\n stop.then(function () {\r\n var e_6, _a;\r\n advance();\r\n try {\r\n for (var advances_2 = __values(advances), advances_2_1 = advances_2.next(); !advances_2_1.done; advances_2_1 = advances_2.next()) {\r\n var advance1 = advances_2_1.value;\r\n advance1();\r\n }\r\n }\r\n catch (e_6_1) { e_6 = { error: e_6_1 }; }\r\n finally {\r\n try {\r\n if (advances_2_1 && !advances_2_1.done && (_a = advances_2.return)) _a.call(advances_2);\r\n }\r\n finally { if (e_6) throw e_6.error; }\r\n }\r\n stopped = true;\r\n });\r\n _a.label = 1;\r\n case 1:\r\n _a.trys.push([1, , 5, 7]);\r\n Promise.all(iters.map(function (iter) { return iter.next(); })).then(function (iterations) { return advance(iterations); }, function (err) { return stop(err); });\r\n return [4 /*yield*/, new Promise(function (resolve) { return (advance = resolve); })];\r\n case 2:\r\n iterations_1 = _a.sent();\r\n if (iterations_1 === undefined) {\r\n return [2 /*return*/];\r\n }\r\n values_2 = iterations_1.map(function (iteration) { return iteration.value; });\r\n if (iterations_1.every(function (iteration) { return iteration.done; })) {\r\n return [2 /*return*/, values_2];\r\n }\r\n // We continuously yield and mutate the same values array so we shallow copy it each time it is pushed.\r\n return [4 /*yield*/, push(values_2.slice())];\r\n case 3:\r\n // We continuously yield and mutate the same values array so we shallow copy it each time it is pushed.\r\n _a.sent();\r\n return [4 /*yield*/, Promise.all(iters.map(function (iter, i) { return __awaiter(_this, void 0, void 0, function () {\r\n var iteration;\r\n return __generator(this, function (_a) {\r\n switch (_a.label) {\r\n case 0:\r\n if (iterations_1[i].done) {\r\n return [2 /*return*/, iterations_1[i].value];\r\n }\r\n _a.label = 1;\r\n case 1:\r\n if (!!stopped) return [3 /*break*/, 4];\r\n Promise.resolve(iter.next()).then(function (iteration) { return advances[i](iteration); }, function (err) { return stop(err); });\r\n return [4 /*yield*/, new Promise(function (resolve) { return (advances[i] = resolve); })];\r\n case 2:\r\n iteration = _a.sent();\r\n if (iteration === undefined) {\r\n return [2 /*return*/, iterations_1[i].value];\r\n }\r\n else if (iteration.done) {\r\n return [2 /*return*/, iteration.value];\r\n }\r\n values_2[i] = iteration.value;\r\n return [4 /*yield*/, push(values_2.slice())];\r\n case 3:\r\n _a.sent();\r\n return [3 /*break*/, 1];\r\n case 4: return [2 /*return*/];\r\n }\r\n });\r\n }); }))];\r\n case 4: return [2 /*return*/, _a.sent()];\r\n case 5:\r\n stop();\r\n return [4 /*yield*/, Promise.all(iters.map(function (iter) { return iter.return && iter.return(); }))];\r\n case 6:\r\n _a.sent();\r\n return [7 /*endfinally*/];\r\n case 7: return [2 /*return*/];\r\n }\r\n });\r\n }); });\r\n}\n\nexport { DroppingBuffer, FixedBuffer, MAX_QUEUE_LENGTH, Repeater, RepeaterOverflowError, SlidingBuffer };\n//# sourceMappingURL=repeater.js.map\n", "import {\n GraffitiErrorInvalidSchema,\n GraffitiErrorPatchError,\n GraffitiErrorPatchTestFailed,\n} from \"@graffiti-garden/api\";\nimport type {\n GraffitiObject,\n GraffitiObjectBase,\n GraffitiPatch,\n JSONSchema,\n GraffitiSession,\n GraffitiObjectUrl,\n} from \"@graffiti-garden/api\";\nimport type { Ajv } from \"ajv\";\nimport type { applyPatch } from \"fast-json-patch\";\n\nexport function unpackObjectUrl(url: string | GraffitiObjectUrl) {\n return typeof url === \"string\" ? url : url.url;\n}\n\nexport function randomBase64(numBytes: number = 24) {\n const bytes = new Uint8Array(numBytes);\n crypto.getRandomValues(bytes);\n // Convert it to base64\n const base64 = btoa(String.fromCodePoint(...bytes));\n // Make sure it is url safe\n return base64.replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/\\=+$/, \"\");\n}\n\nexport function applyGraffitiPatch<Prop extends keyof GraffitiPatch>(\n apply: typeof applyPatch,\n prop: Prop,\n patch: GraffitiPatch,\n object: GraffitiObjectBase,\n): void {\n const ops = patch[prop];\n if (!ops || !ops.length) return;\n try {\n object[prop] = apply(object[prop], ops, true, false).newDocument;\n } catch (e) {\n if (\n typeof e === \"object\" &&\n e &&\n \"name\" in e &&\n typeof e.name === \"string\" &&\n \"message\" in e &&\n typeof e.message === \"string\"\n ) {\n if (e.name === \"TEST_OPERATION_FAILED\") {\n throw new GraffitiErrorPatchTestFailed(e.message);\n } else {\n throw new GraffitiErrorPatchError(e.name + \": \" + e.message);\n }\n } else {\n throw e;\n }\n }\n}\n\nexport function compileGraffitiObjectSchema<Schema extends JSONSchema>(\n ajv: Ajv,\n schema: Schema,\n) {\n try {\n // Force the validation guard because\n // it is too big for the type checker.\n // Fortunately json-schema-to-ts is\n // well tested against ajv.\n return ajv.compile(schema) as (\n data: GraffitiObjectBase,\n ) => data is GraffitiObject<Schema>;\n } catch (error) {\n throw new GraffitiErrorInvalidSchema(\n error instanceof Error ? error.message : undefined,\n );\n }\n}\n\nexport function maskGraffitiObject(\n object: GraffitiObjectBase,\n channels: string[],\n session?: GraffitiSession | null,\n): void {\n if (object.actor !== session?.actor) {\n object.allowed = object.allowed && session ? [session.actor] : undefined;\n object.channels = object.channels.filter((channel) =>\n channels.includes(channel),\n );\n }\n}\nexport function isActorAllowedGraffitiObject(\n object: GraffitiObjectBase,\n session?: GraffitiSession | null,\n) {\n return (\n object.allowed === undefined ||\n object.allowed === null ||\n (!!session?.actor &&\n (object.actor === session.actor ||\n object.allowed.includes(session.actor)))\n );\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["init_dirname", "init_buffer", "init_process", "init_dirname", "init_buffer", "init_process", "Graffiti", "GraffitiObjectJSONSchema", "GraffitiPutObjectJSONSchema", "GraffitiErrorInvalidSchema", "_GraffitiErrorInvalidSchema", "message", "GraffitiErrorPatchTestFailed", "_GraffitiErrorPatchTestFailed", "message", "GraffitiErrorPatchError", "_GraffitiErrorPatchError", "init_dirname", "init_buffer", "init_process", "extendStatics", "d", "b", "p", "__extends", "__", "__awaiter", "thisArg", "_arguments", "P", "generator", "adopt", "value", "resolve", "reject", "fulfilled", "step", "e", "rejected", "result", "__generator", "body", "_", "t", "f", "y", "g", "verb", "n", "v", "op", "__values", "o", "s", "m", "i", "__await", "__asyncGenerator", "q", "a", "resume", "settle", "r", "fulfill", "RepeaterOverflowError", "_super", "message", "_this", "FixedBuffer", "capacity", "SlidingBuffer", "DroppingBuffer", "swallow", "NOOP", "Initial", "Started", "Stopped", "Done", "Rejected", "MAX_QUEUE_LENGTH", "consumeExecution", "err", "execution", "createIteration", "done", "stop", "e_1", "_a", "finish", "_b", "_d", "push_1", "e_1_1", "e_2", "next", "e_2_1", "push", "valueP", "nextP", "next_1", "floating", "unhandled", "onfulfilled", "onrejected", "createStop", "stop1", "stopP", "execute", "push1", "records", "Repeater", "executor", "buffer", "push_2", "push_3", "race", "merge", "zip", "latest", "getIterators", "values", "options", "e_3", "iters", "_loop_1", "values_1", "values_1_1", "e_3_1", "contenders", "advance", "stopped", "finalIteration", "iteration", "i_1", "_loop_2", "j", "iters_1", "iters_1_1", "iter", "e_4", "e_4_1", "advances", "e_5", "advances_1", "advances_1_1", "e_5_1", "iterations", "iterations_1", "values_2", "e_6", "advances_2", "advances_2_1", "advance1", "e_6_1", "init_dirname", "init_buffer", "init_process", "unpackObjectUrl", "url", "applyGraffitiPatch", "apply", "prop", "patch", "object", "ops", "e", "c", "f", "compileGraffitiObjectSchema", "ajv", "schema", "error", "o", "maskGraffitiObject", "channels", "session", "channel", "isActorAllowedGraffitiObject", "GraffitiSynchronize", "r", "Ajv", "applyPatch", "graffiti", "options", "matchObject", "channels", "schema", "session", "seenUrls", "Repeater", "push", "stop", "validate", "compileGraffitiObjectSchema", "callback", "oldObjectRaw", "newObjectRaw", "objectRaw", "isActorAllowedGraffitiObject", "object", "maskGraffitiObject", "args", "channel", "objectUrl", "url", "unpackObjectUrl", "oldObject", "newObject", "waitForListeners", "resolve", "partialObject", "prop", "applyGraffitiPatch", "iterator", "this_", "result", "continue_", "cursor", "wrapped"]
7
7
  }
package/dist/cjs/index.js CHANGED
@@ -88,7 +88,9 @@ class GraffitiSynchronize extends import_api.Graffiti {
88
88
  push(objectRaw);
89
89
  }
90
90
  } else if (objectRaw && matchObject(objectRaw.object) && (this.options.omniscient || (0, import_utilities.isActorAllowedGraffitiObject)(objectRaw.object, session))) {
91
- const object = { ...objectRaw.object };
91
+ const object = JSON.parse(
92
+ JSON.stringify(objectRaw.object)
93
+ );
92
94
  if (!this.options.omniscient) {
93
95
  (0, import_utilities.maskGraffitiObject)(object, channels, session);
94
96
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/index.ts"],
4
- "sourcesContent": ["import type Ajv from \"ajv\";\nimport { Graffiti } from \"@graffiti-garden/api\";\nimport type {\n GraffitiSession,\n JSONSchema,\n GraffitiObjectStream,\n GraffitiObjectStreamContinueEntry,\n GraffitiObjectStreamContinue,\n} from \"@graffiti-garden/api\";\nimport type { GraffitiObjectBase } from \"@graffiti-garden/api\";\nimport { Repeater } from \"@repeaterjs/repeater\";\nimport type { applyPatch } from \"fast-json-patch\";\nimport {\n applyGraffitiPatch,\n compileGraffitiObjectSchema,\n isActorAllowedGraffitiObject,\n maskGraffitiObject,\n unpackObjectUrl,\n} from \"@graffiti-garden/implementation-local/utilities\";\nexport type * from \"@graffiti-garden/api\";\n\nexport type GraffitiSynchronizeCallback = (\n oldObject: GraffitiObjectStreamContinueEntry<{}>,\n newObject?: GraffitiObjectStreamContinueEntry<{}>,\n) => void;\n\nexport interface GraffitiSynchronizeOptions {\n /**\n * Allows synchronize to listen to all objects, not just those\n * that the session is allowed to see. This is useful to get a\n * global view of all Graffiti objects passsing through the system,\n * for example to build a client-side cache. Additional mechanisms\n * should be in place to ensure that users do not see objects or\n * properties they are not allowed to see.\n *\n * Default: `false`\n */\n omniscient?: boolean;\n}\n\n/**\n * Wraps the [Graffiti API](https://api.graffiti.garden/classes/Graffiti.html)\n * so that changes made or received in one part of an application\n * are automatically routed to other parts of the application.\n * This is an important tool for building responsive\n * and consistent user interfaces, and is built upon to make\n * the [Graffiti Vue Plugin](https://vue.graffiti.garden/variables/GraffitiPlugin.html)\n * and possibly other front-end libraries in the future.\n *\n * Specifically, it provides the following *synchronize*\n * methods for each of the following API methods:\n *\n * | API Method | Synchronize Method |\n * |------------|--------------------|\n * | {@link get} | {@link synchronizeGet} |\n * | {@link discover} | {@link synchronizeDiscover} |\n * | {@link recoverOrphans} | {@link synchronizeRecoverOrphans} |\n *\n * Whenever a change is made via {@link put}, {@link patch}, and {@link delete} or\n * received from {@link get}, {@link discover}, and {@link recoverOrphans},\n * those changes are forwarded to the appropriate synchronize method.\n * Each synchronize method returns an iterator that streams these changes\n * continually until the user calls `return` on the iterator or `break`s out of the loop,\n * allowing for live updates without additional polling.\n *\n * Example 1: Suppose a user publishes a post using {@link put}. If the feed\n * displaying that user's posts is using {@link synchronizeDiscover} to listen for changes,\n * then the user's new post will instantly appear in their feed, giving the UI a\n * responsive feel.\n *\n * Example 2: Suppose one of a user's friends changes their name. As soon as the\n * user's application receives one notice of that change (using {@link get}\n * or {@link discover}), then {@link synchronizeDiscover} listeners can be used to update\n * all instance's of that friend's name in the user's application instantly,\n * providing a consistent user experience.\n *\n * @groupDescription Synchronize Methods\n * This group contains methods that listen for changes made via\n * {@link put}, {@link patch}, and {@link delete} or fetched from\n * {@link get}, {@link discover}, and {@link recoverOrphans} and then\n * streams appropriate changes to provide a responsive and consistent user experience.\n */\nexport class GraffitiSynchronize extends Graffiti {\n protected ajv_: Promise<Ajv> | undefined;\n protected applyPatch_: Promise<typeof applyPatch> | undefined;\n protected readonly graffiti: Graffiti;\n protected readonly callbacks = new Set<GraffitiSynchronizeCallback>();\n protected readonly options: GraffitiSynchronizeOptions;\n\n channelStats: Graffiti[\"channelStats\"];\n login: Graffiti[\"login\"];\n logout: Graffiti[\"logout\"];\n sessionEvents: Graffiti[\"sessionEvents\"];\n\n get ajv() {\n if (!this.ajv_) {\n this.ajv_ = (async () => {\n const { default: Ajv } = await import(\"ajv\");\n return new Ajv({ strict: false });\n })();\n }\n return this.ajv_;\n }\n\n get applyPatch() {\n if (!this.applyPatch_) {\n this.applyPatch_ = (async () => {\n const { applyPatch } = await import(\"fast-json-patch\");\n return applyPatch;\n })();\n }\n return this.applyPatch_;\n }\n\n /**\n * Wraps a Graffiti API instance to provide the synchronize methods.\n * The GraffitiSyncrhonize class rather than the Graffiti class\n * must be used for all functions for the synchronize methods to work.\n */\n constructor(\n /**\n * The [Graffiti API](https://api.graffiti.garden/classes/Graffiti.html)\n * instance to wrap.\n */\n graffiti: Graffiti,\n options?: GraffitiSynchronizeOptions,\n ) {\n super();\n this.options = options ?? {};\n this.graffiti = graffiti;\n this.channelStats = graffiti.channelStats.bind(graffiti);\n this.login = graffiti.login.bind(graffiti);\n this.logout = graffiti.logout.bind(graffiti);\n this.sessionEvents = graffiti.sessionEvents;\n }\n\n protected synchronize<Schema extends JSONSchema>(\n matchObject: (object: GraffitiObjectBase) => boolean,\n channels: string[],\n schema: Schema,\n session?: GraffitiSession | null,\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\n const seenUrls = new Set<string>();\n\n const repeater = new Repeater<GraffitiObjectStreamContinueEntry<Schema>>(\n async (push, stop) => {\n const validate = compileGraffitiObjectSchema(await this.ajv, schema);\n const callback: GraffitiSynchronizeCallback = (\n oldObjectRaw,\n newObjectRaw,\n ) => {\n for (const objectRaw of [newObjectRaw, oldObjectRaw]) {\n if (objectRaw?.tombstone) {\n if (seenUrls.has(objectRaw.object.url)) {\n push(objectRaw);\n }\n } else if (\n objectRaw &&\n matchObject(objectRaw.object) &&\n (this.options.omniscient ||\n isActorAllowedGraffitiObject(objectRaw.object, session))\n ) {\n const object = { ...objectRaw.object };\n if (!this.options.omniscient) {\n maskGraffitiObject(object, channels, session);\n }\n if (validate(object)) {\n push({ object });\n seenUrls.add(object.url);\n break;\n }\n }\n }\n };\n\n this.callbacks.add(callback);\n await stop;\n this.callbacks.delete(callback);\n },\n );\n\n return repeater;\n }\n\n /**\n * This method has the same signature as {@link discover} but listens for\n * changes made via {@link put}, {@link patch}, and {@link delete} or\n * fetched from {@link get}, {@link discover}, and {@link recoverOrphans}\n * and then streams appropriate changes to provide a responsive and\n * consistent user experience.\n *\n * Unlike {@link discover}, this method continuously listens for changes\n * and will not terminate unless the user calls the `return` method on the iterator\n * or `break`s out of the loop.\n *\n * @group Synchronize Methods\n */\n synchronizeDiscover<Schema extends JSONSchema>(\n ...args: Parameters<typeof Graffiti.prototype.discover<Schema>>\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\n const [channels, schema, session] = args;\n function matchObject(object: GraffitiObjectBase) {\n return object.channels.some((channel) => channels.includes(channel));\n }\n return this.synchronize<Schema>(matchObject, channels, schema, session);\n }\n\n /**\n * This method has the same signature as {@link get} but\n * listens for changes made via {@link put}, {@link patch}, and {@link delete} or\n * fetched from {@link get}, {@link discover}, and {@link recoverOrphans} and then\n * streams appropriate changes to provide a responsive and consistent user experience.\n *\n * Unlike {@link get}, which returns a single result, this method continuously\n * listens for changes which are output as an asynchronous stream, similar\n * to {@link discover}.\n *\n * @group Synchronize Methods\n */\n synchronizeGet<Schema extends JSONSchema>(\n ...args: Parameters<typeof Graffiti.prototype.get<Schema>>\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\n const [objectUrl, schema, session] = args;\n const url = unpackObjectUrl(objectUrl);\n function matchObject(object: GraffitiObjectBase) {\n return object.url === url;\n }\n return this.synchronize<Schema>(matchObject, [], schema, session);\n }\n\n /**\n * This method has the same signature as {@link recoverOrphans} but\n * listens for changes made via\n * {@link put}, {@link patch}, and {@link delete} or fetched from\n * {@link get}, {@link discover}, and {@link recoverOrphans} and then\n * streams appropriate changes to provide a responsive and consistent user experience.\n *\n * Unlike {@link recoverOrphans}, this method continuously listens for changes\n * and will not terminate unless the user calls the `return` method on the iterator\n * or `break`s out of the loop.\n *\n * @group Synchronize Methods\n */\n synchronizeRecoverOrphans<Schema extends JSONSchema>(\n ...args: Parameters<typeof Graffiti.prototype.recoverOrphans<Schema>>\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\n const [schema, session] = args;\n function matchObject(object: GraffitiObjectBase) {\n return object.actor === session.actor && object.channels.length === 0;\n }\n return this.synchronize<Schema>(matchObject, [], schema, session);\n }\n\n /**\n * Streams changes made to *any* object in *any* channel\n * and made by *any* user. You may want to use it in conjuction with\n * {@link GraffitiSynchronizeOptions.omniscient} to get a global view\n * of all Graffiti objects passing through the system. This is useful\n * for building a client-side cache, for example.\n *\n * Be careful using this method. Without additional filters it can\n * expose the user to content out of context.\n */\n synchronizeAll<Schema extends JSONSchema>(\n schema: Schema,\n session?: GraffitiSession | null,\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\n return this.synchronize<Schema>(() => true, [], schema, session);\n }\n\n protected async synchronizeDispatch(\n oldObject: GraffitiObjectStreamContinueEntry<{}>,\n newObject?: GraffitiObjectStreamContinueEntry<{}>,\n waitForListeners = false,\n ) {\n for (const callback of this.callbacks) {\n callback(oldObject, newObject);\n }\n if (waitForListeners) {\n // Wait for the listeners to receive\n // their objects, before returning the operation\n // that triggered them.\n //\n // This is important for mutators (put, patch, delete)\n // to ensure the application state has been updated\n // everywhere before returning, giving consistent\n // feedback to the user that the operation has completed.\n //\n // The opposite is true for accessors (get, discover, recoverOrphans),\n // where it is a weird user experience to call `get`\n // in one place and have the application update\n // somewhere else first. It is also less efficient.\n //\n // The hack is simply to await one \"macro task cycle\".\n // We need to wait for this cycle rather than using\n // `await push` in the callback, because it turns out\n // that `await push` won't resolve until the following\n // .next() call of the iterator, so if only\n // one .next() is called, this dispatch will hang.\n await new Promise((resolve) => setTimeout(resolve, 0));\n }\n }\n\n get: Graffiti[\"get\"] = async (...args) => {\n const object = await this.graffiti.get(...args);\n this.synchronizeDispatch({ object });\n return object;\n };\n\n put: Graffiti[\"put\"] = async (...args) => {\n const oldObject = await this.graffiti.put<{}>(...args);\n const partialObject = args[0];\n const newObject: GraffitiObjectBase = {\n ...oldObject,\n value: partialObject.value,\n channels: partialObject.channels,\n allowed: partialObject.allowed,\n };\n await this.synchronizeDispatch(\n {\n tombstone: true,\n object: oldObject,\n },\n {\n object: newObject,\n },\n true,\n );\n return oldObject;\n };\n\n patch: Graffiti[\"patch\"] = async (...args) => {\n const oldObject = await this.graffiti.patch(...args);\n const newObject: GraffitiObjectBase = { ...oldObject };\n for (const prop of [\"value\", \"channels\", \"allowed\"] as const) {\n applyGraffitiPatch(await this.applyPatch, prop, args[0], newObject);\n }\n await this.synchronizeDispatch(\n {\n tombstone: true,\n object: oldObject,\n },\n {\n object: newObject,\n },\n true,\n );\n return oldObject;\n };\n\n delete: Graffiti[\"delete\"] = async (...args) => {\n const oldObject = await this.graffiti.delete(...args);\n await this.synchronizeDispatch(\n {\n tombstone: true,\n object: oldObject,\n },\n undefined,\n true,\n );\n return oldObject;\n };\n\n protected objectStreamContinue<Schema extends JSONSchema>(\n iterator: GraffitiObjectStreamContinue<Schema>,\n ): GraffitiObjectStreamContinue<Schema> {\n const this_ = this;\n return (async function* () {\n while (true) {\n const result = await iterator.next();\n if (result.done) {\n const { continue: continue_, cursor } = result.value;\n return {\n continue: () => this_.objectStreamContinue<Schema>(continue_()),\n cursor,\n };\n }\n if (!result.value.error) {\n this_.synchronizeDispatch(\n result.value as GraffitiObjectStreamContinueEntry<{}>,\n );\n }\n yield result.value;\n }\n })();\n }\n\n protected objectStream<Schema extends JSONSchema>(\n iterator: GraffitiObjectStream<Schema>,\n ): GraffitiObjectStream<Schema> {\n const wrapped = this.objectStreamContinue<Schema>(iterator);\n return (async function* () {\n // Filter out the tombstones for type safety\n while (true) {\n const result = await wrapped.next();\n if (result.done) return result.value;\n if (result.value.error || !result.value.tombstone) yield result.value;\n }\n })();\n }\n\n discover: Graffiti[\"discover\"] = (...args) => {\n const iterator = this.graffiti.discover(...args);\n return this.objectStream<(typeof args)[1]>(iterator);\n };\n\n recoverOrphans: Graffiti[\"recoverOrphans\"] = (...args) => {\n const iterator = this.graffiti.recoverOrphans(...args);\n return this.objectStream<(typeof args)[0]>(iterator);\n };\n\n continueObjectStream: Graffiti[\"continueObjectStream\"] = (...args) => {\n // TODO!!\n return this.graffiti.continueObjectStream(...args);\n };\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type Ajv from \"ajv\";\nimport { Graffiti } from \"@graffiti-garden/api\";\nimport type {\n GraffitiSession,\n JSONSchema,\n GraffitiObjectStream,\n GraffitiObjectStreamContinueEntry,\n GraffitiObjectStreamContinue,\n GraffitiObject,\n} from \"@graffiti-garden/api\";\nimport type { GraffitiObjectBase } from \"@graffiti-garden/api\";\nimport { Repeater } from \"@repeaterjs/repeater\";\nimport type { applyPatch } from \"fast-json-patch\";\nimport {\n applyGraffitiPatch,\n compileGraffitiObjectSchema,\n isActorAllowedGraffitiObject,\n maskGraffitiObject,\n unpackObjectUrl,\n} from \"@graffiti-garden/implementation-local/utilities\";\nexport type * from \"@graffiti-garden/api\";\n\nexport type GraffitiSynchronizeCallback = (\n oldObject: GraffitiObjectStreamContinueEntry<{}>,\n newObject?: GraffitiObjectStreamContinueEntry<{}>,\n) => void;\n\nexport interface GraffitiSynchronizeOptions {\n /**\n * Allows synchronize to listen to all objects, not just those\n * that the session is allowed to see. This is useful to get a\n * global view of all Graffiti objects passsing through the system,\n * for example to build a client-side cache. Additional mechanisms\n * should be in place to ensure that users do not see objects or\n * properties they are not allowed to see.\n *\n * Default: `false`\n */\n omniscient?: boolean;\n}\n\n/**\n * Wraps the [Graffiti API](https://api.graffiti.garden/classes/Graffiti.html)\n * so that changes made or received in one part of an application\n * are automatically routed to other parts of the application.\n * This is an important tool for building responsive\n * and consistent user interfaces, and is built upon to make\n * the [Graffiti Vue Plugin](https://vue.graffiti.garden/variables/GraffitiPlugin.html)\n * and possibly other front-end libraries in the future.\n *\n * Specifically, it provides the following *synchronize*\n * methods for each of the following API methods:\n *\n * | API Method | Synchronize Method |\n * |------------|--------------------|\n * | {@link get} | {@link synchronizeGet} |\n * | {@link discover} | {@link synchronizeDiscover} |\n * | {@link recoverOrphans} | {@link synchronizeRecoverOrphans} |\n *\n * Whenever a change is made via {@link put}, {@link patch}, and {@link delete} or\n * received from {@link get}, {@link discover}, and {@link recoverOrphans},\n * those changes are forwarded to the appropriate synchronize method.\n * Each synchronize method returns an iterator that streams these changes\n * continually until the user calls `return` on the iterator or `break`s out of the loop,\n * allowing for live updates without additional polling.\n *\n * Example 1: Suppose a user publishes a post using {@link put}. If the feed\n * displaying that user's posts is using {@link synchronizeDiscover} to listen for changes,\n * then the user's new post will instantly appear in their feed, giving the UI a\n * responsive feel.\n *\n * Example 2: Suppose one of a user's friends changes their name. As soon as the\n * user's application receives one notice of that change (using {@link get}\n * or {@link discover}), then {@link synchronizeDiscover} listeners can be used to update\n * all instance's of that friend's name in the user's application instantly,\n * providing a consistent user experience.\n *\n * @groupDescription Synchronize Methods\n * This group contains methods that listen for changes made via\n * {@link put}, {@link patch}, and {@link delete} or fetched from\n * {@link get}, {@link discover}, and {@link recoverOrphans} and then\n * streams appropriate changes to provide a responsive and consistent user experience.\n */\nexport class GraffitiSynchronize extends Graffiti {\n protected ajv_: Promise<Ajv> | undefined;\n protected applyPatch_: Promise<typeof applyPatch> | undefined;\n protected readonly graffiti: Graffiti;\n protected readonly callbacks = new Set<GraffitiSynchronizeCallback>();\n protected readonly options: GraffitiSynchronizeOptions;\n\n channelStats: Graffiti[\"channelStats\"];\n login: Graffiti[\"login\"];\n logout: Graffiti[\"logout\"];\n sessionEvents: Graffiti[\"sessionEvents\"];\n\n get ajv() {\n if (!this.ajv_) {\n this.ajv_ = (async () => {\n const { default: Ajv } = await import(\"ajv\");\n return new Ajv({ strict: false });\n })();\n }\n return this.ajv_;\n }\n\n get applyPatch() {\n if (!this.applyPatch_) {\n this.applyPatch_ = (async () => {\n const { applyPatch } = await import(\"fast-json-patch\");\n return applyPatch;\n })();\n }\n return this.applyPatch_;\n }\n\n /**\n * Wraps a Graffiti API instance to provide the synchronize methods.\n * The GraffitiSyncrhonize class rather than the Graffiti class\n * must be used for all functions for the synchronize methods to work.\n */\n constructor(\n /**\n * The [Graffiti API](https://api.graffiti.garden/classes/Graffiti.html)\n * instance to wrap.\n */\n graffiti: Graffiti,\n options?: GraffitiSynchronizeOptions,\n ) {\n super();\n this.options = options ?? {};\n this.graffiti = graffiti;\n this.channelStats = graffiti.channelStats.bind(graffiti);\n this.login = graffiti.login.bind(graffiti);\n this.logout = graffiti.logout.bind(graffiti);\n this.sessionEvents = graffiti.sessionEvents;\n }\n\n protected synchronize<Schema extends JSONSchema>(\n matchObject: (object: GraffitiObjectBase) => boolean,\n channels: string[],\n schema: Schema,\n session?: GraffitiSession | null,\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\n const seenUrls = new Set<string>();\n\n const repeater = new Repeater<GraffitiObjectStreamContinueEntry<Schema>>(\n async (push, stop) => {\n const validate = compileGraffitiObjectSchema(await this.ajv, schema);\n const callback: GraffitiSynchronizeCallback = (\n oldObjectRaw,\n newObjectRaw,\n ) => {\n for (const objectRaw of [newObjectRaw, oldObjectRaw]) {\n if (objectRaw?.tombstone) {\n if (seenUrls.has(objectRaw.object.url)) {\n push(objectRaw);\n }\n } else if (\n objectRaw &&\n matchObject(objectRaw.object) &&\n (this.options.omniscient ||\n isActorAllowedGraffitiObject(objectRaw.object, session))\n ) {\n // Deep clone the object to prevent mutation\n const object = JSON.parse(\n JSON.stringify(objectRaw.object),\n ) as GraffitiObject<{}>;\n if (!this.options.omniscient) {\n maskGraffitiObject(object, channels, session);\n }\n if (validate(object)) {\n push({ object });\n seenUrls.add(object.url);\n break;\n }\n }\n }\n };\n\n this.callbacks.add(callback);\n await stop;\n this.callbacks.delete(callback);\n },\n );\n\n return repeater;\n }\n\n /**\n * This method has the same signature as {@link discover} but listens for\n * changes made via {@link put}, {@link patch}, and {@link delete} or\n * fetched from {@link get}, {@link discover}, and {@link recoverOrphans}\n * and then streams appropriate changes to provide a responsive and\n * consistent user experience.\n *\n * Unlike {@link discover}, this method continuously listens for changes\n * and will not terminate unless the user calls the `return` method on the iterator\n * or `break`s out of the loop.\n *\n * @group Synchronize Methods\n */\n synchronizeDiscover<Schema extends JSONSchema>(\n ...args: Parameters<typeof Graffiti.prototype.discover<Schema>>\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\n const [channels, schema, session] = args;\n function matchObject(object: GraffitiObjectBase) {\n return object.channels.some((channel) => channels.includes(channel));\n }\n return this.synchronize<Schema>(matchObject, channels, schema, session);\n }\n\n /**\n * This method has the same signature as {@link get} but\n * listens for changes made via {@link put}, {@link patch}, and {@link delete} or\n * fetched from {@link get}, {@link discover}, and {@link recoverOrphans} and then\n * streams appropriate changes to provide a responsive and consistent user experience.\n *\n * Unlike {@link get}, which returns a single result, this method continuously\n * listens for changes which are output as an asynchronous stream, similar\n * to {@link discover}.\n *\n * @group Synchronize Methods\n */\n synchronizeGet<Schema extends JSONSchema>(\n ...args: Parameters<typeof Graffiti.prototype.get<Schema>>\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\n const [objectUrl, schema, session] = args;\n const url = unpackObjectUrl(objectUrl);\n function matchObject(object: GraffitiObjectBase) {\n return object.url === url;\n }\n return this.synchronize<Schema>(matchObject, [], schema, session);\n }\n\n /**\n * This method has the same signature as {@link recoverOrphans} but\n * listens for changes made via\n * {@link put}, {@link patch}, and {@link delete} or fetched from\n * {@link get}, {@link discover}, and {@link recoverOrphans} and then\n * streams appropriate changes to provide a responsive and consistent user experience.\n *\n * Unlike {@link recoverOrphans}, this method continuously listens for changes\n * and will not terminate unless the user calls the `return` method on the iterator\n * or `break`s out of the loop.\n *\n * @group Synchronize Methods\n */\n synchronizeRecoverOrphans<Schema extends JSONSchema>(\n ...args: Parameters<typeof Graffiti.prototype.recoverOrphans<Schema>>\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\n const [schema, session] = args;\n function matchObject(object: GraffitiObjectBase) {\n return object.actor === session.actor && object.channels.length === 0;\n }\n return this.synchronize<Schema>(matchObject, [], schema, session);\n }\n\n /**\n * Streams changes made to *any* object in *any* channel\n * and made by *any* user. You may want to use it in conjuction with\n * {@link GraffitiSynchronizeOptions.omniscient} to get a global view\n * of all Graffiti objects passing through the system. This is useful\n * for building a client-side cache, for example.\n *\n * Be careful using this method. Without additional filters it can\n * expose the user to content out of context.\n */\n synchronizeAll<Schema extends JSONSchema>(\n schema: Schema,\n session?: GraffitiSession | null,\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\n return this.synchronize<Schema>(() => true, [], schema, session);\n }\n\n protected async synchronizeDispatch(\n oldObject: GraffitiObjectStreamContinueEntry<{}>,\n newObject?: GraffitiObjectStreamContinueEntry<{}>,\n waitForListeners = false,\n ) {\n for (const callback of this.callbacks) {\n callback(oldObject, newObject);\n }\n if (waitForListeners) {\n // Wait for the listeners to receive\n // their objects, before returning the operation\n // that triggered them.\n //\n // This is important for mutators (put, patch, delete)\n // to ensure the application state has been updated\n // everywhere before returning, giving consistent\n // feedback to the user that the operation has completed.\n //\n // The opposite is true for accessors (get, discover, recoverOrphans),\n // where it is a weird user experience to call `get`\n // in one place and have the application update\n // somewhere else first. It is also less efficient.\n //\n // The hack is simply to await one \"macro task cycle\".\n // We need to wait for this cycle rather than using\n // `await push` in the callback, because it turns out\n // that `await push` won't resolve until the following\n // .next() call of the iterator, so if only\n // one .next() is called, this dispatch will hang.\n await new Promise((resolve) => setTimeout(resolve, 0));\n }\n }\n\n get: Graffiti[\"get\"] = async (...args) => {\n const object = await this.graffiti.get(...args);\n this.synchronizeDispatch({ object });\n return object;\n };\n\n put: Graffiti[\"put\"] = async (...args) => {\n const oldObject = await this.graffiti.put<{}>(...args);\n const partialObject = args[0];\n const newObject: GraffitiObjectBase = {\n ...oldObject,\n value: partialObject.value,\n channels: partialObject.channels,\n allowed: partialObject.allowed,\n };\n await this.synchronizeDispatch(\n {\n tombstone: true,\n object: oldObject,\n },\n {\n object: newObject,\n },\n true,\n );\n return oldObject;\n };\n\n patch: Graffiti[\"patch\"] = async (...args) => {\n const oldObject = await this.graffiti.patch(...args);\n const newObject: GraffitiObjectBase = { ...oldObject };\n for (const prop of [\"value\", \"channels\", \"allowed\"] as const) {\n applyGraffitiPatch(await this.applyPatch, prop, args[0], newObject);\n }\n await this.synchronizeDispatch(\n {\n tombstone: true,\n object: oldObject,\n },\n {\n object: newObject,\n },\n true,\n );\n return oldObject;\n };\n\n delete: Graffiti[\"delete\"] = async (...args) => {\n const oldObject = await this.graffiti.delete(...args);\n await this.synchronizeDispatch(\n {\n tombstone: true,\n object: oldObject,\n },\n undefined,\n true,\n );\n return oldObject;\n };\n\n protected objectStreamContinue<Schema extends JSONSchema>(\n iterator: GraffitiObjectStreamContinue<Schema>,\n ): GraffitiObjectStreamContinue<Schema> {\n const this_ = this;\n return (async function* () {\n while (true) {\n const result = await iterator.next();\n if (result.done) {\n const { continue: continue_, cursor } = result.value;\n return {\n continue: () => this_.objectStreamContinue<Schema>(continue_()),\n cursor,\n };\n }\n if (!result.value.error) {\n this_.synchronizeDispatch(\n result.value as GraffitiObjectStreamContinueEntry<{}>,\n );\n }\n yield result.value;\n }\n })();\n }\n\n protected objectStream<Schema extends JSONSchema>(\n iterator: GraffitiObjectStream<Schema>,\n ): GraffitiObjectStream<Schema> {\n const wrapped = this.objectStreamContinue<Schema>(iterator);\n return (async function* () {\n // Filter out the tombstones for type safety\n while (true) {\n const result = await wrapped.next();\n if (result.done) return result.value;\n if (result.value.error || !result.value.tombstone) yield result.value;\n }\n })();\n }\n\n discover: Graffiti[\"discover\"] = (...args) => {\n const iterator = this.graffiti.discover(...args);\n return this.objectStream<(typeof args)[1]>(iterator);\n };\n\n recoverOrphans: Graffiti[\"recoverOrphans\"] = (...args) => {\n const iterator = this.graffiti.recoverOrphans(...args);\n return this.objectStream<(typeof args)[0]>(iterator);\n };\n\n continueObjectStream: Graffiti[\"continueObjectStream\"] = (...args) => {\n // TODO!!\n return this.graffiti.continueObjectStream(...args);\n };\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,iBAAyB;AAUzB,sBAAyB;AAEzB,uBAMO;AAgEA,MAAM,4BAA4B,oBAAS;AAAA,EACtC;AAAA,EACA;AAAA,EACS;AAAA,EACA,YAAY,oBAAI,IAAiC;AAAA,EACjD;AAAA,EAEnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA,IAAI,MAAM;AACR,QAAI,CAAC,KAAK,MAAM;AACd,WAAK,QAAQ,YAAY;AACvB,cAAM,EAAE,SAAS,IAAI,IAAI,MAAM,OAAO,KAAK;AAC3C,eAAO,IAAI,IAAI,EAAE,QAAQ,MAAM,CAAC;AAAA,MAClC,GAAG;AAAA,IACL;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,aAAa;AACf,QAAI,CAAC,KAAK,aAAa;AACrB,WAAK,eAAe,YAAY;AAC9B,cAAM,EAAE,WAAW,IAAI,MAAM,OAAO,iBAAiB;AACrD,eAAO;AAAA,MACT,GAAG;AAAA,IACL;AACA,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,YAKE,UACA,SACA;AACA,UAAM;AACN,SAAK,UAAU,WAAW,CAAC;AAC3B,SAAK,WAAW;AAChB,SAAK,eAAe,SAAS,aAAa,KAAK,QAAQ;AACvD,SAAK,QAAQ,SAAS,MAAM,KAAK,QAAQ;AACzC,SAAK,SAAS,SAAS,OAAO,KAAK,QAAQ;AAC3C,SAAK,gBAAgB,SAAS;AAAA,EAChC;AAAA,EAEU,YACR,aACA,UACA,QACA,SAC2D;AAC3D,UAAM,WAAW,oBAAI,IAAY;AAEjC,UAAM,WAAW,IAAI;AAAA,MACnB,OAAO,MAAM,SAAS;AACpB,cAAM,eAAW,8CAA4B,MAAM,KAAK,KAAK,MAAM;AACnE,cAAM,WAAwC,CAC5C,cACA,iBACG;AACH,qBAAW,aAAa,CAAC,cAAc,YAAY,GAAG;AACpD,gBAAI,WAAW,WAAW;AACxB,kBAAI,SAAS,IAAI,UAAU,OAAO,GAAG,GAAG;AACtC,qBAAK,SAAS;AAAA,cAChB;AAAA,YACF,WACE,aACA,YAAY,UAAU,MAAM,MAC3B,KAAK,QAAQ,kBACZ,+CAA6B,UAAU,QAAQ,OAAO,IACxD;AAEA,oBAAM,SAAS,KAAK;AAAA,gBAClB,KAAK,UAAU,UAAU,MAAM;AAAA,cACjC;AACA,kBAAI,CAAC,KAAK,QAAQ,YAAY;AAC5B,yDAAmB,QAAQ,UAAU,OAAO;AAAA,cAC9C;AACA,kBAAI,SAAS,MAAM,GAAG;AACpB,qBAAK,EAAE,OAAO,CAAC;AACf,yBAAS,IAAI,OAAO,GAAG;AACvB;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAEA,aAAK,UAAU,IAAI,QAAQ;AAC3B,cAAM;AACN,aAAK,UAAU,OAAO,QAAQ;AAAA,MAChC;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,uBACK,MACwD;AAC3D,UAAM,CAAC,UAAU,QAAQ,OAAO,IAAI;AACpC,aAAS,YAAY,QAA4B;AAC/C,aAAO,OAAO,SAAS,KAAK,CAAC,YAAY,SAAS,SAAS,OAAO,CAAC;AAAA,IACrE;AACA,WAAO,KAAK,YAAoB,aAAa,UAAU,QAAQ,OAAO;AAAA,EACxE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,kBACK,MACwD;AAC3D,UAAM,CAAC,WAAW,QAAQ,OAAO,IAAI;AACrC,UAAM,UAAM,kCAAgB,SAAS;AACrC,aAAS,YAAY,QAA4B;AAC/C,aAAO,OAAO,QAAQ;AAAA,IACxB;AACA,WAAO,KAAK,YAAoB,aAAa,CAAC,GAAG,QAAQ,OAAO;AAAA,EAClE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,6BACK,MACwD;AAC3D,UAAM,CAAC,QAAQ,OAAO,IAAI;AAC1B,aAAS,YAAY,QAA4B;AAC/C,aAAO,OAAO,UAAU,QAAQ,SAAS,OAAO,SAAS,WAAW;AAAA,IACtE;AACA,WAAO,KAAK,YAAoB,aAAa,CAAC,GAAG,QAAQ,OAAO;AAAA,EAClE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,eACE,QACA,SAC2D;AAC3D,WAAO,KAAK,YAAoB,MAAM,MAAM,CAAC,GAAG,QAAQ,OAAO;AAAA,EACjE;AAAA,EAEA,MAAgB,oBACd,WACA,WACA,mBAAmB,OACnB;AACA,eAAW,YAAY,KAAK,WAAW;AACrC,eAAS,WAAW,SAAS;AAAA,IAC/B;AACA,QAAI,kBAAkB;AAqBpB,YAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,CAAC,CAAC;AAAA,IACvD;AAAA,EACF;AAAA,EAEA,MAAuB,UAAU,SAAS;AACxC,UAAM,SAAS,MAAM,KAAK,SAAS,IAAI,GAAG,IAAI;AAC9C,SAAK,oBAAoB,EAAE,OAAO,CAAC;AACnC,WAAO;AAAA,EACT;AAAA,EAEA,MAAuB,UAAU,SAAS;AACxC,UAAM,YAAY,MAAM,KAAK,SAAS,IAAQ,GAAG,IAAI;AACrD,UAAM,gBAAgB,KAAK,CAAC;AAC5B,UAAM,YAAgC;AAAA,MACpC,GAAG;AAAA,MACH,OAAO,cAAc;AAAA,MACrB,UAAU,cAAc;AAAA,MACxB,SAAS,cAAc;AAAA,IACzB;AACA,UAAM,KAAK;AAAA,MACT;AAAA,QACE,WAAW;AAAA,QACX,QAAQ;AAAA,MACV;AAAA,MACA;AAAA,QACE,QAAQ;AAAA,MACV;AAAA,MACA;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,QAA2B,UAAU,SAAS;AAC5C,UAAM,YAAY,MAAM,KAAK,SAAS,MAAM,GAAG,IAAI;AACnD,UAAM,YAAgC,EAAE,GAAG,UAAU;AACrD,eAAW,QAAQ,CAAC,SAAS,YAAY,SAAS,GAAY;AAC5D,+CAAmB,MAAM,KAAK,YAAY,MAAM,KAAK,CAAC,GAAG,SAAS;AAAA,IACpE;AACA,UAAM,KAAK;AAAA,MACT;AAAA,QACE,WAAW;AAAA,QACX,QAAQ;AAAA,MACV;AAAA,MACA;AAAA,QACE,QAAQ;AAAA,MACV;AAAA,MACA;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,SAA6B,UAAU,SAAS;AAC9C,UAAM,YAAY,MAAM,KAAK,SAAS,OAAO,GAAG,IAAI;AACpD,UAAM,KAAK;AAAA,MACT;AAAA,QACE,WAAW;AAAA,QACX,QAAQ;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEU,qBACR,UACsC;AACtC,UAAM,QAAQ;AACd,WAAQ,mBAAmB;AACzB,aAAO,MAAM;AACX,cAAM,SAAS,MAAM,SAAS,KAAK;AACnC,YAAI,OAAO,MAAM;AACf,gBAAM,EAAE,UAAU,WAAW,OAAO,IAAI,OAAO;AAC/C,iBAAO;AAAA,YACL,UAAU,MAAM,MAAM,qBAA6B,UAAU,CAAC;AAAA,YAC9D;AAAA,UACF;AAAA,QACF;AACA,YAAI,CAAC,OAAO,MAAM,OAAO;AACvB,gBAAM;AAAA,YACJ,OAAO;AAAA,UACT;AAAA,QACF;AACA,cAAM,OAAO;AAAA,MACf;AAAA,IACF,EAAG;AAAA,EACL;AAAA,EAEU,aACR,UAC8B;AAC9B,UAAM,UAAU,KAAK,qBAA6B,QAAQ;AAC1D,WAAQ,mBAAmB;AAEzB,aAAO,MAAM;AACX,cAAM,SAAS,MAAM,QAAQ,KAAK;AAClC,YAAI,OAAO,KAAM,QAAO,OAAO;AAC/B,YAAI,OAAO,MAAM,SAAS,CAAC,OAAO,MAAM,UAAW,OAAM,OAAO;AAAA,MAClE;AAAA,IACF,EAAG;AAAA,EACL;AAAA,EAEA,WAAiC,IAAI,SAAS;AAC5C,UAAM,WAAW,KAAK,SAAS,SAAS,GAAG,IAAI;AAC/C,WAAO,KAAK,aAA+B,QAAQ;AAAA,EACrD;AAAA,EAEA,iBAA6C,IAAI,SAAS;AACxD,UAAM,WAAW,KAAK,SAAS,eAAe,GAAG,IAAI;AACrD,WAAO,KAAK,aAA+B,QAAQ;AAAA,EACrD;AAAA,EAEA,uBAAyD,IAAI,SAAS;AAEpE,WAAO,KAAK,SAAS,qBAAqB,GAAG,IAAI;AAAA,EACnD;AACF;",
6
6
  "names": []
7
7
  }
package/dist/esm/index.js CHANGED
@@ -61,7 +61,9 @@ class GraffitiSynchronize extends Graffiti {
61
61
  push(objectRaw);
62
62
  }
63
63
  } else if (objectRaw && matchObject(objectRaw.object) && (this.options.omniscient || isActorAllowedGraffitiObject(objectRaw.object, session))) {
64
- const object = { ...objectRaw.object };
64
+ const object = JSON.parse(
65
+ JSON.stringify(objectRaw.object)
66
+ );
65
67
  if (!this.options.omniscient) {
66
68
  maskGraffitiObject(object, channels, session);
67
69
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/index.ts"],
4
- "sourcesContent": ["import type Ajv from \"ajv\";\nimport { Graffiti } from \"@graffiti-garden/api\";\nimport type {\n GraffitiSession,\n JSONSchema,\n GraffitiObjectStream,\n GraffitiObjectStreamContinueEntry,\n GraffitiObjectStreamContinue,\n} from \"@graffiti-garden/api\";\nimport type { GraffitiObjectBase } from \"@graffiti-garden/api\";\nimport { Repeater } from \"@repeaterjs/repeater\";\nimport type { applyPatch } from \"fast-json-patch\";\nimport {\n applyGraffitiPatch,\n compileGraffitiObjectSchema,\n isActorAllowedGraffitiObject,\n maskGraffitiObject,\n unpackObjectUrl,\n} from \"@graffiti-garden/implementation-local/utilities\";\nexport type * from \"@graffiti-garden/api\";\n\nexport type GraffitiSynchronizeCallback = (\n oldObject: GraffitiObjectStreamContinueEntry<{}>,\n newObject?: GraffitiObjectStreamContinueEntry<{}>,\n) => void;\n\nexport interface GraffitiSynchronizeOptions {\n /**\n * Allows synchronize to listen to all objects, not just those\n * that the session is allowed to see. This is useful to get a\n * global view of all Graffiti objects passsing through the system,\n * for example to build a client-side cache. Additional mechanisms\n * should be in place to ensure that users do not see objects or\n * properties they are not allowed to see.\n *\n * Default: `false`\n */\n omniscient?: boolean;\n}\n\n/**\n * Wraps the [Graffiti API](https://api.graffiti.garden/classes/Graffiti.html)\n * so that changes made or received in one part of an application\n * are automatically routed to other parts of the application.\n * This is an important tool for building responsive\n * and consistent user interfaces, and is built upon to make\n * the [Graffiti Vue Plugin](https://vue.graffiti.garden/variables/GraffitiPlugin.html)\n * and possibly other front-end libraries in the future.\n *\n * Specifically, it provides the following *synchronize*\n * methods for each of the following API methods:\n *\n * | API Method | Synchronize Method |\n * |------------|--------------------|\n * | {@link get} | {@link synchronizeGet} |\n * | {@link discover} | {@link synchronizeDiscover} |\n * | {@link recoverOrphans} | {@link synchronizeRecoverOrphans} |\n *\n * Whenever a change is made via {@link put}, {@link patch}, and {@link delete} or\n * received from {@link get}, {@link discover}, and {@link recoverOrphans},\n * those changes are forwarded to the appropriate synchronize method.\n * Each synchronize method returns an iterator that streams these changes\n * continually until the user calls `return` on the iterator or `break`s out of the loop,\n * allowing for live updates without additional polling.\n *\n * Example 1: Suppose a user publishes a post using {@link put}. If the feed\n * displaying that user's posts is using {@link synchronizeDiscover} to listen for changes,\n * then the user's new post will instantly appear in their feed, giving the UI a\n * responsive feel.\n *\n * Example 2: Suppose one of a user's friends changes their name. As soon as the\n * user's application receives one notice of that change (using {@link get}\n * or {@link discover}), then {@link synchronizeDiscover} listeners can be used to update\n * all instance's of that friend's name in the user's application instantly,\n * providing a consistent user experience.\n *\n * @groupDescription Synchronize Methods\n * This group contains methods that listen for changes made via\n * {@link put}, {@link patch}, and {@link delete} or fetched from\n * {@link get}, {@link discover}, and {@link recoverOrphans} and then\n * streams appropriate changes to provide a responsive and consistent user experience.\n */\nexport class GraffitiSynchronize extends Graffiti {\n protected ajv_: Promise<Ajv> | undefined;\n protected applyPatch_: Promise<typeof applyPatch> | undefined;\n protected readonly graffiti: Graffiti;\n protected readonly callbacks = new Set<GraffitiSynchronizeCallback>();\n protected readonly options: GraffitiSynchronizeOptions;\n\n channelStats: Graffiti[\"channelStats\"];\n login: Graffiti[\"login\"];\n logout: Graffiti[\"logout\"];\n sessionEvents: Graffiti[\"sessionEvents\"];\n\n get ajv() {\n if (!this.ajv_) {\n this.ajv_ = (async () => {\n const { default: Ajv } = await import(\"ajv\");\n return new Ajv({ strict: false });\n })();\n }\n return this.ajv_;\n }\n\n get applyPatch() {\n if (!this.applyPatch_) {\n this.applyPatch_ = (async () => {\n const { applyPatch } = await import(\"fast-json-patch\");\n return applyPatch;\n })();\n }\n return this.applyPatch_;\n }\n\n /**\n * Wraps a Graffiti API instance to provide the synchronize methods.\n * The GraffitiSyncrhonize class rather than the Graffiti class\n * must be used for all functions for the synchronize methods to work.\n */\n constructor(\n /**\n * The [Graffiti API](https://api.graffiti.garden/classes/Graffiti.html)\n * instance to wrap.\n */\n graffiti: Graffiti,\n options?: GraffitiSynchronizeOptions,\n ) {\n super();\n this.options = options ?? {};\n this.graffiti = graffiti;\n this.channelStats = graffiti.channelStats.bind(graffiti);\n this.login = graffiti.login.bind(graffiti);\n this.logout = graffiti.logout.bind(graffiti);\n this.sessionEvents = graffiti.sessionEvents;\n }\n\n protected synchronize<Schema extends JSONSchema>(\n matchObject: (object: GraffitiObjectBase) => boolean,\n channels: string[],\n schema: Schema,\n session?: GraffitiSession | null,\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\n const seenUrls = new Set<string>();\n\n const repeater = new Repeater<GraffitiObjectStreamContinueEntry<Schema>>(\n async (push, stop) => {\n const validate = compileGraffitiObjectSchema(await this.ajv, schema);\n const callback: GraffitiSynchronizeCallback = (\n oldObjectRaw,\n newObjectRaw,\n ) => {\n for (const objectRaw of [newObjectRaw, oldObjectRaw]) {\n if (objectRaw?.tombstone) {\n if (seenUrls.has(objectRaw.object.url)) {\n push(objectRaw);\n }\n } else if (\n objectRaw &&\n matchObject(objectRaw.object) &&\n (this.options.omniscient ||\n isActorAllowedGraffitiObject(objectRaw.object, session))\n ) {\n const object = { ...objectRaw.object };\n if (!this.options.omniscient) {\n maskGraffitiObject(object, channels, session);\n }\n if (validate(object)) {\n push({ object });\n seenUrls.add(object.url);\n break;\n }\n }\n }\n };\n\n this.callbacks.add(callback);\n await stop;\n this.callbacks.delete(callback);\n },\n );\n\n return repeater;\n }\n\n /**\n * This method has the same signature as {@link discover} but listens for\n * changes made via {@link put}, {@link patch}, and {@link delete} or\n * fetched from {@link get}, {@link discover}, and {@link recoverOrphans}\n * and then streams appropriate changes to provide a responsive and\n * consistent user experience.\n *\n * Unlike {@link discover}, this method continuously listens for changes\n * and will not terminate unless the user calls the `return` method on the iterator\n * or `break`s out of the loop.\n *\n * @group Synchronize Methods\n */\n synchronizeDiscover<Schema extends JSONSchema>(\n ...args: Parameters<typeof Graffiti.prototype.discover<Schema>>\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\n const [channels, schema, session] = args;\n function matchObject(object: GraffitiObjectBase) {\n return object.channels.some((channel) => channels.includes(channel));\n }\n return this.synchronize<Schema>(matchObject, channels, schema, session);\n }\n\n /**\n * This method has the same signature as {@link get} but\n * listens for changes made via {@link put}, {@link patch}, and {@link delete} or\n * fetched from {@link get}, {@link discover}, and {@link recoverOrphans} and then\n * streams appropriate changes to provide a responsive and consistent user experience.\n *\n * Unlike {@link get}, which returns a single result, this method continuously\n * listens for changes which are output as an asynchronous stream, similar\n * to {@link discover}.\n *\n * @group Synchronize Methods\n */\n synchronizeGet<Schema extends JSONSchema>(\n ...args: Parameters<typeof Graffiti.prototype.get<Schema>>\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\n const [objectUrl, schema, session] = args;\n const url = unpackObjectUrl(objectUrl);\n function matchObject(object: GraffitiObjectBase) {\n return object.url === url;\n }\n return this.synchronize<Schema>(matchObject, [], schema, session);\n }\n\n /**\n * This method has the same signature as {@link recoverOrphans} but\n * listens for changes made via\n * {@link put}, {@link patch}, and {@link delete} or fetched from\n * {@link get}, {@link discover}, and {@link recoverOrphans} and then\n * streams appropriate changes to provide a responsive and consistent user experience.\n *\n * Unlike {@link recoverOrphans}, this method continuously listens for changes\n * and will not terminate unless the user calls the `return` method on the iterator\n * or `break`s out of the loop.\n *\n * @group Synchronize Methods\n */\n synchronizeRecoverOrphans<Schema extends JSONSchema>(\n ...args: Parameters<typeof Graffiti.prototype.recoverOrphans<Schema>>\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\n const [schema, session] = args;\n function matchObject(object: GraffitiObjectBase) {\n return object.actor === session.actor && object.channels.length === 0;\n }\n return this.synchronize<Schema>(matchObject, [], schema, session);\n }\n\n /**\n * Streams changes made to *any* object in *any* channel\n * and made by *any* user. You may want to use it in conjuction with\n * {@link GraffitiSynchronizeOptions.omniscient} to get a global view\n * of all Graffiti objects passing through the system. This is useful\n * for building a client-side cache, for example.\n *\n * Be careful using this method. Without additional filters it can\n * expose the user to content out of context.\n */\n synchronizeAll<Schema extends JSONSchema>(\n schema: Schema,\n session?: GraffitiSession | null,\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\n return this.synchronize<Schema>(() => true, [], schema, session);\n }\n\n protected async synchronizeDispatch(\n oldObject: GraffitiObjectStreamContinueEntry<{}>,\n newObject?: GraffitiObjectStreamContinueEntry<{}>,\n waitForListeners = false,\n ) {\n for (const callback of this.callbacks) {\n callback(oldObject, newObject);\n }\n if (waitForListeners) {\n // Wait for the listeners to receive\n // their objects, before returning the operation\n // that triggered them.\n //\n // This is important for mutators (put, patch, delete)\n // to ensure the application state has been updated\n // everywhere before returning, giving consistent\n // feedback to the user that the operation has completed.\n //\n // The opposite is true for accessors (get, discover, recoverOrphans),\n // where it is a weird user experience to call `get`\n // in one place and have the application update\n // somewhere else first. It is also less efficient.\n //\n // The hack is simply to await one \"macro task cycle\".\n // We need to wait for this cycle rather than using\n // `await push` in the callback, because it turns out\n // that `await push` won't resolve until the following\n // .next() call of the iterator, so if only\n // one .next() is called, this dispatch will hang.\n await new Promise((resolve) => setTimeout(resolve, 0));\n }\n }\n\n get: Graffiti[\"get\"] = async (...args) => {\n const object = await this.graffiti.get(...args);\n this.synchronizeDispatch({ object });\n return object;\n };\n\n put: Graffiti[\"put\"] = async (...args) => {\n const oldObject = await this.graffiti.put<{}>(...args);\n const partialObject = args[0];\n const newObject: GraffitiObjectBase = {\n ...oldObject,\n value: partialObject.value,\n channels: partialObject.channels,\n allowed: partialObject.allowed,\n };\n await this.synchronizeDispatch(\n {\n tombstone: true,\n object: oldObject,\n },\n {\n object: newObject,\n },\n true,\n );\n return oldObject;\n };\n\n patch: Graffiti[\"patch\"] = async (...args) => {\n const oldObject = await this.graffiti.patch(...args);\n const newObject: GraffitiObjectBase = { ...oldObject };\n for (const prop of [\"value\", \"channels\", \"allowed\"] as const) {\n applyGraffitiPatch(await this.applyPatch, prop, args[0], newObject);\n }\n await this.synchronizeDispatch(\n {\n tombstone: true,\n object: oldObject,\n },\n {\n object: newObject,\n },\n true,\n );\n return oldObject;\n };\n\n delete: Graffiti[\"delete\"] = async (...args) => {\n const oldObject = await this.graffiti.delete(...args);\n await this.synchronizeDispatch(\n {\n tombstone: true,\n object: oldObject,\n },\n undefined,\n true,\n );\n return oldObject;\n };\n\n protected objectStreamContinue<Schema extends JSONSchema>(\n iterator: GraffitiObjectStreamContinue<Schema>,\n ): GraffitiObjectStreamContinue<Schema> {\n const this_ = this;\n return (async function* () {\n while (true) {\n const result = await iterator.next();\n if (result.done) {\n const { continue: continue_, cursor } = result.value;\n return {\n continue: () => this_.objectStreamContinue<Schema>(continue_()),\n cursor,\n };\n }\n if (!result.value.error) {\n this_.synchronizeDispatch(\n result.value as GraffitiObjectStreamContinueEntry<{}>,\n );\n }\n yield result.value;\n }\n })();\n }\n\n protected objectStream<Schema extends JSONSchema>(\n iterator: GraffitiObjectStream<Schema>,\n ): GraffitiObjectStream<Schema> {\n const wrapped = this.objectStreamContinue<Schema>(iterator);\n return (async function* () {\n // Filter out the tombstones for type safety\n while (true) {\n const result = await wrapped.next();\n if (result.done) return result.value;\n if (result.value.error || !result.value.tombstone) yield result.value;\n }\n })();\n }\n\n discover: Graffiti[\"discover\"] = (...args) => {\n const iterator = this.graffiti.discover(...args);\n return this.objectStream<(typeof args)[1]>(iterator);\n };\n\n recoverOrphans: Graffiti[\"recoverOrphans\"] = (...args) => {\n const iterator = this.graffiti.recoverOrphans(...args);\n return this.objectStream<(typeof args)[0]>(iterator);\n };\n\n continueObjectStream: Graffiti[\"continueObjectStream\"] = (...args) => {\n // TODO!!\n return this.graffiti.continueObjectStream(...args);\n };\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type Ajv from \"ajv\";\nimport { Graffiti } from \"@graffiti-garden/api\";\nimport type {\n GraffitiSession,\n JSONSchema,\n GraffitiObjectStream,\n GraffitiObjectStreamContinueEntry,\n GraffitiObjectStreamContinue,\n GraffitiObject,\n} from \"@graffiti-garden/api\";\nimport type { GraffitiObjectBase } from \"@graffiti-garden/api\";\nimport { Repeater } from \"@repeaterjs/repeater\";\nimport type { applyPatch } from \"fast-json-patch\";\nimport {\n applyGraffitiPatch,\n compileGraffitiObjectSchema,\n isActorAllowedGraffitiObject,\n maskGraffitiObject,\n unpackObjectUrl,\n} from \"@graffiti-garden/implementation-local/utilities\";\nexport type * from \"@graffiti-garden/api\";\n\nexport type GraffitiSynchronizeCallback = (\n oldObject: GraffitiObjectStreamContinueEntry<{}>,\n newObject?: GraffitiObjectStreamContinueEntry<{}>,\n) => void;\n\nexport interface GraffitiSynchronizeOptions {\n /**\n * Allows synchronize to listen to all objects, not just those\n * that the session is allowed to see. This is useful to get a\n * global view of all Graffiti objects passsing through the system,\n * for example to build a client-side cache. Additional mechanisms\n * should be in place to ensure that users do not see objects or\n * properties they are not allowed to see.\n *\n * Default: `false`\n */\n omniscient?: boolean;\n}\n\n/**\n * Wraps the [Graffiti API](https://api.graffiti.garden/classes/Graffiti.html)\n * so that changes made or received in one part of an application\n * are automatically routed to other parts of the application.\n * This is an important tool for building responsive\n * and consistent user interfaces, and is built upon to make\n * the [Graffiti Vue Plugin](https://vue.graffiti.garden/variables/GraffitiPlugin.html)\n * and possibly other front-end libraries in the future.\n *\n * Specifically, it provides the following *synchronize*\n * methods for each of the following API methods:\n *\n * | API Method | Synchronize Method |\n * |------------|--------------------|\n * | {@link get} | {@link synchronizeGet} |\n * | {@link discover} | {@link synchronizeDiscover} |\n * | {@link recoverOrphans} | {@link synchronizeRecoverOrphans} |\n *\n * Whenever a change is made via {@link put}, {@link patch}, and {@link delete} or\n * received from {@link get}, {@link discover}, and {@link recoverOrphans},\n * those changes are forwarded to the appropriate synchronize method.\n * Each synchronize method returns an iterator that streams these changes\n * continually until the user calls `return` on the iterator or `break`s out of the loop,\n * allowing for live updates without additional polling.\n *\n * Example 1: Suppose a user publishes a post using {@link put}. If the feed\n * displaying that user's posts is using {@link synchronizeDiscover} to listen for changes,\n * then the user's new post will instantly appear in their feed, giving the UI a\n * responsive feel.\n *\n * Example 2: Suppose one of a user's friends changes their name. As soon as the\n * user's application receives one notice of that change (using {@link get}\n * or {@link discover}), then {@link synchronizeDiscover} listeners can be used to update\n * all instance's of that friend's name in the user's application instantly,\n * providing a consistent user experience.\n *\n * @groupDescription Synchronize Methods\n * This group contains methods that listen for changes made via\n * {@link put}, {@link patch}, and {@link delete} or fetched from\n * {@link get}, {@link discover}, and {@link recoverOrphans} and then\n * streams appropriate changes to provide a responsive and consistent user experience.\n */\nexport class GraffitiSynchronize extends Graffiti {\n protected ajv_: Promise<Ajv> | undefined;\n protected applyPatch_: Promise<typeof applyPatch> | undefined;\n protected readonly graffiti: Graffiti;\n protected readonly callbacks = new Set<GraffitiSynchronizeCallback>();\n protected readonly options: GraffitiSynchronizeOptions;\n\n channelStats: Graffiti[\"channelStats\"];\n login: Graffiti[\"login\"];\n logout: Graffiti[\"logout\"];\n sessionEvents: Graffiti[\"sessionEvents\"];\n\n get ajv() {\n if (!this.ajv_) {\n this.ajv_ = (async () => {\n const { default: Ajv } = await import(\"ajv\");\n return new Ajv({ strict: false });\n })();\n }\n return this.ajv_;\n }\n\n get applyPatch() {\n if (!this.applyPatch_) {\n this.applyPatch_ = (async () => {\n const { applyPatch } = await import(\"fast-json-patch\");\n return applyPatch;\n })();\n }\n return this.applyPatch_;\n }\n\n /**\n * Wraps a Graffiti API instance to provide the synchronize methods.\n * The GraffitiSyncrhonize class rather than the Graffiti class\n * must be used for all functions for the synchronize methods to work.\n */\n constructor(\n /**\n * The [Graffiti API](https://api.graffiti.garden/classes/Graffiti.html)\n * instance to wrap.\n */\n graffiti: Graffiti,\n options?: GraffitiSynchronizeOptions,\n ) {\n super();\n this.options = options ?? {};\n this.graffiti = graffiti;\n this.channelStats = graffiti.channelStats.bind(graffiti);\n this.login = graffiti.login.bind(graffiti);\n this.logout = graffiti.logout.bind(graffiti);\n this.sessionEvents = graffiti.sessionEvents;\n }\n\n protected synchronize<Schema extends JSONSchema>(\n matchObject: (object: GraffitiObjectBase) => boolean,\n channels: string[],\n schema: Schema,\n session?: GraffitiSession | null,\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\n const seenUrls = new Set<string>();\n\n const repeater = new Repeater<GraffitiObjectStreamContinueEntry<Schema>>(\n async (push, stop) => {\n const validate = compileGraffitiObjectSchema(await this.ajv, schema);\n const callback: GraffitiSynchronizeCallback = (\n oldObjectRaw,\n newObjectRaw,\n ) => {\n for (const objectRaw of [newObjectRaw, oldObjectRaw]) {\n if (objectRaw?.tombstone) {\n if (seenUrls.has(objectRaw.object.url)) {\n push(objectRaw);\n }\n } else if (\n objectRaw &&\n matchObject(objectRaw.object) &&\n (this.options.omniscient ||\n isActorAllowedGraffitiObject(objectRaw.object, session))\n ) {\n // Deep clone the object to prevent mutation\n const object = JSON.parse(\n JSON.stringify(objectRaw.object),\n ) as GraffitiObject<{}>;\n if (!this.options.omniscient) {\n maskGraffitiObject(object, channels, session);\n }\n if (validate(object)) {\n push({ object });\n seenUrls.add(object.url);\n break;\n }\n }\n }\n };\n\n this.callbacks.add(callback);\n await stop;\n this.callbacks.delete(callback);\n },\n );\n\n return repeater;\n }\n\n /**\n * This method has the same signature as {@link discover} but listens for\n * changes made via {@link put}, {@link patch}, and {@link delete} or\n * fetched from {@link get}, {@link discover}, and {@link recoverOrphans}\n * and then streams appropriate changes to provide a responsive and\n * consistent user experience.\n *\n * Unlike {@link discover}, this method continuously listens for changes\n * and will not terminate unless the user calls the `return` method on the iterator\n * or `break`s out of the loop.\n *\n * @group Synchronize Methods\n */\n synchronizeDiscover<Schema extends JSONSchema>(\n ...args: Parameters<typeof Graffiti.prototype.discover<Schema>>\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\n const [channels, schema, session] = args;\n function matchObject(object: GraffitiObjectBase) {\n return object.channels.some((channel) => channels.includes(channel));\n }\n return this.synchronize<Schema>(matchObject, channels, schema, session);\n }\n\n /**\n * This method has the same signature as {@link get} but\n * listens for changes made via {@link put}, {@link patch}, and {@link delete} or\n * fetched from {@link get}, {@link discover}, and {@link recoverOrphans} and then\n * streams appropriate changes to provide a responsive and consistent user experience.\n *\n * Unlike {@link get}, which returns a single result, this method continuously\n * listens for changes which are output as an asynchronous stream, similar\n * to {@link discover}.\n *\n * @group Synchronize Methods\n */\n synchronizeGet<Schema extends JSONSchema>(\n ...args: Parameters<typeof Graffiti.prototype.get<Schema>>\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\n const [objectUrl, schema, session] = args;\n const url = unpackObjectUrl(objectUrl);\n function matchObject(object: GraffitiObjectBase) {\n return object.url === url;\n }\n return this.synchronize<Schema>(matchObject, [], schema, session);\n }\n\n /**\n * This method has the same signature as {@link recoverOrphans} but\n * listens for changes made via\n * {@link put}, {@link patch}, and {@link delete} or fetched from\n * {@link get}, {@link discover}, and {@link recoverOrphans} and then\n * streams appropriate changes to provide a responsive and consistent user experience.\n *\n * Unlike {@link recoverOrphans}, this method continuously listens for changes\n * and will not terminate unless the user calls the `return` method on the iterator\n * or `break`s out of the loop.\n *\n * @group Synchronize Methods\n */\n synchronizeRecoverOrphans<Schema extends JSONSchema>(\n ...args: Parameters<typeof Graffiti.prototype.recoverOrphans<Schema>>\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\n const [schema, session] = args;\n function matchObject(object: GraffitiObjectBase) {\n return object.actor === session.actor && object.channels.length === 0;\n }\n return this.synchronize<Schema>(matchObject, [], schema, session);\n }\n\n /**\n * Streams changes made to *any* object in *any* channel\n * and made by *any* user. You may want to use it in conjuction with\n * {@link GraffitiSynchronizeOptions.omniscient} to get a global view\n * of all Graffiti objects passing through the system. This is useful\n * for building a client-side cache, for example.\n *\n * Be careful using this method. Without additional filters it can\n * expose the user to content out of context.\n */\n synchronizeAll<Schema extends JSONSchema>(\n schema: Schema,\n session?: GraffitiSession | null,\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\n return this.synchronize<Schema>(() => true, [], schema, session);\n }\n\n protected async synchronizeDispatch(\n oldObject: GraffitiObjectStreamContinueEntry<{}>,\n newObject?: GraffitiObjectStreamContinueEntry<{}>,\n waitForListeners = false,\n ) {\n for (const callback of this.callbacks) {\n callback(oldObject, newObject);\n }\n if (waitForListeners) {\n // Wait for the listeners to receive\n // their objects, before returning the operation\n // that triggered them.\n //\n // This is important for mutators (put, patch, delete)\n // to ensure the application state has been updated\n // everywhere before returning, giving consistent\n // feedback to the user that the operation has completed.\n //\n // The opposite is true for accessors (get, discover, recoverOrphans),\n // where it is a weird user experience to call `get`\n // in one place and have the application update\n // somewhere else first. It is also less efficient.\n //\n // The hack is simply to await one \"macro task cycle\".\n // We need to wait for this cycle rather than using\n // `await push` in the callback, because it turns out\n // that `await push` won't resolve until the following\n // .next() call of the iterator, so if only\n // one .next() is called, this dispatch will hang.\n await new Promise((resolve) => setTimeout(resolve, 0));\n }\n }\n\n get: Graffiti[\"get\"] = async (...args) => {\n const object = await this.graffiti.get(...args);\n this.synchronizeDispatch({ object });\n return object;\n };\n\n put: Graffiti[\"put\"] = async (...args) => {\n const oldObject = await this.graffiti.put<{}>(...args);\n const partialObject = args[0];\n const newObject: GraffitiObjectBase = {\n ...oldObject,\n value: partialObject.value,\n channels: partialObject.channels,\n allowed: partialObject.allowed,\n };\n await this.synchronizeDispatch(\n {\n tombstone: true,\n object: oldObject,\n },\n {\n object: newObject,\n },\n true,\n );\n return oldObject;\n };\n\n patch: Graffiti[\"patch\"] = async (...args) => {\n const oldObject = await this.graffiti.patch(...args);\n const newObject: GraffitiObjectBase = { ...oldObject };\n for (const prop of [\"value\", \"channels\", \"allowed\"] as const) {\n applyGraffitiPatch(await this.applyPatch, prop, args[0], newObject);\n }\n await this.synchronizeDispatch(\n {\n tombstone: true,\n object: oldObject,\n },\n {\n object: newObject,\n },\n true,\n );\n return oldObject;\n };\n\n delete: Graffiti[\"delete\"] = async (...args) => {\n const oldObject = await this.graffiti.delete(...args);\n await this.synchronizeDispatch(\n {\n tombstone: true,\n object: oldObject,\n },\n undefined,\n true,\n );\n return oldObject;\n };\n\n protected objectStreamContinue<Schema extends JSONSchema>(\n iterator: GraffitiObjectStreamContinue<Schema>,\n ): GraffitiObjectStreamContinue<Schema> {\n const this_ = this;\n return (async function* () {\n while (true) {\n const result = await iterator.next();\n if (result.done) {\n const { continue: continue_, cursor } = result.value;\n return {\n continue: () => this_.objectStreamContinue<Schema>(continue_()),\n cursor,\n };\n }\n if (!result.value.error) {\n this_.synchronizeDispatch(\n result.value as GraffitiObjectStreamContinueEntry<{}>,\n );\n }\n yield result.value;\n }\n })();\n }\n\n protected objectStream<Schema extends JSONSchema>(\n iterator: GraffitiObjectStream<Schema>,\n ): GraffitiObjectStream<Schema> {\n const wrapped = this.objectStreamContinue<Schema>(iterator);\n return (async function* () {\n // Filter out the tombstones for type safety\n while (true) {\n const result = await wrapped.next();\n if (result.done) return result.value;\n if (result.value.error || !result.value.tombstone) yield result.value;\n }\n })();\n }\n\n discover: Graffiti[\"discover\"] = (...args) => {\n const iterator = this.graffiti.discover(...args);\n return this.objectStream<(typeof args)[1]>(iterator);\n };\n\n recoverOrphans: Graffiti[\"recoverOrphans\"] = (...args) => {\n const iterator = this.graffiti.recoverOrphans(...args);\n return this.objectStream<(typeof args)[0]>(iterator);\n };\n\n continueObjectStream: Graffiti[\"continueObjectStream\"] = (...args) => {\n // TODO!!\n return this.graffiti.continueObjectStream(...args);\n };\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@graffiti-garden/wrapper-synchronize",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "Internal synchronization for the Graffiti API",
5
5
  "types": "./dist/index.d.ts",
6
6
  "module": "./dist/esm/index.js",
package/src/index.ts CHANGED
@@ -6,6 +6,7 @@ import type {
6
6
  GraffitiObjectStream,
7
7
  GraffitiObjectStreamContinueEntry,
8
8
  GraffitiObjectStreamContinue,
9
+ GraffitiObject,
9
10
  } from "@graffiti-garden/api";
10
11
  import type { GraffitiObjectBase } from "@graffiti-garden/api";
11
12
  import { Repeater } from "@repeaterjs/repeater";
@@ -160,7 +161,10 @@ export class GraffitiSynchronize extends Graffiti {
160
161
  (this.options.omniscient ||
161
162
  isActorAllowedGraffitiObject(objectRaw.object, session))
162
163
  ) {
163
- const object = { ...objectRaw.object };
164
+ // Deep clone the object to prevent mutation
165
+ const object = JSON.parse(
166
+ JSON.stringify(objectRaw.object),
167
+ ) as GraffitiObject<{}>;
164
168
  if (!this.options.omniscient) {
165
169
  maskGraffitiObject(object, channels, session);
166
170
  }