@automerge/automerge-repo 1.0.7 → 1.0.8

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.
Files changed (54) hide show
  1. package/dist/DocHandle.d.ts +1 -1
  2. package/dist/DocHandle.d.ts.map +1 -1
  3. package/dist/DocHandle.js +2 -2
  4. package/dist/DocUrl.d.ts.map +1 -1
  5. package/dist/Repo.d.ts +6 -3
  6. package/dist/Repo.d.ts.map +1 -1
  7. package/dist/Repo.js +13 -8
  8. package/dist/helpers/debounce.d.ts +14 -0
  9. package/dist/helpers/debounce.d.ts.map +1 -0
  10. package/dist/helpers/debounce.js +21 -0
  11. package/dist/helpers/throttle.d.ts +28 -0
  12. package/dist/helpers/throttle.d.ts.map +1 -0
  13. package/dist/helpers/throttle.js +39 -0
  14. package/dist/index.d.ts +3 -3
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +3 -3
  17. package/dist/network/NetworkSubsystem.d.ts +1 -1
  18. package/dist/network/NetworkSubsystem.d.ts.map +1 -1
  19. package/dist/storage/StorageSubsystem.d.ts +1 -1
  20. package/dist/storage/StorageSubsystem.d.ts.map +1 -1
  21. package/dist/storage/StorageSubsystem.js +2 -2
  22. package/dist/synchronizer/CollectionSynchronizer.d.ts +1 -1
  23. package/dist/synchronizer/CollectionSynchronizer.d.ts.map +1 -1
  24. package/dist/synchronizer/CollectionSynchronizer.js +1 -1
  25. package/dist/synchronizer/DocSynchronizer.d.ts +1 -0
  26. package/dist/synchronizer/DocSynchronizer.d.ts.map +1 -1
  27. package/dist/synchronizer/DocSynchronizer.js +3 -5
  28. package/dist/synchronizer/Synchronizer.d.ts +1 -1
  29. package/dist/synchronizer/Synchronizer.d.ts.map +1 -1
  30. package/fuzz/fuzz.ts +8 -6
  31. package/fuzz/tsconfig.json +8 -0
  32. package/package.json +2 -2
  33. package/src/DocHandle.ts +3 -4
  34. package/src/DocUrl.ts +3 -1
  35. package/src/Repo.ts +27 -16
  36. package/src/helpers/debounce.ts +25 -0
  37. package/src/helpers/headsAreSame.ts +1 -1
  38. package/src/helpers/throttle.ts +43 -0
  39. package/src/index.ts +3 -3
  40. package/src/network/NetworkSubsystem.ts +1 -1
  41. package/src/storage/StorageSubsystem.ts +4 -4
  42. package/src/synchronizer/CollectionSynchronizer.ts +2 -2
  43. package/src/synchronizer/DocSynchronizer.ts +10 -7
  44. package/src/synchronizer/Synchronizer.ts +1 -1
  45. package/test/CollectionSynchronizer.test.ts +1 -1
  46. package/test/DocHandle.test.ts +1 -1
  47. package/test/DocSynchronizer.test.ts +0 -4
  48. package/test/Repo.test.ts +115 -124
  49. package/test/helpers/DummyNetworkAdapter.ts +9 -4
  50. package/test/helpers/DummyStorageAdapter.ts +4 -2
  51. package/dist/EphemeralData.d.ts +0 -20
  52. package/dist/EphemeralData.d.ts.map +0 -1
  53. package/dist/EphemeralData.js +0 -1
  54. package/src/EphemeralData.ts +0 -17
@@ -1,7 +1,7 @@
1
1
  import * as A from "@automerge/automerge/next";
2
2
  import { EventEmitter } from "eventemitter3";
3
3
  import { StateValue } from "xstate";
4
- import type { DocumentId, PeerId, AutomergeUrl } from "./types.js";
4
+ import type { AutomergeUrl, DocumentId, PeerId } from "./types.js";
5
5
  /** DocHandle is a wrapper around a single Automerge document that lets us
6
6
  * listen for changes and notify the network and storage of new changes.
7
7
  *
@@ -1 +1 @@
1
- {"version":3,"file":"DocHandle.d.ts","sourceRoot":"","sources":["../src/DocHandle.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"DocHandle.d.ts","sourceRoot":"","sources":["../src/DocHandle.ts"],"names":[],"mappings":"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"}
package/dist/DocHandle.js CHANGED
@@ -3,10 +3,10 @@ import debug from "debug";
3
3
  import { EventEmitter } from "eventemitter3";
4
4
  import { assign, createMachine, interpret, } from "xstate";
5
5
  import { waitFor } from "xstate/lib/waitFor.js";
6
- import { headsAreSame } from "./helpers/headsAreSame.js";
7
- import { withTimeout } from "./helpers/withTimeout.js";
8
6
  import { stringifyAutomergeUrl } from "./DocUrl.js";
9
7
  import { encode } from "./helpers/cbor.js";
8
+ import { headsAreSame } from "./helpers/headsAreSame.js";
9
+ import { withTimeout } from "./helpers/withTimeout.js";
10
10
  /** DocHandle is a wrapper around a single Automerge document that lets us
11
11
  * listen for changes and notify the network and storage of new changes.
12
12
  *
@@ -1 +1 @@
1
- {"version":3,"file":"DocUrl.d.ts","sourceRoot":"","sources":["../src/DocUrl.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,UAAU,EAChB,MAAM,YAAY,CAAA;AAInB,eAAO,MAAM,SAAS,eAAe,CAAA;AAErC;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,QAAS,YAAY;;;CAIlD,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB;gBAElB,UAAU,GAAG,gBAAgB;MAAI,YAQhD,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,QAAS,MAAM,wBAK9C,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,QAAO,YAGpC,CAAA;AAEJ,eAAO,MAAM,kBAAkB,UACtB,UAAU,KAChB,gBAAgB,GAAG,SACyC,CAAA;AAE/D,eAAO,MAAM,kBAAkB,UAAW,gBAAgB,KAAG,UACtB,CAAA;AAEvC,eAAO,MAAM,eAAe,QAAS,MAAM,KAAG,YAAY,GAAG,SAM5D,CAAA"}
1
+ {"version":3,"file":"DocUrl.d.ts","sourceRoot":"","sources":["../src/DocUrl.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,UAAU,EAChB,MAAM,YAAY,CAAA;AAInB,eAAO,MAAM,SAAS,eAAe,CAAA;AAErC;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,QAAS,YAAY;;;CAIlD,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB;gBAGpB,UAAU,GAAG,gBAAgB;MACvC,YAQH,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,QAAS,MAAM,wBAK9C,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,QAAO,YAGpC,CAAA;AAEJ,eAAO,MAAM,kBAAkB,UACtB,UAAU,KAChB,gBAAgB,GAAG,SACyC,CAAA;AAE/D,eAAO,MAAM,kBAAkB,UAAW,gBAAgB,KAAG,UACtB,CAAA;AAEvC,eAAO,MAAM,eAAe,QAAS,MAAM,KAAG,YAAY,GAAG,SAM5D,CAAA"}
package/dist/Repo.d.ts CHANGED
@@ -1,10 +1,10 @@
1
+ import { EventEmitter } from "eventemitter3";
2
+ import { DocHandle } from "./DocHandle.js";
1
3
  import { NetworkAdapter } from "./network/NetworkAdapter.js";
2
4
  import { NetworkSubsystem } from "./network/NetworkSubsystem.js";
3
5
  import { StorageAdapter } from "./storage/StorageAdapter.js";
4
6
  import { StorageSubsystem } from "./storage/StorageSubsystem.js";
5
- import { type AutomergeUrl, DocumentId, PeerId } from "./types.js";
6
- import { DocHandle } from "./DocHandle.js";
7
- import { EventEmitter } from "eventemitter3";
7
+ import { DocumentId, PeerId, type AutomergeUrl } from "./types.js";
8
8
  /** A Repo is a collection of documents with networking, syncing, and storage capabilities. */
