@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.
- package/dist/CollectionHandle.d.ts +14 -0
- package/dist/CollectionHandle.d.ts.map +1 -0
- package/dist/CollectionHandle.js +37 -0
- package/dist/DocHandle.d.ts +67 -2
- package/dist/DocHandle.d.ts.map +1 -1
- package/dist/DocHandle.js +113 -2
- package/dist/DocUrl.d.ts +47 -0
- package/dist/DocUrl.d.ts.map +1 -0
- package/dist/DocUrl.js +72 -0
- package/dist/EphemeralData.d.ts +20 -0
- package/dist/EphemeralData.d.ts.map +1 -0
- package/dist/EphemeralData.js +1 -0
- package/dist/Repo.d.ts +28 -7
- package/dist/Repo.d.ts.map +1 -1
- package/dist/Repo.js +142 -143
- package/dist/ferigan.d.ts +51 -0
- package/dist/ferigan.d.ts.map +1 -0
- package/dist/ferigan.js +98 -0
- package/dist/helpers/tests/storage-adapter-tests.d.ts +2 -2
- package/dist/helpers/tests/storage-adapter-tests.d.ts.map +1 -1
- package/dist/helpers/tests/storage-adapter-tests.js +19 -39
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/network/NetworkSubsystem.d.ts +1 -0
- package/dist/network/NetworkSubsystem.d.ts.map +1 -1
- package/dist/network/NetworkSubsystem.js +3 -0
- package/dist/network/messages.d.ts +7 -1
- package/dist/network/messages.d.ts.map +1 -1
- package/dist/network/messages.js +2 -1
- package/dist/src/DocHandle.d.ts +182 -0
- package/dist/src/DocHandle.d.ts.map +1 -0
- package/dist/src/DocHandle.js +405 -0
- package/dist/src/DocUrl.d.ts +49 -0
- package/dist/src/DocUrl.d.ts.map +1 -0
- package/dist/src/DocUrl.js +72 -0
- package/dist/src/EphemeralData.d.ts +19 -0
- package/dist/src/EphemeralData.d.ts.map +1 -0
- package/dist/src/EphemeralData.js +1 -0
- package/dist/src/Repo.d.ts +74 -0
- package/dist/src/Repo.d.ts.map +1 -0
- package/dist/src/Repo.js +208 -0
- package/dist/src/helpers/arraysAreEqual.d.ts +2 -0
- package/dist/src/helpers/arraysAreEqual.d.ts.map +1 -0
- package/dist/src/helpers/arraysAreEqual.js +2 -0
- package/dist/src/helpers/cbor.d.ts +4 -0
- package/dist/src/helpers/cbor.d.ts.map +1 -0
- package/dist/src/helpers/cbor.js +8 -0
- package/dist/src/helpers/eventPromise.d.ts +11 -0
- package/dist/src/helpers/eventPromise.d.ts.map +1 -0
- package/dist/src/helpers/eventPromise.js +7 -0
- package/dist/src/helpers/headsAreSame.d.ts +2 -0
- package/dist/src/helpers/headsAreSame.d.ts.map +1 -0
- package/dist/src/helpers/headsAreSame.js +4 -0
- package/dist/src/helpers/mergeArrays.d.ts +2 -0
- package/dist/src/helpers/mergeArrays.d.ts.map +1 -0
- package/dist/src/helpers/mergeArrays.js +15 -0
- package/dist/src/helpers/pause.d.ts +6 -0
- package/dist/src/helpers/pause.d.ts.map +1 -0
- package/dist/src/helpers/pause.js +10 -0
- package/dist/src/helpers/tests/network-adapter-tests.d.ts +21 -0
- package/dist/src/helpers/tests/network-adapter-tests.d.ts.map +1 -0
- package/dist/src/helpers/tests/network-adapter-tests.js +122 -0
- package/dist/src/helpers/withTimeout.d.ts +12 -0
- package/dist/src/helpers/withTimeout.d.ts.map +1 -0
- package/dist/src/helpers/withTimeout.js +24 -0
- package/dist/src/index.d.ts +53 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +40 -0
- package/dist/src/network/NetworkAdapter.d.ts +26 -0
- package/dist/src/network/NetworkAdapter.d.ts.map +1 -0
- package/dist/src/network/NetworkAdapter.js +4 -0
- package/dist/src/network/NetworkSubsystem.d.ts +23 -0
- package/dist/src/network/NetworkSubsystem.d.ts.map +1 -0
- package/dist/src/network/NetworkSubsystem.js +120 -0
- package/dist/src/network/messages.d.ts +85 -0
- package/dist/src/network/messages.d.ts.map +1 -0
- package/dist/src/network/messages.js +23 -0
- package/dist/src/storage/StorageAdapter.d.ts +14 -0
- package/dist/src/storage/StorageAdapter.d.ts.map +1 -0
- package/dist/src/storage/StorageAdapter.js +1 -0
- package/dist/src/storage/StorageSubsystem.d.ts +12 -0
- package/dist/src/storage/StorageSubsystem.d.ts.map +1 -0
- package/dist/src/storage/StorageSubsystem.js +145 -0
- package/dist/src/synchronizer/CollectionSynchronizer.d.ts +25 -0
- package/dist/src/synchronizer/CollectionSynchronizer.d.ts.map +1 -0
- package/dist/src/synchronizer/CollectionSynchronizer.js +106 -0
- package/dist/src/synchronizer/DocSynchronizer.d.ts +29 -0
- package/dist/src/synchronizer/DocSynchronizer.d.ts.map +1 -0
- package/dist/src/synchronizer/DocSynchronizer.js +263 -0
- package/dist/src/synchronizer/Synchronizer.d.ts +9 -0
- package/dist/src/synchronizer/Synchronizer.d.ts.map +1 -0
- package/dist/src/synchronizer/Synchronizer.js +2 -0
- package/dist/src/types.d.ts +16 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +1 -0
- package/dist/storage/StorageAdapter.d.ts +9 -0
- package/dist/storage/StorageAdapter.d.ts.map +1 -1
- package/dist/storage/StorageAdapter.js +33 -0
- package/dist/storage/StorageSubsystem.d.ts +12 -2
- package/dist/storage/StorageSubsystem.d.ts.map +1 -1
- package/dist/storage/StorageSubsystem.js +42 -100
- package/dist/synchronizer/CollectionSynchronizer.d.ts +4 -2
- package/dist/synchronizer/CollectionSynchronizer.d.ts.map +1 -1
- package/dist/synchronizer/CollectionSynchronizer.js +28 -15
- package/dist/synchronizer/DocSynchronizer.d.ts +6 -5
- package/dist/synchronizer/DocSynchronizer.d.ts.map +1 -1
- package/dist/synchronizer/DocSynchronizer.js +76 -178
- package/dist/synchronizer/Synchronizer.d.ts +11 -0
- package/dist/synchronizer/Synchronizer.d.ts.map +1 -1
- package/dist/test/CollectionSynchronizer.test.d.ts +2 -0
- package/dist/test/CollectionSynchronizer.test.d.ts.map +1 -0
- package/dist/test/CollectionSynchronizer.test.js +57 -0
- package/dist/test/DocHandle.test.d.ts +2 -0
- package/dist/test/DocHandle.test.d.ts.map +1 -0
- package/dist/test/DocHandle.test.js +238 -0
- package/dist/test/DocSynchronizer.test.d.ts +2 -0
- package/dist/test/DocSynchronizer.test.d.ts.map +1 -0
- package/dist/test/DocSynchronizer.test.js +111 -0
- package/dist/test/Network.test.d.ts +2 -0
- package/dist/test/Network.test.d.ts.map +1 -0
- package/dist/test/Network.test.js +11 -0
- package/dist/test/Repo.test.d.ts +2 -0
- package/dist/test/Repo.test.d.ts.map +1 -0
- package/dist/test/Repo.test.js +568 -0
- package/dist/test/StorageSubsystem.test.d.ts +2 -0
- package/dist/test/StorageSubsystem.test.d.ts.map +1 -0
- package/dist/test/StorageSubsystem.test.js +56 -0
- package/dist/test/helpers/DummyNetworkAdapter.d.ts +9 -0
- package/dist/test/helpers/DummyNetworkAdapter.d.ts.map +1 -0
- package/dist/test/helpers/DummyNetworkAdapter.js +15 -0
- package/dist/test/helpers/DummyStorageAdapter.d.ts +16 -0
- package/dist/test/helpers/DummyStorageAdapter.d.ts.map +1 -0
- package/dist/test/helpers/DummyStorageAdapter.js +33 -0
- package/dist/test/helpers/generate-large-object.d.ts +5 -0
- package/dist/test/helpers/generate-large-object.d.ts.map +1 -0
- package/dist/test/helpers/generate-large-object.js +9 -0
- package/dist/test/helpers/getRandomItem.d.ts +2 -0
- package/dist/test/helpers/getRandomItem.d.ts.map +1 -0
- package/dist/test/helpers/getRandomItem.js +4 -0
- package/dist/test/types.d.ts +4 -0
- package/dist/test/types.d.ts.map +1 -0
- package/dist/test/types.js +1 -0
- package/package.json +3 -3
- package/src/CollectionHandle.ts +54 -0
- package/src/DocHandle.ts +133 -4
- package/src/Repo.ts +192 -183
- package/src/ferigan.ts +184 -0
- package/src/helpers/tests/storage-adapter-tests.ts +31 -62
- package/src/index.ts +2 -0
- package/src/network/NetworkSubsystem.ts +4 -0
- package/src/network/messages.ts +11 -2
- package/src/storage/StorageAdapter.ts +42 -0
- package/src/storage/StorageSubsystem.ts +59 -119
- package/src/synchronizer/CollectionSynchronizer.ts +34 -26
- package/src/synchronizer/DocSynchronizer.ts +84 -231
- package/src/synchronizer/Synchronizer.ts +14 -0
- package/test/CollectionSynchronizer.test.ts +4 -2
- package/test/DocHandle.test.ts +141 -0
- package/test/DocSynchronizer.test.ts +6 -1
- package/test/RemoteHeadsSubscriptions.test.ts +1 -1
- package/test/Repo.test.ts +225 -117
- package/test/StorageSubsystem.test.ts +20 -16
- 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 @@
|
|
|
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 @@
|
|
|
1
|
+
{"version":3,"file":"getRandomItem.d.ts","sourceRoot":"","sources":["../../../test/helpers/getRandomItem.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,aAAa,oBAGzB,CAAA"}
|
|
@@ -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.
|
|
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": "
|
|
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": "
|
|
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
|
|
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 {
|
|
554
|
-
|
|
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
|
|
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"
|