@automerge/automerge-repo-network-websocket 1.0.0-alpha.3 → 1.0.0-alpha.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/dist/BrowserWebSocketClientAdapter.d.ts +2 -1
- package/dist/BrowserWebSocketClientAdapter.d.ts.map +1 -1
- package/dist/BrowserWebSocketClientAdapter.js +19 -5
- package/dist/NodeWSServerAdapter.d.ts +1 -2
- package/dist/NodeWSServerAdapter.d.ts.map +1 -1
- package/dist/NodeWSServerAdapter.js +6 -8
- package/package.json +4 -4
- package/src/BrowserWebSocketClientAdapter.ts +21 -6
- package/src/NodeWSServerAdapter.ts +8 -10
- package/test/Websocket.test.ts +4 -4
- package/test/utilities/WebSockets.ts +1 -1
- package/tsconfig.json +2 -2
|
@@ -6,12 +6,13 @@ declare abstract class WebSocketNetworkAdapter extends NetworkAdapter {
|
|
|
6
6
|
socket?: WebSocket;
|
|
7
7
|
}
|
|
8
8
|
export declare class BrowserWebSocketClientAdapter extends WebSocketNetworkAdapter {
|
|
9
|
+
#private;
|
|
9
10
|
timerId?: ReturnType<typeof setTimeout>;
|
|
10
11
|
url: string;
|
|
11
12
|
constructor(url: string);
|
|
12
13
|
connect(peerId: PeerId): void;
|
|
13
14
|
join(): void;
|
|
14
|
-
|
|
15
|
+
disconnect(): void;
|
|
15
16
|
send(message: FromClientMessage): void;
|
|
16
17
|
announceConnection(peerId: PeerId): void;
|
|
17
18
|
receiveMessage(message: Uint8Array): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BrowserWebSocketClientAdapter.d.ts","sourceRoot":"","sources":["../src/BrowserWebSocketClientAdapter.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"BrowserWebSocketClientAdapter.d.ts","sourceRoot":"","sources":["../src/BrowserWebSocketClientAdapter.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,EAAQ,MAAM,2BAA2B,CAAA;AACxE,OAAO,SAAS,MAAM,eAAe,CAAA;AAIrC,OAAO,EACL,iBAAiB,EAGlB,MAAM,eAAe,CAAA;AAMtB,uBAAe,uBAAwB,SAAQ,cAAc;IAC3D,MAAM,CAAC,EAAE,SAAS,CAAA;CACnB;AAED,qBAAa,6BAA8B,SAAQ,uBAAuB;;IAGxE,OAAO,CAAC,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,CAAA;IAGvC,GAAG,EAAE,MAAM,CAAA;gBAEC,GAAG,EAAE,MAAM;IAKvB,OAAO,CAAC,MAAM,EAAE,MAAM;IA0CtB,IAAI;IAoBJ,UAAU;IAOV,IAAI,CAAC,OAAO,EAAE,iBAAiB;IAwB/B,kBAAkB,CAAC,MAAM,EAAE,MAAM;IAajC,cAAc,CAAC,OAAO,EAAE,UAAU;CA6BnC"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { NetworkAdapter } from "@automerge/automerge-repo";
|
|
2
|
-
import * as CBOR from "cbor-x";
|
|
1
|
+
import { NetworkAdapter, cbor } from "@automerge/automerge-repo";
|
|
3
2
|
import WebSocket from "isomorphic-ws";
|
|
4
3
|
import debug from "debug";
|
|
5
4
|
import { ProtocolV1 } from "./protocolVersion.js";
|
|
@@ -12,6 +11,7 @@ export class BrowserWebSocketClientAdapter extends WebSocketNetworkAdapter {
|
|
|
12
11
|
// Type trickery required for platform independence,
|
|
13
12
|
// see https://stackoverflow.com/questions/45802988/typescript-use-correct-version-of-settimeout-node-vs-window
|
|
14
13
|
timerId;
|
|
14
|
+
#startupComplete = false;
|
|
15
15
|
url;
|
|
16
16
|
constructor(url) {
|
|
17
17
|
super();
|
|
@@ -39,6 +39,16 @@ export class BrowserWebSocketClientAdapter extends WebSocketNetworkAdapter {
|
|
|
39
39
|
// log("Disconnected from server")
|
|
40
40
|
});
|
|
41
41
|
this.socket.addEventListener("message", (event) => this.receiveMessage(event.data));
|
|
42
|
+
// mark this adapter as ready if we haven't received an ack in 1 second.
|
|
43
|
+
// We might hear back from the other end at some point but we shouldn't
|
|
44
|
+
// hold up marking things as unavailable for any longer
|
|
45
|
+
setTimeout(() => {
|
|
46
|
+
if (!this.#startupComplete) {
|
|
47
|
+
this.#startupComplete = true;
|
|
48
|
+
this.emit("ready", { network: this });
|
|
49
|
+
}
|
|
50
|
+
}, 1000);
|
|
51
|
+
this.join();
|
|
42
52
|
}
|
|
43
53
|
join() {
|
|
44
54
|
if (!this.socket) {
|
|
@@ -56,7 +66,7 @@ export class BrowserWebSocketClientAdapter extends WebSocketNetworkAdapter {
|
|
|
56
66
|
}, { once: true });
|
|
57
67
|
}
|
|
58
68
|
}
|
|
59
|
-
|
|
69
|
+
disconnect() {
|
|
60
70
|
if (!this.socket) {
|
|
61
71
|
throw new Error("WTF, get a socket");
|
|
62
72
|
}
|
|
@@ -72,7 +82,7 @@ export class BrowserWebSocketClientAdapter extends WebSocketNetworkAdapter {
|
|
|
72
82
|
if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {
|
|
73
83
|
throw new Error("Websocket Socket not ready!");
|
|
74
84
|
}
|
|
75
|
-
const encoded =
|
|
85
|
+
const encoded = cbor.encode(message);
|
|
76
86
|
// This incantation deals with websocket sending the whole
|
|
77
87
|
// underlying buffer even if we just have a uint8array view on it
|
|
78
88
|
const arrayBuf = encoded.buffer.slice(encoded.byteOffset, encoded.byteOffset + encoded.byteLength);
|
|
@@ -84,10 +94,14 @@ export class BrowserWebSocketClientAdapter extends WebSocketNetworkAdapter {
|
|
|
84
94
|
if (!myPeerId) {
|
|
85
95
|
throw new Error("we should have a peer ID by now");
|
|
86
96
|
}
|
|
97
|
+
if (!this.#startupComplete) {
|
|
98
|
+
this.#startupComplete = true;
|
|
99
|
+
this.emit("ready", { network: this });
|
|
100
|
+
}
|
|
87
101
|
this.emit("peer-candidate", { peerId });
|
|
88
102
|
}
|
|
89
103
|
receiveMessage(message) {
|
|
90
|
-
const decoded =
|
|
104
|
+
const decoded = cbor.decode(new Uint8Array(message));
|
|
91
105
|
const { type, senderId } = decoded;
|
|
92
106
|
const socket = this.socket;
|
|
93
107
|
if (!socket) {
|
|
@@ -9,8 +9,7 @@ export declare class NodeWSServerAdapter extends NetworkAdapter {
|
|
|
9
9
|
};
|
|
10
10
|
constructor(server: WebSocketServer);
|
|
11
11
|
connect(peerId: PeerId): void;
|
|
12
|
-
|
|
13
|
-
leave(): void;
|
|
12
|
+
disconnect(): void;
|
|
14
13
|
send(message: FromServerMessage): void;
|
|
15
14
|
receiveMessage(message: Uint8Array, socket: WebSocket): void;
|
|
16
15
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NodeWSServerAdapter.d.ts","sourceRoot":"","sources":["../src/NodeWSServerAdapter.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"NodeWSServerAdapter.d.ts","sourceRoot":"","sources":["../src/NodeWSServerAdapter.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,eAAe,EAAE,MAAM,eAAe,CAAA;AAK/D,OAAO,EAEL,cAAc,EACd,KAAK,MAAM,EACZ,MAAM,2BAA2B,CAAA;AAClC,OAAO,EAAqB,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAKpE,qBAAa,mBAAoB,SAAQ,cAAc;IACrD,MAAM,EAAE,eAAe,CAAA;IACvB,OAAO,EAAE;QAAE,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAK;gBAEjC,MAAM,EAAE,eAAe;IAKnC,OAAO,CAAC,MAAM,EAAE,MAAM;IAoBtB,UAAU;IAIV,IAAI,CAAC,OAAO,EAAE,iBAAiB;IAyB/B,cAAc,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS;CAuDtD"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import * as CBOR from "cbor-x";
|
|
2
1
|
import debug from "debug";
|
|
3
2
|
const log = debug("WebsocketServer");
|
|
3
|
+
import { cbor as cborHelpers, NetworkAdapter, } from "@automerge/automerge-repo";
|
|
4
4
|
import { ProtocolV1 } from "./protocolVersion.js";
|
|
5
|
-
|
|
5
|
+
const { encode, decode } = cborHelpers;
|
|
6
6
|
export class NodeWSServerAdapter extends NetworkAdapter {
|
|
7
7
|
server;
|
|
8
8
|
sockets = {};
|
|
@@ -23,12 +23,10 @@ export class NodeWSServerAdapter extends NetworkAdapter {
|
|
|
23
23
|
}
|
|
24
24
|
});
|
|
25
25
|
socket.on("message", message => this.receiveMessage(message, socket));
|
|
26
|
+
this.emit("ready", { network: this });
|
|
26
27
|
});
|
|
27
28
|
}
|
|
28
|
-
|
|
29
|
-
// throw new Error("The server doesn't join channels.")
|
|
30
|
-
}
|
|
31
|
-
leave() {
|
|
29
|
+
disconnect() {
|
|
32
30
|
// throw new Error("The server doesn't join channels.")
|
|
33
31
|
}
|
|
34
32
|
send(message) {
|
|
@@ -43,14 +41,14 @@ export class NodeWSServerAdapter extends NetworkAdapter {
|
|
|
43
41
|
log(`Tried to send message to disconnected peer: ${message.targetId}`);
|
|
44
42
|
return;
|
|
45
43
|
}
|
|
46
|
-
const encoded =
|
|
44
|
+
const encoded = encode(message);
|
|
47
45
|
// This incantation deals with websocket sending the whole
|
|
48
46
|
// underlying buffer even if we just have a uint8array view on it
|
|
49
47
|
const arrayBuf = encoded.buffer.slice(encoded.byteOffset, encoded.byteOffset + encoded.byteLength);
|
|
50
48
|
this.sockets[message.targetId]?.send(arrayBuf);
|
|
51
49
|
}
|
|
52
50
|
receiveMessage(message, socket) {
|
|
53
|
-
const cbor =
|
|
51
|
+
const cbor = decode(message);
|
|
54
52
|
const { type, senderId } = cbor;
|
|
55
53
|
const myPeerId = this.peerId;
|
|
56
54
|
if (!myPeerId) {
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@automerge/automerge-repo-network-websocket",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.5",
|
|
4
4
|
"description": "isomorphic node/browser Websocket network adapter for Automerge Repo",
|
|
5
5
|
"peerDependencies": {
|
|
6
|
-
"@automerge/automerge": "^2.1.0-alpha.
|
|
6
|
+
"@automerge/automerge": "^2.1.0-alpha.13"
|
|
7
7
|
},
|
|
8
8
|
"repository": "https://github.com/automerge/automerge-repo",
|
|
9
9
|
"author": "Peter van Hardenberg <pvh@pvh.ca>",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"test": "mocha --no-warnings --experimental-specifier-resolution=node --exit"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@automerge/automerge-repo": "^1.0.0-alpha.
|
|
20
|
+
"@automerge/automerge-repo": "^1.0.0-alpha.5",
|
|
21
21
|
"cbor-x": "^1.3.0",
|
|
22
22
|
"eventemitter3": "^4.0.7",
|
|
23
23
|
"isomorphic-ws": "^5.0.0",
|
|
@@ -34,5 +34,5 @@
|
|
|
34
34
|
"publishConfig": {
|
|
35
35
|
"access": "public"
|
|
36
36
|
},
|
|
37
|
-
"gitHead": "
|
|
37
|
+
"gitHead": "9cd9be160ebda37c8f0d70f2d5cadea5b951a3c3"
|
|
38
38
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { NetworkAdapter, PeerId } from "@automerge/automerge-repo"
|
|
2
|
-
import * as CBOR from "cbor-x"
|
|
1
|
+
import { NetworkAdapter, PeerId, cbor } from "@automerge/automerge-repo"
|
|
3
2
|
import WebSocket from "isomorphic-ws"
|
|
4
3
|
|
|
5
4
|
import debug from "debug"
|
|
@@ -22,6 +21,7 @@ export class BrowserWebSocketClientAdapter extends WebSocketNetworkAdapter {
|
|
|
22
21
|
// Type trickery required for platform independence,
|
|
23
22
|
// see https://stackoverflow.com/questions/45802988/typescript-use-correct-version-of-settimeout-node-vs-window
|
|
24
23
|
timerId?: ReturnType<typeof setTimeout>
|
|
24
|
+
#startupComplete: boolean = false
|
|
25
25
|
|
|
26
26
|
url: string
|
|
27
27
|
|
|
@@ -58,6 +58,18 @@ export class BrowserWebSocketClientAdapter extends WebSocketNetworkAdapter {
|
|
|
58
58
|
this.socket.addEventListener("message", (event: WebSocket.MessageEvent) =>
|
|
59
59
|
this.receiveMessage(event.data as Uint8Array)
|
|
60
60
|
)
|
|
61
|
+
|
|
62
|
+
// mark this adapter as ready if we haven't received an ack in 1 second.
|
|
63
|
+
// We might hear back from the other end at some point but we shouldn't
|
|
64
|
+
// hold up marking things as unavailable for any longer
|
|
65
|
+
setTimeout(() => {
|
|
66
|
+
if (!this.#startupComplete) {
|
|
67
|
+
this.#startupComplete = true
|
|
68
|
+
this.emit("ready", { network: this })
|
|
69
|
+
}
|
|
70
|
+
}, 1000)
|
|
71
|
+
|
|
72
|
+
this.join()
|
|
61
73
|
}
|
|
62
74
|
|
|
63
75
|
join() {
|
|
@@ -80,7 +92,7 @@ export class BrowserWebSocketClientAdapter extends WebSocketNetworkAdapter {
|
|
|
80
92
|
}
|
|
81
93
|
}
|
|
82
94
|
|
|
83
|
-
|
|
95
|
+
disconnect() {
|
|
84
96
|
if (!this.socket) {
|
|
85
97
|
throw new Error("WTF, get a socket")
|
|
86
98
|
}
|
|
@@ -100,7 +112,7 @@ export class BrowserWebSocketClientAdapter extends WebSocketNetworkAdapter {
|
|
|
100
112
|
throw new Error("Websocket Socket not ready!")
|
|
101
113
|
}
|
|
102
114
|
|
|
103
|
-
const encoded =
|
|
115
|
+
const encoded = cbor.encode(message)
|
|
104
116
|
// This incantation deals with websocket sending the whole
|
|
105
117
|
// underlying buffer even if we just have a uint8array view on it
|
|
106
118
|
const arrayBuf = encoded.buffer.slice(
|
|
@@ -117,12 +129,15 @@ export class BrowserWebSocketClientAdapter extends WebSocketNetworkAdapter {
|
|
|
117
129
|
if (!myPeerId) {
|
|
118
130
|
throw new Error("we should have a peer ID by now")
|
|
119
131
|
}
|
|
120
|
-
|
|
132
|
+
if (!this.#startupComplete) {
|
|
133
|
+
this.#startupComplete = true
|
|
134
|
+
this.emit("ready", { network: this })
|
|
135
|
+
}
|
|
121
136
|
this.emit("peer-candidate", { peerId })
|
|
122
137
|
}
|
|
123
138
|
|
|
124
139
|
receiveMessage(message: Uint8Array) {
|
|
125
|
-
const decoded: FromServerMessage =
|
|
140
|
+
const decoded: FromServerMessage = cbor.decode(new Uint8Array(message))
|
|
126
141
|
|
|
127
142
|
const { type, senderId } = decoded
|
|
128
143
|
|
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
import * as CBOR from "cbor-x"
|
|
2
1
|
import { WebSocket, type WebSocketServer } from "isomorphic-ws"
|
|
3
2
|
|
|
4
3
|
import debug from "debug"
|
|
5
4
|
const log = debug("WebsocketServer")
|
|
6
5
|
|
|
7
|
-
import { ProtocolV1, ProtocolVersion } from "./protocolVersion.js"
|
|
8
6
|
import {
|
|
7
|
+
cbor as cborHelpers,
|
|
9
8
|
NetworkAdapter,
|
|
10
|
-
type NetworkAdapterMessage,
|
|
11
9
|
type PeerId,
|
|
12
10
|
} from "@automerge/automerge-repo"
|
|
13
11
|
import { FromClientMessage, FromServerMessage } from "./messages.js"
|
|
12
|
+
import { ProtocolV1, ProtocolVersion } from "./protocolVersion.js"
|
|
13
|
+
|
|
14
|
+
const { encode, decode } = cborHelpers
|
|
14
15
|
|
|
15
16
|
export class NodeWSServerAdapter extends NetworkAdapter {
|
|
16
17
|
server: WebSocketServer
|
|
@@ -37,14 +38,11 @@ export class NodeWSServerAdapter extends NetworkAdapter {
|
|
|
37
38
|
socket.on("message", message =>
|
|
38
39
|
this.receiveMessage(message as Uint8Array, socket)
|
|
39
40
|
)
|
|
41
|
+
this.emit("ready", { network: this })
|
|
40
42
|
})
|
|
41
43
|
}
|
|
42
44
|
|
|
43
|
-
|
|
44
|
-
// throw new Error("The server doesn't join channels.")
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
leave() {
|
|
45
|
+
disconnect() {
|
|
48
46
|
// throw new Error("The server doesn't join channels.")
|
|
49
47
|
}
|
|
50
48
|
|
|
@@ -62,7 +60,7 @@ export class NodeWSServerAdapter extends NetworkAdapter {
|
|
|
62
60
|
return
|
|
63
61
|
}
|
|
64
62
|
|
|
65
|
-
const encoded =
|
|
63
|
+
const encoded = encode(message)
|
|
66
64
|
// This incantation deals with websocket sending the whole
|
|
67
65
|
// underlying buffer even if we just have a uint8array view on it
|
|
68
66
|
const arrayBuf = encoded.buffer.slice(
|
|
@@ -74,7 +72,7 @@ export class NodeWSServerAdapter extends NetworkAdapter {
|
|
|
74
72
|
}
|
|
75
73
|
|
|
76
74
|
receiveMessage(message: Uint8Array, socket: WebSocket) {
|
|
77
|
-
const cbor: FromClientMessage =
|
|
75
|
+
const cbor: FromClientMessage = decode(message)
|
|
78
76
|
|
|
79
77
|
const { type, senderId } = cbor
|
|
80
78
|
|
package/test/Websocket.test.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { runAdapterTests } from "../../automerge-repo/src/helpers/tests/network-adapter-tests"
|
|
2
|
-
import { BrowserWebSocketClientAdapter } from "../src/BrowserWebSocketClientAdapter"
|
|
3
|
-
import { NodeWSServerAdapter } from "../src/NodeWSServerAdapter"
|
|
4
|
-
import { startServer } from "./utilities/WebSockets"
|
|
1
|
+
import { runAdapterTests } from "../../automerge-repo/src/helpers/tests/network-adapter-tests.js"
|
|
2
|
+
import { BrowserWebSocketClientAdapter } from "../src/BrowserWebSocketClientAdapter.js"
|
|
3
|
+
import { NodeWSServerAdapter } from "../src/NodeWSServerAdapter.js"
|
|
4
|
+
import { startServer } from "./utilities/WebSockets.js"
|
|
5
5
|
import * as CBOR from "cbor-x"
|
|
6
6
|
import WebSocket, { AddressInfo } from "ws"
|
|
7
7
|
import { assert } from "chai"
|
package/tsconfig.json
CHANGED