9
9
  /** The `Repo` is the main entry point of this library
10
10
  *
@@ -19,6 +19,9 @@ export declare class Repo extends EventEmitter<RepoEvents> {
19
19
  networkSubsystem: NetworkSubsystem;
20
20
  /** @hidden */
21
21
  storageSubsystem?: StorageSubsystem;
22
+ /** The debounce rate is adjustable on the repo. */
23
+ /** @hidden */
24
+ saveDebounceRate: number;
22
25
  /** By default, we share generously with all peers. */
23
26
  /** @hidden */
24
27
  sharePolicy: SharePolicy;
@@ -1 +1 @@
1
- {"version":3,"file":"Repo.d.ts","sourceRoot":"","sources":["../src/Repo.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAA;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAA;AAEhE,OAAO,EAAE,KAAK,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AASlE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAG5C,8FAA8F;AAC9F;;;;;;GAMG;AACH,qBAAa,IAAK,SAAQ,YAAY,CAAC,UAAU,CAAC;;IAGhD,cAAc;IACd,gBAAgB,EAAE,gBAAgB,CAAA;IAClC,cAAc;IACd,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;IAGnC,sDAAsD;IACtD,cAAc;IACd,WAAW,EAAE,WAAW,CAAmB;gBAE/B,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,UAAU;IAuHjE,8CAA8C;IAC9C,IAAI,OAAO,uCAEV;IAED;;;;OAIG;IACH,MAAM,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC;IA0BzB;;;;;;;;;;;;;;OAcG;IACH,KAAK,CAAC,CAAC,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC,CAAC;IAuBnC;;;OAGG;IACH,IAAI,CAAC,CAAC;IACJ,+CAA+C;IAC/C,YAAY,EAAE,YAAY,GACzB,SAAS,CAAC,CAAC,CAAC;IAgCf,MAAM;IACJ,6CAA6C;IAC7C,EAAE,EAAE,UAAU,GAAG,YAAY;CAUhC;AAED,MAAM,WAAW,UAAU;IACzB,4BAA4B;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAA;IAEf,gDAAgD;IAChD,OAAO,CAAC,EAAE,cAAc,CAAA;IAExB,oDAAoD;IACpD,OAAO,EAAE,cAAc,EAAE,CAAA;IAEzB;;;OAGG;IACH,WAAW,CAAC,EAAE,WAAW,CAAA;CAC1B;AAED;;;;;;;KAOK;AACL,MAAM,MAAM,WAAW,GAAG,CACxB,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,UAAU,KACpB,OAAO,CAAC,OAAO,CAAC,CAAA;AAGrB,MAAM,WAAW,UAAU;IACzB,+CAA+C;IAC/C,QAAQ,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,IAAI,CAAA;IACxC,6BAA6B;IAC7B,iBAAiB,EAAE,CAAC,GAAG,EAAE,qBAAqB,KAAK,IAAI,CAAA;IACvD,4FAA4F;IAC5F,sBAAsB,EAAE,CAAC,GAAG,EAAE,qBAAqB,KAAK,IAAI,CAAA;CAC7D;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC,CAAA;IACtB,KAAK,EAAE,OAAO,CAAA;CACf;AAED,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,UAAU,CAAA;CACvB"}
1
+ {"version":3,"file":"Repo.d.ts","sourceRoot":"","sources":["../src/Repo.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAC5C,OAAO,EAAE,SAAS,EAAiC,MAAM,gBAAgB,CAAA;AAQzE,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAA;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAA;AAEhE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAA;AAElE,8FAA8F;AAC9F;;;;;;GAMG;AACH,qBAAa,IAAK,SAAQ,YAAY,CAAC,UAAU,CAAC;;IAGhD,cAAc;IACd,gBAAgB,EAAE,gBAAgB,CAAA;IAClC,cAAc;IACd,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;IAEnC,mDAAmD;IACnD,cAAc;IACd,gBAAgB,SAAM;IAItB,sDAAsD;IACtD,cAAc;IACd,WAAW,EAAE,WAAW,CAAmB;gBAE/B,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,UAAU;IA8HjE,8CAA8C;IAC9C,IAAI,OAAO,uCAEV;IAED;;;;OAIG;IACH,MAAM,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC;IA0BzB;;;;;;;;;;;;;;OAcG;IACH,KAAK,CAAC,CAAC,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC,CAAC;IAuBnC;;;OAGG;IACH,IAAI,CAAC,CAAC;IACJ,+CAA+C;IAC/C,YAAY,EAAE,YAAY,GACzB,SAAS,CAAC,CAAC,CAAC;IAgCf,MAAM;IACJ,6CAA6C;IAC7C,EAAE,EAAE,UAAU,GAAG,YAAY;CAUhC;AAED,MAAM,WAAW,UAAU;IACzB,4BAA4B;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAA;IAEf,gDAAgD;IAChD,OAAO,CAAC,EAAE,cAAc,CAAA;IAExB,oDAAoD;IACpD,OAAO,EAAE,cAAc,EAAE,CAAA;IAEzB;;;OAGG;IACH,WAAW,CAAC,EAAE,WAAW,CAAA;CAC1B;AAED;;;;;;;KAOK;AACL,MAAM,MAAM,WAAW,GAAG,CACxB,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,UAAU,KACpB,OAAO,CAAC,OAAO,CAAC,CAAA;AAGrB,MAAM,WAAW,UAAU;IACzB,+CAA+C;IAC/C,QAAQ,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,IAAI,CAAA;IACxC,6BAA6B;IAC7B,iBAAiB,EAAE,CAAC,GAAG,EAAE,qBAAqB,KAAK,IAAI,CAAA;IACvD,4FAA4F;IAC5F,sBAAsB,EAAE,CAAC,GAAG,EAAE,qBAAqB,KAAK,IAAI,CAAA;CAC7D;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC,CAAA;IACtB,KAAK,EAAE,OAAO,CAAA;CACf;AAED,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,UAAU,CAAA;CACvB"}
package/dist/Repo.js CHANGED
@@ -1,11 +1,12 @@
1
+ import { next as Automerge } from "@automerge/automerge";
1
2
  import debug from "debug";
3
+ import { EventEmitter } from "eventemitter3";
4
+ import { DocHandle } from "./DocHandle.js";
5
+ import { generateAutomergeUrl, isValidAutomergeUrl, parseAutomergeUrl, parseLegacyUUID, } from "./DocUrl.js";
6
+ import { throttle } from "./helpers/throttle.js";
2
7
  import { NetworkSubsystem } from "./network/NetworkSubsystem.js";
3
8
  import { StorageSubsystem } from "./storage/StorageSubsystem.js";
4
9
  import { CollectionSynchronizer } from "./synchronizer/CollectionSynchronizer.js";
5
- import { parseAutomergeUrl, generateAutomergeUrl, isValidAutomergeUrl, parseLegacyUUID, } from "./DocUrl.js";
6
- import { DocHandle } from "./DocHandle.js";
7
- import { EventEmitter } from "eventemitter3";
8
- import { next as Automerge } from "@automerge/automerge";
9
10
  /** A Repo is a collection of documents with networking, syncing, and storage capabilities. */
10
11
  /** The `Repo` is the main entry point of this library
11
12
  *
@@ -20,6 +21,9 @@ export class Repo extends EventEmitter {
20
21
  networkSubsystem;
21
22
  /** @hidden */
22
23
  storageSubsystem;
24
+ /** The debounce rate is adjustable on the repo. */
25
+ /** @hidden */
26
+ saveDebounceRate = 100;
23
27
  #handleCache = {};
24
28
  /** By default, we share generously with all peers. */
25
29
  /** @hidden */
@@ -33,10 +37,11 @@ export class Repo extends EventEmitter {
33
37
  // up a document by ID. We listen for it in order to wire up storage and network synchronization.
34
38
  this.on("document", async ({ handle, isNew }) => {
35
39
  if (storageSubsystem) {
36
- // Save when the document changes
37
- handle.on("heads-changed", async ({ handle, doc }) => {
38
- await storageSubsystem.saveDoc(handle.documentId, doc);
39
- });
40
+ // Save when the document changes, but no more often than saveDebounceRate.
41
+ const saveFn = ({ handle, doc, }) => {
42
+ void storageSubsystem.saveDoc(handle.documentId, doc);
43
+ };
44
+ const debouncedSaveFn = handle.on("heads-changed", throttle(saveFn, this.saveDebounceRate));
40
45
  if (isNew) {
41
46
  // this is a new document, immediately save it
42
47
  await storageSubsystem.saveDoc(handle.documentId, handle.docSync());
@@ -0,0 +1,14 @@
1
+ /** throttle( callback, rate )
2
+ * Returns a throttle function with a build in debounce timer that runs after `wait` ms.
3
+ *
4
+ * Note that the args go inside the parameter and you should be careful not to
5
+ * recreate the function on each usage. (In React, see useMemo().)
6
+ *
7
+ *
8
+ * Example usage:
9
+ * const callback = throttle((ev) => { doSomethingExpensiveOrOccasional() }, 100)
10
+ * target.addEventListener('frequent-event', callback);
11
+ *
12
+ */
13
+ export declare const throttle: <F extends (...args: Parameters<F>) => ReturnType<F>>(fn: F, rate: number) => (...args: Parameters<F>) => void;
14
+ //# sourceMappingURL=debounce.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debounce.d.ts","sourceRoot":"","sources":["../../src/helpers/debounce.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,eAAO,MAAM,QAAQ,qEAEb,MAAM,qCASb,CAAA"}
@@ -0,0 +1,21 @@
1
+ /** throttle( callback, rate )
2
+ * Returns a throttle function with a build in debounce timer that runs after `wait` ms.
3
+ *
4
+ * Note that the args go inside the parameter and you should be careful not to
5
+ * recreate the function on each usage. (In React, see useMemo().)
6
+ *
7
+ *
8
+ * Example usage:
9
+ * const callback = throttle((ev) => { doSomethingExpensiveOrOccasional() }, 100)
10
+ * target.addEventListener('frequent-event', callback);
11
+ *
12
+ */
13
+ export const throttle = (fn, rate) => {
14
+ let timeout;
15
+ return function (...args) {
16
+ clearTimeout(timeout);
17
+ timeout = setTimeout(() => {
18
+ fn.apply(null, args);
19
+ }, rate);
20
+ };
21
+ };
@@ -0,0 +1,28 @@
1
+ /** Throttle
2
+ * Returns a function with a built in throttle timer that runs after `delay` ms.
3
+ *
4
+ * This function differs from a conventional `throttle` in that it ensures the final
5
+ * call will also execute and delays sending the first one until `delay` ms to allow
6
+ * additional work to accumulate.
7
+ *
8
+ * Here's a diagram:
9
+ *
10
+ * calls +----++++++-----++----
11
+ * dlay ^--v ^--v^--v ^--v
12
+ * execs ---+----+---+------+--
13
+ *
14
+ * The goal in this design is to create batches of changes without flooding
15
+ * communication or storage systems while still feeling responsive.
16
+ * (By default we communicate at 10hz / every 100ms.)
17
+ *
18
+ * Note that the args go inside the parameter and you should be careful not to
19
+ * recreate the function on each usage. (In React, see useMemo().)
20
+ *
21
+ *
22
+ * Example usage:
23
+ * const callback = debounce((ev) => { doSomethingExpensiveOrOccasional() }, 100)
24
+ * target.addEventListener('frequent-event', callback);
25
+ *
26
+ */
27
+ export declare const throttle: <F extends (...args: Parameters<F>) => ReturnType<F>>(fn: F, delay: number) => (...args: Parameters<F>) => void;
28
+ //# sourceMappingURL=throttle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"throttle.d.ts","sourceRoot":"","sources":["../../src/helpers/throttle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,eAAO,MAAM,QAAQ,sEAEZ,MAAM,qCAad,CAAA"}
@@ -0,0 +1,39 @@
1
+ /** Throttle
2
+ * Returns a function with a built in throttle timer that runs after `delay` ms.
3
+ *
4
+ * This function differs from a conventional `throttle` in that it ensures the final
5
+ * call will also execute and delays sending the first one until `delay` ms to allow
6
+ * additional work to accumulate.
7
+ *
8
+ * Here's a diagram:
9
+ *
10
+ * calls +----++++++-----++----
11
+ * dlay ^--v ^--v^--v ^--v
12
+ * execs ---+----+---+------+--
13
+ *
14
+ * The goal in this design is to create batches of changes without flooding
15
+ * communication or storage systems while still feeling responsive.
16
+ * (By default we communicate at 10hz / every 100ms.)
17
+ *
18
+ * Note that the args go inside the parameter and you should be careful not to
19
+ * recreate the function on each usage. (In React, see useMemo().)
20
+ *
21
+ *
22
+ * Example usage:
23
+ * const callback = debounce((ev) => { doSomethingExpensiveOrOccasional() }, 100)
24
+ * target.addEventListener('frequent-event', callback);
25
+ *
26
+ */
27
+ export const throttle = (fn, delay) => {
28
+ let lastCall = Date.now();
29
+ let wait;
30
+ let timeout;
31
+ return function (...args) {
32
+ wait = lastCall + delay - Date.now();
33
+ clearTimeout(timeout);
34
+ timeout = setTimeout(() => {
35
+ fn.apply(null, args);
36
+ lastCall = Date.now();
37
+ }, wait);
38
+ };
39
+ };
package/dist/index.d.ts CHANGED
@@ -25,12 +25,12 @@
25
25
  * const handle = repo.create
26
26
  * ```
27
27
  */
28
- export { Repo } from "./Repo.js";
29
28
  export { DocHandle } from "./DocHandle.js";
30
- export { NetworkAdapter } from "./network/NetworkAdapter.js";
31
- export { StorageAdapter } from "./storage/StorageAdapter.js";
32
29
  export { isValidAutomergeUrl, parseAutomergeUrl, stringifyAutomergeUrl, } from "./DocUrl.js";
30
+ export { Repo } from "./Repo.js";
31
+ export { NetworkAdapter } from "./network/NetworkAdapter.js";
33
32
  export { isValidRepoMessage } from "./network/messages.js";
33
+ export { StorageAdapter } from "./storage/StorageAdapter.js";
34
34
  /** @hidden **/
35
35
  export * as cbor from "./helpers/cbor.js";
36
36
  export type { DocHandleChangePayload, DocHandleDeletePayload, DocHandleEncodedChangePayload, DocHandleEphemeralMessagePayload, DocHandleEvents, DocHandleOptions, DocHandleOutboundEphemeralMessagePayload, HandleState, } from "./DocHandle.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAC5D,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAA;AAE1D,eAAe;AACf,OAAO,KAAK,IAAI,MAAM,mBAAmB,CAAA;AAIzC,YAAY,EACV,sBAAsB,EACtB,sBAAsB,EACtB,6BAA6B,EAC7B,gCAAgC,EAChC,eAAe,EACf,gBAAgB,EAChB,wCAAwC,EACxC,WAAW,GACZ,MAAM,gBAAgB,CAAA;AACvB,YAAY,EACV,qBAAqB,EACrB,eAAe,EACf,UAAU,EACV,UAAU,EACV,WAAW,GACZ,MAAM,WAAW,CAAA;AAClB,YAAY,EACV,oBAAoB,EACpB,WAAW,EACX,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,6BAA6B,CAAA;AACpC,YAAY,EACV,aAAa,EACb,0BAA0B,EAC1B,gBAAgB,EAChB,OAAO,EACP,WAAW,EACX,cAAc,EACd,WAAW,EACX,cAAc,GACf,MAAM,uBAAuB,CAAA;AAC9B,YAAY,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAA;AAC7D,cAAc,YAAY,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAA;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAE5D,eAAe;AACf,OAAO,KAAK,IAAI,MAAM,mBAAmB,CAAA;AAIzC,YAAY,EACV,sBAAsB,EACtB,sBAAsB,EACtB,6BAA6B,EAC7B,gCAAgC,EAChC,eAAe,EACf,gBAAgB,EAChB,wCAAwC,EACxC,WAAW,GACZ,MAAM,gBAAgB,CAAA;AACvB,YAAY,EACV,qBAAqB,EACrB,eAAe,EACf,UAAU,EACV,UAAU,EACV,WAAW,GACZ,MAAM,WAAW,CAAA;AAClB,YAAY,EACV,oBAAoB,EACpB,WAAW,EACX,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,6BAA6B,CAAA;AACpC,YAAY,EACV,aAAa,EACb,0BAA0B,EAC1B,gBAAgB,EAChB,OAAO,EACP,WAAW,EACX,cAAc,EACd,WAAW,EACX,cAAc,GACf,MAAM,uBAAuB,CAAA;AAC9B,YAAY,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAA;AAC7D,cAAc,YAAY,CAAA"}
package/dist/index.js CHANGED
@@ -25,12 +25,12 @@
25
25
  * const handle = repo.create
26
26
  * ```
27
27
  */
28
- export { Repo } from "./Repo.js";
29
28
  export { DocHandle } from "./DocHandle.js";
30
- export { NetworkAdapter } from "./network/NetworkAdapter.js";
31
- export { StorageAdapter } from "./storage/StorageAdapter.js";
32
29
  export { isValidAutomergeUrl, parseAutomergeUrl, stringifyAutomergeUrl, } from "./DocUrl.js";
30
+ export { Repo } from "./Repo.js";
31
+ export { NetworkAdapter } from "./network/NetworkAdapter.js";
33
32
  export { isValidRepoMessage } from "./network/messages.js";
33
+ export { StorageAdapter } from "./storage/StorageAdapter.js";
34
34
  /** @hidden **/
35
35
  export * as cbor from "./helpers/cbor.js";
36
36
  export * from "./types.js";
@@ -1,7 +1,7 @@
1
1
  import { EventEmitter } from "eventemitter3";
2
2
  import { PeerId } from "../types.js";
3
3
  import { NetworkAdapter, PeerDisconnectedPayload } from "./NetworkAdapter.js";
4
- import { RepoMessage, MessageContents } from "./messages.js";
4
+ import { MessageContents, RepoMessage } from "./messages.js";
5
5
  export declare class NetworkSubsystem extends EventEmitter<NetworkSubsystemEvents> {
6
6
  #private;
7
7
  peerId: PeerId;
@@ -1 +1 @@
1
- {"version":3,"file":"NetworkSubsystem.d.ts","sourceRoot":"","sources":["../../src/network/NetworkSubsystem.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAC5C,OAAO,EAAE,MAAM,EAAa,MAAM,aAAa,CAAA;AAC/C,OAAO,EAAE,cAAc,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAA;AAC7E,OAAO,EAEL,WAAW,EACX,eAAe,EAGhB,MAAM,eAAe,CAAA;AAOtB,qBAAa,gBAAiB,SAAQ,YAAY,CAAC,sBAAsB,CAAC;;IAUzB,MAAM;gBAAzC,QAAQ,EAAE,cAAc,EAAE,EAAS,MAAM,SAAiB;IAMtE,iBAAiB,CAAC,cAAc,EAAE,cAAc;IAsEhD,IAAI,CAAC,OAAO,EAAE,eAAe;IAsC7B,OAAO,gBAEN;IAED,SAAS,sBAUR;CACF;AAQD,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,CAAA;IACpC,mBAAmB,EAAE,CAAC,OAAO,EAAE,uBAAuB,KAAK,IAAI,CAAA;IAC/D,OAAO,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,CAAA;IACvC,KAAK,EAAE,MAAM,IAAI,CAAA;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAA;CACf"}
1
+ {"version":3,"file":"NetworkSubsystem.d.ts","sourceRoot":"","sources":["../../src/network/NetworkSubsystem.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAC5C,OAAO,EAAE,MAAM,EAAa,MAAM,aAAa,CAAA;AAC/C,OAAO,EAAE,cAAc,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAA;AAC7E,OAAO,EAEL,eAAe,EACf,WAAW,EAGZ,MAAM,eAAe,CAAA;AAOtB,qBAAa,gBAAiB,SAAQ,YAAY,CAAC,sBAAsB,CAAC;;IAUzB,MAAM;gBAAzC,QAAQ,EAAE,cAAc,EAAE,EAAS,MAAM,SAAiB;IAMtE,iBAAiB,CAAC,cAAc,EAAE,cAAc;IAsEhD,IAAI,CAAC,OAAO,EAAE,eAAe;IAsC7B,OAAO,gBAEN;IAED,SAAS,sBAUR;CACF;AAQD,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,CAAA;IACpC,mBAAmB,EAAE,CAAC,OAAO,EAAE,uBAAuB,KAAK,IAAI,CAAA;IAC/D,OAAO,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,CAAA;IACvC,KAAK,EAAE,MAAM,IAAI,CAAA;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAA;CACf"}
@@ -1,6 +1,6 @@
1
1
  import * as A from "@automerge/automerge/next";
2
- import { StorageAdapter } from "./StorageAdapter.js";
3
2
  import { type DocumentId } from "../types.js";
3
+ import { StorageAdapter } from "./StorageAdapter.js";
4
4
  export type ChunkType = "snapshot" | "incremental";
5
5
  export declare class StorageSubsystem {
6
6
  #private;
@@ -1 +1 @@
1
- {"version":3,"file":"StorageSubsystem.d.ts","sourceRoot":"","sources":["../../src/storage/StorageSubsystem.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,2BAA2B,CAAA;AAC9C,OAAO,EAAE,cAAc,EAAc,MAAM,qBAAqB,CAAA;AAEhE,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAA;AAa7C,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG,aAAa,CAAA;AAelD,qBAAa,gBAAgB;;gBAQf,cAAc,EAAE,cAAc;IAuDpC,OAAO,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;IA0B/D,OAAO,CAAC,UAAU,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAanE,MAAM,CAAC,UAAU,EAAE,UAAU;CAmCpC"}
1
+ {"version":3,"file":"StorageSubsystem.d.ts","sourceRoot":"","sources":["../../src/storage/StorageSubsystem.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,2BAA2B,CAAA;AAK9C,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAA;AAC7C,OAAO,EAAE,cAAc,EAAc,MAAM,qBAAqB,CAAA;AAUhE,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG,aAAa,CAAA;AAelD,qBAAa,gBAAgB;;gBAQf,cAAc,EAAE,cAAc;IAuDpC,OAAO,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;IA0B/D,OAAO,CAAC,UAAU,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAanE,MAAM,CAAC,UAAU,EAAE,UAAU;CAmCpC"}
@@ -1,8 +1,8 @@
1
1
  import * as A from "@automerge/automerge/next";
2
- import * as sha256 from "fast-sha256";
3
- import { mergeArrays } from "../helpers/mergeArrays.js";
4
2
  import debug from "debug";
3
+ import * as sha256 from "fast-sha256";
5
4
  import { headsAreSame } from "../helpers/headsAreSame.js";
5
+ import { mergeArrays } from "../helpers/mergeArrays.js";
6
6
  function keyHash(binary) {
7
7
  const hash = sha256.hash(binary);
8
8
  const hashArray = Array.from(new Uint8Array(hash)); // convert buffer to byte array
@@ -1,7 +1,7 @@
1
1
  import { Repo } from "../Repo.js";
2
+ import { RepoMessage } from "../network/messages.js";
2
3
  import { DocumentId, PeerId } from "../types.js";
3
4
  import { Synchronizer } from "./Synchronizer.js";
4
- import { RepoMessage } from "../network/messages.js";
5
5
  /** A CollectionSynchronizer is responsible for synchronizing a DocCollection with peers. */
6
6
  export declare class CollectionSynchronizer extends Synchronizer {
7
7
  #private;
@@ -1 +1 @@
1
- {"version":3,"file":"CollectionSynchronizer.d.ts","sourceRoot":"","sources":["../../src/synchronizer/CollectionSynchronizer.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEhD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAGhD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAGpD,4FAA4F;AAC5F,qBAAa,sBAAuB,SAAQ,YAAY;;IAU1C,OAAO,CAAC,IAAI;gBAAJ,IAAI,EAAE,IAAI;IAiC9B;;;OAGG;IACG,cAAc,CAAC,OAAO,EAAE,WAAW;IAyBzC;;OAEG;IACH,WAAW,CAAC,UAAU,EAAE,UAAU;IAYlC,cAAc,CAAC,UAAU,EAAE,UAAU;IAIrC,2DAA2D;IAC3D,OAAO,CAAC,MAAM,EAAE,MAAM;IAgBtB,uDAAuD;IACvD,UAAU,CAAC,MAAM,EAAE,MAAM;CAQ1B"}
1
+ {"version":3,"file":"CollectionSynchronizer.d.ts","sourceRoot":"","sources":["../../src/synchronizer/CollectionSynchronizer.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AACjC,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEhD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAIhD,4FAA4F;AAC5F,qBAAa,sBAAuB,SAAQ,YAAY;;IAU1C,OAAO,CAAC,IAAI;gBAAJ,IAAI,EAAE,IAAI;IAiC9B;;;OAGG;IACG,cAAc,CAAC,OAAO,EAAE,WAAW;IAyBzC;;OAEG;IACH,WAAW,CAAC,UAAU,EAAE,UAAU;IAYlC,cAAc,CAAC,UAAU,EAAE,UAAU;IAIrC,2DAA2D;IAC3D,OAAO,CAAC,MAAM,EAAE,MAAM;IAgBtB,uDAAuD;IACvD,UAAU,CAAC,MAAM,EAAE,MAAM;CAQ1B"}
@@ -1,7 +1,7 @@
1
+ import debug from "debug";
1
2
  import { stringifyAutomergeUrl } from "../DocUrl.js";
2
3
  import { DocSynchronizer } from "./DocSynchronizer.js";
3
4
  import { Synchronizer } from "./Synchronizer.js";
4
- import debug from "debug";
5
5
  const log = debug("automerge-repo:collectionsync");
6
6
  /** A CollectionSynchronizer is responsible for synchronizing a DocCollection with peers. */
7
7
  export class CollectionSynchronizer extends Synchronizer {
@@ -10,6 +10,7 @@ type PeerDocumentStatus = "unknown" | "has" | "unavailable" | "wants";
10
10
  export declare class DocSynchronizer extends Synchronizer {
11
11
  #private;
12
12
  private handle;
13
+ syncDebounceRate: number;
13
14
  constructor(handle: DocHandle<unknown>);
14
15
  get peerStates(): Record<PeerId, PeerDocumentStatus>;
15
16
  get documentId(): import("../types.js").DocumentId;
@@ -1 +1 @@
1
- {"version":3,"file":"DocSynchronizer.d.ts","sourceRoot":"","sources":["../../src/synchronizer/DocSynchronizer.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,SAAS,EAKV,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAEL,gBAAgB,EAChB,WAAW,EAEX,cAAc,EACd,WAAW,EAEZ,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAEhD,KAAK,kBAAkB,GAAG,SAAS,GAAG,KAAK,GAAG,aAAa,GAAG,OAAO,CAAA;AAErE;;;GAGG;AACH,qBAAa,eAAgB,SAAQ,YAAY;;IAiBnC,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,SAAS,CAAC,OAAO,CAAC;IAoB9C,IAAI,UAAU,uCAEb;IAED,IAAI,UAAU,qCAEb;IA8FD,OAAO,CAAC,MAAM,EAAE,MAAM;IAItB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE;IAmC3B,OAAO,CAAC,MAAM,EAAE,MAAM;IAKtB,cAAc,CAAC,OAAO,EAAE,WAAW;IAkBnC,uBAAuB,CAAC,OAAO,EAAE,gBAAgB;IAuBjD,kBAAkB,CAAC,OAAO,EAAE,WAAW,GAAG,cAAc;CA4EzD"}
1
+ {"version":3,"file":"DocSynchronizer.d.ts","sourceRoot":"","sources":["../../src/synchronizer/DocSynchronizer.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,SAAS,EAKV,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAEL,gBAAgB,EAEhB,WAAW,EACX,cAAc,EACd,WAAW,EAEZ,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAGhD,KAAK,kBAAkB,GAAG,SAAS,GAAG,KAAK,GAAG,aAAa,GAAG,OAAO,CAAA;AAErE;;;GAGG;AACH,qBAAa,eAAgB,SAAQ,YAAY;;IAgBnC,OAAO,CAAC,MAAM;IAd1B,gBAAgB,SAAM;gBAcF,MAAM,EAAE,SAAS,CAAC,OAAO,CAAC;IAqB9C,IAAI,UAAU,uCAEb;IAED,IAAI,UAAU,qCAEb;IA8FD,OAAO,CAAC,MAAM,EAAE,MAAM;IAItB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE;IAqC3B,OAAO,CAAC,MAAM,EAAE,MAAM;IAKtB,cAAc,CAAC,OAAO,EAAE,WAAW;IAkBnC,uBAAuB,CAAC,OAAO,EAAE,gBAAgB;IAuBjD,kBAAkB,CAAC,OAAO,EAAE,WAAW,GAAG,cAAc;CA4EzD"}
@@ -4,6 +4,7 @@ import debug from "debug";
4
4
  import { READY, REQUESTING, UNAVAILABLE, } from "../DocHandle.js";
5
5
  import { isRequestMessage, } from "../network/messages.js";
6
6
  import { Synchronizer } from "./Synchronizer.js";
7
+ import { throttle } from "../helpers/throttle.js";
7
8
  /**
8
9
  * DocSynchronizer takes a handle to an Automerge document, and receives & dispatches sync messages
9
10
  * to bring it inline with all other peers' versions.
@@ -11,8 +12,7 @@ import { Synchronizer } from "./Synchronizer.js";
11
12
  export class DocSynchronizer extends Synchronizer {
12
13
  handle;
13
14
  #log;
14
- #conciseLog;
15
- #opsLog;
15
+ syncDebounceRate = 100;
16
16
  /** Active peers */
17
17
  #peers = [];
18
18
  #peerDocumentStatuses = {};
@@ -24,10 +24,8 @@ export class DocSynchronizer extends Synchronizer {
24
24
  super();
25
25
  this.handle = handle;
26
26
  const docId = handle.documentId.slice(0, 5);
27
- this.#conciseLog = debug(`automerge-repo:concise:docsync:${docId}`); // Only logs one line per receive/send
28
27
  this.#log = debug(`automerge-repo:docsync:${docId}`);
29
- this.#opsLog = debug(`automerge-repo:ops:docsync:${docId}`); // Log list of ops of each message
30
- handle.on("change", () => this.#syncWithPeers());
28
+ handle.on("change", throttle(() => this.#syncWithPeers(), this.syncDebounceRate));
31
29
  handle.on("ephemeral-message-outbound", payload => this.#broadcastToPeers(payload));
32
30
  // Process pending sync messages immediately after the handle becomes ready.
33
31
  void (async () => {
@@ -1,5 +1,5 @@
1
1
  import { EventEmitter } from "eventemitter3";
2
- import { RepoMessage, MessageContents } from "../network/messages.js";
2
+ import { MessageContents, RepoMessage } from "../network/messages.js";
3
3
  export declare abstract class Synchronizer extends EventEmitter<SynchronizerEvents> {
4
4
  abstract receiveMessage(message: RepoMessage): void;
5
5
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Synchronizer.d.ts","sourceRoot":"","sources":["../../src/synchronizer/Synchronizer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAC5C,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAErE,8BAAsB,YAAa,SAAQ,YAAY,CAAC,kBAAkB,CAAC;IACzE,QAAQ,CAAC,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;CACpD;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,IAAI,CAAA;CACxC"}
1
+ {"version":3,"file":"Synchronizer.d.ts","sourceRoot":"","sources":["../../src/synchronizer/Synchronizer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAC5C,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAErE,8BAAsB,YAAa,SAAQ,YAAY,CAAC,kBAAkB,CAAC;IACzE,QAAQ,CAAC,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;CACpD;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,IAAI,CAAA;CACxC"}
package/fuzz/fuzz.ts CHANGED
@@ -1,13 +1,15 @@
1
- import assert from "assert"
2
1
  import { MessageChannelNetworkAdapter } from "@automerge/automerge-repo-network-messagechannel"
3
2
  import * as Automerge from "@automerge/automerge/next"
4
-
5
- import { DocHandle, DocumentId, PeerId, SharePolicy } from "../src"
3
+ import assert from "assert"
6
4
  import { eventPromise } from "../src/helpers/eventPromise.js"
7
5
  import { pause } from "../src/helpers/pause.js"
8
- import { Repo } from "../src/Repo.js"
9
- import { DummyNetworkAdapter } from "../test/helpers/DummyNetworkAdapter.js"
10
- import { DummyStorageAdapter } from "../test/helpers/DummyStorageAdapter.js"
6
+ import {
7
+ DocHandle,
8
+ DocumentId,
9
+ PeerId,
10
+ Repo,
11
+ SharePolicy,
12
+ } from "../src/index.js"
11
13
  import { getRandomItem } from "../test/helpers/getRandomItem.js"
12
14
 
13
15
  interface TestDoc {
@@ -0,0 +1,8 @@
1
+ {
2
+ "compilerOptions": {
3
+ "module": "NodeNext",
4
+ "moduleResolution": "Node16",
5
+ "noEmit": true
6
+ },
7
+ "include": ["**/*.ts"]
8
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@automerge/automerge-repo",
3
- "version": "1.0.7",
3
+ "version": "1.0.8",
4
4
  "description": "A repository object to manage a collection of automerge documents",
5
5
  "repository": "https://github.com/automerge/automerge-repo/tree/master/packages/automerge-repo",
6
6
  "author": "Peter van Hardenberg <pvh@pvh.ca>",
@@ -57,5 +57,5 @@
57
57
  "publishConfig": {
58
58
  "access": "public"
59
59
  },
60
- "gitHead": "71060981f168e511a99ab85b155a54a13fd04bcc"
60
+ "gitHead": "d244a36aebab52a86f91b5427bbe8ab2800bf2f4"
61
61
  }
package/src/DocHandle.ts CHANGED
@@ -14,12 +14,11 @@ import {
14
14
  TypegenDisabled,
15
15
  } from "xstate"
16
16
  import { waitFor } from "xstate/lib/waitFor.js"
17
- import { headsAreSame } from "./helpers/headsAreSame.js"
18
- import { pause } from "./helpers/pause.js"
19
- import { TimeoutError, withTimeout } from "./helpers/withTimeout.js"
20
- import type { DocumentId, PeerId, AutomergeUrl } from "./types.js"
21
17
  import { stringifyAutomergeUrl } from "./DocUrl.js"
22
18
  import { encode } from "./helpers/cbor.js"
19
+ import { headsAreSame } from "./helpers/headsAreSame.js"
20
+ import { withTimeout } from "./helpers/withTimeout.js"
21
+ import type { AutomergeUrl, DocumentId, PeerId } from "./types.js"
23
22
 
24
23
  /** DocHandle is a wrapper around a single Automerge document that lets us
25
24
  * listen for changes and notify the network and storage of new changes.
package/src/DocUrl.ts CHANGED
@@ -29,7 +29,9 @@ export const parseAutomergeUrl = (url: AutomergeUrl) => {
29
29
  */
30
30
  export const stringifyAutomergeUrl = ({
31
31
  documentId,
32
- }: {documentId: DocumentId | BinaryDocumentId}): AutomergeUrl => {
32
+ }: {
33
+ documentId: DocumentId | BinaryDocumentId
34
+ }): AutomergeUrl => {
33
35
  if (documentId instanceof Uint8Array)
34
36
  return (urlPrefix +
35
37
  binaryToDocumentId(documentId as BinaryDocumentId)) as AutomergeUrl
package/src/Repo.ts CHANGED
@@ -1,21 +1,20 @@
1
+ import { next as Automerge } from "@automerge/automerge"
1
2
  import debug from "debug"
2
- import { NetworkAdapter } from "./network/NetworkAdapter.js"
3
- import { NetworkSubsystem } from "./network/NetworkSubsystem.js"
4
- import { StorageAdapter } from "./storage/StorageAdapter.js"
5
- import { StorageSubsystem } from "./storage/StorageSubsystem.js"
6
- import { CollectionSynchronizer } from "./synchronizer/CollectionSynchronizer.js"
7
- import { type AutomergeUrl, DocumentId, PeerId } from "./types.js"
8
-
3
+ import { EventEmitter } from "eventemitter3"
4
+ import { DocHandle, DocHandleEncodedChangePayload } from "./DocHandle.js"
9
5
  import {
10
- parseAutomergeUrl,
11
6
  generateAutomergeUrl,
12
7
  isValidAutomergeUrl,
8
+ parseAutomergeUrl,
13
9
  parseLegacyUUID,
14
10
  } from "./DocUrl.js"
15
-
16
- import { DocHandle } from "./DocHandle.js"
17
- import { EventEmitter } from "eventemitter3"
18
- import { next as Automerge } from "@automerge/automerge"
11
+ import { throttle } from "./helpers/throttle.js"
12
+ import { NetworkAdapter } from "./network/NetworkAdapter.js"
13
+ import { NetworkSubsystem } from "./network/NetworkSubsystem.js"
14
+ import { StorageAdapter } from "./storage/StorageAdapter.js"
15
+ import { StorageSubsystem } from "./storage/StorageSubsystem.js"
16
+ import { CollectionSynchronizer } from "./synchronizer/CollectionSynchronizer.js"
17
+ import { DocumentId, PeerId, type AutomergeUrl } from "./types.js"
19
18
 
20
19
  /** A Repo is a collection of documents with networking, syncing, and storage capabilities. */
21
20
  /** The `Repo` is the main entry point of this library
@@ -32,6 +31,11 @@ export class Repo extends EventEmitter<RepoEvents> {
32
31
  networkSubsystem: NetworkSubsystem
33
32
  /** @hidden */
34
33
  storageSubsystem?: StorageSubsystem
34
+
35
+ /** The debounce rate is adjustable on the repo. */
36
+ /** @hidden */
37
+ saveDebounceRate = 100
38
+
35
39
  #handleCache: Record<DocumentId, DocHandle<any>> = {}
36
40
 
37
41
  /** By default, we share generously with all peers. */
@@ -49,10 +53,17 @@ export class Repo extends EventEmitter<RepoEvents> {
49
53
  // up a document by ID. We listen for it in order to wire up storage and network synchronization.
50
54
  this.on("document", async ({ handle, isNew }) => {
51
55
  if (storageSubsystem) {
52
- // Save when the document changes
53
- handle.on("heads-changed", async ({ handle, doc }) => {
54
- await storageSubsystem.saveDoc(handle.documentId, doc)
55
- })
56
+ // Save when the document changes, but no more often than saveDebounceRate.
57
+ const saveFn = ({
58
+ handle,
59
+ doc,
60
+ }: DocHandleEncodedChangePayload<any>) => {
61
+ void storageSubsystem.saveDoc(handle.documentId, doc)
62
+ }
63
+ const debouncedSaveFn = handle.on(
64
+ "heads-changed",
65
+ throttle(saveFn, this.saveDebounceRate)
66
+ )
56
67
 
57
68
  if (isNew) {
58
69
  // this is a new document, immediately save it
@@ -0,0 +1,25 @@
1
+ /** throttle( callback, rate )
2
+ * Returns a throttle function with a build in debounce timer that runs after `wait` ms.
3
+ *
4
+ * Note that the args go inside the parameter and you should be careful not to
5
+ * recreate the function on each usage. (In React, see useMemo().)
6
+ *
7
+ *
8
+ * Example usage:
9
+ * const callback = throttle((ev) => { doSomethingExpensiveOrOccasional() }, 100)
10
+ * target.addEventListener('frequent-event', callback);
11
+ *
12
+ */
13
+
14
+ export const throttle = <F extends (...args: Parameters<F>) => ReturnType<F>>(
15
+ fn: F,
16
+ rate: number
17
+ ) => {
18
+ let timeout: ReturnType<typeof setTimeout>
19
+ return function (...args: Parameters<F>) {
20
+ clearTimeout(timeout)
21
+ timeout = setTimeout(() => {
22
+ fn.apply(null, args)
23
+ }, rate)
24
+ }
25
+ }
@@ -1,4 +1,4 @@
1
- import {Heads} from "@automerge/automerge/next"
1
+ import { Heads } from "@automerge/automerge/next"
2
2
  import { arraysAreEqual } from "./arraysAreEqual.js"
3
3
 
4
4
  export const headsAreSame = (a: Heads, b: Heads) => {