@automerge/automerge-repo 1.0.0-alpha.3 → 1.0.0-alpha.4
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/DocCollection.d.ts +2 -1
- package/dist/DocCollection.d.ts.map +1 -1
- package/dist/DocCollection.js +3 -3
- package/dist/DocHandle.d.ts +8 -3
- package/dist/DocHandle.d.ts.map +1 -1
- package/dist/DocHandle.js +28 -6
- package/dist/DocUrl.d.ts +1 -1
- package/dist/DocUrl.d.ts.map +1 -1
- package/dist/Repo.d.ts.map +1 -1
- package/dist/Repo.js +25 -7
- package/dist/helpers/cbor.d.ts +4 -0
- package/dist/helpers/cbor.d.ts.map +1 -0
- package/dist/helpers/cbor.js +8 -0
- package/dist/helpers/eventPromise.d.ts +1 -1
- package/dist/helpers/eventPromise.d.ts.map +1 -1
- package/dist/helpers/headsAreSame.d.ts +0 -1
- package/dist/helpers/headsAreSame.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/network/NetworkAdapter.d.ts +2 -2
- package/dist/network/NetworkAdapter.d.ts.map +1 -1
- package/dist/network/NetworkAdapter.js +1 -1
- package/dist/network/NetworkSubsystem.d.ts +4 -2
- package/dist/network/NetworkSubsystem.d.ts.map +1 -1
- package/dist/network/NetworkSubsystem.js +30 -7
- package/dist/network/messages.d.ts +2 -2
- package/dist/network/messages.d.ts.map +1 -1
- package/dist/storage/StorageSubsystem.d.ts +1 -1
- package/dist/storage/StorageSubsystem.d.ts.map +1 -1
- package/dist/storage/StorageSubsystem.js +2 -2
- package/dist/synchronizer/DocSynchronizer.d.ts.map +1 -1
- package/dist/synchronizer/DocSynchronizer.js +11 -12
- package/dist/synchronizer/Synchronizer.d.ts +1 -1
- package/dist/synchronizer/Synchronizer.d.ts.map +1 -1
- package/dist/synchronizer/Synchronizer.js +1 -1
- package/fuzz/fuzz.ts +1 -1
- package/package.json +3 -3
- package/src/DocCollection.ts +4 -3
- package/src/DocHandle.ts +34 -4
- package/src/DocUrl.ts +1 -1
- package/src/Repo.ts +23 -7
- package/src/helpers/cbor.ts +10 -0
- package/src/helpers/eventPromise.ts +1 -1
- package/src/helpers/headsAreSame.ts +1 -1
- package/src/index.ts +2 -0
- package/src/network/NetworkAdapter.ts +2 -2
- package/src/network/NetworkSubsystem.ts +33 -6
- package/src/network/messages.ts +2 -2
- package/src/storage/StorageSubsystem.ts +2 -2
- package/src/synchronizer/DocSynchronizer.ts +14 -14
- package/src/synchronizer/Synchronizer.ts +1 -1
- package/test/CollectionSynchronizer.test.ts +1 -1
- package/test/DocCollection.test.ts +2 -2
- package/test/DocHandle.test.ts +5 -5
- package/test/Repo.test.ts +53 -11
- package/test/StorageSubsystem.test.ts +2 -3
- package/test/helpers/DummyNetworkAdapter.ts +11 -2
- package/test/helpers/DummyStorageAdapter.ts +1 -1
- package/tsconfig.json +2 -2
package/dist/DocCollection.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import EventEmitter from "eventemitter3";
|
|
1
|
+
import { EventEmitter } from "eventemitter3";
|
|
2
2
|
import { DocHandle } from "./DocHandle.js";
|
|
3
3
|
import { DocumentId, AutomergeUrl } from "./types.js";
|
|
4
4
|
import { type SharePolicy } from "./Repo.js";
|
|
@@ -37,6 +37,7 @@ interface DocCollectionEvents {
|
|
|
37
37
|
}
|
|
38
38
|
interface DocumentPayload {
|
|
39
39
|
handle: DocHandle<any>;
|
|
40
|
+
isNew: boolean;
|
|
40
41
|
}
|
|
41
42
|
interface DeleteDocumentPayload {
|
|
42
43
|
documentId: DocumentId;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DocCollection.d.ts","sourceRoot":"","sources":["../src/DocCollection.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"DocCollection.d.ts","sourceRoot":"","sources":["../src/DocCollection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAAE,UAAU,EAAyB,YAAY,EAAE,MAAM,YAAY,CAAA;AAC5E,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAA;AAS5C;;;KAGK;AACL,qBAAa,aAAc,SAAQ,YAAY,CAAC,mBAAmB,CAAC;;IAGlE,sDAAsD;IACtD,WAAW,EAAE,WAAW,CAAmB;;IAwB3C,8CAA8C;IAC9C,IAAI,OAAO,uCAEV;IAED;;;;OAIG;IACH,MAAM,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC;IA0BzB;;;OAGG;IACH,IAAI,CAAC,CAAC;IACJ,+CAA+C;IAC/C,YAAY,EAAE,YAAY,GACzB,SAAS,CAAC,CAAC,CAAC;IAwBf,MAAM;IACJ,6CAA6C;IAC7C,EAAE,EAAE,UAAU,GAAG,YAAY;CAchC;AAGD,UAAU,mBAAmB;IAC3B,QAAQ,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,IAAI,CAAA;IACxC,iBAAiB,EAAE,CAAC,GAAG,EAAE,qBAAqB,KAAK,IAAI,CAAA;IACvD,sBAAsB,EAAE,CAAC,GAAG,EAAE,qBAAqB,KAAK,IAAI,CAAA;CAC7D;AAED,UAAU,eAAe;IACvB,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC,CAAA;IACtB,KAAK,EAAE,OAAO,CAAA;CACf;AAED,UAAU,qBAAqB;IAC7B,UAAU,EAAE,UAAU,CAAA;CACvB"}
|
package/dist/DocCollection.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import EventEmitter from "eventemitter3";
|
|
1
|
+
import { EventEmitter } from "eventemitter3";
|
|
2
2
|
import { DocHandle } from "./DocHandle.js";
|
|
3
3
|
import { generateAutomergeUrl, isValidAutomergeUrl, parseAutomergeUrl, } from "./DocUrl.js";
|
|
4
4
|
/**
|
|
@@ -55,7 +55,7 @@ export class DocCollection extends EventEmitter {
|
|
|
55
55
|
// Generate a new UUID and store it in the buffer
|
|
56
56
|
const { documentId } = parseAutomergeUrl(generateAutomergeUrl());
|
|
57
57
|
const handle = this.#getHandle(documentId, true);
|
|
58
|
-
this.emit("document", { handle });
|
|
58
|
+
this.emit("document", { handle, isNew: true });
|
|
59
59
|
return handle;
|
|
60
60
|
}
|
|
61
61
|
/**
|
|
@@ -82,7 +82,7 @@ export class DocCollection extends EventEmitter {
|
|
|
82
82
|
return this.#handleCache[documentId];
|
|
83
83
|
}
|
|
84
84
|
const handle = this.#getHandle(documentId, false);
|
|
85
|
-
this.emit("document", { handle });
|
|
85
|
+
this.emit("document", { handle, isNew: false });
|
|
86
86
|
return handle;
|
|
87
87
|
}
|
|
88
88
|
delete(
|
package/dist/DocHandle.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import * as A from "@automerge/automerge";
|
|
2
|
-
import EventEmitter from "eventemitter3";
|
|
1
|
+
import * as A from "@automerge/automerge/next";
|
|
2
|
+
import { EventEmitter } from "eventemitter3";
|
|
3
3
|
import { StateValue } from "xstate";
|
|
4
4
|
import type { DocumentId, PeerId, AutomergeUrl } from "./types.js";
|
|
5
5
|
/** DocHandle is a wrapper around a single Automerge document that lets us listen for changes. */
|
|
@@ -59,6 +59,8 @@ export declare class DocHandle<T>//
|
|
|
59
59
|
unavailable(): void;
|
|
60
60
|
/** `request` is called by the repo when the document is not found in storage */
|
|
61
61
|
request(): void;
|
|
62
|
+
awaitNetwork(): void;
|
|
63
|
+
networkReady(): void;
|
|
62
64
|
/** `delete` is called by the repo when the document is deleted */
|
|
63
65
|
delete(): void;
|
|
64
66
|
/** `broadcast` sends an arbitrary ephemeral message out to all reachable peers who would receive sync messages from you
|
|
@@ -111,6 +113,7 @@ export interface DocHandleEvents<T> {
|
|
|
111
113
|
export declare const HandleState: {
|
|
112
114
|
readonly IDLE: "idle";
|
|
113
115
|
readonly LOADING: "loading";
|
|
116
|
+
readonly AWAITING_NETWORK: "awaitingNetwork";
|
|
114
117
|
readonly REQUESTING: "requesting";
|
|
115
118
|
readonly READY: "ready";
|
|
116
119
|
readonly FAILED: "failed";
|
|
@@ -123,11 +126,13 @@ export declare const Event: {
|
|
|
123
126
|
readonly FIND: "FIND";
|
|
124
127
|
readonly REQUEST: "REQUEST";
|
|
125
128
|
readonly REQUEST_COMPLETE: "REQUEST_COMPLETE";
|
|
129
|
+
readonly AWAIT_NETWORK: "AWAIT_NETWORK";
|
|
130
|
+
readonly NETWORK_READY: "NETWORK_READY";
|
|
126
131
|
readonly UPDATE: "UPDATE";
|
|
127
132
|
readonly TIMEOUT: "TIMEOUT";
|
|
128
133
|
readonly DELETE: "DELETE";
|
|
129
134
|
readonly MARK_UNAVAILABLE: "MARK_UNAVAILABLE";
|
|
130
135
|
};
|
|
131
|
-
export declare const IDLE: "idle", LOADING: "loading", REQUESTING: "requesting", READY: "ready", FAILED: "failed", DELETED: "deleted", UNAVAILABLE: "unavailable";
|
|
136
|
+
export declare const IDLE: "idle", LOADING: "loading", AWAITING_NETWORK: "awaitingNetwork", REQUESTING: "requesting", READY: "ready", FAILED: "failed", DELETED: "deleted", UNAVAILABLE: "unavailable";
|
|
132
137
|
export {};
|
|
133
138
|
//# sourceMappingURL=DocHandle.d.ts.map
|
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,
|
|
1
|
+
{"version":3,"file":"DocHandle.d.ts","sourceRoot":"","sources":["../src/DocHandle.ts"],"names":[],"mappings":"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"}
|
package/dist/DocHandle.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import * as A from "@automerge/automerge";
|
|
1
|
+
import * as A from "@automerge/automerge/next";
|
|
2
2
|
import debug from "debug";
|
|
3
|
-
import EventEmitter from "eventemitter3";
|
|
3
|
+
import { EventEmitter } from "eventemitter3";
|
|
4
4
|
import { assign, createMachine, interpret, } from "xstate";
|
|
5
5
|
import { waitFor } from "xstate/lib/waitFor.js";
|
|
6
6
|
import { headsAreSame } from "./helpers/headsAreSame.js";
|
|
7
7
|
import { pause } from "./helpers/pause.js";
|
|
8
8
|
import { TimeoutError, withTimeout } from "./helpers/withTimeout.js";
|
|
9
9
|
import { stringifyAutomergeUrl } from "./DocUrl.js";
|
|
10
|
-
import { encode } from "cbor
|
|
10
|
+
import { encode } from "./helpers/cbor.js";
|
|
11
11
|
/** DocHandle is a wrapper around a single Automerge document that lets us listen for changes. */
|
|
12
12
|
export class DocHandle//
|
|
13
13
|
extends EventEmitter {
|
|
@@ -24,7 +24,11 @@ export class DocHandle//
|
|
|
24
24
|
this.#timeoutDelay = timeoutDelay;
|
|
25
25
|
this.#log = debug(`automerge-repo:dochandle:${this.documentId.slice(0, 5)}`);
|
|
26
26
|
// initial doc
|
|
27
|
-
|
|
27
|
+
let doc = A.init();
|
|
28
|
+
// Make an empty change so that we have something to save to disk
|
|
29
|
+
if (isNew) {
|
|
30
|
+
doc = A.emptyChange(doc, {});
|
|
31
|
+
}
|
|
28
32
|
/**
|
|
29
33
|
* Internally we use a state machine to orchestrate document loading and/or syncing, in order to
|
|
30
34
|
* avoid requesting data we already have, or surfacing intermediate values to the consumer.
|
|
@@ -59,6 +63,8 @@ export class DocHandle//
|
|
|
59
63
|
UPDATE: { actions: "onUpdate", target: READY },
|
|
60
64
|
// REQUEST is called by the Repo if the document is not found in storage
|
|
61
65
|
REQUEST: { target: REQUESTING },
|
|
66
|
+
// AWAIT_NETWORK is called by the repo if the document is not found in storage but the network is not yet ready
|
|
67
|
+
AWAIT_NETWORK: { target: AWAITING_NETWORK },
|
|
62
68
|
DELETE: { actions: "onDelete", target: DELETED },
|
|
63
69
|
},
|
|
64
70
|
after: [
|
|
@@ -68,6 +74,11 @@ export class DocHandle//
|
|
|
68
74
|
},
|
|
69
75
|
],
|
|
70
76
|
},
|
|
77
|
+
awaitingNetwork: {
|
|
78
|
+
on: {
|
|
79
|
+
NETWORK_READY: { target: REQUESTING },
|
|
80
|
+
}
|
|
81
|
+
},
|
|
71
82
|
requesting: {
|
|
72
83
|
on: {
|
|
73
84
|
MARK_UNAVAILABLE: {
|
|
@@ -278,6 +289,14 @@ export class DocHandle//
|
|
|
278
289
|
if (this.#state === LOADING)
|
|
279
290
|
this.#machine.send(REQUEST);
|
|
280
291
|
}
|
|
292
|
+
awaitNetwork() {
|
|
293
|
+
if (this.#state === LOADING)
|
|
294
|
+
this.#machine.send(AWAIT_NETWORK);
|
|
295
|
+
}
|
|
296
|
+
networkReady() {
|
|
297
|
+
if (this.#state === AWAITING_NETWORK)
|
|
298
|
+
this.#machine.send(NETWORK_READY);
|
|
299
|
+
}
|
|
281
300
|
/** `delete` is called by the repo when the document is deleted */
|
|
282
301
|
delete() {
|
|
283
302
|
this.#machine.send(DELETE);
|
|
@@ -300,6 +319,7 @@ export class DocHandle//
|
|
|
300
319
|
export const HandleState = {
|
|
301
320
|
IDLE: "idle",
|
|
302
321
|
LOADING: "loading",
|
|
322
|
+
AWAITING_NETWORK: "awaitingNetwork",
|
|
303
323
|
REQUESTING: "requesting",
|
|
304
324
|
READY: "ready",
|
|
305
325
|
FAILED: "failed",
|
|
@@ -312,11 +332,13 @@ export const Event = {
|
|
|
312
332
|
FIND: "FIND",
|
|
313
333
|
REQUEST: "REQUEST",
|
|
314
334
|
REQUEST_COMPLETE: "REQUEST_COMPLETE",
|
|
335
|
+
AWAIT_NETWORK: "AWAIT_NETWORK",
|
|
336
|
+
NETWORK_READY: "NETWORK_READY",
|
|
315
337
|
UPDATE: "UPDATE",
|
|
316
338
|
TIMEOUT: "TIMEOUT",
|
|
317
339
|
DELETE: "DELETE",
|
|
318
340
|
MARK_UNAVAILABLE: "MARK_UNAVAILABLE",
|
|
319
341
|
};
|
|
320
342
|
// CONSTANTS
|
|
321
|
-
export const { IDLE, LOADING, REQUESTING, READY, FAILED, DELETED, UNAVAILABLE, } = HandleState;
|
|
322
|
-
const { CREATE, FIND, REQUEST, UPDATE, TIMEOUT, DELETE, REQUEST_COMPLETE, MARK_UNAVAILABLE, } = Event;
|
|
343
|
+
export const { IDLE, LOADING, AWAITING_NETWORK, REQUESTING, READY, FAILED, DELETED, UNAVAILABLE, } = HandleState;
|
|
344
|
+
const { CREATE, FIND, REQUEST, UPDATE, TIMEOUT, DELETE, REQUEST_COMPLETE, MARK_UNAVAILABLE, AWAIT_NETWORK, NETWORK_READY } = Event;
|
package/dist/DocUrl.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type AutomergeUrl, type BinaryDocumentId, type DocumentId } from "./types";
|
|
1
|
+
import { type AutomergeUrl, type BinaryDocumentId, type DocumentId } from "./types.js";
|
|
2
2
|
export declare const urlPrefix = "automerge:";
|
|
3
3
|
/**
|
|
4
4
|
* given an Automerge URL, return a decoded DocumentId (and the encoded DocumentId)
|
package/dist/DocUrl.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DocUrl.d.ts","sourceRoot":"","sources":["../src/DocUrl.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,UAAU,EAChB,MAAM,
|
|
1
|
+
{"version":3,"file":"DocUrl.d.ts","sourceRoot":"","sources":["../src/DocUrl.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,UAAU,EAChB,MAAM,YAAY,CAAA;AAInB,eAAO,MAAM,SAAS,eAAe,CAAA;AAErC;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,QAAS,YAAY;;;CAIlD,CAAA;AAED,UAAU,4BAA4B;IACpC,UAAU,EAAE,UAAU,GAAG,gBAAgB,CAAA;CAC1C;AAED;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB,oBAE/B,4BAA4B,KAAG,YAQjC,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,QAAS,MAAM,wBAK9C,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,QAAO,YAGpC,CAAA;AAEJ,eAAO,MAAM,kBAAkB,UACtB,UAAU,KAChB,gBAAgB,GAAG,SACyC,CAAA;AAE/D,eAAO,MAAM,kBAAkB,UAAW,gBAAgB,KAAG,UACtB,CAAA"}
|
package/dist/Repo.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Repo.d.ts","sourceRoot":"","sources":["../src/Repo.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAA;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAA;AAEhE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAE/C,oFAAoF;AACpF,qBAAa,IAAK,SAAQ,aAAa;;IAGrC,gBAAgB,EAAE,gBAAgB,CAAA;IAClC,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;gBAEvB,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,UAAU;
|
|
1
|
+
{"version":3,"file":"Repo.d.ts","sourceRoot":"","sources":["../src/Repo.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAA;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAA;AAEhE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAE/C,oFAAoF;AACpF,qBAAa,IAAK,SAAQ,aAAa;;IAGrC,gBAAgB,EAAE,gBAAgB,CAAA;IAClC,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;gBAEvB,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,UAAU;CAiGlE;AAED,MAAM,WAAW,UAAU;IACzB,4BAA4B;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAA;IAEf,gDAAgD;IAChD,OAAO,CAAC,EAAE,cAAc,CAAA;IAExB,oDAAoD;IACpD,OAAO,EAAE,cAAc,EAAE,CAAA;IAEzB;;;OAGG;IACH,WAAW,CAAC,EAAE,WAAW,CAAA;CAC1B;AAED,MAAM,MAAM,WAAW,GAAG,CACxB,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,UAAU,KACpB,OAAO,CAAC,OAAO,CAAC,CAAA"}
|
package/dist/Repo.js
CHANGED
|
@@ -15,16 +15,22 @@ export class Repo extends DocCollection {
|
|
|
15
15
|
// DOC COLLECTION
|
|
16
16
|
// The `document` event is fired by the DocCollection any time we create a new document or look
|
|
17
17
|
// up a document by ID. We listen for it in order to wire up storage and network synchronization.
|
|
18
|
-
this.on("document", async ({ handle }) => {
|
|
18
|
+
this.on("document", async ({ handle, isNew }) => {
|
|
19
19
|
if (storageSubsystem) {
|
|
20
20
|
// Save when the document changes
|
|
21
21
|
handle.on("heads-changed", async ({ handle, doc }) => {
|
|
22
22
|
await storageSubsystem.saveDoc(handle.documentId, doc);
|
|
23
23
|
});
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
if (isNew) {
|
|
25
|
+
// this is a new document, immediately save it
|
|
26
|
+
await storageSubsystem.saveDoc(handle.documentId, handle.docSync());
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
// Try to load from disk
|
|
30
|
+
const loadedDoc = await storageSubsystem.loadDoc(handle.documentId);
|
|
31
|
+
if (loadedDoc) {
|
|
32
|
+
handle.update(() => loadedDoc);
|
|
33
|
+
}
|
|
28
34
|
}
|
|
29
35
|
}
|
|
30
36
|
handle.on("unavailable", () => {
|
|
@@ -33,7 +39,17 @@ export class Repo extends DocCollection {
|
|
|
33
39
|
documentId: handle.documentId,
|
|
34
40
|
});
|
|
35
41
|
});
|
|
36
|
-
|
|
42
|
+
if (this.networkSubsystem.isReady()) {
|
|
43
|
+
handle.request();
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
handle.awaitNetwork();
|
|
47
|
+
this.networkSubsystem.whenReady().then(() => {
|
|
48
|
+
handle.networkReady();
|
|
49
|
+
}).catch(err => {
|
|
50
|
+
this.#log("error waiting for network", { err });
|
|
51
|
+
});
|
|
52
|
+
}
|
|
37
53
|
// Register the document with the synchronizer. This advertises our interest in the document.
|
|
38
54
|
synchronizer.addDocument(handle.documentId);
|
|
39
55
|
});
|
|
@@ -41,7 +57,9 @@ export class Repo extends DocCollection {
|
|
|
41
57
|
// TODO Pass the delete on to the network
|
|
42
58
|
// synchronizer.removeDocument(documentId)
|
|
43
59
|
if (storageSubsystem) {
|
|
44
|
-
storageSubsystem.remove(documentId)
|
|
60
|
+
storageSubsystem.remove(documentId).catch(err => {
|
|
61
|
+
this.#log("error deleting document", { documentId, err });
|
|
62
|
+
});
|
|
45
63
|
}
|
|
46
64
|
});
|
|
47
65
|
// SYNCHRONIZER
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cbor.d.ts","sourceRoot":"","sources":["../../src/helpers/cbor.ts"],"names":[],"mappings":";AAEA,wBAAgB,MAAM,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,CAGvC;AAED,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,GAAG,CAEpD"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import EventEmitter from "eventemitter3";
|
|
1
|
+
import { EventEmitter } from "eventemitter3";
|
|
2
2
|
/** Returns a promise that resolves when the given event is emitted on the given emitter. */
|
|
3
3
|
export declare const eventPromise: (emitter: EventEmitter, event: string) => Promise<any>;
|
|
4
4
|
export declare const eventPromises: (emitters: EventEmitter[], event: string) => Promise<any[]>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eventPromise.d.ts","sourceRoot":"","sources":["../../src/helpers/eventPromise.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"eventPromise.d.ts","sourceRoot":"","sources":["../../src/helpers/eventPromise.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAE5C,4FAA4F;AAC5F,eAAO,MAAM,YAAY,YAAa,YAAY,SAAS,MAAM,iBACE,CAAA;AAEnE,eAAO,MAAM,aAAa,aAAc,YAAY,EAAE,SAAS,MAAM,mBAGpE,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"headsAreSame.d.ts","sourceRoot":"","sources":["../../src/helpers/headsAreSame.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"headsAreSame.d.ts","sourceRoot":"","sources":["../../src/helpers/headsAreSame.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,YAAY,iCAExB,CAAA"}
|
package/dist/index.d.ts
CHANGED
|
@@ -11,4 +11,5 @@ export { StorageSubsystem } from "./storage/StorageSubsystem.js";
|
|
|
11
11
|
export { CollectionSynchronizer } from "./synchronizer/CollectionSynchronizer.js";
|
|
12
12
|
export { parseAutomergeUrl, isValidAutomergeUrl, stringifyAutomergeUrl as generateAutomergeUrl, } from "./DocUrl.js";
|
|
13
13
|
export * from "./types.js";
|
|
14
|
+
export * as cbor from "./helpers/cbor.js";
|
|
14
15
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AACvD,YAAY,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAA;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAC5D,YAAY,EACV,WAAW,EACX,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,6BAA6B,CAAA;AAMpC,YAAY,EACV,OAAO,EACP,qBAAqB,EACrB,gBAAgB,EAChB,WAAW,GACZ,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAA;AAChE,OAAO,EAAE,IAAI,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAA;AAClD,OAAO,EAAE,cAAc,EAAE,KAAK,UAAU,EAAE,MAAM,6BAA6B,CAAA;AAC7E,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAA;AAChE,OAAO,EAAE,sBAAsB,EAAE,MAAM,0CAA0C,CAAA;AACjF,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,IAAI,oBAAoB,GAC9C,MAAM,aAAa,CAAA;AACpB,cAAc,YAAY,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AACvD,YAAY,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAA;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAC5D,YAAY,EACV,WAAW,EACX,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,6BAA6B,CAAA;AAMpC,YAAY,EACV,OAAO,EACP,qBAAqB,EACrB,gBAAgB,EAChB,WAAW,GACZ,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAA;AAChE,OAAO,EAAE,IAAI,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAA;AAClD,OAAO,EAAE,cAAc,EAAE,KAAK,UAAU,EAAE,MAAM,6BAA6B,CAAA;AAC7E,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAA;AAChE,OAAO,EAAE,sBAAsB,EAAE,MAAM,0CAA0C,CAAA;AACjF,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,IAAI,oBAAoB,GAC9C,MAAM,aAAa,CAAA;AACpB,cAAc,YAAY,CAAA;AAE1B,OAAO,KAAK,IAAI,MAAM,mBAAmB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -8,3 +8,4 @@ export { StorageSubsystem } from "./storage/StorageSubsystem.js";
|
|
|
8
8
|
export { CollectionSynchronizer } from "./synchronizer/CollectionSynchronizer.js";
|
|
9
9
|
export { parseAutomergeUrl, isValidAutomergeUrl, stringifyAutomergeUrl as generateAutomergeUrl, } from "./DocUrl.js";
|
|
10
10
|
export * from "./types.js";
|
|
11
|
+
export * as cbor from "./helpers/cbor.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import EventEmitter from "eventemitter3";
|
|
1
|
+
import { EventEmitter } from "eventemitter3";
|
|
2
2
|
import { PeerId } from "../types.js";
|
|
3
3
|
import { Message } from "./messages.js";
|
|
4
4
|
export declare abstract class NetworkAdapter extends EventEmitter<NetworkAdapterEvents> {
|
|
@@ -9,7 +9,7 @@ export declare abstract class NetworkAdapter extends EventEmitter<NetworkAdapter
|
|
|
9
9
|
abstract leave(): void;
|
|
10
10
|
}
|
|
11
11
|
export interface NetworkAdapterEvents {
|
|
12
|
-
|
|
12
|
+
ready: (payload: OpenPayload) => void;
|
|
13
13
|
close: () => void;
|
|
14
14
|
"peer-candidate": (payload: PeerCandidatePayload) => void;
|
|
15
15
|
"peer-disconnected": (payload: PeerDisconnectedPayload) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NetworkAdapter.d.ts","sourceRoot":"","sources":["../../src/network/NetworkAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"NetworkAdapter.d.ts","sourceRoot":"","sources":["../../src/network/NetworkAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAEvC,8BAAsB,cAAe,SAAQ,YAAY,CAAC,oBAAoB,CAAC;IAC7E,MAAM,CAAC,EAAE,MAAM,CAAA;IAEf,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI;IAEpC,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAErC,QAAQ,CAAC,IAAI,IAAI,IAAI;IAErB,QAAQ,CAAC,KAAK,IAAI,IAAI;CACvB;AAID,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,CAAA;IACrC,KAAK,EAAE,MAAM,IAAI,CAAA;IACjB,gBAAgB,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,IAAI,CAAA;IACzD,mBAAmB,EAAE,CAAC,OAAO,EAAE,uBAAuB,KAAK,IAAI,CAAA;IAC/D,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;CACpC;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,cAAc,CAAA;CACxB;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,CAAA;CACf"}
|
|
@@ -1,21 +1,23 @@
|
|
|
1
|
-
import EventEmitter from "eventemitter3";
|
|
1
|
+
import { EventEmitter } from "eventemitter3";
|
|
2
2
|
import { PeerId } from "../types.js";
|
|
3
3
|
import { NetworkAdapter, PeerDisconnectedPayload } from "./NetworkAdapter.js";
|
|
4
4
|
import { Message, MessageContents } from "./messages.js";
|
|
5
5
|
export declare class NetworkSubsystem extends EventEmitter<NetworkSubsystemEvents> {
|
|
6
6
|
#private;
|
|
7
|
-
private adapters;
|
|
8
7
|
peerId: PeerId;
|
|
9
8
|
constructor(adapters: NetworkAdapter[], peerId?: PeerId);
|
|
10
9
|
addNetworkAdapter(networkAdapter: NetworkAdapter): void;
|
|
11
10
|
send(message: MessageContents): void;
|
|
12
11
|
join(): void;
|
|
13
12
|
leave(): void;
|
|
13
|
+
isReady: () => boolean;
|
|
14
|
+
whenReady: () => Promise<void>;
|
|
14
15
|
}
|
|
15
16
|
export interface NetworkSubsystemEvents {
|
|
16
17
|
peer: (payload: PeerPayload) => void;
|
|
17
18
|
"peer-disconnected": (payload: PeerDisconnectedPayload) => void;
|
|
18
19
|
message: (payload: Message) => void;
|
|
20
|
+
"ready": () => void;
|
|
19
21
|
}
|
|
20
22
|
export interface PeerPayload {
|
|
21
23
|
peerId: PeerId;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NetworkSubsystem.d.ts","sourceRoot":"","sources":["../../src/network/NetworkSubsystem.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"NetworkSubsystem.d.ts","sourceRoot":"","sources":["../../src/network/NetworkSubsystem.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,cAAc,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAA;AAE7E,OAAO,EAIL,OAAO,EACP,eAAe,EAChB,MAAM,eAAe,CAAA;AAUtB,qBAAa,gBAAiB,SAAQ,YAAY,CAAC,sBAAsB,CAAC;;IAY/D,MAAM;gBADb,QAAQ,EAAE,cAAc,EAAE,EACnB,MAAM,SAAiB;IAOhC,iBAAiB,CAAC,cAAc,EAAE,cAAc;IAkEhD,IAAI,CAAC,OAAO,EAAE,eAAe;IA2B7B,IAAI;IAKJ,KAAK;IAKL,OAAO,gBAEN;IAED,SAAS,sBAUR;CACF;AAQD,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,CAAA;IACpC,mBAAmB,EAAE,CAAC,OAAO,EAAE,uBAAuB,KAAK,IAAI,CAAA;IAC/D,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;IACnC,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAA;CACf"}
|
|
@@ -1,24 +1,31 @@
|
|
|
1
|
-
import EventEmitter from "eventemitter3";
|
|
1
|
+
import { EventEmitter } from "eventemitter3";
|
|
2
2
|
import { isEphemeralMessage, isValidMessage, } from "./messages.js";
|
|
3
3
|
import debug from "debug";
|
|
4
4
|
const getEphemeralMessageSource = (message) => `${message.senderId}:${message.sessionId}`;
|
|
5
5
|
export class NetworkSubsystem extends EventEmitter {
|
|
6
|
-
adapters;
|
|
7
6
|
peerId;
|
|
8
7
|
#log;
|
|
9
8
|
#adaptersByPeer = {};
|
|
10
9
|
#count = 0;
|
|
11
10
|
#sessionId = Math.random().toString(36).slice(2);
|
|
12
11
|
#ephemeralSessionCounts = {};
|
|
12
|
+
#readyAdapterCount = 0;
|
|
13
|
+
#adapters = [];
|
|
13
14
|
constructor(adapters, peerId = randomPeerId()) {
|
|
14
15
|
super();
|
|
15
|
-
this.adapters = adapters;
|
|
16
16
|
this.peerId = peerId;
|
|
17
17
|
this.#log = debug(`automerge-repo:network:${this.peerId}`);
|
|
18
|
-
|
|
18
|
+
adapters.forEach(a => this.addNetworkAdapter(a));
|
|
19
19
|
}
|
|
20
20
|
addNetworkAdapter(networkAdapter) {
|
|
21
|
-
|
|
21
|
+
this.#adapters.push(networkAdapter);
|
|
22
|
+
networkAdapter.once("ready", () => {
|
|
23
|
+
this.#readyAdapterCount++;
|
|
24
|
+
this.#log("Adapters ready: ", this.#readyAdapterCount, "/", this.#adapters.length);
|
|
25
|
+
if (this.#readyAdapterCount === this.#adapters.length) {
|
|
26
|
+
this.emit("ready");
|
|
27
|
+
}
|
|
28
|
+
});
|
|
22
29
|
networkAdapter.on("peer-candidate", ({ peerId }) => {
|
|
23
30
|
this.#log(`peer candidate: ${peerId} `);
|
|
24
31
|
// TODO: This is where authentication would happen
|
|
@@ -58,6 +65,7 @@ export class NetworkSubsystem extends EventEmitter {
|
|
|
58
65
|
}
|
|
59
66
|
});
|
|
60
67
|
});
|
|
68
|
+
networkAdapter.connect(this.peerId);
|
|
61
69
|
networkAdapter.join();
|
|
62
70
|
}
|
|
63
71
|
send(message) {
|
|
@@ -87,12 +95,27 @@ export class NetworkSubsystem extends EventEmitter {
|
|
|
87
95
|
}
|
|
88
96
|
join() {
|
|
89
97
|
this.#log(`Joining network`);
|
|
90
|
-
this
|
|
98
|
+
this.#adapters.forEach(a => a.join());
|
|
91
99
|
}
|
|
92
100
|
leave() {
|
|
93
101
|
this.#log(`Leaving network`);
|
|
94
|
-
this
|
|
102
|
+
this.#adapters.forEach(a => a.leave());
|
|
95
103
|
}
|
|
104
|
+
isReady = () => {
|
|
105
|
+
return this.#readyAdapterCount === this.#adapters.length;
|
|
106
|
+
};
|
|
107
|
+
whenReady = async () => {
|
|
108
|
+
if (this.isReady()) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
return new Promise(resolve => {
|
|
113
|
+
this.once("ready", () => {
|
|
114
|
+
resolve();
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
};
|
|
96
119
|
}
|
|
97
120
|
function randomPeerId() {
|
|
98
121
|
return `user-${Math.round(Math.random() * 100000)}`;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { SessionId } from "../EphemeralData";
|
|
2
|
-
import { DocumentId, PeerId } from "../types";
|
|
1
|
+
import { SessionId } from "../EphemeralData.js";
|
|
2
|
+
import { DocumentId, PeerId } from "../types.js";
|
|
3
3
|
export declare function isValidMessage(message: NetworkAdapterMessage): message is SyncMessage | EphemeralMessage | RequestMessage | DocumentUnavailableMessage;
|
|
4
4
|
export declare function isDocumentUnavailableMessage(message: NetworkAdapterMessage): message is DocumentUnavailableMessage;
|
|
5
5
|
export declare function isRequestMessage(message: NetworkAdapterMessage): message is RequestMessage;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/network/messages.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/network/messages.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEhD,wBAAgB,cAAc,CAC5B,OAAO,EAAE,qBAAqB,GAC7B,OAAO,IACN,WAAW,GACX,gBAAgB,GAChB,cAAc,GACd,0BAA0B,CAU7B;AAED,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,qBAAqB,GAC7B,OAAO,IAAI,0BAA0B,CAEvC;AAED,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,qBAAqB,GAC7B,OAAO,IAAI,cAAc,CAE3B;AAED,wBAAgB,aAAa,CAC3B,OAAO,EAAE,qBAAqB,GAC7B,OAAO,IAAI,WAAW,CAExB;AAED,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,qBAAqB,GAAG,eAAe,GAC/C,OAAO,IAAI,gBAAgB,GAAG,wBAAwB,CAExD;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,UAAU,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,UAAU,CAAA;CACvB;AAED,MAAM,MAAM,WAAW,GAAG,mBAAmB,GAAG,mBAAmB,CAAA;AAEnE,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,SAAS,CAAA;CACrB;AAED,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,WAAW,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,UAAU,CAAA;IACtB,IAAI,EAAE,UAAU,CAAA;CACjB;AAED,MAAM,MAAM,gBAAgB,GAAG,wBAAwB,GACrD,wBAAwB,CAAA;AAE1B,MAAM,WAAW,kCAAkC;IACjD,IAAI,EAAE,iBAAiB,CAAA;IACvB,UAAU,EAAE,UAAU,CAAA;IACtB,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,MAAM,0BAA0B,GAAG,mBAAmB,GAC1D,kCAAkC,CAAA;AAEpC,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,SAAS,CAAA;IACf,IAAI,EAAE,UAAU,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,UAAU,CAAA;CACvB;AAED,MAAM,MAAM,cAAc,GAAG,mBAAmB,GAAG,sBAAsB,CAAA;AAEzE,MAAM,MAAM,eAAe,GACvB,mBAAmB,GACnB,wBAAwB,GACxB,sBAAsB,GACtB,kCAAkC,CAAA;AAEtC,MAAM,MAAM,OAAO,GACf,WAAW,GACX,gBAAgB,GAChB,cAAc,GACd,0BAA0B,CAAA;AAE9B,MAAM,MAAM,mBAAmB,GAC3B,WAAW,GACX,cAAc,GACd,0BAA0B,GAC1B,gBAAgB,CAAA;AAEpB,KAAK,aAAa,GAAG;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,QAAQ,CAAA;CACf,CAAA;AAED,KAAK,cAAc,GAAG;IACpB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,SAAS,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG,aAAa,GAAG,cAAc,GAAG,OAAO,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StorageSubsystem.d.ts","sourceRoot":"","sources":["../../src/storage/StorageSubsystem.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"StorageSubsystem.d.ts","sourceRoot":"","sources":["../../src/storage/StorageSubsystem.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,2BAA2B,CAAA;AAC9C,OAAO,EAAE,cAAc,EAAc,MAAM,qBAAqB,CAAA;AAEhE,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAA;AAa7C,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG,aAAa,CAAA;AAelD,qBAAa,gBAAgB;;gBAMf,cAAc,EAAE,cAAc;IAqDpC,OAAO,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;IA0B/D,OAAO,CAAC,UAAU,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAanE,MAAM,CAAC,UAAU,EAAE,UAAU;CAgCpC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as A from "@automerge/automerge";
|
|
1
|
+
import * as A from "@automerge/automerge/next";
|
|
2
2
|
import * as sha256 from "fast-sha256";
|
|
3
3
|
import { mergeArrays } from "../helpers/mergeArrays.js";
|
|
4
4
|
import debug from "debug";
|
|
@@ -11,7 +11,7 @@ function keyHash(binary) {
|
|
|
11
11
|
}
|
|
12
12
|
function headsHash(heads) {
|
|
13
13
|
let encoder = new TextEncoder();
|
|
14
|
-
let headsbinary = mergeArrays(heads.map(h => encoder.encode(h)));
|
|
14
|
+
let headsbinary = mergeArrays(heads.map((h) => encoder.encode(h)));
|
|
15
15
|
return keyHash(headsbinary);
|
|
16
16
|
}
|
|
17
17
|
export class StorageSubsystem {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DocSynchronizer.d.ts","sourceRoot":"","sources":["../../src/synchronizer/DocSynchronizer.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"DocSynchronizer.d.ts","sourceRoot":"","sources":["../../src/synchronizer/DocSynchronizer.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,SAAS,EAKV,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAGhD,OAAO,EACL,gBAAgB,EAIhB,cAAc,EACd,mBAAmB,EACnB,WAAW,EACZ,MAAM,wBAAwB,CAAA;AAE/B,KAAK,kBAAkB,GAAG,SAAS,GAAG,KAAK,GAAG,aAAa,GAAG,OAAO,CAAA;AAGrE;;;GAGG;AACH,qBAAa,eAAgB,SAAQ,YAAY;;IAiBnC,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC;IAoB1C,IAAI,UAAU,uCAEb;IAED,IAAI,UAAU,qCAEb;IAiHD,OAAO,CAAC,MAAM,EAAE,MAAM;IAItB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE;IA6B3B,OAAO,CAAC,MAAM,EAAE,MAAM;IAKtB,cAAc,CAAC,OAAO,EAAE,mBAAmB;IAkB3C,uBAAuB,CAAC,OAAO,EAAE,gBAAgB;IAuBjD,kBAAkB,CAAC,OAAO,EAAE,WAAW,GAAG,cAAc;CA2EzD"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as A from "@automerge/automerge";
|
|
1
|
+
import * as A from "@automerge/automerge/next";
|
|
2
2
|
import { READY, REQUESTING, UNAVAILABLE, } from "../DocHandle.js";
|
|
3
3
|
import { Synchronizer } from "./Synchronizer.js";
|
|
4
4
|
import debug from "debug";
|
|
@@ -124,7 +124,7 @@ export class DocSynchronizer extends Synchronizer {
|
|
|
124
124
|
this.#log(logText, decoded);
|
|
125
125
|
// expanding is expensive, so only do it if we're logging at this level
|
|
126
126
|
const expanded = this.#opsLog.enabled
|
|
127
|
-
? decoded.changes.flatMap(change => A.decodeChange(change).ops.map(op => JSON.stringify(op)))
|
|
127
|
+
? decoded.changes.flatMap((change) => A.decodeChange(change).ops.map((op) => JSON.stringify(op)))
|
|
128
128
|
: null;
|
|
129
129
|
this.#opsLog(logText, expanded);
|
|
130
130
|
};
|
|
@@ -134,19 +134,18 @@ export class DocSynchronizer extends Synchronizer {
|
|
|
134
134
|
}
|
|
135
135
|
beginSync(peerIds) {
|
|
136
136
|
this.#log(`beginSync: ${peerIds.join(", ")}`);
|
|
137
|
+
// HACK: if we have a sync state already, we round-trip it through the encoding system to make
|
|
138
|
+
// sure state is preserved. This prevents an infinite loop caused by failed attempts to send
|
|
139
|
+
// messages during disconnection.
|
|
140
|
+
// TODO: cover that case with a test and remove this hack
|
|
141
|
+
peerIds.forEach(peerId => {
|
|
142
|
+
const syncStateRaw = this.#getSyncState(peerId);
|
|
143
|
+
const syncState = A.decodeSyncState(A.encodeSyncState(syncStateRaw));
|
|
144
|
+
this.#setSyncState(peerId, syncState);
|
|
145
|
+
});
|
|
137
146
|
// At this point if we don't have anything in our storage, we need to use an empty doc to sync
|
|
138
147
|
// with; but we don't want to surface that state to the front end
|
|
139
148
|
void this.handle.doc([READY, REQUESTING, UNAVAILABLE]).then(doc => {
|
|
140
|
-
// if we don't have any peers, then we can say the document is unavailable
|
|
141
|
-
// HACK: if we have a sync state already, we round-trip it through the encoding system to make
|
|
142
|
-
// sure state is preserved. This prevents an infinite loop caused by failed attempts to send
|
|
143
|
-
// messages during disconnection.
|
|
144
|
-
// TODO: cover that case with a test and remove this hack
|
|
145
|
-
peerIds.forEach(peerId => {
|
|
146
|
-
const syncStateRaw = this.#getSyncState(peerId);
|
|
147
|
-
const syncState = A.decodeSyncState(A.encodeSyncState(syncStateRaw));
|
|
148
|
-
this.#setSyncState(peerId, syncState);
|
|
149
|
-
});
|
|
150
149
|
// we register out peers first, then say that sync has started
|
|
151
150
|
this.#syncStarted = true;
|
|
152
151
|
this.#checkDocUnavailable();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import EventEmitter from "eventemitter3";
|
|
1
|
+
import { EventEmitter } from "eventemitter3";
|
|
2
2
|
import { Message, MessageContents } from "../network/messages.js";
|
|
3
3
|
export declare abstract class Synchronizer extends EventEmitter<SynchronizerEvents> {
|
|
4
4
|
abstract receiveMessage(message: Message): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Synchronizer.d.ts","sourceRoot":"","sources":["../../src/synchronizer/Synchronizer.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"Synchronizer.d.ts","sourceRoot":"","sources":["../../src/synchronizer/Synchronizer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAC5C,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAEjE,8BAAsB,YAAa,SAAQ,YAAY,CAAC,kBAAkB,CAAC;IACzE,QAAQ,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;CAChD;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,IAAI,CAAA;CACxC"}
|
package/fuzz/fuzz.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import assert from "assert"
|
|
2
2
|
import { MessageChannelNetworkAdapter } from "@automerge/automerge-repo-network-messagechannel"
|
|
3
|
-
import * as Automerge from "@automerge/automerge"
|
|
3
|
+
import * as Automerge from "@automerge/automerge/next"
|
|
4
4
|
|
|
5
5
|
import { DocHandle, DocumentId, PeerId, SharePolicy } from "../src"
|
|
6
6
|
import { eventPromise } from "../src/helpers/eventPromise.js"
|