@automerge/automerge-repo 2.0.0-alpha.6 → 2.0.0-beta.1

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 (79) hide show
  1. package/README.md +8 -8
  2. package/dist/AutomergeUrl.d.ts +17 -5
  3. package/dist/AutomergeUrl.d.ts.map +1 -1
  4. package/dist/AutomergeUrl.js +71 -24
  5. package/dist/DocHandle.d.ts +87 -30
  6. package/dist/DocHandle.d.ts.map +1 -1
  7. package/dist/DocHandle.js +198 -48
  8. package/dist/FindProgress.d.ts +30 -0
  9. package/dist/FindProgress.d.ts.map +1 -0
  10. package/dist/FindProgress.js +1 -0
  11. package/dist/RemoteHeadsSubscriptions.d.ts +4 -5
  12. package/dist/RemoteHeadsSubscriptions.d.ts.map +1 -1
  13. package/dist/RemoteHeadsSubscriptions.js +4 -1
  14. package/dist/Repo.d.ts +46 -6
  15. package/dist/Repo.d.ts.map +1 -1
  16. package/dist/Repo.js +252 -67
  17. package/dist/helpers/abortable.d.ts +39 -0
  18. package/dist/helpers/abortable.d.ts.map +1 -0
  19. package/dist/helpers/abortable.js +45 -0
  20. package/dist/helpers/arraysAreEqual.d.ts.map +1 -1
  21. package/dist/helpers/bufferFromHex.d.ts +3 -0
  22. package/dist/helpers/bufferFromHex.d.ts.map +1 -0
  23. package/dist/helpers/bufferFromHex.js +13 -0
  24. package/dist/helpers/debounce.d.ts.map +1 -1
  25. package/dist/helpers/eventPromise.d.ts.map +1 -1
  26. package/dist/helpers/headsAreSame.d.ts +2 -2
  27. package/dist/helpers/headsAreSame.d.ts.map +1 -1
  28. package/dist/helpers/mergeArrays.d.ts +1 -1
  29. package/dist/helpers/mergeArrays.d.ts.map +1 -1
  30. package/dist/helpers/pause.d.ts.map +1 -1
  31. package/dist/helpers/tests/network-adapter-tests.d.ts.map +1 -1
  32. package/dist/helpers/tests/network-adapter-tests.js +13 -13
  33. package/dist/helpers/tests/storage-adapter-tests.d.ts +2 -2
  34. package/dist/helpers/tests/storage-adapter-tests.d.ts.map +1 -1
  35. package/dist/helpers/tests/storage-adapter-tests.js +25 -48
  36. package/dist/helpers/throttle.d.ts.map +1 -1
  37. package/dist/helpers/withTimeout.d.ts.map +1 -1
  38. package/dist/index.d.ts +2 -1
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +1 -1
  41. package/dist/network/messages.d.ts.map +1 -1
  42. package/dist/storage/StorageSubsystem.d.ts +15 -1
  43. package/dist/storage/StorageSubsystem.d.ts.map +1 -1
  44. package/dist/storage/StorageSubsystem.js +50 -14
  45. package/dist/synchronizer/CollectionSynchronizer.d.ts +4 -3
  46. package/dist/synchronizer/CollectionSynchronizer.d.ts.map +1 -1
  47. package/dist/synchronizer/CollectionSynchronizer.js +34 -15
  48. package/dist/synchronizer/DocSynchronizer.d.ts +3 -2
  49. package/dist/synchronizer/DocSynchronizer.d.ts.map +1 -1
  50. package/dist/synchronizer/DocSynchronizer.js +51 -27
  51. package/dist/synchronizer/Synchronizer.d.ts +11 -0
  52. package/dist/synchronizer/Synchronizer.d.ts.map +1 -1
  53. package/dist/types.d.ts +4 -1
  54. package/dist/types.d.ts.map +1 -1
  55. package/fuzz/fuzz.ts +3 -3
  56. package/package.json +3 -4
  57. package/src/AutomergeUrl.ts +101 -26
  58. package/src/DocHandle.ts +268 -58
  59. package/src/FindProgress.ts +48 -0
  60. package/src/RemoteHeadsSubscriptions.ts +11 -9
  61. package/src/Repo.ts +364 -74
  62. package/src/helpers/abortable.ts +61 -0
  63. package/src/helpers/bufferFromHex.ts +14 -0
  64. package/src/helpers/headsAreSame.ts +2 -2
  65. package/src/helpers/tests/network-adapter-tests.ts +14 -13
  66. package/src/helpers/tests/storage-adapter-tests.ts +44 -86
  67. package/src/index.ts +7 -0
  68. package/src/storage/StorageSubsystem.ts +66 -16
  69. package/src/synchronizer/CollectionSynchronizer.ts +37 -16
  70. package/src/synchronizer/DocSynchronizer.ts +59 -32
  71. package/src/synchronizer/Synchronizer.ts +14 -0
  72. package/src/types.ts +4 -1
  73. package/test/AutomergeUrl.test.ts +130 -0
  74. package/test/CollectionSynchronizer.test.ts +4 -4
  75. package/test/DocHandle.test.ts +255 -30
  76. package/test/DocSynchronizer.test.ts +10 -3
  77. package/test/Repo.test.ts +376 -203
  78. package/test/StorageSubsystem.test.ts +80 -1
  79. package/test/remoteHeads.test.ts +27 -12
package/dist/DocHandle.js CHANGED
@@ -2,7 +2,7 @@ import * as A from "@automerge/automerge/slim/next";
2
2
  import debug from "debug";
3
3
  import { EventEmitter } from "eventemitter3";
