@automerge/automerge-repo 2.0.0-alpha.5 → 2.0.0-alpha.7
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/DocHandle.d.ts +34 -0
- package/dist/DocHandle.d.ts.map +1 -1
- package/dist/DocHandle.js +53 -0
- package/dist/storage/StorageSubsystem.d.ts.map +1 -1
- package/dist/storage/StorageSubsystem.js +8 -2
- package/package.json +2 -2
- package/src/DocHandle.ts +57 -0
- package/src/storage/StorageSubsystem.ts +7 -2
- package/test/DocHandle.test.ts +82 -0
- package/test/StorageSubsystem.test.ts +17 -0
package/dist/DocHandle.d.ts
CHANGED
|
@@ -86,6 +86,40 @@ export declare class DocHandle<T> extends EventEmitter<DocHandleEvents<T>> {
|
|
|
86
86
|
* @returns the current document's heads, or undefined if the document is not ready
|
|
87
87
|
*/
|
|
88
88
|
heads(): A.Heads | undefined;
|
|
89
|
+
/**
|
|
90
|
+
* Creates a fixed "view" of an automerge document at the given point in time represented
|
|
91
|
+
* by the `heads` passed in. The return value is the same type as docSync() and will return
|
|
92
|
+
* undefined if the object hasn't finished loading.
|
|
93
|
+
*
|
|
94
|
+
* @remarks
|
|
95
|
+
* A point-in-time in an automerge document is an *array* of heads since there may be
|
|
96
|
+
* concurrent edits. This API just returns a topologically sorted history of all edits
|
|
97
|
+
* so every previous entry will be (in some sense) before later ones, but the set of all possible
|
|
98
|
+
* history views would be quite large under concurrency (every thing in each branch against each other).
|
|
99
|
+
* There might be a clever way to think about this, but we haven't found it yet, so for now at least
|
|
100
|
+
* we present a single traversable view which excludes concurrency.
|
|
101
|
+
* @returns The individual heads for every change in the document.
|
|
102
|
+
*/
|
|
103
|
+
history(): A.Heads[] | undefined;
|
|
104
|
+
/**
|
|
105
|
+
* Creates a fixed "view" of an automerge document at the given point in time represented
|
|
106
|
+
* by the `heads` passed in. The return value is the same type as docSync() and will return
|
|
107
|
+
* undefined if the object hasn't finished loading.
|
|
108
|
+
* @returns
|
|
109
|
+
*/
|
|
110
|
+
view(heads: A.Heads): A.Doc<T> | undefined;
|
|
111
|
+
/**
|
|
112
|
+
* Creates a fixed "view" of an automerge document at the given point in time represented
|
|
113
|
+
* by the `heads` passed in. The return value is the same type as docSync() and will return
|
|
114
|
+
* undefined if the object hasn't finished loading.
|
|
115
|
+
*
|
|
116
|
+
* @remarks
|
|
117
|
+
* We allow specifying both a from/to heads or just a single comparison point, in which case
|
|
118
|
+
* the base will be the current document heads.
|
|
119
|
+
*
|
|
120
|
+
* @returns Automerge patches that go from one document state to the other. Use view() to get the full state.
|
|
121
|
+
*/
|
|
122
|
+
diff(first: A.Heads, second?: A.Heads): A.Patch[] | undefined;
|
|
89
123
|
/**
|
|
90
124
|
* `update` is called any time we have a new document state; could be
|
|
91
125
|
* from a local change, a remote change, or a new document from storage.
|
package/dist/DocHandle.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DocHandle.d.ts","sourceRoot":"","sources":["../src/DocHandle.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DocHandle.d.ts","sourceRoot":"","sources":["../src/DocHandle.ts"],"names":[],"mappings":"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"}
|
package/dist/DocHandle.js
CHANGED
|
@@ -253,6 +253,59 @@ export class DocHandle extends EventEmitter {
|
|
|
253
253
|
}
|
|
254
254
|
return A.getHeads(this.#doc);
|
|
255
255
|
}
|
|
256
|
+
/**
|
|
257
|
+
* Creates a fixed "view" of an automerge document at the given point in time represented
|
|
258
|
+
* by the `heads` passed in. The return value is the same type as docSync() and will return
|
|
259
|
+
* undefined if the object hasn't finished loading.
|
|
260
|
+
*
|
|
261
|
+
* @remarks
|
|
262
|
+
* A point-in-time in an automerge document is an *array* of heads since there may be
|
|
263
|
+
* concurrent edits. This API just returns a topologically sorted history of all edits
|
|
264
|
+
* so every previous entry will be (in some sense) before later ones, but the set of all possible
|
|
265
|
+
* history views would be quite large under concurrency (every thing in each branch against each other).
|
|
266
|
+
* There might be a clever way to think about this, but we haven't found it yet, so for now at least
|
|
267
|
+
* we present a single traversable view which excludes concurrency.
|
|
268
|
+
* @returns The individual heads for every change in the document.
|
|
269
|
+
*/
|
|
270
|
+
history() {
|
|
271
|
+
if (!this.isReady()) {
|
|
272
|
+
return undefined;
|
|
273
|
+
}
|
|
274
|
+
// This just returns all the heads as individual strings.
|
|
275
|
+
return A.topoHistoryTraversal(this.#doc).map(h => [h]);
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Creates a fixed "view" of an automerge document at the given point in time represented
|
|
279
|
+
* by the `heads` passed in. The return value is the same type as docSync() and will return
|
|
280
|
+
* undefined if the object hasn't finished loading.
|
|
281
|
+
* @returns
|
|
282
|
+
*/
|
|
283
|
+
view(heads) {
|
|
284
|
+
if (!this.isReady()) {
|
|
285
|
+
return undefined;
|
|
286
|
+
}
|
|
287
|
+
return A.view(this.#doc, heads);
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Creates a fixed "view" of an automerge document at the given point in time represented
|
|
291
|
+
* by the `heads` passed in. The return value is the same type as docSync() and will return
|
|
292
|
+
* undefined if the object hasn't finished loading.
|
|
293
|
+
*
|
|
294
|
+
* @remarks
|
|
295
|
+
* We allow specifying both a from/to heads or just a single comparison point, in which case
|
|
296
|
+
* the base will be the current document heads.
|
|
297
|
+
*
|
|
298
|
+
* @returns Automerge patches that go from one document state to the other. Use view() to get the full state.
|
|
299
|
+
*/
|
|
300
|
+
diff(first, second) {
|
|
301
|
+
if (!this.isReady()) {
|
|
302
|
+
return undefined;
|
|
303
|
+
}
|
|
304
|
+
// We allow only one set of heads to be specified, in which case we use the doc's heads
|
|
305
|
+
const from = second ? first : this.heads() || []; // because we guard above this should always have useful data
|
|
306
|
+
const to = second ? second : first;
|
|
307
|
+
return A.diff(this.#doc, from, to);
|
|
308
|
+
}
|
|
256
309
|
/**
|
|
257
310
|
* `update` is called any time we have a new document state; could be
|
|
258
311
|
* from a local change, a remote change, or a new document from storage.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StorageSubsystem.d.ts","sourceRoot":"","sources":["../../src/storage/StorageSubsystem.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,gCAAgC,CAAA;AAInD,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAA;AAC7C,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAA;AACtE,OAAO,EAAyB,SAAS,EAAE,MAAM,YAAY,CAAA;AAK7D;;;GAGG;AACH,qBAAa,gBAAgB;;gBAef,cAAc,EAAE,uBAAuB;IAI7C,EAAE,IAAI,OAAO,CAAC,SAAS,CAAC;IA2B9B,kCAAkC;IAC5B,IAAI;IACR,iFAAiF;IACjF,SAAS,EAAE,MAAM;IAEjB,yFAAyF;IACzF,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAKlC,gCAAgC;IAC1B,IAAI;IACR,iFAAiF;IACjF,SAAS,EAAE,MAAM;IAEjB,yFAAyF;IACzF,GAAG,EAAE,MAAM;IAEX,sCAAsC;IACtC,IAAI,EAAE,UAAU,GACf,OAAO,CAAC,IAAI,CAAC;IAKhB,oCAAoC;IAC9B,MAAM;IACV,iFAAiF;IACjF,SAAS,EAAE,MAAM;IAEjB,2FAA2F;IAC3F,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,IAAI,CAAC;IAOhB;;OAEG;IACG,OAAO,CAAC,CAAC,EAAE,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAmClE;;;;;;OAMG;IACG,OAAO,CAAC,UAAU,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAazE;;OAEG;IACG,SAAS,CAAC,UAAU,EAAE,UAAU;IAkEhC,aAAa,CACjB,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC,CAAC,CAAC,SAAS,GAAG,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"StorageSubsystem.d.ts","sourceRoot":"","sources":["../../src/storage/StorageSubsystem.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,gCAAgC,CAAA;AAInD,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAA;AAC7C,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAA;AACtE,OAAO,EAAyB,SAAS,EAAE,MAAM,YAAY,CAAA;AAK7D;;;GAGG;AACH,qBAAa,gBAAgB;;gBAef,cAAc,EAAE,uBAAuB;IAI7C,EAAE,IAAI,OAAO,CAAC,SAAS,CAAC;IA2B9B,kCAAkC;IAC5B,IAAI;IACR,iFAAiF;IACjF,SAAS,EAAE,MAAM;IAEjB,yFAAyF;IACzF,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAKlC,gCAAgC;IAC1B,IAAI;IACR,iFAAiF;IACjF,SAAS,EAAE,MAAM;IAEjB,yFAAyF;IACzF,GAAG,EAAE,MAAM;IAEX,sCAAsC;IACtC,IAAI,EAAE,UAAU,GACf,OAAO,CAAC,IAAI,CAAC;IAKhB,oCAAoC;IAC9B,MAAM;IACV,iFAAiF;IACjF,SAAS,EAAE,MAAM;IAEjB,2FAA2F;IAC3F,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,IAAI,CAAC;IAOhB;;OAEG;IACG,OAAO,CAAC,CAAC,EAAE,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAmClE;;;;;;OAMG;IACG,OAAO,CAAC,UAAU,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAazE;;OAEG;IACG,SAAS,CAAC,UAAU,EAAE,UAAU;IAkEhC,aAAa,CACjB,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC,CAAC,CAAC,SAAS,GAAG,SAAS,CAAC;IAW7B,aAAa,CACjB,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,SAAS,EACpB,SAAS,EAAE,CAAC,CAAC,SAAS,GACrB,OAAO,CAAC,IAAI,CAAC;CA8CjB"}
|
|
@@ -178,8 +178,14 @@ export class StorageSubsystem {
|
|
|
178
178
|
}
|
|
179
179
|
async loadSyncState(documentId, storageId) {
|
|
180
180
|
const key = [documentId, "sync-state", storageId];
|
|
181
|
-
|
|
182
|
-
|
|
181
|
+
try {
|
|
182
|
+
const loaded = await this.#storageAdapter.load(key);
|
|
183
|
+
return loaded ? A.decodeSyncState(loaded) : undefined;
|
|
184
|
+
}
|
|
185
|
+
catch (e) {
|
|
186
|
+
this.#log(`Error loading sync state for ${documentId} from ${storageId}`);
|
|
187
|
+
return undefined;
|
|
188
|
+
}
|
|
183
189
|
}
|
|
184
190
|
async saveSyncState(documentId, storageId, syncState) {
|
|
185
191
|
const key = [documentId, "sync-state", storageId];
|
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-alpha.7",
|
|
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>",
|
|
@@ -60,5 +60,5 @@
|
|
|
60
60
|
"publishConfig": {
|
|
61
61
|
"access": "public"
|
|
62
62
|
},
|
|
63
|
-
"gitHead": "
|
|
63
|
+
"gitHead": "4279df7dad7ef5f33b1544e3945dab3839fa5ef6"
|
|
64
64
|
}
|
package/src/DocHandle.ts
CHANGED
|
@@ -291,6 +291,63 @@ export class DocHandle<T> extends EventEmitter<DocHandleEvents<T>> {
|
|
|
291
291
|
return A.getHeads(this.#doc)
|
|
292
292
|
}
|
|
293
293
|
|
|
294
|
+
/**
|
|
295
|
+
* Creates a fixed "view" of an automerge document at the given point in time represented
|
|
296
|
+
* by the `heads` passed in. The return value is the same type as docSync() and will return
|
|
297
|
+
* undefined if the object hasn't finished loading.
|
|
298
|
+
*
|
|
299
|
+
* @remarks
|
|
300
|
+
* A point-in-time in an automerge document is an *array* of heads since there may be
|
|
301
|
+
* concurrent edits. This API just returns a topologically sorted history of all edits
|
|
302
|
+
* so every previous entry will be (in some sense) before later ones, but the set of all possible
|
|
303
|
+
* history views would be quite large under concurrency (every thing in each branch against each other).
|
|
304
|
+
* There might be a clever way to think about this, but we haven't found it yet, so for now at least
|
|
305
|
+
* we present a single traversable view which excludes concurrency.
|
|
306
|
+
* @returns The individual heads for every change in the document.
|
|
307
|
+
*/
|
|
308
|
+
history(): A.Heads[] | undefined {
|
|
309
|
+
if (!this.isReady()) {
|
|
310
|
+
return undefined
|
|
311
|
+
}
|
|
312
|
+
// This just returns all the heads as individual strings.
|
|
313
|
+
|
|
314
|
+
return A.topoHistoryTraversal(this.#doc).map(h => [h]) as A.Heads[]
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Creates a fixed "view" of an automerge document at the given point in time represented
|
|
319
|
+
* by the `heads` passed in. The return value is the same type as docSync() and will return
|
|
320
|
+
* undefined if the object hasn't finished loading.
|
|
321
|
+
* @returns
|
|
322
|
+
*/
|
|
323
|
+
view(heads: A.Heads): A.Doc<T> | undefined {
|
|
324
|
+
if (!this.isReady()) {
|
|
325
|
+
return undefined
|
|
326
|
+
}
|
|
327
|
+
return A.view(this.#doc, heads)
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Creates a fixed "view" of an automerge document at the given point in time represented
|
|
332
|
+
* by the `heads` passed in. The return value is the same type as docSync() and will return
|
|
333
|
+
* undefined if the object hasn't finished loading.
|
|
334
|
+
*
|
|
335
|
+
* @remarks
|
|
336
|
+
* We allow specifying both a from/to heads or just a single comparison point, in which case
|
|
337
|
+
* the base will be the current document heads.
|
|
338
|
+
*
|
|
339
|
+
* @returns Automerge patches that go from one document state to the other. Use view() to get the full state.
|
|
340
|
+
*/
|
|
341
|
+
diff(first: A.Heads, second?: A.Heads): A.Patch[] | undefined {
|
|
342
|
+
if (!this.isReady()) {
|
|
343
|
+
return undefined
|
|
344
|
+
}
|
|
345
|
+
// We allow only one set of heads to be specified, in which case we use the doc's heads
|
|
346
|
+
const from = second ? first : this.heads() || [] // because we guard above this should always have useful data
|
|
347
|
+
const to = second ? second : first
|
|
348
|
+
return A.diff(this.#doc, from, to)
|
|
349
|
+
}
|
|
350
|
+
|
|
294
351
|
/**
|
|
295
352
|
* `update` is called any time we have a new document state; could be
|
|
296
353
|
* from a local change, a remote change, or a new document from storage.
|
|
@@ -232,8 +232,13 @@ export class StorageSubsystem {
|
|
|
232
232
|
storageId: StorageId
|
|
233
233
|
): Promise<A.SyncState | undefined> {
|
|
234
234
|
const key = [documentId, "sync-state", storageId]
|
|
235
|
-
|
|
236
|
-
|
|
235
|
+
try {
|
|
236
|
+
const loaded = await this.#storageAdapter.load(key)
|
|
237
|
+
return loaded ? A.decodeSyncState(loaded) : undefined
|
|
238
|
+
} catch (e) {
|
|
239
|
+
this.#log(`Error loading sync state for ${documentId} from ${storageId}`)
|
|
240
|
+
return undefined
|
|
241
|
+
}
|
|
237
242
|
}
|
|
238
243
|
|
|
239
244
|
async saveSyncState(
|
package/test/DocHandle.test.ts
CHANGED
|
@@ -68,6 +68,15 @@ describe("DocHandle", () => {
|
|
|
68
68
|
assert.equal(doc?.foo, "bar")
|
|
69
69
|
})
|
|
70
70
|
|
|
71
|
+
/** HISTORY TRAVERSAL
|
|
72
|
+
* This API is relatively alpha-ish but we're already
|
|
73
|
+
* doing things in our own apps that are fairly ambitious
|
|
74
|
+
* by routing around to a lower-level API.
|
|
75
|
+
* This is an attempt to wrap up the existing practice
|
|
76
|
+
* in a slightly more supportable set of APIs but should be
|
|
77
|
+
* considered provisional: expect further improvements.
|
|
78
|
+
*/
|
|
79
|
+
|
|
71
80
|
it("should return the heads when requested", async () => {
|
|
72
81
|
const handle = setup()
|
|
73
82
|
handle.change(d => (d.foo = "bar"))
|
|
@@ -84,6 +93,79 @@ describe("DocHandle", () => {
|
|
|
84
93
|
assert.deepEqual(handle.heads(), undefined)
|
|
85
94
|
})
|
|
86
95
|
|
|
96
|
+
it("should return the history when requested", async () => {
|
|
97
|
+
const handle = setup()
|
|
98
|
+
handle.change(d => (d.foo = "bar"))
|
|
99
|
+
handle.change(d => (d.foo = "baz"))
|
|
100
|
+
assert.equal(handle.isReady(), true)
|
|
101
|
+
|
|
102
|
+
const history = handle.history()
|
|
103
|
+
assert.deepEqual(handle.history().length, 2)
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
it("should return a commit from the history", async () => {
|
|
107
|
+
const handle = setup()
|
|
108
|
+
handle.change(d => (d.foo = "zero"))
|
|
109
|
+
handle.change(d => (d.foo = "one"))
|
|
110
|
+
handle.change(d => (d.foo = "two"))
|
|
111
|
+
handle.change(d => (d.foo = "three"))
|
|
112
|
+
assert.equal(handle.isReady(), true)
|
|
113
|
+
|
|
114
|
+
const history = handle.history()
|
|
115
|
+
const view = handle.view(history[1])
|
|
116
|
+
assert.deepEqual(view, { foo: "one" })
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
it("should return a commit from the history", async () => {
|
|
120
|
+
const handle = setup()
|
|
121
|
+
handle.change(d => (d.foo = "zero"))
|
|
122
|
+
handle.change(d => (d.foo = "one"))
|
|
123
|
+
handle.change(d => (d.foo = "two"))
|
|
124
|
+
handle.change(d => (d.foo = "three"))
|
|
125
|
+
assert.equal(handle.isReady(), true)
|
|
126
|
+
|
|
127
|
+
const history = handle.history()
|
|
128
|
+
const view = handle.view(history[1])
|
|
129
|
+
assert.deepEqual(view, { foo: "one" })
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
it("should return diffs", async () => {
|
|
133
|
+
const handle = setup()
|
|
134
|
+
handle.change(d => (d.foo = "zero"))
|
|
135
|
+
handle.change(d => (d.foo = "one"))
|
|
136
|
+
handle.change(d => (d.foo = "two"))
|
|
137
|
+
handle.change(d => (d.foo = "three"))
|
|
138
|
+
assert.equal(handle.isReady(), true)
|
|
139
|
+
|
|
140
|
+
const history = handle.history()
|
|
141
|
+
const patches = handle.diff(history[1])
|
|
142
|
+
assert.deepEqual(patches, [
|
|
143
|
+
{ action: "put", path: ["foo"], value: "" },
|
|
144
|
+
{ action: "splice", path: ["foo", 0], value: "one" },
|
|
145
|
+
])
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
it("should support arbitrary diffs too", async () => {
|
|
149
|
+
const handle = setup()
|
|
150
|
+
handle.change(d => (d.foo = "zero"))
|
|
151
|
+
handle.change(d => (d.foo = "one"))
|
|
152
|
+
handle.change(d => (d.foo = "two"))
|
|
153
|
+
handle.change(d => (d.foo = "three"))
|
|
154
|
+
assert.equal(handle.isReady(), true)
|
|
155
|
+
|
|
156
|
+
const history = handle.history()
|
|
157
|
+
const patches = handle.diff(history[1], history[3])
|
|
158
|
+
assert.deepEqual(patches, [
|
|
159
|
+
{ action: "put", path: ["foo"], value: "" },
|
|
160
|
+
{ action: "splice", path: ["foo", 0], value: "three" },
|
|
161
|
+
])
|
|
162
|
+
const backPatches = handle.diff(history[3], history[1])
|
|
163
|
+
assert.deepEqual(backPatches, [
|
|
164
|
+
{ action: "put", path: ["foo"], value: "" },
|
|
165
|
+
{ action: "splice", path: ["foo", 0], value: "one" },
|
|
166
|
+
])
|
|
167
|
+
})
|
|
168
|
+
|
|
87
169
|
/**
|
|
88
170
|
* Once there's a Repo#stop API this case should be covered in accompanying
|
|
89
171
|
* tests and the following test removed.
|
|
@@ -211,6 +211,23 @@ describe("StorageSubsystem", () => {
|
|
|
211
211
|
)
|
|
212
212
|
assert.strictEqual(loadedSyncState, undefined)
|
|
213
213
|
})
|
|
214
|
+
|
|
215
|
+
it("returns a undefined if loading an existing sync state fails", async () => {
|
|
216
|
+
const storage = new StorageSubsystem(adapter)
|
|
217
|
+
|
|
218
|
+
const { documentId } = parseAutomergeUrl(generateAutomergeUrl())
|
|
219
|
+
const bobStorageId = Uuid.v4() as StorageId
|
|
220
|
+
|
|
221
|
+
const syncStateKey = [documentId, "sync-state", bobStorageId]
|
|
222
|
+
// Save garbage data to simulate a corrupted sync state
|
|
223
|
+
await adapter.save(syncStateKey, Buffer.from("invalid data"))
|
|
224
|
+
|
|
225
|
+
const loadedSyncState = await storage.loadSyncState(
|
|
226
|
+
documentId,
|
|
227
|
+
bobStorageId
|
|
228
|
+
)
|
|
229
|
+
assert.strictEqual(loadedSyncState, undefined)
|
|
230
|
+
})
|
|
214
231
|
})
|
|
215
232
|
|
|
216
233
|
describe("storage id", () => {
|