@automerge/automerge-repo-network-websocket 1.1.3 → 1.1.5
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 +25 -27
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/index.ts +10 -3
- package/test/Websocket.test.ts +2 -2
package/README.md
CHANGED
|
@@ -25,38 +25,37 @@ Before sync can continue each peer needs to exchange peer IDs and agree on the
|
|
|
25
25
|
protocol version they are using (although currently there is only one version).
|
|
26
26
|
Handshake is the following steps:
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
- Once a connection is established the initiating peer sends a
|
|
29
29
|
[join](#join) message with the `senderId` set to the initiating peers ID and
|
|
30
30
|
the `protocolVersion` set to "1"
|
|
31
|
-
|
|
31
|
+
- The receiving peer waits until it receives a message from the initiating
|
|
32
32
|
peer, if the initiating peer receives a message before sending the join message
|
|
33
33
|
the initiating peer SHOULD terminate the connection.
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
34
|
+
- When the receiving peer receives the join message
|
|
35
|
+
- if the `protocolVersion` is not "1" the receiving peer sends an
|
|
36
|
+
[error](#error) message and terminates the connection
|
|
37
|
+
- otherwise
|
|
38
|
+
- store the `senderId` as the peer ID of the initiating peer
|
|
39
|
+
- emit a "peer-candidate" event with the sender ID as the peer
|
|
40
|
+
- respond with a [peer](#peer) message with the `targetId` set to the
|
|
41
|
+
initiating peers peer ID, the `senderId` set to the receiving peers
|
|
42
|
+
peer ID and the `selectedProtocolVersion` set to "1"
|
|
43
|
+
- begin the sync phase
|
|
44
|
+
- Once the initiating peer has sent the join message it waits for a peer message
|
|
45
45
|
in response. If it receives any other message type before the join message
|
|
46
46
|
the receiving peer should send an [error](#error) message and terminates the
|
|
47
47
|
connection
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
- When the initiating peer receives the peer message
|
|
49
|
+
- it stores the `senderId` as the peer ID of the receiving peer.
|
|
50
|
+
- it emits a "peer-candidate" event with the sender ID as the peer
|
|
51
|
+
- if the `selectedProtocolVersion` is anything other than "1" the initiating
|
|
52
52
|
peer sends an [error](#error) message and terminates the connection
|
|
53
|
-
|
|
53
|
+
- it begins the sync phase
|
|
54
54
|
|
|
55
55
|
#### Peer IDs and storage IDs
|
|
56
56
|
|
|
57
57
|
The peer ID is an ephemeral ID which is assumed to only live for the lifetime of the process which advertises the given ID (e.g. a browser tab). Peers may optionally advertise a storage ID in the `join` and `peer` messages, this is an ID which is assumed to be tied to a persistent storage of some kind (e.g. an IndexedDB in a browser). Many peer IDs can advertise the same storage ID (as in the case of many browser tabs). The use of a storage ID allows other peers to know whether to save and reload sync states for a given peer (if the peer advertises a storage ID, then save and reload the sync state attached to that storage ID).
|
|
58
58
|
|
|
59
|
-
|
|
60
59
|
### Sync Phase
|
|
61
60
|
|
|
62
61
|
In the sync phase either side may send a [request](#request), [sync](#sync),
|
|
@@ -71,13 +70,13 @@ from the `NetworkAdapter` on receipt.
|
|
|
71
70
|
|
|
72
71
|
In some cases peers wish to know about the state of peers who are separated from them by several intermediate peers. For example, a tab running a text editor may wish to show whether the contents of the editor are up to date with respect to a tab running in a browser on another users device. This is achieved by gossiping remote heads across intermediate nodes. The logic for this is the following:
|
|
73
72
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
73
|
+
- For a given connection each peer maintains a list of the storage IDs the remote peer is interested in (note this is storage IDs, not peer IDs)
|
|
74
|
+
- Any peer can send a [`remote-subscription-changed`](#remote-subscription-changed) message to change the set of storage IDs they want the recipient to watch on the sender's behalf
|
|
75
|
+
- Any time a peer receives a sync message it checks:
|
|
76
|
+
- Is the sync message from a peer with a storage ID which some other remote peer has registered interest in
|
|
77
|
+
- Is the remote peer permitted access to the document which the message pertains to (i.e. either the `sharePolicy` return `true` or the local peer is already syncing the document with the remote)
|
|
78
|
+
- The local peer sends a [`remote-heads-changed`](#remote-heads-changed) message to each remote peer who passes these checks
|
|
79
|
+
- Additionally, whenever the local peer receives a `remote-heads-changed` message it performs the same checks and additionally checks if the timestamp on the `remote-heads-changed` message is greater than the last timestamp for the same storage ID/document combination and if so it forwards it.
|
|
81
80
|
|
|
82
81
|
In the `browser <-> sync server <-> browser` text editor example above each browser tab would send a `remote-subscription-changed` message to the sync server adding the other browsers storage ID (presumably communicated out of band) to their subscriptions with the sync server. The sync server will then send `remote-heads-changed` messages to each tab when their heads change.
|
|
83
82
|
|
|
@@ -205,7 +204,6 @@ it
|
|
|
205
204
|
|
|
206
205
|
Sent when a peer wants to send an ephemeral message to another peer
|
|
207
206
|
|
|
208
|
-
|
|
209
207
|
```cddl
|
|
210
208
|
{
|
|
211
209
|
type: "ephemeral",
|
package/dist/index.d.ts
CHANGED
|
@@ -14,6 +14,6 @@
|
|
|
14
14
|
* */
|
|
15
15
|
export { BrowserWebSocketClientAdapter } from "./BrowserWebSocketClientAdapter.js";
|
|
16
16
|
export { NodeWSServerAdapter } from "./NodeWSServerAdapter.js";
|
|
17
|
-
export type { FromClientMessage, FromServerMessage, JoinMessage, LeaveMessage, ErrorMessage, PeerMessage } from "./messages.js";
|
|
17
|
+
export type { FromClientMessage, FromServerMessage, JoinMessage, LeaveMessage, ErrorMessage, PeerMessage, } from "./messages.js";
|
|
18
18
|
export type { ProtocolVersion, ProtocolV1 } from "./protocolVersion.js";
|
|
19
19
|
//# 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;;;;;;;;;;;;;KAaK;AACL,OAAO,EAAE,6BAA6B,EAAE,MAAM,oCAAoC,CAAA;AAClF,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAC9D,YAAY,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;KAaK;AACL,OAAO,EAAE,6BAA6B,EAAE,MAAM,oCAAoC,CAAA;AAClF,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAC9D,YAAY,EACV,iBAAiB,EACjB,iBAAiB,EACjB,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,WAAW,GACZ,MAAM,eAAe,CAAA;AACtB,YAAY,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@automerge/automerge-repo-network-websocket",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.5",
|
|
4
4
|
"description": "isomorphic node/browser Websocket network adapter for Automerge Repo",
|
|
5
5
|
"repository": "https://github.com/automerge/automerge-repo/tree/master/packages/automerge-repo-network-websocket",
|
|
6
6
|
"author": "Peter van Hardenberg <pvh@pvh.ca>",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"test": "vitest"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@automerge/automerge-repo": "1.1.
|
|
16
|
+
"@automerge/automerge-repo": "1.1.5",
|
|
17
17
|
"cbor-x": "^1.3.0",
|
|
18
18
|
"debug": "^4.3.4",
|
|
19
19
|
"eventemitter3": "^5.0.1",
|
|
@@ -31,5 +31,5 @@
|
|
|
31
31
|
"publishConfig": {
|
|
32
32
|
"access": "public"
|
|
33
33
|
},
|
|
34
|
-
"gitHead": "
|
|
34
|
+
"gitHead": "64edfaea5e53e77cd9158fc1df52fea85801db71"
|
|
35
35
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* A `NetworkAdapter` which connects to a remote host via WebSockets
|
|
3
3
|
*
|
|
4
|
-
* The websocket protocol requires a server to be listening and a client to
|
|
4
|
+
* The websocket protocol requires a server to be listening and a client to
|
|
5
5
|
* connect to the server. To that end the {@link NodeWSServerAdapter} does not
|
|
6
|
-
* make outbound connections and instead listens on the provided socket for
|
|
6
|
+
* make outbound connections and instead listens on the provided socket for
|
|
7
7
|
* new connections whilst the {@link BrowserWebSocketClientAdapter} makes an
|
|
8
8
|
* outbound connection to the provided socket.
|
|
9
9
|
*
|
|
@@ -14,5 +14,12 @@
|
|
|
14
14
|
* */
|
|
15
15
|
export { BrowserWebSocketClientAdapter } from "./BrowserWebSocketClientAdapter.js"
|
|
16
16
|
export { NodeWSServerAdapter } from "./NodeWSServerAdapter.js"
|
|
17
|
-
export type {
|
|
17
|
+
export type {
|
|
18
|
+
FromClientMessage,
|
|
19
|
+
FromServerMessage,
|
|
20
|
+
JoinMessage,
|
|
21
|
+
LeaveMessage,
|
|
22
|
+
ErrorMessage,
|
|
23
|
+
PeerMessage,
|
|
24
|
+
} from "./messages.js"
|
|
18
25
|
export type { ProtocolVersion, ProtocolV1 } from "./protocolVersion.js"
|
package/test/Websocket.test.ts
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
import { generateAutomergeUrl } from "@automerge/automerge-repo/dist/AutomergeUrl"
|
|
11
11
|
import { eventPromise } from "@automerge/automerge-repo/src/helpers/eventPromise"
|
|
12
12
|
import { headsAreSame } from "@automerge/automerge-repo/src/helpers/headsAreSame.js"
|
|
13
|
-
import {
|
|
13
|
+
import { runNetworkAdapterTests } from "@automerge/automerge-repo/src/helpers/tests/network-adapter-tests.js"
|
|
14
14
|
import { DummyStorageAdapter } from "@automerge/automerge-repo/test/helpers/DummyStorageAdapter.js"
|
|
15
15
|
import assert from "assert"
|
|
16
16
|
import * as CBOR from "cbor-x"
|
|
@@ -27,7 +27,7 @@ describe("Websocket adapters", () => {
|
|
|
27
27
|
const serverPeerId = "server" as PeerId
|
|
28
28
|
const documentId = parseAutomergeUrl(generateAutomergeUrl()).documentId
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
runNetworkAdapterTests(async () => {
|
|
31
31
|
const {
|
|
32
32
|
clients: [aliceAdapter, bobAdapter],
|
|
33
33
|
server,
|