4
4
  import { assertEvent, assign, createActor, setup, waitFor } from "xstate";
5
- import { stringifyAutomergeUrl } from "./AutomergeUrl.js";
5
+ import { decodeHeads, encodeHeads, stringifyAutomergeUrl, } from "./AutomergeUrl.js";
6
6
  import { encode } from "./helpers/cbor.js";
7
7
  import { headsAreSame } from "./helpers/headsAreSame.js";
8
8
  import { withTimeout } from "./helpers/withTimeout.js";
@@ -24,6 +24,8 @@ export class DocHandle extends EventEmitter {
24
24
  #log;
25
25
  /** The XState actor running our state machine. */
26
26
  #machine;
27
+ /** If set, this handle will only show the document at these heads */
28
+ #fixedHeads;
27
29
  /** The last known state of our document. */
28
30
  #prevDocState = A.init();
29
31
  /** How long to wait before giving up on a document. (Note that a document will be marked
@@ -31,6 +33,8 @@ export class DocHandle extends EventEmitter {
31
33
  #timeoutDelay = 60_000;
32
34
  /** A dictionary mapping each peer to the last heads we know they have. */
33
35
  #remoteHeads = {};
36
+ /** Cache for view handles, keyed by the stringified heads */
37
+ #viewCache = new Map();
34
38
  /** @hidden */
35
39
  constructor(documentId, options = {}) {
36
40
  super();
@@ -38,6 +42,9 @@ export class DocHandle extends EventEmitter {
38
42
  if ("timeoutDelay" in options && options.timeoutDelay) {
39
43
  this.#timeoutDelay = options.timeoutDelay;
40
44
  }
45
+ if ("heads" in options) {
46
+ this.#fixedHeads = options.heads;
47
+ }
41
48
  const doc = A.init();
42
49
  this.#log = debug(`automerge-repo:dochandle:${this.documentId.slice(0, 5)}`);
43
50
  const delay = this.#timeoutDelay;
@@ -59,9 +66,12 @@ export class DocHandle extends EventEmitter {
59
66
  this.emit("delete", { handle: this });
60
67
  return { doc: A.init() };
61
68
  }),
62
- onUnavailable: () => {
63
- this.emit("unavailable", { handle: this });
64
- },
69
+ onUnavailable: assign(() => {
70
+ return { doc: A.init() };
71
+ }),
72
+ onUnload: assign(() => {
73
+ return { doc: A.init() };
74
+ }),
65
75
  },
66
76
  }).createMachine({
67
77
  /** @xstate-layout N4IgpgJg5mDOIC5QAoC2BDAxgCwJYDswBKAYgFUAFAEQEEAVAUQG0AGAXUVAAcB7WXAC64e+TiAAeiAOwAOAKwA6ACxSAzKqks1ATjlTdAGhABPRAFolAJksKN2y1KtKAbFLla5AX09G0WPISkVAwAMgyMrBxIILz8QiJikggAjCzOijKqLEqqybJyLizaRqYIFpbJtro5Uo7J2o5S3r4YOATECrgQADZgJADCAEoM9MzsYrGCwqLRSeoyCtra8pa5adquySXmDjY5ac7JljLJeepKzSB+bYGdPX0AYgCSAHJUkRN8UwmziM7HCgqyVcUnqcmScmcMm2ZV2yiyzkOx1OalUFx8V1aAQ63R46AgBCgJGGAEUyAwAMp0D7RSbxGagJKHFgKOSWJTJGRSCosCpKaEmRCqbQKU5yXINeTaer6LwY67YogKXH4wkkKgAeX6AH1hjQqABNGncL70xKIJQ5RY5BHOJag6wwpRyEWImQVeT1aWrVSXBXtJUqgn4Ik0ADqNCedG1L3CYY1gwA0saYqbpuaEG4pKLksKpFDgcsCjDhTnxTKpTLdH6sQGFOgAO7oKYhl5gAQNngAJwA1iRY3R40ndSNDSm6enfpm5BkWAVkvy7bpuTCKq7ndZnfVeSwuTX-HWu2AAI4AVzgQhD6q12rILxoADVIyEaAAhMLjtM-RmIE4LVSQi4nLLDIGzOCWwLKA0cgyLBoFWNy+43B0R5nheaqajqepjuMtJfgyEh-FoixqMCoKqOyhzgYKCDOq6UIeuCSxHOoSGKgop74OgABuzbdOgABGvTXlho5GrhJpxJOP4pLulT6KoMhpJY2hzsWNF0QobqMV6LG+pc+A8BAcBiP6gSfFJ36EQgKksksKxrHamwwmY7gLKB85QjBzoAWxdZdL0FnfARST8ooLC7qoTnWBU4pyC5ViVMKBQaHUDQuM4fm3EGhJBWaU7-CysEAUp3LpEpWw0WYRw2LmqzgqciIsCxWUdI2zaXlAbYdt2PZ5dJ1n5jY2iJY1ikOIcMJHCyUWHC62hRZkUVNPKta3Kh56wJ1-VWUyzhFc64JWJCtQNBBzhQW4cHwbsrVKpxPF8YJgV4ZZIWIKkiKiiNSkqZYWjzCWaQ5hFh0AcCuR3QoR74qUknBRmzholpv3OkpRQNNRpTzaKTWKbIWR5FDxm9AIkA7e9skUYCWayLILBZGoLkUSKbIyIdpxHPoyTeN4QA */
@@ -71,6 +81,7 @@ export class DocHandle extends EventEmitter {
71
81
  context: { documentId, doc },
72
82
  on: {
73
83
  UPDATE: { actions: "onUpdate" },
84
+ UNLOAD: ".unloaded",
74
85
  DELETE: ".deleted",
75
86
  },
76
87
  states: {
@@ -98,6 +109,12 @@ export class DocHandle extends EventEmitter {
98
109
  on: { DOC_READY: "ready" },
99
110
  },
100
111
  ready: {},
112
+ unloaded: {
113
+ entry: "onUnload",
114
+ on: {
115
+ RELOAD: "loading",
116
+ },
117
+ },
101
118
  deleted: { entry: "onDelete", type: "final" },
102
119
  },
103
120
  });
@@ -113,7 +130,7 @@ export class DocHandle extends EventEmitter {
113
130
  });
