@graffiti-garden/implementation-local 0.2.10 → 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.
@@ -2,6 +2,7 @@ import Ajv from "ajv-draft-04";
2
2
  import type { Graffiti, GraffitiSession, JSONSchema4 } from "@graffiti-garden/api";
3
3
  import type { GraffitiObjectBase } from "@graffiti-garden/api";
4
4
  type GraffitiDatabaseMethods = Pick<Graffiti, "get" | "put" | "patch" | "delete" | "discover" | "recoverOrphans">;
5
+ type Callback = (oldObject: GraffitiObjectBase, newObject?: GraffitiObjectBase) => void;
5
6
  /**
6
7
  * Wraps a partial implementation of the [Graffiti API](https://api.graffiti.garden/classes/Graffiti.html)
7
8
  * to provide the [`synchronize`](https://api.graffiti.garden/classes/Graffiti.html#synchronize) method.
@@ -9,11 +10,11 @@ type GraffitiDatabaseMethods = Pick<Graffiti, "get" | "put" | "patch" | "delete"
9
10
  * `get`, `put`, `patch`, `delete`, and `discover`.
10
11
  */
11
12
  export declare class GraffitiSynchronize implements Pick<Graffiti, "put" | "get" | "patch" | "delete" | "discover" | "recoverOrphans" | "synchronizeDiscover" | "synchronizeGet" | "synchronizeRecoverOrphans"> {
12
- protected readonly synchronizeEvents: EventTarget;
13
13
  protected readonly ajv: Ajv;
14
14
  protected readonly graffiti: GraffitiDatabaseMethods;
15
+ protected readonly callbacks: Set<Callback>;
15
16
  constructor(graffiti: GraffitiDatabaseMethods, ajv?: Ajv);
16
- protected synchronizeDispatch(oldObject: GraffitiObjectBase, newObject?: GraffitiObjectBase): void;
17
+ protected synchronizeDispatch(oldObject: GraffitiObjectBase, newObject?: GraffitiObjectBase): Promise<void>;
17
18
  get: Graffiti["get"];
18
19
  put: Graffiti["put"];
19
20
  patch: Graffiti["patch"];
@@ -1 +1 @@
1
- {"version":3,"file":"synchronize.d.ts","sourceRoot":"","sources":["../src/synchronize.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,cAAc,CAAC;AAC/B,OAAO,KAAK,EACV,QAAQ,EACR,eAAe,EACf,WAAW,EACZ,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAiB/D,KAAK,uBAAuB,GAAG,IAAI,CACjC,QAAQ,EACR,KAAK,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,UAAU,GAAG,gBAAgB,CACnE,CAAC;AAEF;;;;;GAKG;AACH,qBAAa,mBACX,YACE,IAAI,CACF,QAAQ,EACN,KAAK,GACL,KAAK,GACL,OAAO,GACP,QAAQ,GACR,UAAU,GACV,gBAAgB,GAChB,qBAAqB,GACrB,gBAAgB,GAChB,2BAA2B,CAC9B;IAEH,SAAS,CAAC,QAAQ,CAAC,iBAAiB,cAAqB;IACzD,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAC5B,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,uBAAuB,CAAC;gBAIzC,QAAQ,EAAE,uBAAuB,EAAE,GAAG,CAAC,EAAE,GAAG;IAKxD,SAAS,CAAC,mBAAmB,CAC3B,SAAS,EAAE,kBAAkB,EAC7B,SAAS,CAAC,EAAE,kBAAkB;IAWhC,GAAG,EAAE,QAAQ,CAAC,KAAK,CAAC,CAIlB;IAEF,GAAG,EAAE,QAAQ,CAAC,KAAK,CAAC,CAYlB;IAEF,KAAK,EAAE,QAAQ,CAAC,OAAO,CAAC,CAStB;IAEF,MAAM,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAIxB;IAEF,SAAS,CAAC,YAAY,CAAC,MAAM,SAAS,WAAW,EAC/C,QAAQ,EAAE,UAAU,CAAC,OAAO,QAAQ,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;;;;;;;;;IAiBlE,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,CAG5B;IAEF,cAAc,EAAE,QAAQ,CAAC,gBAAgB,CAAC,CAGxC;IAEF,SAAS,CAAC,WAAW,CAAC,MAAM,SAAS,WAAW,EAC9C,WAAW,EAAE,CAAC,MAAM,EAAE,kBAAkB,KAAK,OAAO,EACpD,QAAQ,EAAE,MAAM,EAAE,EAClB,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,eAAe,GAAG,IAAI;IAyClC,mBAAmB,EAAE,QAAQ,CAAC,qBAAqB,CAAC,CAMlD;IAEF,cAAc,EAAE,QAAQ,CAAC,gBAAgB,CAAC,CAQxC;IAEF,yBAAyB,EAAE,QAAQ,CAAC,2BAA2B,CAAC,CAQ9D;CACH"}
1
+ {"version":3,"file":"synchronize.d.ts","sourceRoot":"","sources":["../src/synchronize.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,cAAc,CAAC;AAC/B,OAAO,KAAK,EACV,QAAQ,EACR,eAAe,EACf,WAAW,EACZ,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAY/D,KAAK,uBAAuB,GAAG,IAAI,CACjC,QAAQ,EACR,KAAK,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,UAAU,GAAG,gBAAgB,CACnE,CAAC;AAEF,KAAK,QAAQ,GAAG,CACd,SAAS,EAAE,kBAAkB,EAC7B,SAAS,CAAC,EAAE,kBAAkB,KAC3B,IAAI,CAAC;AAEV;;;;;GAKG;AACH,qBAAa,mBACX,YACE,IAAI,CACF,QAAQ,EACN,KAAK,GACL,KAAK,GACL,OAAO,GACP,QAAQ,GACR,UAAU,GACV,gBAAgB,GAChB,qBAAqB,GACrB,gBAAgB,GAChB,2BAA2B,CAC9B;IAEH,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAC5B,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,uBAAuB,CAAC;IACrD,SAAS,CAAC,QAAQ,CAAC,SAAS,gBAAuB;gBAIvC,QAAQ,EAAE,uBAAuB,EAAE,GAAG,CAAC,EAAE,GAAG;cAKxC,mBAAmB,CACjC,SAAS,EAAE,kBAAkB,EAC7B,SAAS,CAAC,EAAE,kBAAkB;IAchC,GAAG,EAAE,QAAQ,CAAC,KAAK,CAAC,CAIlB;IAEF,GAAG,EAAE,QAAQ,CAAC,KAAK,CAAC,CAYlB;IAEF,KAAK,EAAE,QAAQ,CAAC,OAAO,CAAC,CAStB;IAEF,MAAM,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAIxB;IAEF,SAAS,CAAC,YAAY,CAAC,MAAM,SAAS,WAAW,EAC/C,QAAQ,EAAE,UAAU,CAAC,OAAO,QAAQ,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;;;;;;;;;IAiBlE,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,CAG5B;IAEF,cAAc,EAAE,QAAQ,CAAC,gBAAgB,CAAC,CAGxC;IAEF,SAAS,CAAC,WAAW,CAAC,MAAM,SAAS,WAAW,EAC9C,WAAW,EAAE,CAAC,MAAM,EAAE,kBAAkB,KAAK,OAAO,EACpD,QAAQ,EAAE,MAAM,EAAE,EAClB,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,eAAe,GAAG,IAAI;IAgClC,mBAAmB,EAAE,QAAQ,CAAC,qBAAqB,CAAC,CAMlD;IAEF,cAAc,EAAE,QAAQ,CAAC,gBAAgB,CAAC,CAQxC;IAEF,yBAAyB,EAAE,QAAQ,CAAC,2BAA2B,CAAC,CAQ9D;CACH"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@graffiti-garden/implementation-local",
3
- "version": "0.2.10",
3
+ "version": "0.2.11",
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",
@@ -89,7 +89,7 @@
89
89
  "vitest": "^2.1.8"
90
90
  },
91
91
  "dependencies": {
92
- "@graffiti-garden/api": "^0.2.7",
92
+ "@graffiti-garden/api": "^0.2.11",
93
93
  "@repeaterjs/repeater": "^3.0.6",
94
94
  "@types/pouchdb": "^6.4.2",
95
95
  "ajv": "^8.17.1",
@@ -16,16 +16,16 @@ import {
16
16
  unpackLocationOrUri,
17
17
  } from "./utilities.js";
18
18
 
19
- type SynchronizeEvent = CustomEvent<{
20
- oldObject: GraffitiObjectBase;
21
- newObject?: GraffitiObjectBase;
22
- }>;
23
-
24
19
  type GraffitiDatabaseMethods = Pick<
25
20
  Graffiti,
26
21
  "get" | "put" | "patch" | "delete" | "discover" | "recoverOrphans"
27
22
  >;
28
23
 
24
+ type Callback = (
25
+ oldObject: GraffitiObjectBase,
26
+ newObject?: GraffitiObjectBase,
27
+ ) => void;
28
+
29
29
  /**
30
30
  * Wraps a partial implementation of the [Graffiti API](https://api.graffiti.garden/classes/Graffiti.html)
31
31
  * to provide the [`synchronize`](https://api.graffiti.garden/classes/Graffiti.html#synchronize) method.
@@ -47,9 +47,9 @@ export class GraffitiSynchronize
47
47
  | "synchronizeRecoverOrphans"
48
48
  >
49
49
  {
50
- protected readonly synchronizeEvents = new EventTarget();
51
50
  protected readonly ajv: Ajv;
52
51
  protected readonly graffiti: GraffitiDatabaseMethods;
52
+ protected readonly callbacks = new Set<Callback>();
53
53
 
54
54
  // Pass in the ajv instance
55
55
  // and database methods to wrap
@@ -58,17 +58,20 @@ export class GraffitiSynchronize
58
58
  this.graffiti = graffiti;
59
59
  }
60
60
 
61
- protected synchronizeDispatch(
61
+ protected async synchronizeDispatch(
62
62
  oldObject: GraffitiObjectBase,
63
63
  newObject?: GraffitiObjectBase,
64
64
  ) {
65
- const event: SynchronizeEvent = new CustomEvent("change", {
66
- detail: {
67
- oldObject,
68
- newObject,
69
- },
70
- });
71
- this.synchronizeEvents.dispatchEvent(event);
65
+ for (const callback of this.callbacks) {
66
+ callback(oldObject, newObject);
67
+ }
68
+ // No idea why this works...
69
+ // You can't await push in the callback
70
+ // below, because the await will only resolve
71
+ // after a subsequent .next() call
72
+ await Promise.resolve();
73
+ await Promise.resolve();
74
+ await Promise.resolve();
72
75
  }
73
76
 
74
77
  get: Graffiti["get"] = async (...args) => {
@@ -87,7 +90,7 @@ export class GraffitiSynchronize
87
90
  allowed: partialObject.allowed,
88
91
  tombstone: false,
89
92
  };
90
- this.synchronizeDispatch(oldObject, newObject);
93
+ await this.synchronizeDispatch(oldObject, newObject);
91
94
  return oldObject;
92
95
  };
93
96
 
@@ -98,13 +101,13 @@ export class GraffitiSynchronize
98
101
  for (const prop of ["value", "channels", "allowed"] as const) {
99
102
  applyGraffitiPatch(applyPatch, prop, args[0], newObject);
100
103
  }
101
- this.synchronizeDispatch(oldObject, newObject);
104
+ await this.synchronizeDispatch(oldObject, newObject);
102
105
  return oldObject;
103
106
  };
104
107
 
105
108
  delete: Graffiti["delete"] = async (...args) => {
106
109
  const oldObject = await this.graffiti.delete(...args);
107
- this.synchronizeDispatch(oldObject);
110
+ await this.synchronizeDispatch(oldObject);
108
111
  return oldObject;
109
112
  };
110
113
 
@@ -147,10 +150,7 @@ export class GraffitiSynchronize
147
150
  const repeater: ReturnType<
148
151
  typeof Graffiti.prototype.synchronizeDiscover<typeof schema>
149
152
  > = new Repeater(async (push, stop) => {
150
- const callback = (event: SynchronizeEvent) => {
151
- const { oldObject: oldObjectRaw, newObject: newObjectRaw } =
152
- event.detail;
153
-
153
+ const callback: Callback = async (oldObjectRaw, newObjectRaw) => {
154
154
  for (const objectRaw of [newObjectRaw, oldObjectRaw]) {
155
155
  if (
156
156
  objectRaw &&
@@ -167,15 +167,9 @@ export class GraffitiSynchronize
167
167
  }
168
168
  };
169
169
 
170
- this.synchronizeEvents.addEventListener(
171
- "change",
172
- callback as EventListener,
173
- );
170
+ this.callbacks.add(callback);
174
171
  await stop;
175
- this.synchronizeEvents.removeEventListener(
176
- "change",
177
- callback as EventListener,
178
- );
172
+ this.callbacks.delete(callback);
179
173
  });
180
174
 
181
175
  return repeater;