@automerge/automerge-repo 2.0.0-alpha.6 → 2.0.0-collectionsync-alpha.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 (164) hide show
  1. package/dist/CollectionHandle.d.ts +14 -0
  2. package/dist/CollectionHandle.d.ts.map +1 -0
  3. package/dist/CollectionHandle.js +37 -0
  4. package/dist/DocHandle.d.ts +67 -2
  5. package/dist/DocHandle.d.ts.map +1 -1
  6. package/dist/DocHandle.js +113 -2
  7. package/dist/DocUrl.d.ts +47 -0
  8. package/dist/DocUrl.d.ts.map +1 -0
  9. package/dist/DocUrl.js +72 -0
  10. package/dist/EphemeralData.d.ts +20 -0
  11. package/dist/EphemeralData.d.ts.map +1 -0
  12. package/dist/EphemeralData.js +1 -0
  13. package/dist/Repo.d.ts +28 -7
  14. package/dist/Repo.d.ts.map +1 -1
  15. package/dist/Repo.js +142 -143
  16. package/dist/ferigan.d.ts +51 -0
  17. package/dist/ferigan.d.ts.map +1 -0
  18. package/dist/ferigan.js +98 -0
  19. package/dist/helpers/tests/storage-adapter-tests.d.ts +2 -2
  20. package/dist/helpers/tests/storage-adapter-tests.d.ts.map +1 -1
  21. package/dist/helpers/tests/storage-adapter-tests.js +19 -39
  22. package/dist/index.d.ts +2 -0
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +1 -0
  25. package/dist/network/NetworkSubsystem.d.ts +1 -0
  26. package/dist/network/NetworkSubsystem.d.ts.map +1 -1
  27. package/dist/network/NetworkSubsystem.js +3 -0
  28. package/dist/network/messages.d.ts +7 -1
  29. package/dist/network/messages.d.ts.map +1 -1
  30. package/dist/network/messages.js +2 -1
  31. package/dist/src/DocHandle.d.ts +182 -0
  32. package/dist/src/DocHandle.d.ts.map +1 -0
  33. package/dist/src/DocHandle.js +405 -0
  34. package/dist/src/DocUrl.d.ts +49 -0
  35. package/dist/src/DocUrl.d.ts.map +1 -0
  36. package/dist/src/DocUrl.js +72 -0
  37. package/dist/src/EphemeralData.d.ts +19 -0
  38. package/dist/src/EphemeralData.d.ts.map +1 -0
  39. package/dist/src/EphemeralData.js +1 -0
  40. package/dist/src/Repo.d.ts +74 -0
  41. package/dist/src/Repo.d.ts.map +1 -0
  42. package/dist/src/Repo.js +208 -0
  43. package/dist/src/helpers/arraysAreEqual.d.ts +2 -0
  44. package/dist/src/helpers/arraysAreEqual.d.ts.map +1 -0
  45. package/dist/src/helpers/arraysAreEqual.js +2 -0
  46. package/dist/src/helpers/cbor.d.ts +4 -0
  47. package/dist/src/helpers/cbor.d.ts.map +1 -0
  48. package/dist/src/helpers/cbor.js +8 -0
  49. package/dist/src/helpers/eventPromise.d.ts +11 -0
  50. package/dist/src/helpers/eventPromise.d.ts.map +1 -0
  51. package/dist/src/helpers/eventPromise.js +7 -0
  52. package/dist/src/helpers/headsAreSame.d.ts +2 -0
  53. package/dist/src/helpers/headsAreSame.d.ts.map +1 -0
  54. package/dist/src/helpers/headsAreSame.js +4 -0
  55. package/dist/src/helpers/mergeArrays.d.ts +2 -0
  56. package/dist/src/helpers/mergeArrays.d.ts.map +1 -0
  57. package/dist/src/helpers/mergeArrays.js +15 -0
  58. package/dist/src/helpers/pause.d.ts +6 -0
  59. package/dist/src/helpers/pause.d.ts.map +1 -0
  60. package/dist/src/helpers/pause.js +10 -0
  61. package/dist/src/helpers/tests/network-adapter-tests.d.ts +21 -0
  62. package/dist/src/helpers/tests/network-adapter-tests.d.ts.map +1 -0
  63. package/dist/src/helpers/tests/network-adapter-tests.js +122 -0
  64. package/dist/src/helpers/withTimeout.d.ts +12 -0
  65. package/dist/src/helpers/withTimeout.d.ts.map +1 -0
  66. package/dist/src/helpers/withTimeout.js +24 -0
  67. package/dist/src/index.d.ts +53 -0
  68. package/dist/src/index.d.ts.map +1 -0
  69. package/dist/src/index.js +40 -0
  70. package/dist/src/network/NetworkAdapter.d.ts +26 -0
  71. package/dist/src/network/NetworkAdapter.d.ts.map +1 -0
  72. package/dist/src/network/NetworkAdapter.js +4 -0
  73. package/dist/src/network/NetworkSubsystem.d.ts +23 -0
  74. package/dist/src/network/NetworkSubsystem.d.ts.map +1 -0
  75. package/dist/src/network/NetworkSubsystem.js +120 -0
  76. package/dist/src/network/messages.d.ts +85 -0
  77. package/dist/src/network/messages.d.ts.map +1 -0
  78. package/dist/src/network/messages.js +23 -0
  79. package/dist/src/storage/StorageAdapter.d.ts +14 -0
  80. package/dist/src/storage/StorageAdapter.d.ts.map +1 -0
  81. package/dist/src/storage/StorageAdapter.js +1 -0
  82. package/dist/src/storage/StorageSubsystem.d.ts +12 -0
  83. package/dist/src/storage/StorageSubsystem.d.ts.map +1 -0
  84. package/dist/src/storage/StorageSubsystem.js +145 -0
  85. package/dist/src/synchronizer/CollectionSynchronizer.d.ts +25 -0
  86. package/dist/src/synchronizer/CollectionSynchronizer.d.ts.map +1 -0
  87. package/dist/src/synchronizer/CollectionSynchronizer.js +106 -0
  88. package/dist/src/synchronizer/DocSynchronizer.d.ts +29 -0
  89. package/dist/src/synchronizer/DocSynchronizer.d.ts.map +1 -0
  90. package/dist/src/synchronizer/DocSynchronizer.js +263 -0
  91. package/dist/src/synchronizer/Synchronizer.d.ts +9 -0
  92. package/dist/src/synchronizer/Synchronizer.d.ts.map +1 -0
  93. package/dist/src/synchronizer/Synchronizer.js +2 -0
  94. package/dist/src/types.d.ts +16 -0
  95. package/dist/src/types.d.ts.map +1 -0
  96. package/dist/src/types.js +1 -0
  97. package/dist/storage/StorageAdapter.d.ts +9 -0
  98. package/dist/storage/StorageAdapter.d.ts.map +1 -1
  99. package/dist/storage/StorageAdapter.js +33 -0
  100. package/dist/storage/StorageSubsystem.d.ts +12 -2
  101. package/dist/storage/StorageSubsystem.d.ts.map +1 -1
  102. package/dist/storage/StorageSubsystem.js +42 -100
  103. package/dist/synchronizer/CollectionSynchronizer.d.ts +4 -2
  104. package/dist/synchronizer/CollectionSynchronizer.d.ts.map +1 -1
  105. package/dist/synchronizer/CollectionSynchronizer.js +28 -15
  106. package/dist/synchronizer/DocSynchronizer.d.ts +6 -5
  107. package/dist/synchronizer/DocSynchronizer.d.ts.map +1 -1
  108. package/dist/synchronizer/DocSynchronizer.js +76 -178
  109. package/dist/synchronizer/Synchronizer.d.ts +11 -0
  110. package/dist/synchronizer/Synchronizer.d.ts.map +1 -1
  111. package/dist/test/CollectionSynchronizer.test.d.ts +2 -0
  112. package/dist/test/CollectionSynchronizer.test.d.ts.map +1 -0
  113. package/dist/test/CollectionSynchronizer.test.js +57 -0
  114. package/dist/test/DocHandle.test.d.ts +2 -0
  115. package/dist/test/DocHandle.test.d.ts.map +1 -0
  116. package/dist/test/DocHandle.test.js +238 -0
  117. package/dist/test/DocSynchronizer.test.d.ts +2 -0
  118. package/dist/test/DocSynchronizer.test.d.ts.map +1 -0
  119. package/dist/test/DocSynchronizer.test.js +111 -0
  120. package/dist/test/Network.test.d.ts +2 -0
  121. package/dist/test/Network.test.d.ts.map +1 -0
  122. package/dist/test/Network.test.js +11 -0
  123. package/dist/test/Repo.test.d.ts +2 -0
  124. package/dist/test/Repo.test.d.ts.map +1 -0
  125. package/dist/test/Repo.test.js +568 -0
  126. package/dist/test/StorageSubsystem.test.d.ts +2 -0
  127. package/dist/test/StorageSubsystem.test.d.ts.map +1 -0
  128. package/dist/test/StorageSubsystem.test.js +56 -0
  129. package/dist/test/helpers/DummyNetworkAdapter.d.ts +9 -0
  130. package/dist/test/helpers/DummyNetworkAdapter.d.ts.map +1 -0
  131. package/dist/test/helpers/DummyNetworkAdapter.js +15 -0
  132. package/dist/test/helpers/DummyStorageAdapter.d.ts +16 -0
  133. package/dist/test/helpers/DummyStorageAdapter.d.ts.map +1 -0
  134. package/dist/test/helpers/DummyStorageAdapter.js +33 -0
  135. package/dist/test/helpers/generate-large-object.d.ts +5 -0
  136. package/dist/test/helpers/generate-large-object.d.ts.map +1 -0
  137. package/dist/test/helpers/generate-large-object.js +9 -0
  138. package/dist/test/helpers/getRandomItem.d.ts +2 -0
  139. package/dist/test/helpers/getRandomItem.d.ts.map +1 -0
  140. package/dist/test/helpers/getRandomItem.js +4 -0
  141. package/dist/test/types.d.ts +4 -0
  142. package/dist/test/types.d.ts.map +1 -0
  143. package/dist/test/types.js +1 -0
  144. package/package.json +3 -3
  145. package/src/CollectionHandle.ts +54 -0
  146. package/src/DocHandle.ts +133 -4
  147. package/src/Repo.ts +192 -183
  148. package/src/ferigan.ts +184 -0
  149. package/src/helpers/tests/storage-adapter-tests.ts +31 -62
  150. package/src/index.ts +2 -0
  151. package/src/network/NetworkSubsystem.ts +4 -0
  152. package/src/network/messages.ts +11 -2
  153. package/src/storage/StorageAdapter.ts +42 -0
  154. package/src/storage/StorageSubsystem.ts +59 -119
  155. package/src/synchronizer/CollectionSynchronizer.ts +34 -26
  156. package/src/synchronizer/DocSynchronizer.ts +84 -231
  157. package/src/synchronizer/Synchronizer.ts +14 -0
  158. package/test/CollectionSynchronizer.test.ts +4 -2
  159. package/test/DocHandle.test.ts +141 -0
  160. package/test/DocSynchronizer.test.ts +6 -1
  161. package/test/RemoteHeadsSubscriptions.test.ts +1 -1
  162. package/test/Repo.test.ts +225 -117
  163. package/test/StorageSubsystem.test.ts +20 -16
  164. package/test/remoteHeads.test.ts +1 -1
