@automerge/automerge-repo 2.0.0-alpha.20 → 2.0.0-alpha.22
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/README.md +5 -6
- package/dist/DocHandle.d.ts +12 -15
- package/dist/DocHandle.d.ts.map +1 -1
- package/dist/DocHandle.js +22 -32
- package/dist/FindProgress.d.ts +30 -0
- package/dist/FindProgress.d.ts.map +1 -0
- package/dist/FindProgress.js +1 -0
- package/dist/Repo.d.ts +9 -4
- package/dist/Repo.d.ts.map +1 -1
- package/dist/Repo.js +166 -69
- package/dist/helpers/abortable.d.ts +39 -0
- package/dist/helpers/abortable.d.ts.map +1 -0
- package/dist/helpers/abortable.js +45 -0
- package/dist/helpers/tests/network-adapter-tests.d.ts.map +1 -1
- package/dist/helpers/tests/network-adapter-tests.js +13 -13
- package/dist/synchronizer/CollectionSynchronizer.d.ts +2 -1
- package/dist/synchronizer/CollectionSynchronizer.d.ts.map +1 -1
- package/dist/synchronizer/CollectionSynchronizer.js +18 -14
- package/dist/synchronizer/DocSynchronizer.d.ts +3 -2
- package/dist/synchronizer/DocSynchronizer.d.ts.map +1 -1
- package/dist/synchronizer/DocSynchronizer.js +16 -8
- package/fuzz/fuzz.ts +3 -3
- package/package.json +2 -2
- package/src/DocHandle.ts +26 -33
- package/src/FindProgress.ts +48 -0
- package/src/Repo.ts +187 -67
- package/src/helpers/abortable.ts +61 -0
- package/src/helpers/tests/network-adapter-tests.ts +14 -13
- package/src/synchronizer/CollectionSynchronizer.ts +18 -14
- package/src/synchronizer/DocSynchronizer.ts +19 -9
- package/test/CollectionSynchronizer.test.ts +4 -4
- package/test/DocHandle.test.ts +26 -73
- package/test/Repo.test.ts +171 -210
- package/test/remoteHeads.test.ts +27 -12
package/README.md
CHANGED
|
@@ -40,9 +40,9 @@ A `Repo` exposes these methods:
|
|
|
40
40
|
|
|
41
41
|
- `create<T>(initialValue: T?)`
|
|
42
42
|
Creates a new `Automerge.Doc` and returns a `DocHandle` for it. Accepts an optional initial value for the document. Produces an empty document (potentially violating the type!) otherwise.
|
|
43
|
-
- `find<T>(docId: DocumentId)
|
|
43
|
+
- `find<T>(docId: DocumentId): Promise<DocHandle<T>>`
|
|
44
44
|
Looks up a given document either on the local machine or (if necessary) over any configured
|
|
45
|
-
networks.
|
|
45
|
+
networks. Returns a promise that resolves when the document is loaded or throws if load fails.
|
|
46
46
|
- `delete(docId: DocumentId)`
|
|
47
47
|
Deletes the local copy of a document from the local cache and local storage. _This does not currently delete the document from any other peers_.
|
|
48
48
|
- `import(binary: Uint8Array)`
|
|
@@ -57,10 +57,9 @@ A `Repo` exposes these methods:
|
|
|
57
57
|
A `DocHandle` is a wrapper around an `Automerge.Doc`. Its primary function is to dispatch changes to
|
|
58
58
|
the document.
|
|
59
59
|
|
|
60
|
-
- `handle.doc()`
|
|
61
|
-
Returns a `
|
|
62
|
-
|
|
63
|
-
returning a value.
|
|
60
|
+
- `handle.doc()`
|
|
61
|
+
Returns a `Doc<T>` that will contain the current value of the document.
|
|
62
|
+
Throws an error if the document is deleted.
|
|
64
63
|
- `handle.change((doc: T) => void)`
|
|
65
64
|
Calls the provided callback with an instrumented mutable object
|
|
66
65
|
representing the document. Any changes made to the document will be recorded and distributed to
|
package/dist/DocHandle.d.ts
CHANGED
|
@@ -70,29 +70,27 @@ export declare class DocHandle<T> extends EventEmitter<DocHandleEvents<T>> {
|
|
|
70
70
|
* This is the recommended way to access a handle's document. Note that this waits for the handle
|
|
71
71
|
* to be ready if necessary. If loading (or synchronization) fails, this will never resolve.
|
|
72
72
|
*/
|
|
73
|
-
|
|
73
|
+
legacyAsyncDoc(
|
|
74
74
|
/** states to wait for, such as "LOADING". mostly for internal use. */
|
|
75
75
|
awaitStates?: HandleState[]): Promise<A.Doc<T> | undefined>;
|
|
76
76
|
/**
|
|
77
|
-
*
|
|
78
|
-
* undefined. Consider using `await handle.doc()` instead. Check `isReady()`, or use `whenReady()`
|
|
79
|
-
* if you want to make sure loading is complete first.
|
|
77
|
+
* Returns the current state of the Automerge document this handle manages.
|
|
80
78
|
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
79
|
+
* @returns the current document
|
|
80
|
+
* @throws on deleted and unavailable documents
|
|
83
81
|
*
|
|
84
|
-
* Note that `undefined` is not a valid Automerge document, so the return from this function is
|
|
85
|
-
* unambigous.
|
|
86
|
-
*
|
|
87
|
-
* @returns the current document, or undefined if the document is not ready.
|
|
88
82
|
*/
|
|
89
|
-
|
|
83
|
+
doc(): A.Doc<T>;
|
|
84
|
+
/**
|
|
85
|
+
*
|
|
86
|
+
* @deprecated */
|
|
87
|
+
docSync(): A.Doc<T>;
|
|
90
88
|
/**
|
|
91
89
|
* Returns the current "heads" of the document, akin to a git commit.
|
|
92
90
|
* This precisely defines the state of a document.
|
|
93
91
|
* @returns the current document's heads, or undefined if the document is not ready
|
|
94
92
|
*/
|
|
95
|
-
heads(): UrlHeads
|
|
93
|
+
heads(): UrlHeads;
|
|
96
94
|
begin(): void;
|
|
97
95
|
/**
|
|
98
96
|
* Returns an array of all past "heads" for the document in topological order.
|
|
@@ -108,8 +106,8 @@ export declare class DocHandle<T> extends EventEmitter<DocHandleEvents<T>> {
|
|
|
108
106
|
*/
|
|
109
107
|
history(): UrlHeads[] | undefined;
|
|
110
108
|
/**
|
|
111
|
-
* Creates a
|
|
112
|
-
* by the `heads` passed in. The return value is the same type as
|
|
109
|
+
* Creates a fixed "view" of an automerge document at the given point in time represented
|
|
110
|
+
* by the `heads` passed in. The return value is the same type as doc() and will return
|
|
113
111
|
* undefined if the object hasn't finished loading.
|
|
114
112
|
*
|
|
115
113
|
* @remarks
|
|
@@ -245,7 +243,6 @@ export interface DocHandleEvents<T> {
|
|
|
245
243
|
"heads-changed": (payload: DocHandleEncodedChangePayload<T>) => void;
|
|
246
244
|
change: (payload: DocHandleChangePayload<T>) => void;
|
|
247
245
|
delete: (payload: DocHandleDeletePayload<T>) => void;
|
|
248
|
-
unavailable: (payload: DocHandleUnavailablePayload<T>) => void;
|
|
249
246
|
"ephemeral-message": (payload: DocHandleEphemeralMessagePayload<T>) => void;
|
|
250
247
|
"ephemeral-message-outbound": (payload: DocHandleOutboundEphemeralMessagePayload<T>) => void;
|
|
251
248
|
"remote-heads": (payload: DocHandleRemoteHeadsPayload) => void;
|
package/dist/DocHandle.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DocHandle.d.ts","sourceRoot":"","sources":["../src/DocHandle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,gCAAgC,CAAA;AAEnD,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAU5C,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAC5E,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAE9C;;;;;;;;;;;;GAYG;AACH,qBAAa,SAAS,CAAC,CAAC,CAAE,SAAQ,YAAY,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;;IAqBvD,UAAU,EAAE,UAAU;IAF/B,cAAc;gBAEL,UAAU,EAAE,UAAU,EAC7B,OAAO,GAAE,gBAAgB,CAAC,CAAC,CAAM;IAqKnC;OACG;IACH,IAAI,GAAG,IAAI,YAAY,CAKtB;IAED;;;;;OAKG;IACH,OAAO,gBAAgC;IAEvC;;;;;OAKG;IACH,UAAU,gBAAmC;IAE7C;;;;;OAKG;IACH,SAAS,gBAAkC;IAE3C;;;;OAIG;IACH,aAAa,gBAAsC;IAEnD;;OAEG;IACH,OAAO,WAAY,WAAW,EAAE,aAC0B;IAE1D,cAAc;IACd,IAAI,KAAK,yFAER;IAED;;;;;;OAMG;IACG,SAAS,CAAC,WAAW,GAAE,WAAW,EAAc;IAItD;;;;;OAKG;IACG,
|
|
1
|
+
{"version":3,"file":"DocHandle.d.ts","sourceRoot":"","sources":["../src/DocHandle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,gCAAgC,CAAA;AAEnD,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAU5C,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAC5E,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAE9C;;;;;;;;;;;;GAYG;AACH,qBAAa,SAAS,CAAC,CAAC,CAAE,SAAQ,YAAY,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;;IAqBvD,UAAU,EAAE,UAAU;IAF/B,cAAc;gBAEL,UAAU,EAAE,UAAU,EAC7B,OAAO,GAAE,gBAAgB,CAAC,CAAC,CAAM;IAqKnC;OACG;IACH,IAAI,GAAG,IAAI,YAAY,CAKtB;IAED;;;;;OAKG;IACH,OAAO,gBAAgC;IAEvC;;;;;OAKG;IACH,UAAU,gBAAmC;IAE7C;;;;;OAKG;IACH,SAAS,gBAAkC;IAE3C;;;;OAIG;IACH,aAAa,gBAAsC;IAEnD;;OAEG;IACH,OAAO,WAAY,WAAW,EAAE,aAC0B;IAE1D,cAAc;IACd,IAAI,KAAK,yFAER;IAED;;;;;;OAMG;IACG,SAAS,CAAC,WAAW,GAAE,WAAW,EAAc;IAItD;;;;;OAKG;IACG,cAAc;IAClB,sEAAsE;IACtE,WAAW,GAAE,WAAW,EAA6B;IAavD;;;;;;OAMG;IACH,GAAG;IAQH;;qBAEiB;IACjB,OAAO;IAOP;;;;OAIG;IACH,KAAK,IAAI,QAAQ;IAQjB,KAAK;IAIL;;;;;;;;;;;OAWG;IACH,OAAO,IAAI,QAAQ,EAAE,GAAG,SAAS;IAWjC;;;;;;;;;;;;OAYG;IACH,IAAI,CAAC,KAAK,EAAE,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC;IAiBnC;;;;;;;;;;;;OAYG;IACH,IAAI,CAAC,KAAK,EAAE,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,QAAQ,GAAG,CAAC,CAAC,KAAK,EAAE;IAkClE;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,aAAa,GAAG,SAAS;IAetD;;;;;OAKG;IACH,MAAM,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAI5C;;;;OAIG;IACH,WAAW;IAIX;;;OAGG;IACH,cAAc,CAAC,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ;IAKpD,0CAA0C;IAC1C,cAAc,CAAC,SAAS,EAAE,SAAS,GAAG,QAAQ,GAAG,SAAS;IAI1D;;;;;;;;;;;;;;OAcG;IACH,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,OAAO,GAAE,CAAC,CAAC,aAAa,CAAC,CAAC,CAAM;IAkBhE;;;;OAIG;IACH,QAAQ,CACN,KAAK,EAAE,QAAQ,EACf,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EACvB,OAAO,GAAE,CAAC,CAAC,aAAa,CAAC,CAAC,CAAM,GAC/B,QAAQ,EAAE,GAAG,SAAS;IA6BzB;;;;;;;OAOG;IACH,KAAK;IACH,wDAAwD;IACxD,WAAW,EAAE,SAAS,CAAC,CAAC,CAAC;IAiB3B;;;OAGG;IACH,WAAW;IAIX;;SAEK;IACL,OAAO;IAIP,8DAA8D;IAC9D,MAAM;IAIN,sDAAsD;IACtD,MAAM;IAIN,uDAAuD;IACvD,MAAM;IAIN;;;;;;OAMG;IACH,SAAS,CAAC,OAAO,EAAE,OAAO;IAO1B,OAAO,IAAI;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE;CAGlD;AAID,cAAc;AACd,MAAM,MAAM,gBAAgB,CAAC,CAAC,IAE1B;IACE,gGAAgG;IAChG,KAAK,EAAE,IAAI,CAAA;IAEX,yCAAyC;IACzC,YAAY,CAAC,EAAE,CAAC,CAAA;CACjB,GAED;IACE,KAAK,CAAC,EAAE,KAAK,CAAA;IAGb,KAAK,CAAC,EAAE,QAAQ,CAAA;IAEhB,+HAA+H;IAC/H,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,CAAA;AAIL,2EAA2E;AAC3E,MAAM,WAAW,eAAe,CAAC,CAAC;IAChC,eAAe,EAAE,CAAC,OAAO,EAAE,6BAA6B,CAAC,CAAC,CAAC,KAAK,IAAI,CAAA;IACpE,MAAM,EAAE,CAAC,OAAO,EAAE,sBAAsB,CAAC,CAAC,CAAC,KAAK,IAAI,CAAA;IACpD,MAAM,EAAE,CAAC,OAAO,EAAE,sBAAsB,CAAC,CAAC,CAAC,KAAK,IAAI,CAAA;IACpD,mBAAmB,EAAE,CAAC,OAAO,EAAE,gCAAgC,CAAC,CAAC,CAAC,KAAK,IAAI,CAAA;IAC3E,4BAA4B,EAAE,CAC5B,OAAO,EAAE,wCAAwC,CAAC,CAAC,CAAC,KACjD,IAAI,CAAA;IACT,cAAc,EAAE,CAAC,OAAO,EAAE,2BAA2B,KAAK,IAAI,CAAA;CAC/D;AAED,sDAAsD;AACtD,MAAM,WAAW,6BAA6B,CAAC,CAAC;IAC9C,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,CAAA;IACpB,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;CACd;AAED,6CAA6C;AAC7C,MAAM,WAAW,sBAAsB,CAAC,CAAC;IACvC,8BAA8B;IAC9B,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,CAAA;IACpB,iDAAiD;IACjD,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;IACb,wDAAwD;IACxD,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,CAAA;IAClB,mCAAmC;IACnC,SAAS,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;CAC1B;AAED,4CAA4C;AAC5C,MAAM,WAAW,sBAAsB,CAAC,CAAC;IACvC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,CAAA;CACrB;AAED,6DAA6D;AAC7D,MAAM,WAAW,2BAA2B,CAAC,CAAC;IAC5C,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,CAAA;CACrB;AAED,qEAAqE;AACrE,MAAM,WAAW,gCAAgC,CAAC,CAAC;IACjD,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,CAAA;IACpB,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,OAAO,CAAA;CACjB;AAED,kEAAkE;AAClE,MAAM,WAAW,wCAAwC,CAAC,CAAC;IACzD,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,CAAA;IACpB,IAAI,EAAE,UAAU,CAAA;CACjB;AAED,8DAA8D;AAC9D,MAAM,WAAW,2BAA2B;IAC1C,SAAS,EAAE,SAAS,CAAA;IACpB,KAAK,EAAE,QAAQ,CAAA;CAChB;AAMD;;GAEG;AACH,eAAO,MAAM,WAAW;IACtB,kEAAkE;;IAElE,mDAAmD;;IAEnD,6EAA6E;;IAE7E,gCAAgC;;IAEhC,2EAA2E;;IAE3E,kDAAkD;;IAElD,4EAA4E;;CAEpE,CAAA;AACV,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,OAAO,WAAW,CAAC,CAAA;AAExE,eAAO,MACL,IAAI,UACJ,OAAO,aACP,UAAU,gBACV,KAAK,WACL,QAAQ,cACR,OAAO,aACP,WAAW,eACE,CAAA"}
|
package/dist/DocHandle.js
CHANGED
|
@@ -64,12 +64,12 @@ export class DocHandle extends EventEmitter {
|
|
|
64
64
|
this.emit("delete", { handle: this });
|
|
65
65
|
return { doc: A.init() };
|
|
66
66
|
}),
|
|
67
|
+
onUnavailable: assign(() => {
|
|
68
|
+
return { doc: A.init() };
|
|
69
|
+
}),
|
|
67
70
|
onUnload: assign(() => {
|
|
68
71
|
return { doc: A.init() };
|
|
69
72
|
}),
|
|
70
|
-
onUnavailable: () => {
|
|
71
|
-
this.emit("unavailable", { handle: this });
|
|
72
|
-
},
|
|
73
73
|
},
|
|
74
74
|
}).createMachine({
|
|
75
75
|
/** @xstate-layout N4IgpgJg5mDOIC5QAoC2BDAxgCwJYDswBKAYgFUAFAEQEEAVAUQG0AGAXUVAAcB7WXAC64e+TiAAeiAOwAOAKwA6ACxSAzKqks1ATjlTdAGhABPRAFolAJksKN2y1KtKAbFLla5AX09G0WPISkVAwAMgyMrBxIILz8QiJikggAjCzOijKqLEqqybJyLizaRqYIFpbJtro5Uo7J2o5S3r4YOATECrgQADZgJADCAEoM9MzsYrGCwqLRSeoyCtra8pa5adquySXmDjY5ac7JljLJeepKzSB+bYGdPX0AYgCSAHJUkRN8UwmziM7HCgqyVcUnqcmScmcMm2ZV2yiyzkOx1OalUFx8V1aAQ63R46AgBCgJGGAEUyAwAMp0D7RSbxGagJKHFgKOSWJTJGRSCosCpKaEmRCqbQKU5yXINeTaer6LwY67YogKXH4wkkKgAeX6AH1hjQqABNGncL70xKIJQ5RY5BHOJag6wwpRyEWImQVeT1aWrVSXBXtJUqgn4Ik0ADqNCedG1L3CYY1gwA0saYqbpuaEG4pKLksKpFDgcsCjDhTnxTKpTLdH6sQGFOgAO7oKYhl5gAQNngAJwA1iRY3R40ndSNDSm6enfpm5BkWAVkvy7bpuTCKq7ndZnfVeSwuTX-HWu2AAI4AVzgQhD6q12rILxoADVIyEaAAhMLjtM-RmIE4LVSQi4nLLDIGzOCWwLKA0cgyLBoFWNy+43B0R5nheaqajqepjuMtJfgyEh-FoixqMCoKqOyhzgYKCDOq6UIeuCSxHOoSGKgop74OgABuzbdOgABGvTXlho5GrhJpxJOP4pLulT6KoMhpJY2hzsWNF0QobqMV6LG+pc+A8BAcBiP6gSfFJ36EQgKksksKxrHamwwmY7gLKB85QjBzoAWxdZdL0FnfARST8ooLC7qoTnWBU4pyC5ViVMKBQaHUDQuM4fm3EGhJBWaU7-CysEAUp3LpEpWw0WYRw2LmqzgqciIsCxWUdI2zaXlAbYdt2PZ5dJ1n5jY2iJY1ikOIcMJHCyUWHC62hRZkUVNPKta3Kh56wJ1-VWUyzhFc64JWJCtQNBBzhQW4cHwbsrVKpxPF8YJgV4ZZIWIKkiKiiNSkqZYWjzCWaQ5hFh0AcCuR3QoR74qUknBRmzholpv3OkpRQNNRpTzaKTWKbIWR5FDxm9AIkA7e9skUYCWayLILBZGoLkUSKbIyIdpxHPoyTeN4QA */
|
|
@@ -234,7 +234,7 @@ export class DocHandle extends EventEmitter {
|
|
|
234
234
|
* This is the recommended way to access a handle's document. Note that this waits for the handle
|
|
235
235
|
* to be ready if necessary. If loading (or synchronization) fails, this will never resolve.
|
|
236
236
|
*/
|
|
237
|
-
async
|
|
237
|
+
async legacyAsyncDoc(
|
|
238
238
|
/** states to wait for, such as "LOADING". mostly for internal use. */
|
|
239
239
|
awaitStates = ["ready", "unavailable"]) {
|
|
240
240
|
try {
|
|
@@ -245,38 +245,31 @@ export class DocHandle extends EventEmitter {
|
|
|
245
245
|
// if we timed out, return undefined
|
|
246
246
|
return undefined;
|
|
247
247
|
}
|
|
248
|
-
// If we have fixed heads, return a view at those heads
|
|
249
|
-
if (this.#fixedHeads) {
|
|
250
|
-
const doc = this.#doc;
|
|
251
|
-
if (!doc || this.isUnavailable())
|
|
252
|
-
return undefined;
|
|
253
|
-
return A.view(doc, decodeHeads(this.#fixedHeads));
|
|
254
|
-
}
|
|
255
248
|
// Return the document
|
|
256
249
|
return !this.isUnavailable() ? this.#doc : undefined;
|
|
257
250
|
}
|
|
258
251
|
/**
|
|
259
|
-
*
|
|
260
|
-
* undefined. Consider using `await handle.doc()` instead. Check `isReady()`, or use `whenReady()`
|
|
261
|
-
* if you want to make sure loading is complete first.
|
|
262
|
-
*
|
|
263
|
-
* Not to be confused with the SyncState of the document, which describes the state of the
|
|
264
|
-
* synchronization process.
|
|
252
|
+
* Returns the current state of the Automerge document this handle manages.
|
|
265
253
|
*
|
|
266
|
-
*
|
|
267
|
-
*
|
|
254
|
+
* @returns the current document
|
|
255
|
+
* @throws on deleted and unavailable documents
|
|
268
256
|
*
|
|
269
|
-
* @returns the current document, or undefined if the document is not ready.
|
|
270
257
|
*/
|
|
271
|
-
|
|
258
|
+
doc() {
|
|
272
259
|
if (!this.isReady())
|
|
273
|
-
|
|
260
|
+
throw new Error("DocHandle is not ready");
|
|
274
261
|
if (this.#fixedHeads) {
|
|
275
|
-
|
|
276
|
-
return doc ? A.view(doc, decodeHeads(this.#fixedHeads)) : undefined;
|
|
262
|
+
return A.view(this.#doc, decodeHeads(this.#fixedHeads));
|
|
277
263
|
}
|
|
278
264
|
return this.#doc;
|
|
279
265
|
}
|
|
266
|
+
/**
|
|
267
|
+
*
|
|
268
|
+
* @deprecated */
|
|
269
|
+
docSync() {
|
|
270
|
+
console.warn("docSync is deprecated. Use doc() instead. This function will be removed as part of the 2.0 release.");
|
|
271
|
+
return this.doc();
|
|
272
|
+
}
|
|
280
273
|
/**
|
|
281
274
|
* Returns the current "heads" of the document, akin to a git commit.
|
|
282
275
|
* This precisely defines the state of a document.
|
|
@@ -284,7 +277,7 @@ export class DocHandle extends EventEmitter {
|
|
|
284
277
|
*/
|
|
285
278
|
heads() {
|
|
286
279
|
if (!this.isReady())
|
|
287
|
-
|
|
280
|
+
throw new Error("DocHandle is not ready");
|
|
288
281
|
if (this.#fixedHeads) {
|
|
289
282
|
return this.#fixedHeads;
|
|
290
283
|
}
|
|
@@ -313,8 +306,8 @@ export class DocHandle extends EventEmitter {
|
|
|
313
306
|
return A.topoHistoryTraversal(this.#doc).map(h => encodeHeads([h]));
|
|
314
307
|
}
|
|
315
308
|
/**
|
|
316
|
-
* Creates a
|
|
317
|
-
* by the `heads` passed in. The return value is the same type as
|
|
309
|
+
* Creates a fixed "view" of an automerge document at the given point in time represented
|
|
310
|
+
* by the `heads` passed in. The return value is the same type as doc() and will return
|
|
318
311
|
* undefined if the object hasn't finished loading.
|
|
319
312
|
*
|
|
320
313
|
* @remarks
|
|
@@ -367,7 +360,7 @@ export class DocHandle extends EventEmitter {
|
|
|
367
360
|
if (!otherHeads)
|
|
368
361
|
throw new Error("Other document's heads not available");
|
|
369
362
|
// Create a temporary merged doc to verify shared history and compute diff
|
|
370
|
-
const mergedDoc = A.merge(A.clone(doc), first.
|
|
363
|
+
const mergedDoc = A.merge(A.clone(doc), first.doc());
|
|
371
364
|
// Use the merged doc to compute the diff
|
|
372
365
|
return A.diff(mergedDoc, decodeHeads(this.heads()), decodeHeads(otherHeads));
|
|
373
366
|
}
|
|
@@ -499,10 +492,7 @@ export class DocHandle extends EventEmitter {
|
|
|
499
492
|
if (this.#fixedHeads) {
|
|
500
493
|
throw new Error(`DocHandle#${this.documentId} is in view-only mode at specific heads. Use clone() to create a new document from this state.`);
|
|
501
494
|
}
|
|
502
|
-
const mergingDoc = otherHandle.
|
|
503
|
-
if (!mergingDoc) {
|
|
504
|
-
throw new Error("The document to be merged in is falsy, aborting.");
|
|
505
|
-
}
|
|
495
|
+
const mergingDoc = otherHandle.doc();
|
|
506
496
|
this.update(doc => {
|
|
507
497
|
return A.merge(doc, mergingDoc);
|
|
508
498
|
});
|
|
@@ -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 {};
|
package/dist/Repo.d.ts
CHANGED
|
@@ -8,6 +8,8 @@ import { StorageId } from "./storage/types.js";
|
|
|
8
8
|
import { CollectionSynchronizer } from "./synchronizer/CollectionSynchronizer.js";
|
|
9
9
|
import { DocSyncMetrics } from "./synchronizer/Synchronizer.js";
|
|
10
10
|
import type { AnyDocumentId, AutomergeUrl, DocumentId, PeerId } from "./types.js";
|
|
11
|
+
import { AbortOptions } from "./helpers/abortable.js";
|
|
12
|
+
import { FindProgress, FindProgressWithMethods } from "./FindProgress.js";
|
|
11
13
|
/** A Repo is a collection of documents with networking, syncing, and storage capabilities. */
|
|
12
14
|
/** The `Repo` is the main entry point of this library
|
|
13
15
|
*
|
|
@@ -57,17 +59,17 @@ export declare class Repo extends EventEmitter<RepoEvents> {
|
|
|
57
59
|
* Any peers this `Repo` is connected to for whom `sharePolicy` returns `true` will
|
|
58
60
|
* be notified of the newly created DocHandle.
|
|
59
61
|
*
|
|
60
|
-
* @throws if the cloned handle is not yet ready or if
|
|
61
|
-
* `clonedHandle.docSync()` returns `undefined` (i.e. the handle is unavailable).
|
|
62
62
|
*/
|
|
63
63
|
clone<T>(clonedHandle: DocHandle<T>): DocHandle<T>;
|
|
64
|
+
findWithProgress<T>(id: AnyDocumentId, options?: AbortOptions): FindProgressWithMethods<T> | FindProgress<T>;
|
|
65
|
+
find<T>(id: AnyDocumentId, options?: RepoFindOptions & AbortOptions): Promise<DocHandle<T>>;
|
|
64
66
|
/**
|
|
65
67
|
* Retrieves a document by id. It gets data from the local system, but also emits a `document`
|
|
66
68
|
* event to advertise interest in the document.
|
|
67
69
|
*/
|
|
68
|
-
|
|
70
|
+
findClassic<T>(
|
|
69
71
|
/** The url or documentId of the handle to retrieve */
|
|
70
|
-
id: AnyDocumentId): DocHandle<T
|
|
72
|
+
id: AnyDocumentId, options?: RepoFindOptions & AbortOptions): Promise<DocHandle<T>>;
|
|
71
73
|
delete(
|
|
72
74
|
/** The url or documentId of the handle to delete */
|
|
73
75
|
id: AnyDocumentId): void;
|
|
@@ -151,6 +153,9 @@ export interface RepoEvents {
|
|
|
151
153
|
"unavailable-document": (arg: DeleteDocumentPayload) => void;
|
|
152
154
|
"doc-metrics": (arg: DocMetrics) => void;
|
|
153
155
|
}
|
|
156
|
+
export interface RepoFindOptions {
|
|
157
|
+
allowableStates?: string[];
|
|
158
|
+
}
|
|
154
159
|
export interface DocumentPayload {
|
|
155
160
|
handle: DocHandle<any>;
|
|
156
161
|
}
|
package/dist/Repo.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Repo.d.ts","sourceRoot":"","sources":["../src/Repo.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAQ5C,OAAO,EAEL,SAAS,EAKV,MAAM,gBAAgB,CAAA;AAIvB,OAAO,EACL,uBAAuB,EACvB,KAAK,YAAY,EAClB,MAAM,sCAAsC,CAAA;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAA;AAEhE,OAAO,EAAE,uBAAuB,EAAE,MAAM,sCAAsC,CAAA;AAC9E,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAA;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAC9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,0CAA0C,CAAA;AACjF,OAAO,EACL,cAAc,EAEf,MAAM,gCAAgC,CAAA;AACvC,OAAO,KAAK,EACV,aAAa,EACb,YAAY,EACZ,UAAU,EACV,MAAM,EACP,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"Repo.d.ts","sourceRoot":"","sources":["../src/Repo.ts"],"names":[],"mappings":"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"}
|
package/dist/Repo.js
CHANGED
|
@@ -9,6 +9,7 @@ import { throttle } from "./helpers/throttle.js";
|
|
|
9
9
|
import { NetworkSubsystem } from "./network/NetworkSubsystem.js";
|
|
10
10
|
import { StorageSubsystem } from "./storage/StorageSubsystem.js";
|
|
11
11
|
import { CollectionSynchronizer } from "./synchronizer/CollectionSynchronizer.js";
|
|
12
|
+
import { abortable } from "./helpers/abortable.js";
|
|
12
13
|
function randomPeerId() {
|
|
13
14
|
return ("peer-" + Math.random().toString(36).slice(4));
|
|
14
15
|
}
|
|
@@ -170,16 +171,8 @@ export class Repo extends EventEmitter {
|
|
|
170
171
|
};
|
|
171
172
|
handle.on("heads-changed", throttle(saveFn, this.saveDebounceRate));
|
|
172
173
|
}
|
|
173
|
-
handle.on("unavailable", () => {
|
|
174
|
-
this.#log("document unavailable", { documentId: handle.documentId });
|
|
175
|
-
this.emit("unavailable-document", {
|
|
176
|
-
documentId: handle.documentId,
|
|
177
|
-
});
|
|
178
|
-
});
|
|
179
174
|
// Register the document with the synchronizer. This advertises our interest in the document.
|
|
180
|
-
this.synchronizer.addDocument(handle
|
|
181
|
-
// Preserve the old event in case anyone was using it.
|
|
182
|
-
this.emit("document", { handle });
|
|
175
|
+
this.synchronizer.addDocument(handle);
|
|
183
176
|
}
|
|
184
177
|
#receiveMessage(message) {
|
|
185
178
|
switch (message.type) {
|
|
@@ -280,18 +273,13 @@ export class Repo extends EventEmitter {
|
|
|
280
273
|
* Any peers this `Repo` is connected to for whom `sharePolicy` returns `true` will
|
|
281
274
|
* be notified of the newly created DocHandle.
|
|
282
275
|
*
|
|
283
|
-
* @throws if the cloned handle is not yet ready or if
|
|
284
|
-
* `clonedHandle.docSync()` returns `undefined` (i.e. the handle is unavailable).
|
|
285
276
|
*/
|
|
286
277
|
clone(clonedHandle) {
|
|
287
278
|
if (!clonedHandle.isReady()) {
|
|
288
279
|
throw new Error(`Cloned handle is not yet in ready state.
|
|
289
280
|
(Try await handle.whenReady() first.)`);
|
|
290
281
|
}
|
|
291
|
-
const sourceDoc = clonedHandle.
|
|
292
|
-
if (!sourceDoc) {
|
|
293
|
-
throw new Error("Cloned handle doesn't have a document.");
|
|
294
|
-
}
|
|
282
|
+
const sourceDoc = clonedHandle.doc();
|
|
295
283
|
const handle = this.create();
|
|
296
284
|
handle.update(() => {
|
|
297
285
|
// we replace the document with the new cloned one
|
|
@@ -299,58 +287,171 @@ export class Repo extends EventEmitter {
|
|
|
299
287
|
});
|
|
300
288
|
return handle;
|
|
301
289
|
}
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
*/
|
|
306
|
-
find(
|
|
307
|
-
/** The url or documentId of the handle to retrieve */
|
|
308
|
-
id) {
|
|
290
|
+
findWithProgress(id, options = {}) {
|
|
291
|
+
const { signal } = options;
|
|
292
|
+
const abortPromise = abortable(signal);
|
|
309
293
|
const { documentId, heads } = isValidAutomergeUrl(id)
|
|
310
294
|
? parseAutomergeUrl(id)
|
|
311
295
|
: { documentId: interpretAsDocumentId(id), heads: undefined };
|
|
312
|
-
|
|
313
|
-
if (
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
}
|
|
296
|
+
// Check cache first - return plain FindStep for terminal states
|
|
297
|
+
if (this.#handleCache[documentId]) {
|
|
298
|
+
const handle = this.#handleCache[documentId];
|
|
299
|
+
if (handle.state === UNAVAILABLE) {
|
|
300
|
+
const result = {
|
|
301
|
+
state: "unavailable",
|
|
302
|
+
error: new Error(`Document ${id} is unavailable`),
|
|
303
|
+
handle,
|
|
304
|
+
};
|
|
305
|
+
return result;
|
|
306
|
+
}
|
|
307
|
+
if (handle.state === DELETED) {
|
|
308
|
+
return {
|
|
309
|
+
state: "failed",
|
|
310
|
+
error: new Error(`Document ${id} was deleted`),
|
|
311
|
+
handle,
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
if (handle.state === READY) {
|
|
315
|
+
// If we already have the handle, return it immediately (or a view of the handle if heads are specified)
|
|
316
|
+
return {
|
|
317
|
+
state: "ready",
|
|
318
|
+
// TODO: this handle needs to be cached (or at least avoid running clone)
|
|
319
|
+
handle: heads ? handle.view(heads) : handle,
|
|
320
|
+
};
|
|
321
321
|
}
|
|
322
|
-
// If we already have the handle, return it immediately (or a view of the handle if heads are specified)
|
|
323
|
-
return heads ? cachedHandle.view(heads) : cachedHandle;
|
|
324
322
|
}
|
|
325
|
-
//
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
323
|
+
// the generator takes over `this`, so we need an alias to the repo this
|
|
324
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
325
|
+
const that = this;
|
|
326
|
+
async function* progressGenerator() {
|
|
327
|
+
try {
|
|
328
|
+
const handle = that.#getHandle({ documentId });
|
|
329
|
+
yield { state: "loading", progress: 25, handle };
|
|
330
|
+
const loadingPromise = await (that.storageSubsystem
|
|
331
|
+
? that.storageSubsystem.loadDoc(handle.documentId)
|
|
332
|
+
: Promise.resolve(null));
|
|
333
|
+
const loadedDoc = await Promise.race([loadingPromise, abortPromise]);
|
|
334
|
+
if (loadedDoc) {
|
|
335
|
+
handle.update(() => loadedDoc);
|
|
336
|
+
handle.doneLoading();
|
|
337
|
+
yield { state: "loading", progress: 50, handle };
|
|
338
|
+
}
|
|
339
|
+
else {
|
|
340
|
+
await Promise.race([that.networkSubsystem.whenReady(), abortPromise]);
|
|
341
|
+
handle.request();
|
|
342
|
+
yield { state: "loading", progress: 75, handle };
|
|
343
|
+
}
|
|
344
|
+
that.#registerHandleWithSubsystems(handle);
|
|
345
|
+
await Promise.race([
|
|
346
|
+
handle.whenReady([READY, UNAVAILABLE]),
|
|
347
|
+
abortPromise,
|
|
348
|
+
]);
|
|
349
|
+
if (handle.state === UNAVAILABLE) {
|
|
350
|
+
yield { state: "unavailable", handle };
|
|
351
|
+
}
|
|
352
|
+
if (handle.state === DELETED) {
|
|
353
|
+
throw new Error(`Document ${id} was deleted`);
|
|
354
|
+
}
|
|
355
|
+
yield { state: "ready", handle };
|
|
340
356
|
}
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
357
|
+
catch (error) {
|
|
358
|
+
yield {
|
|
359
|
+
state: "failed",
|
|
360
|
+
error: error instanceof Error ? error : new Error(String(error)),
|
|
361
|
+
handle,
|
|
362
|
+
};
|
|
346
363
|
}
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
364
|
+
}
|
|
365
|
+
const iterator = progressGenerator();
|
|
366
|
+
const next = async () => {
|
|
367
|
+
const result = await iterator.next();
|
|
368
|
+
return { ...result.value, next };
|
|
369
|
+
};
|
|
370
|
+
const untilReady = async (allowableStates) => {
|
|
371
|
+
for await (const state of iterator) {
|
|
372
|
+
if (allowableStates.includes(state.handle.state)) {
|
|
373
|
+
return state.handle;
|
|
374
|
+
}
|
|
375
|
+
if (state.state === "unavailable") {
|
|
376
|
+
throw new Error(`Document ${id} is unavailable`);
|
|
377
|
+
}
|
|
378
|
+
if (state.state === "ready")
|
|
379
|
+
return state.handle;
|
|
380
|
+
if (state.state === "failed")
|
|
381
|
+
throw state.error;
|
|
382
|
+
}
|
|
383
|
+
throw new Error("Iterator completed without reaching ready state");
|
|
384
|
+
};
|
|
385
|
+
const handle = this.#getHandle({ documentId });
|
|
386
|
+
const initial = { state: "loading", progress: 0, handle };
|
|
387
|
+
return { ...initial, next, untilReady };
|
|
388
|
+
}
|
|
389
|
+
async find(id, options = {}) {
|
|
390
|
+
const { allowableStates = ["ready"], signal } = options;
|
|
391
|
+
const progress = this.findWithProgress(id, { signal });
|
|
392
|
+
/*if (allowableStates.includes(progress.state)) {
|
|
393
|
+
console.log("returning early")
|
|
394
|
+
return progress.handle
|
|
395
|
+
}*/
|
|
396
|
+
if ("untilReady" in progress) {
|
|
397
|
+
this.#registerHandleWithSubsystems(progress.handle);
|
|
398
|
+
return progress.untilReady(allowableStates);
|
|
399
|
+
}
|
|
400
|
+
else {
|
|
401
|
+
return progress.handle;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* Loads a document without waiting for ready state
|
|
406
|
+
*/
|
|
407
|
+
async #loadDocument(documentId) {
|
|
408
|
+
// If we have the handle cached, return it
|
|
409
|
+
if (this.#handleCache[documentId]) {
|
|
410
|
+
return this.#handleCache[documentId];
|
|
411
|
+
}
|
|
412
|
+
// If we don't already have the handle, make an empty one and try loading it
|
|
413
|
+
const handle = this.#getHandle({ documentId });
|
|
414
|
+
const loadedDoc = await (this.storageSubsystem
|
|
415
|
+
? this.storageSubsystem.loadDoc(handle.documentId)
|
|
416
|
+
: Promise.resolve(null));
|
|
417
|
+
if (loadedDoc) {
|
|
418
|
+
// We need to cast this to <T> because loadDoc operates in <unknowns>.
|
|
419
|
+
// This is really where we ought to be validating the input matches <T>.
|
|
420
|
+
handle.update(() => loadedDoc);
|
|
421
|
+
handle.doneLoading();
|
|
422
|
+
}
|
|
423
|
+
else {
|
|
424
|
+
// Because the network subsystem might still be booting up, we wait
|
|
425
|
+
// here so that we don't immediately give up loading because we're still
|
|
426
|
+
// making our initial connection to a sync server.
|
|
427
|
+
await this.networkSubsystem.whenReady();
|
|
428
|
+
handle.request();
|
|
429
|
+
}
|
|
430
|
+
this.#registerHandleWithSubsystems(handle);
|
|
431
|
+
return handle;
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* Retrieves a document by id. It gets data from the local system, but also emits a `document`
|
|
435
|
+
* event to advertise interest in the document.
|
|
436
|
+
*/
|
|
437
|
+
async findClassic(
|
|
438
|
+
/** The url or documentId of the handle to retrieve */
|
|
439
|
+
id, options = {}) {
|
|
440
|
+
const documentId = interpretAsDocumentId(id);
|
|
441
|
+
const { allowableStates, signal } = options;
|
|
442
|
+
return Promise.race([
|
|
443
|
+
(async () => {
|
|
444
|
+
const handle = await this.#loadDocument(documentId);
|
|
445
|
+
if (!allowableStates) {
|
|
446
|
+
await handle.whenReady([READY, UNAVAILABLE]);
|
|
447
|
+
if (handle.state === UNAVAILABLE && !signal?.aborted) {
|
|
448
|
+
throw new Error(`Document ${id} is unavailable`);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
return handle;
|
|
452
|
+
})(),
|
|
453
|
+
abortable(signal),
|
|
454
|
+
]);
|
|
354
455
|
}
|
|
355
456
|
delete(
|
|
356
457
|
/** The url or documentId of the handle to delete */
|
|
@@ -371,9 +472,7 @@ export class Repo extends EventEmitter {
|
|
|
371
472
|
async export(id) {
|
|
372
473
|
const documentId = interpretAsDocumentId(id);
|
|
373
474
|
const handle = this.#getHandle({ documentId });
|
|
374
|
-
const doc =
|
|
375
|
-
if (!doc)
|
|
376
|
-
return undefined;
|
|
475
|
+
const doc = handle.doc();
|
|
377
476
|
return Automerge.save(doc);
|
|
378
477
|
}
|
|
379
478
|
/**
|
|
@@ -419,11 +518,7 @@ export class Repo extends EventEmitter {
|
|
|
419
518
|
? documents.map(id => this.#handleCache[id])
|
|
420
519
|
: Object.values(this.#handleCache);
|
|
421
520
|
await Promise.all(handles.map(async (handle) => {
|
|
422
|
-
|
|
423
|
-
if (!doc) {
|
|
424
|
-
return;
|
|
425
|
-
}
|
|
426
|
-
return this.storageSubsystem.saveDoc(handle.documentId, doc);
|
|
521
|
+
return this.storageSubsystem.saveDoc(handle.documentId, handle.doc());
|
|
427
522
|
}));
|
|
428
523
|
}
|
|
429
524
|
/**
|
|
@@ -438,7 +533,9 @@ export class Repo extends EventEmitter {
|
|
|
438
533
|
return;
|
|
439
534
|
}
|
|
440
535
|
const handle = this.#getHandle({ documentId });
|
|
441
|
-
|
|
536
|
+
await handle.whenReady([READY, UNLOADED, DELETED, UNAVAILABLE]);
|
|
537
|
+
const doc = handle.doc();
|
|
538
|
+
// because this is an internal-ish function, we'll be extra careful about undefined docs here
|
|
442
539
|
if (doc) {
|
|
443
540
|
if (handle.isReady()) {
|
|
444
541
|
handle.unload();
|