@graffiti-garden/wrapper-vue 0.1.1 → 0.1.2

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/plugin.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";var V=Object.defineProperty;var $=(t,e,r)=>e in t?V(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r;var d=(t,e,r)=>$(t,typeof e!="symbol"?e+"":e,r);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=require("vue"),G=Symbol(),y=Symbol();function g(){const t=s.inject(G);if(!t)throw new Error("No Graffiti instance provided");return t}function R(){const t=s.inject(y);if(!t)throw new Error("No Graffiti session provided");return t}class z{constructor(e){d(this,"poll",async e=>{let r;try{r=await this.getter()}catch{e(null);return}e(r)});this.getter=e}clear(){}}class w{constructor(e,r){d(this,"bookmark");d(this,"iterator");d(this,"poll",async e=>{var a,u;const r=new Date().getTime(),o={...this.schemaGetter()};this.bookmark&&this.bookmark.fullRepollBy>r&&(o.properties={...o.properties,lastModified:{minimum:this.bookmark.lastModified,...(a=o.properties)==null?void 0:a.lastModified}});let n;try{n=this.streamFactory()}catch(f){console.error(f);return}this.iterator=n;let i=(u=this.bookmark)==null?void 0:u.lastModified,l=await n.next();for(;!l.done;){if(l.value.error){console.error(l.value.error),l=await n.next();continue}const f=l.value.value;(!i||f.lastModified>i)&&(i=f.lastModified),e(f),l=await n.next()}if(this.iterator!==n)return;this.iterator=void 0;const{tombstoneRetention:c}=l.value;i&&(this.bookmark={lastModified:i,fullRepollBy:r+c})});this.schemaGetter=e,this.streamFactory=r}clear(){var e;this.bookmark=void 0,(e=this.iterator)==null||e.return({tombstoneRetention:0}),this.iterator=void 0}}function S(t,e){return t.lastModified>e.lastModified||t.lastModified===e.lastModified&&!t.tombstone&&e.tombstone}class L{constructor(){d(this,"result",s.ref(void 0))}clear(){this.result.value=void 0}onObject(e){(!e||!this.result.value||S(e,this.result.value))&&(!e||e.tombstone?this.result.value=null:this.result.value=e)}}class P{constructor(e){d(this,"REFRESH_RATE",100);d(this,"results",s.ref([]));d(this,"resultsRaw",new Map);d(this,"batchFlattenTimer");this.graffiti=e}clear(){this.resultsRaw.clear(),this.results.value=[],clearTimeout(this.batchFlattenTimer),this.batchFlattenTimer=void 0}flattenResults(){this.results.value=Array.from(this.resultsRaw.values()).reduce((e,r)=>{const{tombstone:o}=r;return o||e.push({...r,tombstone:o}),e},[])}onObject(e){if(!e)return;const r=this.graffiti.objectToUri(e),o=this.resultsRaw.get(r);o&&!S(e,o)||(this.resultsRaw.set(r,e),this.batchFlattenTimer||(this.batchFlattenTimer=setTimeout(()=>{this.flattenResults(),this.batchFlattenTimer=void 0},this.REFRESH_RATE)))}}function b(t,e,r,o){let n;async function i(){n=r();for await(const a of n){if(a.error){console.error(a.error);continue}t.onObject(a.value)}}const l=()=>e.poll(t.onObject.bind(t)),c=s.ref(!1);return s.watch(o,async(a,u)=>{if(JSON.stringify(a)!==JSON.stringify(u)){n==null||n.return(),t.clear(),e.clear(),i(),c.value=!0;try{await l()}finally{c.value=!1}}},{immediate:!0}),s.onScopeDispose(()=>n==null?void 0:n.return()),{poll:l,isPolling:c}}function O(t,e){return()=>{const r=s.toValue(e);return r===void 0?t==null?void 0:t.value:r}}function h(t){return t.map(e=>e())}function _(t,e,r){const o=g(),n=R(),i=()=>s.toValue(t),l=()=>s.toValue(e),c=O(n,r),a=[i,l,c],u=()=>o.synchronizeDiscover(...h(a)),f=()=>o.discover(...h(a)),m=new P(o),p=new w(l,f),{poll:v,isPolling:D}=b(m,p,u,a);return{results:m.results,poll:v,isPolling:D}}function E(t,e,r){const o=g(),n=R(),i=()=>s.toValue(t),l=()=>s.toValue(e),c=O(n,r),a=[i,l,c],u=()=>o.synchronizeGet(...h(a)),f=new L,m=new z(()=>o.get(...h(a))),{poll:p,isPolling:v}=b(f,m,u,a);return{result:f.result,poll:p,isPolling:v}}function k(t,e){const r=g(),o=()=>s.toValue(t),i=[o,()=>s.toValue(e)],l=()=>r.synchronizeRecoverOrphans(...h(i)),c=new P(r),a=new w(o,()=>r.recoverOrphans(...h(i))),{poll:u,isPolling:f}=b(c,a,l,i);return{results:c.results,poll:u,isPolling:f}}const F=s.defineComponent({__name:"Discover",props:{channels:{},schema:{},session:{}},setup(t){const e=t,{results:r,poll:o,isPolling:n}=_(s.toRef(e,"channels"),s.toRef(e,"schema"),s.toRef(e,"session"));return(i,l)=>s.renderSlot(i.$slots,"default",{results:s.unref(r),poll:s.unref(o),isPolling:s.unref(n)})}}),M=s.defineComponent({__name:"Get",props:{locationOrUri:{},schema:{},session:{}},setup(t){const e=t,{result:r,poll:o,isPolling:n}=E(s.toRef(e,"locationOrUri"),s.toRef(e,"schema"),s.toRef(e,"session"));return(i,l)=>s.renderSlot(i.$slots,"default",{result:s.unref(r),poll:s.unref(o),isPolling:s.unref(n)})}}),T=s.defineComponent({__name:"RecoverOrphans",props:{schema:{},session:{}},setup(t){const e=t,{results:r,poll:o,isPolling:n}=k(s.toRef(e,"schema"),s.toRef(e,"session"));return(i,l)=>s.renderSlot(i.$slots,"default",{results:s.unref(r),poll:s.unref(o),isPolling:s.unref(n)})}}),U={install(t,e){const r=e.useGraffiti(),o=s.ref(void 0);r.sessionEvents.addEventListener("initialized",n=>{const i=n.detail;if(o.value||(o.value=null),i&&i.error&&console.error(i.error),i&&i.href){const l=t.config.globalProperties.$router;if(l){const c=new URL(i.href);l.replace(c.pathname+c.search+c.hash)}}}),r.sessionEvents.addEventListener("login",n=>{const i=n.detail;if(i.error){console.error("Error logging in:"),console.error(i.error);return}else o.value=i.session}),r.sessionEvents.addEventListener("logout",n=>{const i=n.detail;i.error?(console.error("Error logging out:"),console.error(i.error)):o.value=null}),t.provide(G,r),t.provide(y,o),t.component("GraffitiDiscover",F),t.component("GraffitiGet",M),t.component("GraffitiRecoverOrphans",T),t.config.globalProperties.$graffiti=r,t.config.globalProperties.$graffitiSession=o}};exports.GraffitiDiscover=F;exports.GraffitiGet=M;exports.GraffitiPlugin=U;exports.GraffitiRecoverOrphans=T;exports.graffitiInjectKey=G;exports.graffitiSessionInjectKey=y;exports.useGraffiti=g;exports.useGraffitiDiscover=_;exports.useGraffitiGet=E;exports.useGraffitiRecoverOrphans=k;exports.useGraffitiSession=R;
1
+ "use strict";var V=Object.defineProperty;var $=(t,e,r)=>e in t?V(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r;var d=(t,e,r)=>$(t,typeof e!="symbol"?e+"":e,r);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=require("vue"),G=Symbol(),y=Symbol();function g(){const t=s.inject(G);if(!t)throw new Error("No Graffiti instance provided");return t}function R(){const t=s.inject(y);if(!t)throw new Error("No Graffiti session provided");return t}class z{constructor(e){d(this,"poll",async e=>{let r;try{r=await this.getter()}catch{e(null);return}e(r)});this.getter=e}clear(){}}class b{constructor(e,r){d(this,"bookmark");d(this,"iterator");d(this,"poll",async e=>{var a,u;const r=new Date().getTime(),o={...this.schemaGetter()};this.bookmark&&this.bookmark.fullRepollBy>r&&(o.properties={...o.properties,lastModified:{minimum:this.bookmark.lastModified,...(a=o.properties)==null?void 0:a.lastModified}});let i;try{i=this.streamFactory()}catch(f){console.error(f);return}this.iterator=i;let n=(u=this.bookmark)==null?void 0:u.lastModified,l=await i.next();for(;!l.done;){if(l.value.error){console.error(l.value.error),l=await i.next();continue}const f=l.value.value;(!n||f.lastModified>n)&&(n=f.lastModified),e(f),l=await i.next()}if(this.iterator!==i)return;this.iterator=void 0;const{tombstoneRetention:c}=l.value;n&&(this.bookmark={lastModified:n,fullRepollBy:r+c})});this.schemaGetter=e,this.streamFactory=r}clear(){var e;this.bookmark=void 0,(e=this.iterator)==null||e.return({tombstoneRetention:0}),this.iterator=void 0}}function S(t,e){return t.lastModified>e.lastModified||t.lastModified===e.lastModified&&!t.tombstone&&e.tombstone}class L{constructor(){d(this,"result",s.ref(void 0))}clear(){this.result.value=void 0}onObject(e){(!e||!this.result.value||S(e,this.result.value))&&(!e||e.tombstone?this.result.value=null:this.result.value=e)}}class P{constructor(e){d(this,"results",s.ref([]));d(this,"resultsRaw",new Map);d(this,"batchFlattenTimer");this.graffiti=e}clear(){this.resultsRaw.clear(),this.results.value=[],clearTimeout(this.batchFlattenTimer),this.batchFlattenTimer=void 0}flattenResults(){this.results.value=Array.from(this.resultsRaw.values()).reduce((e,r)=>{const{tombstone:o}=r;return o||e.push({...r,tombstone:o}),e},[])}onObject(e){if(!e)return;const r=this.graffiti.objectToUri(e),o=this.resultsRaw.get(r);o&&!S(e,o)||(this.resultsRaw.set(r,e),this.batchFlattenTimer||(this.batchFlattenTimer=setTimeout(()=>{this.flattenResults(),this.batchFlattenTimer=void 0},0)))}}function w(t,e,r,o){let i;async function n(){i=r();for await(const a of i){if(a.error){console.error(a.error);continue}t.onObject(a.value)}}const l=()=>e.poll(t.onObject.bind(t)),c=s.ref(!1);return s.watch(o,async(a,u)=>{if(JSON.stringify(a)!==JSON.stringify(u)){i==null||i.return(),t.clear(),e.clear(),n(),c.value=!0;try{await l()}finally{c.value=!1}}},{immediate:!0}),s.onScopeDispose(()=>i==null?void 0:i.return()),{poll:l,isPolling:c}}function O(t,e){return()=>{const r=s.toValue(e);return r===void 0?t==null?void 0:t.value:r}}function h(t){return t.map(e=>e())}function k(t,e,r){const o=g(),i=R(),n=()=>s.toValue(t),l=()=>s.toValue(e),c=O(i,r),a=[n,l,c],u=()=>o.synchronizeDiscover(...h(a)),f=()=>o.discover(...h(a)),m=new P(o),p=new b(l,f),{poll:v,isPolling:D}=w(m,p,u,a);return{results:m.results,poll:v,isPolling:D}}function _(t,e,r){const o=g(),i=R(),n=()=>s.toValue(t),l=()=>s.toValue(e),c=O(i,r),a=[n,l,c],u=()=>o.synchronizeGet(...h(a)),f=new L,m=new z(()=>o.get(...h(a))),{poll:p,isPolling:v}=w(f,m,u,a);return{result:f.result,poll:p,isPolling:v}}function M(t,e){const r=g(),o=()=>s.toValue(t),n=[o,()=>s.toValue(e)],l=()=>r.synchronizeRecoverOrphans(...h(n)),c=new P(r),a=new b(o,()=>r.recoverOrphans(...h(n))),{poll:u,isPolling:f}=w(c,a,l,n);return{results:c.results,poll:u,isPolling:f}}const F=s.defineComponent({__name:"Discover",props:{channels:{},schema:{},session:{}},setup(t){const e=t,{results:r,poll:o,isPolling:i}=k(s.toRef(e,"channels"),s.toRef(e,"schema"),s.toRef(e,"session"));return(n,l)=>s.renderSlot(n.$slots,"default",{results:s.unref(r),poll:s.unref(o),isPolling:s.unref(i)})}}),T=s.defineComponent({__name:"Get",props:{locationOrUri:{},schema:{},session:{}},setup(t){const e=t,{result:r,poll:o,isPolling:i}=_(s.toRef(e,"locationOrUri"),s.toRef(e,"schema"),s.toRef(e,"session"));return(n,l)=>s.renderSlot(n.$slots,"default",{result:s.unref(r),poll:s.unref(o),isPolling:s.unref(i)})}}),E=s.defineComponent({__name:"RecoverOrphans",props:{schema:{},session:{}},setup(t){const e=t,{results:r,poll:o,isPolling:i}=M(s.toRef(e,"schema"),s.toRef(e,"session"));return(n,l)=>s.renderSlot(n.$slots,"default",{results:s.unref(r),poll:s.unref(o),isPolling:s.unref(i)})}}),U={install(t,e){const r=e.useGraffiti(),o=s.ref(void 0);r.sessionEvents.addEventListener("initialized",async i=>{const n=i.detail;if(n&&n.error&&console.error(n.error),n&&n.href){const l=t.config.globalProperties.$router;if(l){const c=new URL(n.href);await l.replace(c.pathname+c.search+c.hash)}}o.value||(o.value=null)}),r.sessionEvents.addEventListener("login",i=>{const n=i.detail;if(n.error){console.error("Error logging in:"),console.error(n.error);return}else o.value=n.session}),r.sessionEvents.addEventListener("logout",i=>{const n=i.detail;n.error?(console.error("Error logging out:"),console.error(n.error)):o.value=null}),t.provide(G,r),t.provide(y,o),t.component("GraffitiDiscover",F),t.component("GraffitiGet",T),t.component("GraffitiRecoverOrphans",E),t.config.globalProperties.$graffiti=r,t.config.globalProperties.$graffitiSession=o}};exports.GraffitiDiscover=F;exports.GraffitiGet=T;exports.GraffitiPlugin=U;exports.GraffitiRecoverOrphans=E;exports.graffitiInjectKey=G;exports.graffitiSessionInjectKey=y;exports.useGraffiti=g;exports.useGraffitiDiscover=k;exports.useGraffitiGet=_;exports.useGraffitiRecoverOrphans=M;exports.useGraffitiSession=R;
2
2
  //# sourceMappingURL=plugin.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.cjs","sources":["../src/injections.ts","../src/pollers.ts","../node_modules/@graffiti-garden/implementation-local/dist/esm/utilities.js","../src/reducers.ts","../src/composables.ts","../src/Discover.vue","../src/Get.vue","../src/RecoverOrphans.vue","../src/plugin.ts"],"sourcesContent":["import { inject } from \"vue\";\nimport type { InjectionKey, Ref } from \"vue\";\nimport type { Graffiti, GraffitiSession } from \"@graffiti-garden/api\";\n\nexport const graffitiInjectKey = Symbol() as InjectionKey<Graffiti>;\nexport const graffitiSessionInjectKey = Symbol() as InjectionKey<\n Ref<GraffitiSession | undefined | null>\n>;\n\nexport function useGraffiti() {\n const graffiti = inject(graffitiInjectKey);\n if (!graffiti) {\n throw new Error(\"No Graffiti instance provided\");\n }\n return graffiti;\n}\n\nexport function useGraffitiSession() {\n const session = inject(graffitiSessionInjectKey);\n if (!session) {\n throw new Error(\"No Graffiti session provided\");\n }\n return session;\n}\n","import type {\n Graffiti,\n JSONSchema4,\n GraffitiObject,\n} from \"@graffiti-garden/api\";\n\nexport abstract class Poller<Schema extends JSONSchema4> {\n abstract poll(\n onObject: (object: GraffitiObject<Schema> | null) => void,\n ): Promise<void>;\n abstract clear(): void;\n}\n\n/**\n * Polls for a single object and calls onValue with the result.\n */\nexport class GetPoller<Schema extends JSONSchema4> implements Poller<Schema> {\n constructor(readonly getter: () => Promise<GraffitiObject<Schema>>) {}\n\n poll: Poller<Schema>[\"poll\"] = async (onObject) => {\n let object: GraffitiObject<Schema>;\n try {\n object = await this.getter();\n } catch (e) {\n onObject(null);\n return;\n }\n onObject(object);\n };\n\n clear() {}\n}\n\n/**\n * Polls for multiple objects and calls `onObject` with the result.\n * If `poll` is called multiple times, it doesn't poll the results\n * entirely from scratch, but instead only polls the new results.\n */\nexport class StreamPoller<Schema extends JSONSchema4>\n implements Poller<Schema>\n{\n bookmark:\n | {\n lastModified: number;\n fullRepollBy: number;\n }\n | undefined = undefined;\n iterator: ReturnType<typeof Graffiti.prototype.discover<Schema>> | undefined =\n undefined;\n\n constructor(\n readonly schemaGetter: () => Schema,\n readonly streamFactory: () => ReturnType<\n typeof Graffiti.prototype.discover<Schema>\n >,\n ) {}\n\n clear() {\n this.bookmark = undefined;\n this.iterator?.return({ tombstoneRetention: 0 });\n this.iterator = undefined;\n }\n\n poll: Poller<Schema>[\"poll\"] = async (onObject) => {\n const startOfPoll = new Date().getTime();\n\n // Add a query for lastModified if it's not in the schema\n const schema = { ...this.schemaGetter() };\n if (this.bookmark && this.bookmark.fullRepollBy > startOfPoll) {\n schema.properties = {\n ...schema.properties,\n lastModified: {\n minimum: this.bookmark.lastModified,\n // if the schema already has a minimum\n // it won't be overridden because\n // the schema below takes precedence\n ...schema.properties?.lastModified,\n },\n };\n }\n\n let myIterator: ReturnType<typeof Graffiti.prototype.discover<Schema>>;\n try {\n myIterator = this.streamFactory();\n } catch (e) {\n console.error(e);\n return;\n }\n\n // Claim the spot as the current iterator\n this.iterator = myIterator;\n\n // Keep track of the latest lastModified value\n // while streaming results\n let myLastModified = this.bookmark?.lastModified;\n let result = await myIterator.next();\n while (!result.done) {\n if (result.value.error) {\n console.error(result.value.error);\n result = await myIterator.next();\n continue;\n }\n\n const object = result.value.value;\n if (!myLastModified || object.lastModified > myLastModified) {\n myLastModified = object.lastModified;\n }\n\n onObject(object);\n\n result = await myIterator.next();\n }\n\n // Make sure we're still the current iterator\n if (this.iterator !== myIterator) return;\n\n // We've successfully polled all results\n // without getting overridden\n this.iterator = undefined;\n\n // Only now do we update the cache parameters\n // because the results may have appeared out\n // of order\n const { tombstoneRetention } = result.value;\n if (myLastModified) {\n this.bookmark = {\n lastModified: myLastModified,\n fullRepollBy: startOfPoll + tombstoneRetention,\n };\n }\n };\n}\n","import{GraffitiErrorInvalidSchema as n,GraffitiErrorInvalidUri as f,GraffitiErrorPatchError as c,GraffitiErrorPatchTestFailed as s}from\"@graffiti-garden/api\";const p=e=>`${e.source}/${encodeURIComponent(e.actor)}/${encodeURIComponent(e.name)}`,d=e=>{const t=e.split(\"/\"),r=t.pop(),o=t.pop();if(!r||!o||!t.length)throw new f;return{name:decodeURIComponent(r),actor:decodeURIComponent(o),source:t.join(\"/\")}};function l(e=16){const t=new Uint8Array(e);return crypto.getRandomValues(t),btoa(String.fromCodePoint(...t)).replace(/\\+/g,\"-\").replace(/\\//g,\"_\").replace(/\\=+$/,\"\")}function u(e){return typeof e==\"string\"?{location:d(e),uri:e}:{location:{name:e.name,actor:e.actor,source:e.source},uri:p(e)}}function G(e,t){return e.lastModified>t.lastModified||e.lastModified===t.lastModified&&!e.tombstone&&t.tombstone}function h(e,t,r,o){const i=r[t];if(!(!i||!i.length))try{o[t]=e(o[t],i,!0,!1).newDocument}catch(a){throw typeof a==\"object\"&&a&&\"name\"in a&&typeof a.name==\"string\"&&\"message\"in a&&typeof a.message==\"string\"?a.name===\"TEST_OPERATION_FAILED\"?new s(a.message):new c(a.name+\": \"+a.message):a}}function w(e,t){try{return e.compile(t)}catch(r){throw new n(r instanceof Error?r.message:void 0)}}function y(e,t,r){e.actor!==r?.actor&&(e.allowed=e.allowed&&r?[r.actor]:void 0,e.channels=e.channels.filter(o=>t.includes(o)))}function g(e,t){return e.allowed===void 0||e.allowed===null||!!t?.actor&&(e.actor===t.actor||e.allowed.includes(t.actor))}export{h as applyGraffitiPatch,w as attemptAjvCompile,g as isActorAllowedGraffitiObject,G as isObjectNewer,p as locationToUri,y as maskGraffitiObject,l as randomBase64,u as unpackLocationOrUri,d as uriToLocation};\n//# sourceMappingURL=utilities.js.map\n","import { ref } from \"vue\";\nimport type { JSONSchema4 } from \"@graffiti-garden/api\";\nimport type { GraffitiObject, Graffiti } from \"@graffiti-garden/api\";\nimport { isObjectNewer } from \"@graffiti-garden/implementation-local/utilities\";\n\nexport abstract class Reducer<Schema extends JSONSchema4> {\n abstract clear(): void;\n abstract onObject(object: GraffitiObject<Schema> | null): void;\n}\n\n/**\n * Retrieves multiple Graffiti objects and retains\n * the most recent one as the `result` property (a Vue ref).\n * Before any objects have been received, the result\n * is `undefined`. If the object has been deleted,\n * the result is `null`.\n */\nexport class SingletonReducer<Schema extends JSONSchema4>\n implements Reducer<Schema>\n{\n readonly result = ref<\n (GraffitiObject<Schema> & { tombstone: false }) | null | undefined\n >(undefined);\n\n clear() {\n this.result.value = undefined;\n }\n\n onObject(object: GraffitiObject<Schema> | null) {\n if (\n !object ||\n !this.result.value ||\n isObjectNewer(object, this.result.value)\n ) {\n if (!object || object.tombstone) {\n this.result.value = null;\n } else {\n this.result.value = object;\n }\n }\n }\n}\n\n/**\n * Retrieves multiple Graffiti objects and retains\n * the most recent one per URI as the `results` property (a Vue ref).\n * If multiple objects are received concurrently,\n * they are processed in batches every `REFRESH_RATE` milliseconds\n * to avoid freezing the interface.\n */\nexport class ArrayReducer<Schema extends JSONSchema4>\n implements Reducer<Schema>\n{\n REFRESH_RATE = 100; // milliseconds\n readonly results = ref<(GraffitiObject<Schema> & { tombstone: false })[]>([]);\n readonly resultsRaw = new Map<string, GraffitiObject<Schema>>();\n batchFlattenTimer: ReturnType<typeof setTimeout> | undefined = undefined;\n\n constructor(readonly graffiti: Graffiti) {}\n\n clear() {\n this.resultsRaw.clear();\n this.results.value = [];\n clearTimeout(this.batchFlattenTimer);\n this.batchFlattenTimer = undefined;\n }\n\n flattenResults() {\n this.results.value = Array.from(this.resultsRaw.values()).reduce<\n (GraffitiObject<Schema> & { tombstone: false })[]\n >((acc, object) => {\n const { tombstone } = object;\n if (!tombstone) {\n acc.push({ ...object, tombstone });\n }\n return acc;\n }, []);\n }\n\n onObject(object: GraffitiObject<Schema> | null) {\n if (!object) return;\n const url = this.graffiti.objectToUri(object);\n const existing = this.resultsRaw.get(url);\n if (existing && !isObjectNewer(object, existing)) return;\n this.resultsRaw.set(url, object);\n\n // Don't flatten the results all at once,\n // because we may get a lot of results\n // and we don't want the interface to\n // freeze up\n if (!this.batchFlattenTimer) {\n this.batchFlattenTimer = setTimeout(() => {\n this.flattenResults();\n this.batchFlattenTimer = undefined;\n }, this.REFRESH_RATE);\n }\n }\n}\n","import {\n onScopeDispose,\n ref,\n toValue,\n watch,\n type MaybeRefOrGetter,\n} from \"vue\";\nimport type {\n GraffitiLocation,\n GraffitiObject,\n GraffitiSession,\n JSONSchema4,\n} from \"@graffiti-garden/api\";\nimport { useGraffiti, useGraffitiSession } from \"./injections\";\nimport type { GraffitiStream } from \"@graffiti-garden/api\";\nimport { GetPoller, Poller, StreamPoller } from \"./pollers\";\nimport { ArrayReducer, Reducer, SingletonReducer } from \"./reducers\";\n\nfunction makeComposable<Schema extends JSONSchema4>(\n reducer: Reducer<Schema>,\n poller: Poller<Schema>,\n synchronizeFactory: () => GraffitiStream<GraffitiObject<Schema>>,\n toWatch: readonly (() => any)[],\n) {\n let synchronizeIterator: GraffitiStream<GraffitiObject<Schema>> | undefined =\n undefined;\n async function pollSynchronize() {\n synchronizeIterator = synchronizeFactory();\n for await (const result of synchronizeIterator) {\n if (result.error) {\n console.error(result.error);\n continue;\n }\n reducer.onObject(result.value);\n }\n }\n\n const poll = () => poller.poll(reducer.onObject.bind(reducer));\n\n const isPolling = ref(false);\n watch(\n toWatch,\n async (newValue, oldValue) => {\n // Catch unnecessary updates\n if (JSON.stringify(newValue) === JSON.stringify(oldValue)) {\n return;\n }\n\n synchronizeIterator?.return();\n reducer.clear();\n poller.clear();\n\n pollSynchronize();\n\n isPolling.value = true;\n try {\n await poll();\n } finally {\n isPolling.value = false;\n }\n },\n {\n immediate: true,\n },\n );\n onScopeDispose(() => synchronizeIterator?.return());\n\n return { poll, isPolling };\n}\n\nfunction toSessionGetter(\n sessionInjected: ReturnType<typeof useGraffitiSession>,\n session?: MaybeRefOrGetter<GraffitiSession | undefined | null>,\n) {\n return () => {\n const sessionValue = toValue(session);\n if (sessionValue === undefined) {\n return sessionInjected?.value;\n } else {\n return sessionValue;\n }\n };\n}\n\nfunction callGetters<T extends readonly (() => any)[]>(\n getters: T,\n): {\n [K in keyof T]: ReturnType<T[K]>;\n} {\n return getters.map((fn) => fn()) as any;\n}\n\n/**\n * A reactive version of the [`Graffiti.discover`](https://api.graffiti.garden/classes/Graffiti.html#discover)\n * method. Its arguments are the same, but now they can be\n * reactive Vue refs or getters. As they change the output will\n * automatically update.\n *\n * Rather than returning a stream of Graffiti objects, this\n * function returns a reactive array of objects. It also\n * provides a method to poll for new results and a boolean\n * ref indicating if the poll is currently running.\n *\n * All [`tombstone`](https://api.graffiti.garden/interfaces/GraffitiObjectBase.html#tombstone)d\n * objects are filtered out.\n *\n * @returns An object containing\n * - `results`: a reactive array of Graffiti objects\n * - `poll`: a method to poll for new results\n * - `isPolling`: a boolean ref indicating if the poll is currently running\n */\nexport function useGraffitiDiscover<Schema extends JSONSchema4>(\n /**\n * A list of channels to discover objects from.\n * Reactivity will only trigger\n * when the root array changes, not when the elements\n * change. If you need reactivity on the elements,\n * create a getter, e.g. `() => [toValue(myReactiveChannel)]`.\n */\n channels: MaybeRefOrGetter<string[]>,\n /**\n * A [JSON Schema](https://json-schema.org/) object describing the schema\n * of the objects to discover. All other objects will be filtered out\n * and the output will be typed as `GraffitiObject<Schema>`.\n * Reactivity only triggers when the root object changes, not when\n * the root object changes, not when the properties change.\n * Create a getter if you need reactivity on the properties.\n */\n schema: MaybeRefOrGetter<Schema>,\n /**\n * A Graffiti session object. If not provided, the\n * global plugin session will be used.\n */\n session?: MaybeRefOrGetter<GraffitiSession | undefined | null>,\n) {\n const graffiti = useGraffiti();\n const sessionInjected = useGraffitiSession();\n\n const channelsGetter = () => toValue(channels);\n const schemaGetter = () => toValue(schema);\n const sessionGetter = toSessionGetter(sessionInjected, session);\n const argGetters = [channelsGetter, schemaGetter, sessionGetter] as const;\n\n const synchronizeFactory = () =>\n graffiti.synchronizeDiscover(...callGetters(argGetters));\n const streamFactory = () => graffiti.discover(...callGetters(argGetters));\n\n const reducer = new ArrayReducer<Schema>(graffiti);\n const poller = new StreamPoller(schemaGetter, streamFactory);\n\n const { poll, isPolling } = makeComposable(\n reducer,\n poller,\n synchronizeFactory,\n argGetters,\n );\n\n return {\n results: reducer.results,\n poll,\n isPolling,\n };\n}\n\n/**\n * A reactive version of the [`Graffiti.get`](https://api.graffiti.garden/classes/Graffiti.html#get)\n * method. Its arguments are the same, but now they can be\n * reactive Vue refs or getters. As they change the output will\n * automatically update.\n *\n * Rather than returning a single Graffiti object, this\n * function returns a reactive object. It also\n * provides a method to poll for new results and a boolean\n * ref indicating if the poll is currently running.\n *\n * While the object is first being fetched, the result\n * is `undefined`. If the object has been deleted,\n * the result is `null`. Otherwise, the result is the\n * most recent object fetched. All [`tombstone`](https://api.graffiti.garden/interfaces/GraffitiObjectBase.html#tombstone)d\n * objects are filtered out.\n *\n * @returns An object containing\n * - `results`: a reactive array of Graffiti objects\n * - `poll`: a method to poll for new results\n * - `isPolling`: a boolean ref indicating if the poll is currently running\n */\nexport function useGraffitiGet<Schema extends JSONSchema4>(\n /**\n * A Graffiti location or URI to fetch the object from.\n */\n locationOrUri: MaybeRefOrGetter<GraffitiLocation | string>,\n /**\n * A [JSON Schema](https://json-schema.org/) object describing the schema\n * of the objects to discover. All other objects will be filtered out\n * and the output will be typed as `GraffitiObject<Schema>`.\n * Like the `channels` argument, reactivity only triggers when\n */\n schema: MaybeRefOrGetter<Schema>,\n /**\n * A Graffiti session object. If not provided, the\n * global plugin session will be used.\n */\n session?: MaybeRefOrGetter<GraffitiSession | undefined | null>,\n) {\n const graffiti = useGraffiti();\n const sessionInjected = useGraffitiSession();\n\n const locationOrUriGetter = () => toValue(locationOrUri);\n const schemaGetter = () => toValue(schema);\n const sessionGetter = toSessionGetter(sessionInjected, session);\n const argGetters = [\n locationOrUriGetter,\n schemaGetter,\n sessionGetter,\n ] as const;\n\n const synchronizeFactory = () =>\n graffiti.synchronizeGet(...callGetters(argGetters));\n\n const reducer = new SingletonReducer<Schema>();\n const poller = new GetPoller(() => graffiti.get(...callGetters(argGetters)));\n\n const { poll, isPolling } = makeComposable(\n reducer,\n poller,\n synchronizeFactory,\n argGetters,\n );\n\n return {\n result: reducer.result,\n poll,\n isPolling,\n };\n}\n\nexport function useGraffitiRecoverOrphans<Schema extends JSONSchema4>(\n schema: MaybeRefOrGetter<Schema>,\n session: MaybeRefOrGetter<GraffitiSession>,\n) {\n const graffiti = useGraffiti();\n\n const schemaGetter = () => toValue(schema);\n const sessionGetter = () => toValue(session);\n const argGetters = [schemaGetter, sessionGetter] as const;\n\n const synchronizeFactory = () =>\n graffiti.synchronizeRecoverOrphans(...callGetters(argGetters));\n\n const reducer = new ArrayReducer<Schema>(graffiti);\n const poller = new StreamPoller(schemaGetter, () =>\n graffiti.recoverOrphans(...callGetters(argGetters)),\n );\n\n const { poll, isPolling } = makeComposable(\n reducer,\n poller,\n synchronizeFactory,\n argGetters,\n );\n\n return {\n results: reducer.results,\n poll,\n isPolling,\n };\n}\n","<script setup lang=\"ts\" generic=\"Schema extends JSONSchema4\">\nimport { toRef } from \"vue\";\nimport type { GraffitiSession, JSONSchema4 } from \"@graffiti-garden/api\";\nimport { useGraffitiDiscover } from \"./composables\";\n\nconst props = defineProps<{\n channels: string[];\n schema: Schema;\n session?: GraffitiSession | null;\n}>();\n\nconst { results, poll, isPolling } = useGraffitiDiscover<Schema>(\n toRef(props, \"channels\"),\n toRef(props, \"schema\"),\n toRef(props, \"session\"),\n);\n</script>\n\n<template>\n <slot :results=\"results\" :poll=\"poll\" :isPolling=\"isPolling\"></slot>\n</template>\n","<script setup lang=\"ts\" generic=\"Schema extends JSONSchema4\">\nimport { toRef } from \"vue\";\nimport type {\n GraffitiLocation,\n GraffitiSession,\n JSONSchema4,\n} from \"@graffiti-garden/api\";\nimport { useGraffitiGet } from \"./composables\";\n\nconst props = defineProps<{\n locationOrUri: string | GraffitiLocation;\n schema: Schema;\n session?: GraffitiSession | null;\n}>();\n\nconst { result, poll, isPolling } = useGraffitiGet<Schema>(\n toRef(props, \"locationOrUri\"),\n toRef(props, \"schema\"),\n toRef(props, \"session\"),\n);\n</script>\n\n<template>\n <slot :result=\"result\" :poll=\"poll\" :isPolling=\"isPolling\"></slot>\n</template>\n","<script setup lang=\"ts\" generic=\"Schema extends JSONSchema4\">\nimport { toRef } from \"vue\";\nimport type { GraffitiSession, JSONSchema4 } from \"@graffiti-garden/api\";\nimport { useGraffitiRecoverOrphans } from \"./composables\";\n\nconst props = defineProps<{\n schema: Schema;\n session: GraffitiSession;\n}>();\n\nconst { results, poll, isPolling } = useGraffitiRecoverOrphans<Schema>(\n toRef(props, \"schema\"),\n toRef(props, \"session\"),\n);\n</script>\n\n<template>\n <slot :results=\"results\" :poll=\"poll\" :isPolling=\"isPolling\"></slot>\n</template>\n","import type { App, Plugin, Ref } from \"vue\";\nimport { ref } from \"vue\";\nimport Discover from \"./Discover.vue\";\nimport Get from \"./Get.vue\";\nimport RecoverOrphans from \"./RecoverOrphans.vue\";\nimport type {\n GraffitiFactory,\n Graffiti,\n GraffitiSession,\n GraffitiLoginEvent,\n GraffitiLogoutEvent,\n GraffitiSessionInitializedEvent,\n} from \"@graffiti-garden/api\";\nimport { graffitiInjectKey, graffitiSessionInjectKey } from \"./injections\";\nimport type { Router } from \"vue-router\";\n\ndeclare module \"vue\" {\n export interface ComponentCustomProperties {\n $graffiti: Graffiti;\n $graffitiSession: Ref<GraffitiSession | undefined | null>;\n }\n\n export interface GlobalComponents {\n GraffitiDiscover: typeof Discover;\n GraffitiGet: typeof Get;\n GraffitiRecoverOrphans: typeof RecoverOrphans;\n }\n}\n\nexport interface GraffitiPluginOptions {\n useGraffiti: GraffitiFactory;\n}\n\nexport const GraffitiPlugin: Plugin<GraffitiPluginOptions> = {\n install(app: App, options: GraffitiPluginOptions) {\n const graffiti = options.useGraffiti();\n const graffitiSession = ref<GraffitiSession | undefined | null>(undefined);\n graffiti.sessionEvents.addEventListener(\"initialized\", (evt) => {\n const detail = (evt as GraffitiSessionInitializedEvent).detail;\n\n // Set the session to \"null\" if the user is not logged in\n if (!graffitiSession.value) {\n graffitiSession.value = null;\n }\n\n if (detail && detail.error) {\n console.error(detail.error);\n }\n\n if (detail && detail.href) {\n // If we're using Vue Router, redirect to the URL after login\n const router = app.config.globalProperties.$router as\n | Router\n | undefined;\n if (router) {\n const url = new URL(detail.href);\n router.replace(url.pathname + url.search + url.hash);\n }\n }\n });\n graffiti.sessionEvents.addEventListener(\"login\", (evt) => {\n const detail = (evt as GraffitiLoginEvent).detail;\n if (detail.error) {\n console.error(\"Error logging in:\");\n console.error(detail.error);\n return;\n } else {\n graffitiSession.value = detail.session;\n }\n });\n graffiti.sessionEvents.addEventListener(\"logout\", (evt) => {\n const detail = (evt as GraffitiLogoutEvent).detail;\n if (detail.error) {\n console.error(\"Error logging out:\");\n console.error(detail.error);\n } else {\n graffitiSession.value = null;\n }\n });\n\n app.provide(graffitiInjectKey, graffiti);\n app.provide(graffitiSessionInjectKey, graffitiSession);\n\n app.component(\"GraffitiDiscover\", Discover);\n app.component(\"GraffitiGet\", Get);\n app.component(\"GraffitiRecoverOrphans\", RecoverOrphans);\n app.config.globalProperties.$graffiti = graffiti;\n app.config.globalProperties.$graffitiSession = graffitiSession;\n },\n};\n\nexport * from \"./composables\";\nexport * from \"./injections\";\nexport { Discover as GraffitiDiscover };\nexport { Get as GraffitiGet };\nexport { RecoverOrphans as GraffitiRecoverOrphans };\n"],"names":["graffitiInjectKey","graffitiSessionInjectKey","useGraffiti","graffiti","inject","useGraffitiSession","session","GetPoller","getter","__publicField","onObject","object","StreamPoller","schemaGetter","streamFactory","startOfPoll","schema","_a","myIterator","e","myLastModified","_b","result","tombstoneRetention","G","t","SingletonReducer","ref","isObjectNewer","ArrayReducer","acc","tombstone","url","existing","makeComposable","reducer","poller","synchronizeFactory","toWatch","synchronizeIterator","pollSynchronize","poll","isPolling","watch","newValue","oldValue","onScopeDispose","toSessionGetter","sessionInjected","sessionValue","toValue","callGetters","getters","fn","useGraffitiDiscover","channels","channelsGetter","sessionGetter","argGetters","useGraffitiGet","locationOrUri","locationOrUriGetter","useGraffitiRecoverOrphans","props","__props","results","toRef","GraffitiPlugin","app","options","graffitiSession","evt","detail","router","Discover","Get","RecoverOrphans"],"mappings":"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","x_google_ignoreList":[2]}
1
+ {"version":3,"file":"plugin.cjs","sources":["../src/injections.ts","../src/pollers.ts","../node_modules/@graffiti-garden/implementation-local/dist/esm/utilities.js","../src/reducers.ts","../src/composables.ts","../src/Discover.vue","../src/Get.vue","../src/RecoverOrphans.vue","../src/plugin.ts"],"sourcesContent":["import { inject } from \"vue\";\nimport type { InjectionKey, Ref } from \"vue\";\nimport type { Graffiti, GraffitiSession } from \"@graffiti-garden/api\";\n\nexport const graffitiInjectKey = Symbol() as InjectionKey<Graffiti>;\nexport const graffitiSessionInjectKey = Symbol() as InjectionKey<\n Ref<GraffitiSession | undefined | null>\n>;\n\nexport function useGraffiti() {\n const graffiti = inject(graffitiInjectKey);\n if (!graffiti) {\n throw new Error(\"No Graffiti instance provided\");\n }\n return graffiti;\n}\n\nexport function useGraffitiSession() {\n const session = inject(graffitiSessionInjectKey);\n if (!session) {\n throw new Error(\"No Graffiti session provided\");\n }\n return session;\n}\n","import type {\n Graffiti,\n JSONSchema4,\n GraffitiObject,\n} from \"@graffiti-garden/api\";\n\nexport abstract class Poller<Schema extends JSONSchema4> {\n abstract poll(\n onObject: (object: GraffitiObject<Schema> | null) => void,\n ): Promise<void>;\n abstract clear(): void;\n}\n\n/**\n * Polls for a single object and calls onValue with the result.\n */\nexport class GetPoller<Schema extends JSONSchema4> implements Poller<Schema> {\n constructor(readonly getter: () => Promise<GraffitiObject<Schema>>) {}\n\n poll: Poller<Schema>[\"poll\"] = async (onObject) => {\n let object: GraffitiObject<Schema>;\n try {\n object = await this.getter();\n } catch (e) {\n onObject(null);\n return;\n }\n onObject(object);\n };\n\n clear() {}\n}\n\n/**\n * Polls for multiple objects and calls `onObject` with the result.\n * If `poll` is called multiple times, it doesn't poll the results\n * entirely from scratch, but instead only polls the new results.\n */\nexport class StreamPoller<Schema extends JSONSchema4>\n implements Poller<Schema>\n{\n bookmark:\n | {\n lastModified: number;\n fullRepollBy: number;\n }\n | undefined = undefined;\n iterator: ReturnType<typeof Graffiti.prototype.discover<Schema>> | undefined =\n undefined;\n\n constructor(\n readonly schemaGetter: () => Schema,\n readonly streamFactory: () => ReturnType<\n typeof Graffiti.prototype.discover<Schema>\n >,\n ) {}\n\n clear() {\n this.bookmark = undefined;\n this.iterator?.return({ tombstoneRetention: 0 });\n this.iterator = undefined;\n }\n\n poll: Poller<Schema>[\"poll\"] = async (onObject) => {\n const startOfPoll = new Date().getTime();\n\n // Add a query for lastModified if it's not in the schema\n const schema = { ...this.schemaGetter() };\n if (this.bookmark && this.bookmark.fullRepollBy > startOfPoll) {\n schema.properties = {\n ...schema.properties,\n lastModified: {\n minimum: this.bookmark.lastModified,\n // if the schema already has a minimum\n // it won't be overridden because\n // the schema below takes precedence\n ...schema.properties?.lastModified,\n },\n };\n }\n\n let myIterator: ReturnType<typeof Graffiti.prototype.discover<Schema>>;\n try {\n myIterator = this.streamFactory();\n } catch (e) {\n console.error(e);\n return;\n }\n\n // Claim the spot as the current iterator\n this.iterator = myIterator;\n\n // Keep track of the latest lastModified value\n // while streaming results\n let myLastModified = this.bookmark?.lastModified;\n let result = await myIterator.next();\n while (!result.done) {\n if (result.value.error) {\n console.error(result.value.error);\n result = await myIterator.next();\n continue;\n }\n\n const object = result.value.value;\n if (!myLastModified || object.lastModified > myLastModified) {\n myLastModified = object.lastModified;\n }\n\n onObject(object);\n\n result = await myIterator.next();\n }\n\n // Make sure we're still the current iterator\n if (this.iterator !== myIterator) return;\n\n // We've successfully polled all results\n // without getting overridden\n this.iterator = undefined;\n\n // Only now do we update the cache parameters\n // because the results may have appeared out\n // of order\n const { tombstoneRetention } = result.value;\n if (myLastModified) {\n this.bookmark = {\n lastModified: myLastModified,\n fullRepollBy: startOfPoll + tombstoneRetention,\n };\n }\n };\n}\n","import{GraffitiErrorInvalidSchema as n,GraffitiErrorInvalidUri as f,GraffitiErrorPatchError as c,GraffitiErrorPatchTestFailed as s}from\"@graffiti-garden/api\";const p=e=>`${e.source}/${encodeURIComponent(e.actor)}/${encodeURIComponent(e.name)}`,d=e=>{const t=e.split(\"/\"),r=t.pop(),o=t.pop();if(!r||!o||!t.length)throw new f;return{name:decodeURIComponent(r),actor:decodeURIComponent(o),source:t.join(\"/\")}};function l(e=16){const t=new Uint8Array(e);return crypto.getRandomValues(t),btoa(String.fromCodePoint(...t)).replace(/\\+/g,\"-\").replace(/\\//g,\"_\").replace(/\\=+$/,\"\")}function u(e){return typeof e==\"string\"?{location:d(e),uri:e}:{location:{name:e.name,actor:e.actor,source:e.source},uri:p(e)}}function G(e,t){return e.lastModified>t.lastModified||e.lastModified===t.lastModified&&!e.tombstone&&t.tombstone}function h(e,t,r,o){const i=r[t];if(!(!i||!i.length))try{o[t]=e(o[t],i,!0,!1).newDocument}catch(a){throw typeof a==\"object\"&&a&&\"name\"in a&&typeof a.name==\"string\"&&\"message\"in a&&typeof a.message==\"string\"?a.name===\"TEST_OPERATION_FAILED\"?new s(a.message):new c(a.name+\": \"+a.message):a}}function w(e,t){try{return e.compile(t)}catch(r){throw new n(r instanceof Error?r.message:void 0)}}function y(e,t,r){e.actor!==r?.actor&&(e.allowed=e.allowed&&r?[r.actor]:void 0,e.channels=e.channels.filter(o=>t.includes(o)))}function g(e,t){return e.allowed===void 0||e.allowed===null||!!t?.actor&&(e.actor===t.actor||e.allowed.includes(t.actor))}export{h as applyGraffitiPatch,w as attemptAjvCompile,g as isActorAllowedGraffitiObject,G as isObjectNewer,p as locationToUri,y as maskGraffitiObject,l as randomBase64,u as unpackLocationOrUri,d as uriToLocation};\n//# sourceMappingURL=utilities.js.map\n","import { ref } from \"vue\";\nimport type { JSONSchema4 } from \"@graffiti-garden/api\";\nimport type { GraffitiObject, Graffiti } from \"@graffiti-garden/api\";\nimport { isObjectNewer } from \"@graffiti-garden/implementation-local/utilities\";\n\nexport abstract class Reducer<Schema extends JSONSchema4> {\n abstract clear(): void;\n abstract onObject(object: GraffitiObject<Schema> | null): void;\n}\n\n/**\n * Retrieves multiple Graffiti objects and retains\n * the most recent one as the `result` property (a Vue ref).\n * Before any objects have been received, the result\n * is `undefined`. If the object has been deleted,\n * the result is `null`.\n */\nexport class SingletonReducer<Schema extends JSONSchema4>\n implements Reducer<Schema>\n{\n readonly result = ref<\n (GraffitiObject<Schema> & { tombstone: false }) | null | undefined\n >(undefined);\n\n clear() {\n this.result.value = undefined;\n }\n\n onObject(object: GraffitiObject<Schema> | null) {\n if (\n !object ||\n !this.result.value ||\n isObjectNewer(object, this.result.value)\n ) {\n if (!object || object.tombstone) {\n this.result.value = null;\n } else {\n this.result.value = object;\n }\n }\n }\n}\n\n/**\n * Retrieves multiple Graffiti objects and retains\n * the most recent one per URI as the `results` property (a Vue ref).\n * If multiple objects are received concurrently,\n * they are processed in batches every `REFRESH_RATE` milliseconds\n * to avoid freezing the interface.\n */\nexport class ArrayReducer<Schema extends JSONSchema4>\n implements Reducer<Schema>\n{\n readonly results = ref<(GraffitiObject<Schema> & { tombstone: false })[]>([]);\n readonly resultsRaw = new Map<string, GraffitiObject<Schema>>();\n batchFlattenTimer: ReturnType<typeof setTimeout> | undefined = undefined;\n\n constructor(readonly graffiti: Graffiti) {}\n\n clear() {\n this.resultsRaw.clear();\n this.results.value = [];\n clearTimeout(this.batchFlattenTimer);\n this.batchFlattenTimer = undefined;\n }\n\n flattenResults() {\n this.results.value = Array.from(this.resultsRaw.values()).reduce<\n (GraffitiObject<Schema> & { tombstone: false })[]\n >((acc, object) => {\n const { tombstone } = object;\n if (!tombstone) {\n acc.push({ ...object, tombstone });\n }\n return acc;\n }, []);\n }\n\n onObject(object: GraffitiObject<Schema> | null) {\n if (!object) return;\n const url = this.graffiti.objectToUri(object);\n const existing = this.resultsRaw.get(url);\n if (existing && !isObjectNewer(object, existing)) return;\n this.resultsRaw.set(url, object);\n\n // Don't flatten the results all at once,\n // because we may get a lot of results\n // and we don't want the interface to\n // freeze up\n if (!this.batchFlattenTimer) {\n this.batchFlattenTimer = setTimeout(() => {\n this.flattenResults();\n this.batchFlattenTimer = undefined;\n }, 0);\n }\n }\n}\n","import {\n onScopeDispose,\n ref,\n toValue,\n watch,\n type MaybeRefOrGetter,\n} from \"vue\";\nimport type {\n GraffitiLocation,\n GraffitiObject,\n GraffitiSession,\n JSONSchema4,\n} from \"@graffiti-garden/api\";\nimport { useGraffiti, useGraffitiSession } from \"./injections\";\nimport type { GraffitiStream } from \"@graffiti-garden/api\";\nimport { GetPoller, Poller, StreamPoller } from \"./pollers\";\nimport { ArrayReducer, Reducer, SingletonReducer } from \"./reducers\";\n\nfunction makeComposable<Schema extends JSONSchema4>(\n reducer: Reducer<Schema>,\n poller: Poller<Schema>,\n synchronizeFactory: () => GraffitiStream<GraffitiObject<Schema>>,\n toWatch: readonly (() => any)[],\n) {\n let synchronizeIterator: GraffitiStream<GraffitiObject<Schema>> | undefined =\n undefined;\n async function pollSynchronize() {\n synchronizeIterator = synchronizeFactory();\n for await (const result of synchronizeIterator) {\n if (result.error) {\n console.error(result.error);\n continue;\n }\n reducer.onObject(result.value);\n }\n }\n\n const poll = () => poller.poll(reducer.onObject.bind(reducer));\n\n const isPolling = ref(false);\n watch(\n toWatch,\n async (newValue, oldValue) => {\n // Catch unnecessary updates\n if (JSON.stringify(newValue) === JSON.stringify(oldValue)) {\n return;\n }\n\n synchronizeIterator?.return();\n reducer.clear();\n poller.clear();\n\n pollSynchronize();\n\n isPolling.value = true;\n try {\n await poll();\n } finally {\n isPolling.value = false;\n }\n },\n {\n immediate: true,\n },\n );\n onScopeDispose(() => synchronizeIterator?.return());\n\n return { poll, isPolling };\n}\n\nfunction toSessionGetter(\n sessionInjected: ReturnType<typeof useGraffitiSession>,\n session?: MaybeRefOrGetter<GraffitiSession | undefined | null>,\n) {\n return () => {\n const sessionValue = toValue(session);\n if (sessionValue === undefined) {\n return sessionInjected?.value;\n } else {\n return sessionValue;\n }\n };\n}\n\nfunction callGetters<T extends readonly (() => any)[]>(\n getters: T,\n): {\n [K in keyof T]: ReturnType<T[K]>;\n} {\n return getters.map((fn) => fn()) as any;\n}\n\n/**\n * A reactive version of the [`Graffiti.discover`](https://api.graffiti.garden/classes/Graffiti.html#discover)\n * method. Its arguments are the same, but now they can be\n * reactive Vue refs or getters. As they change the output will\n * automatically update.\n *\n * Rather than returning a stream of Graffiti objects, this\n * function returns a reactive array of objects. It also\n * provides a method to poll for new results and a boolean\n * ref indicating if the poll is currently running.\n *\n * All [`tombstone`](https://api.graffiti.garden/interfaces/GraffitiObjectBase.html#tombstone)d\n * objects are filtered out.\n *\n * @returns An object containing\n * - `results`: a reactive array of Graffiti objects\n * - `poll`: a method to poll for new results\n * - `isPolling`: a boolean ref indicating if the poll is currently running\n */\nexport function useGraffitiDiscover<Schema extends JSONSchema4>(\n /**\n * A list of channels to discover objects from.\n * Reactivity will only trigger\n * when the root array changes, not when the elements\n * change. If you need reactivity on the elements,\n * create a getter, e.g. `() => [toValue(myReactiveChannel)]`.\n */\n channels: MaybeRefOrGetter<string[]>,\n /**\n * A [JSON Schema](https://json-schema.org/) object describing the schema\n * of the objects to discover. All other objects will be filtered out\n * and the output will be typed as `GraffitiObject<Schema>`.\n * Reactivity only triggers when the root object changes, not when\n * the root object changes, not when the properties change.\n * Create a getter if you need reactivity on the properties.\n */\n schema: MaybeRefOrGetter<Schema>,\n /**\n * A Graffiti session object. If not provided, the\n * global plugin session will be used.\n */\n session?: MaybeRefOrGetter<GraffitiSession | undefined | null>,\n) {\n const graffiti = useGraffiti();\n const sessionInjected = useGraffitiSession();\n\n const channelsGetter = () => toValue(channels);\n const schemaGetter = () => toValue(schema);\n const sessionGetter = toSessionGetter(sessionInjected, session);\n const argGetters = [channelsGetter, schemaGetter, sessionGetter] as const;\n\n const synchronizeFactory = () =>\n graffiti.synchronizeDiscover(...callGetters(argGetters));\n const streamFactory = () => graffiti.discover(...callGetters(argGetters));\n\n const reducer = new ArrayReducer<Schema>(graffiti);\n const poller = new StreamPoller(schemaGetter, streamFactory);\n\n const { poll, isPolling } = makeComposable(\n reducer,\n poller,\n synchronizeFactory,\n argGetters,\n );\n\n return {\n results: reducer.results,\n poll,\n isPolling,\n };\n}\n\n/**\n * A reactive version of the [`Graffiti.get`](https://api.graffiti.garden/classes/Graffiti.html#get)\n * method. Its arguments are the same, but now they can be\n * reactive Vue refs or getters. As they change the output will\n * automatically update.\n *\n * Rather than returning a single Graffiti object, this\n * function returns a reactive object. It also\n * provides a method to poll for new results and a boolean\n * ref indicating if the poll is currently running.\n *\n * While the object is first being fetched, the result\n * is `undefined`. If the object has been deleted,\n * the result is `null`. Otherwise, the result is the\n * most recent object fetched. All [`tombstone`](https://api.graffiti.garden/interfaces/GraffitiObjectBase.html#tombstone)d\n * objects are filtered out.\n *\n * @returns An object containing\n * - `results`: a reactive array of Graffiti objects\n * - `poll`: a method to poll for new results\n * - `isPolling`: a boolean ref indicating if the poll is currently running\n */\nexport function useGraffitiGet<Schema extends JSONSchema4>(\n /**\n * A Graffiti location or URI to fetch the object from.\n */\n locationOrUri: MaybeRefOrGetter<GraffitiLocation | string>,\n /**\n * A [JSON Schema](https://json-schema.org/) object describing the schema\n * of the objects to discover. All other objects will be filtered out\n * and the output will be typed as `GraffitiObject<Schema>`.\n * Like the `channels` argument, reactivity only triggers when\n */\n schema: MaybeRefOrGetter<Schema>,\n /**\n * A Graffiti session object. If not provided, the\n * global plugin session will be used.\n */\n session?: MaybeRefOrGetter<GraffitiSession | undefined | null>,\n) {\n const graffiti = useGraffiti();\n const sessionInjected = useGraffitiSession();\n\n const locationOrUriGetter = () => toValue(locationOrUri);\n const schemaGetter = () => toValue(schema);\n const sessionGetter = toSessionGetter(sessionInjected, session);\n const argGetters = [\n locationOrUriGetter,\n schemaGetter,\n sessionGetter,\n ] as const;\n\n const synchronizeFactory = () =>\n graffiti.synchronizeGet(...callGetters(argGetters));\n\n const reducer = new SingletonReducer<Schema>();\n const poller = new GetPoller(() => graffiti.get(...callGetters(argGetters)));\n\n const { poll, isPolling } = makeComposable(\n reducer,\n poller,\n synchronizeFactory,\n argGetters,\n );\n\n return {\n result: reducer.result,\n poll,\n isPolling,\n };\n}\n\nexport function useGraffitiRecoverOrphans<Schema extends JSONSchema4>(\n schema: MaybeRefOrGetter<Schema>,\n session: MaybeRefOrGetter<GraffitiSession>,\n) {\n const graffiti = useGraffiti();\n\n const schemaGetter = () => toValue(schema);\n const sessionGetter = () => toValue(session);\n const argGetters = [schemaGetter, sessionGetter] as const;\n\n const synchronizeFactory = () =>\n graffiti.synchronizeRecoverOrphans(...callGetters(argGetters));\n\n const reducer = new ArrayReducer<Schema>(graffiti);\n const poller = new StreamPoller(schemaGetter, () =>\n graffiti.recoverOrphans(...callGetters(argGetters)),\n );\n\n const { poll, isPolling } = makeComposable(\n reducer,\n poller,\n synchronizeFactory,\n argGetters,\n );\n\n return {\n results: reducer.results,\n poll,\n isPolling,\n };\n}\n","<script setup lang=\"ts\" generic=\"Schema extends JSONSchema4\">\nimport { toRef } from \"vue\";\nimport type { GraffitiSession, JSONSchema4 } from \"@graffiti-garden/api\";\nimport { useGraffitiDiscover } from \"./composables\";\n\nconst props = defineProps<{\n channels: string[];\n schema: Schema;\n session?: GraffitiSession | null;\n}>();\n\nconst { results, poll, isPolling } = useGraffitiDiscover<Schema>(\n toRef(props, \"channels\"),\n toRef(props, \"schema\"),\n toRef(props, \"session\"),\n);\n</script>\n\n<template>\n <slot :results=\"results\" :poll=\"poll\" :isPolling=\"isPolling\"></slot>\n</template>\n","<script setup lang=\"ts\" generic=\"Schema extends JSONSchema4\">\nimport { toRef } from \"vue\";\nimport type {\n GraffitiLocation,\n GraffitiSession,\n JSONSchema4,\n} from \"@graffiti-garden/api\";\nimport { useGraffitiGet } from \"./composables\";\n\nconst props = defineProps<{\n locationOrUri: string | GraffitiLocation;\n schema: Schema;\n session?: GraffitiSession | null;\n}>();\n\nconst { result, poll, isPolling } = useGraffitiGet<Schema>(\n toRef(props, \"locationOrUri\"),\n toRef(props, \"schema\"),\n toRef(props, \"session\"),\n);\n</script>\n\n<template>\n <slot :result=\"result\" :poll=\"poll\" :isPolling=\"isPolling\"></slot>\n</template>\n","<script setup lang=\"ts\" generic=\"Schema extends JSONSchema4\">\nimport { toRef } from \"vue\";\nimport type { GraffitiSession, JSONSchema4 } from \"@graffiti-garden/api\";\nimport { useGraffitiRecoverOrphans } from \"./composables\";\n\nconst props = defineProps<{\n schema: Schema;\n session: GraffitiSession;\n}>();\n\nconst { results, poll, isPolling } = useGraffitiRecoverOrphans<Schema>(\n toRef(props, \"schema\"),\n toRef(props, \"session\"),\n);\n</script>\n\n<template>\n <slot :results=\"results\" :poll=\"poll\" :isPolling=\"isPolling\"></slot>\n</template>\n","import type { App, Plugin, Ref } from \"vue\";\nimport { ref } from \"vue\";\nimport Discover from \"./Discover.vue\";\nimport Get from \"./Get.vue\";\nimport RecoverOrphans from \"./RecoverOrphans.vue\";\nimport type {\n GraffitiFactory,\n Graffiti,\n GraffitiSession,\n GraffitiLoginEvent,\n GraffitiLogoutEvent,\n GraffitiSessionInitializedEvent,\n} from \"@graffiti-garden/api\";\nimport { graffitiInjectKey, graffitiSessionInjectKey } from \"./injections\";\nimport type { Router } from \"vue-router\";\n\ndeclare module \"vue\" {\n export interface ComponentCustomProperties {\n $graffiti: Graffiti;\n $graffitiSession: Ref<GraffitiSession | undefined | null>;\n }\n\n export interface GlobalComponents {\n GraffitiDiscover: typeof Discover;\n GraffitiGet: typeof Get;\n GraffitiRecoverOrphans: typeof RecoverOrphans;\n }\n}\n\nexport interface GraffitiPluginOptions {\n useGraffiti: GraffitiFactory;\n}\n\nexport const GraffitiPlugin: Plugin<GraffitiPluginOptions> = {\n install(app: App, options: GraffitiPluginOptions) {\n const graffiti = options.useGraffiti();\n const graffitiSession = ref<GraffitiSession | undefined | null>(undefined);\n graffiti.sessionEvents.addEventListener(\"initialized\", async (evt) => {\n const detail = (evt as GraffitiSessionInitializedEvent).detail;\n\n if (detail && detail.error) {\n console.error(detail.error);\n }\n\n if (detail && detail.href) {\n // If we're using Vue Router, redirect to the URL after login\n const router = app.config.globalProperties.$router as\n | Router\n | undefined;\n if (router) {\n const url = new URL(detail.href);\n await router.replace(url.pathname + url.search + url.hash);\n }\n }\n\n // Set the session to \"null\" if the user is not logged in\n if (!graffitiSession.value) {\n graffitiSession.value = null;\n }\n });\n graffiti.sessionEvents.addEventListener(\"login\", (evt) => {\n const detail = (evt as GraffitiLoginEvent).detail;\n if (detail.error) {\n console.error(\"Error logging in:\");\n console.error(detail.error);\n return;\n } else {\n graffitiSession.value = detail.session;\n }\n });\n graffiti.sessionEvents.addEventListener(\"logout\", (evt) => {\n const detail = (evt as GraffitiLogoutEvent).detail;\n if (detail.error) {\n console.error(\"Error logging out:\");\n console.error(detail.error);\n } else {\n graffitiSession.value = null;\n }\n });\n\n app.provide(graffitiInjectKey, graffiti);\n app.provide(graffitiSessionInjectKey, graffitiSession);\n\n app.component(\"GraffitiDiscover\", Discover);\n app.component(\"GraffitiGet\", Get);\n app.component(\"GraffitiRecoverOrphans\", RecoverOrphans);\n app.config.globalProperties.$graffiti = graffiti;\n app.config.globalProperties.$graffitiSession = graffitiSession;\n },\n};\n\nexport * from \"./composables\";\nexport * from \"./injections\";\nexport { Discover as GraffitiDiscover };\nexport { Get as GraffitiGet };\nexport { RecoverOrphans as GraffitiRecoverOrphans };\n"],"names":["graffitiInjectKey","graffitiSessionInjectKey","useGraffiti","graffiti","inject","useGraffitiSession","session","GetPoller","getter","__publicField","onObject","object","StreamPoller","schemaGetter","streamFactory","startOfPoll","schema","_a","myIterator","e","myLastModified","_b","result","tombstoneRetention","G","t","SingletonReducer","ref","isObjectNewer","ArrayReducer","acc","tombstone","url","existing","makeComposable","reducer","poller","synchronizeFactory","toWatch","synchronizeIterator","pollSynchronize","poll","isPolling","watch","newValue","oldValue","onScopeDispose","toSessionGetter","sessionInjected","sessionValue","toValue","callGetters","getters","fn","useGraffitiDiscover","channels","channelsGetter","sessionGetter","argGetters","useGraffitiGet","locationOrUri","locationOrUriGetter","useGraffitiRecoverOrphans","props","__props","results","toRef","GraffitiPlugin","app","options","graffitiSession","evt","detail","router","Discover","Get","RecoverOrphans"],"mappings":"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","x_google_ignoreList":[2]}
package/dist/plugin.js CHANGED
@@ -1,16 +1,16 @@
1
1
  var D = Object.defineProperty;
2
2
  var x = (t, e, s) => e in t ? D(t, e, { enumerable: !0, configurable: !0, writable: !0, value: s }) : t[e] = s;
3
3
  var f = (t, e, s) => x(t, typeof e != "symbol" ? e + "" : e, s);
4
- import { inject as _, ref as v, watch as z, onScopeDispose as L, toValue as m, defineComponent as w, toRef as d, renderSlot as R, unref as h } from "vue";
5
- const E = Symbol(), S = Symbol();
6
- function b() {
7
- const t = _(E);
4
+ import { inject as k, ref as v, watch as z, onScopeDispose as L, toValue as m, defineComponent as w, toRef as d, renderSlot as b, unref as h } from "vue";
5
+ const O = Symbol(), _ = Symbol();
6
+ function R() {
7
+ const t = k(O);
8
8
  if (!t)
9
9
  throw new Error("No Graffiti instance provided");
10
10
  return t;
11
11
  }
12
- function k() {
13
- const t = _(S);
12
+ function S() {
13
+ const t = k(_);
14
14
  if (!t)
15
15
  throw new Error("No Graffiti session provided");
16
16
  return t;
@@ -32,7 +32,7 @@ class U {
32
32
  clear() {
33
33
  }
34
34
  }
35
- class O {
35
+ class M {
36
36
  constructor(e, s) {
37
37
  f(this, "bookmark");
38
38
  f(this, "iterator");
@@ -49,26 +49,26 @@ class O {
49
49
  ...(l = r.properties) == null ? void 0 : l.lastModified
50
50
  }
51
51
  });
52
- let i;
52
+ let n;
53
53
  try {
54
- i = this.streamFactory();
54
+ n = this.streamFactory();
55
55
  } catch (c) {
56
56
  console.error(c);
57
57
  return;
58
58
  }
59
- this.iterator = i;
60
- let o = (u = this.bookmark) == null ? void 0 : u.lastModified, n = await i.next();
61
- for (; !n.done; ) {
62
- if (n.value.error) {
63
- console.error(n.value.error), n = await i.next();
59
+ this.iterator = n;
60
+ let o = (u = this.bookmark) == null ? void 0 : u.lastModified, i = await n.next();
61
+ for (; !i.done; ) {
62
+ if (i.value.error) {
63
+ console.error(i.value.error), i = await n.next();
64
64
  continue;
65
65
  }
66
- const c = n.value.value;
67
- (!o || c.lastModified > o) && (o = c.lastModified), e(c), n = await i.next();
66
+ const c = i.value.value;
67
+ (!o || c.lastModified > o) && (o = c.lastModified), e(c), i = await n.next();
68
68
  }
69
- if (this.iterator !== i) return;
69
+ if (this.iterator !== n) return;
70
70
  this.iterator = void 0;
71
- const { tombstoneRetention: a } = n.value;
71
+ const { tombstoneRetention: a } = i.value;
72
72
  o && (this.bookmark = {
73
73
  lastModified: o,
74
74
  fullRepollBy: s + a
@@ -84,7 +84,7 @@ class O {
84
84
  function F(t, e) {
85
85
  return t.lastModified > e.lastModified || t.lastModified === e.lastModified && !t.tombstone && e.tombstone;
86
86
  }
87
- class A {
87
+ class N {
88
88
  constructor() {
89
89
  f(this, "result", v(void 0));
90
90
  }
@@ -95,10 +95,8 @@ class A {
95
95
  (!e || !this.result.value || F(e, this.result.value)) && (!e || e.tombstone ? this.result.value = null : this.result.value = e);
96
96
  }
97
97
  }
98
- class M {
98
+ class E {
99
99
  constructor(e) {
100
- f(this, "REFRESH_RATE", 100);
101
- // milliseconds
102
100
  f(this, "results", v([]));
103
101
  f(this, "resultsRaw", /* @__PURE__ */ new Map());
104
102
  f(this, "batchFlattenTimer");
@@ -118,14 +116,14 @@ class M {
118
116
  const s = this.graffiti.objectToUri(e), r = this.resultsRaw.get(s);
119
117
  r && !F(e, r) || (this.resultsRaw.set(s, e), this.batchFlattenTimer || (this.batchFlattenTimer = setTimeout(() => {
120
118
  this.flattenResults(), this.batchFlattenTimer = void 0;
121
- }, this.REFRESH_RATE)));
119
+ }, 0)));
122
120
  }
123
121
  }
124
122
  function P(t, e, s, r) {
125
- let i;
123
+ let n;
126
124
  async function o() {
127
- i = s();
128
- for await (const l of i) {
125
+ n = s();
126
+ for await (const l of n) {
129
127
  if (l.error) {
130
128
  console.error(l.error);
131
129
  continue;
@@ -133,14 +131,14 @@ function P(t, e, s, r) {
133
131
  t.onObject(l.value);
134
132
  }
135
133
  }
136
- const n = () => e.poll(t.onObject.bind(t)), a = v(!1);
134
+ const i = () => e.poll(t.onObject.bind(t)), a = v(!1);
137
135
  return z(
138
136
  r,
139
137
  async (l, u) => {
140
138
  if (JSON.stringify(l) !== JSON.stringify(u)) {
141
- i == null || i.return(), t.clear(), e.clear(), o(), a.value = !0;
139
+ n == null || n.return(), t.clear(), e.clear(), o(), a.value = !0;
142
140
  try {
143
- await n();
141
+ await i();
144
142
  } finally {
145
143
  a.value = !1;
146
144
  }
@@ -149,7 +147,7 @@ function P(t, e, s, r) {
149
147
  {
150
148
  immediate: !0
151
149
  }
152
- ), L(() => i == null ? void 0 : i.return()), { poll: n, isPolling: a };
150
+ ), L(() => n == null ? void 0 : n.return()), { poll: i, isPolling: a };
153
151
  }
154
152
  function T(t, e) {
155
153
  return () => {
@@ -160,8 +158,8 @@ function T(t, e) {
160
158
  function p(t) {
161
159
  return t.map((e) => e());
162
160
  }
163
- function N(t, e, s) {
164
- const r = b(), i = k(), o = () => m(t), n = () => m(e), a = T(i, s), l = [o, n, a], u = () => r.synchronizeDiscover(...p(l)), c = () => r.discover(...p(l)), g = new M(r), G = new O(n, c), { poll: y, isPolling: $ } = P(
161
+ function A(t, e, s) {
162
+ const r = R(), n = S(), o = () => m(t), i = () => m(e), a = T(n, s), l = [o, i, a], u = () => r.synchronizeDiscover(...p(l)), c = () => r.discover(...p(l)), g = new E(r), G = new M(i, c), { poll: y, isPolling: $ } = P(
165
163
  g,
166
164
  G,
167
165
  u,
@@ -174,11 +172,11 @@ function N(t, e, s) {
174
172
  };
175
173
  }
176
174
  function B(t, e, s) {
177
- const r = b(), i = k(), o = () => m(t), n = () => m(e), a = T(i, s), l = [
175
+ const r = R(), n = S(), o = () => m(t), i = () => m(e), a = T(n, s), l = [
178
176
  o,
179
- n,
177
+ i,
180
178
  a
181
- ], u = () => r.synchronizeGet(...p(l)), c = new A(), g = new U(() => r.get(...p(l))), { poll: G, isPolling: y } = P(
179
+ ], u = () => r.synchronizeGet(...p(l)), c = new N(), g = new U(() => r.get(...p(l))), { poll: G, isPolling: y } = P(
182
180
  c,
183
181
  g,
184
182
  u,
@@ -191,13 +189,13 @@ function B(t, e, s) {
191
189
  };
192
190
  }
193
191
  function C(t, e) {
194
- const s = b(), r = () => m(t), o = [r, () => m(e)], n = () => s.synchronizeRecoverOrphans(...p(o)), a = new M(s), l = new O(
192
+ const s = R(), r = () => m(t), o = [r, () => m(e)], i = () => s.synchronizeRecoverOrphans(...p(o)), a = new E(s), l = new M(
195
193
  r,
196
194
  () => s.recoverOrphans(...p(o))
197
195
  ), { poll: u, isPolling: c } = P(
198
196
  a,
199
197
  l,
200
- n,
198
+ i,
201
199
  o
202
200
  );
203
201
  return {
@@ -206,7 +204,7 @@ function C(t, e) {
206
204
  isPolling: c
207
205
  };
208
206
  }
209
- const H = /* @__PURE__ */ w({
207
+ const J = /* @__PURE__ */ w({
210
208
  __name: "Discover",
211
209
  props: {
212
210
  channels: {},
@@ -214,18 +212,18 @@ const H = /* @__PURE__ */ w({
214
212
  session: {}
215
213
  },
216
214
  setup(t) {
217
- const e = t, { results: s, poll: r, isPolling: i } = N(
215
+ const e = t, { results: s, poll: r, isPolling: n } = A(
218
216
  d(e, "channels"),
219
217
  d(e, "schema"),
220
218
  d(e, "session")
221
219
  );
222
- return (o, n) => R(o.$slots, "default", {
220
+ return (o, i) => b(o.$slots, "default", {
223
221
  results: h(s),
224
222
  poll: h(r),
225
- isPolling: h(i)
223
+ isPolling: h(n)
226
224
  });
227
225
  }
228
- }), J = /* @__PURE__ */ w({
226
+ }), K = /* @__PURE__ */ w({
229
227
  __name: "Get",
230
228
  props: {
231
229
  locationOrUri: {},
@@ -233,70 +231,71 @@ const H = /* @__PURE__ */ w({
233
231
  session: {}
234
232
  },
235
233
  setup(t) {
236
- const e = t, { result: s, poll: r, isPolling: i } = B(
234
+ const e = t, { result: s, poll: r, isPolling: n } = B(
237
235
  d(e, "locationOrUri"),
238
236
  d(e, "schema"),
239
237
  d(e, "session")
240
238
  );
241
- return (o, n) => R(o.$slots, "default", {
239
+ return (o, i) => b(o.$slots, "default", {
242
240
  result: h(s),
243
241
  poll: h(r),
244
- isPolling: h(i)
242
+ isPolling: h(n)
245
243
  });
246
244
  }
247
- }), K = /* @__PURE__ */ w({
245
+ }), V = /* @__PURE__ */ w({
248
246
  __name: "RecoverOrphans",
249
247
  props: {
250
248
  schema: {},
251
249
  session: {}
252
250
  },
253
251
  setup(t) {
254
- const e = t, { results: s, poll: r, isPolling: i } = C(
252
+ const e = t, { results: s, poll: r, isPolling: n } = C(
255
253
  d(e, "schema"),
256
254
  d(e, "session")
257
255
  );
258
- return (o, n) => R(o.$slots, "default", {
256
+ return (o, i) => b(o.$slots, "default", {
259
257
  results: h(s),
260
258
  poll: h(r),
261
- isPolling: h(i)
259
+ isPolling: h(n)
262
260
  });
263
261
  }
264
262
  }), Q = {
265
263
  install(t, e) {
266
264
  const s = e.useGraffiti(), r = v(void 0);
267
- s.sessionEvents.addEventListener("initialized", (i) => {
268
- const o = i.detail;
269
- if (r.value || (r.value = null), o && o.error && console.error(o.error), o && o.href) {
270
- const n = t.config.globalProperties.$router;
271
- if (n) {
265
+ s.sessionEvents.addEventListener("initialized", async (n) => {
266
+ const o = n.detail;
267
+ if (o && o.error && console.error(o.error), o && o.href) {
268
+ const i = t.config.globalProperties.$router;
269
+ if (i) {
272
270
  const a = new URL(o.href);
273
- n.replace(a.pathname + a.search + a.hash);
271
+ await i.replace(a.pathname + a.search + a.hash);
274
272
  }
275
273
  }
276
- }), s.sessionEvents.addEventListener("login", (i) => {
277
- const o = i.detail;
274
+ r.value || (r.value = null);
275
+ }), s.sessionEvents.addEventListener("login", (n) => {
276
+ const o = n.detail;
278
277
  if (o.error) {
279
278
  console.error("Error logging in:"), console.error(o.error);
280
279
  return;
281
280
  } else
282
281
  r.value = o.session;
283
- }), s.sessionEvents.addEventListener("logout", (i) => {
284
- const o = i.detail;
282
+ }), s.sessionEvents.addEventListener("logout", (n) => {
283
+ const o = n.detail;
285
284
  o.error ? (console.error("Error logging out:"), console.error(o.error)) : r.value = null;
286
- }), t.provide(E, s), t.provide(S, r), t.component("GraffitiDiscover", H), t.component("GraffitiGet", J), t.component("GraffitiRecoverOrphans", K), t.config.globalProperties.$graffiti = s, t.config.globalProperties.$graffitiSession = r;
285
+ }), t.provide(O, s), t.provide(_, r), t.component("GraffitiDiscover", J), t.component("GraffitiGet", K), t.component("GraffitiRecoverOrphans", V), t.config.globalProperties.$graffiti = s, t.config.globalProperties.$graffitiSession = r;
287
286
  }
288
287
  };
289
288
  export {
290
- H as GraffitiDiscover,
291
- J as GraffitiGet,
289
+ J as GraffitiDiscover,
290
+ K as GraffitiGet,
292
291
  Q as GraffitiPlugin,
293
- K as GraffitiRecoverOrphans,
294
- E as graffitiInjectKey,
295
- S as graffitiSessionInjectKey,
296
- b as useGraffiti,
297
- N as useGraffitiDiscover,
292
+ V as GraffitiRecoverOrphans,
293
+ O as graffitiInjectKey,
294
+ _ as graffitiSessionInjectKey,
295
+ R as useGraffiti,
296
+ A as useGraffitiDiscover,
298
297
  B as useGraffitiGet,
299
298
  C as useGraffitiRecoverOrphans,
300
- k as useGraffitiSession
299
+ S as useGraffitiSession
301
300
  };
302
301
  //# sourceMappingURL=plugin.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.js","sources":["../src/injections.ts","../src/pollers.ts","../node_modules/@graffiti-garden/implementation-local/dist/esm/utilities.js","../src/reducers.ts","../src/composables.ts","../src/Discover.vue","../src/Get.vue","../src/RecoverOrphans.vue","../src/plugin.ts"],"sourcesContent":["import { inject } from \"vue\";\nimport type { InjectionKey, Ref } from \"vue\";\nimport type { Graffiti, GraffitiSession } from \"@graffiti-garden/api\";\n\nexport const graffitiInjectKey = Symbol() as InjectionKey<Graffiti>;\nexport const graffitiSessionInjectKey = Symbol() as InjectionKey<\n Ref<GraffitiSession | undefined | null>\n>;\n\nexport function useGraffiti() {\n const graffiti = inject(graffitiInjectKey);\n if (!graffiti) {\n throw new Error(\"No Graffiti instance provided\");\n }\n return graffiti;\n}\n\nexport function useGraffitiSession() {\n const session = inject(graffitiSessionInjectKey);\n if (!session) {\n throw new Error(\"No Graffiti session provided\");\n }\n return session;\n}\n","import type {\n Graffiti,\n JSONSchema4,\n GraffitiObject,\n} from \"@graffiti-garden/api\";\n\nexport abstract class Poller<Schema extends JSONSchema4> {\n abstract poll(\n onObject: (object: GraffitiObject<Schema> | null) => void,\n ): Promise<void>;\n abstract clear(): void;\n}\n\n/**\n * Polls for a single object and calls onValue with the result.\n */\nexport class GetPoller<Schema extends JSONSchema4> implements Poller<Schema> {\n constructor(readonly getter: () => Promise<GraffitiObject<Schema>>) {}\n\n poll: Poller<Schema>[\"poll\"] = async (onObject) => {\n let object: GraffitiObject<Schema>;\n try {\n object = await this.getter();\n } catch (e) {\n onObject(null);\n return;\n }\n onObject(object);\n };\n\n clear() {}\n}\n\n/**\n * Polls for multiple objects and calls `onObject` with the result.\n * If `poll` is called multiple times, it doesn't poll the results\n * entirely from scratch, but instead only polls the new results.\n */\nexport class StreamPoller<Schema extends JSONSchema4>\n implements Poller<Schema>\n{\n bookmark:\n | {\n lastModified: number;\n fullRepollBy: number;\n }\n | undefined = undefined;\n iterator: ReturnType<typeof Graffiti.prototype.discover<Schema>> | undefined =\n undefined;\n\n constructor(\n readonly schemaGetter: () => Schema,\n readonly streamFactory: () => ReturnType<\n typeof Graffiti.prototype.discover<Schema>\n >,\n ) {}\n\n clear() {\n this.bookmark = undefined;\n this.iterator?.return({ tombstoneRetention: 0 });\n this.iterator = undefined;\n }\n\n poll: Poller<Schema>[\"poll\"] = async (onObject) => {\n const startOfPoll = new Date().getTime();\n\n // Add a query for lastModified if it's not in the schema\n const schema = { ...this.schemaGetter() };\n if (this.bookmark && this.bookmark.fullRepollBy > startOfPoll) {\n schema.properties = {\n ...schema.properties,\n lastModified: {\n minimum: this.bookmark.lastModified,\n // if the schema already has a minimum\n // it won't be overridden because\n // the schema below takes precedence\n ...schema.properties?.lastModified,\n },\n };\n }\n\n let myIterator: ReturnType<typeof Graffiti.prototype.discover<Schema>>;\n try {\n myIterator = this.streamFactory();\n } catch (e) {\n console.error(e);\n return;\n }\n\n // Claim the spot as the current iterator\n this.iterator = myIterator;\n\n // Keep track of the latest lastModified value\n // while streaming results\n let myLastModified = this.bookmark?.lastModified;\n let result = await myIterator.next();\n while (!result.done) {\n if (result.value.error) {\n console.error(result.value.error);\n result = await myIterator.next();\n continue;\n }\n\n const object = result.value.value;\n if (!myLastModified || object.lastModified > myLastModified) {\n myLastModified = object.lastModified;\n }\n\n onObject(object);\n\n result = await myIterator.next();\n }\n\n // Make sure we're still the current iterator\n if (this.iterator !== myIterator) return;\n\n // We've successfully polled all results\n // without getting overridden\n this.iterator = undefined;\n\n // Only now do we update the cache parameters\n // because the results may have appeared out\n // of order\n const { tombstoneRetention } = result.value;\n if (myLastModified) {\n this.bookmark = {\n lastModified: myLastModified,\n fullRepollBy: startOfPoll + tombstoneRetention,\n };\n }\n };\n}\n","import{GraffitiErrorInvalidSchema as n,GraffitiErrorInvalidUri as f,GraffitiErrorPatchError as c,GraffitiErrorPatchTestFailed as s}from\"@graffiti-garden/api\";const p=e=>`${e.source}/${encodeURIComponent(e.actor)}/${encodeURIComponent(e.name)}`,d=e=>{const t=e.split(\"/\"),r=t.pop(),o=t.pop();if(!r||!o||!t.length)throw new f;return{name:decodeURIComponent(r),actor:decodeURIComponent(o),source:t.join(\"/\")}};function l(e=16){const t=new Uint8Array(e);return crypto.getRandomValues(t),btoa(String.fromCodePoint(...t)).replace(/\\+/g,\"-\").replace(/\\//g,\"_\").replace(/\\=+$/,\"\")}function u(e){return typeof e==\"string\"?{location:d(e),uri:e}:{location:{name:e.name,actor:e.actor,source:e.source},uri:p(e)}}function G(e,t){return e.lastModified>t.lastModified||e.lastModified===t.lastModified&&!e.tombstone&&t.tombstone}function h(e,t,r,o){const i=r[t];if(!(!i||!i.length))try{o[t]=e(o[t],i,!0,!1).newDocument}catch(a){throw typeof a==\"object\"&&a&&\"name\"in a&&typeof a.name==\"string\"&&\"message\"in a&&typeof a.message==\"string\"?a.name===\"TEST_OPERATION_FAILED\"?new s(a.message):new c(a.name+\": \"+a.message):a}}function w(e,t){try{return e.compile(t)}catch(r){throw new n(r instanceof Error?r.message:void 0)}}function y(e,t,r){e.actor!==r?.actor&&(e.allowed=e.allowed&&r?[r.actor]:void 0,e.channels=e.channels.filter(o=>t.includes(o)))}function g(e,t){return e.allowed===void 0||e.allowed===null||!!t?.actor&&(e.actor===t.actor||e.allowed.includes(t.actor))}export{h as applyGraffitiPatch,w as attemptAjvCompile,g as isActorAllowedGraffitiObject,G as isObjectNewer,p as locationToUri,y as maskGraffitiObject,l as randomBase64,u as unpackLocationOrUri,d as uriToLocation};\n//# sourceMappingURL=utilities.js.map\n","import { ref } from \"vue\";\nimport type { JSONSchema4 } from \"@graffiti-garden/api\";\nimport type { GraffitiObject, Graffiti } from \"@graffiti-garden/api\";\nimport { isObjectNewer } from \"@graffiti-garden/implementation-local/utilities\";\n\nexport abstract class Reducer<Schema extends JSONSchema4> {\n abstract clear(): void;\n abstract onObject(object: GraffitiObject<Schema> | null): void;\n}\n\n/**\n * Retrieves multiple Graffiti objects and retains\n * the most recent one as the `result` property (a Vue ref).\n * Before any objects have been received, the result\n * is `undefined`. If the object has been deleted,\n * the result is `null`.\n */\nexport class SingletonReducer<Schema extends JSONSchema4>\n implements Reducer<Schema>\n{\n readonly result = ref<\n (GraffitiObject<Schema> & { tombstone: false }) | null | undefined\n >(undefined);\n\n clear() {\n this.result.value = undefined;\n }\n\n onObject(object: GraffitiObject<Schema> | null) {\n if (\n !object ||\n !this.result.value ||\n isObjectNewer(object, this.result.value)\n ) {\n if (!object || object.tombstone) {\n this.result.value = null;\n } else {\n this.result.value = object;\n }\n }\n }\n}\n\n/**\n * Retrieves multiple Graffiti objects and retains\n * the most recent one per URI as the `results` property (a Vue ref).\n * If multiple objects are received concurrently,\n * they are processed in batches every `REFRESH_RATE` milliseconds\n * to avoid freezing the interface.\n */\nexport class ArrayReducer<Schema extends JSONSchema4>\n implements Reducer<Schema>\n{\n REFRESH_RATE = 100; // milliseconds\n readonly results = ref<(GraffitiObject<Schema> & { tombstone: false })[]>([]);\n readonly resultsRaw = new Map<string, GraffitiObject<Schema>>();\n batchFlattenTimer: ReturnType<typeof setTimeout> | undefined = undefined;\n\n constructor(readonly graffiti: Graffiti) {}\n\n clear() {\n this.resultsRaw.clear();\n this.results.value = [];\n clearTimeout(this.batchFlattenTimer);\n this.batchFlattenTimer = undefined;\n }\n\n flattenResults() {\n this.results.value = Array.from(this.resultsRaw.values()).reduce<\n (GraffitiObject<Schema> & { tombstone: false })[]\n >((acc, object) => {\n const { tombstone } = object;\n if (!tombstone) {\n acc.push({ ...object, tombstone });\n }\n return acc;\n }, []);\n }\n\n onObject(object: GraffitiObject<Schema> | null) {\n if (!object) return;\n const url = this.graffiti.objectToUri(object);\n const existing = this.resultsRaw.get(url);\n if (existing && !isObjectNewer(object, existing)) return;\n this.resultsRaw.set(url, object);\n\n // Don't flatten the results all at once,\n // because we may get a lot of results\n // and we don't want the interface to\n // freeze up\n if (!this.batchFlattenTimer) {\n this.batchFlattenTimer = setTimeout(() => {\n this.flattenResults();\n this.batchFlattenTimer = undefined;\n }, this.REFRESH_RATE);\n }\n }\n}\n","import {\n onScopeDispose,\n ref,\n toValue,\n watch,\n type MaybeRefOrGetter,\n} from \"vue\";\nimport type {\n GraffitiLocation,\n GraffitiObject,\n GraffitiSession,\n JSONSchema4,\n} from \"@graffiti-garden/api\";\nimport { useGraffiti, useGraffitiSession } from \"./injections\";\nimport type { GraffitiStream } from \"@graffiti-garden/api\";\nimport { GetPoller, Poller, StreamPoller } from \"./pollers\";\nimport { ArrayReducer, Reducer, SingletonReducer } from \"./reducers\";\n\nfunction makeComposable<Schema extends JSONSchema4>(\n reducer: Reducer<Schema>,\n poller: Poller<Schema>,\n synchronizeFactory: () => GraffitiStream<GraffitiObject<Schema>>,\n toWatch: readonly (() => any)[],\n) {\n let synchronizeIterator: GraffitiStream<GraffitiObject<Schema>> | undefined =\n undefined;\n async function pollSynchronize() {\n synchronizeIterator = synchronizeFactory();\n for await (const result of synchronizeIterator) {\n if (result.error) {\n console.error(result.error);\n continue;\n }\n reducer.onObject(result.value);\n }\n }\n\n const poll = () => poller.poll(reducer.onObject.bind(reducer));\n\n const isPolling = ref(false);\n watch(\n toWatch,\n async (newValue, oldValue) => {\n // Catch unnecessary updates\n if (JSON.stringify(newValue) === JSON.stringify(oldValue)) {\n return;\n }\n\n synchronizeIterator?.return();\n reducer.clear();\n poller.clear();\n\n pollSynchronize();\n\n isPolling.value = true;\n try {\n await poll();\n } finally {\n isPolling.value = false;\n }\n },\n {\n immediate: true,\n },\n );\n onScopeDispose(() => synchronizeIterator?.return());\n\n return { poll, isPolling };\n}\n\nfunction toSessionGetter(\n sessionInjected: ReturnType<typeof useGraffitiSession>,\n session?: MaybeRefOrGetter<GraffitiSession | undefined | null>,\n) {\n return () => {\n const sessionValue = toValue(session);\n if (sessionValue === undefined) {\n return sessionInjected?.value;\n } else {\n return sessionValue;\n }\n };\n}\n\nfunction callGetters<T extends readonly (() => any)[]>(\n getters: T,\n): {\n [K in keyof T]: ReturnType<T[K]>;\n} {\n return getters.map((fn) => fn()) as any;\n}\n\n/**\n * A reactive version of the [`Graffiti.discover`](https://api.graffiti.garden/classes/Graffiti.html#discover)\n * method. Its arguments are the same, but now they can be\n * reactive Vue refs or getters. As they change the output will\n * automatically update.\n *\n * Rather than returning a stream of Graffiti objects, this\n * function returns a reactive array of objects. It also\n * provides a method to poll for new results and a boolean\n * ref indicating if the poll is currently running.\n *\n * All [`tombstone`](https://api.graffiti.garden/interfaces/GraffitiObjectBase.html#tombstone)d\n * objects are filtered out.\n *\n * @returns An object containing\n * - `results`: a reactive array of Graffiti objects\n * - `poll`: a method to poll for new results\n * - `isPolling`: a boolean ref indicating if the poll is currently running\n */\nexport function useGraffitiDiscover<Schema extends JSONSchema4>(\n /**\n * A list of channels to discover objects from.\n * Reactivity will only trigger\n * when the root array changes, not when the elements\n * change. If you need reactivity on the elements,\n * create a getter, e.g. `() => [toValue(myReactiveChannel)]`.\n */\n channels: MaybeRefOrGetter<string[]>,\n /**\n * A [JSON Schema](https://json-schema.org/) object describing the schema\n * of the objects to discover. All other objects will be filtered out\n * and the output will be typed as `GraffitiObject<Schema>`.\n * Reactivity only triggers when the root object changes, not when\n * the root object changes, not when the properties change.\n * Create a getter if you need reactivity on the properties.\n */\n schema: MaybeRefOrGetter<Schema>,\n /**\n * A Graffiti session object. If not provided, the\n * global plugin session will be used.\n */\n session?: MaybeRefOrGetter<GraffitiSession | undefined | null>,\n) {\n const graffiti = useGraffiti();\n const sessionInjected = useGraffitiSession();\n\n const channelsGetter = () => toValue(channels);\n const schemaGetter = () => toValue(schema);\n const sessionGetter = toSessionGetter(sessionInjected, session);\n const argGetters = [channelsGetter, schemaGetter, sessionGetter] as const;\n\n const synchronizeFactory = () =>\n graffiti.synchronizeDiscover(...callGetters(argGetters));\n const streamFactory = () => graffiti.discover(...callGetters(argGetters));\n\n const reducer = new ArrayReducer<Schema>(graffiti);\n const poller = new StreamPoller(schemaGetter, streamFactory);\n\n const { poll, isPolling } = makeComposable(\n reducer,\n poller,\n synchronizeFactory,\n argGetters,\n );\n\n return {\n results: reducer.results,\n poll,\n isPolling,\n };\n}\n\n/**\n * A reactive version of the [`Graffiti.get`](https://api.graffiti.garden/classes/Graffiti.html#get)\n * method. Its arguments are the same, but now they can be\n * reactive Vue refs or getters. As they change the output will\n * automatically update.\n *\n * Rather than returning a single Graffiti object, this\n * function returns a reactive object. It also\n * provides a method to poll for new results and a boolean\n * ref indicating if the poll is currently running.\n *\n * While the object is first being fetched, the result\n * is `undefined`. If the object has been deleted,\n * the result is `null`. Otherwise, the result is the\n * most recent object fetched. All [`tombstone`](https://api.graffiti.garden/interfaces/GraffitiObjectBase.html#tombstone)d\n * objects are filtered out.\n *\n * @returns An object containing\n * - `results`: a reactive array of Graffiti objects\n * - `poll`: a method to poll for new results\n * - `isPolling`: a boolean ref indicating if the poll is currently running\n */\nexport function useGraffitiGet<Schema extends JSONSchema4>(\n /**\n * A Graffiti location or URI to fetch the object from.\n */\n locationOrUri: MaybeRefOrGetter<GraffitiLocation | string>,\n /**\n * A [JSON Schema](https://json-schema.org/) object describing the schema\n * of the objects to discover. All other objects will be filtered out\n * and the output will be typed as `GraffitiObject<Schema>`.\n * Like the `channels` argument, reactivity only triggers when\n */\n schema: MaybeRefOrGetter<Schema>,\n /**\n * A Graffiti session object. If not provided, the\n * global plugin session will be used.\n */\n session?: MaybeRefOrGetter<GraffitiSession | undefined | null>,\n) {\n const graffiti = useGraffiti();\n const sessionInjected = useGraffitiSession();\n\n const locationOrUriGetter = () => toValue(locationOrUri);\n const schemaGetter = () => toValue(schema);\n const sessionGetter = toSessionGetter(sessionInjected, session);\n const argGetters = [\n locationOrUriGetter,\n schemaGetter,\n sessionGetter,\n ] as const;\n\n const synchronizeFactory = () =>\n graffiti.synchronizeGet(...callGetters(argGetters));\n\n const reducer = new SingletonReducer<Schema>();\n const poller = new GetPoller(() => graffiti.get(...callGetters(argGetters)));\n\n const { poll, isPolling } = makeComposable(\n reducer,\n poller,\n synchronizeFactory,\n argGetters,\n );\n\n return {\n result: reducer.result,\n poll,\n isPolling,\n };\n}\n\nexport function useGraffitiRecoverOrphans<Schema extends JSONSchema4>(\n schema: MaybeRefOrGetter<Schema>,\n session: MaybeRefOrGetter<GraffitiSession>,\n) {\n const graffiti = useGraffiti();\n\n const schemaGetter = () => toValue(schema);\n const sessionGetter = () => toValue(session);\n const argGetters = [schemaGetter, sessionGetter] as const;\n\n const synchronizeFactory = () =>\n graffiti.synchronizeRecoverOrphans(...callGetters(argGetters));\n\n const reducer = new ArrayReducer<Schema>(graffiti);\n const poller = new StreamPoller(schemaGetter, () =>\n graffiti.recoverOrphans(...callGetters(argGetters)),\n );\n\n const { poll, isPolling } = makeComposable(\n reducer,\n poller,\n synchronizeFactory,\n argGetters,\n );\n\n return {\n results: reducer.results,\n poll,\n isPolling,\n };\n}\n","<script setup lang=\"ts\" generic=\"Schema extends JSONSchema4\">\nimport { toRef } from \"vue\";\nimport type { GraffitiSession, JSONSchema4 } from \"@graffiti-garden/api\";\nimport { useGraffitiDiscover } from \"./composables\";\n\nconst props = defineProps<{\n channels: string[];\n schema: Schema;\n session?: GraffitiSession | null;\n}>();\n\nconst { results, poll, isPolling } = useGraffitiDiscover<Schema>(\n toRef(props, \"channels\"),\n toRef(props, \"schema\"),\n toRef(props, \"session\"),\n);\n</script>\n\n<template>\n <slot :results=\"results\" :poll=\"poll\" :isPolling=\"isPolling\"></slot>\n</template>\n","<script setup lang=\"ts\" generic=\"Schema extends JSONSchema4\">\nimport { toRef } from \"vue\";\nimport type {\n GraffitiLocation,\n GraffitiSession,\n JSONSchema4,\n} from \"@graffiti-garden/api\";\nimport { useGraffitiGet } from \"./composables\";\n\nconst props = defineProps<{\n locationOrUri: string | GraffitiLocation;\n schema: Schema;\n session?: GraffitiSession | null;\n}>();\n\nconst { result, poll, isPolling } = useGraffitiGet<Schema>(\n toRef(props, \"locationOrUri\"),\n toRef(props, \"schema\"),\n toRef(props, \"session\"),\n);\n</script>\n\n<template>\n <slot :result=\"result\" :poll=\"poll\" :isPolling=\"isPolling\"></slot>\n</template>\n","<script setup lang=\"ts\" generic=\"Schema extends JSONSchema4\">\nimport { toRef } from \"vue\";\nimport type { GraffitiSession, JSONSchema4 } from \"@graffiti-garden/api\";\nimport { useGraffitiRecoverOrphans } from \"./composables\";\n\nconst props = defineProps<{\n schema: Schema;\n session: GraffitiSession;\n}>();\n\nconst { results, poll, isPolling } = useGraffitiRecoverOrphans<Schema>(\n toRef(props, \"schema\"),\n toRef(props, \"session\"),\n);\n</script>\n\n<template>\n <slot :results=\"results\" :poll=\"poll\" :isPolling=\"isPolling\"></slot>\n</template>\n","import type { App, Plugin, Ref } from \"vue\";\nimport { ref } from \"vue\";\nimport Discover from \"./Discover.vue\";\nimport Get from \"./Get.vue\";\nimport RecoverOrphans from \"./RecoverOrphans.vue\";\nimport type {\n GraffitiFactory,\n Graffiti,\n GraffitiSession,\n GraffitiLoginEvent,\n GraffitiLogoutEvent,\n GraffitiSessionInitializedEvent,\n} from \"@graffiti-garden/api\";\nimport { graffitiInjectKey, graffitiSessionInjectKey } from \"./injections\";\nimport type { Router } from \"vue-router\";\n\ndeclare module \"vue\" {\n export interface ComponentCustomProperties {\n $graffiti: Graffiti;\n $graffitiSession: Ref<GraffitiSession | undefined | null>;\n }\n\n export interface GlobalComponents {\n GraffitiDiscover: typeof Discover;\n GraffitiGet: typeof Get;\n GraffitiRecoverOrphans: typeof RecoverOrphans;\n }\n}\n\nexport interface GraffitiPluginOptions {\n useGraffiti: GraffitiFactory;\n}\n\nexport const GraffitiPlugin: Plugin<GraffitiPluginOptions> = {\n install(app: App, options: GraffitiPluginOptions) {\n const graffiti = options.useGraffiti();\n const graffitiSession = ref<GraffitiSession | undefined | null>(undefined);\n graffiti.sessionEvents.addEventListener(\"initialized\", (evt) => {\n const detail = (evt as GraffitiSessionInitializedEvent).detail;\n\n // Set the session to \"null\" if the user is not logged in\n if (!graffitiSession.value) {\n graffitiSession.value = null;\n }\n\n if (detail && detail.error) {\n console.error(detail.error);\n }\n\n if (detail && detail.href) {\n // If we're using Vue Router, redirect to the URL after login\n const router = app.config.globalProperties.$router as\n | Router\n | undefined;\n if (router) {\n const url = new URL(detail.href);\n router.replace(url.pathname + url.search + url.hash);\n }\n }\n });\n graffiti.sessionEvents.addEventListener(\"login\", (evt) => {\n const detail = (evt as GraffitiLoginEvent).detail;\n if (detail.error) {\n console.error(\"Error logging in:\");\n console.error(detail.error);\n return;\n } else {\n graffitiSession.value = detail.session;\n }\n });\n graffiti.sessionEvents.addEventListener(\"logout\", (evt) => {\n const detail = (evt as GraffitiLogoutEvent).detail;\n if (detail.error) {\n console.error(\"Error logging out:\");\n console.error(detail.error);\n } else {\n graffitiSession.value = null;\n }\n });\n\n app.provide(graffitiInjectKey, graffiti);\n app.provide(graffitiSessionInjectKey, graffitiSession);\n\n app.component(\"GraffitiDiscover\", Discover);\n app.component(\"GraffitiGet\", Get);\n app.component(\"GraffitiRecoverOrphans\", RecoverOrphans);\n app.config.globalProperties.$graffiti = graffiti;\n app.config.globalProperties.$graffitiSession = graffitiSession;\n },\n};\n\nexport * from \"./composables\";\nexport * from \"./injections\";\nexport { Discover as GraffitiDiscover };\nexport { Get as GraffitiGet };\nexport { RecoverOrphans as GraffitiRecoverOrphans };\n"],"names":["graffitiInjectKey","graffitiSessionInjectKey","useGraffiti","graffiti","inject","useGraffitiSession","session","GetPoller","getter","__publicField","onObject","object","StreamPoller","schemaGetter","streamFactory","startOfPoll","schema","_a","myIterator","e","myLastModified","_b","result","tombstoneRetention","G","t","SingletonReducer","ref","isObjectNewer","ArrayReducer","acc","tombstone","url","existing","makeComposable","reducer","poller","synchronizeFactory","toWatch","synchronizeIterator","pollSynchronize","poll","isPolling","watch","newValue","oldValue","onScopeDispose","toSessionGetter","sessionInjected","sessionValue","toValue","callGetters","getters","fn","useGraffitiDiscover","channels","channelsGetter","sessionGetter","argGetters","useGraffitiGet","locationOrUri","locationOrUriGetter","useGraffitiRecoverOrphans","props","__props","results","toRef","GraffitiPlugin","app","options","graffitiSession","evt","detail","router","Discover","Get","RecoverOrphans"],"mappings":"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","x_google_ignoreList":[2]}
1
+ {"version":3,"file":"plugin.js","sources":["../src/injections.ts","../src/pollers.ts","../node_modules/@graffiti-garden/implementation-local/dist/esm/utilities.js","../src/reducers.ts","../src/composables.ts","../src/Discover.vue","../src/Get.vue","../src/RecoverOrphans.vue","../src/plugin.ts"],"sourcesContent":["import { inject } from \"vue\";\nimport type { InjectionKey, Ref } from \"vue\";\nimport type { Graffiti, GraffitiSession } from \"@graffiti-garden/api\";\n\nexport const graffitiInjectKey = Symbol() as InjectionKey<Graffiti>;\nexport const graffitiSessionInjectKey = Symbol() as InjectionKey<\n Ref<GraffitiSession | undefined | null>\n>;\n\nexport function useGraffiti() {\n const graffiti = inject(graffitiInjectKey);\n if (!graffiti) {\n throw new Error(\"No Graffiti instance provided\");\n }\n return graffiti;\n}\n\nexport function useGraffitiSession() {\n const session = inject(graffitiSessionInjectKey);\n if (!session) {\n throw new Error(\"No Graffiti session provided\");\n }\n return session;\n}\n","import type {\n Graffiti,\n JSONSchema4,\n GraffitiObject,\n} from \"@graffiti-garden/api\";\n\nexport abstract class Poller<Schema extends JSONSchema4> {\n abstract poll(\n onObject: (object: GraffitiObject<Schema> | null) => void,\n ): Promise<void>;\n abstract clear(): void;\n}\n\n/**\n * Polls for a single object and calls onValue with the result.\n */\nexport class GetPoller<Schema extends JSONSchema4> implements Poller<Schema> {\n constructor(readonly getter: () => Promise<GraffitiObject<Schema>>) {}\n\n poll: Poller<Schema>[\"poll\"] = async (onObject) => {\n let object: GraffitiObject<Schema>;\n try {\n object = await this.getter();\n } catch (e) {\n onObject(null);\n return;\n }\n onObject(object);\n };\n\n clear() {}\n}\n\n/**\n * Polls for multiple objects and calls `onObject` with the result.\n * If `poll` is called multiple times, it doesn't poll the results\n * entirely from scratch, but instead only polls the new results.\n */\nexport class StreamPoller<Schema extends JSONSchema4>\n implements Poller<Schema>\n{\n bookmark:\n | {\n lastModified: number;\n fullRepollBy: number;\n }\n | undefined = undefined;\n iterator: ReturnType<typeof Graffiti.prototype.discover<Schema>> | undefined =\n undefined;\n\n constructor(\n readonly schemaGetter: () => Schema,\n readonly streamFactory: () => ReturnType<\n typeof Graffiti.prototype.discover<Schema>\n >,\n ) {}\n\n clear() {\n this.bookmark = undefined;\n this.iterator?.return({ tombstoneRetention: 0 });\n this.iterator = undefined;\n }\n\n poll: Poller<Schema>[\"poll\"] = async (onObject) => {\n const startOfPoll = new Date().getTime();\n\n // Add a query for lastModified if it's not in the schema\n const schema = { ...this.schemaGetter() };\n if (this.bookmark && this.bookmark.fullRepollBy > startOfPoll) {\n schema.properties = {\n ...schema.properties,\n lastModified: {\n minimum: this.bookmark.lastModified,\n // if the schema already has a minimum\n // it won't be overridden because\n // the schema below takes precedence\n ...schema.properties?.lastModified,\n },\n };\n }\n\n let myIterator: ReturnType<typeof Graffiti.prototype.discover<Schema>>;\n try {\n myIterator = this.streamFactory();\n } catch (e) {\n console.error(e);\n return;\n }\n\n // Claim the spot as the current iterator\n this.iterator = myIterator;\n\n // Keep track of the latest lastModified value\n // while streaming results\n let myLastModified = this.bookmark?.lastModified;\n let result = await myIterator.next();\n while (!result.done) {\n if (result.value.error) {\n console.error(result.value.error);\n result = await myIterator.next();\n continue;\n }\n\n const object = result.value.value;\n if (!myLastModified || object.lastModified > myLastModified) {\n myLastModified = object.lastModified;\n }\n\n onObject(object);\n\n result = await myIterator.next();\n }\n\n // Make sure we're still the current iterator\n if (this.iterator !== myIterator) return;\n\n // We've successfully polled all results\n // without getting overridden\n this.iterator = undefined;\n\n // Only now do we update the cache parameters\n // because the results may have appeared out\n // of order\n const { tombstoneRetention } = result.value;\n if (myLastModified) {\n this.bookmark = {\n lastModified: myLastModified,\n fullRepollBy: startOfPoll + tombstoneRetention,\n };\n }\n };\n}\n","import{GraffitiErrorInvalidSchema as n,GraffitiErrorInvalidUri as f,GraffitiErrorPatchError as c,GraffitiErrorPatchTestFailed as s}from\"@graffiti-garden/api\";const p=e=>`${e.source}/${encodeURIComponent(e.actor)}/${encodeURIComponent(e.name)}`,d=e=>{const t=e.split(\"/\"),r=t.pop(),o=t.pop();if(!r||!o||!t.length)throw new f;return{name:decodeURIComponent(r),actor:decodeURIComponent(o),source:t.join(\"/\")}};function l(e=16){const t=new Uint8Array(e);return crypto.getRandomValues(t),btoa(String.fromCodePoint(...t)).replace(/\\+/g,\"-\").replace(/\\//g,\"_\").replace(/\\=+$/,\"\")}function u(e){return typeof e==\"string\"?{location:d(e),uri:e}:{location:{name:e.name,actor:e.actor,source:e.source},uri:p(e)}}function G(e,t){return e.lastModified>t.lastModified||e.lastModified===t.lastModified&&!e.tombstone&&t.tombstone}function h(e,t,r,o){const i=r[t];if(!(!i||!i.length))try{o[t]=e(o[t],i,!0,!1).newDocument}catch(a){throw typeof a==\"object\"&&a&&\"name\"in a&&typeof a.name==\"string\"&&\"message\"in a&&typeof a.message==\"string\"?a.name===\"TEST_OPERATION_FAILED\"?new s(a.message):new c(a.name+\": \"+a.message):a}}function w(e,t){try{return e.compile(t)}catch(r){throw new n(r instanceof Error?r.message:void 0)}}function y(e,t,r){e.actor!==r?.actor&&(e.allowed=e.allowed&&r?[r.actor]:void 0,e.channels=e.channels.filter(o=>t.includes(o)))}function g(e,t){return e.allowed===void 0||e.allowed===null||!!t?.actor&&(e.actor===t.actor||e.allowed.includes(t.actor))}export{h as applyGraffitiPatch,w as attemptAjvCompile,g as isActorAllowedGraffitiObject,G as isObjectNewer,p as locationToUri,y as maskGraffitiObject,l as randomBase64,u as unpackLocationOrUri,d as uriToLocation};\n//# sourceMappingURL=utilities.js.map\n","import { ref } from \"vue\";\nimport type { JSONSchema4 } from \"@graffiti-garden/api\";\nimport type { GraffitiObject, Graffiti } from \"@graffiti-garden/api\";\nimport { isObjectNewer } from \"@graffiti-garden/implementation-local/utilities\";\n\nexport abstract class Reducer<Schema extends JSONSchema4> {\n abstract clear(): void;\n abstract onObject(object: GraffitiObject<Schema> | null): void;\n}\n\n/**\n * Retrieves multiple Graffiti objects and retains\n * the most recent one as the `result` property (a Vue ref).\n * Before any objects have been received, the result\n * is `undefined`. If the object has been deleted,\n * the result is `null`.\n */\nexport class SingletonReducer<Schema extends JSONSchema4>\n implements Reducer<Schema>\n{\n readonly result = ref<\n (GraffitiObject<Schema> & { tombstone: false }) | null | undefined\n >(undefined);\n\n clear() {\n this.result.value = undefined;\n }\n\n onObject(object: GraffitiObject<Schema> | null) {\n if (\n !object ||\n !this.result.value ||\n isObjectNewer(object, this.result.value)\n ) {\n if (!object || object.tombstone) {\n this.result.value = null;\n } else {\n this.result.value = object;\n }\n }\n }\n}\n\n/**\n * Retrieves multiple Graffiti objects and retains\n * the most recent one per URI as the `results` property (a Vue ref).\n * If multiple objects are received concurrently,\n * they are processed in batches every `REFRESH_RATE` milliseconds\n * to avoid freezing the interface.\n */\nexport class ArrayReducer<Schema extends JSONSchema4>\n implements Reducer<Schema>\n{\n readonly results = ref<(GraffitiObject<Schema> & { tombstone: false })[]>([]);\n readonly resultsRaw = new Map<string, GraffitiObject<Schema>>();\n batchFlattenTimer: ReturnType<typeof setTimeout> | undefined = undefined;\n\n constructor(readonly graffiti: Graffiti) {}\n\n clear() {\n this.resultsRaw.clear();\n this.results.value = [];\n clearTimeout(this.batchFlattenTimer);\n this.batchFlattenTimer = undefined;\n }\n\n flattenResults() {\n this.results.value = Array.from(this.resultsRaw.values()).reduce<\n (GraffitiObject<Schema> & { tombstone: false })[]\n >((acc, object) => {\n const { tombstone } = object;\n if (!tombstone) {\n acc.push({ ...object, tombstone });\n }\n return acc;\n }, []);\n }\n\n onObject(object: GraffitiObject<Schema> | null) {\n if (!object) return;\n const url = this.graffiti.objectToUri(object);\n const existing = this.resultsRaw.get(url);\n if (existing && !isObjectNewer(object, existing)) return;\n this.resultsRaw.set(url, object);\n\n // Don't flatten the results all at once,\n // because we may get a lot of results\n // and we don't want the interface to\n // freeze up\n if (!this.batchFlattenTimer) {\n this.batchFlattenTimer = setTimeout(() => {\n this.flattenResults();\n this.batchFlattenTimer = undefined;\n }, 0);\n }\n }\n}\n","import {\n onScopeDispose,\n ref,\n toValue,\n watch,\n type MaybeRefOrGetter,\n} from \"vue\";\nimport type {\n GraffitiLocation,\n GraffitiObject,\n GraffitiSession,\n JSONSchema4,\n} from \"@graffiti-garden/api\";\nimport { useGraffiti, useGraffitiSession } from \"./injections\";\nimport type { GraffitiStream } from \"@graffiti-garden/api\";\nimport { GetPoller, Poller, StreamPoller } from \"./pollers\";\nimport { ArrayReducer, Reducer, SingletonReducer } from \"./reducers\";\n\nfunction makeComposable<Schema extends JSONSchema4>(\n reducer: Reducer<Schema>,\n poller: Poller<Schema>,\n synchronizeFactory: () => GraffitiStream<GraffitiObject<Schema>>,\n toWatch: readonly (() => any)[],\n) {\n let synchronizeIterator: GraffitiStream<GraffitiObject<Schema>> | undefined =\n undefined;\n async function pollSynchronize() {\n synchronizeIterator = synchronizeFactory();\n for await (const result of synchronizeIterator) {\n if (result.error) {\n console.error(result.error);\n continue;\n }\n reducer.onObject(result.value);\n }\n }\n\n const poll = () => poller.poll(reducer.onObject.bind(reducer));\n\n const isPolling = ref(false);\n watch(\n toWatch,\n async (newValue, oldValue) => {\n // Catch unnecessary updates\n if (JSON.stringify(newValue) === JSON.stringify(oldValue)) {\n return;\n }\n\n synchronizeIterator?.return();\n reducer.clear();\n poller.clear();\n\n pollSynchronize();\n\n isPolling.value = true;\n try {\n await poll();\n } finally {\n isPolling.value = false;\n }\n },\n {\n immediate: true,\n },\n );\n onScopeDispose(() => synchronizeIterator?.return());\n\n return { poll, isPolling };\n}\n\nfunction toSessionGetter(\n sessionInjected: ReturnType<typeof useGraffitiSession>,\n session?: MaybeRefOrGetter<GraffitiSession | undefined | null>,\n) {\n return () => {\n const sessionValue = toValue(session);\n if (sessionValue === undefined) {\n return sessionInjected?.value;\n } else {\n return sessionValue;\n }\n };\n}\n\nfunction callGetters<T extends readonly (() => any)[]>(\n getters: T,\n): {\n [K in keyof T]: ReturnType<T[K]>;\n} {\n return getters.map((fn) => fn()) as any;\n}\n\n/**\n * A reactive version of the [`Graffiti.discover`](https://api.graffiti.garden/classes/Graffiti.html#discover)\n * method. Its arguments are the same, but now they can be\n * reactive Vue refs or getters. As they change the output will\n * automatically update.\n *\n * Rather than returning a stream of Graffiti objects, this\n * function returns a reactive array of objects. It also\n * provides a method to poll for new results and a boolean\n * ref indicating if the poll is currently running.\n *\n * All [`tombstone`](https://api.graffiti.garden/interfaces/GraffitiObjectBase.html#tombstone)d\n * objects are filtered out.\n *\n * @returns An object containing\n * - `results`: a reactive array of Graffiti objects\n * - `poll`: a method to poll for new results\n * - `isPolling`: a boolean ref indicating if the poll is currently running\n */\nexport function useGraffitiDiscover<Schema extends JSONSchema4>(\n /**\n * A list of channels to discover objects from.\n * Reactivity will only trigger\n * when the root array changes, not when the elements\n * change. If you need reactivity on the elements,\n * create a getter, e.g. `() => [toValue(myReactiveChannel)]`.\n */\n channels: MaybeRefOrGetter<string[]>,\n /**\n * A [JSON Schema](https://json-schema.org/) object describing the schema\n * of the objects to discover. All other objects will be filtered out\n * and the output will be typed as `GraffitiObject<Schema>`.\n * Reactivity only triggers when the root object changes, not when\n * the root object changes, not when the properties change.\n * Create a getter if you need reactivity on the properties.\n */\n schema: MaybeRefOrGetter<Schema>,\n /**\n * A Graffiti session object. If not provided, the\n * global plugin session will be used.\n */\n session?: MaybeRefOrGetter<GraffitiSession | undefined | null>,\n) {\n const graffiti = useGraffiti();\n const sessionInjected = useGraffitiSession();\n\n const channelsGetter = () => toValue(channels);\n const schemaGetter = () => toValue(schema);\n const sessionGetter = toSessionGetter(sessionInjected, session);\n const argGetters = [channelsGetter, schemaGetter, sessionGetter] as const;\n\n const synchronizeFactory = () =>\n graffiti.synchronizeDiscover(...callGetters(argGetters));\n const streamFactory = () => graffiti.discover(...callGetters(argGetters));\n\n const reducer = new ArrayReducer<Schema>(graffiti);\n const poller = new StreamPoller(schemaGetter, streamFactory);\n\n const { poll, isPolling } = makeComposable(\n reducer,\n poller,\n synchronizeFactory,\n argGetters,\n );\n\n return {\n results: reducer.results,\n poll,\n isPolling,\n };\n}\n\n/**\n * A reactive version of the [`Graffiti.get`](https://api.graffiti.garden/classes/Graffiti.html#get)\n * method. Its arguments are the same, but now they can be\n * reactive Vue refs or getters. As they change the output will\n * automatically update.\n *\n * Rather than returning a single Graffiti object, this\n * function returns a reactive object. It also\n * provides a method to poll for new results and a boolean\n * ref indicating if the poll is currently running.\n *\n * While the object is first being fetched, the result\n * is `undefined`. If the object has been deleted,\n * the result is `null`. Otherwise, the result is the\n * most recent object fetched. All [`tombstone`](https://api.graffiti.garden/interfaces/GraffitiObjectBase.html#tombstone)d\n * objects are filtered out.\n *\n * @returns An object containing\n * - `results`: a reactive array of Graffiti objects\n * - `poll`: a method to poll for new results\n * - `isPolling`: a boolean ref indicating if the poll is currently running\n */\nexport function useGraffitiGet<Schema extends JSONSchema4>(\n /**\n * A Graffiti location or URI to fetch the object from.\n */\n locationOrUri: MaybeRefOrGetter<GraffitiLocation | string>,\n /**\n * A [JSON Schema](https://json-schema.org/) object describing the schema\n * of the objects to discover. All other objects will be filtered out\n * and the output will be typed as `GraffitiObject<Schema>`.\n * Like the `channels` argument, reactivity only triggers when\n */\n schema: MaybeRefOrGetter<Schema>,\n /**\n * A Graffiti session object. If not provided, the\n * global plugin session will be used.\n */\n session?: MaybeRefOrGetter<GraffitiSession | undefined | null>,\n) {\n const graffiti = useGraffiti();\n const sessionInjected = useGraffitiSession();\n\n const locationOrUriGetter = () => toValue(locationOrUri);\n const schemaGetter = () => toValue(schema);\n const sessionGetter = toSessionGetter(sessionInjected, session);\n const argGetters = [\n locationOrUriGetter,\n schemaGetter,\n sessionGetter,\n ] as const;\n\n const synchronizeFactory = () =>\n graffiti.synchronizeGet(...callGetters(argGetters));\n\n const reducer = new SingletonReducer<Schema>();\n const poller = new GetPoller(() => graffiti.get(...callGetters(argGetters)));\n\n const { poll, isPolling } = makeComposable(\n reducer,\n poller,\n synchronizeFactory,\n argGetters,\n );\n\n return {\n result: reducer.result,\n poll,\n isPolling,\n };\n}\n\nexport function useGraffitiRecoverOrphans<Schema extends JSONSchema4>(\n schema: MaybeRefOrGetter<Schema>,\n session: MaybeRefOrGetter<GraffitiSession>,\n) {\n const graffiti = useGraffiti();\n\n const schemaGetter = () => toValue(schema);\n const sessionGetter = () => toValue(session);\n const argGetters = [schemaGetter, sessionGetter] as const;\n\n const synchronizeFactory = () =>\n graffiti.synchronizeRecoverOrphans(...callGetters(argGetters));\n\n const reducer = new ArrayReducer<Schema>(graffiti);\n const poller = new StreamPoller(schemaGetter, () =>\n graffiti.recoverOrphans(...callGetters(argGetters)),\n );\n\n const { poll, isPolling } = makeComposable(\n reducer,\n poller,\n synchronizeFactory,\n argGetters,\n );\n\n return {\n results: reducer.results,\n poll,\n isPolling,\n };\n}\n","<script setup lang=\"ts\" generic=\"Schema extends JSONSchema4\">\nimport { toRef } from \"vue\";\nimport type { GraffitiSession, JSONSchema4 } from \"@graffiti-garden/api\";\nimport { useGraffitiDiscover } from \"./composables\";\n\nconst props = defineProps<{\n channels: string[];\n schema: Schema;\n session?: GraffitiSession | null;\n}>();\n\nconst { results, poll, isPolling } = useGraffitiDiscover<Schema>(\n toRef(props, \"channels\"),\n toRef(props, \"schema\"),\n toRef(props, \"session\"),\n);\n</script>\n\n<template>\n <slot :results=\"results\" :poll=\"poll\" :isPolling=\"isPolling\"></slot>\n</template>\n","<script setup lang=\"ts\" generic=\"Schema extends JSONSchema4\">\nimport { toRef } from \"vue\";\nimport type {\n GraffitiLocation,\n GraffitiSession,\n JSONSchema4,\n} from \"@graffiti-garden/api\";\nimport { useGraffitiGet } from \"./composables\";\n\nconst props = defineProps<{\n locationOrUri: string | GraffitiLocation;\n schema: Schema;\n session?: GraffitiSession | null;\n}>();\n\nconst { result, poll, isPolling } = useGraffitiGet<Schema>(\n toRef(props, \"locationOrUri\"),\n toRef(props, \"schema\"),\n toRef(props, \"session\"),\n);\n</script>\n\n<template>\n <slot :result=\"result\" :poll=\"poll\" :isPolling=\"isPolling\"></slot>\n</template>\n","<script setup lang=\"ts\" generic=\"Schema extends JSONSchema4\">\nimport { toRef } from \"vue\";\nimport type { GraffitiSession, JSONSchema4 } from \"@graffiti-garden/api\";\nimport { useGraffitiRecoverOrphans } from \"./composables\";\n\nconst props = defineProps<{\n schema: Schema;\n session: GraffitiSession;\n}>();\n\nconst { results, poll, isPolling } = useGraffitiRecoverOrphans<Schema>(\n toRef(props, \"schema\"),\n toRef(props, \"session\"),\n);\n</script>\n\n<template>\n <slot :results=\"results\" :poll=\"poll\" :isPolling=\"isPolling\"></slot>\n</template>\n","import type { App, Plugin, Ref } from \"vue\";\nimport { ref } from \"vue\";\nimport Discover from \"./Discover.vue\";\nimport Get from \"./Get.vue\";\nimport RecoverOrphans from \"./RecoverOrphans.vue\";\nimport type {\n GraffitiFactory,\n Graffiti,\n GraffitiSession,\n GraffitiLoginEvent,\n GraffitiLogoutEvent,\n GraffitiSessionInitializedEvent,\n} from \"@graffiti-garden/api\";\nimport { graffitiInjectKey, graffitiSessionInjectKey } from \"./injections\";\nimport type { Router } from \"vue-router\";\n\ndeclare module \"vue\" {\n export interface ComponentCustomProperties {\n $graffiti: Graffiti;\n $graffitiSession: Ref<GraffitiSession | undefined | null>;\n }\n\n export interface GlobalComponents {\n GraffitiDiscover: typeof Discover;\n GraffitiGet: typeof Get;\n GraffitiRecoverOrphans: typeof RecoverOrphans;\n }\n}\n\nexport interface GraffitiPluginOptions {\n useGraffiti: GraffitiFactory;\n}\n\nexport const GraffitiPlugin: Plugin<GraffitiPluginOptions> = {\n install(app: App, options: GraffitiPluginOptions) {\n const graffiti = options.useGraffiti();\n const graffitiSession = ref<GraffitiSession | undefined | null>(undefined);\n graffiti.sessionEvents.addEventListener(\"initialized\", async (evt) => {\n const detail = (evt as GraffitiSessionInitializedEvent).detail;\n\n if (detail && detail.error) {\n console.error(detail.error);\n }\n\n if (detail && detail.href) {\n // If we're using Vue Router, redirect to the URL after login\n const router = app.config.globalProperties.$router as\n | Router\n | undefined;\n if (router) {\n const url = new URL(detail.href);\n await router.replace(url.pathname + url.search + url.hash);\n }\n }\n\n // Set the session to \"null\" if the user is not logged in\n if (!graffitiSession.value) {\n graffitiSession.value = null;\n }\n });\n graffiti.sessionEvents.addEventListener(\"login\", (evt) => {\n const detail = (evt as GraffitiLoginEvent).detail;\n if (detail.error) {\n console.error(\"Error logging in:\");\n console.error(detail.error);\n return;\n } else {\n graffitiSession.value = detail.session;\n }\n });\n graffiti.sessionEvents.addEventListener(\"logout\", (evt) => {\n const detail = (evt as GraffitiLogoutEvent).detail;\n if (detail.error) {\n console.error(\"Error logging out:\");\n console.error(detail.error);\n } else {\n graffitiSession.value = null;\n }\n });\n\n app.provide(graffitiInjectKey, graffiti);\n app.provide(graffitiSessionInjectKey, graffitiSession);\n\n app.component(\"GraffitiDiscover\", Discover);\n app.component(\"GraffitiGet\", Get);\n app.component(\"GraffitiRecoverOrphans\", RecoverOrphans);\n app.config.globalProperties.$graffiti = graffiti;\n app.config.globalProperties.$graffitiSession = graffitiSession;\n },\n};\n\nexport * from \"./composables\";\nexport * from \"./injections\";\nexport { Discover as GraffitiDiscover };\nexport { Get as GraffitiGet };\nexport { RecoverOrphans as GraffitiRecoverOrphans };\n"],"names":["graffitiInjectKey","graffitiSessionInjectKey","useGraffiti","graffiti","inject","useGraffitiSession","session","GetPoller","getter","__publicField","onObject","object","StreamPoller","schemaGetter","streamFactory","startOfPoll","schema","_a","myIterator","e","myLastModified","_b","result","tombstoneRetention","G","t","SingletonReducer","ref","isObjectNewer","ArrayReducer","acc","tombstone","url","existing","makeComposable","reducer","poller","synchronizeFactory","toWatch","synchronizeIterator","pollSynchronize","poll","isPolling","watch","newValue","oldValue","onScopeDispose","toSessionGetter","sessionInjected","sessionValue","toValue","callGetters","getters","fn","useGraffitiDiscover","channels","channelsGetter","sessionGetter","argGetters","useGraffitiGet","locationOrUri","locationOrUriGetter","useGraffitiRecoverOrphans","props","__props","results","toRef","GraffitiPlugin","app","options","graffitiSession","evt","detail","router","Discover","Get","RecoverOrphans"],"mappings":"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","x_google_ignoreList":[2]}
@@ -40,7 +40,6 @@ export declare class SingletonReducer<Schema extends JSONSchema4> implements Red
40
40
  */
41
41
  export declare class ArrayReducer<Schema extends JSONSchema4> implements Reducer<Schema> {
42
42
  readonly graffiti: Graffiti;
43
- REFRESH_RATE: number;
44
43
  readonly results: import('vue').Ref<import('@vue/reactivity').UnwrapRefSimple<import('@graffiti-garden/api').GraffitiObjectBase & import('ajv/dist/core').JTDDataType<Schema> & {
45
44
  tombstone: false;
46
45
  }>[], (import('@graffiti-garden/api').GraffitiObjectBase & import('ajv/dist/core').JTDDataType<Schema> & {
package/dist/stats.html CHANGED
@@ -4929,7 +4929,7 @@ var drawChart = (function (exports) {
4929
4929
  </script>
4930
4930
  <script>
4931
4931
  /*<!--*/
4932
- const data = {"version":2,"tree":{"name":"root","children":[{"name":"plugin.cjs","children":[{"name":"src","children":[{"uid":"ecebd9e9-1","name":"injections.ts"},{"uid":"ecebd9e9-3","name":"pollers.ts"},{"uid":"ecebd9e9-7","name":"reducers.ts"},{"uid":"ecebd9e9-9","name":"composables.ts"},{"uid":"ecebd9e9-11","name":"Discover.vue?vue&type=script&setup=true&lang.ts"},{"uid":"ecebd9e9-13","name":"Get.vue?vue&type=script&setup=true&lang.ts"},{"uid":"ecebd9e9-15","name":"RecoverOrphans.vue?vue&type=script&setup=true&lang.ts"},{"uid":"ecebd9e9-17","name":"plugin.ts"}]},{"name":"node_modules/@graffiti-garden/implementation-local/dist/esm/utilities.js","uid":"ecebd9e9-5"}]}],"isRoot":true},"nodeParts":{"ecebd9e9-1":{"renderedLength":434,"gzipLength":0,"brotliLength":0,"metaUid":"ecebd9e9-0"},"ecebd9e9-3":{"renderedLength":2103,"gzipLength":0,"brotliLength":0,"metaUid":"ecebd9e9-2"},"ecebd9e9-5":{"renderedLength":113,"gzipLength":0,"brotliLength":0,"metaUid":"ecebd9e9-4"},"ecebd9e9-7":{"renderedLength":1411,"gzipLength":0,"brotliLength":0,"metaUid":"ecebd9e9-6"},"ecebd9e9-9":{"renderedLength":3668,"gzipLength":0,"brotliLength":0,"metaUid":"ecebd9e9-8"},"ecebd9e9-11":{"renderedLength":582,"gzipLength":0,"brotliLength":0,"metaUid":"ecebd9e9-10"},"ecebd9e9-13":{"renderedLength":579,"gzipLength":0,"brotliLength":0,"metaUid":"ecebd9e9-12"},"ecebd9e9-15":{"renderedLength":538,"gzipLength":0,"brotliLength":0,"metaUid":"ecebd9e9-14"},"ecebd9e9-17":{"renderedLength":1623,"gzipLength":0,"brotliLength":0,"metaUid":"ecebd9e9-16"}},"nodeMetas":{"ecebd9e9-0":{"id":"/src/injections.ts","moduleParts":{"plugin.cjs":"ecebd9e9-1"},"imported":[{"uid":"ecebd9e9-18"}],"importedBy":[{"uid":"ecebd9e9-16"},{"uid":"ecebd9e9-8"}]},"ecebd9e9-2":{"id":"/src/pollers.ts","moduleParts":{"plugin.cjs":"ecebd9e9-3"},"imported":[],"importedBy":[{"uid":"ecebd9e9-8"}]},"ecebd9e9-4":{"id":"/node_modules/@graffiti-garden/implementation-local/dist/esm/utilities.js","moduleParts":{"plugin.cjs":"ecebd9e9-5"},"imported":[{"uid":"ecebd9e9-22"}],"importedBy":[{"uid":"ecebd9e9-6"}]},"ecebd9e9-6":{"id":"/src/reducers.ts","moduleParts":{"plugin.cjs":"ecebd9e9-7"},"imported":[{"uid":"ecebd9e9-18"},{"uid":"ecebd9e9-4"}],"importedBy":[{"uid":"ecebd9e9-8"}]},"ecebd9e9-8":{"id":"/src/composables.ts","moduleParts":{"plugin.cjs":"ecebd9e9-9"},"imported":[{"uid":"ecebd9e9-18"},{"uid":"ecebd9e9-0"},{"uid":"ecebd9e9-2"},{"uid":"ecebd9e9-6"}],"importedBy":[{"uid":"ecebd9e9-16"},{"uid":"ecebd9e9-10"},{"uid":"ecebd9e9-12"},{"uid":"ecebd9e9-14"}]},"ecebd9e9-10":{"id":"/src/Discover.vue?vue&type=script&setup=true&lang.ts","moduleParts":{"plugin.cjs":"ecebd9e9-11"},"imported":[{"uid":"ecebd9e9-18"},{"uid":"ecebd9e9-8"}],"importedBy":[{"uid":"ecebd9e9-19"}]},"ecebd9e9-12":{"id":"/src/Get.vue?vue&type=script&setup=true&lang.ts","moduleParts":{"plugin.cjs":"ecebd9e9-13"},"imported":[{"uid":"ecebd9e9-18"},{"uid":"ecebd9e9-8"}],"importedBy":[{"uid":"ecebd9e9-20"}]},"ecebd9e9-14":{"id":"/src/RecoverOrphans.vue?vue&type=script&setup=true&lang.ts","moduleParts":{"plugin.cjs":"ecebd9e9-15"},"imported":[{"uid":"ecebd9e9-18"},{"uid":"ecebd9e9-8"}],"importedBy":[{"uid":"ecebd9e9-21"}]},"ecebd9e9-16":{"id":"/src/plugin.ts","moduleParts":{"plugin.cjs":"ecebd9e9-17"},"imported":[{"uid":"ecebd9e9-18"},{"uid":"ecebd9e9-19"},{"uid":"ecebd9e9-20"},{"uid":"ecebd9e9-21"},{"uid":"ecebd9e9-0"},{"uid":"ecebd9e9-8"}],"importedBy":[],"isEntry":true},"ecebd9e9-18":{"id":"vue","moduleParts":{},"imported":[],"importedBy":[{"uid":"ecebd9e9-16"},{"uid":"ecebd9e9-0"},{"uid":"ecebd9e9-8"},{"uid":"ecebd9e9-10"},{"uid":"ecebd9e9-12"},{"uid":"ecebd9e9-14"},{"uid":"ecebd9e9-6"}],"isExternal":true},"ecebd9e9-19":{"id":"/src/Discover.vue","moduleParts":{},"imported":[{"uid":"ecebd9e9-10"}],"importedBy":[{"uid":"ecebd9e9-16"}]},"ecebd9e9-20":{"id":"/src/Get.vue","moduleParts":{},"imported":[{"uid":"ecebd9e9-12"}],"importedBy":[{"uid":"ecebd9e9-16"}]},"ecebd9e9-21":{"id":"/src/RecoverOrphans.vue","moduleParts":{},"imported":[{"uid":"ecebd9e9-14"}],"importedBy":[{"uid":"ecebd9e9-16"}]},"ecebd9e9-22":{"id":"/node_modules/@graffiti-garden/api/dist/index.mjs","moduleParts":{},"imported":[],"importedBy":[{"uid":"ecebd9e9-4"}]}},"env":{"rollup":"4.34.4"},"options":{"gzip":false,"brotli":false,"sourcemap":false}};
4932
+ const data = {"version":2,"tree":{"name":"root","children":[{"name":"plugin.cjs","children":[{"name":"src","children":[{"uid":"4572799c-1","name":"injections.ts"},{"uid":"4572799c-3","name":"pollers.ts"},{"uid":"4572799c-7","name":"reducers.ts"},{"uid":"4572799c-9","name":"composables.ts"},{"uid":"4572799c-11","name":"Discover.vue?vue&type=script&setup=true&lang.ts"},{"uid":"4572799c-13","name":"Get.vue?vue&type=script&setup=true&lang.ts"},{"uid":"4572799c-15","name":"RecoverOrphans.vue?vue&type=script&setup=true&lang.ts"},{"uid":"4572799c-17","name":"plugin.ts"}]},{"name":"node_modules/@graffiti-garden/implementation-local/dist/esm/utilities.js","uid":"4572799c-5"}]}],"isRoot":true},"nodeParts":{"4572799c-1":{"renderedLength":434,"gzipLength":0,"brotliLength":0,"metaUid":"4572799c-0"},"4572799c-3":{"renderedLength":2103,"gzipLength":0,"brotliLength":0,"metaUid":"4572799c-2"},"4572799c-5":{"renderedLength":113,"gzipLength":0,"brotliLength":0,"metaUid":"4572799c-4"},"4572799c-7":{"renderedLength":1355,"gzipLength":0,"brotliLength":0,"metaUid":"4572799c-6"},"4572799c-9":{"renderedLength":3668,"gzipLength":0,"brotliLength":0,"metaUid":"4572799c-8"},"4572799c-11":{"renderedLength":582,"gzipLength":0,"brotliLength":0,"metaUid":"4572799c-10"},"4572799c-13":{"renderedLength":579,"gzipLength":0,"brotliLength":0,"metaUid":"4572799c-12"},"4572799c-15":{"renderedLength":538,"gzipLength":0,"brotliLength":0,"metaUid":"4572799c-14"},"4572799c-17":{"renderedLength":1635,"gzipLength":0,"brotliLength":0,"metaUid":"4572799c-16"}},"nodeMetas":{"4572799c-0":{"id":"/src/injections.ts","moduleParts":{"plugin.cjs":"4572799c-1"},"imported":[{"uid":"4572799c-18"}],"importedBy":[{"uid":"4572799c-16"},{"uid":"4572799c-8"}]},"4572799c-2":{"id":"/src/pollers.ts","moduleParts":{"plugin.cjs":"4572799c-3"},"imported":[],"importedBy":[{"uid":"4572799c-8"}]},"4572799c-4":{"id":"/node_modules/@graffiti-garden/implementation-local/dist/esm/utilities.js","moduleParts":{"plugin.cjs":"4572799c-5"},"imported":[{"uid":"4572799c-22"}],"importedBy":[{"uid":"4572799c-6"}]},"4572799c-6":{"id":"/src/reducers.ts","moduleParts":{"plugin.cjs":"4572799c-7"},"imported":[{"uid":"4572799c-18"},{"uid":"4572799c-4"}],"importedBy":[{"uid":"4572799c-8"}]},"4572799c-8":{"id":"/src/composables.ts","moduleParts":{"plugin.cjs":"4572799c-9"},"imported":[{"uid":"4572799c-18"},{"uid":"4572799c-0"},{"uid":"4572799c-2"},{"uid":"4572799c-6"}],"importedBy":[{"uid":"4572799c-16"},{"uid":"4572799c-10"},{"uid":"4572799c-12"},{"uid":"4572799c-14"}]},"4572799c-10":{"id":"/src/Discover.vue?vue&type=script&setup=true&lang.ts","moduleParts":{"plugin.cjs":"4572799c-11"},"imported":[{"uid":"4572799c-18"},{"uid":"4572799c-8"}],"importedBy":[{"uid":"4572799c-19"}]},"4572799c-12":{"id":"/src/Get.vue?vue&type=script&setup=true&lang.ts","moduleParts":{"plugin.cjs":"4572799c-13"},"imported":[{"uid":"4572799c-18"},{"uid":"4572799c-8"}],"importedBy":[{"uid":"4572799c-20"}]},"4572799c-14":{"id":"/src/RecoverOrphans.vue?vue&type=script&setup=true&lang.ts","moduleParts":{"plugin.cjs":"4572799c-15"},"imported":[{"uid":"4572799c-18"},{"uid":"4572799c-8"}],"importedBy":[{"uid":"4572799c-21"}]},"4572799c-16":{"id":"/src/plugin.ts","moduleParts":{"plugin.cjs":"4572799c-17"},"imported":[{"uid":"4572799c-18"},{"uid":"4572799c-19"},{"uid":"4572799c-20"},{"uid":"4572799c-21"},{"uid":"4572799c-0"},{"uid":"4572799c-8"}],"importedBy":[],"isEntry":true},"4572799c-18":{"id":"vue","moduleParts":{},"imported":[],"importedBy":[{"uid":"4572799c-16"},{"uid":"4572799c-0"},{"uid":"4572799c-8"},{"uid":"4572799c-10"},{"uid":"4572799c-12"},{"uid":"4572799c-14"},{"uid":"4572799c-6"}],"isExternal":true},"4572799c-19":{"id":"/src/Discover.vue","moduleParts":{},"imported":[{"uid":"4572799c-10"}],"importedBy":[{"uid":"4572799c-16"}]},"4572799c-20":{"id":"/src/Get.vue","moduleParts":{},"imported":[{"uid":"4572799c-12"}],"importedBy":[{"uid":"4572799c-16"}]},"4572799c-21":{"id":"/src/RecoverOrphans.vue","moduleParts":{},"imported":[{"uid":"4572799c-14"}],"importedBy":[{"uid":"4572799c-16"}]},"4572799c-22":{"id":"/node_modules/@graffiti-garden/api/dist/index.mjs","moduleParts":{},"imported":[],"importedBy":[{"uid":"4572799c-4"}]}},"env":{"rollup":"4.34.4"},"options":{"gzip":false,"brotli":false,"sourcemap":false}};
4933
4933
 
4934
4934
  const run = () => {
4935
4935
  const width = window.innerWidth;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@graffiti-garden/wrapper-vue",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Vue.js wrapper for the Graffiti API",
5
5
  "type": "module",
6
6
  "types": "./dist/plugin.d.ts",
@@ -41,10 +41,10 @@
41
41
  "url": "https://github.com/graffiti-garden/wrapper-vue/issues"
42
42
  },
43
43
  "dependencies": {
44
- "@graffiti-garden/api": "^0.2.8"
44
+ "@graffiti-garden/api": "^0.2.11"
45
45
  },
46
46
  "devDependencies": {
47
- "@graffiti-garden/implementation-local": "^0.2.10",
47
+ "@graffiti-garden/implementation-local": "^0.2.12",
48
48
  "@vitejs/plugin-vue": "^5.2.1",
49
49
  "@vue/typescript-plugin": "^2.2.0",
50
50
  "rollup-plugin-visualizer": "^5.14.0",
package/src/plugin.ts CHANGED
@@ -35,14 +35,9 @@ export const GraffitiPlugin: Plugin<GraffitiPluginOptions> = {
35
35
  install(app: App, options: GraffitiPluginOptions) {
36
36
  const graffiti = options.useGraffiti();
37
37
  const graffitiSession = ref<GraffitiSession | undefined | null>(undefined);
38
- graffiti.sessionEvents.addEventListener("initialized", (evt) => {
38
+ graffiti.sessionEvents.addEventListener("initialized", async (evt) => {
39
39
  const detail = (evt as GraffitiSessionInitializedEvent).detail;
40
40
 
41
- // Set the session to "null" if the user is not logged in
42
- if (!graffitiSession.value) {
43
- graffitiSession.value = null;
44
- }
45
-
46
41
  if (detail && detail.error) {
47
42
  console.error(detail.error);
48
43
  }
@@ -54,9 +49,14 @@ export const GraffitiPlugin: Plugin<GraffitiPluginOptions> = {
54
49
  | undefined;
55
50
  if (router) {
56
51
  const url = new URL(detail.href);
57
- router.replace(url.pathname + url.search + url.hash);
52
+ await router.replace(url.pathname + url.search + url.hash);
58
53
  }
59
54
  }
55
+
56
+ // Set the session to "null" if the user is not logged in
57
+ if (!graffitiSession.value) {
58
+ graffitiSession.value = null;
59
+ }
60
60
  });
61
61
  graffiti.sessionEvents.addEventListener("login", (evt) => {
62
62
  const detail = (evt as GraffitiLoginEvent).detail;
package/src/reducers.ts CHANGED
@@ -51,7 +51,6 @@ export class SingletonReducer<Schema extends JSONSchema4>
51
51
  export class ArrayReducer<Schema extends JSONSchema4>
52
52
  implements Reducer<Schema>
53
53
  {
54
- REFRESH_RATE = 100; // milliseconds
55
54
  readonly results = ref<(GraffitiObject<Schema> & { tombstone: false })[]>([]);
56
55
  readonly resultsRaw = new Map<string, GraffitiObject<Schema>>();
57
56
  batchFlattenTimer: ReturnType<typeof setTimeout> | undefined = undefined;
@@ -92,7 +91,7 @@ export class ArrayReducer<Schema extends JSONSchema4>
92
91
  this.batchFlattenTimer = setTimeout(() => {
93
92
  this.flattenResults();
94
93
  this.batchFlattenTimer = undefined;
95
- }, this.REFRESH_RATE);
94
+ }, 0);
96
95
  }
97
96
  }
98
97
  }