@graffiti-garden/wrapper-synchronize 1.0.2 → 1.0.4
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.
- package/dist/browser/index.js +1 -1
- package/dist/browser/index.js.map +3 -3
- package/dist/cjs/index.js +12 -3
- package/dist/cjs/index.js.map +2 -2
- package/dist/esm/index.js +12 -3
- package/dist/esm/index.js.map +2 -2
- package/dist/index.d.ts.map +1 -1
- package/package.json +7 -7
- package/src/index.ts +23 -3
package/dist/browser/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{b as g,c as j,d as x}from"./chunk-YB7WCAZH.js";g();x();j();g();x();j();var re={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"}},additionalProperties:!1,required:["value","channels","actor","url"]},de={...re,required:["value","channels"]};var D=class Q extends Error{constructor(r){super(r),this.name="GraffitiErrorNotFound",Object.setPrototypeOf(this,Q.prototype)}},ne=class X extends Error{constructor(r){super(r),this.name="GraffitiErrorInvalidSchema",Object.setPrototypeOf(this,X.prototype)}};function N(t){return typeof t=="string"?t:t.url}function K(t,r){try{return t.compile(r)}catch(e){throw new ne(e instanceof Error?e.message:void 0)}}function Y(t,r){return!Array.isArray(t.allowed)||typeof r?.actor=="string"&&(t.actor===r.actor||t.allowed.includes(r.actor))}function Z(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)))}g();x();j();var R=function(t,r){return R=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])},R(t,r)};function ie(t,r){R(t,r);function e(){this.constructor=t}t.prototype=r===null?Object.create(r):(e.prototype=r.prototype,new e)}function G(t,r,e,n){function o(i){return i instanceof e?i:new e(function(s){s(i)})}return new(e||(e=Promise))(function(i,s){function c(f){try{a(n.next(f))}catch(h){s(h)}}function l(f){try{a(n.throw(f))}catch(h){s(h)}}function a(f){f.done?i(f.value):o(f.value).then(c,l)}a((n=n.apply(t,r||[])).next())})}function b(t,r){var e={label:0,sent:function(){if(i[0]&1)throw i[1];return i[1]},trys:[],ops:[]},n,o,i,s;return s={next:c(0),throw:c(1),return:c(2)},typeof Symbol=="function"&&(s[Symbol.iterator]=function(){return this}),s;function c(a){return function(f){return l([a,f])}}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(f){a=[6,f],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 k(t){return this instanceof k?(this.v=t,this):new k(t)}function oe(t,r,e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var n=e.apply(t,r||[]),o,i=[];return o={},s("next"),s("throw"),s("return"),o[Symbol.asyncIterator]=function(){return this},o;function s(u){n[u]&&(o[u]=function(d){return new Promise(function(p,y){i.push([u,d,p,y])>1||c(u,d)})})}function c(u,d){try{l(n[u](d))}catch(p){h(i[0][3],p)}}function l(u){u.value instanceof k?Promise.resolve(u.value.v).then(a,f):h(i[0][2],u)}function a(u){c("next",u)}function f(u){c("throw",u)}function h(u,d){u(d),i.shift(),i.length&&c(i[0][0],i[0][1])}}var ee=(function(t){ie(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),be=(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})(),we=(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})(),Se=(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,$=1,S=2,M=3,V=4,T=1024,B=function(){};function O(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 w(t,r){var e=t.state>=M;return Promise.resolve(r).then(function(n){return!e&&t.state>=V?O(t).then(function(o){return{value:o,done:!0}}):{value:n,done:e}})}function _(t,r){var e,n;if(!(t.state>=S))if(t.state=S,t.onnext(),t.onstop(),t.err==null&&(t.err=r),t.pushes.length===0&&(typeof t.buffer>"u"||t.buffer.empty))A(t);else try{for(var o=P(t.pushes),i=o.next();!i.done;i=o.next()){var s=i.value;s.resolve()}}catch(c){e={error:c}}finally{try{i&&!i.done&&(n=o.return)&&n.call(o)}finally{if(e)throw e.error}}}function A(t){var r,e;if(!(t.state>=M)){t.state<S&&_(t),t.state=M,t.buffer=void 0;try{for(var n=P(t.nexts),o=n.next();!o.done;o=n.next()){var i=o.value,s=t.pending===void 0?O(t):t.pending.then(function(){return O(t)});i.resolve(w(t,s))}}catch(c){r={error:c}}finally{try{o&&!o.done&&(e=n.return)&&e.call(n)}finally{if(r)throw r.error}}t.pushes=[],t.nexts=[]}}function U(t){t.state>=V||(t.state<M&&A(t),t.state=V)}function ae(t,r){if(F(r),t.pushes.length>=T)throw new ee("No more than "+T+" pending calls to push are allowed on a single repeater.");if(t.state>=S)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<S&&(t.err=l),U(t)});var n;if(t.nexts.length){var o=t.nexts.shift();o.resolve(w(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,s={},c=n.catch(function(l){if(i)throw l});return s.then=function(l,a){return i=!1,Promise.prototype.then.call(n,l,a)},s.catch=function(l){return i=!1,Promise.prototype.catch.call(n,l)},s.finally=n.finally.bind(n),t.pending=e.then(function(){return c}).catch(function(l){t.err=l,U(t)}),s}function ue(t){var r=_.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 se(t){if(!(t.state>=$)){t.state=$;var r=ae.bind(null,t),e=ue(t);t.execution=new Promise(function(n){return n(t.executor(r,e))}),t.execution.catch(function(){return _(t)})}}var q=new WeakMap,E=(function(){function t(r,e){q.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=q.get(this);if(e===void 0)throw new Error("WeakMap error");if(e.nexts.length>=T)throw new ee("No more than "+T+" pending calls to next are allowed on a single repeater.");if(e.state<=J&&se(e),e.onnext(r),typeof e.buffer<"u"&&!e.buffer.empty){var n=w(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,w(e,i.value)}else if(e.state>=S)return A(e),w(e,O(e));return new Promise(function(s){return e.nexts.push({resolve:s,value:r})})},t.prototype.return=function(r){F(r);var e=q.get(this);if(e===void 0)throw new Error("WeakMap error");return A(e),e.execution=Promise.resolve(e.execution).then(function(){return r}),w(e,O(e))},t.prototype.throw=function(r){var e=q.get(this);if(e===void 0)throw new Error("WeakMap error");return e.state<=J||e.state>=S||typeof e.buffer<"u"&&!e.buffer.empty?(A(e),e.err==null&&(e.err=r),w(e,O(e))):this.next(Promise.reject(r))},t.prototype[Symbol.asyncIterator]=function(){return this},t.race=ce,t.merge=fe,t.zip=le,t.latest=he,t})();function I(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 oe(this,arguments,function(){return b(this,function(u){switch(u.label){case 0:return r.yieldValues?[4,k(a)]:[3,3];case 1:return[4,u.sent()];case 2:u.sent(),u.label=3;case 3:return r.returnValues?[4,k(a)]:[3,5];case 4:return[2,u.sent()];case 5:return[2]}})})})())};try{for(var s=P(t),c=s.next();!c.done;c=s.next()){var l=c.value;i(l)}}catch(a){e={error:a}}finally{try{c&&!c.done&&(n=s.return)&&n.call(s)}finally{if(e)throw e.error}}return o}function ce(t){var r=this,e=I(t,{returnValues:!0});return new E(function(n,o){return G(r,void 0,void 0,function(){var i,s,c,l,a,f;return b(this,function(h){switch(h.label){case 0:if(!e.length)return o(),[2];s=!1,o.then(function(){i(),s=!0}),h.label=1;case 1:h.trys.push([1,,5,7]),l=void 0,a=0,f=function(){var u,d,p,y,m,z;return b(this,function(C){switch(C.label){case 0:u=a;try{for(d=(m=void 0,P(e)),p=d.next();!p.done;p=d.next())y=p.value,Promise.resolve(y.next()).then(function(v){v.done?(o(),c===void 0&&(c=v)):a===u&&(a++,i(v))},function(v){return o(v)})}catch(v){m={error:v}}finally{try{p&&!p.done&&(z=d.return)&&z.call(d)}finally{if(m)throw m.error}}return[4,new Promise(function(v){return i=v})];case 1:return l=C.sent(),l===void 0?[3,3]:[4,n(l.value)];case 2:C.sent(),C.label=3;case 3:return[2]}})},h.label=2;case 2:return s?[3,4]:[5,f()];case 3:return h.sent(),[3,2];case 4:return[2,c&&c.value];case 5:return o(),[4,Promise.race(e.map(function(u){return u.return&&u.return()}))];case 6:return h.sent(),[7];case 7:return[2]}})})})}function fe(t){var r=this,e=I(t,{yieldValues:!0});return new E(function(n,o){return G(r,void 0,void 0,function(){var i,s,c,l=this;return b(this,function(a){switch(a.label){case 0:if(!e.length)return o(),[2];i=[],s=!1,o.then(function(){var f,h;s=!0;try{for(var u=P(i),d=u.next();!d.done;d=u.next()){var p=d.value;p()}}catch(y){f={error:y}}finally{try{d&&!d.done&&(h=u.return)&&h.call(u)}finally{if(f)throw f.error}}}),a.label=1;case 1:return a.trys.push([1,,3,4]),[4,Promise.all(e.map(function(f,h){return G(l,void 0,void 0,function(){var u,d;return b(this,function(p){switch(p.label){case 0:p.trys.push([0,,6,9]),p.label=1;case 1:return s?[3,5]:(Promise.resolve(f.next()).then(function(y){return i[h](y)},function(y){return o(y)}),[4,new Promise(function(y){i[h]=y})]);case 2:return u=p.sent(),u===void 0?[3,4]:u.done?(c=u,[2]):[4,n(u.value)];case 3:p.sent(),p.label=4;case 4:return[3,1];case 5:return[3,9];case 6:return d=f.return,d?[4,f.return()]:[3,8];case 7:d=p.sent(),p.label=8;case 8:return[7];case 9:return[2]}})})}))];case 2:return a.sent(),[2,c&&c.value];case 3:return o(),[7];case 4:return[2]}})})})}function le(t){var r=this,e=I(t,{returnValues:!0});return new E(function(n,o){return G(r,void 0,void 0,function(){var i,s,c,l;return b(this,function(a){switch(a.label){case 0:if(!e.length)return o(),[2,[]];s=!1,o.then(function(){i(),s=!0}),a.label=1;case 1:a.trys.push([1,,6,8]),a.label=2;case 2:return s?[3,5]:(Promise.all(e.map(function(f){return f.next()})).then(function(f){return i(f)},function(f){return o(f)}),[4,new Promise(function(f){return i=f})]);case 3:return c=a.sent(),c===void 0?[2]:(l=c.map(function(f){return f.value}),c.some(function(f){return f.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(f){return f.return&&f.return()}))];case 7:return a.sent(),[7];case 8:return[2]}})})})}function he(t){var r=this,e=I(t,{yieldValues:!0,returnValues:!0});return new E(function(n,o){return G(r,void 0,void 0,function(){var i,s,c,l,a,f=this;return b(this,function(h){switch(h.label){case 0:if(!e.length)return o(),[2,[]];s=[],c=!1,o.then(function(){var u,d;i();try{for(var p=P(s),y=p.next();!y.done;y=p.next()){var m=y.value;m()}}catch(z){u={error:z}}finally{try{y&&!y.done&&(d=p.return)&&d.call(p)}finally{if(u)throw u.error}}c=!0}),h.label=1;case 1:return h.trys.push([1,,5,7]),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 2:return l=h.sent(),l===void 0?[2]:(a=l.map(function(u){return u.value}),l.every(function(u){return u.done})?[2,a]:[4,n(a.slice())]);case 3:return h.sent(),[4,Promise.all(e.map(function(u,d){return G(f,void 0,void 0,function(){var p;return b(this,function(y){switch(y.label){case 0:if(l[d].done)return[2,l[d].value];y.label=1;case 1:return c?[3,4]:(Promise.resolve(u.next()).then(function(m){return s[d](m)},function(m){return o(m)}),[4,new Promise(function(m){return s[d]=m})]);case 2:return p=y.sent(),p===void 0?[2,l[d].value]:p.done?[2,p.value]:(a[d]=p.value,[4,n(a.slice())]);case 3:return y.sent(),[3,1];case 4:return[2]}})})}))];case 4:return[2,h.sent()];case 5:return o(),[4,Promise.all(e.map(function(u){return u.return&&u.return()}))];case 6:return h.sent(),[7];case 7:return[2]}})})})}var te=class{ajv_;graffiti;callbacks=new Set;options;login;logout;sessionEvents;postMedia;getMedia;deleteMedia;actorToHandle;handleToActor;get ajv(){return this.ajv_||(this.ajv_=(async()=>{let{default:r}=await import("./ajv-UZKI6BMI.js");return new r({strict:!1})})()),this.ajv_}constructor(r,e){this.options=e??{},this.graffiti=r,this.login=r.login.bind(r),this.logout=r.logout.bind(r),this.sessionEvents=r.sessionEvents,this.postMedia=r.postMedia.bind(r),this.getMedia=r.getMedia.bind(r),this.deleteMedia=r.deleteMedia.bind(r),this.actorToHandle=r.actorToHandle.bind(r),this.handleToActor=r.handleToActor.bind(r)}synchronize(r,e,n,o,i=new Set){let s=new E(async(c,l)=>{let a=K(await this.ajv,n),f=h=>{if(h?.tombstone)i.has(h.object.url)&&c(h);else if(h&&r(h.object)&&(this.options.omniscient||Y(h.object,o))){let u=JSON.parse(JSON.stringify(h.object));this.options.omniscient||Z(u,e,o),a(u)&&(c({object:u}),i.add(u.url))}};this.callbacks.add(f),await l,this.callbacks.delete(f)});return(async function*(){for await(let c of s)yield c})()}synchronizeDiscover(r,e,n){function o(i){return i.channels.some(s=>r.includes(s))}return this.synchronize(o,r,e,n)}synchronizeGet(r,e,n){let o=N(r);function i(s){return s.url===o}return this.synchronize(i,[],e,n,new Set([o]))}synchronizeAll(r,e){return this.synchronize(()=>!0,[],r,e)}async synchronizeDispatch(r,e=!1){for(let n of this.callbacks)n(r);e&&await new Promise(n=>setTimeout(n,0))}get=async(...r)=>{try{let e=await this.graffiti.get(...r);return this.synchronizeDispatch({object:e}),e}catch(e){throw e instanceof D&&this.synchronizeDispatch({tombstone:!0,object:{url:N(r[0])}}),e}};post=async(...r)=>{let e=await this.graffiti.post(...r);return await this.synchronizeDispatch({object:e},!0),e};delete=async(...r)=>{let e={tombstone:!0,object:{url:N(r[0])}};try{let n=await this.graffiti.delete(...r);return await this.synchronizeDispatch(e,!0),n}catch(n){throw n instanceof D&&await this.synchronizeDispatch(e,!0),n}};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:s=>e.objectStreamContinue(o(s)),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)};continueDiscover=(...r)=>{let e=this.graffiti.continueDiscover(...r);return this.objectStreamContinue(e)}};export{te as GraffitiSynchronize};
|
|
1
|
+
import{b as g,c as j,d as O}from"./chunk-YB7WCAZH.js";g();O();j();g();O();j();var re={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"}},additionalProperties:!1,required:["value","channels","actor","url"]},de={...re,required:["value","channels"]};var D=class Q extends Error{constructor(r){super(r),this.name="GraffitiErrorNotFound",Object.setPrototypeOf(this,Q.prototype)}},X=class K extends Error{constructor(r){super(r),this.name="GraffitiErrorInvalidSchema",Object.setPrototypeOf(this,K.prototype)}};function N(t){return typeof t=="string"?t:t.url}function Y(t,r){return!Array.isArray(t.allowed)||typeof r?.actor=="string"&&(t.actor===r.actor||t.allowed.includes(r.actor))}function Z(t,r,e){if(e===t.actor)return t;let n=t.allowed&&e?[e]:void 0,o=t.channels.filter(i=>r.includes(i));return{...t,allowed:n,channels:o}}g();O();j();var R=function(t,r){return R=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])},R(t,r)};function ne(t,r){R(t,r);function e(){this.constructor=t}t.prototype=r===null?Object.create(r):(e.prototype=r.prototype,new e)}function G(t,r,e,n){function o(i){return i instanceof e?i:new e(function(u){u(i)})}return new(e||(e=Promise))(function(i,u){function c(f){try{a(n.next(f))}catch(h){u(h)}}function l(f){try{a(n.throw(f))}catch(h){u(h)}}function a(f){f.done?i(f.value):o(f.value).then(c,l)}a((n=n.apply(t,r||[])).next())})}function b(t,r){var e={label:0,sent:function(){if(i[0]&1)throw i[1];return i[1]},trys:[],ops:[]},n,o,i,u;return u={next:c(0),throw:c(1),return:c(2)},typeof Symbol=="function"&&(u[Symbol.iterator]=function(){return this}),u;function c(a){return function(f){return l([a,f])}}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(f){a=[6,f],o=0}finally{n=i=0}if(a[0]&5)throw a[1];return{value:a[0]?a[1]:void 0,done:!0}}}function E(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 k(t){return this instanceof k?(this.v=t,this):new k(t)}function ie(t,r,e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var n=e.apply(t,r||[]),o,i=[];return o={},u("next"),u("throw"),u("return"),o[Symbol.asyncIterator]=function(){return this},o;function u(s){n[s]&&(o[s]=function(d){return new Promise(function(p,y){i.push([s,d,p,y])>1||c(s,d)})})}function c(s,d){try{l(n[s](d))}catch(p){h(i[0][3],p)}}function l(s){s.value instanceof k?Promise.resolve(s.value.v).then(a,f):h(i[0][2],s)}function a(s){c("next",s)}function f(s){c("throw",s)}function h(s,d){s(d),i.shift(),i.length&&c(i[0][0],i[0][1])}}var ee=(function(t){ne(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),be=(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})(),we=(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})(),Se=(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,$=1,S=2,q=3,V=4,T=1024,B=function(){};function x(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 w(t,r){var e=t.state>=q;return Promise.resolve(r).then(function(n){return!e&&t.state>=V?x(t).then(function(o){return{value:o,done:!0}}):{value:n,done:e}})}function _(t,r){var e,n;if(!(t.state>=S))if(t.state=S,t.onnext(),t.onstop(),t.err==null&&(t.err=r),t.pushes.length===0&&(typeof t.buffer>"u"||t.buffer.empty))A(t);else try{for(var o=E(t.pushes),i=o.next();!i.done;i=o.next()){var u=i.value;u.resolve()}}catch(c){e={error:c}}finally{try{i&&!i.done&&(n=o.return)&&n.call(o)}finally{if(e)throw e.error}}}function A(t){var r,e;if(!(t.state>=q)){t.state<S&&_(t),t.state=q,t.buffer=void 0;try{for(var n=E(t.nexts),o=n.next();!o.done;o=n.next()){var i=o.value,u=t.pending===void 0?x(t):t.pending.then(function(){return x(t)});i.resolve(w(t,u))}}catch(c){r={error:c}}finally{try{o&&!o.done&&(e=n.return)&&e.call(n)}finally{if(r)throw r.error}}t.pushes=[],t.nexts=[]}}function U(t){t.state>=V||(t.state<q&&A(t),t.state=V)}function oe(t,r){if(F(r),t.pushes.length>=T)throw new ee("No more than "+T+" pending calls to push are allowed on a single repeater.");if(t.state>=S)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<S&&(t.err=l),U(t)});var n;if(t.nexts.length){var o=t.nexts.shift();o.resolve(w(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,u={},c=n.catch(function(l){if(i)throw l});return u.then=function(l,a){return i=!1,Promise.prototype.then.call(n,l,a)},u.catch=function(l){return i=!1,Promise.prototype.catch.call(n,l)},u.finally=n.finally.bind(n),t.pending=e.then(function(){return c}).catch(function(l){t.err=l,U(t)}),u}function ae(t){var r=_.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 se(t){if(!(t.state>=$)){t.state=$;var r=oe.bind(null,t),e=ae(t);t.execution=new Promise(function(n){return n(t.executor(r,e))}),t.execution.catch(function(){return _(t)})}}var M=new WeakMap,P=(function(){function t(r,e){M.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=M.get(this);if(e===void 0)throw new Error("WeakMap error");if(e.nexts.length>=T)throw new ee("No more than "+T+" pending calls to next are allowed on a single repeater.");if(e.state<=J&&se(e),e.onnext(r),typeof e.buffer<"u"&&!e.buffer.empty){var n=w(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,w(e,i.value)}else if(e.state>=S)return A(e),w(e,x(e));return new Promise(function(u){return e.nexts.push({resolve:u,value:r})})},t.prototype.return=function(r){F(r);var e=M.get(this);if(e===void 0)throw new Error("WeakMap error");return A(e),e.execution=Promise.resolve(e.execution).then(function(){return r}),w(e,x(e))},t.prototype.throw=function(r){var e=M.get(this);if(e===void 0)throw new Error("WeakMap error");return e.state<=J||e.state>=S||typeof e.buffer<"u"&&!e.buffer.empty?(A(e),e.err==null&&(e.err=r),w(e,x(e))):this.next(Promise.reject(r))},t.prototype[Symbol.asyncIterator]=function(){return this},t.race=ue,t.merge=ce,t.zip=fe,t.latest=le,t})();function I(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 ie(this,arguments,function(){return b(this,function(s){switch(s.label){case 0:return r.yieldValues?[4,k(a)]:[3,3];case 1:return[4,s.sent()];case 2:s.sent(),s.label=3;case 3:return r.returnValues?[4,k(a)]:[3,5];case 4:return[2,s.sent()];case 5:return[2]}})})})())};try{for(var u=E(t),c=u.next();!c.done;c=u.next()){var l=c.value;i(l)}}catch(a){e={error:a}}finally{try{c&&!c.done&&(n=u.return)&&n.call(u)}finally{if(e)throw e.error}}return o}function ue(t){var r=this,e=I(t,{returnValues:!0});return new P(function(n,o){return G(r,void 0,void 0,function(){var i,u,c,l,a,f;return b(this,function(h){switch(h.label){case 0:if(!e.length)return o(),[2];u=!1,o.then(function(){i(),u=!0}),h.label=1;case 1:h.trys.push([1,,5,7]),l=void 0,a=0,f=function(){var s,d,p,y,m,C;return b(this,function(z){switch(z.label){case 0:s=a;try{for(d=(m=void 0,E(e)),p=d.next();!p.done;p=d.next())y=p.value,Promise.resolve(y.next()).then(function(v){v.done?(o(),c===void 0&&(c=v)):a===s&&(a++,i(v))},function(v){return o(v)})}catch(v){m={error:v}}finally{try{p&&!p.done&&(C=d.return)&&C.call(d)}finally{if(m)throw m.error}}return[4,new Promise(function(v){return i=v})];case 1:return l=z.sent(),l===void 0?[3,3]:[4,n(l.value)];case 2:z.sent(),z.label=3;case 3:return[2]}})},h.label=2;case 2:return u?[3,4]:[5,f()];case 3:return h.sent(),[3,2];case 4:return[2,c&&c.value];case 5:return o(),[4,Promise.race(e.map(function(s){return s.return&&s.return()}))];case 6:return h.sent(),[7];case 7:return[2]}})})})}function ce(t){var r=this,e=I(t,{yieldValues:!0});return new P(function(n,o){return G(r,void 0,void 0,function(){var i,u,c,l=this;return b(this,function(a){switch(a.label){case 0:if(!e.length)return o(),[2];i=[],u=!1,o.then(function(){var f,h;u=!0;try{for(var s=E(i),d=s.next();!d.done;d=s.next()){var p=d.value;p()}}catch(y){f={error:y}}finally{try{d&&!d.done&&(h=s.return)&&h.call(s)}finally{if(f)throw f.error}}}),a.label=1;case 1:return a.trys.push([1,,3,4]),[4,Promise.all(e.map(function(f,h){return G(l,void 0,void 0,function(){var s,d;return b(this,function(p){switch(p.label){case 0:p.trys.push([0,,6,9]),p.label=1;case 1:return u?[3,5]:(Promise.resolve(f.next()).then(function(y){return i[h](y)},function(y){return o(y)}),[4,new Promise(function(y){i[h]=y})]);case 2:return s=p.sent(),s===void 0?[3,4]:s.done?(c=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 d=f.return,d?[4,f.return()]:[3,8];case 7:d=p.sent(),p.label=8;case 8:return[7];case 9:return[2]}})})}))];case 2:return a.sent(),[2,c&&c.value];case 3:return o(),[7];case 4:return[2]}})})})}function fe(t){var r=this,e=I(t,{returnValues:!0});return new P(function(n,o){return G(r,void 0,void 0,function(){var i,u,c,l;return b(this,function(a){switch(a.label){case 0:if(!e.length)return o(),[2,[]];u=!1,o.then(function(){i(),u=!0}),a.label=1;case 1:a.trys.push([1,,6,8]),a.label=2;case 2:return u?[3,5]:(Promise.all(e.map(function(f){return f.next()})).then(function(f){return i(f)},function(f){return o(f)}),[4,new Promise(function(f){return i=f})]);case 3:return c=a.sent(),c===void 0?[2]:(l=c.map(function(f){return f.value}),c.some(function(f){return f.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(f){return f.return&&f.return()}))];case 7:return a.sent(),[7];case 8:return[2]}})})})}function le(t){var r=this,e=I(t,{yieldValues:!0,returnValues:!0});return new P(function(n,o){return G(r,void 0,void 0,function(){var i,u,c,l,a,f=this;return b(this,function(h){switch(h.label){case 0:if(!e.length)return o(),[2,[]];u=[],c=!1,o.then(function(){var s,d;i();try{for(var p=E(u),y=p.next();!y.done;y=p.next()){var m=y.value;m()}}catch(C){s={error:C}}finally{try{y&&!y.done&&(d=p.return)&&d.call(p)}finally{if(s)throw s.error}}c=!0}),h.label=1;case 1:return h.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=h.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 h.sent(),[4,Promise.all(e.map(function(s,d){return G(f,void 0,void 0,function(){var p;return b(this,function(y){switch(y.label){case 0:if(l[d].done)return[2,l[d].value];y.label=1;case 1:return c?[3,4]:(Promise.resolve(s.next()).then(function(m){return u[d](m)},function(m){return o(m)}),[4,new Promise(function(m){return u[d]=m})]);case 2:return p=y.sent(),p===void 0?[2,l[d].value]:p.done?[2,p.value]:(a[d]=p.value,[4,n(a.slice())]);case 3:return y.sent(),[3,1];case 4:return[2]}})})}))];case 4:return[2,h.sent()];case 5:return o(),[4,Promise.all(e.map(function(s){return s.return&&s.return()}))];case 6:return h.sent(),[7];case 7:return[2]}})})})}var te=class{ajv_;graffiti;callbacks=new Set;options;login;logout;sessionEvents;postMedia;getMedia;deleteMedia;actorToHandle;handleToActor;get ajv(){return this.ajv_||(this.ajv_=(async()=>{let{default:r}=await import("./ajv-UZKI6BMI.js");return new r({strict:!1})})()),this.ajv_}constructor(r,e){this.options=e??{},this.graffiti=r,this.login=r.login.bind(r),this.logout=r.logout.bind(r),this.sessionEvents=r.sessionEvents,this.postMedia=r.postMedia.bind(r),this.getMedia=r.getMedia.bind(r),this.deleteMedia=r.deleteMedia.bind(r),this.actorToHandle=r.actorToHandle.bind(r),this.handleToActor=r.handleToActor.bind(r)}synchronize(r,e,n,o,i=new Set){let u=new P(async(c,l)=>{let a=he(await this.ajv,n),f=h=>{if(h?.tombstone)i.has(h.object.url)&&c(h);else if(h&&r(h.object)&&(this.options.omniscient||Y(h.object,o))){let s=JSON.parse(JSON.stringify(h.object));this.options.omniscient||(s=Z(s,e,o?.actor)),a(s)&&(c({object:s}),i.add(s.url))}};this.callbacks.add(f),await l,this.callbacks.delete(f)});return(async function*(){for await(let c of u)yield c})()}synchronizeDiscover(r,e,n){function o(i){return i.channels.some(u=>r.includes(u))}return this.synchronize(o,r,e,n)}synchronizeGet(r,e,n){let o=N(r);function i(u){return u.url===o}return this.synchronize(i,[],e,n,new Set([o]))}synchronizeAll(r,e){return this.synchronize(()=>!0,[],r,e)}async synchronizeDispatch(r,e=!1){for(let n of this.callbacks)n(r);e&&await new Promise(n=>setTimeout(n,0))}get=async(...r)=>{try{let e=await this.graffiti.get(...r);return this.synchronizeDispatch({object:e}),e}catch(e){throw e instanceof D&&this.synchronizeDispatch({tombstone:!0,object:{url:N(r[0])}}),e}};post=async(...r)=>{let e=await this.graffiti.post(...r);return await this.synchronizeDispatch({object:e},!0),e};delete=async(...r)=>{let e={tombstone:!0,object:{url:N(r[0])}};try{let n=await this.graffiti.delete(...r);return await this.synchronizeDispatch(e,!0),n}catch(n){throw n instanceof D&&await this.synchronizeDispatch(e,!0),n}};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:u=>e.objectStreamContinue(o(u)),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)};continueDiscover=(...r)=>{let e=this.graffiti.continueDiscover(...r);return this.objectStreamContinue(e)}};function he(t,r){try{return t.compile(r)}catch(e){throw new X(e instanceof Error?e.message:String(e))}}export{te 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/@graffiti-garden/api/src/4-utilities.ts", "../../node_modules/@repeaterjs/repeater/repeater.js"],
|
|
4
|
-
"sourcesContent": ["import type Ajv from \"ajv\";\nimport type {\n Graffiti,\n GraffitiSession,\n JSONSchema,\n GraffitiObjectBase,\n GraffitiObjectStream,\n GraffitiObjectStreamContinueEntry,\n GraffitiObjectStreamContinue,\n GraffitiObjectUrl,\n} from \"@graffiti-garden/api\";\nimport {\n GraffitiErrorNotFound,\n compileGraffitiObjectSchema,\n isActorAllowedGraffitiObject,\n maskGraffitiObject,\n unpackObjectUrl,\n} from \"@graffiti-garden/api\";\nimport { Repeater } from \"@repeaterjs/repeater\";\nexport type * from \"@graffiti-garden/api\";\n\nexport type GraffitiSynchronizeCallback = (\n object: 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 * [See a live example](/example).\n *\n * Specifically, this library provides the following *synchronize*\n * methods to correspond with each of the following Graffiti API methods:\n *\n * | API Method | Synchronize Method |\n * |------------|--------------------|\n * | {@link get} | {@link synchronizeGet} |\n * | {@link discover} | {@link synchronizeDiscover} |\n *\n * Whenever a change is made via {@link post} and {@link delete} or\n * received from {@link get}, {@link discover}, and {@link continueDiscover},\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 post}. 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 * Additionally, the library supplies a {@link synchronizeAll} method that can be used\n * to stream all the Graffiti changes that an application is aware of, which can be used\n * for caching or history building.\n *\n * The source code for this library is [available on GitHub](https://github.com/graffiti-garden/wrapper-synchronize/).\n *\n * @groupDescription 0 - Synchronize Methods\n * This group contains methods that listen for changes made via\n * {@link post}, and {@link delete} or fetched from\n * {@link get}, {@link discover}, or {@link continueDiscover} and then\n * streams appropriate changes to provide a responsive and consistent user experience.\n */\nexport class GraffitiSynchronize implements Graffiti {\n protected ajv_: Promise<Ajv> | undefined;\n protected readonly graffiti: Graffiti;\n protected readonly callbacks = new Set<GraffitiSynchronizeCallback>();\n protected readonly options: GraffitiSynchronizeOptions;\n\n login: Graffiti[\"login\"];\n logout: Graffiti[\"logout\"];\n sessionEvents: Graffiti[\"sessionEvents\"];\n postMedia: Graffiti[\"postMedia\"];\n getMedia: Graffiti[\"getMedia\"];\n deleteMedia: Graffiti[\"deleteMedia\"];\n actorToHandle: Graffiti[\"actorToHandle\"];\n handleToActor: Graffiti[\"handleToActor\"];\n\n protected 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 /**\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 this.options = options ?? {};\n this.graffiti = graffiti;\n this.login = graffiti.login.bind(graffiti);\n this.logout = graffiti.logout.bind(graffiti);\n this.sessionEvents = graffiti.sessionEvents;\n this.postMedia = graffiti.postMedia.bind(graffiti);\n this.getMedia = graffiti.getMedia.bind(graffiti);\n this.deleteMedia = graffiti.deleteMedia.bind(graffiti);\n this.actorToHandle = graffiti.actorToHandle.bind(graffiti);\n this.handleToActor = graffiti.handleToActor.bind(graffiti);\n }\n\n protected synchronize<Schema extends JSONSchema>(\n matchObject: (object: GraffitiObjectBase) => boolean,\n channels: string[],\n schema: Schema,\n session?: GraffitiSession | null,\n seenUrls: Set<string> = new Set<string>(),\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\n const repeater = new Repeater<GraffitiObjectStreamContinueEntry<Schema>>(\n async (push, stop) => {\n const validate = compileGraffitiObjectSchema(await this.ajv, schema);\n const callback: GraffitiSynchronizeCallback = (objectUpdate) => {\n if (objectUpdate?.tombstone) {\n if (seenUrls.has(objectUpdate.object.url)) {\n push(objectUpdate);\n }\n } else if (\n objectUpdate &&\n matchObject(objectUpdate.object) &&\n (this.options.omniscient ||\n isActorAllowedGraffitiObject(objectUpdate.object, session))\n ) {\n // Deep clone the object to prevent mutation\n const object = JSON.parse(\n JSON.stringify(objectUpdate.object),\n ) as GraffitiObjectBase;\n if (!this.options.omniscient) {\n maskGraffitiObject(object, channels, session);\n }\n if (validate(object)) {\n push({ object });\n seenUrls.add(object.url);\n }\n }\n };\n\n this.callbacks.add(callback);\n await stop;\n this.callbacks.delete(callback);\n },\n );\n\n return (async function* () {\n for await (const i of repeater) yield i;\n })();\n }\n\n /**\n * This method has the same signature as {@link discover} but listens for\n * changes made via {@link post} and {@link delete} or\n * fetched from {@link get}, {@link discover}, and {@link continueDiscover}\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 0 - Synchronize Methods\n */\n synchronizeDiscover<Schema extends JSONSchema>(\n channels: string[],\n schema: Schema,\n session?: GraffitiSession | null,\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\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 post}, and {@link delete} or\n * fetched from {@link get}, {@link discover}, and {@link continueDiscover} 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 0 - Synchronize Methods\n */\n synchronizeGet<Schema extends JSONSchema>(\n objectUrl: string | GraffitiObjectUrl,\n schema: Schema,\n session?: GraffitiSession | null | undefined,\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\n const url = unpackObjectUrl(objectUrl);\n function matchObject(object: GraffitiObjectBase) {\n return object.url === url;\n }\n return this.synchronize<Schema>(\n matchObject,\n [],\n schema,\n session,\n new Set<string>([url]),\n );\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 * @group 0 - Synchronize Methods\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 objectUpdate: GraffitiObjectStreamContinueEntry<{}>,\n waitForListeners = false,\n ) {\n for (const callback of this.callbacks) {\n callback(objectUpdate);\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 try {\n const object = await this.graffiti.get(...args);\n this.synchronizeDispatch({ object });\n return object;\n } catch (error) {\n if (error instanceof GraffitiErrorNotFound) {\n this.synchronizeDispatch({\n tombstone: true,\n object: { url: unpackObjectUrl(args[0]) },\n });\n }\n throw error;\n }\n };\n\n post: Graffiti[\"post\"] = async (...args) => {\n // @ts-ignore\n const object = await this.graffiti.post(...args);\n await this.synchronizeDispatch({ object }, true);\n return object;\n };\n\n delete: Graffiti[\"delete\"] = async (...args) => {\n const update = {\n tombstone: true,\n object: { url: unpackObjectUrl(args[0]) },\n } as const;\n try {\n const oldObject = await this.graffiti.delete(...args);\n await this.synchronizeDispatch(update, true);\n return oldObject;\n } catch (error) {\n if (error instanceof GraffitiErrorNotFound) {\n await this.synchronizeDispatch(update, true);\n }\n throw error;\n }\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: (session?: GraffitiSession | null) =>\n this_.objectStreamContinue<Schema>(continue_(session)),\n cursor,\n };\n }\n if (!result.value.error) {\n this_.synchronizeDispatch(result.value);\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 continueDiscover: Graffiti[\"continueDiscover\"] = (...args) => {\n const iterator = this.graffiti.continueDiscover(...args);\n return this.objectStreamContinue<{}>(iterator);\n };\n}\n", "import type {\n GraffitiObjectUrl,\n GraffitiObject,\n GraffitiObjectBase,\n GraffitiSession,\n GraffitiPostObject,\n GraffitiObjectStream,\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 applications,\n * from applications like Twitter, to Messenger, to Wikipedia, to many more new designs.\n * See the [Graffiti project website](https://graffiti.garden)\n * for links to example applications. Additionally, apps built on top\n * of the API interoperate with each other so you can seamlessly switch\n * between apps without losing your friends or data.\n *\n * These API 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 that data\u2014no server code necessary!\n *\n * The Typescript code for this API is [open source on Github](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-remote),\n * that lets people choose where their data is stored (you do not need to host your own server)\n * and a [local implementation](https://github.com/graffiti-garden/implementation-local)\n * that can be used for testing and development. Different implementations can\n * be swapped-in in the future without changing the API or any of the apps built on\n * top of it. In fact, we're working on an end-to-end encrypted version now!\n * [Follow Theia on BlueSky for updates](https://bsky.app/profile/theias.place).\n *\n * On the other side of the stack, there is [Vue plugin](https://vue.graffiti.garden/variables/GraffitiPlugin.html)\n * that wraps around this API to provide reactivity. Other plugin frameworks\n * and high-level libraries will be available in the future.\n *\n * ## API Overview\n *\n * The Graffiti API provides applications with methods for {@link login} and {@link logout},\n * methods to interact with data objects using standard database operations ({@link post}, {@link get}, and {@link delete}),\n * and a method to {@link discover} data objects created by others.\n * These data objects have a couple structured properties:\n * - {@link GraffitiObjectBase.url | `url`} (string): A globally unique identifier and locator for the object.\n * - {@link GraffitiObjectBase.actor | `actor`} (string): An unforgeable identifier for the creator of the object.\n * - {@link GraffitiObjectBase.allowed | `allowed`} (string[] | undefined): An array of the actors who are allowed to access the object (undefined for public objects).\n * - {@link GraffitiObjectBase.channels | `channels`} (string[]): An array of the *contexts* in which the object should appear.\n *\n * All other data is stored in the object's unstructured {@link GraffitiObjectBase.value | `value`} property.\n * This data can be used to represent social artifacts (e.g. posts, profiles) and activities (e.g. likes, follows).\n * For example, a post might have the value:\n\n * ```js\n * {\n * title: \"My First Post\",\n * content: \"Hello, world!\",\n * published: 1630483200000\n * }\n * ```\n *\n * a profile might have the value:\n *\n * ```js\n * {\n * name: \"Theia Henderson\",\n * pronouns: \"she/her\",\n * describes: \"did:web:theias.place\" // Theia's actor ID\n * }\n * ```\n *\n * and a \"Like\" might have the value:\n *\n * ```js\n * {\n * activity: \"Like\",\n * target: \"graffiti:remote:pod.graffiti.garden/12345\" // The URL of the graffiti object being liked\n * }\n * ```\n *\n * New social artifacts and activities can be easily created, simply\n * by creating new objects with appropriate properties. Despite the lack of\n * structure, we expect Graffiti object properties to adhere to a \"[folksonomy](https://en.wikipedia.org/wiki/Folksonomy)\",\n * similar to hashtags. Any string can be used as a hashtag on Twitter,\n * but there is social value in using the same hashtags at other people and\n * so a structure naturally emerges. Similarly, Graffiti objects\n * can have arbitrary properties but if people use the same properties as each other,\n * their apps will interoperate, which has social value.\n *\n * For a more complete and detailed overview of Graffiti's design, please\n * refer to [this section of the Graffiti paper](https://dl.acm.org/doi/10.1145/3746059.3747627#sec-3),\n * published in ACM UIST 2025. The paper also overviews {@link GraffitiObjectBase.channels | `channels`},\n * which are Graffiti's means of organizing data contextually, and a concept called \"total reification\",\n * which handles explains how moderation, collaboration, and other interactions are managed.\n *\n * @groupDescription 1 - Single-Object Methods\n * Methods for {@link post | creating}, {@link get | reading},\n * and {@link delete | deleting} {@link GraffitiObjectBase | Graffiti objects}.\n * @groupDescription 2 - Multi-Object Methods\n * Methods that retrieve or accumulate information about multiple {@link GraffitiObjectBase | Graffiti objects} at a time.\n * @groupDescription 3 - Media Methods\n * Methods for {@link postMedia | creating}, {@link getMedia | reading},\n * and {@link deleteMedia | deleting} media data.\n * @groupDescription 4 - Identity Methods\n * Methods and properties for logging in and out.\n */\nexport abstract class Graffiti {\n /**\n * Creates a new {@link GraffitiObjectBase | object}.\n *\n * @returns Returns the object that has been posted, complete with its\n * assigned {@link GraffitiObjectBase.url | `url`} and\n * {@link GraffitiObjectBase.actor | `actor`}.\n *\n * @group 1 - Single-Object Methods\n */\n abstract post<Schema extends JSONSchema>(\n /**\n * An object to post, minus its {@link GraffitiObjectBase.url | `url`} and\n * {@link GraffitiObjectBase.actor | `actor`}, which will be assigned once posted.\n * 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. It is recommended to use a schema to\n * ensure that the posted object matches subsequent {@link get} or {@link discover}\n * methods.\n */\n partialObject: GraffitiPostObject<Schema>,\n /**\n * An implementation-specific object with information to authenticate the\n * {@link GraffitiObjectBase.actor | `actor`}.\n */\n session: GraffitiSession,\n ): Promise<GraffitiObject<Schema>>;\n\n /**\n * Retrieves an object from a given {@link GraffitiObjectBase.url | `url`} matching\n * the provided `schema`.\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 email.\n *\n * @returns Returns the retrieved object.\n *\n * @throws {@link GraffitiErrorNotFound} if the object does not exist, has been deleted, or the actor 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 1 - Single-Object 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 * Deletes an object from a given {@link GraffitiObjectBase.url | `url`}\n * that had previously been {@link post | `post`ed}.\n * The deleting {@link GraffitiObjectBase.actor | `actor`} must be the same as the\n * `actor` that created the object.\n *\n * @throws {@link GraffitiErrorNotFound} if the object does not exist, has already been deleted,\n * or the actor 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 1 - Single-Object 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<void>;\n\n /**\n * Discovers objects created by any actor 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 querying {@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 *\n * @returns Returns a stream of objects that match the given {@link GraffitiObjectBase.channels | `channels`}\n * and [JSON Schema](https://json-schema.org).\n *\n * @group 2 - Multi-Object 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 * Continues a {@link GraffitiObjectStream} from a given\n * {@link GraffitiObjectStreamReturn.cursor | `cursor`} string.\n * The continuation will return new objects that have been {@link post | `post`ed}\n * that match the original stream, and also returns the\n * {@link GraffitiObjectBase.url | `url`}s of objects that\n * have been {@link delete | `delete`d}, as marked by a `tombstone`.\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 2 - Multi-Object Methods\n */\n abstract continueDiscover(\n cursor: string,\n session?: GraffitiSession | null,\n ): GraffitiObjectStreamContinue<{}>;\n\n /**\n * Uploads media data, such as an image or video.\n *\n * Unlike structured {@link GraffitiObjectBase | objects},\n * media is not indexed for {@link discover | `discover`y} and\n * must be retrieved by its exact URL using {@link getMedia}\n *\n * @returns The URL that the media was posted to.\n *\n * @group 3 - Media Methods\n */\n abstract postMedia(\n media: {\n /**\n * The binary data of the media to be uploaded,\n * along with its [media type](https://www.iana.org/assignments/media-types/media-types.xhtml),\n * formatted as a [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob).\n */\n data: Blob;\n /**\n * An optional list, identical in function to an object's\n * {@link GraffitiObjectBase.allowed | `allowed`} property,\n * that specifies the {@link GraffitiObjectBase.actor | `actor`}s\n * who are allowed to access the media. If the list is `undefined`\n * or `null`, anyone with the URL can access the media. If the list\n * is empty, only the {@link GraffitiObjectBase.actor | `actor`}\n * who {@link postMedia | `post`ed} the media can access it.\n */\n allowed?: string[] | null;\n },\n /**\n * An implementation-specific object with information to authenticate the\n * {@link GraffitiObjectBase.actor | `actor`}.\n */\n session: GraffitiSession,\n ): Promise<string>;\n\n /**\n * Deletes media previously {@link postMedia | `post`ed} to a given URL.\n *\n * @throws {@link GraffitiErrorNotFound} if no media at that URL exists.\n *\n * @throws {@link GraffitiErrorForbidden} if the {@link GraffitiObjectBase.actor | `actor`}\n * provided in the `session` is not the same as the `actor` that {@link postMedia | `post`ed}\n * the media.\n *\n * @group 3 - Media Methods\n */\n abstract deleteMedia(\n /**\n * A globally unique identifier and locator for the media.\n */\n mediaUrl: string,\n /**\n * An implementation-specific object with information to authenticate the\n * {@link GraffitiObjectBase.actor | `actor`}.\n */\n session: GraffitiSession,\n ): Promise<void>;\n\n /**\n * Retrieves media from the given media URL, adhering to the given requirements.\n *\n * @throws {@link GraffitiErrorNotFound} if no media at that URL exists.\n *\n * @throws {@link GraffitiErrorTooLarge} if the media exceeds the given `maxBytes`.\n *\n * @throws {@link GraffitiErrorNotAcceptable} if the media does not match the given\n * `accept` specification.\n *\n * @returns The URL of the retrieved media, as a [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob)\n * and the {@link GraffitiObjectBase.actor | `actor`} that posted it.\n *\n * @group 3 - Media Methods\n */\n abstract getMedia(\n /**\n * A globally unique identifier and locator for the media.\n */\n mediaUrl: string,\n /**\n * A set of requirements the retrieved media must meet.\n */\n requirements: {\n /**\n * A list of acceptable media types for the retrieved media,\n * formatted as like an [HTTP Accept header](https://httpwg.org/specs/rfc9110.html#field.accept)\n */\n accept?: string;\n /**\n * The maximum acceptable size, in bytes, of the media.\n */\n maxBytes?: number;\n },\n /**\n * An implementation-specific object with information to authenticate the\n * {@link GraffitiObjectBase.actor | `actor`}.\n */\n session?: GraffitiSession | null,\n ): Promise<{\n data: Blob;\n actor: string;\n allowed?: string[] | null;\n }>;\n\n /**\n * Begins the login process. Depending on the implementation, this may\n * involve redirecting to a login page or opening a popup,\n * so it should always be called in response to a gesture, such as clicking\n * a button, due to the [feature-gating browser security feature](https://developer.mozilla.org/en-US/docs/Web/Security/User_activation).\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 4 - Identity Methods\n */\n abstract login(\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 ): Promise<void>;\n\n /**\n * Begins the logout process for a particular {@link GraffitiSession | session}. 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 gesture, such as clicking\n * a button, due to the [feature-gating browser security feature](https://developer.mozilla.org/en-US/docs/Web/Security/User_activation).\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 4 - Identity Methods\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 their corresponding event types:\n * - `login` - {@link GraffitiLoginEvent}\n * - `logout` - {@link GraffitiLogoutEvent}\n * - `initialized` - {@link GraffitiSessionInitializedEvent}\n *\n * @group 4 - Identity Methods\n */\n abstract readonly sessionEvents: EventTarget;\n\n /**\n * Retrieves the human-readable handle associated\n * with the given actor. The handle may change over time\n * and so it should be used for display purposes only.\n *\n * The inverse of {@link handleToActor}.\n *\n * @throws {@link GraffitiErrorNotFound} if a handle cannot be\n * found for the given actor.\n *\n * @returns A human-readable handle for the given actor.\n *\n * @group 4 - Identity Methods\n */\n abstract actorToHandle(actor: string): Promise<string>;\n\n /**\n * Retrieves the actor ID associated with the given handle.\n *\n * The inverse of {@link actorToHandle}.\n *\n * @throws {@link GraffitiErrorNotFound} if there is no actor\n * with the given handle.\n *\n * @returns The actor ID for the given handle.\n *\n * @group 4 - Identity Methods\n */\n abstract handleToActor(handle: string): Promise<string>;\n}\n", "import type { JSONSchema, FromSchema } from \"json-schema-to-ts\";\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 *\n * Each object embeds the {@link actor | `actor`} that created it.\n * Object content and metadata are static but an object may be deleted by\n * its creating {@link actor | `actor`}.\n *\n * An object's content is stored in its {@link value | `value`} property, which can be any JSON\n * object. However, it is recommended to use 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 * Each object is globally addressable via its {@link url | `url`}.\n *\n * An object's {@link channels | `channels`} and {@link allowed | `allowed`} properties\n * are set by an objects creator to shape the visibility of and access to their object.\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 actor's own {@link actor | `actor`} URI. Posting an object to this channel is a way to broadcast\n * the object to the actor's followers, like posting a tweet.\n * - The URL of a Graffiti post. Posting an object to this channel is a way to broadcast to anyone viewing\n * the post, like commenting on a tweet.\n * - A URI representing a topic. Posting an object to 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 actors other than the creator, like\n * a BCC email. An actor 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 post their object to 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.post | created } the object.\n * This `actor` has the unique permission to\n * {@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 *\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 [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/**\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 GraffitiPostObjectJSONSchema>;\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 },\n additionalProperties: false,\n required: [\"value\", \"channels\", \"actor\", \"url\"],\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 applications can call\n * {@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 must be constructed locally before calling {@link Graffiti.post}.\n * This local copy ignores system-generated properties\n * ({@link GraffitiObjectBase.url | `url`} and {@link GraffitiObjectBase.actor | `actor`}),\n * 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 */\nexport type GraffitiPostObject<Schema extends JSONSchema> = Pick<\n GraffitiObjectBase,\n \"value\" | \"channels\" | \"allowed\"\n> &\n FromSchema<Schema & typeof GraffitiPostObjectJSONSchema>;\n\n/**\n * A JSON Schema equivalent to the {@link GraffitiPostObject} type.\n * Needed internally for type inference of JSON Schemas, but can\n * be used by implementations to validate objects.\n */\nexport const GraffitiPostObjectJSONSchema = {\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 authenticate a particular {@link GraffitiObjectBase.actor | `actor`}.\n * This object is required of all {@link Graffiti} methods\n * that modify objects or media 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 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 people 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 *\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`} to authenticate with.\n */\n actor: string;\n}\n\n/**\n * A stream of data that are returned by {@link Graffiti.discover}.\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 GraffitiObjectStreamError}.\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 GraffitiObjectStreamError | GraffitiObjectStreamEntry<Schema>,\n GraffitiObjectStreamReturn<Schema>\n>;\n\n/**\n * An error that can occur in a {@link GraffitiObjectStream}.\n *\n * @internal\n */\nexport interface GraffitiObjectStreamError {\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 GraffitiObjectStreamError}\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 actor's privacy.\n *\n * @internal\n */\nexport interface GraffitiObjectStreamContinueTombstone {\n /**\n * Empty property for compatibility with {@link GraffitiObjectStreamError}\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 an actor's privacy.\n */\n object: {\n /**\n * The {@link GraffitiObjectBase.url | `url`} of the deleted object.\n */\n url: string;\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 person\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: (\n session?: GraffitiSession | null,\n ) => 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.continueDiscover} 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.continueDiscover}.\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 GraffitiObjectStreamError | GraffitiObjectStreamContinueEntry<Schema>,\n GraffitiObjectStreamReturn<Schema>\n >;\n\n/**\n * The event type produced in {@link Graffiti.sessionEvents}\n * when a actor 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 actor 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 that originated a login request,\n * 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 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 GraffitiErrorTooLarge extends Error {\n constructor(message?: string) {\n super(message);\n this.name = \"GraffitiErrorTooLarge\";\n Object.setPrototypeOf(this, GraffitiErrorTooLarge.prototype);\n }\n}\n\nexport class GraffitiErrorNotAcceptable extends Error {\n constructor(message?: string) {\n super(message);\n this.name = \"GraffitiErrorNotAcceptable\";\n Object.setPrototypeOf(this, GraffitiErrorNotAcceptable.prototype);\n }\n}\n", "import type { JSONSchema } from \"json-schema-to-ts\";\nimport type { Ajv } from \"ajv\";\nimport { GraffitiErrorInvalidSchema } from \"./3-errors\";\nimport type {\n GraffitiObjectBase,\n GraffitiObject,\n GraffitiObjectUrl,\n GraffitiSession,\n} from \"./2-types\";\n\nexport function unpackObjectUrl(url: string | GraffitiObjectUrl) {\n return typeof url === \"string\" ? url : url.url;\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 isActorAllowedGraffitiObject(\n object: GraffitiObjectBase,\n session?: GraffitiSession | null,\n) {\n return (\n // If there is no allowed list, the actor is allowed.\n !Array.isArray(object.allowed) ||\n // Otherwise...\n (typeof session?.actor === \"string\" &&\n // The actor must be the creator of the object\n (object.actor === session.actor ||\n // Or be on the allowed list\n object.allowed.includes(session.actor)))\n );\n}\n\nexport function maskGraffitiObject(\n object: GraffitiObjectBase,\n channels: string[],\n session?: GraffitiSession | null,\n): void {\n // If the actor is not the creator, mask the object.\n if (object.actor !== session?.actor) {\n // If there is an allowed list, mask it to only include the actor\n // (This assumes the actor is already allowed to access the object)\n object.allowed = object.allowed && session ? [session.actor] : undefined;\n // Mask the channels to only include the channels that are being queried\n object.channels = object.channels.filter((channel) =>\n channels.includes(channel),\n );\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"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["init_dirname", "init_buffer", "init_process", "init_dirname", "init_buffer", "init_process", "GraffitiObjectJSONSchema", "GraffitiPostObjectJSONSchema", "GraffitiErrorNotFound", "_GraffitiErrorNotFound", "message", "GraffitiErrorInvalidSchema", "_GraffitiErrorInvalidSchema", "unpackObjectUrl", "url", "
|
|
4
|
+
"sourcesContent": ["import type Ajv from \"ajv\";\nimport type {\n Graffiti,\n GraffitiSession,\n JSONSchema,\n GraffitiObjectBase,\n GraffitiObjectStream,\n GraffitiObjectStreamContinueEntry,\n GraffitiObjectStreamContinue,\n GraffitiObjectUrl,\n GraffitiObject,\n} from \"@graffiti-garden/api\";\nimport {\n GraffitiErrorInvalidSchema,\n GraffitiErrorNotFound,\n isActorAllowedGraffitiObject,\n maskGraffitiObject,\n unpackObjectUrl,\n} from \"@graffiti-garden/api\";\nimport { Repeater } from \"@repeaterjs/repeater\";\nexport type * from \"@graffiti-garden/api\";\n\nexport type GraffitiSynchronizeCallback = (\n object: 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 * [See a live example](/example).\n *\n * Specifically, this library provides the following *synchronize*\n * methods to correspond with each of the following Graffiti API methods:\n *\n * | API Method | Synchronize Method |\n * |------------|--------------------|\n * | {@link get} | {@link synchronizeGet} |\n * | {@link discover} | {@link synchronizeDiscover} |\n *\n * Whenever a change is made via {@link post} and {@link delete} or\n * received from {@link get}, {@link discover}, and {@link continueDiscover},\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 post}. 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 * Additionally, the library supplies a {@link synchronizeAll} method that can be used\n * to stream all the Graffiti changes that an application is aware of, which can be used\n * for caching or history building.\n *\n * The source code for this library is [available on GitHub](https://github.com/graffiti-garden/wrapper-synchronize/).\n *\n * @groupDescription 0 - Synchronize Methods\n * This group contains methods that listen for changes made via\n * {@link post}, and {@link delete} or fetched from\n * {@link get}, {@link discover}, or {@link continueDiscover} and then\n * streams appropriate changes to provide a responsive and consistent user experience.\n */\nexport class GraffitiSynchronize implements Graffiti {\n protected ajv_: Promise<Ajv> | undefined;\n protected readonly graffiti: Graffiti;\n protected readonly callbacks = new Set<GraffitiSynchronizeCallback>();\n protected readonly options: GraffitiSynchronizeOptions;\n\n login: Graffiti[\"login\"];\n logout: Graffiti[\"logout\"];\n sessionEvents: Graffiti[\"sessionEvents\"];\n postMedia: Graffiti[\"postMedia\"];\n getMedia: Graffiti[\"getMedia\"];\n deleteMedia: Graffiti[\"deleteMedia\"];\n actorToHandle: Graffiti[\"actorToHandle\"];\n handleToActor: Graffiti[\"handleToActor\"];\n\n protected 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 /**\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 this.options = options ?? {};\n this.graffiti = graffiti;\n this.login = graffiti.login.bind(graffiti);\n this.logout = graffiti.logout.bind(graffiti);\n this.sessionEvents = graffiti.sessionEvents;\n this.postMedia = graffiti.postMedia.bind(graffiti);\n this.getMedia = graffiti.getMedia.bind(graffiti);\n this.deleteMedia = graffiti.deleteMedia.bind(graffiti);\n this.actorToHandle = graffiti.actorToHandle.bind(graffiti);\n this.handleToActor = graffiti.handleToActor.bind(graffiti);\n }\n\n protected synchronize<Schema extends JSONSchema>(\n matchObject: (object: GraffitiObjectBase) => boolean,\n channels: string[],\n schema: Schema,\n session?: GraffitiSession | null,\n seenUrls: Set<string> = new Set<string>(),\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\n const repeater = new Repeater<GraffitiObjectStreamContinueEntry<Schema>>(\n async (push, stop) => {\n const validate = compileGraffitiObjectSchema(await this.ajv, schema);\n const callback: GraffitiSynchronizeCallback = (objectUpdate) => {\n if (objectUpdate?.tombstone) {\n if (seenUrls.has(objectUpdate.object.url)) {\n push(objectUpdate);\n }\n } else if (\n objectUpdate &&\n matchObject(objectUpdate.object) &&\n (this.options.omniscient ||\n isActorAllowedGraffitiObject(objectUpdate.object, session))\n ) {\n // Deep clone the object to prevent mutation\n let object = JSON.parse(\n JSON.stringify(objectUpdate.object),\n ) as GraffitiObjectBase;\n if (!this.options.omniscient) {\n object = maskGraffitiObject(object, channels, session?.actor);\n }\n if (validate(object)) {\n push({ object });\n seenUrls.add(object.url);\n }\n }\n };\n\n this.callbacks.add(callback);\n await stop;\n this.callbacks.delete(callback);\n },\n );\n\n return (async function* () {\n for await (const i of repeater) yield i;\n })();\n }\n\n /**\n * This method has the same signature as {@link discover} but listens for\n * changes made via {@link post} and {@link delete} or\n * fetched from {@link get}, {@link discover}, and {@link continueDiscover}\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 0 - Synchronize Methods\n */\n synchronizeDiscover<Schema extends JSONSchema>(\n channels: string[],\n schema: Schema,\n session?: GraffitiSession | null,\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\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 post}, and {@link delete} or\n * fetched from {@link get}, {@link discover}, and {@link continueDiscover} 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 0 - Synchronize Methods\n */\n synchronizeGet<Schema extends JSONSchema>(\n objectUrl: string | GraffitiObjectUrl,\n schema: Schema,\n session?: GraffitiSession | null | undefined,\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\n const url = unpackObjectUrl(objectUrl);\n function matchObject(object: GraffitiObjectBase) {\n return object.url === url;\n }\n return this.synchronize<Schema>(\n matchObject,\n [],\n schema,\n session,\n new Set<string>([url]),\n );\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 * @group 0 - Synchronize Methods\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 objectUpdate: GraffitiObjectStreamContinueEntry<{}>,\n waitForListeners = false,\n ) {\n for (const callback of this.callbacks) {\n callback(objectUpdate);\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 try {\n const object = await this.graffiti.get(...args);\n this.synchronizeDispatch({ object });\n return object;\n } catch (error) {\n if (error instanceof GraffitiErrorNotFound) {\n this.synchronizeDispatch({\n tombstone: true,\n object: { url: unpackObjectUrl(args[0]) },\n });\n }\n throw error;\n }\n };\n\n post: Graffiti[\"post\"] = async (...args) => {\n // @ts-ignore\n const object = await this.graffiti.post(...args);\n await this.synchronizeDispatch({ object }, true);\n return object;\n };\n\n delete: Graffiti[\"delete\"] = async (...args) => {\n const update = {\n tombstone: true,\n object: { url: unpackObjectUrl(args[0]) },\n } as const;\n try {\n const oldObject = await this.graffiti.delete(...args);\n await this.synchronizeDispatch(update, true);\n return oldObject;\n } catch (error) {\n if (error instanceof GraffitiErrorNotFound) {\n await this.synchronizeDispatch(update, true);\n }\n throw error;\n }\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: (session?: GraffitiSession | null) =>\n this_.objectStreamContinue<Schema>(continue_(session)),\n cursor,\n };\n }\n if (!result.value.error) {\n this_.synchronizeDispatch(result.value);\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 continueDiscover: Graffiti[\"continueDiscover\"] = (...args) => {\n const iterator = this.graffiti.continueDiscover(...args);\n return this.objectStreamContinue<{}>(iterator);\n };\n}\n\nfunction 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 : String(error),\n );\n }\n}\n", "import type {\n GraffitiObjectUrl,\n GraffitiObject,\n GraffitiObjectBase,\n GraffitiSession,\n GraffitiPostObject,\n GraffitiObjectStream,\n GraffitiObjectStreamContinue,\n GraffitiMedia,\n GraffitiPostMedia,\n GraffitiMediaAccept,\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 applications,\n * from applications like Twitter, to Messenger, to Wikipedia, to many more new designs.\n * See the [Graffiti project website](https://graffiti.garden)\n * for links to example applications. Additionally, apps built on top\n * of the API interoperate with each other so you can seamlessly switch\n * between apps without losing your friends or data.\n *\n * These API 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 that data\u2014no server code necessary!\n *\n * The Typescript code for this API is [open source on Github](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-remote),\n * that lets people choose where their data is stored (you do not need to host your own server)\n * and a [local implementation](https://github.com/graffiti-garden/implementation-local)\n * that can be used for testing and development. Different implementations can\n * be swapped-in in the future without changing the API or any of the apps built on\n * top of it. In fact, we're working on an end-to-end encrypted version now!\n * [Follow Theia on BlueSky for updates](https://bsky.app/profile/theias.place).\n *\n * On the other side of the stack, there is [Vue plugin](https://vue.graffiti.garden/variables/GraffitiPlugin.html)\n * that wraps around this API to provide reactivity. Other plugin frameworks\n * and high-level libraries will be available in the future.\n *\n * ## API Overview\n *\n * The Graffiti API provides applications with methods for {@link login} and {@link logout},\n * methods to interact with data objects using standard database operations ({@link post}, {@link get}, and {@link delete}),\n * and a method to {@link discover} data objects created by others.\n * These data objects have a couple structured properties:\n * - {@link GraffitiObjectBase.url | `url`} (string): A globally unique identifier and locator for the object.\n * - {@link GraffitiObjectBase.actor | `actor`} (string): An unforgeable identifier for the creator of the object.\n * - {@link GraffitiObjectBase.allowed | `allowed`} (string[] | undefined): An array of the actors who are allowed to access the object (undefined for public objects).\n * - {@link GraffitiObjectBase.channels | `channels`} (string[]): An array of the *contexts* in which the object should appear.\n *\n * All other data is stored in the object's unstructured {@link GraffitiObjectBase.value | `value`} property.\n * This data can be used to represent social artifacts (e.g. posts, profiles) and activities (e.g. likes, follows).\n * For example, a post might have the value:\n\n * ```js\n * {\n * title: \"My First Post\",\n * content: \"Hello, world!\",\n * published: 1630483200000\n * }\n * ```\n *\n * a profile might have the value:\n *\n * ```js\n * {\n * name: \"Theia Henderson\",\n * pronouns: \"she/her\",\n * describes: \"did:web:theias.place\" // Theia's actor ID\n * }\n * ```\n *\n * and a \"Like\" might have the value:\n *\n * ```js\n * {\n * activity: \"Like\",\n * target: \"graffiti:remote:pod.graffiti.garden/12345\" // The URL of the graffiti object being liked\n * }\n * ```\n *\n * New social artifacts and activities can be easily created, simply\n * by creating new objects with appropriate properties. Despite the lack of\n * structure, we expect Graffiti object properties to adhere to a \"[folksonomy](https://en.wikipedia.org/wiki/Folksonomy)\",\n * similar to hashtags. Any string can be used as a hashtag on Twitter,\n * but there is social value in using the same hashtags at other people and\n * so a structure naturally emerges. Similarly, Graffiti objects\n * can have arbitrary properties but if people use the same properties as each other,\n * their apps will interoperate, which has social value.\n *\n * For a more complete and detailed overview of Graffiti's design, please\n * refer to [this section of the Graffiti paper](https://dl.acm.org/doi/10.1145/3746059.3747627#sec-3),\n * published in ACM UIST 2025. The paper also overviews {@link GraffitiObjectBase.channels | `channels`},\n * which are Graffiti's means of organizing data contextually, and a concept called \"total reification\",\n * which handles explains how moderation, collaboration, and other interactions are managed.\n *\n * @groupDescription 1 - Single-Object Methods\n * Methods for {@link post | creating}, {@link get | reading},\n * and {@link delete | deleting} {@link GraffitiObjectBase | Graffiti objects}.\n * @groupDescription 2 - Multi-Object Methods\n * Methods that retrieve or accumulate information about multiple {@link GraffitiObjectBase | Graffiti objects} at a time.\n * @groupDescription 3 - Media Methods\n * Methods for {@link postMedia | creating}, {@link getMedia | reading},\n * and {@link deleteMedia | deleting} media data.\n * @groupDescription 4 - Identity Methods\n * Methods and properties for logging in and out.\n */\nexport abstract class Graffiti {\n /**\n * Creates a new {@link GraffitiObjectBase | object}.\n *\n * @returns Returns the object that has been posted, complete with its\n * assigned {@link GraffitiObjectBase.url | `url`} and\n * {@link GraffitiObjectBase.actor | `actor`}.\n *\n * @group 1 - Single-Object Methods\n */\n abstract post<Schema extends JSONSchema>(\n /**\n * An object to post, minus its {@link GraffitiObjectBase.url | `url`} and\n * {@link GraffitiObjectBase.actor | `actor`}, which will be assigned once posted.\n * 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. It is recommended to use a schema to\n * ensure that the posted object matches subsequent {@link get} or {@link discover}\n * methods.\n */\n partialObject: GraffitiPostObject<Schema>,\n /**\n * An implementation-specific object with information to authenticate the\n * {@link GraffitiObjectBase.actor | `actor`}.\n */\n session: GraffitiSession,\n ): Promise<GraffitiObject<Schema>>;\n\n /**\n * Retrieves an object from a given {@link GraffitiObjectBase.url | `url`} matching\n * the provided `schema`.\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 email.\n *\n * @returns Returns the retrieved object.\n *\n * @throws {@link GraffitiErrorNotFound} if the object does not exist, has been deleted, or the actor 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 * @throws {@link GraffitiErrorInvalidSchema} If an invalid schema is provided.\n *\n * @group 1 - Single-Object 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 * Deletes an object from a given {@link GraffitiObjectBase.url | `url`}\n * that had previously been {@link post | `post`ed}.\n * The deleting {@link GraffitiObjectBase.actor | `actor`} must be the same as the\n * `actor` that created the object.\n *\n * @throws {@link GraffitiErrorNotFound} if the object does not exist, has already been deleted,\n * or the actor 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 1 - Single-Object 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 actor 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 querying {@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 *\n * @throws {@link GraffitiErrorInvalidSchema} if an invalid schema is provided.\n * Discovery is lazy and will not throw until the iterator is consumed.\n *\n * @returns Returns a stream of objects that match the given {@link GraffitiObjectBase.channels | `channels`}\n * and [JSON Schema](https://json-schema.org).\n *\n * @group 2 - Multi-Object 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 * Continues a {@link GraffitiObjectStream} from a given\n * {@link GraffitiObjectStreamReturn.cursor | `cursor`} string.\n * The continuation will return new objects that have been {@link post | `post`ed}\n * that match the original stream, and also returns the\n * {@link GraffitiObjectBase.url | `url`}s of objects that\n * have been {@link delete | `delete`d}, as marked by a `tombstone`.\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 GraffitiErrorNotFound} upon iteration\n * if the cursor is invalid or expired.\n *\n * @throws {@link GraffitiErrorForbidden} upon iteration\n * 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 2 - Multi-Object Methods\n */\n abstract continueDiscover(\n cursor: string,\n session?: GraffitiSession | null,\n ): GraffitiObjectStreamContinue<{}>;\n\n /**\n * Uploads media data, such as an image or video.\n *\n * Unlike structured {@link GraffitiObjectBase | objects},\n * media is not indexed for {@link discover | `discover`y} and\n * must be retrieved by its exact URL using {@link getMedia}\n *\n * @returns The URL that the media was posted to.\n *\n * @group 3 - Media Methods\n */\n abstract postMedia(\n /**\n * The media data to upload, and optionally\n * an {@link GraffitiObjectBase.allowed | `allowed`}\n * list of actors that can view it.\n */\n media: GraffitiPostMedia,\n /**\n * An implementation-specific object with information to authenticate the\n * {@link GraffitiObjectBase.actor | `actor`}.\n */\n session: GraffitiSession,\n ): Promise<string>;\n\n /**\n * Deletes media previously {@link postMedia | `post`ed} to a given URL.\n *\n * @throws {@link GraffitiErrorNotFound} if no media at that URL exists.\n *\n * @throws {@link GraffitiErrorForbidden} if the {@link GraffitiObjectBase.actor | `actor`}\n * provided in the `session` is not the same as the `actor` that {@link postMedia | `post`ed}\n * the media.\n *\n * @group 3 - Media Methods\n */\n abstract deleteMedia(\n /**\n * A globally unique identifier and locator for the media.\n */\n url: string,\n /**\n * An implementation-specific object with information to authenticate the\n * {@link GraffitiObjectBase.actor | `actor`}.\n */\n session: GraffitiSession,\n ): Promise<void>;\n\n /**\n * Retrieves media from the given media URL, adhering to the given requirements.\n *\n * @throws {@link GraffitiErrorNotFound} if no media at that URL exists.\n *\n * @throws {@link GraffitiErrorTooLarge} if the media exceeds the given `maxBytes`.\n *\n * @throws {@link GraffitiErrorNotAcceptable} if the media does not match the given\n * `accept` specification.\n *\n * @returns The URL of the retrieved media, as a [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob)\n * and the {@link GraffitiObjectBase.actor | `actor`} that posted it.\n *\n * @group 3 - Media Methods\n */\n abstract getMedia(\n /**\n * A globally unique identifier and locator for the media.\n */\n mediaUrl: string,\n /**\n * A specification for what types and sizes of media are acceptable.\n */\n accept: GraffitiMediaAccept,\n /**\n * An implementation-specific object with information to authenticate the\n * {@link GraffitiObjectBase.actor | `actor`}.\n */\n session?: GraffitiSession | null,\n ): Promise<GraffitiMedia>;\n\n /**\n * Begins the login process. Depending on the implementation, this may\n * involve redirecting to a login page or opening a popup,\n * so it should always be called in response to a gesture, such as clicking\n * a button, due to the [feature-gating browser security feature](https://developer.mozilla.org/en-US/docs/Web/Security/User_activation).\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 4 - Identity Methods\n */\n abstract login(\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 ): Promise<void>;\n\n /**\n * Begins the logout process for a particular {@link GraffitiSession | session}. 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 gesture, such as clicking\n * a button, due to the [feature-gating browser security feature](https://developer.mozilla.org/en-US/docs/Web/Security/User_activation).\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 4 - Identity Methods\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 their corresponding event types:\n * - `login` - {@link GraffitiLoginEvent}\n * - `logout` - {@link GraffitiLogoutEvent}\n * - `initialized` - {@link GraffitiSessionInitializedEvent}\n *\n * @group 4 - Identity Methods\n */\n abstract readonly sessionEvents: EventTarget;\n\n /**\n * Retrieves the human-readable handle associated\n * with the given actor. The handle may change over time\n * and so it should be used for display purposes only.\n *\n * The inverse of {@link handleToActor}.\n *\n * @throws {@link GraffitiErrorNotFound} if a handle cannot be\n * found for the given actor.\n *\n * @returns A human-readable handle for the given actor.\n *\n * @group 4 - Identity Methods\n */\n abstract actorToHandle(actor: string): Promise<string>;\n\n /**\n * Retrieves the actor ID associated with the given handle.\n *\n * The inverse of {@link actorToHandle}.\n *\n * @throws {@link GraffitiErrorNotFound} if there is no actor\n * with the given handle.\n *\n * @returns The actor ID for the given handle.\n *\n * @group 4 - Identity Methods\n */\n abstract handleToActor(handle: string): Promise<string>;\n}\n", "import type { JSONSchema, FromSchema } from \"json-schema-to-ts\";\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 *\n * Each object embeds the {@link actor | `actor`} that created it.\n * Object content and metadata are static but an object may be deleted by\n * its creating {@link actor | `actor`}.\n *\n * An object's content is stored in its {@link value | `value`} property, which can be any JSON\n * object. However, it is recommended to use 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 * Each object is globally addressable via its {@link url | `url`}.\n *\n * An object's {@link channels | `channels`} and {@link allowed | `allowed`} properties\n * are set by an objects creator to shape the visibility of and access to their object.\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 actor's own {@link actor | `actor`} URI. Posting an object to this channel is a way to broadcast\n * the object to the actor's followers, like posting a tweet.\n * - The URL of a Graffiti post. Posting an object to this channel is a way to broadcast to anyone viewing\n * the post, like commenting on a tweet.\n * - A URI representing a topic. Posting an object to 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 actors other than the creator, like\n * a BCC email. An actor 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 post their object to 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.post | created } the object.\n * This `actor` has the unique permission to\n * {@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 *\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 [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/**\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 GraffitiPostObjectJSONSchema>;\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 },\n additionalProperties: false,\n required: [\"value\", \"channels\", \"actor\", \"url\"],\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 applications can call\n * {@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 must be constructed locally before calling {@link Graffiti.post}.\n * This local copy ignores system-generated properties\n * ({@link GraffitiObjectBase.url | `url`} and {@link GraffitiObjectBase.actor | `actor`}),\n * 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 */\nexport type GraffitiPostObject<Schema extends JSONSchema> = Pick<\n GraffitiObjectBase,\n \"value\" | \"channels\" | \"allowed\"\n> &\n FromSchema<Schema & typeof GraffitiPostObjectJSONSchema>;\n\n/**\n * A JSON Schema equivalent to the {@link GraffitiPostObject} type.\n * Needed internally for type inference of JSON Schemas, but can\n * be used by implementations to validate objects.\n */\nexport const GraffitiPostObjectJSONSchema = {\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 authenticate a particular {@link GraffitiObjectBase.actor | `actor`}.\n * This object is required of all {@link Graffiti} methods\n * that modify objects or media 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 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 people 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 *\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`} to authenticate with.\n */\n actor: string;\n}\n\n/**\n * A stream of data that are returned by {@link Graffiti.discover}.\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 GraffitiObjectStreamError}.\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 GraffitiObjectStreamError | GraffitiObjectStreamEntry<Schema>,\n GraffitiObjectStreamReturn<Schema>\n>;\n\n/**\n * An error that can occur in a {@link GraffitiObjectStream}.\n *\n * @internal\n */\nexport interface GraffitiObjectStreamError {\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 GraffitiObjectStreamError}\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 actor's privacy.\n *\n * @internal\n */\nexport interface GraffitiObjectStreamContinueTombstone {\n /**\n * Empty property for compatibility with {@link GraffitiObjectStreamError}\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 an actor's privacy.\n */\n object: {\n /**\n * The {@link GraffitiObjectBase.url | `url`} of the deleted object.\n */\n url: string;\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 person\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: (\n session?: GraffitiSession | null,\n ) => 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.continueDiscover} 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.continueDiscover}.\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 GraffitiObjectStreamError | GraffitiObjectStreamContinueEntry<Schema>,\n GraffitiObjectStreamReturn<Schema>\n >;\n\n/**\n * The event type produced in {@link Graffiti.sessionEvents}\n * when a actor 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?: GraffitiSession;\n }\n | {\n error?: undefined;\n session: GraffitiSession;\n }\n>;\n\n/**\n * The event type produced in {@link Graffiti.sessionEvents}\n * when a actor 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 that originated a login request,\n * 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\nexport type GraffitiMedia = {\n /**\n * The binary data of the media to be uploaded,\n * along with its [media type](https://www.iana.org/assignments/media-types/media-types.xhtml),\n * formatted as a [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob).\n */\n data: Blob;\n /**\n * The {@link GraffitiObjectBase.actor | `actor`} that\n * {@link Graffiti.postMedia | `post`ed} the media.\n */\n actor: string;\n /**\n * An optional list, identical in function to an object's\n * {@link GraffitiObjectBase.allowed | `allowed`} property,\n * that specifies the {@link GraffitiObjectBase.actor | `actor`}s\n * who are allowed to access the media. If the list is `undefined`\n * or `null`, anyone with the URL can access the media. If the list\n * is empty, only the {@link GraffitiObjectBase.actor | `actor`}\n * who {@link Graffiti.postMedia | `post`ed} the media can access it.\n */\n allowed?: string[] | null;\n};\n\nexport type GraffitiPostMedia = Pick<GraffitiMedia, \"data\" | \"allowed\">;\n\nexport type GraffitiMediaAccept = {\n /**\n * A list of acceptable media types for the retrieved media.\n * Each type in the list may be of the form `<type>/<subtype>`,\n * `<type>/*`, or `*/*`, just as types are formatted in\n * an [HTTP Accept header](https://httpwg.org/specs/rfc9110.html#field.accept).\n */\n types?: string[];\n /**\n * The maximum acceptable size, in bytes, of the media.\n */\n maxBytes?: number;\n};\n", "export 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 GraffitiErrorTooLarge extends Error {\n constructor(message?: string) {\n super(message);\n this.name = \"GraffitiErrorTooLarge\";\n Object.setPrototypeOf(this, GraffitiErrorTooLarge.prototype);\n }\n}\n\nexport class GraffitiErrorNotAcceptable extends Error {\n constructor(message?: string) {\n super(message);\n this.name = \"GraffitiErrorNotAcceptable\";\n Object.setPrototypeOf(this, GraffitiErrorNotAcceptable.prototype);\n }\n}\n", "import type {\n GraffitiObjectBase,\n GraffitiObjectUrl,\n GraffitiSession,\n} from \"./2-types\";\n\nexport function unpackObjectUrl(url: string | GraffitiObjectUrl) {\n return typeof url === \"string\" ? url : url.url;\n}\n\nexport function isActorAllowedGraffitiObject(\n object: GraffitiObjectBase,\n session?: GraffitiSession | null,\n) {\n return (\n // If there is no allowed list, the actor is allowed.\n !Array.isArray(object.allowed) ||\n // Otherwise...\n (typeof session?.actor === \"string\" &&\n // The actor must be the creator of the object\n (object.actor === session.actor ||\n // Or be on the allowed list\n object.allowed.includes(session.actor)))\n );\n}\n\nexport function maskGraffitiObject(\n object: GraffitiObjectBase,\n channels: string[],\n actor?: string | null,\n): GraffitiObjectBase {\n // If the actor is the creator, return the object as is\n if (actor === object.actor) return object;\n\n // If there is an allowed list, mask it to only include the actor\n // (This assumes the actor is already allowed to access the object)\n const allowedMasked = object.allowed && actor ? [actor] : undefined;\n // Mask the channels to only include the channels that are being queried\n const channelsMasked = object.channels.filter((c) => channels.includes(c));\n\n return {\n ...object,\n allowed: allowedMasked,\n channels: channelsMasked,\n };\n}\n\nexport function isMediaAcceptable(\n mediaType: string,\n acceptableMediaTypes: string[],\n): boolean {\n const [type, subtype] = mediaType.toLowerCase().split(\";\")[0].split(\"/\");\n\n if (!type || !subtype) return false;\n\n return acceptableMediaTypes.some((acceptable) => {\n const [accType, accSubtype] = acceptable\n .toLowerCase()\n .split(\";\")[0]\n .split(\"/\");\n\n if (!accType || !accSubtype) return false;\n\n return (\n (accType === type || accType === \"*\") &&\n (accSubtype === subtype || accSubtype === \"*\")\n );\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"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["init_dirname", "init_buffer", "init_process", "init_dirname", "init_buffer", "init_process", "GraffitiObjectJSONSchema", "GraffitiPostObjectJSONSchema", "GraffitiErrorNotFound", "_GraffitiErrorNotFound", "message", "GraffitiErrorInvalidSchema", "_GraffitiErrorInvalidSchema", "unpackObjectUrl", "url", "isActorAllowedGraffitiObject", "object", "session", "maskGraffitiObject", "channels", "actor", "allowedMasked", "channelsMasked", "c", "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", "GraffitiSynchronize", "Ajv", "graffiti", "options", "matchObject", "channels", "schema", "session", "seenUrls", "repeater", "Repeater", "push", "stop", "validate", "compileGraffitiObjectSchema", "callback", "objectUpdate", "y", "object", "j", "i", "channel", "objectUrl", "url", "h", "waitForListeners", "resolve", "args", "error", "f", "update", "oldObject", "iterator", "this_", "result", "continue_", "cursor", "wrapped", "ajv", "m"]
|
|
7
7
|
}
|
package/dist/cjs/index.js
CHANGED
|
@@ -75,18 +75,18 @@ class GraffitiSynchronize {
|
|
|
75
75
|
synchronize(matchObject, channels, schema, session, seenUrls = /* @__PURE__ */ new Set()) {
|
|
76
76
|
const repeater = new import_repeater.Repeater(
|
|
77
77
|
async (push, stop) => {
|
|
78
|
-
const validate =
|
|
78
|
+
const validate = compileGraffitiObjectSchema(await this.ajv, schema);
|
|
79
79
|
const callback = (objectUpdate) => {
|
|
80
80
|
if (objectUpdate?.tombstone) {
|
|
81
81
|
if (seenUrls.has(objectUpdate.object.url)) {
|
|
82
82
|
push(objectUpdate);
|
|
83
83
|
}
|
|
84
84
|
} else if (objectUpdate && matchObject(objectUpdate.object) && (this.options.omniscient || (0, import_api.isActorAllowedGraffitiObject)(objectUpdate.object, session))) {
|
|
85
|
-
|
|
85
|
+
let object = JSON.parse(
|
|
86
86
|
JSON.stringify(objectUpdate.object)
|
|
87
87
|
);
|
|
88
88
|
if (!this.options.omniscient) {
|
|
89
|
-
(0, import_api.maskGraffitiObject)(object, channels, session);
|
|
89
|
+
object = (0, import_api.maskGraffitiObject)(object, channels, session?.actor);
|
|
90
90
|
}
|
|
91
91
|
if (validate(object)) {
|
|
92
92
|
push({ object });
|
|
@@ -244,4 +244,13 @@ class GraffitiSynchronize {
|
|
|
244
244
|
return this.objectStreamContinue(iterator);
|
|
245
245
|
};
|
|
246
246
|
}
|
|
247
|
+
function compileGraffitiObjectSchema(ajv, schema) {
|
|
248
|
+
try {
|
|
249
|
+
return ajv.compile(schema);
|
|
250
|
+
} catch (error) {
|
|
251
|
+
throw new import_api.GraffitiErrorInvalidSchema(
|
|
252
|
+
error instanceof Error ? error.message : String(error)
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
247
256
|
//# sourceMappingURL=index.js.map
|
package/dist/cjs/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/index.ts"],
|
|
4
|
-
"sourcesContent": ["import type Ajv from \"ajv\";\nimport type {\n Graffiti,\n GraffitiSession,\n JSONSchema,\n GraffitiObjectBase,\n GraffitiObjectStream,\n GraffitiObjectStreamContinueEntry,\n GraffitiObjectStreamContinue,\n GraffitiObjectUrl,\n} from \"@graffiti-garden/api\";\nimport {\n GraffitiErrorNotFound,\n compileGraffitiObjectSchema,\n isActorAllowedGraffitiObject,\n maskGraffitiObject,\n unpackObjectUrl,\n} from \"@graffiti-garden/api\";\nimport { Repeater } from \"@repeaterjs/repeater\";\nexport type * from \"@graffiti-garden/api\";\n\nexport type GraffitiSynchronizeCallback = (\n object: 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 * [See a live example](/example).\n *\n * Specifically, this library provides the following *synchronize*\n * methods to correspond with each of the following Graffiti API methods:\n *\n * | API Method | Synchronize Method |\n * |------------|--------------------|\n * | {@link get} | {@link synchronizeGet} |\n * | {@link discover} | {@link synchronizeDiscover} |\n *\n * Whenever a change is made via {@link post} and {@link delete} or\n * received from {@link get}, {@link discover}, and {@link continueDiscover},\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 post}. 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 * Additionally, the library supplies a {@link synchronizeAll} method that can be used\n * to stream all the Graffiti changes that an application is aware of, which can be used\n * for caching or history building.\n *\n * The source code for this library is [available on GitHub](https://github.com/graffiti-garden/wrapper-synchronize/).\n *\n * @groupDescription 0 - Synchronize Methods\n * This group contains methods that listen for changes made via\n * {@link post}, and {@link delete} or fetched from\n * {@link get}, {@link discover}, or {@link continueDiscover} and then\n * streams appropriate changes to provide a responsive and consistent user experience.\n */\nexport class GraffitiSynchronize implements Graffiti {\n protected ajv_: Promise<Ajv> | undefined;\n protected readonly graffiti: Graffiti;\n protected readonly callbacks = new Set<GraffitiSynchronizeCallback>();\n protected readonly options: GraffitiSynchronizeOptions;\n\n login: Graffiti[\"login\"];\n logout: Graffiti[\"logout\"];\n sessionEvents: Graffiti[\"sessionEvents\"];\n postMedia: Graffiti[\"postMedia\"];\n getMedia: Graffiti[\"getMedia\"];\n deleteMedia: Graffiti[\"deleteMedia\"];\n actorToHandle: Graffiti[\"actorToHandle\"];\n handleToActor: Graffiti[\"handleToActor\"];\n\n protected 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 /**\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 this.options = options ?? {};\n this.graffiti = graffiti;\n this.login = graffiti.login.bind(graffiti);\n this.logout = graffiti.logout.bind(graffiti);\n this.sessionEvents = graffiti.sessionEvents;\n this.postMedia = graffiti.postMedia.bind(graffiti);\n this.getMedia = graffiti.getMedia.bind(graffiti);\n this.deleteMedia = graffiti.deleteMedia.bind(graffiti);\n this.actorToHandle = graffiti.actorToHandle.bind(graffiti);\n this.handleToActor = graffiti.handleToActor.bind(graffiti);\n }\n\n protected synchronize<Schema extends JSONSchema>(\n matchObject: (object: GraffitiObjectBase) => boolean,\n channels: string[],\n schema: Schema,\n session?: GraffitiSession | null,\n seenUrls: Set<string> = new Set<string>(),\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\n const repeater = new Repeater<GraffitiObjectStreamContinueEntry<Schema>>(\n async (push, stop) => {\n const validate = compileGraffitiObjectSchema(await this.ajv, schema);\n const callback: GraffitiSynchronizeCallback = (objectUpdate) => {\n if (objectUpdate?.tombstone) {\n if (seenUrls.has(objectUpdate.object.url)) {\n push(objectUpdate);\n }\n } else if (\n objectUpdate &&\n matchObject(objectUpdate.object) &&\n (this.options.omniscient ||\n isActorAllowedGraffitiObject(objectUpdate.object, session))\n ) {\n // Deep clone the object to prevent mutation\n const object = JSON.parse(\n JSON.stringify(objectUpdate.object),\n ) as GraffitiObjectBase;\n if (!this.options.omniscient) {\n maskGraffitiObject(object, channels, session);\n }\n if (validate(object)) {\n push({ object });\n seenUrls.add(object.url);\n }\n }\n };\n\n this.callbacks.add(callback);\n await stop;\n this.callbacks.delete(callback);\n },\n );\n\n return (async function* () {\n for await (const i of repeater) yield i;\n })();\n }\n\n /**\n * This method has the same signature as {@link discover} but listens for\n * changes made via {@link post} and {@link delete} or\n * fetched from {@link get}, {@link discover}, and {@link continueDiscover}\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 0 - Synchronize Methods\n */\n synchronizeDiscover<Schema extends JSONSchema>(\n channels: string[],\n schema: Schema,\n session?: GraffitiSession | null,\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\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 post}, and {@link delete} or\n * fetched from {@link get}, {@link discover}, and {@link continueDiscover} 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 0 - Synchronize Methods\n */\n synchronizeGet<Schema extends JSONSchema>(\n objectUrl: string | GraffitiObjectUrl,\n schema: Schema,\n session?: GraffitiSession | null | undefined,\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\n const url = unpackObjectUrl(objectUrl);\n function matchObject(object: GraffitiObjectBase) {\n return object.url === url;\n }\n return this.synchronize<Schema>(\n matchObject,\n [],\n schema,\n session,\n new Set<string>([url]),\n );\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 * @group 0 - Synchronize Methods\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 objectUpdate: GraffitiObjectStreamContinueEntry<{}>,\n waitForListeners = false,\n ) {\n for (const callback of this.callbacks) {\n callback(objectUpdate);\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 try {\n const object = await this.graffiti.get(...args);\n this.synchronizeDispatch({ object });\n return object;\n } catch (error) {\n if (error instanceof GraffitiErrorNotFound) {\n this.synchronizeDispatch({\n tombstone: true,\n object: { url: unpackObjectUrl(args[0]) },\n });\n }\n throw error;\n }\n };\n\n post: Graffiti[\"post\"] = async (...args) => {\n // @ts-ignore\n const object = await this.graffiti.post(...args);\n await this.synchronizeDispatch({ object }, true);\n return object;\n };\n\n delete: Graffiti[\"delete\"] = async (...args) => {\n const update = {\n tombstone: true,\n object: { url: unpackObjectUrl(args[0]) },\n } as const;\n try {\n const oldObject = await this.graffiti.delete(...args);\n await this.synchronizeDispatch(update, true);\n return oldObject;\n } catch (error) {\n if (error instanceof GraffitiErrorNotFound) {\n await this.synchronizeDispatch(update, true);\n }\n throw error;\n }\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: (session?: GraffitiSession | null) =>\n this_.objectStreamContinue<Schema>(continue_(session)),\n cursor,\n };\n }\n if (!result.value.error) {\n this_.synchronizeDispatch(result.value);\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 continueDiscover: Graffiti[\"continueDiscover\"] = (...args) => {\n const iterator = this.graffiti.continueDiscover(...args);\n return this.objectStreamContinue<{}>(iterator);\n };\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
4
|
+
"sourcesContent": ["import type Ajv from \"ajv\";\nimport type {\n Graffiti,\n GraffitiSession,\n JSONSchema,\n GraffitiObjectBase,\n GraffitiObjectStream,\n GraffitiObjectStreamContinueEntry,\n GraffitiObjectStreamContinue,\n GraffitiObjectUrl,\n GraffitiObject,\n} from \"@graffiti-garden/api\";\nimport {\n GraffitiErrorInvalidSchema,\n GraffitiErrorNotFound,\n isActorAllowedGraffitiObject,\n maskGraffitiObject,\n unpackObjectUrl,\n} from \"@graffiti-garden/api\";\nimport { Repeater } from \"@repeaterjs/repeater\";\nexport type * from \"@graffiti-garden/api\";\n\nexport type GraffitiSynchronizeCallback = (\n object: 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 * [See a live example](/example).\n *\n * Specifically, this library provides the following *synchronize*\n * methods to correspond with each of the following Graffiti API methods:\n *\n * | API Method | Synchronize Method |\n * |------------|--------------------|\n * | {@link get} | {@link synchronizeGet} |\n * | {@link discover} | {@link synchronizeDiscover} |\n *\n * Whenever a change is made via {@link post} and {@link delete} or\n * received from {@link get}, {@link discover}, and {@link continueDiscover},\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 post}. 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 * Additionally, the library supplies a {@link synchronizeAll} method that can be used\n * to stream all the Graffiti changes that an application is aware of, which can be used\n * for caching or history building.\n *\n * The source code for this library is [available on GitHub](https://github.com/graffiti-garden/wrapper-synchronize/).\n *\n * @groupDescription 0 - Synchronize Methods\n * This group contains methods that listen for changes made via\n * {@link post}, and {@link delete} or fetched from\n * {@link get}, {@link discover}, or {@link continueDiscover} and then\n * streams appropriate changes to provide a responsive and consistent user experience.\n */\nexport class GraffitiSynchronize implements Graffiti {\n protected ajv_: Promise<Ajv> | undefined;\n protected readonly graffiti: Graffiti;\n protected readonly callbacks = new Set<GraffitiSynchronizeCallback>();\n protected readonly options: GraffitiSynchronizeOptions;\n\n login: Graffiti[\"login\"];\n logout: Graffiti[\"logout\"];\n sessionEvents: Graffiti[\"sessionEvents\"];\n postMedia: Graffiti[\"postMedia\"];\n getMedia: Graffiti[\"getMedia\"];\n deleteMedia: Graffiti[\"deleteMedia\"];\n actorToHandle: Graffiti[\"actorToHandle\"];\n handleToActor: Graffiti[\"handleToActor\"];\n\n protected 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 /**\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 this.options = options ?? {};\n this.graffiti = graffiti;\n this.login = graffiti.login.bind(graffiti);\n this.logout = graffiti.logout.bind(graffiti);\n this.sessionEvents = graffiti.sessionEvents;\n this.postMedia = graffiti.postMedia.bind(graffiti);\n this.getMedia = graffiti.getMedia.bind(graffiti);\n this.deleteMedia = graffiti.deleteMedia.bind(graffiti);\n this.actorToHandle = graffiti.actorToHandle.bind(graffiti);\n this.handleToActor = graffiti.handleToActor.bind(graffiti);\n }\n\n protected synchronize<Schema extends JSONSchema>(\n matchObject: (object: GraffitiObjectBase) => boolean,\n channels: string[],\n schema: Schema,\n session?: GraffitiSession | null,\n seenUrls: Set<string> = new Set<string>(),\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\n const repeater = new Repeater<GraffitiObjectStreamContinueEntry<Schema>>(\n async (push, stop) => {\n const validate = compileGraffitiObjectSchema(await this.ajv, schema);\n const callback: GraffitiSynchronizeCallback = (objectUpdate) => {\n if (objectUpdate?.tombstone) {\n if (seenUrls.has(objectUpdate.object.url)) {\n push(objectUpdate);\n }\n } else if (\n objectUpdate &&\n matchObject(objectUpdate.object) &&\n (this.options.omniscient ||\n isActorAllowedGraffitiObject(objectUpdate.object, session))\n ) {\n // Deep clone the object to prevent mutation\n let object = JSON.parse(\n JSON.stringify(objectUpdate.object),\n ) as GraffitiObjectBase;\n if (!this.options.omniscient) {\n object = maskGraffitiObject(object, channels, session?.actor);\n }\n if (validate(object)) {\n push({ object });\n seenUrls.add(object.url);\n }\n }\n };\n\n this.callbacks.add(callback);\n await stop;\n this.callbacks.delete(callback);\n },\n );\n\n return (async function* () {\n for await (const i of repeater) yield i;\n })();\n }\n\n /**\n * This method has the same signature as {@link discover} but listens for\n * changes made via {@link post} and {@link delete} or\n * fetched from {@link get}, {@link discover}, and {@link continueDiscover}\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 0 - Synchronize Methods\n */\n synchronizeDiscover<Schema extends JSONSchema>(\n channels: string[],\n schema: Schema,\n session?: GraffitiSession | null,\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\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 post}, and {@link delete} or\n * fetched from {@link get}, {@link discover}, and {@link continueDiscover} 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 0 - Synchronize Methods\n */\n synchronizeGet<Schema extends JSONSchema>(\n objectUrl: string | GraffitiObjectUrl,\n schema: Schema,\n session?: GraffitiSession | null | undefined,\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\n const url = unpackObjectUrl(objectUrl);\n function matchObject(object: GraffitiObjectBase) {\n return object.url === url;\n }\n return this.synchronize<Schema>(\n matchObject,\n [],\n schema,\n session,\n new Set<string>([url]),\n );\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 * @group 0 - Synchronize Methods\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 objectUpdate: GraffitiObjectStreamContinueEntry<{}>,\n waitForListeners = false,\n ) {\n for (const callback of this.callbacks) {\n callback(objectUpdate);\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 try {\n const object = await this.graffiti.get(...args);\n this.synchronizeDispatch({ object });\n return object;\n } catch (error) {\n if (error instanceof GraffitiErrorNotFound) {\n this.synchronizeDispatch({\n tombstone: true,\n object: { url: unpackObjectUrl(args[0]) },\n });\n }\n throw error;\n }\n };\n\n post: Graffiti[\"post\"] = async (...args) => {\n // @ts-ignore\n const object = await this.graffiti.post(...args);\n await this.synchronizeDispatch({ object }, true);\n return object;\n };\n\n delete: Graffiti[\"delete\"] = async (...args) => {\n const update = {\n tombstone: true,\n object: { url: unpackObjectUrl(args[0]) },\n } as const;\n try {\n const oldObject = await this.graffiti.delete(...args);\n await this.synchronizeDispatch(update, true);\n return oldObject;\n } catch (error) {\n if (error instanceof GraffitiErrorNotFound) {\n await this.synchronizeDispatch(update, true);\n }\n throw error;\n }\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: (session?: GraffitiSession | null) =>\n this_.objectStreamContinue<Schema>(continue_(session)),\n cursor,\n };\n }\n if (!result.value.error) {\n this_.synchronizeDispatch(result.value);\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 continueDiscover: Graffiti[\"continueDiscover\"] = (...args) => {\n const iterator = this.graffiti.continueDiscover(...args);\n return this.objectStreamContinue<{}>(iterator);\n };\n}\n\nfunction 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 : String(error),\n );\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/esm/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
|
+
GraffitiErrorInvalidSchema,
|
|
2
3
|
GraffitiErrorNotFound,
|
|
3
|
-
compileGraffitiObjectSchema,
|
|
4
4
|
isActorAllowedGraffitiObject,
|
|
5
5
|
maskGraffitiObject,
|
|
6
6
|
unpackObjectUrl
|
|
@@ -55,11 +55,11 @@ class GraffitiSynchronize {
|
|
|
55
55
|
push(objectUpdate);
|
|
56
56
|
}
|
|
57
57
|
} else if (objectUpdate && matchObject(objectUpdate.object) && (this.options.omniscient || isActorAllowedGraffitiObject(objectUpdate.object, session))) {
|
|
58
|
-
|
|
58
|
+
let object = JSON.parse(
|
|
59
59
|
JSON.stringify(objectUpdate.object)
|
|
60
60
|
);
|
|
61
61
|
if (!this.options.omniscient) {
|
|
62
|
-
maskGraffitiObject(object, channels, session);
|
|
62
|
+
object = maskGraffitiObject(object, channels, session?.actor);
|
|
63
63
|
}
|
|
64
64
|
if (validate(object)) {
|
|
65
65
|
push({ object });
|
|
@@ -217,6 +217,15 @@ class GraffitiSynchronize {
|
|
|
217
217
|
return this.objectStreamContinue(iterator);
|
|
218
218
|
};
|
|
219
219
|
}
|
|
220
|
+
function compileGraffitiObjectSchema(ajv, schema) {
|
|
221
|
+
try {
|
|
222
|
+
return ajv.compile(schema);
|
|
223
|
+
} catch (error) {
|
|
224
|
+
throw new GraffitiErrorInvalidSchema(
|
|
225
|
+
error instanceof Error ? error.message : String(error)
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
220
229
|
export {
|
|
221
230
|
GraffitiSynchronize
|
|
222
231
|
};
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/index.ts"],
|
|
4
|
-
"sourcesContent": ["import type Ajv from \"ajv\";\nimport type {\n Graffiti,\n GraffitiSession,\n JSONSchema,\n GraffitiObjectBase,\n GraffitiObjectStream,\n GraffitiObjectStreamContinueEntry,\n GraffitiObjectStreamContinue,\n GraffitiObjectUrl,\n} from \"@graffiti-garden/api\";\nimport {\n GraffitiErrorNotFound,\n compileGraffitiObjectSchema,\n isActorAllowedGraffitiObject,\n maskGraffitiObject,\n unpackObjectUrl,\n} from \"@graffiti-garden/api\";\nimport { Repeater } from \"@repeaterjs/repeater\";\nexport type * from \"@graffiti-garden/api\";\n\nexport type GraffitiSynchronizeCallback = (\n object: 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 * [See a live example](/example).\n *\n * Specifically, this library provides the following *synchronize*\n * methods to correspond with each of the following Graffiti API methods:\n *\n * | API Method | Synchronize Method |\n * |------------|--------------------|\n * | {@link get} | {@link synchronizeGet} |\n * | {@link discover} | {@link synchronizeDiscover} |\n *\n * Whenever a change is made via {@link post} and {@link delete} or\n * received from {@link get}, {@link discover}, and {@link continueDiscover},\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 post}. 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 * Additionally, the library supplies a {@link synchronizeAll} method that can be used\n * to stream all the Graffiti changes that an application is aware of, which can be used\n * for caching or history building.\n *\n * The source code for this library is [available on GitHub](https://github.com/graffiti-garden/wrapper-synchronize/).\n *\n * @groupDescription 0 - Synchronize Methods\n * This group contains methods that listen for changes made via\n * {@link post}, and {@link delete} or fetched from\n * {@link get}, {@link discover}, or {@link continueDiscover} and then\n * streams appropriate changes to provide a responsive and consistent user experience.\n */\nexport class GraffitiSynchronize implements Graffiti {\n protected ajv_: Promise<Ajv> | undefined;\n protected readonly graffiti: Graffiti;\n protected readonly callbacks = new Set<GraffitiSynchronizeCallback>();\n protected readonly options: GraffitiSynchronizeOptions;\n\n login: Graffiti[\"login\"];\n logout: Graffiti[\"logout\"];\n sessionEvents: Graffiti[\"sessionEvents\"];\n postMedia: Graffiti[\"postMedia\"];\n getMedia: Graffiti[\"getMedia\"];\n deleteMedia: Graffiti[\"deleteMedia\"];\n actorToHandle: Graffiti[\"actorToHandle\"];\n handleToActor: Graffiti[\"handleToActor\"];\n\n protected 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 /**\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 this.options = options ?? {};\n this.graffiti = graffiti;\n this.login = graffiti.login.bind(graffiti);\n this.logout = graffiti.logout.bind(graffiti);\n this.sessionEvents = graffiti.sessionEvents;\n this.postMedia = graffiti.postMedia.bind(graffiti);\n this.getMedia = graffiti.getMedia.bind(graffiti);\n this.deleteMedia = graffiti.deleteMedia.bind(graffiti);\n this.actorToHandle = graffiti.actorToHandle.bind(graffiti);\n this.handleToActor = graffiti.handleToActor.bind(graffiti);\n }\n\n protected synchronize<Schema extends JSONSchema>(\n matchObject: (object: GraffitiObjectBase) => boolean,\n channels: string[],\n schema: Schema,\n session?: GraffitiSession | null,\n seenUrls: Set<string> = new Set<string>(),\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\n const repeater = new Repeater<GraffitiObjectStreamContinueEntry<Schema>>(\n async (push, stop) => {\n const validate = compileGraffitiObjectSchema(await this.ajv, schema);\n const callback: GraffitiSynchronizeCallback = (objectUpdate) => {\n if (objectUpdate?.tombstone) {\n if (seenUrls.has(objectUpdate.object.url)) {\n push(objectUpdate);\n }\n } else if (\n objectUpdate &&\n matchObject(objectUpdate.object) &&\n (this.options.omniscient ||\n isActorAllowedGraffitiObject(objectUpdate.object, session))\n ) {\n // Deep clone the object to prevent mutation\n const object = JSON.parse(\n JSON.stringify(objectUpdate.object),\n ) as GraffitiObjectBase;\n if (!this.options.omniscient) {\n maskGraffitiObject(object, channels, session);\n }\n if (validate(object)) {\n push({ object });\n seenUrls.add(object.url);\n }\n }\n };\n\n this.callbacks.add(callback);\n await stop;\n this.callbacks.delete(callback);\n },\n );\n\n return (async function* () {\n for await (const i of repeater) yield i;\n })();\n }\n\n /**\n * This method has the same signature as {@link discover} but listens for\n * changes made via {@link post} and {@link delete} or\n * fetched from {@link get}, {@link discover}, and {@link continueDiscover}\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 0 - Synchronize Methods\n */\n synchronizeDiscover<Schema extends JSONSchema>(\n channels: string[],\n schema: Schema,\n session?: GraffitiSession | null,\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\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 post}, and {@link delete} or\n * fetched from {@link get}, {@link discover}, and {@link continueDiscover} 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 0 - Synchronize Methods\n */\n synchronizeGet<Schema extends JSONSchema>(\n objectUrl: string | GraffitiObjectUrl,\n schema: Schema,\n session?: GraffitiSession | null | undefined,\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\n const url = unpackObjectUrl(objectUrl);\n function matchObject(object: GraffitiObjectBase) {\n return object.url === url;\n }\n return this.synchronize<Schema>(\n matchObject,\n [],\n schema,\n session,\n new Set<string>([url]),\n );\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 * @group 0 - Synchronize Methods\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 objectUpdate: GraffitiObjectStreamContinueEntry<{}>,\n waitForListeners = false,\n ) {\n for (const callback of this.callbacks) {\n callback(objectUpdate);\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 try {\n const object = await this.graffiti.get(...args);\n this.synchronizeDispatch({ object });\n return object;\n } catch (error) {\n if (error instanceof GraffitiErrorNotFound) {\n this.synchronizeDispatch({\n tombstone: true,\n object: { url: unpackObjectUrl(args[0]) },\n });\n }\n throw error;\n }\n };\n\n post: Graffiti[\"post\"] = async (...args) => {\n // @ts-ignore\n const object = await this.graffiti.post(...args);\n await this.synchronizeDispatch({ object }, true);\n return object;\n };\n\n delete: Graffiti[\"delete\"] = async (...args) => {\n const update = {\n tombstone: true,\n object: { url: unpackObjectUrl(args[0]) },\n } as const;\n try {\n const oldObject = await this.graffiti.delete(...args);\n await this.synchronizeDispatch(update, true);\n return oldObject;\n } catch (error) {\n if (error instanceof GraffitiErrorNotFound) {\n await this.synchronizeDispatch(update, true);\n }\n throw error;\n }\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: (session?: GraffitiSession | null) =>\n this_.objectStreamContinue<Schema>(continue_(session)),\n cursor,\n };\n }\n if (!result.value.error) {\n this_.synchronizeDispatch(result.value);\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 continueDiscover: Graffiti[\"continueDiscover\"] = (...args) => {\n const iterator = this.graffiti.continueDiscover(...args);\n return this.objectStreamContinue<{}>(iterator);\n };\n}\n"],
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["import type Ajv from \"ajv\";\nimport type {\n Graffiti,\n GraffitiSession,\n JSONSchema,\n GraffitiObjectBase,\n GraffitiObjectStream,\n GraffitiObjectStreamContinueEntry,\n GraffitiObjectStreamContinue,\n GraffitiObjectUrl,\n GraffitiObject,\n} from \"@graffiti-garden/api\";\nimport {\n GraffitiErrorInvalidSchema,\n GraffitiErrorNotFound,\n isActorAllowedGraffitiObject,\n maskGraffitiObject,\n unpackObjectUrl,\n} from \"@graffiti-garden/api\";\nimport { Repeater } from \"@repeaterjs/repeater\";\nexport type * from \"@graffiti-garden/api\";\n\nexport type GraffitiSynchronizeCallback = (\n object: 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 * [See a live example](/example).\n *\n * Specifically, this library provides the following *synchronize*\n * methods to correspond with each of the following Graffiti API methods:\n *\n * | API Method | Synchronize Method |\n * |------------|--------------------|\n * | {@link get} | {@link synchronizeGet} |\n * | {@link discover} | {@link synchronizeDiscover} |\n *\n * Whenever a change is made via {@link post} and {@link delete} or\n * received from {@link get}, {@link discover}, and {@link continueDiscover},\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 post}. 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 * Additionally, the library supplies a {@link synchronizeAll} method that can be used\n * to stream all the Graffiti changes that an application is aware of, which can be used\n * for caching or history building.\n *\n * The source code for this library is [available on GitHub](https://github.com/graffiti-garden/wrapper-synchronize/).\n *\n * @groupDescription 0 - Synchronize Methods\n * This group contains methods that listen for changes made via\n * {@link post}, and {@link delete} or fetched from\n * {@link get}, {@link discover}, or {@link continueDiscover} and then\n * streams appropriate changes to provide a responsive and consistent user experience.\n */\nexport class GraffitiSynchronize implements Graffiti {\n protected ajv_: Promise<Ajv> | undefined;\n protected readonly graffiti: Graffiti;\n protected readonly callbacks = new Set<GraffitiSynchronizeCallback>();\n protected readonly options: GraffitiSynchronizeOptions;\n\n login: Graffiti[\"login\"];\n logout: Graffiti[\"logout\"];\n sessionEvents: Graffiti[\"sessionEvents\"];\n postMedia: Graffiti[\"postMedia\"];\n getMedia: Graffiti[\"getMedia\"];\n deleteMedia: Graffiti[\"deleteMedia\"];\n actorToHandle: Graffiti[\"actorToHandle\"];\n handleToActor: Graffiti[\"handleToActor\"];\n\n protected 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 /**\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 this.options = options ?? {};\n this.graffiti = graffiti;\n this.login = graffiti.login.bind(graffiti);\n this.logout = graffiti.logout.bind(graffiti);\n this.sessionEvents = graffiti.sessionEvents;\n this.postMedia = graffiti.postMedia.bind(graffiti);\n this.getMedia = graffiti.getMedia.bind(graffiti);\n this.deleteMedia = graffiti.deleteMedia.bind(graffiti);\n this.actorToHandle = graffiti.actorToHandle.bind(graffiti);\n this.handleToActor = graffiti.handleToActor.bind(graffiti);\n }\n\n protected synchronize<Schema extends JSONSchema>(\n matchObject: (object: GraffitiObjectBase) => boolean,\n channels: string[],\n schema: Schema,\n session?: GraffitiSession | null,\n seenUrls: Set<string> = new Set<string>(),\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\n const repeater = new Repeater<GraffitiObjectStreamContinueEntry<Schema>>(\n async (push, stop) => {\n const validate = compileGraffitiObjectSchema(await this.ajv, schema);\n const callback: GraffitiSynchronizeCallback = (objectUpdate) => {\n if (objectUpdate?.tombstone) {\n if (seenUrls.has(objectUpdate.object.url)) {\n push(objectUpdate);\n }\n } else if (\n objectUpdate &&\n matchObject(objectUpdate.object) &&\n (this.options.omniscient ||\n isActorAllowedGraffitiObject(objectUpdate.object, session))\n ) {\n // Deep clone the object to prevent mutation\n let object = JSON.parse(\n JSON.stringify(objectUpdate.object),\n ) as GraffitiObjectBase;\n if (!this.options.omniscient) {\n object = maskGraffitiObject(object, channels, session?.actor);\n }\n if (validate(object)) {\n push({ object });\n seenUrls.add(object.url);\n }\n }\n };\n\n this.callbacks.add(callback);\n await stop;\n this.callbacks.delete(callback);\n },\n );\n\n return (async function* () {\n for await (const i of repeater) yield i;\n })();\n }\n\n /**\n * This method has the same signature as {@link discover} but listens for\n * changes made via {@link post} and {@link delete} or\n * fetched from {@link get}, {@link discover}, and {@link continueDiscover}\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 0 - Synchronize Methods\n */\n synchronizeDiscover<Schema extends JSONSchema>(\n channels: string[],\n schema: Schema,\n session?: GraffitiSession | null,\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\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 post}, and {@link delete} or\n * fetched from {@link get}, {@link discover}, and {@link continueDiscover} 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 0 - Synchronize Methods\n */\n synchronizeGet<Schema extends JSONSchema>(\n objectUrl: string | GraffitiObjectUrl,\n schema: Schema,\n session?: GraffitiSession | null | undefined,\n ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {\n const url = unpackObjectUrl(objectUrl);\n function matchObject(object: GraffitiObjectBase) {\n return object.url === url;\n }\n return this.synchronize<Schema>(\n matchObject,\n [],\n schema,\n session,\n new Set<string>([url]),\n );\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 * @group 0 - Synchronize Methods\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 objectUpdate: GraffitiObjectStreamContinueEntry<{}>,\n waitForListeners = false,\n ) {\n for (const callback of this.callbacks) {\n callback(objectUpdate);\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 try {\n const object = await this.graffiti.get(...args);\n this.synchronizeDispatch({ object });\n return object;\n } catch (error) {\n if (error instanceof GraffitiErrorNotFound) {\n this.synchronizeDispatch({\n tombstone: true,\n object: { url: unpackObjectUrl(args[0]) },\n });\n }\n throw error;\n }\n };\n\n post: Graffiti[\"post\"] = async (...args) => {\n // @ts-ignore\n const object = await this.graffiti.post(...args);\n await this.synchronizeDispatch({ object }, true);\n return object;\n };\n\n delete: Graffiti[\"delete\"] = async (...args) => {\n const update = {\n tombstone: true,\n object: { url: unpackObjectUrl(args[0]) },\n } as const;\n try {\n const oldObject = await this.graffiti.delete(...args);\n await this.synchronizeDispatch(update, true);\n return oldObject;\n } catch (error) {\n if (error instanceof GraffitiErrorNotFound) {\n await this.synchronizeDispatch(update, true);\n }\n throw error;\n }\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: (session?: GraffitiSession | null) =>\n this_.objectStreamContinue<Schema>(continue_(session)),\n cursor,\n };\n }\n if (!result.value.error) {\n this_.synchronizeDispatch(result.value);\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 continueDiscover: Graffiti[\"continueDiscover\"] = (...args) => {\n const iterator = this.graffiti.continueDiscover(...args);\n return this.objectStreamContinue<{}>(iterator);\n };\n}\n\nfunction 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 : String(error),\n );\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,KAAK,CAAC;AAC3B,OAAO,KAAK,EACV,QAAQ,EACR,eAAe,EACf,UAAU,EACV,kBAAkB,EAClB,oBAAoB,EACpB,iCAAiC,EACjC,4BAA4B,EAC5B,iBAAiB,
|
|
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": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "Internal synchronization for the Graffiti API",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"module": "./dist/esm/index.js",
|
|
@@ -45,17 +45,17 @@
|
|
|
45
45
|
},
|
|
46
46
|
"homepage": "https://sync.graffiti.garden/classes/GraffitiSynchronize.html",
|
|
47
47
|
"devDependencies": {
|
|
48
|
-
"@graffiti-garden/implementation-local": "^1.0.
|
|
49
|
-
"@types/node": "^25.0.
|
|
50
|
-
"@vitest/coverage-v8": "^4.0.
|
|
48
|
+
"@graffiti-garden/implementation-local": "^1.0.4",
|
|
49
|
+
"@types/node": "^25.0.6",
|
|
50
|
+
"@vitest/coverage-v8": "^4.0.17",
|
|
51
51
|
"esbuild-plugin-polyfill-node": "^0.3.0",
|
|
52
52
|
"tsx": "^4.20.6",
|
|
53
|
-
"typedoc": "^0.28.
|
|
53
|
+
"typedoc": "^0.28.16",
|
|
54
54
|
"typescript": "^5.9.3",
|
|
55
|
-
"vitest": "^4.0.
|
|
55
|
+
"vitest": "^4.0.17"
|
|
56
56
|
},
|
|
57
57
|
"dependencies": {
|
|
58
|
-
"@graffiti-garden/api": "^1.0.
|
|
58
|
+
"@graffiti-garden/api": "^1.0.4",
|
|
59
59
|
"@repeaterjs/repeater": "^3.0.6",
|
|
60
60
|
"ajv": "^8.17.1"
|
|
61
61
|
}
|
package/src/index.ts
CHANGED
|
@@ -8,10 +8,11 @@ import type {
|
|
|
8
8
|
GraffitiObjectStreamContinueEntry,
|
|
9
9
|
GraffitiObjectStreamContinue,
|
|
10
10
|
GraffitiObjectUrl,
|
|
11
|
+
GraffitiObject,
|
|
11
12
|
} from "@graffiti-garden/api";
|
|
12
13
|
import {
|
|
14
|
+
GraffitiErrorInvalidSchema,
|
|
13
15
|
GraffitiErrorNotFound,
|
|
14
|
-
compileGraffitiObjectSchema,
|
|
15
16
|
isActorAllowedGraffitiObject,
|
|
16
17
|
maskGraffitiObject,
|
|
17
18
|
unpackObjectUrl,
|
|
@@ -158,11 +159,11 @@ export class GraffitiSynchronize implements Graffiti {
|
|
|
158
159
|
isActorAllowedGraffitiObject(objectUpdate.object, session))
|
|
159
160
|
) {
|
|
160
161
|
// Deep clone the object to prevent mutation
|
|
161
|
-
|
|
162
|
+
let object = JSON.parse(
|
|
162
163
|
JSON.stringify(objectUpdate.object),
|
|
163
164
|
) as GraffitiObjectBase;
|
|
164
165
|
if (!this.options.omniscient) {
|
|
165
|
-
maskGraffitiObject(object, channels, session);
|
|
166
|
+
object = maskGraffitiObject(object, channels, session?.actor);
|
|
166
167
|
}
|
|
167
168
|
if (validate(object)) {
|
|
168
169
|
push({ object });
|
|
@@ -374,3 +375,22 @@ export class GraffitiSynchronize implements Graffiti {
|
|
|
374
375
|
return this.objectStreamContinue<{}>(iterator);
|
|
375
376
|
};
|
|
376
377
|
}
|
|
378
|
+
|
|
379
|
+
function compileGraffitiObjectSchema<Schema extends JSONSchema>(
|
|
380
|
+
ajv: Ajv,
|
|
381
|
+
schema: Schema,
|
|
382
|
+
) {
|
|
383
|
+
try {
|
|
384
|
+
// Force the validation guard because
|
|
385
|
+
// it is too big for the type checker.
|
|
386
|
+
// Fortunately json-schema-to-ts is
|
|
387
|
+
// well tested against ajv.
|
|
388
|
+
return ajv.compile(schema) as (
|
|
389
|
+
data: GraffitiObjectBase,
|
|
390
|
+
) => data is GraffitiObject<Schema>;
|
|
391
|
+
} catch (error) {
|
|
392
|
+
throw new GraffitiErrorInvalidSchema(
|
|
393
|
+
error instanceof Error ? error.message : String(error),
|
|
394
|
+
);
|
|
395
|
+
}
|
|
396
|
+
}
|