@graffiti-garden/implementation-local 0.2.9 → 0.2.11
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/cjs/synchronize.js +1 -1
- package/dist/cjs/synchronize.js.map +3 -3
- package/dist/esm/synchronize.js +1 -1
- package/dist/esm/synchronize.js.map +3 -3
- package/dist/index.browser.js +9 -9
- package/dist/index.browser.js.map +3 -3
- package/dist/synchronize.d.ts +3 -2
- package/dist/synchronize.d.ts.map +1 -1
- package/package.json +2 -7
- package/src/synchronize.ts +23 -29
package/dist/cjs/synchronize.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var G=Object.create;var h=Object.defineProperty;var
|
|
1
|
+
"use strict";var G=Object.create;var h=Object.defineProperty;var O=Object.getOwnPropertyDescriptor;var w=Object.getOwnPropertyNames;var z=Object.getPrototypeOf,g=Object.prototype.hasOwnProperty;var S=(r,e)=>{for(var t in e)h(r,t,{get:e[t],enumerable:!0})},y=(r,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let a of w(e))!g.call(r,a)&&a!==t&&h(r,a,{get:()=>e[a],enumerable:!(i=O(e,a))||i.enumerable});return r};var k=(r,e,t)=>(t=r!=null?G(z(r)):{},y(e||!r||!r.__esModule?h(t,"default",{value:r,enumerable:!0}):t,r)),D=r=>y(h({},"__esModule",{value:!0}),r);var P={};S(P,{GraffitiSynchronize:()=>B});module.exports=D(P);var d=k(require("ajv-draft-04")),u=require("@repeaterjs/repeater"),m=require("fast-json-patch"),c=require("./utilities.js");class B{ajv;graffiti;callbacks=new Set;constructor(e,t){this.ajv=t??new d.default({strict:!1}),this.graffiti=e}async synchronizeDispatch(e,t){for(const i of this.callbacks)i(e,t);await Promise.resolve(),await Promise.resolve(),await Promise.resolve()}get=async(...e)=>{const t=await this.graffiti.get(...e);return this.synchronizeDispatch(t),t};put=async(...e)=>{const t=await this.graffiti.put(...e),i=e[0],a={...t,value:i.value,channels:i.channels,allowed:i.allowed,tombstone:!1};return await this.synchronizeDispatch(t,a),t};patch=async(...e)=>{const t=await this.graffiti.patch(...e),i={...t};i.tombstone=!1;for(const a of["value","channels","allowed"])(0,c.applyGraffitiPatch)(m.applyPatch,a,e[0],i);return await this.synchronizeDispatch(t,i),t};delete=async(...e)=>{const t=await this.graffiti.delete(...e);return await this.synchronizeDispatch(t),t};objectStream(e){const t=this.synchronizeDispatch.bind(this);return async function*(){let a=await e.next();for(;!a.done;)a.value.error||t(a.value.value),yield a.value,a=await e.next();return a.value}()}discover=(...e)=>{const t=this.graffiti.discover(...e);return this.objectStream(t)};recoverOrphans=(...e)=>{const t=this.graffiti.recoverOrphans(...e);return this.objectStream(t)};synchronize(e,t,i,a){const s=(0,c.attemptAjvCompile)(this.ajv,i);return new u.Repeater(async(o,l)=>{const b=async(v,j)=>{for(const f of[j,v])if(f&&e(f)&&(0,c.isActorAllowedGraffitiObject)(f,a)){const p={...f};if((0,c.maskGraffitiObject)(p,t,a),s(p)){o({value:p});break}}};this.callbacks.add(b),await l,this.callbacks.delete(b)})}synchronizeDiscover=(...e)=>{const[t,i,a]=e;function s(n){return n.channels.some(o=>t.includes(o))}return this.synchronize(s,t,i,a)};synchronizeGet=(...e)=>{const[t,i,a]=e;function s(n){const o=(0,c.locationToUri)(n),{uri:l}=(0,c.unpackLocationOrUri)(t);return o===l}return this.synchronize(s,[],i,a)};synchronizeRecoverOrphans=(...e)=>{const[t,i]=e;function a(s){return s.actor===i.actor&&s.channels.length===0}return this.synchronize(a,[],t,i)}}
|
|
2
2
|
//# sourceMappingURL=synchronize.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/synchronize.ts"],
|
|
4
|
-
"sourcesContent": ["import Ajv from \"ajv-draft-04\";\nimport type {\n Graffiti,\n GraffitiSession,\n JSONSchema4,\n} from \"@graffiti-garden/api\";\nimport type { GraffitiObjectBase } from \"@graffiti-garden/api\";\nimport { Repeater } from \"@repeaterjs/repeater\";\nimport { applyPatch } from \"fast-json-patch\";\nimport {\n applyGraffitiPatch,\n attemptAjvCompile,\n isActorAllowedGraffitiObject,\n locationToUri,\n maskGraffitiObject,\n unpackLocationOrUri,\n} from \"./utilities.js\";\n\ntype
|
|
5
|
-
"mappings": "0jBAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,yBAAAE,IAAA,eAAAC,EAAAH,GAAA,IAAAI,EAAgB,2BAOhBC,EAAyB,gCACzBC,EAA2B,2BAC3BC,EAOO,0BAkBA,MAAML,CAcb,CACqB,
|
|
6
|
-
"names": ["synchronize_exports", "__export", "GraffitiSynchronize", "__toCommonJS", "import_ajv_draft_04", "import_repeater", "import_fast_json_patch", "import_utilities", "graffiti", "ajv", "Ajv", "oldObject", "newObject", "
|
|
4
|
+
"sourcesContent": ["import Ajv from \"ajv-draft-04\";\nimport type {\n Graffiti,\n GraffitiSession,\n JSONSchema4,\n} from \"@graffiti-garden/api\";\nimport type { GraffitiObjectBase } from \"@graffiti-garden/api\";\nimport { Repeater } from \"@repeaterjs/repeater\";\nimport { applyPatch } from \"fast-json-patch\";\nimport {\n applyGraffitiPatch,\n attemptAjvCompile,\n isActorAllowedGraffitiObject,\n locationToUri,\n maskGraffitiObject,\n unpackLocationOrUri,\n} from \"./utilities.js\";\n\ntype GraffitiDatabaseMethods = Pick<\n Graffiti,\n \"get\" | \"put\" | \"patch\" | \"delete\" | \"discover\" | \"recoverOrphans\"\n>;\n\ntype Callback = (\n oldObject: GraffitiObjectBase,\n newObject?: GraffitiObjectBase,\n) => void;\n\n/**\n * Wraps a partial implementation of the [Graffiti API](https://api.graffiti.garden/classes/Graffiti.html)\n * to provide the [`synchronize`](https://api.graffiti.garden/classes/Graffiti.html#synchronize) method.\n * The partial implementation must include the primary database methods:\n * `get`, `put`, `patch`, `delete`, and `discover`.\n */\nexport class GraffitiSynchronize\n implements\n Pick<\n Graffiti,\n | \"put\"\n | \"get\"\n | \"patch\"\n | \"delete\"\n | \"discover\"\n | \"recoverOrphans\"\n | \"synchronizeDiscover\"\n | \"synchronizeGet\"\n | \"synchronizeRecoverOrphans\"\n >\n{\n protected readonly ajv: Ajv;\n protected readonly graffiti: GraffitiDatabaseMethods;\n protected readonly callbacks = new Set<Callback>();\n\n // Pass in the ajv instance\n // and database methods to wrap\n constructor(graffiti: GraffitiDatabaseMethods, ajv?: Ajv) {\n this.ajv = ajv ?? new Ajv({ strict: false });\n this.graffiti = graffiti;\n }\n\n protected async synchronizeDispatch(\n oldObject: GraffitiObjectBase,\n newObject?: GraffitiObjectBase,\n ) {\n for (const callback of this.callbacks) {\n callback(oldObject, newObject);\n }\n // No idea why this works...\n // You can't await push in the callback\n // below, because the await will only resolve\n // after a subsequent .next() call\n await Promise.resolve();\n await Promise.resolve();\n await Promise.resolve();\n }\n\n get: Graffiti[\"get\"] = async (...args) => {\n const object = await this.graffiti.get(...args);\n this.synchronizeDispatch(object);\n return object;\n };\n\n put: Graffiti[\"put\"] = async (...args) => {\n const oldObject = await this.graffiti.put(...args);\n const partialObject = args[0];\n const newObject: GraffitiObjectBase = {\n ...oldObject,\n value: partialObject.value,\n channels: partialObject.channels,\n allowed: partialObject.allowed,\n tombstone: false,\n };\n await this.synchronizeDispatch(oldObject, newObject);\n return oldObject;\n };\n\n patch: Graffiti[\"patch\"] = async (...args) => {\n const oldObject = await this.graffiti.patch(...args);\n const newObject: GraffitiObjectBase = { ...oldObject };\n newObject.tombstone = false;\n for (const prop of [\"value\", \"channels\", \"allowed\"] as const) {\n applyGraffitiPatch(applyPatch, prop, args[0], newObject);\n }\n await this.synchronizeDispatch(oldObject, newObject);\n return oldObject;\n };\n\n delete: Graffiti[\"delete\"] = async (...args) => {\n const oldObject = await this.graffiti.delete(...args);\n await this.synchronizeDispatch(oldObject);\n return oldObject;\n };\n\n protected objectStream<Schema extends JSONSchema4>(\n iterator: ReturnType<typeof Graffiti.prototype.discover<Schema>>,\n ) {\n const dispatch = this.synchronizeDispatch.bind(this);\n const wrapper = async function* () {\n let result = await iterator.next();\n while (!result.done) {\n if (!result.value.error) {\n dispatch(result.value.value);\n }\n yield result.value;\n result = await iterator.next();\n }\n return result.value;\n };\n return wrapper();\n }\n\n discover: Graffiti[\"discover\"] = (...args) => {\n const iterator = this.graffiti.discover(...args);\n return this.objectStream(iterator);\n };\n\n recoverOrphans: Graffiti[\"recoverOrphans\"] = (...args) => {\n const iterator = this.graffiti.recoverOrphans(...args);\n return this.objectStream(iterator);\n };\n\n protected synchronize<Schema extends JSONSchema4>(\n matchObject: (object: GraffitiObjectBase) => boolean,\n channels: string[],\n schema: Schema,\n session?: GraffitiSession | null,\n ) {\n const validate = attemptAjvCompile(this.ajv, schema);\n\n const repeater: ReturnType<\n typeof Graffiti.prototype.synchronizeDiscover<typeof schema>\n > = new Repeater(async (push, stop) => {\n const callback: Callback = async (oldObjectRaw, newObjectRaw) => {\n for (const objectRaw of [newObjectRaw, oldObjectRaw]) {\n if (\n objectRaw &&\n matchObject(objectRaw) &&\n isActorAllowedGraffitiObject(objectRaw, session)\n ) {\n const object = { ...objectRaw };\n maskGraffitiObject(object, channels, session);\n if (validate(object)) {\n push({ value: object });\n break;\n }\n }\n }\n };\n\n this.callbacks.add(callback);\n await stop;\n this.callbacks.delete(callback);\n });\n\n return repeater;\n }\n\n synchronizeDiscover: Graffiti[\"synchronizeDiscover\"] = (...args) => {\n const [channels, schema, session] = args;\n function matchObject(object: GraffitiObjectBase) {\n return object.channels.some((channel) => channels.includes(channel));\n }\n return this.synchronize(matchObject, channels, schema, session);\n };\n\n synchronizeGet: Graffiti[\"synchronizeGet\"] = (...args) => {\n const [locationOrUri, schema, session] = args;\n function matchObject(object: GraffitiObjectBase) {\n const objectUri = locationToUri(object);\n const { uri } = unpackLocationOrUri(locationOrUri);\n return objectUri === uri;\n }\n return this.synchronize(matchObject, [], schema, session);\n };\n\n synchronizeRecoverOrphans: Graffiti[\"synchronizeRecoverOrphans\"] = (\n ...args\n ) => {\n const [schema, session] = args;\n function matchObject(object: GraffitiObjectBase) {\n return object.actor === session.actor && object.channels.length === 0;\n }\n return this.synchronize(matchObject, [], schema, session);\n };\n}\n"],
|
|
5
|
+
"mappings": "0jBAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,yBAAAE,IAAA,eAAAC,EAAAH,GAAA,IAAAI,EAAgB,2BAOhBC,EAAyB,gCACzBC,EAA2B,2BAC3BC,EAOO,0BAkBA,MAAML,CAcb,CACqB,IACA,SACA,UAAY,IAAI,IAInC,YAAYM,EAAmCC,EAAW,CACxD,KAAK,IAAMA,GAAO,IAAI,EAAAC,QAAI,CAAE,OAAQ,EAAM,CAAC,EAC3C,KAAK,SAAWF,CAClB,CAEA,MAAgB,oBACdG,EACAC,EACA,CACA,UAAWC,KAAY,KAAK,UAC1BA,EAASF,EAAWC,CAAS,EAM/B,MAAM,QAAQ,QAAQ,EACtB,MAAM,QAAQ,QAAQ,EACtB,MAAM,QAAQ,QAAQ,CACxB,CAEA,IAAuB,SAAUE,IAAS,CACxC,MAAMC,EAAS,MAAM,KAAK,SAAS,IAAI,GAAGD,CAAI,EAC9C,YAAK,oBAAoBC,CAAM,EACxBA,CACT,EAEA,IAAuB,SAAUD,IAAS,CACxC,MAAMH,EAAY,MAAM,KAAK,SAAS,IAAI,GAAGG,CAAI,EAC3CE,EAAgBF,EAAK,CAAC,EACtBF,EAAgC,CACpC,GAAGD,EACH,MAAOK,EAAc,MACrB,SAAUA,EAAc,SACxB,QAASA,EAAc,QACvB,UAAW,EACb,EACA,aAAM,KAAK,oBAAoBL,EAAWC,CAAS,EAC5CD,CACT,EAEA,MAA2B,SAAUG,IAAS,CAC5C,MAAMH,EAAY,MAAM,KAAK,SAAS,MAAM,GAAGG,CAAI,EAC7CF,EAAgC,CAAE,GAAGD,CAAU,EACrDC,EAAU,UAAY,GACtB,UAAWK,IAAQ,CAAC,QAAS,WAAY,SAAS,KAChD,sBAAmB,aAAYA,EAAMH,EAAK,CAAC,EAAGF,CAAS,EAEzD,aAAM,KAAK,oBAAoBD,EAAWC,CAAS,EAC5CD,CACT,EAEA,OAA6B,SAAUG,IAAS,CAC9C,MAAMH,EAAY,MAAM,KAAK,SAAS,OAAO,GAAGG,CAAI,EACpD,aAAM,KAAK,oBAAoBH,CAAS,EACjCA,CACT,EAEU,aACRO,EACA,CACA,MAAMC,EAAW,KAAK,oBAAoB,KAAK,IAAI,EAYnD,OAXgB,iBAAmB,CACjC,IAAIC,EAAS,MAAMF,EAAS,KAAK,EACjC,KAAO,CAACE,EAAO,MACRA,EAAO,MAAM,OAChBD,EAASC,EAAO,MAAM,KAAK,EAE7B,MAAMA,EAAO,MACbA,EAAS,MAAMF,EAAS,KAAK,EAE/B,OAAOE,EAAO,KAChB,EACe,CACjB,CAEA,SAAiC,IAAIN,IAAS,CAC5C,MAAMI,EAAW,KAAK,SAAS,SAAS,GAAGJ,CAAI,EAC/C,OAAO,KAAK,aAAaI,CAAQ,CACnC,EAEA,eAA6C,IAAIJ,IAAS,CACxD,MAAMI,EAAW,KAAK,SAAS,eAAe,GAAGJ,CAAI,EACrD,OAAO,KAAK,aAAaI,CAAQ,CACnC,EAEU,YACRG,EACAC,EACAC,EACAC,EACA,CACA,MAAMC,KAAW,qBAAkB,KAAK,IAAKF,CAAM,EA2BnD,OAvBI,IAAI,WAAS,MAAOG,EAAMC,IAAS,CACrC,MAAMd,EAAqB,MAAOe,EAAcC,IAAiB,CAC/D,UAAWC,IAAa,CAACD,EAAcD,CAAY,EACjD,GACEE,GACAT,EAAYS,CAAS,MACrB,gCAA6BA,EAAWN,CAAO,EAC/C,CACA,MAAMT,EAAS,CAAE,GAAGe,CAAU,EAE9B,MADA,sBAAmBf,EAAQO,EAAUE,CAAO,EACxCC,EAASV,CAAM,EAAG,CACpBW,EAAK,CAAE,MAAOX,CAAO,CAAC,EACtB,KACF,CACF,CAEJ,EAEA,KAAK,UAAU,IAAIF,CAAQ,EAC3B,MAAMc,EACN,KAAK,UAAU,OAAOd,CAAQ,CAChC,CAAC,CAGH,CAEA,oBAAuD,IAAIC,IAAS,CAClE,KAAM,CAACQ,EAAUC,EAAQC,CAAO,EAAIV,EACpC,SAASO,EAAYN,EAA4B,CAC/C,OAAOA,EAAO,SAAS,KAAMgB,GAAYT,EAAS,SAASS,CAAO,CAAC,CACrE,CACA,OAAO,KAAK,YAAYV,EAAaC,EAAUC,EAAQC,CAAO,CAChE,EAEA,eAA6C,IAAIV,IAAS,CACxD,KAAM,CAACkB,EAAeT,EAAQC,CAAO,EAAIV,EACzC,SAASO,EAAYN,EAA4B,CAC/C,MAAMkB,KAAY,iBAAclB,CAAM,EAChC,CAAE,IAAAmB,CAAI,KAAI,uBAAoBF,CAAa,EACjD,OAAOC,IAAcC,CACvB,CACA,OAAO,KAAK,YAAYb,EAAa,CAAC,EAAGE,EAAQC,CAAO,CAC1D,EAEA,0BAAmE,IAC9DV,IACA,CACH,KAAM,CAACS,EAAQC,CAAO,EAAIV,EAC1B,SAASO,EAAYN,EAA4B,CAC/C,OAAOA,EAAO,QAAUS,EAAQ,OAAST,EAAO,SAAS,SAAW,CACtE,CACA,OAAO,KAAK,YAAYM,EAAa,CAAC,EAAGE,EAAQC,CAAO,CAC1D,CACF",
|
|
6
|
+
"names": ["synchronize_exports", "__export", "GraffitiSynchronize", "__toCommonJS", "import_ajv_draft_04", "import_repeater", "import_fast_json_patch", "import_utilities", "graffiti", "ajv", "Ajv", "oldObject", "newObject", "callback", "args", "object", "partialObject", "prop", "iterator", "dispatch", "result", "matchObject", "channels", "schema", "session", "validate", "push", "stop", "oldObjectRaw", "newObjectRaw", "objectRaw", "channel", "locationOrUri", "objectUri", "uri"]
|
|
7
7
|
}
|
package/dist/esm/synchronize.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import
|
|
1
|
+
import b from"ajv-draft-04";import{Repeater as y}from"@repeaterjs/repeater";import{applyPatch as d}from"fast-json-patch";import{applyGraffitiPatch as u,attemptAjvCompile as m,isActorAllowedGraffitiObject as v,locationToUri as j,maskGraffitiObject as G,unpackLocationOrUri as O}from"./utilities.js";class D{ajv;graffiti;callbacks=new Set;constructor(e,t){this.ajv=t??new b({strict:!1}),this.graffiti=e}async synchronizeDispatch(e,t){for(const a of this.callbacks)a(e,t);await Promise.resolve(),await Promise.resolve(),await Promise.resolve()}get=async(...e)=>{const t=await this.graffiti.get(...e);return this.synchronizeDispatch(t),t};put=async(...e)=>{const t=await this.graffiti.put(...e),a=e[0],i={...t,value:a.value,channels:a.channels,allowed:a.allowed,tombstone:!1};return await this.synchronizeDispatch(t,i),t};patch=async(...e)=>{const t=await this.graffiti.patch(...e),a={...t};a.tombstone=!1;for(const i of["value","channels","allowed"])u(d,i,e[0],a);return await this.synchronizeDispatch(t,a),t};delete=async(...e)=>{const t=await this.graffiti.delete(...e);return await this.synchronizeDispatch(t),t};objectStream(e){const t=this.synchronizeDispatch.bind(this);return async function*(){let i=await e.next();for(;!i.done;)i.value.error||t(i.value.value),yield i.value,i=await e.next();return i.value}()}discover=(...e)=>{const t=this.graffiti.discover(...e);return this.objectStream(t)};recoverOrphans=(...e)=>{const t=this.graffiti.recoverOrphans(...e);return this.objectStream(t)};synchronize(e,t,a,i){const r=m(this.ajv,a);return new y(async(c,n)=>{const h=async(l,p)=>{for(const o of[p,l])if(o&&e(o)&&v(o,i)){const f={...o};if(G(f,t,i),r(f)){c({value:f});break}}};this.callbacks.add(h),await n,this.callbacks.delete(h)})}synchronizeDiscover=(...e)=>{const[t,a,i]=e;function r(s){return s.channels.some(c=>t.includes(c))}return this.synchronize(r,t,a,i)};synchronizeGet=(...e)=>{const[t,a,i]=e;function r(s){const c=j(s),{uri:n}=O(t);return c===n}return this.synchronize(r,[],a,i)};synchronizeRecoverOrphans=(...e)=>{const[t,a]=e;function i(r){return r.actor===a.actor&&r.channels.length===0}return this.synchronize(i,[],t,a)}}export{D as GraffitiSynchronize};
|
|
2
2
|
//# sourceMappingURL=synchronize.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/synchronize.ts"],
|
|
4
|
-
"sourcesContent": ["import Ajv from \"ajv-draft-04\";\nimport type {\n Graffiti,\n GraffitiSession,\n JSONSchema4,\n} from \"@graffiti-garden/api\";\nimport type { GraffitiObjectBase } from \"@graffiti-garden/api\";\nimport { Repeater } from \"@repeaterjs/repeater\";\nimport { applyPatch } from \"fast-json-patch\";\nimport {\n applyGraffitiPatch,\n attemptAjvCompile,\n isActorAllowedGraffitiObject,\n locationToUri,\n maskGraffitiObject,\n unpackLocationOrUri,\n} from \"./utilities.js\";\n\ntype
|
|
5
|
-
"mappings": "AAAA,OAAOA,MAAS,eAOhB,OAAS,YAAAC,MAAgB,uBACzB,OAAS,cAAAC,MAAkB,kBAC3B,OACE,sBAAAC,EACA,qBAAAC,EACA,gCAAAC,EACA,iBAAAC,EACA,sBAAAC,EACA,uBAAAC,MACK,iBAkBA,MAAMC,CAcb,CACqB,
|
|
6
|
-
"names": ["Ajv", "Repeater", "applyPatch", "applyGraffitiPatch", "attemptAjvCompile", "isActorAllowedGraffitiObject", "locationToUri", "maskGraffitiObject", "unpackLocationOrUri", "GraffitiSynchronize", "graffiti", "ajv", "oldObject", "newObject", "
|
|
4
|
+
"sourcesContent": ["import Ajv from \"ajv-draft-04\";\nimport type {\n Graffiti,\n GraffitiSession,\n JSONSchema4,\n} from \"@graffiti-garden/api\";\nimport type { GraffitiObjectBase } from \"@graffiti-garden/api\";\nimport { Repeater } from \"@repeaterjs/repeater\";\nimport { applyPatch } from \"fast-json-patch\";\nimport {\n applyGraffitiPatch,\n attemptAjvCompile,\n isActorAllowedGraffitiObject,\n locationToUri,\n maskGraffitiObject,\n unpackLocationOrUri,\n} from \"./utilities.js\";\n\ntype GraffitiDatabaseMethods = Pick<\n Graffiti,\n \"get\" | \"put\" | \"patch\" | \"delete\" | \"discover\" | \"recoverOrphans\"\n>;\n\ntype Callback = (\n oldObject: GraffitiObjectBase,\n newObject?: GraffitiObjectBase,\n) => void;\n\n/**\n * Wraps a partial implementation of the [Graffiti API](https://api.graffiti.garden/classes/Graffiti.html)\n * to provide the [`synchronize`](https://api.graffiti.garden/classes/Graffiti.html#synchronize) method.\n * The partial implementation must include the primary database methods:\n * `get`, `put`, `patch`, `delete`, and `discover`.\n */\nexport class GraffitiSynchronize\n implements\n Pick<\n Graffiti,\n | \"put\"\n | \"get\"\n | \"patch\"\n | \"delete\"\n | \"discover\"\n | \"recoverOrphans\"\n | \"synchronizeDiscover\"\n | \"synchronizeGet\"\n | \"synchronizeRecoverOrphans\"\n >\n{\n protected readonly ajv: Ajv;\n protected readonly graffiti: GraffitiDatabaseMethods;\n protected readonly callbacks = new Set<Callback>();\n\n // Pass in the ajv instance\n // and database methods to wrap\n constructor(graffiti: GraffitiDatabaseMethods, ajv?: Ajv) {\n this.ajv = ajv ?? new Ajv({ strict: false });\n this.graffiti = graffiti;\n }\n\n protected async synchronizeDispatch(\n oldObject: GraffitiObjectBase,\n newObject?: GraffitiObjectBase,\n ) {\n for (const callback of this.callbacks) {\n callback(oldObject, newObject);\n }\n // No idea why this works...\n // You can't await push in the callback\n // below, because the await will only resolve\n // after a subsequent .next() call\n await Promise.resolve();\n await Promise.resolve();\n await Promise.resolve();\n }\n\n get: Graffiti[\"get\"] = async (...args) => {\n const object = await this.graffiti.get(...args);\n this.synchronizeDispatch(object);\n return object;\n };\n\n put: Graffiti[\"put\"] = async (...args) => {\n const oldObject = await this.graffiti.put(...args);\n const partialObject = args[0];\n const newObject: GraffitiObjectBase = {\n ...oldObject,\n value: partialObject.value,\n channels: partialObject.channels,\n allowed: partialObject.allowed,\n tombstone: false,\n };\n await this.synchronizeDispatch(oldObject, newObject);\n return oldObject;\n };\n\n patch: Graffiti[\"patch\"] = async (...args) => {\n const oldObject = await this.graffiti.patch(...args);\n const newObject: GraffitiObjectBase = { ...oldObject };\n newObject.tombstone = false;\n for (const prop of [\"value\", \"channels\", \"allowed\"] as const) {\n applyGraffitiPatch(applyPatch, prop, args[0], newObject);\n }\n await this.synchronizeDispatch(oldObject, newObject);\n return oldObject;\n };\n\n delete: Graffiti[\"delete\"] = async (...args) => {\n const oldObject = await this.graffiti.delete(...args);\n await this.synchronizeDispatch(oldObject);\n return oldObject;\n };\n\n protected objectStream<Schema extends JSONSchema4>(\n iterator: ReturnType<typeof Graffiti.prototype.discover<Schema>>,\n ) {\n const dispatch = this.synchronizeDispatch.bind(this);\n const wrapper = async function* () {\n let result = await iterator.next();\n while (!result.done) {\n if (!result.value.error) {\n dispatch(result.value.value);\n }\n yield result.value;\n result = await iterator.next();\n }\n return result.value;\n };\n return wrapper();\n }\n\n discover: Graffiti[\"discover\"] = (...args) => {\n const iterator = this.graffiti.discover(...args);\n return this.objectStream(iterator);\n };\n\n recoverOrphans: Graffiti[\"recoverOrphans\"] = (...args) => {\n const iterator = this.graffiti.recoverOrphans(...args);\n return this.objectStream(iterator);\n };\n\n protected synchronize<Schema extends JSONSchema4>(\n matchObject: (object: GraffitiObjectBase) => boolean,\n channels: string[],\n schema: Schema,\n session?: GraffitiSession | null,\n ) {\n const validate = attemptAjvCompile(this.ajv, schema);\n\n const repeater: ReturnType<\n typeof Graffiti.prototype.synchronizeDiscover<typeof schema>\n > = new Repeater(async (push, stop) => {\n const callback: Callback = async (oldObjectRaw, newObjectRaw) => {\n for (const objectRaw of [newObjectRaw, oldObjectRaw]) {\n if (\n objectRaw &&\n matchObject(objectRaw) &&\n isActorAllowedGraffitiObject(objectRaw, session)\n ) {\n const object = { ...objectRaw };\n maskGraffitiObject(object, channels, session);\n if (validate(object)) {\n push({ value: object });\n break;\n }\n }\n }\n };\n\n this.callbacks.add(callback);\n await stop;\n this.callbacks.delete(callback);\n });\n\n return repeater;\n }\n\n synchronizeDiscover: Graffiti[\"synchronizeDiscover\"] = (...args) => {\n const [channels, schema, session] = args;\n function matchObject(object: GraffitiObjectBase) {\n return object.channels.some((channel) => channels.includes(channel));\n }\n return this.synchronize(matchObject, channels, schema, session);\n };\n\n synchronizeGet: Graffiti[\"synchronizeGet\"] = (...args) => {\n const [locationOrUri, schema, session] = args;\n function matchObject(object: GraffitiObjectBase) {\n const objectUri = locationToUri(object);\n const { uri } = unpackLocationOrUri(locationOrUri);\n return objectUri === uri;\n }\n return this.synchronize(matchObject, [], schema, session);\n };\n\n synchronizeRecoverOrphans: Graffiti[\"synchronizeRecoverOrphans\"] = (\n ...args\n ) => {\n const [schema, session] = args;\n function matchObject(object: GraffitiObjectBase) {\n return object.actor === session.actor && object.channels.length === 0;\n }\n return this.synchronize(matchObject, [], schema, session);\n };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["Ajv", "Repeater", "applyPatch", "applyGraffitiPatch", "attemptAjvCompile", "isActorAllowedGraffitiObject", "locationToUri", "maskGraffitiObject", "unpackLocationOrUri", "GraffitiSynchronize", "graffiti", "ajv", "oldObject", "newObject", "callback", "args", "object", "partialObject", "prop", "iterator", "dispatch", "result", "matchObject", "channels", "schema", "session", "validate", "push", "stop", "oldObjectRaw", "newObjectRaw", "objectRaw", "channel", "locationOrUri", "objectUri", "uri"]
|
|
7
7
|
}
|