@dabble/patches 0.2.4 → 0.2.6

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,3 +1,4 @@
1
+ import { type Unsubscriber } from '../event-signal.js';
1
2
  import type { JSONPatch } from '../json-patch/JSONPatch.js';
2
3
  import type { Change, PatchesSnapshot } from '../types.js';
3
4
  /**
@@ -29,12 +30,16 @@ export declare class PatchesDoc<T extends object = object> {
29
30
  get id(): string | null;
30
31
  /** Current local state (committed + sending + pending). */
31
32
  get state(): T;
33
+ /** Alias for state. */
34
+ get value(): T;
32
35
  /** Last committed revision number from the server. */
33
36
  get committedRev(): number;
34
37
  /** Are there changes currently awaiting server confirmation? */
35
38
  get isSending(): boolean;
36
39
  /** Are there local changes that haven't been sent yet? */
37
40
  get hasPending(): boolean;
41
+ /** Subscribe to be notified whenever value changes. */
42
+ subscribe(onUpdate: (newValue: T) => void): Unsubscriber;
38
43
  /**
39
44
  * Exports the document state for persistence.
40
45
  * NOTE: Any changes currently marked as `sending` are included in the
@@ -37,6 +37,10 @@ export class PatchesDoc {
37
37
  get state() {
38
38
  return this._state;
39
39
  }
40
+ /** Alias for state. */
41
+ get value() {
42
+ return this._state;
43
+ }
40
44
  /** Last committed revision number from the server. */
41
45
  get committedRev() {
42
46
  return this._committedRev;
@@ -49,6 +53,12 @@ export class PatchesDoc {
49
53
  get hasPending() {
50
54
  return this._pendingChanges.length > 0;
51
55
  }
56
+ /** Subscribe to be notified whenever value changes. */
57
+ subscribe(onUpdate) {
58
+ const unsub = this.onUpdate(onUpdate);
59
+ onUpdate(this._state);
60
+ return unsub;
61
+ }
52
62
  /**
53
63
  * Exports the document state for persistence.
54
64
  * NOTE: Any changes currently marked as `sending` are included in the
@@ -174,14 +174,14 @@ export class IndexedDBStore {
174
174
  let docMeta = await docsStore.get(docId);
175
175
  if (!docMeta) {
176
176
  docMeta = { docId, committedRev: 0 };
177
- await docsStore.add(docMeta);
177
+ await docsStore.put(docMeta);
178
178
  }
179
179
  else if (docMeta.deleted) {
180
180
  delete docMeta.deleted;
181
181
  await docsStore.put(docMeta);
182
182
  console.warn(`Revived document ${docId} by saving pending changes.`);
183
183
  }
184
- await Promise.all(changes.map(change => pendingChanges.add({ ...change, docId })));
184
+ await Promise.all(changes.map(change => pendingChanges.put({ ...change, docId })));
185
185
  this.onPendingChanges.emit(docId, changes);
186
186
  await tx.complete();
187
187
  }
@@ -206,7 +206,7 @@ export class IndexedDBStore {
206
206
  async saveCommittedChanges(docId, changes, sentPendingRange) {
207
207
  const [tx, committedChanges, pendingChanges, snapshots, docsStore] = await this.transaction(['committedChanges', 'pendingChanges', 'snapshots', 'docs'], 'readwrite');
208
208
  // Save committed changes
209
- await Promise.all(changes.map(change => committedChanges.add({ ...change, docId })));
209
+ await Promise.all(changes.map(change => committedChanges.put({ ...change, docId })));
210
210
  // Remove pending changes if range provided
211
211
  if (sentPendingRange) {
212
212
  await pendingChanges.delete([docId, sentPendingRange[0]], [docId, sentPendingRange[1]]);
@@ -226,7 +226,7 @@ export class IndexedDBStore {
226
226
  if (!firstPending?.baseRev || firstPending?.baseRev >= lastRev) {
227
227
  const state = applyChanges(snapshot?.state, committed);
228
228
  await Promise.all([
229
- snapshots.add({
229
+ snapshots.put({
230
230
  docId,
231
231
  rev: lastRev,
232
232
  state,
@@ -266,7 +266,7 @@ export class IndexedDBStore {
266
266
  }
267
267
  else {
268
268
  // If doesn't exist, add it
269
- await docsStore.add({ docId, committedRev: 0 });
269
+ await docsStore.put({ docId, committedRev: 0 });
270
270
  }
271
271
  }));
272
272
  await tx.complete();
@@ -338,9 +338,9 @@ class IDBStoreWrapper {
338
338
  request.onerror = () => reject(request.error);
339
339
  });
340
340
  }
341
- async add(value) {
341
+ async put(value) {
342
342
  return new Promise((resolve, reject) => {
343
- const request = this.store.add(value);
343
+ const request = this.store.put(value);
344
344
  request.onsuccess = () => resolve(request.result);
345
345
  request.onerror = () => reject(request.error);
346
346
  });
@@ -374,11 +374,4 @@ class IDBStoreWrapper {
374
374
  request.onerror = () => reject(request.error);
375
375
  });
376
376
  }
377
- async put(value) {
378
- return new Promise((resolve, reject) => {
379
- const request = this.store.put(value);
380
- request.onsuccess = () => resolve(request.result);
381
- request.onerror = () => reject(request.error);
382
- });
383
- }
384
377
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dabble/patches",
3
- "version": "0.2.4",
3
+ "version": "0.2.6",
4
4
  "description": "Immutable JSON Patch implementation based on RFC 6902 supporting operational transformation and last-writer-wins",
5
5
  "author": "Jacob Wright <jacwright@gmail.com>",
6
6
  "bugs": {