@graffiti-garden/implementation-local 0.6.0 → 0.6.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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/index.ts"],
4
- "sourcesContent": ["import { Graffiti, type GraffitiSession } from \"@graffiti-garden/api\";\nimport { GraffitiLocalSessionManager } from \"./session-manager.js\";\nimport {\n GraffitiLocalDatabase,\n type GraffitiLocalOptions,\n} from \"./database.js\";\n\nexport type { GraffitiLocalOptions };\n\n/**\n * A local implementation of the [Graffiti API](https://api.graffiti.garden/classes/Graffiti.html)\n * based on [PouchDB](https://pouchdb.com/). PouchDb will automatically persist data in a local\n * database, either in the browser or in Node.js.\n * It can also be configured to work with an external [CouchDB](https://couchdb.apache.org/) server,\n * although using it with a remote server will not be secure.\n */\nexport class GraffitiLocal extends Graffiti {\n protected sessionManagerLocal = new GraffitiLocalSessionManager();\n login = this.sessionManagerLocal.login.bind(this.sessionManagerLocal);\n logout = this.sessionManagerLocal.logout.bind(this.sessionManagerLocal);\n sessionEvents = this.sessionManagerLocal.sessionEvents;\n\n put: Graffiti[\"put\"];\n get: Graffiti[\"get\"];\n patch: Graffiti[\"patch\"];\n delete: Graffiti[\"delete\"];\n discover: Graffiti[\"discover\"];\n recoverOrphans: Graffiti[\"recoverOrphans\"];\n channelStats: Graffiti[\"channelStats\"];\n continueStream: Graffiti[\"continueStream\"];\n\n constructor(options?: GraffitiLocalOptions) {\n super();\n\n const graffitiPouchDbBase = new GraffitiLocalDatabase(options);\n\n this.put = graffitiPouchDbBase.put.bind(graffitiPouchDbBase);\n this.get = graffitiPouchDbBase.get.bind(graffitiPouchDbBase);\n this.patch = graffitiPouchDbBase.patch.bind(graffitiPouchDbBase);\n this.delete = graffitiPouchDbBase.delete.bind(graffitiPouchDbBase);\n this.discover = graffitiPouchDbBase.discover.bind(graffitiPouchDbBase);\n this.recoverOrphans =\n graffitiPouchDbBase.recoverOrphans.bind(graffitiPouchDbBase);\n this.channelStats =\n graffitiPouchDbBase.channelStats.bind(graffitiPouchDbBase);\n this.continueStream =\n graffitiPouchDbBase.continueStream.bind(graffitiPouchDbBase);\n }\n}\n"],
5
- "mappings": "AAAA,SAAS,gBAAsC;AAC/C,SAAS,mCAAmC;AAC5C;AAAA,EACE;AAAA,OAEK;AAWA,MAAM,sBAAsB,SAAS;AAAA,EAChC,sBAAsB,IAAI,4BAA4B;AAAA,EAChE,QAAQ,KAAK,oBAAoB,MAAM,KAAK,KAAK,mBAAmB;AAAA,EACpE,SAAS,KAAK,oBAAoB,OAAO,KAAK,KAAK,mBAAmB;AAAA,EACtE,gBAAgB,KAAK,oBAAoB;AAAA,EAEzC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA,YAAY,SAAgC;AAC1C,UAAM;AAEN,UAAM,sBAAsB,IAAI,sBAAsB,OAAO;AAE7D,SAAK,MAAM,oBAAoB,IAAI,KAAK,mBAAmB;AAC3D,SAAK,MAAM,oBAAoB,IAAI,KAAK,mBAAmB;AAC3D,SAAK,QAAQ,oBAAoB,MAAM,KAAK,mBAAmB;AAC/D,SAAK,SAAS,oBAAoB,OAAO,KAAK,mBAAmB;AACjE,SAAK,WAAW,oBAAoB,SAAS,KAAK,mBAAmB;AACrE,SAAK,iBACH,oBAAoB,eAAe,KAAK,mBAAmB;AAC7D,SAAK,eACH,oBAAoB,aAAa,KAAK,mBAAmB;AAC3D,SAAK,iBACH,oBAAoB,eAAe,KAAK,mBAAmB;AAAA,EAC/D;AACF;",
4
+ "sourcesContent": ["import { Graffiti, type GraffitiSession } from \"@graffiti-garden/api\";\nimport { GraffitiLocalSessionManager } from \"./session-manager.js\";\nimport {\n GraffitiLocalDatabase,\n type GraffitiLocalOptions,\n} from \"./database.js\";\n\nexport type { GraffitiLocalOptions };\n\n/**\n * A local implementation of the [Graffiti API](https://api.graffiti.garden/classes/Graffiti.html)\n * based on [PouchDB](https://pouchdb.com/). PouchDb will automatically persist data in a local\n * database, either in the browser or in Node.js.\n * It can also be configured to work with an external [CouchDB](https://couchdb.apache.org/) server,\n * although using it with a remote server will not be secure.\n */\nexport class GraffitiLocal extends Graffiti {\n protected sessionManagerLocal = new GraffitiLocalSessionManager();\n login = this.sessionManagerLocal.login.bind(this.sessionManagerLocal);\n logout = this.sessionManagerLocal.logout.bind(this.sessionManagerLocal);\n sessionEvents = this.sessionManagerLocal.sessionEvents;\n\n put: Graffiti[\"put\"];\n get: Graffiti[\"get\"];\n patch: Graffiti[\"patch\"];\n delete: Graffiti[\"delete\"];\n discover: Graffiti[\"discover\"];\n recoverOrphans: Graffiti[\"recoverOrphans\"];\n channelStats: Graffiti[\"channelStats\"];\n continueObjectStream: Graffiti[\"continueObjectStream\"];\n\n constructor(options?: GraffitiLocalOptions) {\n super();\n\n const graffitiPouchDbBase = new GraffitiLocalDatabase(options);\n\n this.put = graffitiPouchDbBase.put.bind(graffitiPouchDbBase);\n this.get = graffitiPouchDbBase.get.bind(graffitiPouchDbBase);\n this.patch = graffitiPouchDbBase.patch.bind(graffitiPouchDbBase);\n this.delete = graffitiPouchDbBase.delete.bind(graffitiPouchDbBase);\n this.discover = graffitiPouchDbBase.discover.bind(graffitiPouchDbBase);\n this.recoverOrphans =\n graffitiPouchDbBase.recoverOrphans.bind(graffitiPouchDbBase);\n this.channelStats =\n graffitiPouchDbBase.channelStats.bind(graffitiPouchDbBase);\n this.continueObjectStream =\n graffitiPouchDbBase.continueObjectStream.bind(graffitiPouchDbBase);\n }\n}\n"],
5
+ "mappings": "AAAA,SAAS,gBAAsC;AAC/C,SAAS,mCAAmC;AAC5C;AAAA,EACE;AAAA,OAEK;AAWA,MAAM,sBAAsB,SAAS;AAAA,EAChC,sBAAsB,IAAI,4BAA4B;AAAA,EAChE,QAAQ,KAAK,oBAAoB,MAAM,KAAK,KAAK,mBAAmB;AAAA,EACpE,SAAS,KAAK,oBAAoB,OAAO,KAAK,KAAK,mBAAmB;AAAA,EACtE,gBAAgB,KAAK,oBAAoB;AAAA,EAEzC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA,YAAY,SAAgC;AAC1C,UAAM;AAEN,UAAM,sBAAsB,IAAI,sBAAsB,OAAO;AAE7D,SAAK,MAAM,oBAAoB,IAAI,KAAK,mBAAmB;AAC3D,SAAK,MAAM,oBAAoB,IAAI,KAAK,mBAAmB;AAC3D,SAAK,QAAQ,oBAAoB,MAAM,KAAK,mBAAmB;AAC/D,SAAK,SAAS,oBAAoB,OAAO,KAAK,mBAAmB;AACjE,SAAK,WAAW,oBAAoB,SAAS,KAAK,mBAAmB;AACrE,SAAK,iBACH,oBAAoB,eAAe,KAAK,mBAAmB;AAC7D,SAAK,eACH,oBAAoB,aAAa,KAAK,mBAAmB;AAC3D,SAAK,uBACH,oBAAoB,qBAAqB,KAAK,mBAAmB;AAAA,EACrE;AACF;",
6
6
  "names": []
