@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.
- package/dist/DocHandle.d.ts +1 -1
- package/dist/DocHandle.d.ts.map +1 -1
- package/dist/DocHandle.js +2 -2
- package/dist/DocUrl.d.ts.map +1 -1
- package/dist/Repo.d.ts +6 -3
- package/dist/Repo.d.ts.map +1 -1
- package/dist/Repo.js +13 -8
- package/dist/helpers/debounce.d.ts +14 -0
- package/dist/helpers/debounce.d.ts.map +1 -0
- package/dist/helpers/debounce.js +21 -0
- package/dist/helpers/throttle.d.ts +28 -0
- package/dist/helpers/throttle.d.ts.map +1 -0
- package/dist/helpers/throttle.js +39 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/network/NetworkSubsystem.d.ts +1 -1
- package/dist/network/NetworkSubsystem.d.ts.map +1 -1
- package/dist/storage/StorageSubsystem.d.ts +1 -1
- package/dist/storage/StorageSubsystem.d.ts.map +1 -1
- package/dist/storage/StorageSubsystem.js +2 -2
- package/dist/synchronizer/CollectionSynchronizer.d.ts +1 -1
- package/dist/synchronizer/CollectionSynchronizer.d.ts.map +1 -1
- package/dist/synchronizer/CollectionSynchronizer.js +1 -1
- package/dist/synchronizer/DocSynchronizer.d.ts +1 -0
- package/dist/synchronizer/DocSynchronizer.d.ts.map +1 -1
- package/dist/synchronizer/DocSynchronizer.js +3 -5
- package/dist/synchronizer/Synchronizer.d.ts +1 -1
- package/dist/synchronizer/Synchronizer.d.ts.map +1 -1
- package/fuzz/fuzz.ts +8 -6
- package/fuzz/tsconfig.json +8 -0
- package/package.json +2 -2
- package/src/DocHandle.ts +3 -4
- package/src/DocUrl.ts +3 -1
- package/src/Repo.ts +27 -16
- package/src/helpers/debounce.ts +25 -0
- package/src/helpers/headsAreSame.ts +1 -1
- package/src/helpers/throttle.ts +43 -0
- package/src/index.ts +3 -3
- package/src/network/NetworkSubsystem.ts +1 -1
- package/src/storage/StorageSubsystem.ts +4 -4
- package/src/synchronizer/CollectionSynchronizer.ts +2 -2
- package/src/synchronizer/DocSynchronizer.ts +10 -7
- package/src/synchronizer/Synchronizer.ts +1 -1
- package/test/CollectionSynchronizer.test.ts +1 -1
- package/test/DocHandle.test.ts +1 -1
- package/test/DocSynchronizer.test.ts +0 -4
- package/test/Repo.test.ts +115 -124
- package/test/helpers/DummyNetworkAdapter.ts +9 -4
- package/test/helpers/DummyStorageAdapter.ts +4 -2
- package/dist/EphemeralData.d.ts +0 -20
- package/dist/EphemeralData.d.ts.map +0 -1
- package/dist/EphemeralData.js +0 -1
- package/src/EphemeralData.ts +0 -17
package/dist/DocHandle.d.ts
CHANGED
|
@@ -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
|
|
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
|
*
|
package/dist/DocHandle.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DocHandle.d.ts","sourceRoot":"","sources":["../src/DocHandle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,2BAA2B,CAAA;AAE9C,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAC5C,OAAO,EASL,UAAU,EAEX,MAAM,QAAQ,CAAA;
|
|
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
|
*
|
package/dist/DocUrl.d.ts.map
CHANGED
|
@@ -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;
|
|
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 {
|
|
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;
|
package/dist/Repo.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Repo.d.ts","sourceRoot":"","sources":["../src/Repo.ts"],"names":[],"mappings":"
|
|
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
|
-
|
|
38
|
-
|
|
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";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAE,
|
|
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 {
|
|
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,
|
|
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;
|
|
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":"
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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 {
|
|
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,
|
|
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 {
|
|
9
|
-
|
|
10
|
-
|
|
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 {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@automerge/automerge-repo",
|
|
3
|
-
"version": "1.0.
|
|
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": "
|
|
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
|
-
}: {
|
|
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 {
|
|
3
|
-
import {
|
|
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 {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
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
|
-
|
|
54
|
-
|
|
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
|
+
}
|