@@ -0,0 +1,33 @@
1
+ export class DummyStorageAdapter {
2
+ #data = {}
3
+ #keyToString(key) {
4
+ return key.join(".")
5
+ }
6
+ #stringToKey(key) {
7
+ return key.split(".")
8
+ }
9
+ async loadRange(keyPrefix) {
10
+ const range = Object.entries(this.#data)
11
+ .filter(([key, _]) => key.startsWith(this.#keyToString(keyPrefix)))
12
+ .map(([key, data]) => ({ key: this.#stringToKey(key), data }))
13
+ return Promise.resolve(range)
14
+ }
15
+ async removeRange(keyPrefix) {
16
+ Object.entries(this.#data)
17
+ .filter(([key, _]) => key.startsWith(this.#keyToString(keyPrefix)))
18
+ .forEach(([key, _]) => delete this.#data[key])
19
+ }
20
+ async load(key) {
21
+ return new Promise(resolve => resolve(this.#data[this.#keyToString(key)]))
22
+ }
23
+ async save(key, binary) {
24
+ this.#data[this.#keyToString(key)] = binary
25
+ return Promise.resolve()
26
+ }
27
+ async remove(key) {
28
+ delete this.#data[this.#keyToString(key)]
29
+ }
30
+ keys() {
31
+ return Object.keys(this.#data)
32
+ }
33
+ }
@@ -0,0 +1,5 @@
1
+ export type LargeObject = {
2
+ [key: string]: number
3
+ }
4
+ export declare function generateLargeObject(size: number): LargeObject
5
+ //# sourceMappingURL=generate-large-object.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-large-object.d.ts","sourceRoot":"","sources":["../../../test/helpers/generate-large-object.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,CAAA;AAEnD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAU7D"}
@@ -0,0 +1,9 @@
1
+ export function generateLargeObject(size) {
2
+ const largeObject = {}
3
+ for (let i = 0; i < size; i++) {
4
+ const key = `key${i}`
5
+ const value = Math.random()
6
+ largeObject[key] = value
7
+ }
8
+ return largeObject
9
+ }
@@ -0,0 +1,2 @@
1
+ export declare const getRandomItem: <T>(obj: T[]) => T
2
+ //# sourceMappingURL=getRandomItem.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getRandomItem.d.ts","sourceRoot":"","sources":["../../../test/helpers/getRandomItem.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,aAAa,oBAGzB,CAAA"}
@@ -0,0 +1,4 @@
1
+ export const getRandomItem = obj => {
2
+ const index = Math.floor(Math.random() * obj.length)
3
+ return obj[index]
4
+ }
@@ -0,0 +1,4 @@
1
+ export interface TestDoc {
2
+ foo: string
3
+ }
4
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../test/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,OAAO;IACtB,GAAG,EAAE,MAAM,CAAA;CACZ"}
@@ -0,0 +1 @@
1
+ export {}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@automerge/automerge-repo",
3
- "version": "2.0.0-alpha.6",
3
+ "version": "2.0.0-collectionsync-alpha.1",
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>",
@@ -23,7 +23,7 @@
23
23
  "vite": "^5.0.8"
24
24
  },
25
25
  "dependencies": {
26
- "@automerge/automerge": "^2.2.8",
26
+ "@automerge/automerge": "3.0.0-collectionsync-alpha.1",
27
27
  "bs58check": "^3.0.1",
28
28
  "cbor-x": "^1.3.0",
29
29
  "debug": "^4.3.4",
@@ -60,5 +60,5 @@
60
60
  "publishConfig": {
61
61
  "access": "public"
62
62
  },
63
- "gitHead": "87353a94d2e5d8facc1db359d9e6fa74e2ab8888"
63
+ "gitHead": "0a639a7d57bcee4e0a87890e6592b9582c2a5d6f"
64
64
  }
@@ -0,0 +1,54 @@
1
+ import { EventEmitter } from "eventemitter3"
2
+ import { Ferigan, Index } from "./ferigan.js"
3
+ import { AutomergeUrl, DocumentId } from "./types.js"
4
+ import { next as A } from "@automerge/automerge"
5
+ import { parseAutomergeUrl } from "./AutomergeUrl.js"
6
+
7
+ export type CollectionHandleEvents = {
8
+ doc_added: (url: AutomergeUrl) => void
9
+ }
10
+
11
+ export class CollectionHandle extends EventEmitter<CollectionHandleEvents> {
12
+ //#index: Index
13
+ #beelay: A.beelay.Beelay
14
+ //#ferigan: Ferigan
15
+ #rootId: DocumentId
16
+ #rootUrl: AutomergeUrl
17
+ #entries: AutomergeUrl[] = []
18
+
19
+ get index(): Index {
20
+ return {
21
+ rootUrl: this.#rootUrl,
22
+ entries: this.#entries,
23
+ }
24
+ }
25
+
26
+ constructor(
27
+ belay: A.beelay.Beelay,
28
+ rootUrl: AutomergeUrl,
29
+ entries: AutomergeUrl[]
30
+ ) {
31
+ super()
32
+ this.#rootUrl = rootUrl
33
+ this.#rootId = parseAutomergeUrl(rootUrl).documentId
34
+ this.#beelay = belay
35
+ this.#entries = entries
36
+
37
+ //this.#ferigan.on("indexChanged", ({indexUrl, change}) => {
38
+ //if (indexUrl != this.#index.rootUrl) {
39
+ //return
40
+ //}
41
+
42
+ //if (change.type === "add") {
43
+ //this.#index.entries.push(change.url)
44
+ //this.emit("doc_added", change.url as AutomergeUrl)
45
+ //}
46
+ //})
47
+ }
48
+
49
+ add(url: AutomergeUrl): void {
50
+ this.#entries.push(url)
51
+ let docId = parseAutomergeUrl(url).documentId
52
+ this.#beelay.addLink({ from: this.#rootId, to: docId })
53
+ }
54
+ }
package/src/DocHandle.ts CHANGED
@@ -72,6 +72,9 @@ export class DocHandle<T> extends EventEmitter<DocHandleEvents<T>> {
72
72
  this.emit("delete", { handle: this })
73
73
  return { doc: A.init() }
74
74
  }),
75
+ onUnload: assign(() => {
76
+ return { doc: A.init() }
77
+ }),
75
78
  onUnavailable: () => {
76
79
  this.emit("unavailable", { handle: this })
77
80
  },
@@ -86,6 +89,7 @@ export class DocHandle<T> extends EventEmitter<DocHandleEvents<T>> {
86
89
  context: { documentId, doc },
87
90
  on: {
88
91
  UPDATE: { actions: "onUpdate" },
92
+ UNLOAD: ".unloaded",
89
93
  DELETE: ".deleted",
90
94
  },
91
95
  states: {
@@ -113,6 +117,12 @@ export class DocHandle<T> extends EventEmitter<DocHandleEvents<T>> {
113
117
  on: { DOC_READY: "ready" },
114
118
  },
115
119
  ready: {},
120
+ unloaded: {
121
+ entry: "onUnload",
122
+ on: {
123
+ RELOAD: "loading",
124
+ },
125
+ },
116
126
  deleted: { entry: "onDelete", type: "final" },
117
127
  },
118
128
  })
@@ -131,7 +141,7 @@ export class DocHandle<T> extends EventEmitter<DocHandleEvents<T>> {
131
141
 
132
142
  // Start the machine, and send a create or find event to get things going
133
143
  this.#machine.start()
134
- this.#machine.send({ type: BEGIN })
144
+ this.begin()
135
145
  }
136
146
 
137
147
  // PRIVATE
@@ -203,6 +213,14 @@ export class DocHandle<T> extends EventEmitter<DocHandleEvents<T>> {
203
213
  */
204
214
  isReady = () => this.inState(["ready"])
205
215
 
216
+ /**
217
+ * @returns true if the document has been unloaded.
218
+ *
219
+ * Unloaded documents are freed from memory but not removed from local storage. It's not currently
220
+ * possible at runtime to reload an unloaded document.
221
+ */
222
+ isUnloaded = () => this.inState(["unloaded"])
223
+
206
224
  /**
207
225
  * @returns true if the document has been marked as deleted.
208
226
  *
@@ -291,6 +309,94 @@ export class DocHandle<T> extends EventEmitter<DocHandleEvents<T>> {
291
309
  return A.getHeads(this.#doc)
292
310
  }
293
311
 
312
+ begin() {
313
+ this.#machine.send({ type: BEGIN })
314
+ }
315
+
316
+ /**
317
+ * Creates a fixed "view" of an automerge document at the given point in time represented
318
+ * by the `heads` passed in. The return value is the same type as docSync() and will return
319
+ * undefined if the object hasn't finished loading.
320
+ *
321
+ * @remarks
322
+ * A point-in-time in an automerge document is an *array* of heads since there may be
323
+ * concurrent edits. This API just returns a topologically sorted history of all edits
324
+ * so every previous entry will be (in some sense) before later ones, but the set of all possible
325
+ * history views would be quite large under concurrency (every thing in each branch against each other).
326
+ * There might be a clever way to think about this, but we haven't found it yet, so for now at least
327
+ * we present a single traversable view which excludes concurrency.
328
+ * @returns The individual heads for every change in the document.
329
+ */
330
+ history(): A.Heads[] | undefined {
331
+ if (!this.isReady()) {
332
+ return undefined
333
+ }
334
+ // This just returns all the heads as individual strings.
335
+
336
+ return A.topoHistoryTraversal(this.#doc).map(h => [h]) as A.Heads[]
337
+ }
338
+
339
+ /**
340
+ * Creates a fixed "view" of an automerge document at the given point in time represented
341
+ * by the `heads` passed in. The return value is the same type as docSync() and will return
342
+ * undefined if the object hasn't finished loading.
343
+ *
344
+ * @remarks
345
+ * Note that our Typescript types do not consider change over time and the current version
346
+ * of Automerge doesn't check types at runtime, so if you go back to an old set of heads
347
+ * that doesn't match the heads here, Typescript will not save you.
348
+ *
349
+ * @returns An Automerge.Doc<T> at the point in time.
350
+ */
351
+ view(heads: A.Heads): A.Doc<T> | undefined {
352
+ if (!this.isReady()) {
353
+ return undefined
354
+ }
355
+ return A.view(this.#doc, heads)
356
+ }
357
+
358
+ /**
359
+ * Returns a set of Patch operations that will move a materialized document from one state to another
360
+ * if applied.
361
+ *
362
+ * @remarks
363
+ * We allow specifying both a from/to heads or just a single comparison point, in which case
364
+ * the base will be the current document heads.
365
+ *
366
+ * @returns Automerge patches that go from one document state to the other. Use view() to get the full state.
367
+ */
368
+ diff(first: A.Heads, second?: A.Heads): A.Patch[] | undefined {
369
+ if (!this.isReady()) {
370
+ return undefined
371
+ }
372
+ // We allow only one set of heads to be specified, in which case we use the doc's heads
373
+ const from = second ? first : this.heads() || [] // because we guard above this should always have useful data
374
+ const to = second ? second : first
375
+ return A.diff(this.#doc, from, to)
376
+ }
377
+
378
+ /**
379
+ * `metadata(head?)` allows you to look at the metadata for a change
380
+ * this can be used to build history graphs to find commit messages and edit times.
381
+ * this interface.
382
+ *
383
+ * @remarks
384
+ * I'm really not convinced this is the right way to surface this information so
385
+ * I'm leaving this API "hidden".
386
+ *
387
+ * @hidden
388
+ */
389
+ metadata(change?: string): A.DecodedChange | undefined {
390
+ if (!this.isReady()) {
391
+ return undefined
392
+ }
393
+ if (!change) {
394
+ change = this.heads()![0]
395
+ }
396
+ // we return undefined instead of null by convention in this API
397
+ return A.inspectChange(this.#doc, change) || undefined
398
+ }
399
+
294
400
  /**
295
401
  * `update` is called any time we have a new document state; could be
296
402
  * from a local change, a remote change, or a new document from storage.
@@ -421,6 +527,16 @@ export class DocHandle<T> extends EventEmitter<DocHandleEvents<T>> {
421
527
  if (this.#state === "loading") this.#machine.send({ type: REQUEST })
422
528
  }
423
529
 
530
+ /** Called by the repo to free memory used by the document. */
531
+ unload() {
532
+ this.#machine.send({ type: UNLOAD })
533
+ }
534
+
535
+ /** Called by the repo to reuse an unloaded handle. */
536
+ reload() {
537
+ this.#machine.send({ type: RELOAD })
538
+ }
539
+
424
540
  /** Called by the repo when the document is deleted. */
425
541
  delete() {
426
542
  this.#machine.send({ type: DELETE })
@@ -543,6 +659,8 @@ export const HandleState = {
543
659
  REQUESTING: "requesting",
544
660
  /** The document is available */
545
661
  READY: "ready",
662
+ /** The document has been unloaded from the handle, to free memory usage */
663
+ UNLOADED: "unloaded",
546
664
  /** The document has been deleted from the repo */
547
665
  DELETED: "deleted",
548
666
  /** The document was not available in storage or from any connected peers */
@@ -550,8 +668,15 @@ export const HandleState = {
550
668
  } as const
551
669
  export type HandleState = (typeof HandleState)[keyof typeof HandleState]
552
670
 
553
- export const { IDLE, LOADING, REQUESTING, READY, DELETED, UNAVAILABLE } =
554
- HandleState
671
+ export const {
672
+ IDLE,
673
+ LOADING,
674
+ REQUESTING,
675
+ READY,
676
+ UNLOADED,
677
+ DELETED,
678
+ UNAVAILABLE,
679
+ } = HandleState
555
680
 
556
681
  // context
557
682
 
@@ -571,14 +696,18 @@ type DocHandleEvent<T> =
571
696
  type: typeof UPDATE
572
697
  payload: { callback: (doc: A.Doc<T>) => A.Doc<T> }
573
698
  }
574
- | { type: typeof TIMEOUT }
699
+ | { type: typeof UNLOAD }
700
+ | { type: typeof RELOAD }
575
701
  | { type: typeof DELETE }
702
+ | { type: typeof TIMEOUT }
576
703
  | { type: typeof DOC_UNAVAILABLE }
577
704
 
578
705
  const BEGIN = "BEGIN"
579
706
  const REQUEST = "REQUEST"
580
707
  const DOC_READY = "DOC_READY"
581
708
  const UPDATE = "UPDATE"
709
+ const UNLOAD = "UNLOAD"
710
+ const RELOAD = "RELOAD"
582
711
  const DELETE = "DELETE"
583
712
  const TIMEOUT = "TIMEOUT"
584
713
  const DOC_UNAVAILABLE = "DOC_UNAVAILABLE"