7
7
  }
@@ -1,6 +1,5 @@
1
1
  import {
2
2
  GraffitiErrorInvalidSchema,
3
- GraffitiErrorInvalidUri,
4
3
  GraffitiErrorPatchError,
5
4
  GraffitiErrorPatchTestFailed
6
5
  } from "@graffiti-garden/api";
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/utilities.ts"],
4
- "sourcesContent": ["import {\n GraffitiErrorInvalidSchema,\n GraffitiErrorInvalidUri,\n GraffitiErrorPatchError,\n GraffitiErrorPatchTestFailed,\n} from \"@graffiti-garden/api\";\nimport type {\n GraffitiObject,\n GraffitiObjectBase,\n GraffitiPatch,\n JSONSchema,\n GraffitiSession,\n GraffitiObjectUrl,\n} from \"@graffiti-garden/api\";\nimport type { Ajv } from \"ajv\";\nimport type { applyPatch } from \"fast-json-patch\";\n\nexport function unpackObjectUrl(url: string | GraffitiObjectUrl) {\n return typeof url === \"string\" ? url : url.url;\n}\n\nexport function randomBase64(numBytes: number = 24) {\n const bytes = new Uint8Array(numBytes);\n crypto.getRandomValues(bytes);\n // Convert it to base64\n const base64 = btoa(String.fromCodePoint(...bytes));\n // Make sure it is url safe\n return base64.replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/\\=+$/, \"\");\n}\n\nexport function applyGraffitiPatch<Prop extends keyof GraffitiPatch>(\n apply: typeof applyPatch,\n prop: Prop,\n patch: GraffitiPatch,\n object: GraffitiObjectBase,\n): void {\n const ops = patch[prop];\n if (!ops || !ops.length) return;\n try {\n object[prop] = apply(object[prop], ops, true, false).newDocument;\n } catch (e) {\n if (\n typeof e === \"object\" &&\n e &&\n \"name\" in e &&\n typeof e.name === \"string\" &&\n \"message\" in e &&\n typeof e.message === \"string\"\n ) {\n if (e.name === \"TEST_OPERATION_FAILED\") {\n throw new GraffitiErrorPatchTestFailed(e.message);\n } else {\n throw new GraffitiErrorPatchError(e.name + \": \" + e.message);\n }\n } else {\n throw e;\n }\n }\n}\n\nexport function compileGraffitiObjectSchema<Schema extends JSONSchema>(\n ajv: Ajv,\n schema: Schema,\n) {\n try {\n // Force the validation guard because\n // it is too big for the type checker.\n // Fortunately json-schema-to-ts is\n // well tested against ajv.\n return ajv.compile(schema) as (\n data: GraffitiObjectBase,\n ) => data is GraffitiObject<Schema>;\n } catch (error) {\n throw new GraffitiErrorInvalidSchema(\n error instanceof Error ? error.message : undefined,\n );\n }\n}\n\nexport function maskGraffitiObject(\n object: GraffitiObjectBase,\n channels: string[],\n session?: GraffitiSession | null,\n): void {\n if (object.actor !== session?.actor) {\n object.allowed = object.allowed && session ? [session.actor] : undefined;\n object.channels = object.channels.filter((channel) =>\n channels.includes(channel),\n );\n }\n}\nexport function isActorAllowedGraffitiObject(\n object: GraffitiObjectBase,\n session?: GraffitiSession | null,\n) {\n return (\n object.allowed === undefined ||\n object.allowed === null ||\n (!!session?.actor &&\n (object.actor === session.actor ||\n object.allowed.includes(session.actor)))\n );\n}\n"],
5
- "mappings": "AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAYA,SAAS,gBAAgB,KAAiC;AAC/D,SAAO,OAAO,QAAQ,WAAW,MAAM,IAAI;AAC7C;AAEO,SAAS,aAAa,WAAmB,IAAI;AAClD,QAAM,QAAQ,IAAI,WAAW,QAAQ;AACrC,SAAO,gBAAgB,KAAK;AAE5B,QAAM,SAAS,KAAK,OAAO,cAAc,GAAG,KAAK,CAAC;AAElD,SAAO,OAAO,QAAQ,OAAO,GAAG,EAAE,QAAQ,OAAO,GAAG,EAAE,QAAQ,QAAQ,EAAE;AAC1E;AAEO,SAAS,mBACd,OACA,MACA,OACA,QACM;AACN,QAAM,MAAM,MAAM,IAAI;AACtB,MAAI,CAAC,OAAO,CAAC,IAAI,OAAQ;AACzB,MAAI;AACF,WAAO,IAAI,IAAI,MAAM,OAAO,IAAI,GAAG,KAAK,MAAM,KAAK,EAAE;AAAA,EACvD,SAAS,GAAG;AACV,QACE,OAAO,MAAM,YACb,KACA,UAAU,KACV,OAAO,EAAE,SAAS,YAClB,aAAa,KACb,OAAO,EAAE,YAAY,UACrB;AACA,UAAI,EAAE,SAAS,yBAAyB;AACtC,cAAM,IAAI,6BAA6B,EAAE,OAAO;AAAA,MAClD,OAAO;AACL,cAAM,IAAI,wBAAwB,EAAE,OAAO,OAAO,EAAE,OAAO;AAAA,MAC7D;AAAA,IACF,OAAO;AACL,YAAM;AAAA,IACR;AAAA,EACF;AACF;AAEO,SAAS,4BACd,KACA,QACA;AACA,MAAI;AAKF,WAAO,IAAI,QAAQ,MAAM;AAAA,EAG3B,SAAS,OAAO;AACd,UAAM,IAAI;AAAA,MACR,iBAAiB,QAAQ,MAAM,UAAU;AAAA,IAC3C;AAAA,EACF;AACF;AAEO,SAAS,mBACd,QACA,UACA,SACM;AACN,MAAI,OAAO,UAAU,SAAS,OAAO;AACnC,WAAO,UAAU,OAAO,WAAW,UAAU,CAAC,QAAQ,KAAK,IAAI;AAC/D,WAAO,WAAW,OAAO,SAAS;AAAA,MAAO,CAAC,YACxC,SAAS,SAAS,OAAO;AAAA,IAC3B;AAAA,EACF;AACF;AACO,SAAS,6BACd,QACA,SACA;AACA,SACE,OAAO,YAAY,UACnB,OAAO,YAAY,QAClB,CAAC,CAAC,SAAS,UACT,OAAO,UAAU,QAAQ,SACxB,OAAO,QAAQ,SAAS,QAAQ,KAAK;AAE7C;",
4
+ "sourcesContent": ["import {\n GraffitiErrorInvalidSchema,\n GraffitiErrorPatchError,\n GraffitiErrorPatchTestFailed,\n} from \"@graffiti-garden/api\";\nimport type {\n GraffitiObject,\n GraffitiObjectBase,\n GraffitiPatch,\n JSONSchema,\n GraffitiSession,\n GraffitiObjectUrl,\n} from \"@graffiti-garden/api\";\nimport type { Ajv } from \"ajv\";\nimport type { applyPatch } from \"fast-json-patch\";\n\nexport function unpackObjectUrl(url: string | GraffitiObjectUrl) {\n return typeof url === \"string\" ? url : url.url;\n}\n\nexport function randomBase64(numBytes: number = 24) {\n const bytes = new Uint8Array(numBytes);\n crypto.getRandomValues(bytes);\n // Convert it to base64\n const base64 = btoa(String.fromCodePoint(...bytes));\n // Make sure it is url safe\n return base64.replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/\\=+$/, \"\");\n}\n\nexport function applyGraffitiPatch<Prop extends keyof GraffitiPatch>(\n apply: typeof applyPatch,\n prop: Prop,\n patch: GraffitiPatch,\n object: GraffitiObjectBase,\n): void {\n const ops = patch[prop];\n if (!ops || !ops.length) return;\n try {\n object[prop] = apply(object[prop], ops, true, false).newDocument;\n } catch (e) {\n if (\n typeof e === \"object\" &&\n e &&\n \"name\" in e &&\n typeof e.name === \"string\" &&\n \"message\" in e &&\n typeof e.message === \"string\"\n ) {\n if (e.name === \"TEST_OPERATION_FAILED\") {\n throw new GraffitiErrorPatchTestFailed(e.message);\n } else {\n throw new GraffitiErrorPatchError(e.name + \": \" + e.message);\n }\n } else {\n throw e;\n }\n }\n}\n\nexport function compileGraffitiObjectSchema<Schema extends JSONSchema>(\n ajv: Ajv,\n schema: Schema,\n) {\n try {\n // Force the validation guard because\n // it is too big for the type checker.\n // Fortunately json-schema-to-ts is\n // well tested against ajv.\n return ajv.compile(schema) as (\n data: GraffitiObjectBase,\n ) => data is GraffitiObject<Schema>;\n } catch (error) {\n throw new GraffitiErrorInvalidSchema(\n error instanceof Error ? error.message : undefined,\n );\n }\n}\n\nexport function maskGraffitiObject(\n object: GraffitiObjectBase,\n channels: string[],\n session?: GraffitiSession | null,\n): void {\n if (object.actor !== session?.actor) {\n object.allowed = object.allowed && session ? [session.actor] : undefined;\n object.channels = object.channels.filter((channel) =>\n channels.includes(channel),\n );\n }\n}\nexport function isActorAllowedGraffitiObject(\n object: GraffitiObjectBase,\n session?: GraffitiSession | null,\n) {\n return (\n object.allowed === undefined ||\n object.allowed === null ||\n (!!session?.actor &&\n (object.actor === session.actor ||\n object.allowed.includes(session.actor)))\n );\n}\n"],
5
+ "mappings": "AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAYA,SAAS,gBAAgB,KAAiC;AAC/D,SAAO,OAAO,QAAQ,WAAW,MAAM,IAAI;AAC7C;AAEO,SAAS,aAAa,WAAmB,IAAI;AAClD,QAAM,QAAQ,IAAI,WAAW,QAAQ;AACrC,SAAO,gBAAgB,KAAK;AAE5B,QAAM,SAAS,KAAK,OAAO,cAAc,GAAG,KAAK,CAAC;AAElD,SAAO,OAAO,QAAQ,OAAO,GAAG,EAAE,QAAQ,OAAO,GAAG,EAAE,QAAQ,QAAQ,EAAE;AAC1E;AAEO,SAAS,mBACd,OACA,MACA,OACA,QACM;AACN,QAAM,MAAM,MAAM,IAAI;AACtB,MAAI,CAAC,OAAO,CAAC,IAAI,OAAQ;AACzB,MAAI;AACF,WAAO,IAAI,IAAI,MAAM,OAAO,IAAI,GAAG,KAAK,MAAM,KAAK,EAAE;AAAA,EACvD,SAAS,GAAG;AACV,QACE,OAAO,MAAM,YACb,KACA,UAAU,KACV,OAAO,EAAE,SAAS,YAClB,aAAa,KACb,OAAO,EAAE,YAAY,UACrB;AACA,UAAI,EAAE,SAAS,yBAAyB;AACtC,cAAM,IAAI,6BAA6B,EAAE,OAAO;AAAA,MAClD,OAAO;AACL,cAAM,IAAI,wBAAwB,EAAE,OAAO,OAAO,EAAE,OAAO;AAAA,MAC7D;AAAA,IACF,OAAO;AACL,YAAM;AAAA,IACR;AAAA,EACF;AACF;AAEO,SAAS,4BACd,KACA,QACA;AACA,MAAI;AAKF,WAAO,IAAI,QAAQ,MAAM;AAAA,EAG3B,SAAS,OAAO;AACd,UAAM,IAAI;AAAA,MACR,iBAAiB,QAAQ,MAAM,UAAU;AAAA,IAC3C;AAAA,EACF;AACF;AAEO,SAAS,mBACd,QACA,UACA,SACM;AACN,MAAI,OAAO,UAAU,SAAS,OAAO;AACnC,WAAO,UAAU,OAAO,WAAW,UAAU,CAAC,QAAQ,KAAK,IAAI;AAC/D,WAAO,WAAW,OAAO,SAAS;AAAA,MAAO,CAAC,YACxC,SAAS,SAAS,OAAO;AAAA,IAC3B;AAAA,EACF;AACF;AACO,SAAS,6BACd,QACA,SACA;AACA,SACE,OAAO,YAAY,UACnB,OAAO,YAAY,QAClB,CAAC,CAAC,SAAS,UACT,OAAO,UAAU,QAAQ,SACxB,OAAO,QAAQ,SAAS,QAAQ,KAAK;AAE7C;",
6
6
  "names": []