114
131
  // Start the machine, and send a create or find event to get things going
115
132
  this.#machine.start();
116
- this.#machine.send({ type: BEGIN });
133
+ this.begin();
117
134
  }
118
135
  // PRIVATE
119
136
  /** Returns the current document, regardless of state */
@@ -140,7 +157,7 @@ export class DocHandle extends EventEmitter {
140
157
  #checkForChanges(before, after) {
141
158
  const beforeHeads = A.getHeads(before);
142
159
  const afterHeads = A.getHeads(after);
143
- const docChanged = !headsAreSame(afterHeads, beforeHeads);
160
+ const docChanged = !headsAreSame(encodeHeads(afterHeads), encodeHeads(beforeHeads));
144
161
  if (docChanged) {
145
162
  this.emit("heads-changed", { handle: this, doc: after });
146
163
  const patches = A.diff(after, beforeHeads, afterHeads);
@@ -163,7 +180,10 @@ export class DocHandle extends EventEmitter {
163
180
  /** Our documentId in Automerge URL form.
164
181
  */
165
182
  get url() {
166
- return stringifyAutomergeUrl({ documentId: this.documentId });
183
+ return stringifyAutomergeUrl({
184
+ documentId: this.documentId,
185
+ heads: this.#fixedHeads,
186
+ });
167
187
  }
168
188
  /**
169
189
  * @returns true if the document is ready for accessing or changes.
@@ -172,6 +192,13 @@ export class DocHandle extends EventEmitter {
172
192
  * peers. We do not currently have an equivalent `whenSynced()`.
173
193
  */
174
194
  isReady = () => this.inState(["ready"]);
195
+ /**
196
+ * @returns true if the document has been unloaded.
197
+ *
198
+ * Unloaded documents are freed from memory but not removed from local storage. It's not currently
199
+ * possible at runtime to reload an unloaded document.
200
+ */
201
+ isUnloaded = () => this.inState(["unloaded"]);
175
202
  /**
176
203
  * @returns true if the document has been marked as deleted.
177
204
  *
@@ -204,43 +231,26 @@ export class DocHandle extends EventEmitter {
204
231
  await withTimeout(this.#statePromise(awaitStates), this.#timeoutDelay);
205
232
  }
206
233
  /**
207
- * @returns the current state of this handle's Automerge document.
234
+ * Returns the current state of the Automerge document this handle manages.
235
+ *
236
+ * @returns the current document
237
+ * @throws on deleted and unavailable documents
208
238
  *
209
- * This is the recommended way to access a handle's document. Note that this waits for the handle
210
- * to be ready if necessary. If loading (or synchronization) fails, this will never resolve.
211
239
  */
212
- async doc(
213
- /** states to wait for, such as "LOADING". mostly for internal use. */
214
- awaitStates = ["ready", "unavailable"]) {
215
- try {
216
- // wait for the document to enter one of the desired states
217
- await this.#statePromise(awaitStates);
218
- }
219
- catch (error) {
220
- // if we timed out, return undefined
221
- return undefined;
240
+ doc() {
241
+ if (!this.isReady())
242
+ throw new Error("DocHandle is not ready");
243
+ if (this.#fixedHeads) {
244
+ return A.view(this.#doc, decodeHeads(this.#fixedHeads));
222
245
  }
223
- // Return the document
224
- return !this.isUnavailable() ? this.#doc : undefined;
246
+ return this.#doc;
225
247
  }
226
248
  /**
227
- * Synchronously returns the current state of the Automerge document this handle manages, or
228
- * undefined. Consider using `await handle.doc()` instead. Check `isReady()`, or use `whenReady()`
229
- * if you want to make sure loading is complete first.
230
- *
231
- * Not to be confused with the SyncState of the document, which describes the state of the
232
- * synchronization process.
233
- *
234
- * Note that `undefined` is not a valid Automerge document, so the return from this function is
235
- * unambigous.
236
249
  *
237
- * @returns the current document, or undefined if the document is not ready.
238
- */
250
+ * @deprecated */
239
251
  docSync() {
240
- if (!this.isReady())
241
- return undefined;
242
- else
243
- return this.#doc;
252
+ console.warn("docSync is deprecated. Use doc() instead. This function will be removed as part of the 2.0 release.");
253
+ return this.doc();
244
254
  }
245
255
  /**
246
256
  * Returns the current "heads" of the document, akin to a git commit.
@@ -248,10 +258,129 @@ export class DocHandle extends EventEmitter {
248
258
  * @returns the current document's heads, or undefined if the document is not ready
249
259
  */
250
260
  heads() {
261
+ if (!this.isReady())
262
+ throw new Error("DocHandle is not ready");
263
+ if (this.#fixedHeads) {
264
+ return this.#fixedHeads;
265
+ }
266
+ return encodeHeads(A.getHeads(this.#doc));
267
+ }
268
+ begin() {
269
+ this.#machine.send({ type: BEGIN });
270
+ }
271
+ /**
272
+ * Returns an array of all past "heads" for the document in topological order.
273
+ *
274
+ * @remarks
275
+ * A point-in-time in an automerge document is an *array* of heads since there may be
276
+ * concurrent edits. This API just returns a topologically sorted history of all edits
277
+ * so every previous entry will be (in some sense) before later ones, but the set of all possible
278
+ * history views would be quite large under concurrency (every thing in each branch against each other).
279
+ * There might be a clever way to think about this, but we haven't found it yet, so for now at least
280
+ * we present a single traversable view which excludes concurrency.
281
+ * @returns UrlHeads[] - The individual heads for every change in the document. Each item is a tagged string[1].
282
+ */
283
+ history() {
284
+ if (!this.isReady()) {
285
+ return undefined;
286
+ }
287
+ // This just returns all the heads as individual strings.
288
+ return A.topoHistoryTraversal(this.#doc).map(h => encodeHeads([h]));
289
+ }
290
+ /**
291
+ * Creates a fixed "view" of an automerge document at the given point in time represented
292
+ * by the `heads` passed in. The return value is the same type as doc() and will return
293
+ * undefined if the object hasn't finished loading.
294
+ *
295
+ * @remarks
296
+ * Note that our Typescript types do not consider change over time and the current version
297
+ * of Automerge doesn't check types at runtime, so if you go back to an old set of heads
298
+ * that doesn't match the heads here, Typescript will not save you.
299
+ *
300
+ * @argument heads - The heads to view the document at. See history().
301
+ * @returns DocHandle<T> at the time of `heads`
302
+ */
303
+ view(heads) {
304
+ if (!this.isReady()) {
305
+ throw new Error(`DocHandle#${this.documentId} is not ready. Check \`handle.isReady()\` before calling view().`);
306
+ }
307
+ // Create a cache key from the heads
308
+ const cacheKey = JSON.stringify(heads);
309
+ // Check if we have a cached handle for these heads
310
+ const cachedHandle = this.#viewCache.get(cacheKey);
311
+ if (cachedHandle) {
312
+ return cachedHandle;
313
+ }
314
+ // Create a new handle with the same documentId but fixed heads
315
+ const handle = new DocHandle(this.documentId, {
316
+ heads,
317
+ timeoutDelay: this.#timeoutDelay,
318
+ });
319
+ handle.update(() => A.clone(this.#doc));
320
+ handle.doneLoading();
321
+ // Store in cache
322
+ this.#viewCache.set(cacheKey, handle);
323
+ return handle;
324
+ }
325
+ /**
326
+ * Returns a set of Patch operations that will move a materialized document from one state to another
327
+ * if applied.
328
+ *
329
+ * @remarks
330
+ * We allow specifying either:
331
+ * - Two sets of heads to compare directly
332
+ * - A single set of heads to compare against our current heads
333
+ * - Another DocHandle to compare against (which must share history with this document)
334
+ *
335
+ * @throws Error if the documents don't share history or if either document is not ready
336
+ * @returns Automerge patches that go from one document state to the other
337
+ */
338
+ diff(first, second) {
339
+ if (!this.isReady()) {
340
+ throw new Error(`DocHandle#${this.documentId} is not ready. Check \`handle.isReady()\` before calling diff().`);
341
+ }
342
+ const doc = this.#doc;
343
+ if (!doc)
344
+ throw new Error("Document not available");
345
+ // If first argument is a DocHandle
346
+ if (first instanceof DocHandle) {
347
+ if (!first.isReady()) {
348
+ throw new Error("Cannot diff against a handle that isn't ready");
349
+ }
350
+ const otherHeads = first.heads();
351
+ if (!otherHeads)
352
+ throw new Error("Other document's heads not available");
353
+ // Create a temporary merged doc to verify shared history and compute diff
354
+ const mergedDoc = A.merge(A.clone(doc), first.doc());
355
+ // Use the merged doc to compute the diff
356
+ return A.diff(mergedDoc, decodeHeads(this.heads()), decodeHeads(otherHeads));
357
+ }
358
+ // Otherwise treat as heads
359
+ const from = second ? first : (this.heads() || []);
360
+ const to = second ? second : first;
361
+ return A.diff(doc, decodeHeads(from), decodeHeads(to));
362
+ }
363
+ /**
364
+ * `metadata(head?)` allows you to look at the metadata for a change
365
+ * this can be used to build history graphs to find commit messages and edit times.
366
+ * this interface.
367
+ *
368
+ * @remarks
369
+ * I'm really not convinced this is the right way to surface this information so
370
+ * I'm leaving this API "hidden".
371
+ *
372
+ * @hidden
373
+ */
374
+ metadata(change) {
251
375
  if (!this.isReady()) {
252
376
  return undefined;
253
377
  }
254
- return A.getHeads(this.#doc);
378
+ if (!change) {
379
+ change = this.heads()[0];
380
+ }
381
+ // we return undefined instead of null by convention in this API
382
+ return (A.inspectChange(this.#doc, decodeHeads([change])[0]) ||
383
+ undefined);
255
384
  }
256
385
  /**
257
386
  * `update` is called any time we have a new document state; could be
@@ -271,7 +400,7 @@ export class DocHandle extends EventEmitter {
271
400
  this.#machine.send({ type: DOC_READY });
272
401
  }
273
402
  /**
274
- * Called by the repo either when a doc handle changes or we receive new remote heads.
403
+ * Called by the repo when a doc handle changes or we receive new remote heads.
275
404
  * @hidden
276
405
  */
277
406
  setRemoteHeads(storageId, heads) {
@@ -301,6 +430,9 @@ export class DocHandle extends EventEmitter {
301
430
  if (!this.isReady()) {
302
431
  throw new Error(`DocHandle#${this.documentId} is in ${this.state} and not ready. Check \`handle.isReady()\` before accessing the document.`);
303
432
  }
433
+ if (this.#fixedHeads) {
434
+ throw new Error(`DocHandle#${this.documentId} is in view-only mode at specific heads. Use clone() to create a new document from this state.`);
435
+ }
304
436
  this.#machine.send({
305
437
  type: UPDATE,
306
438
  payload: { callback: doc => A.change(doc, options, callback) },
@@ -315,13 +447,18 @@ export class DocHandle extends EventEmitter {
315
447
  if (!this.isReady()) {
316
448
  throw new Error(`DocHandle#${this.documentId} is not ready. Check \`handle.isReady()\` before accessing the document.`);
317
449
  }
450
+ if (this.#fixedHeads) {
451
+ throw new Error(`DocHandle#${this.documentId} is in view-only mode at specific heads. Use clone() to create a new document from this state.`);
452
+ }
318
453
  let resultHeads = undefined;
319
454
  this.#machine.send({
320
455
  type: UPDATE,
321
456
  payload: {
322
457
  callback: doc => {
323
- const result = A.changeAt(doc, heads, options, callback);
324
- resultHeads = result.newHeads || undefined;
458
+ const result = A.changeAt(doc, decodeHeads(heads), options, callback);
459
+ resultHeads = result.newHeads
460
+ ? encodeHeads(result.newHeads)
461
+ : undefined;
325
462
  return result.newDoc;
326
463
  },
327
464
  },
@@ -343,28 +480,37 @@ export class DocHandle extends EventEmitter {
343
480
  if (!this.isReady() || !otherHandle.isReady()) {
344
481
  throw new Error("Both handles must be ready to merge");
345
482
  }
346
- const mergingDoc = otherHandle.docSync();
347
- if (!mergingDoc) {
348
- throw new Error("The document to be merged in is falsy, aborting.");
483
+ if (this.#fixedHeads) {
484
+ throw new Error(`DocHandle#${this.documentId} is in view-only mode at specific heads. Use clone() to create a new document from this state.`);
349
485
  }
486
+ const mergingDoc = otherHandle.doc();
350
487
  this.update(doc => {
351
488
  return A.merge(doc, mergingDoc);
352
489
  });
353
490
  }
354
491
  /**
355
- * Used in testing to mark this document as unavailable.
492
+ * Updates the internal state machine to mark the document unavailable.
356
493
  * @hidden
357
494
  */
358
495
  unavailable() {
359
496
  this.#machine.send({ type: DOC_UNAVAILABLE });
360
497
  }
361
- /** Called by the repo when the document is not found in storage.
498
+ /**
499
+ * Called by the repo either when the document is not found in storage.
362
500
  * @hidden
363
501
  * */
364
502
  request() {
365
503
  if (this.#state === "loading")
366
504
  this.#machine.send({ type: REQUEST });
367
505
  }
506
+ /** Called by the repo to free memory used by the document. */
507
+ unload() {
508
+ this.#machine.send({ type: UNLOAD });
509
+ }
510
+ /** Called by the repo to reuse an unloaded handle. */
511
+ reload() {
512
+ this.#machine.send({ type: RELOAD });
513
+ }
368
514
  /** Called by the repo when the document is deleted. */
369
515
  delete() {
370
516
  this.#machine.send({ type: DELETE });
@@ -379,7 +525,7 @@ export class DocHandle extends EventEmitter {
379
525
  broadcast(message) {
380
526
  this.emit("ephemeral-message-outbound", {
381
527
  handle: this,
382
- data: encode(message),
528
+ data: new Uint8Array(encode(message)),
383
529
  });
384
530
  }
385
531
  metrics() {
@@ -400,16 +546,20 @@ export const HandleState = {
400
546
  REQUESTING: "requesting",
401
547
  /** The document is available */
402
548
  READY: "ready",
549
+ /** The document has been unloaded from the handle, to free memory usage */
550
+ UNLOADED: "unloaded",
403
551
  /** The document has been deleted from the repo */
404
552
  DELETED: "deleted",
405
553
  /** The document was not available in storage or from any connected peers */
406
554
  UNAVAILABLE: "unavailable",
407
555
  };
408
- export const { IDLE, LOADING, REQUESTING, READY, DELETED, UNAVAILABLE } = HandleState;
556
+ export const { IDLE, LOADING, REQUESTING, READY, UNLOADED, DELETED, UNAVAILABLE, } = HandleState;
409
557
  const BEGIN = "BEGIN";
410
558
  const REQUEST = "REQUEST";
411
559
  const DOC_READY = "DOC_READY";
412
560
  const UPDATE = "UPDATE";
561
+ const UNLOAD = "UNLOAD";
562
+ const RELOAD = "RELOAD";
413
563
  const DELETE = "DELETE";
414
564
  const TIMEOUT = "TIMEOUT";
415
565
  const DOC_UNAVAILABLE = "DOC_UNAVAILABLE";
@@ -0,0 +1,30 @@
1
+ import { DocHandle } from "./DocHandle.js";
2
+ export type FindProgressState = "loading" | "ready" | "failed" | "aborted" | "unavailable";
3
+ interface FindProgressBase<T> {
4
+ state: FindProgressState;
5
+ handle: DocHandle<T>;
6
+ }
7
+ interface FindProgressLoading<T> extends FindProgressBase<T> {
8
+ state: "loading";
9
+ progress: number;
10
+ }
11
+ interface FindProgressReady<T> extends FindProgressBase<T> {
12
+ state: "ready";
13
+ }
14
+ interface FindProgressFailed<T> extends FindProgressBase<T> {
15
+ state: "failed";
16
+ error: Error;
17
+ }
18
+ interface FindProgressUnavailable<T> extends FindProgressBase<T> {
19
+ state: "unavailable";
20
+ }
21
+ interface FindProgressAborted<T> extends FindProgressBase<T> {
22
+ state: "aborted";
23
+ }
24
+ export type FindProgress<T> = FindProgressLoading<T> | FindProgressReady<T> | FindProgressFailed<T> | FindProgressUnavailable<T> | FindProgressAborted<T>;
25
+ export type FindProgressWithMethods<T> = FindProgress<T> & {
26
+ next: () => Promise<FindProgressWithMethods<T>>;
27
+ untilReady: (allowableStates: string[]) => Promise<DocHandle<T>>;
28
+ };
29
+ export {};
30
+ //# sourceMappingURL=FindProgress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FindProgress.d.ts","sourceRoot":"","sources":["../src/FindProgress.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAE1C,MAAM,MAAM,iBAAiB,GACzB,SAAS,GACT,OAAO,GACP,QAAQ,GACR,SAAS,GACT,aAAa,CAAA;AAEjB,UAAU,gBAAgB,CAAC,CAAC;IAC1B,KAAK,EAAE,iBAAiB,CAAA;IACxB,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,CAAA;CACrB;AAED,UAAU,mBAAmB,CAAC,CAAC,CAAE,SAAQ,gBAAgB,CAAC,CAAC,CAAC;IAC1D,KAAK,EAAE,SAAS,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,UAAU,iBAAiB,CAAC,CAAC,CAAE,SAAQ,gBAAgB,CAAC,CAAC,CAAC;IACxD,KAAK,EAAE,OAAO,CAAA;CACf;AAED,UAAU,kBAAkB,CAAC,CAAC,CAAE,SAAQ,gBAAgB,CAAC,CAAC,CAAC;IACzD,KAAK,EAAE,QAAQ,CAAA;IACf,KAAK,EAAE,KAAK,CAAA;CACb;AAED,UAAU,uBAAuB,CAAC,CAAC,CAAE,SAAQ,gBAAgB,CAAC,CAAC,CAAC;IAC9D,KAAK,EAAE,aAAa,CAAA;CACrB;AAED,UAAU,mBAAmB,CAAC,CAAC,CAAE,SAAQ,gBAAgB,CAAC,CAAC,CAAC;IAC1D,KAAK,EAAE,SAAS,CAAA;CACjB;AAED,MAAM,MAAM,YAAY,CAAC,CAAC,IACtB,mBAAmB,CAAC,CAAC,CAAC,GACtB,iBAAiB,CAAC,CAAC,CAAC,GACpB,kBAAkB,CAAC,CAAC,CAAC,GACrB,uBAAuB,CAAC,CAAC,CAAC,GAC1B,mBAAmB,CAAC,CAAC,CAAC,CAAA;AAE1B,MAAM,MAAM,uBAAuB,CAAC,CAAC,IAAI,YAAY,CAAC,CAAC,CAAC,GAAG;IACzD,IAAI,EAAE,MAAM,OAAO,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC,CAAA;IAE/C,UAAU,EAAE,CAAC,eAAe,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAA;CACjE,CAAA"}
@@ -0,0 +1 @@
1
+ export {};
@@ -1,19 +1,18 @@
1
- import { next as A } from "@automerge/automerge/slim";
2
1
  import { EventEmitter } from "eventemitter3";
3
- import { DocumentId, PeerId } from "./types.js";
2
+ import { DocumentId, PeerId, UrlHeads } from "./types.js";
4
3
  import { RemoteHeadsChanged, RemoteSubscriptionControlMessage } from "./network/messages.js";
5
4
  import { StorageId } from "./index.js";
6
5
  export type RemoteHeadsSubscriptionEventPayload = {
7
6
  documentId: DocumentId;
8
7
  storageId: StorageId;
9
- remoteHeads: A.Heads;
8
+ remoteHeads: UrlHeads;
10
9
  timestamp: number;
11
10
  };
12
11
  export type NotifyRemoteHeadsPayload = {
13
12
  targetId: PeerId;
14
13
  documentId: DocumentId;
15
14
  storageId: StorageId;
16
- heads: A.Heads;
15
+ heads: UrlHeads;
17
16
  timestamp: number;
18
17
  };
19
18
  type RemoteHeadsSubscriptionEvents = {
@@ -33,7 +32,7 @@ export declare class RemoteHeadsSubscriptions extends EventEmitter<RemoteHeadsSu
33
32
  /** A peer we are not directly connected to has changed their heads */
34
33
  handleRemoteHeads(msg: RemoteHeadsChanged): void;
35
34
  /** A peer we are directly connected to has updated their heads */
36
- handleImmediateRemoteHeadsChanged(documentId: DocumentId, storageId: StorageId, heads: A.Heads): void;
35
+ handleImmediateRemoteHeadsChanged(documentId: DocumentId, storageId: StorageId, heads: UrlHeads): void;
37
36
  addGenerousPeer(peerId: PeerId): void;
38
37
  removePeer(peerId: PeerId): void;
39
38
  subscribePeerToDoc(peerId: PeerId, documentId: DocumentId): void;
@@ -1 +1 @@
1
- {"version":3,"file":"RemoteHeadsSubscriptions.d.ts","sourceRoot":"","sources":["../src/RemoteHeadsSubscriptions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,IAAI,CAAC,EAAE,MAAM,2BAA2B,CAAA;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAC/C,OAAO,EACL,kBAAkB,EAClB,gCAAgC,EACjC,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAItC,MAAM,MAAM,mCAAmC,GAAG;IAChD,UAAU,EAAE,UAAU,CAAA;IACtB,SAAS,EAAE,SAAS,CAAA;IACpB,WAAW,EAAE,CAAC,CAAC,KAAK,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAGD,MAAM,MAAM,wBAAwB,GAAG;IACrC,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,UAAU,CAAA;IACtB,SAAS,EAAE,SAAS,CAAA;IACpB,KAAK,EAAE,CAAC,CAAC,KAAK,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,KAAK,6BAA6B,GAAG;IACnC,sBAAsB,EAAE,CAAC,OAAO,EAAE,mCAAmC,KAAK,IAAI,CAAA;IAC9E,oBAAoB,EAAE,CAAC,OAAO,EAAE;QAC9B,KAAK,EAAE,MAAM,EAAE,CAAA;QACf,GAAG,CAAC,EAAE,SAAS,EAAE,CAAA;QACjB,MAAM,CAAC,EAAE,SAAS,EAAE,CAAA;KACrB,KAAK,IAAI,CAAA;IACV,qBAAqB,EAAE,CAAC,OAAO,EAAE,wBAAwB,KAAK,IAAI,CAAA;CACnE,CAAA;AAED,qBAAa,wBAAyB,SAAQ,YAAY,CAAC,6BAA6B,CAAC;;IAcvF,kBAAkB,CAAC,OAAO,EAAE,SAAS,EAAE;IAkBvC,sBAAsB,CAAC,OAAO,EAAE,SAAS,EAAE;IAsB3C,oBAAoB,CAAC,OAAO,EAAE,gCAAgC;IA0E9D,sEAAsE;IACtE,iBAAiB,CAAC,GAAG,EAAE,kBAAkB;IAgDzC,kEAAkE;IAClE,iCAAiC,CAC/B,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,SAAS,EACpB,KAAK,EAAE,CAAC,CAAC,KAAK;IAgChB,eAAe,CAAC,MAAM,EAAE,MAAM;IAwB9B,UAAU,CAAC,MAAM,EAAE,MAAM;IA2BzB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU;CAoE1D"}
1
+ {"version":3,"file":"RemoteHeadsSubscriptions.d.ts","sourceRoot":"","sources":["../src/RemoteHeadsSubscriptions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACzD,OAAO,EACL,kBAAkB,EAClB,gCAAgC,EACjC,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAItC,MAAM,MAAM,mCAAmC,GAAG;IAChD,UAAU,EAAE,UAAU,CAAA;IACtB,SAAS,EAAE,SAAS,CAAA;IACpB,WAAW,EAAE,QAAQ,CAAA;IACrB,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAGD,MAAM,MAAM,wBAAwB,GAAG;IACrC,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,UAAU,CAAA;IACtB,SAAS,EAAE,SAAS,CAAA;IACpB,KAAK,EAAE,QAAQ,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,KAAK,6BAA6B,GAAG;IACnC,sBAAsB,EAAE,CAAC,OAAO,EAAE,mCAAmC,KAAK,IAAI,CAAA;IAC9E,oBAAoB,EAAE,CAAC,OAAO,EAAE;QAC9B,KAAK,EAAE,MAAM,EAAE,CAAA;QACf,GAAG,CAAC,EAAE,SAAS,EAAE,CAAA;QACjB,MAAM,CAAC,EAAE,SAAS,EAAE,CAAA;KACrB,KAAK,IAAI,CAAA;IACV,qBAAqB,EAAE,CAAC,OAAO,EAAE,wBAAwB,KAAK,IAAI,CAAA;CACnE,CAAA;AAED,qBAAa,wBAAyB,SAAQ,YAAY,CAAC,6BAA6B,CAAC;;IAcvF,kBAAkB,CAAC,OAAO,EAAE,SAAS,EAAE;IAkBvC,sBAAsB,CAAC,OAAO,EAAE,SAAS,EAAE;IAsB3C,oBAAoB,CAAC,OAAO,EAAE,gCAAgC;IA0E9D,sEAAsE;IACtE,iBAAiB,CAAC,GAAG,EAAE,kBAAkB;IAgDzC,kEAAkE;IAClE,iCAAiC,CAC/B,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,SAAS,EACpB,KAAK,EAAE,QAAQ;IAgCjB,eAAe,CAAC,MAAM,EAAE,MAAM;IAwB9B,UAAU,CAAC,MAAM,EAAE,MAAM;IA2BzB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU;CAuE1D"}
@@ -270,7 +270,10 @@ export class RemoteHeadsSubscriptions extends EventEmitter {
270
270
  continue;
271
271
  }
272
272
  else {
273
- remote.set(storageId, { timestamp, heads });
273
+ remote.set(storageId, {
274
+ timestamp,
275
+ heads: heads,
276
+ });
274
277
  changedHeads.push({
275
278
  documentId,
276
279
  storageId: storageId,
package/dist/Repo.d.ts CHANGED
@@ -6,7 +6,20 @@ import { StorageAdapterInterface } from "./storage/StorageAdapterInterface.js";
6
6
  import { StorageSubsystem } from "./storage/StorageSubsystem.js";
7
7
  import { StorageId } from "./storage/types.js";
8
8
  import { CollectionSynchronizer } from "./synchronizer/CollectionSynchronizer.js";
9
- import type { AnyDocumentId, DocumentId, PeerId } from "./types.js";
9
+ import { DocSyncMetrics } from "./synchronizer/Synchronizer.js";
10
+ import type { AnyDocumentId, AutomergeUrl, DocumentId, PeerId } from "./types.js";
11
+ import { AbortOptions } from "./helpers/abortable.js";
12
+ import { FindProgress } from "./FindProgress.js";
13
+ export type FindProgressWithMethods<T> = FindProgress<T> & {
14
+ untilReady: (allowableStates: string[]) => Promise<DocHandle<T>>;
15
+ peek: () => FindProgress<T>;
16
+ subscribe: (callback: (progress: FindProgress<T>) => void) => () => void;
17
+ };
18
+ export type ProgressSignal<T> = {
19
+ peek: () => FindProgress<T>;
20
+ subscribe: (callback: (progress: FindProgress<T>) => void) => () => void;
21
+ untilReady: (allowableStates: string[]) => Promise<DocHandle<T>>;
22
+ };
10
23
  /** A Repo is a collection of documents with networking, syncing, and storage capabilities. */
11
24
  /** The `Repo` is the main entry point of this library
12
25
  *
@@ -32,7 +45,7 @@ export declare class Repo extends EventEmitter<RepoEvents> {
32
45
  /** maps peer id to to persistence information (storageId, isEphemeral), access by collection synchronizer */
33
46
  /** @hidden */
34
47
  peerMetadataByPeerId: Record<PeerId, PeerMetadata>;
35
- constructor({ storage, network, peerId, sharePolicy, isEphemeral, enableRemoteHeadsGossiping, }?: RepoConfig);
48
+ constructor({ storage, network, peerId, sharePolicy, isEphemeral, enableRemoteHeadsGossiping, denylist, }?: RepoConfig);
36
49
  /** Returns all the handles we have cached. */
37
50
  get handles(): Record<DocumentId, DocHandle<any>>;
38
51
  /** Returns a list of all connected peer ids */
@@ -56,17 +69,17 @@ export declare class Repo extends EventEmitter<RepoEvents> {
56
69
  * Any peers this `Repo` is connected to for whom `sharePolicy` returns `true` will
57
70
  * be notified of the newly created DocHandle.
58
71
  *
59
- * @throws if the cloned handle is not yet ready or if
60
- * `clonedHandle.docSync()` returns `undefined` (i.e. the handle is unavailable).
61
72
  */
62
73
  clone<T>(clonedHandle: DocHandle<T>): DocHandle<T>;
74
+ findWithProgress<T>(id: AnyDocumentId, options?: AbortOptions): FindProgressWithMethods<T> | FindProgress<T>;
75
+ find<T>(id: AnyDocumentId, options?: RepoFindOptions & AbortOptions): Promise<DocHandle<T>>;
63
76
  /**
64
77
  * Retrieves a document by id. It gets data from the local system, but also emits a `document`
65
78
  * event to advertise interest in the document.
66
79
  */
67
- find<T>(
80
+ findClassic<T>(
68
81
  /** The url or documentId of the handle to retrieve */
69
- id: AnyDocumentId): DocHandle<T>;
82
+ id: AnyDocumentId, options?: RepoFindOptions & AbortOptions): Promise<DocHandle<T>>;
70
83
  delete(
71
84
  /** The url or documentId of the handle to delete */
72
85
  id: AnyDocumentId): void;
@@ -92,6 +105,13 @@ export declare class Repo extends EventEmitter<RepoEvents> {
92
105
  * @returns Promise<void>
93
106
  */
94
107
  flush(documents?: DocumentId[]): Promise<void>;
108
+ /**
109
+ * Removes a DocHandle from the handleCache.
110
+ * @hidden this API is experimental and may change.
111
+ * @param documentId - documentId of the DocHandle to remove from handleCache, if present in cache.
112
+ * @returns Promise<void>
113
+ */
114
+ removeFromCache(documentId: DocumentId): Promise<void>;
95
115
  shutdown(): Promise<void>;
96
116
  metrics(): {
97
117
  documents: {
@@ -118,6 +138,12 @@ export interface RepoConfig {
118
138
  * Whether to enable the experimental remote heads gossiping feature
119
139
  */
120
140
  enableRemoteHeadsGossiping?: boolean;
141
+ /**
142
+ * A list of automerge URLs which should never be loaded regardless of what
143
+ * messages are received or what the share policy is. This is useful to avoid
144
+ * loading documents that are known to be too resource intensive.
145
+ */
146
+ denylist?: AutomergeUrl[];
121
147
  }
122
148
  /** A function that determines whether we should share a document with a peer
123
149
  *
@@ -135,6 +161,10 @@ export interface RepoEvents {
135
161
  "delete-document": (arg: DeleteDocumentPayload) => void;
136
162
  /** A document was marked as unavailable (we don't have it and none of our peers have it) */
137
163
  "unavailable-document": (arg: DeleteDocumentPayload) => void;
164
+ "doc-metrics": (arg: DocMetrics) => void;
165
+ }
166
+ export interface RepoFindOptions {
167
+ allowableStates?: string[];
138
168
  }
139
169
  export interface DocumentPayload {
140
170
  handle: DocHandle<any>;
@@ -142,4 +172,14 @@ export interface DocumentPayload {
142
172
  export interface DeleteDocumentPayload {
143
173
  documentId: DocumentId;
144
174
  }
175
+ export type DocMetrics = DocSyncMetrics | {
176
+ type: "doc-loaded";
177
+ documentId: DocumentId;
178
+ durationMillis: number;
179
+ numOps: number;
180
+ numChanges: number;
181
+ } | {
182
+ type: "doc-denied";
183
+ documentId: DocumentId;
184
+ };
145
185
  //# sourceMappingURL=Repo.d.ts.map
@@ -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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"}