@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.
@@ -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.
@@ -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;IAM7B,aAAa,CACjB,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,SAAS,EACpB,SAAS,EAAE,CAAC,CAAC,SAAS,GACrB,OAAO,CAAC,IAAI,CAAC;CA8CjB"}
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
- const loaded = await this.#storageAdapter.load(key);
182
- return loaded ? A.decodeSyncState(loaded) : undefined;
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.5",
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": "9f10cdceb172f92cdf2dc1be361a940dfd3c5858"
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
- const loaded = await this.#storageAdapter.load(key)
236
- return loaded ? A.decodeSyncState(loaded) : undefined
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(
@@ -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", () => {