7
7
  }
package/dist/index.d.ts CHANGED
@@ -24,7 +24,7 @@ export declare class GraffitiLocal extends Graffiti {
24
24
  discover: Graffiti["discover"];
25
25
  recoverOrphans: Graffiti["recoverOrphans"];
26
26
  channelStats: Graffiti["channelStats"];
27
- continueStream: Graffiti["continueStream"];
27
+ continueObjectStream: Graffiti["continueObjectStream"];
28
28
  constructor(options?: GraffitiLocalOptions);
29
29
  }
30
30
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACtE,OAAO,EAAE,2BAA2B,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,eAAe,CAAC;AAEvB,YAAY,EAAE,oBAAoB,EAAE,CAAC;AAErC;;;;;;GAMG;AACH,qBAAa,aAAc,SAAQ,QAAQ;IACzC,SAAS,CAAC,mBAAmB,8BAAqC;IAClE,KAAK;aA+BkvsB,CAAC;aAA6iB,CAAC;wBA/BhutB;IACtE,MAAM,8CAAkE;IACxE,aAAa,cAA0C;IAEvD,GAAG,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;IACrB,GAAG,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;IACrB,KAAK,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;IACzB,MAAM,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC3B,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC;IAC/B,cAAc,EAAE,QAAQ,CAAC,gBAAgB,CAAC,CAAC;IAC3C,YAAY,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC;IACvC,cAAc,EAAE,QAAQ,CAAC,gBAAgB,CAAC,CAAC;gBAE/B,OAAO,CAAC,EAAE,oBAAoB;CAiB3C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACtE,OAAO,EAAE,2BAA2B,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,eAAe,CAAC;AAEvB,YAAY,EAAE,oBAAoB,EAAE,CAAC;AAErC;;;;;;GAMG;AACH,qBAAa,aAAc,SAAQ,QAAQ;IACzC,SAAS,CAAC,mBAAmB,8BAAqC;IAClE,KAAK;aA+Bq7tB,CAAC;aAA6iB,CAAC;wBA/Bn6uB;IACtE,MAAM,8CAAkE;IACxE,aAAa,cAA0C;IAEvD,GAAG,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;IACrB,GAAG,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;IACrB,KAAK,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;IACzB,MAAM,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC3B,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC;IAC/B,cAAc,EAAE,QAAQ,CAAC,gBAAgB,CAAC,CAAC;IAC3C,YAAY,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC;IACvC,oBAAoB,EAAE,QAAQ,CAAC,sBAAsB,CAAC,CAAC;gBAE3C,OAAO,CAAC,EAAE,oBAAoB;CAiB3C"}
@@ -1 +1 @@
1
- {"version":3,"file":"utilities.d.ts","sourceRoot":"","sources":["../src/utilities.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,cAAc,EACd,kBAAkB,EAClB,aAAa,EACb,UAAU,EACV,eAAe,EACf,iBAAiB,EAClB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAC/B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,iBAAiB,UAE9D;AAED,wBAAgB,YAAY,CAAC,QAAQ,GAAE,MAAW,UAOjD;AAED,wBAAgB,kBAAkB,CAAC,IAAI,SAAS,MAAM,aAAa,EACjE,KAAK,EAAE,OAAO,UAAU,EACxB,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,aAAa,EACpB,MAAM,EAAE,kBAAkB,GACzB,IAAI,CAuBN;AAED,wBAAgB,2BAA2B,CAAC,MAAM,SAAS,UAAU,EACnE,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,MAAM,UAQJ,kBAAkB,KACrB,IAAI,IAAI,cAAc,CAAC,MAAM,CAAC,CAMtC;AAED,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,kBAAkB,EAC1B,QAAQ,EAAE,MAAM,EAAE,EAClB,OAAO,CAAC,EAAE,eAAe,GAAG,IAAI,GAC/B,IAAI,CAON;AACD,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,kBAAkB,EAC1B,OAAO,CAAC,EAAE,eAAe,GAAG,IAAI,WASjC"}
1
+ {"version":3,"file":"utilities.d.ts","sourceRoot":"","sources":["../src/utilities.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,cAAc,EACd,kBAAkB,EAClB,aAAa,EACb,UAAU,EACV,eAAe,EACf,iBAAiB,EAClB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAC/B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,iBAAiB,UAE9D;AAED,wBAAgB,YAAY,CAAC,QAAQ,GAAE,MAAW,UAOjD;AAED,wBAAgB,kBAAkB,CAAC,IAAI,SAAS,MAAM,aAAa,EACjE,KAAK,EAAE,OAAO,UAAU,EACxB,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,aAAa,EACpB,MAAM,EAAE,kBAAkB,GACzB,IAAI,CAuBN;AAED,wBAAgB,2BAA2B,CAAC,MAAM,SAAS,UAAU,EACnE,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,MAAM,UAQJ,kBAAkB,KACrB,IAAI,IAAI,cAAc,CAAC,MAAM,CAAC,CAMtC;AAED,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,kBAAkB,EAC1B,QAAQ,EAAE,MAAM,EAAE,EAClB,OAAO,CAAC,EAAE,eAAe,GAAG,IAAI,GAC/B,IAAI,CAON;AACD,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,kBAAkB,EAC1B,OAAO,CAAC,EAAE,eAAe,GAAG,IAAI,WASjC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@graffiti-garden/implementation-local",
3
- "version": "0.6.0",
3
+ "version": "0.6.2",
4
4
  "description": "A local implementation of the Graffiti API using PouchDB",
5
5
  "types": "./dist/index.d.ts",
6
6
  "module": "./dist/esm/index.js",
@@ -82,7 +82,6 @@
82
82
  },
83
83
  "dependencies": {
84
84
  "@graffiti-garden/api": "^0.6.0",
85
- "@repeaterjs/repeater": "^3.0.6",
86
85
  "@types/pouchdb": "^6.4.2",
87
86
  "ajv": "^8.17.1",
88
87
  "fast-json-patch": "^3.1.1",
package/src/database.ts CHANGED
@@ -4,9 +4,8 @@ import type {
4
4
  GraffitiObjectUrl,
5
5
  JSONSchema,
6
6
  GraffitiSession,
7
- GraffitiObject,
8
- GraffitiStream,
9
- ChannelStats,
7
+ GraffitiObjectStreamContinue,
8
+ GraffitiObjectStreamContinueEntry,
10
9
  } from "@graffiti-garden/api";
11
10
  import {
12
11
  GraffitiErrorNotFound,
@@ -22,7 +21,6 @@ import {
22
21
  compileGraffitiObjectSchema,
23
22
  unpackObjectUrl,
24
23
  } from "./utilities.js";
25
- import { Repeater } from "@repeaterjs/repeater";
26
24
  import type Ajv from "ajv";
27
25
  import type { applyPatch } from "fast-json-patch";
28
26
 
@@ -68,6 +66,7 @@ export interface GraffitiLocalOptions {
68
66
  }
69
67
 
70
68
  const DEFAULT_ORIGIN = "graffiti:local:";
69
+ const LAST_MODIFIED_BUFFER = 60000;
71
70
 
72
71
  type GraffitiObjectWithTombstone = GraffitiObjectBase & { tombstone: boolean };
73
72
 
@@ -170,8 +169,8 @@ export class GraffitiLocalDatabase
170
169
  protected get applyPatch() {
171
170
  if (!this.applyPatch_) {
172
171
  this.applyPatch_ = (async () => {
173
- const { applyPatch } = await import("fast-json-patch");
174
- return applyPatch;
172
+ const imported = await import("fast-json-patch");
173
+ return imported.applyPatch || imported.default.applyPatch;
175
174
  })();
176
175
  }
177
176
  return this.applyPatch_;
@@ -587,103 +586,105 @@ export class GraffitiLocalDatabase
587
586
  };
588
587
  }
589
588
 
590
- protected discoverMeta<Schema extends JSONSchema>(
591
- channels: string[],
592
- schema: Schema,
593
- session?: GraffitiSession | null,
594
- ifModifiedSince?: number,
595
- ): GraffitiStream<GraffitiObject<Schema>> {
596
- const { startKeySuffix, endKeySuffix } = this.queryLastModifiedSuffixes(
597
- schema,
598
- ifModifiedSince,
599
- );
600
-
601
- // Don't return tombstones on the first pass
589
+ protected async *streamObjects<Schema extends JSONSchema>(
590
+ index: string,
591
+ startkey: string,
592
+ endkey: string,
593
+ validate: ReturnType<typeof compileGraffitiObjectSchema<Schema>>,
594
+ session: GraffitiSession | undefined | null,
595
+ ifModifiedSince: number | undefined,
596
+ channels?: string[],
597
+ processedIds?: Set<string>,
598
+ ): AsyncGenerator<GraffitiObjectStreamContinueEntry<Schema>> {
602
599
  const showTombstones = ifModifiedSince !== undefined;
603
600
 
604
- const repeater: GraffitiStream<GraffitiObject<typeof schema>> =
605
- // @ts-ignore
606
- new Repeater(async (push, stop) => {
607
- const validate = compileGraffitiObjectSchema(await this.ajv, schema);
601
+ const result = await (
602
+ await this.db
603
+ ).query<GraffitiObjectWithTombstone>(index, {
604
+ startkey,
605
+ endkey,
606
+ include_docs: true,
607
+ });
608
608
 
609
- const processedIds = new Set<string>();
609
+ for (const row of result.rows) {
610
+ const doc = row.doc;
611
+ if (!doc) continue;
610
612
 
611
- for (const channel of channels) {
612
- const keyPrefix = encodeURIComponent(channel) + "/";
613
- const startkey = keyPrefix + startKeySuffix;
614
- const endkey = keyPrefix + endKeySuffix;
613
+ if (processedIds?.has(doc._id)) continue;
614
+ processedIds?.add(doc._id);
615
615
 
616
- const result = await (
617
- await this.db
618
- ).query<GraffitiObjectWithTombstone>(
619
- "indexes/objectsPerChannelAndLastModified",
620
- { startkey, endkey, include_docs: true },
621
- );
616
+ if (!showTombstones && doc.tombstone) continue;
622
617
 
623
- for (const row of result.rows) {
624
- const doc = row.doc;
625
- if (!doc) continue;
618
+ const object = this.extractGraffitiObject(doc);
626
619
 
627
- if (!showTombstones && doc.tombstone) continue;
620
+ if (channels) {
621
+ if (!isActorAllowedGraffitiObject(object, session)) continue;
622
+ maskGraffitiObject(object, channels, session);
623
+ }
628
624
 
629
- const object = this.extractGraffitiObject(doc);
625
+ if (!validate(object)) continue;
630
626
 
631
- if (!ifModifiedSince || object.lastModified > ifModifiedSince) {
632
- ifModifiedSince = object.lastModified;
633
- }
627
+ yield doc.tombstone
628
+ ? {
629
+ tombstone: true,
630
+ object: {
631
+ url: object.url,
632
+ lastModified: object.lastModified,
633
+ },
634
+ }
635
+ : { object };
636
+ }
637
+ }
634
638
 
635
- // Don't double return the same object
636
- // (which can happen if it's in multiple channels)
637
- if (processedIds.has(doc._id)) continue;
638
- processedIds.add(doc._id);
639
+ protected async *discoverMeta<Schema extends JSONSchema>(
640
+ args: Parameters<typeof Graffiti.prototype.discover<Schema>>,
641
+ ifModifiedSince?: number,
642
+ ): AsyncGenerator<
643
+ GraffitiObjectStreamContinueEntry<Schema>,
644
+ number | undefined
645
+ > {
646
+ const [channels, schema, session] = args;
647
+ const validate = compileGraffitiObjectSchema(await this.ajv, schema);
648
+ const { startKeySuffix, endKeySuffix } = this.queryLastModifiedSuffixes(
649
+ schema,
650
+ ifModifiedSince,
651
+ );
639
652
 
640
- // Make sure the user is allowed to see it
641
- if (!isActorAllowedGraffitiObject(doc, session)) continue;
653
+ const processedIds = new Set<string>();
642
654
 
643
- // Mask out the allowed list and channels
644
- // if the user is not the owner
645
- maskGraffitiObject(object, channels, session);
655
+ const startTime = new Date().getTime();
646
656
 
647
- // Check that it matches the schema
648
- if (validate(object)) {
649
- await push({
650
- value: object,
651
- ...(doc.tombstone ? { tombstone: true } : {}),
652
- });
653
- }
654
- }
655
- }
656
- stop();
657
-
658
- const cursor: string =
659
- "discover:" +
660
- JSON.stringify({
661
- channels,
662
- schema,
663
- ifModifiedSince,
664
- actor: session?.actor,
665
- });
666
- return {
667
- cursor,
668
- continue: () =>
669
- this.continueStream(cursor, session) as GraffitiStream<
670
- GraffitiObject<Schema>
671
- >,
672
- };
673
- });
657
+ for (const channel of channels) {
658
+ const keyPrefix = encodeURIComponent(channel) + "/";
659
+ const startkey = keyPrefix + startKeySuffix;
660
+ const endkey = keyPrefix + endKeySuffix;
674
661
 
675
- return repeater;
676
- }
662
+ const iterator = this.streamObjects<Schema>(
663
+ "indexes/objectsPerChannelAndLastModified",
664
+ startkey,
665
+ endkey,
666
+ validate,
667
+ session,
668
+ ifModifiedSince,
669
+ channels,
670
+ processedIds,
671
+ );
677
672
 
678
- discover: Graffiti["discover"] = (...args) => {
679
- return this.discoverMeta<(typeof args)[1]>(...args);
680
- };
673
+ for await (const result of iterator) yield result;
674
+ }
675
+
676
+ // Subtract a minute to make sure we don't miss any objects
677
+ return startTime - LAST_MODIFIED_BUFFER;
678
+ }
681
679
 
682
- protected recoverOrphansMeta<Schema extends JSONSchema>(
683
- schema: Schema,
684
- session: GraffitiSession,
680
+ protected async *recoverOrphansMeta<Schema extends JSONSchema>(
681
+ args: Parameters<typeof Graffiti.prototype.recoverOrphans<Schema>>,
685
682
  ifModifiedSince?: number,
686
- ): GraffitiStream<GraffitiObject<Schema>> {
683
+ ): AsyncGenerator<
684
+ GraffitiObjectStreamContinueEntry<Schema>,
685
+ number | undefined
686
+ > {
687
+ const [schema, session] = args;
687
688
  const { startKeySuffix, endKeySuffix } = this.queryLastModifiedSuffixes(
688
689
  schema,
689
690
  ifModifiedSince,
@@ -692,139 +693,196 @@ export class GraffitiLocalDatabase
692
693
  const startkey = keyPrefix + startKeySuffix;
693
694
  const endkey = keyPrefix + endKeySuffix;
694
695
 
695
- // Don't return tombstones on the first pass
696
- const showTombstones = ifModifiedSince !== undefined;
696
+ const validate = compileGraffitiObjectSchema(await this.ajv, schema);
697
697
 
698
- const repeater: GraffitiStream<GraffitiObject<Schema>> =
699
- // @ts-ignore
700
- new Repeater(async (push, stop) => {
701
- const validate = compileGraffitiObjectSchema(await this.ajv, schema);
702
-
703
- const result = await (
704
- await this.db
705
- ).query<GraffitiObjectWithTombstone>(
706
- "indexes/orphansPerActorAndLastModified",
707
- {
708
- startkey,
709
- endkey,
710
- include_docs: true,
711
- },
712
- );
698
+ const startTime = new Date().getTime();
699
+
700
+ const iterator = this.streamObjects<Schema>(
701
+ "indexes/orphansPerActorAndLastModified",
702
+ startkey,
703
+ endkey,
704
+ validate,
705
+ session,
706
+ ifModifiedSince,
707
+ );
713
708
 
714
- for (const row of result.rows) {
715
- const doc = row.doc;
716
- if (!doc) continue;
709
+ for await (const result of iterator) yield result;
717
710
 
718
- if (!showTombstones && doc.tombstone) continue;
711
+ return startTime - LAST_MODIFIED_BUFFER;
712
+ }
719
713
 
720
- if (!ifModifiedSince || doc.lastModified > ifModifiedSince) {
721
- ifModifiedSince = doc.lastModified;
722
- }
714
+ protected discoverCursor(
715
+ args: Parameters<typeof Graffiti.prototype.discover<{}>>,
716
+ ifModifiedSince?: number,
717
+ ): string {
718
+ return (
719
+ "discover:" +
720
+ JSON.stringify({
721
+ channels: args[0],
722
+ schema: args[1],
723
+ actor: args[2]?.actor,
724
+ ifModifiedSince: ifModifiedSince,
725
+ })
726
+ );
727
+ }
723
728
 
724
- // No masking/access necessary because
725
- // the objects are all owned by the querier
729
+ protected async *discoverContinue<Schema extends JSONSchema>(
730
+ args: Parameters<typeof Graffiti.prototype.discover<Schema>>,
731
+ ifModifiedSince?: number,
732
+ ): GraffitiObjectStreamContinue<Schema> {
733
+ const iterator = this.discoverMeta(args, ifModifiedSince);
726
734
 
727
- const object = this.extractGraffitiObject(doc);
728
- if (validate(object)) {
729
- await push({
730
- value: object,
731
- ...(doc.tombstone ? { tombstone: true } : {}),
732
- });
733
- }
735
+ while (true) {
736
+ const result = await iterator.next();
737
+ if (result.done) {
738
+ const ifModifiedSince = result.value;
739
+ return {
740
+ continue: () => this.discoverContinue<Schema>(args, ifModifiedSince),
741
+ cursor: this.discoverCursor(args, ifModifiedSince),
742
+ };
743
+ }
744
+ yield result.value;
745
+ }
746
+ }
747
+
748
+ discover: Graffiti["discover"] = (...args) => {
749
+ const iterator = this.discoverMeta(args);
750
+
751
+ const this_ = this;
752
+ return (async function* () {
753
+ while (true) {
754
+ const result = await iterator.next();
755
+ if (result.done) {
756
+ return {
757
+ continue: () =>
758
+ this_.discoverContinue<(typeof args)[1]>(args, result.value),
759
+ cursor: this_.discoverCursor(args, result.value),
760
+ };
734
761
  }
735
- stop();
736
- const cursor: string =
737
- "recover-orphans:" +
738
- JSON.stringify({
739
- schema,
740
- actor: session.actor,
741
- ifModifiedSince,
742
- });
762
+ // Make sure to filter out tombstones
763
+ if (result.value.tombstone) continue;
764
+ yield result.value;
765
+ }
766
+ })();
767
+ };
768
+
769
+ protected recoverOrphansCursor(
770
+ args: Parameters<typeof Graffiti.prototype.recoverOrphans<{}>>,
771
+ ifModifiedSince?: number,
772
+ ): string {
773
+ return (
774
+ "orphans:" +
775
+ JSON.stringify({
776
+ schema: args[0],
777
+ actor: args[1]?.actor,
778
+ ifModifiedSince,
779
+ })
780
+ );
781
+ }
782
+
783
+ protected async *recoverOrphansContinue<Schema extends JSONSchema>(
784
+ args: Parameters<typeof Graffiti.prototype.recoverOrphans<Schema>>,
785
+ ifModifiedSince?: number,
786
+ ): GraffitiObjectStreamContinue<Schema> {
787
+ const iterator = this.recoverOrphansMeta(args, ifModifiedSince);
788
+
789
+ while (true) {
790
+ const result = await iterator.next();
791
+ if (result.done) {
792
+ const ifModifiedSince = result.value;
743
793
  return {
744
- cursor,
745
794
  continue: () =>
746
- this.continueStream(cursor, session) as GraffitiStream<
747
- GraffitiObject<Schema>
748
- >,
795
+ this.recoverOrphansContinue<Schema>(args, ifModifiedSince),
796
+ cursor: this.recoverOrphansCursor(args, ifModifiedSince),
749
797
  };
750
- });
751
-
752
- return repeater;
798
+ }
799
+ yield result.value;
800
+ }
753
801
  }
754
802
 
755
803
  recoverOrphans: Graffiti["recoverOrphans"] = (...args) => {
756
- return this.recoverOrphansMeta<(typeof args)[0]>(...args);
804
+ const iterator = this.recoverOrphansMeta(args);
805
+
806
+ const this_ = this;
807
+ return (async function* () {
808
+ while (true) {
809
+ const result = await iterator.next();
810
+ if (result.done) {
811
+ return {
812
+ continue: () =>
813
+ this_.recoverOrphansContinue<(typeof args)[0]>(
814
+ args,
815
+ result.value,
816
+ ),
817
+ cursor: this_.recoverOrphansCursor(args, result.value),
818
+ };
819
+ }
820
+ // Make sure to filter out tombstones
821
+ if (result.value.tombstone) continue;
822
+ yield result.value;
823
+ }
824
+ })();
757
825
  };
758
826
 
759
827
  channelStats: Graffiti["channelStats"] = (session) => {
760
- const repeater: ReturnType<typeof Graffiti.prototype.channelStats> =
761
- new Repeater(async (push, stop) => {
762
- const keyPrefix = encodeURIComponent(session.actor) + "/";
763
- const result = await (
764
- await this.db
765
- ).query("indexes/channelStatsPerActor", {
766
- startkey: keyPrefix,
767
- endkey: keyPrefix + "\uffff",
768
- reduce: true,
769
- group: true,
770
- });
771
- for (const row of result.rows) {
772
- const channelEncoded = row.key.split("/")[1];
773
- if (typeof channelEncoded !== "string") continue;
774
- const { count, max: lastModified } = row.value;
775
- if (typeof count !== "number" || typeof lastModified !== "number")
776
- continue;
777
- await push({
778
- value: {
779
- channel: decodeURIComponent(channelEncoded),
780
- count,
781
- lastModified,
782
- },
783
- });
784
- }
785
- stop();
786
- const cursor = "channel-stats";
787
- return {
788
- cursor,
789
- continue: () =>
790
- this.continueStream(
791
- cursor,
792
- session,
793
- ) as GraffitiStream<ChannelStats>,
794
- };
828
+ const this_ = this;
829
+ return (async function* () {
830
+ const keyPrefix = encodeURIComponent(session.actor) + "/";
831
+ const result = await (
832
+ await this_.db
833
+ ).query("indexes/channelStatsPerActor", {
834
+ startkey: keyPrefix,
835
+ endkey: keyPrefix + "\uffff",
836
+ reduce: true,
837
+ group: true,
795
838
  });
796
-
797
- return repeater;
839
+ for (const row of result.rows) {
840
+ const channelEncoded = row.key.split("/")[1];
841
+ if (typeof channelEncoded !== "string") continue;
842
+ const { count, max: lastModified } = row.value;
843
+ if (typeof count !== "number" || typeof lastModified !== "number")
844
+ continue;
845
+ yield {
846
+ value: {
847
+ channel: decodeURIComponent(channelEncoded),
848
+ count,
849
+ lastModified,
850
+ },
851
+ };
852
+ }
853
+ })();
798
854
  };
799
855
 
800
- continueStream: Graffiti["continueStream"] = (cursor, session) => {
801
- if (cursor === "channel-stats") {
802
- if (!session) {
856
+ continueObjectStream: Graffiti["continueObjectStream"] = (
857
+ cursor,
858
+ session,
859
+ ) => {
860
+ if (cursor.startsWith("discover:")) {
861
+ const { channels, schema, actor, ifModifiedSince } = JSON.parse(
862
+ cursor.slice("discover:".length),
863
+ );
864
+ if (actor && actor !== session?.actor) {
803
865
  throw new GraffitiErrorForbidden(
804
- "You must be logged in to continue the stream",
866
+ "Cannot continue a cursor for another actor",
805
867
  );
806
868
  }
807
- return this.channelStats(session);
808
- } else if (cursor.startsWith("recover-orphans:")) {
869
+ return this.discoverContinue<{}>(
870
+ [channels, schema, session],
871
+ ifModifiedSince,
872
+ );
873
+ } else if (cursor.startsWith("orphans:")) {
809
874
  const { schema, actor, ifModifiedSince } = JSON.parse(
810
- cursor.slice("recover-orphans:".length),
875
+ cursor.slice("orphans:".length),
811
876
  );
812
- if (!session || session.actor !== actor) {
877
+ if (!session || actor !== session?.actor) {
813
878
  throw new GraffitiErrorForbidden(
814
- "You must be logged in as the actor same actor who started the stream",
879
+ "Cannot continue a cursor for another actor",
815
880
  );
816
881
  }
817
- return this.recoverOrphansMeta(schema, session, ifModifiedSince);
818
- } else if (cursor.startsWith("discover:")) {
819
- const { channels, schema, actor, ifModifiedSince } = JSON.parse(
820
- cursor.slice("discover:".length),
882
+ return this.recoverOrphansContinue<{}>(
883
+ [schema, session],
884
+ ifModifiedSince,
821
885
  );
822
- if (session?.actor !== actor) {
823
- throw new GraffitiErrorForbidden(
824
- "You must be logged in as the actor same actor who started the stream",
825
- );
826
- }
827
- return this.discoverMeta(channels, schema, session, ifModifiedSince);
828
886
  } else {
829
887
  throw new GraffitiErrorNotFound("Cursor not found");
830
888
  }
package/src/index.ts CHANGED
@@ -27,7 +27,7 @@ export class GraffitiLocal extends Graffiti {
27
27
  discover: Graffiti["discover"];
28
28
  recoverOrphans: Graffiti["recoverOrphans"];
29
29
  channelStats: Graffiti["channelStats"];
30
- continueStream: Graffiti["continueStream"];
30
+ continueObjectStream: Graffiti["continueObjectStream"];
31
31
 
32
32
  constructor(options?: GraffitiLocalOptions) {
33
33
  super();
@@ -43,7 +43,7 @@ export class GraffitiLocal extends Graffiti {
43
43
  graffitiPouchDbBase.recoverOrphans.bind(graffitiPouchDbBase);
44
44
  this.channelStats =
45
45
  graffitiPouchDbBase.channelStats.bind(graffitiPouchDbBase);
46
- this.continueStream =
47
- graffitiPouchDbBase.continueStream.bind(graffitiPouchDbBase);
46
+ this.continueObjectStream =
47
+ graffitiPouchDbBase.continueObjectStream.bind(graffitiPouchDbBase);
48
48
  }
49
49
  }
package/src/utilities.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import {
2
2
  GraffitiErrorInvalidSchema,
3
- GraffitiErrorInvalidUri,
4
3
  GraffitiErrorPatchError,
5
4
  GraffitiErrorPatchTestFailed,
6
5
  } from "@graffiti-garden/api";