@automerge/automerge-repo 2.0.8 → 2.1.0

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/Repo.d.ts CHANGED
@@ -34,9 +34,6 @@ export declare class Repo extends EventEmitter<RepoEvents> {
34
34
  networkSubsystem: NetworkSubsystem;
35
35
  /** @hidden */
36
36
  storageSubsystem?: StorageSubsystem;
37
- /** The debounce rate is adjustable on the repo. */
38
- /** @hidden */
39
- saveDebounceRate: number;
40
37
  /** @hidden */
41
38
  synchronizer: CollectionSynchronizer;
42
39
  /** By default, we share generously with all peers. */
@@ -45,7 +42,7 @@ export declare class Repo extends EventEmitter<RepoEvents> {
45
42
  /** maps peer id to to persistence information (storageId, isEphemeral), access by collection synchronizer */
46
43
  /** @hidden */
47
44
  peerMetadataByPeerId: Record<PeerId, PeerMetadata>;
48
- constructor({ storage, network, peerId, sharePolicy, isEphemeral, enableRemoteHeadsGossiping, denylist, }?: RepoConfig);
45
+ constructor({ storage, network, peerId, sharePolicy, isEphemeral, enableRemoteHeadsGossiping, denylist, saveDebounceRate, }?: RepoConfig);
49
46
  /** Returns all the handles we have cached. */
50
47
  get handles(): Record<DocumentId, DocHandle<any>>;
51
48
  /** Returns a list of all connected peer ids */
@@ -144,6 +141,10 @@ export interface RepoConfig {
144
141
  * loading documents that are known to be too resource intensive.
145
142
  */
146
143
  denylist?: AutomergeUrl[];
144
+ /**
145
+ * The debounce rate in milliseconds for saving documents. Defaults to 100ms.
146
+ */
147
+ saveDebounceRate?: number;
147
148
  }
148
149
  /** A function that determines whether we should share a document with a peer
149
150
  *
@@ -1 +1 @@
1
- {"version":3,"file":"Repo.d.ts","sourceRoot":"","sources":["../src/Repo.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Repo.d.ts","sourceRoot":"","sources":["../src/Repo.ts"],"names":[],"mappings":"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"}
package/dist/Repo.js CHANGED
@@ -27,9 +27,10 @@ export class Repo extends EventEmitter {
27
27
  networkSubsystem;
28
28
  /** @hidden */
29
29
  storageSubsystem;
30
- /** The debounce rate is adjustable on the repo. */
31
30
  /** @hidden */
32
- saveDebounceRate = 100;
31
+ #saveDebounceRate;
32
+ /** @hidden */
33
+ #saveFn;
33
34
  #handleCache = {};
34
35
  /** @hidden */
35
36
  synchronizer;
@@ -42,7 +43,7 @@ export class Repo extends EventEmitter {
42
43
  #remoteHeadsSubscriptions = new RemoteHeadsSubscriptions();
43
44
  #remoteHeadsGossipingEnabled = false;
44
45
  #progressCache = {};
45
- constructor({ storage, network = [], peerId = randomPeerId(), sharePolicy, isEphemeral = storage === undefined, enableRemoteHeadsGossiping = false, denylist = [], } = {}) {
46
+ constructor({ storage, network = [], peerId = randomPeerId(), sharePolicy, isEphemeral = storage === undefined, enableRemoteHeadsGossiping = false, denylist = [], saveDebounceRate = 100, } = {}) {
46
47
  super();
47
48
  this.#remoteHeadsGossipingEnabled = enableRemoteHeadsGossiping;
48
49
  this.#log = debug(`automerge-repo:repo`);
@@ -77,6 +78,17 @@ export class Repo extends EventEmitter {
77
78
  storageSubsystem.on("document-loaded", event => this.emit("doc-metrics", { type: "doc-loaded", ...event }));
78
79
  }
79
80
  this.storageSubsystem = storageSubsystem;
81
+ this.#saveDebounceRate = saveDebounceRate;
82
+ if (this.storageSubsystem) {
83
+ const saveFn = ({ handle, doc }) => {
84
+ void this.storageSubsystem.saveDoc(handle.documentId, doc);
85
+ };
86
+ // Save no more often than saveDebounceRate.
87
+ this.#saveFn = throttle(saveFn, this.#saveDebounceRate);
88
+ }
89
+ else {
90
+ this.#saveFn = () => { };
91
+ }
80
92
  // NETWORK
81
93
  // The network subsystem deals with sending and receiving messages to and from peers.
82
94
  const myPeerMetadata = (async () => ({
@@ -169,13 +181,13 @@ export class Repo extends EventEmitter {
169
181
  // The `document` event is fired by the DocCollection any time we create a new document or look
170
182
  // up a document by ID. We listen for it in order to wire up storage and network synchronization.
171
183
  #registerHandleWithSubsystems(handle) {
172
- const { storageSubsystem } = this;
173
- if (storageSubsystem) {
174
- // Save when the document changes, but no more often than saveDebounceRate.
175
- const saveFn = ({ handle, doc }) => {
176
- void storageSubsystem.saveDoc(handle.documentId, doc);
177
- };
178
- handle.on("heads-changed", throttle(saveFn, this.saveDebounceRate));
184
+ if (this.storageSubsystem) {
185
+ // Add save function as a listener if it's not already registered
186
+ const existingListeners = handle.listeners("heads-changed");
187
+ if (!existingListeners.some(listener => listener === this.#saveFn)) {
188
+ // Save when the document changes
189
+ handle.on("heads-changed", this.#saveFn);
190
+ }
179
191
  }
180
192
  // Register the document with the synchronizer. This advertises our interest in the document.
181
193
  this.synchronizer.addDocument(handle);
@@ -215,7 +227,7 @@ export class Repo extends EventEmitter {
215
227
  if (!handler) {
216
228
  handler = this.#throttledSaveSyncStateHandlers[storageId] = throttle(({ documentId, syncState }) => {
217
229
  void this.storageSubsystem.saveSyncState(documentId, storageId, syncState);
218
- }, this.saveDebounceRate);
230
+ }, this.#saveDebounceRate);
219
231
  }
220
232
  handler(payload);
221
233
  }
package/dist/index.d.ts CHANGED
@@ -44,8 +44,8 @@ export type { DocumentUnavailableMessage, EphemeralMessage, Message, RepoMessage
44
44
  export type { Chunk, ChunkInfo, ChunkType, StorageKey, StorageId, } from "./storage/types.js";
45
45
  export * from "./types.js";
46
46
  export declare const Counter: typeof Automerge.Counter;
47
- export declare const RawString: typeof Automerge.RawString;
48
- export declare const ImmutableString: typeof Automerge.RawString;
47
+ export declare const RawString: typeof Automerge.ImmutableString;
48
+ export declare const ImmutableString: typeof Automerge.ImmutableString;
49
49
  export type RawString = InstanceType<typeof Automerge.RawString>;
50
50
  export type ImmutableString = RawString;
51
51
  export type Counter = Automerge.Counter;
@@ -75,8 +75,8 @@ export declare const insertAt: typeof Automerge.insertAt;
75
75
  export declare const deleteAt: typeof Automerge.deleteAt;
76
76
  export declare const mark: typeof Automerge.mark;
77
77
  export declare const unmark: typeof Automerge.unmark;
78
- export declare const isRawString: typeof Automerge.isRawString;
79
- export declare const isImmutableString: typeof Automerge.isRawString;
78
+ export declare const isRawString: typeof Automerge.isImmutableString;
79
+ export declare const isImmutableString: typeof Automerge.isImmutableString;
80
80
  export declare const getObjectId: typeof Automerge.getObjectId;
81
81
  export type { ObjID };
82
82
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
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,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,EACrB,oBAAoB,EACpB,WAAW,EACX,WAAW,GACZ,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAC5D,YAAY,EAAE,uBAAuB,EAAE,MAAM,sCAAsC,CAAA;AACnF,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAC5D,YAAY,EAAE,uBAAuB,EAAE,MAAM,sCAAsC,CAAA;AACnF,OAAO,EAAE,IAAI,IAAI,SAAS,EAAE,KAAK,KAAK,EAAE,MAAM,2BAA2B,CAAA;AAEzE,eAAe;AACf,OAAO,KAAK,IAAI,MAAM,mBAAmB,CAAA;AAIzC,YAAY,EACV,sBAAsB,EACtB,sBAAsB,EACtB,6BAA6B,EAC7B,gCAAgC,EAChC,2BAA2B,EAC3B,eAAe,EACf,gBAAgB,EAChB,wCAAwC,EACxC,WAAW,EACX,QAAQ,GACT,MAAM,gBAAgB,CAAA;AAEvB,YAAY,EACV,qBAAqB,EACrB,eAAe,EACf,UAAU,EACV,UAAU,EACV,WAAW,GACZ,MAAM,WAAW,CAAA;AAElB,YAAY,EACV,oBAAoB,EACpB,WAAW,EACX,oBAAoB,EACpB,uBAAuB,EACvB,YAAY,GACb,MAAM,sCAAsC,CAAA;AAE7C,YAAY,EACV,sBAAsB,EACtB,WAAW,GACZ,MAAM,+BAA+B,CAAA;AAEtC,YAAY,EACV,0BAA0B,EAC1B,gBAAgB,EAChB,OAAO,EACP,WAAW,EACX,cAAc,EACd,WAAW,GACZ,MAAM,uBAAuB,CAAA;AAE9B,YAAY,EACV,KAAK,EACL,SAAS,EACT,SAAS,EACT,UAAU,EACV,SAAS,GACV,MAAM,oBAAoB,CAAA;AAE3B,cAAc,YAAY,CAAA;AAiB1B,eAAO,MAAM,OAAO,0BAAoB,CAAA;AACxC,eAAO,MAAM,SAAS,4BAAsB,CAAA;AAE5C,eAAO,MAAM,eAAe,4BAAsB,CAAA;AAIlD,MAAM,MAAM,SAAS,GAAG,YAAY,CAAC,OAAO,SAAS,CAAC,SAAS,CAAC,CAAA;AAChE,MAAM,MAAM,eAAe,GAAG,SAAS,CAAA;AAEvC,MAAM,MAAM,OAAO,GAAG,SAAS,CAAC,OAAO,CAAA;AACvC,MAAM,MAAM,GAAG,CAAC,CAAC,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;AACrC,MAAM,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAA;AACnC,MAAM,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAA;AACnC,MAAM,MAAM,aAAa,CAAC,CAAC,IAAI,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,CAAA;AACzD,MAAM,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAA;AACjC,MAAM,MAAM,OAAO,GAAG,SAAS,CAAC,OAAO,CAAA;AACvC,MAAM,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,CAAA;AACrC,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;AAC/C,MAAM,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAA;AACjC,MAAM,MAAM,OAAO,GAAG,SAAS,CAAC,OAAO,CAAA;AACvC,MAAM,MAAM,SAAS,GAAG,SAAS,CAAC,SAAS,CAAA;AAC3C,MAAM,MAAM,SAAS,GAAG,SAAS,CAAC,SAAS,CAAA;AAC3C,MAAM,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,CAAA;AAIrC,eAAO,MAAM,UAAU,6BAAuB,CAAA;AAC9C,eAAO,MAAM,aAAa,gCAA0B,CAAA;AACpD,eAAO,MAAM,YAAY,+BAAyB,CAAA;AAClD,eAAO,MAAM,IAAI,uBAAiB,CAAA;AAClC,eAAO,MAAM,YAAY,+BAAyB,CAAA;AAKlD,eAAO,MAAM,SAAS,4BAAsB,CAAA;AAC5C,eAAO,MAAM,iBAAiB,oCAA8B,CAAA;AAC5D,eAAO,MAAM,MAAM,yBAAmB,CAAA;AACtC,eAAO,MAAM,UAAU,6BAAuB,CAAA;AAC9C,eAAO,MAAM,QAAQ,2BAAqB,CAAA;AAC1C,eAAO,MAAM,QAAQ,2BAAqB,CAAA;AAC1C,eAAO,MAAM,IAAI,uBAAiB,CAAA;AAClC,eAAO,MAAM,MAAM,yBAAmB,CAAA;AACtC,eAAO,MAAM,WAAW,8BAAwB,CAAA;AAEhD,eAAO,MAAM,iBAAiB,8BAAwB,CAAA;AAEtD,eAAO,MAAM,WAAW,8BAAwB,CAAA;AAChD,YAAY,EAAE,KAAK,EAAE,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@automerge/automerge-repo",
3
- "version": "2.0.8",
3
+ "version": "2.1.0",
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>",
@@ -24,7 +24,7 @@
24
24
  "vite": "^5.0.8"
25
25
  },
26
26
  "dependencies": {
27
- "@automerge/automerge": "^2.2.8",
27
+ "@automerge/automerge": "2.2.8 - 3",
28
28
  "bs58check": "^3.0.1",
29
29
  "cbor-x": "^1.3.0",
30
30
  "debug": "^4.3.4",
@@ -59,5 +59,5 @@
59
59
  "publishConfig": {
60
60
  "access": "public"
61
61
  },
62
- "gitHead": "52d6515aa258d1724c6798a058cf5d40869d86b4"
62
+ "gitHead": "34ba1fc8aec5a33b8bfc509fa45aaa44d4672fe7"
63
63
  }
package/src/Repo.ts CHANGED
@@ -74,9 +74,11 @@ export class Repo extends EventEmitter<RepoEvents> {
74
74
  /** @hidden */
75
75
  storageSubsystem?: StorageSubsystem
76
76
 
77
- /** The debounce rate is adjustable on the repo. */
78
77
  /** @hidden */
79
- saveDebounceRate = 100
78
+ #saveDebounceRate: number
79
+
80
+ /** @hidden */
81
+ #saveFn: (payload: DocHandleEncodedChangePayload<any>) => void
80
82
 
81
83
  #handleCache: Record<DocumentId, DocHandle<any>> = {}
82
84
 
@@ -103,6 +105,7 @@ export class Repo extends EventEmitter<RepoEvents> {
103
105
  isEphemeral = storage === undefined,
104
106
  enableRemoteHeadsGossiping = false,
105
107
  denylist = [],
108
+ saveDebounceRate = 100,
106
109
  }: RepoConfig = {}) {
107
110
  super()
108
111
  this.#remoteHeadsGossipingEnabled = enableRemoteHeadsGossiping
@@ -149,6 +152,18 @@ export class Repo extends EventEmitter<RepoEvents> {
149
152
 
150
153
  this.storageSubsystem = storageSubsystem
151
154
 
155
+ this.#saveDebounceRate = saveDebounceRate
156
+
157
+ if (this.storageSubsystem) {
158
+ const saveFn = ({ handle, doc }: DocHandleEncodedChangePayload<any>) => {
159
+ void this.storageSubsystem!.saveDoc(handle.documentId, doc)
160
+ }
161
+ // Save no more often than saveDebounceRate.
162
+ this.#saveFn = throttle(saveFn, this.#saveDebounceRate)
163
+ } else {
164
+ this.#saveFn = () => {}
165
+ }
166
+
152
167
  // NETWORK
153
168
  // The network subsystem deals with sending and receiving messages to and from peers.
154
169
 
@@ -271,13 +286,13 @@ export class Repo extends EventEmitter<RepoEvents> {
271
286
  // The `document` event is fired by the DocCollection any time we create a new document or look
272
287
  // up a document by ID. We listen for it in order to wire up storage and network synchronization.
273
288
  #registerHandleWithSubsystems(handle: DocHandle<any>) {
274
- const { storageSubsystem } = this
275
- if (storageSubsystem) {
276
- // Save when the document changes, but no more often than saveDebounceRate.
277
- const saveFn = ({ handle, doc }: DocHandleEncodedChangePayload<any>) => {
278
- void storageSubsystem.saveDoc(handle.documentId, doc)
289
+ if (this.storageSubsystem) {
290
+ // Add save function as a listener if it's not already registered
291
+ const existingListeners = handle.listeners("heads-changed")
292
+ if (!existingListeners.some(listener => listener === this.#saveFn)) {
293
+ // Save when the document changes
294
+ handle.on("heads-changed", this.#saveFn)
279
295
  }
280
- handle.on("heads-changed", throttle(saveFn, this.saveDebounceRate))
281
296
  }
282
297
 
283
298
  // Register the document with the synchronizer. This advertises our interest in the document.
@@ -334,7 +349,7 @@ export class Repo extends EventEmitter<RepoEvents> {
334
349
  syncState
335
350
  )
336
351
  },
337
- this.saveDebounceRate
352
+ this.#saveDebounceRate
338
353
  )
339
354
  }
340
355
 
@@ -861,6 +876,11 @@ export interface RepoConfig {
861
876
  * loading documents that are known to be too resource intensive.
862
877
  */
863
878
  denylist?: AutomergeUrl[]
879
+
880
+ /**
881
+ * The debounce rate in milliseconds for saving documents. Defaults to 100ms.
882
+ */
883
+ saveDebounceRate?: number
864
884
  }
865
885
 
866
886
  /** A function that determines whether we should share a document with a peer
package/test/Repo.test.ts CHANGED
@@ -51,8 +51,8 @@ describe("Repo", () => {
51
51
  const repo = new Repo({
52
52
  storage: storageAdapter,
53
53
  network: [networkAdapter],
54
+ saveDebounceRate: 1,
54
55
  })
55
- repo.saveDebounceRate = 1
56
56
  return { repo, storageAdapter, networkAdapter }
57
57
  }
58
58
 
@@ -601,6 +601,85 @@ describe("Repo", () => {
601
601
  assert(Object.keys(repo.handles).length === handleCacheSize)
602
602
  })
603
603
  })
604
+
605
+ describe("registerHandleWithSubsystems", () => {
606
+ it("registers document with synchronizer when creating a new document", async () => {
607
+ const { repo } = setup()
608
+ const handle = repo.create<TestDoc>()
609
+ assert(repo.synchronizer.docSynchronizers[handle.documentId])
610
+ })
611
+
612
+ it("registers save to storage when creating a new document", async () => {
613
+ const { repo, storageAdapter } = setup()
614
+ const handle = repo.create<TestDoc>()
615
+ await pause(10) // wait for debounced save to complete
616
+ assert(
617
+ storageAdapter.keys().some(key => key.includes(handle.documentId))
618
+ )
619
+ })
620
+
621
+ it("registers document with synchronizer when finding an existing document", async () => {
622
+ const { repo, storageAdapter } = setup()
623
+ const handle = repo.create<TestDoc>()
624
+ await pause(10) // wait for debounced save to complete
625
+
626
+ const repo2 = new Repo({ storage: storageAdapter })
627
+ await repo2.find<TestDoc>(handle.url)
628
+ assert(repo2.synchronizer.docSynchronizers[handle.documentId])
629
+ })
630
+
631
+ it("registers document with synchronizer when finding an existing document with progress", async () => {
632
+ const { repo, storageAdapter } = setup()
633
+ const handle = repo.create<TestDoc>()
634
+ await pause(10) // wait for debounced save to complete
635
+
636
+ const repo2 = new Repo({ storage: storageAdapter })
637
+ repo2.findWithProgress<TestDoc>(handle.url)
638
+ await pause(10)
639
+ assert(repo2.synchronizer.docSynchronizers[handle.documentId])
640
+ })
641
+
642
+ it("registers document with synchronizer when there is no storage subsystem", async () => {
643
+ const repo = new Repo()
644
+ const handle = repo.create<TestDoc>()
645
+ assert(repo.synchronizer.docSynchronizers[handle.documentId])
646
+ assert.equal(handle.listenerCount("heads-changed"), 0) // no save listener registered
647
+ })
648
+
649
+ it("respects saveDebounceRate when saving", async () => {
650
+ const storageAdapter = new DummyStorageAdapter()
651
+ const networkAdapter = new DummyNetworkAdapter()
652
+ const repo = new Repo({
653
+ storage: storageAdapter,
654
+ network: [networkAdapter],
655
+ saveDebounceRate: 100,
656
+ })
657
+ const handle = repo.create<TestDoc>()
658
+
659
+ for (let i = 0; i < 5; i++) {
660
+ handle.change(d => {
661
+ d.foo = `bar${i}`
662
+ })
663
+ }
664
+ await pause(10)
665
+ assert(storageAdapter.keys().length < 5)
666
+
667
+ const keysBeforeDebouncedSave = storageAdapter.keys().length
668
+ await pause(150)
669
+ const keysAfterDebouncedSave = storageAdapter.keys().length
670
+ assert(keysAfterDebouncedSave > keysBeforeDebouncedSave)
671
+ })
672
+
673
+ it("does not add duplicate heads-changed listeners", async () => {
674
+ const { repo } = setup()
675
+ const handle = repo.create<TestDoc>()
676
+ await pause(10) // wait for debounced save to complete
677
+ await repo.find<TestDoc>(handle.url)
678
+ repo.findWithProgress<TestDoc>(handle.url)
679
+ await pause(10)
680
+ assert.equal(handle.listenerCount("heads-changed"), 1)
681
+ })
682
+ })
604
683
  })
605
684
 
606
685
  describe("flush behaviour", () => {
@@ -1368,6 +1447,18 @@ describe("Repo", () => {
1368
1447
 
1369
1448
  teardown()
1370
1449
  })
1450
+
1451
+ it("does not add duplicate heads-changed listeners", async () => {
1452
+ const { aliceRepo, bobRepo, teardown } = await setup()
1453
+
1454
+ const aliceHandle = aliceRepo.create<TestDoc>({ foo: "bar" })
1455
+ await pause(10)
1456
+
1457
+ const bobHandle = await bobRepo.find<TestDoc>(aliceHandle.url)
1458
+ assert.equal(bobHandle.listenerCount("heads-changed"), 1)
1459
+
1460
+ teardown()
1461
+ })
1371
1462
  })
1372
1463
 
1373
1464
  describe("with peers (mesh network)", () => {