@automerge/automerge-repo-network-websocket 1.0.0-alpha.0 → 1.0.0-alpha.3
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 +4 -4
- package/dist/BrowserWebSocketClientAdapter.d.ts.map +1 -1
- package/dist/BrowserWebSocketClientAdapter.js +23 -30
- package/dist/NodeWSServerAdapter.d.ts +3 -2
- package/dist/NodeWSServerAdapter.d.ts.map +1 -1
- package/dist/NodeWSServerAdapter.js +20 -36
- package/dist/messages.d.ts +26 -0
- package/dist/messages.d.ts.map +1 -0
- package/package.json +4 -4
- package/src/BrowserWebSocketClientAdapter.ts +35 -55
- package/src/NodeWSServerAdapter.ts +33 -64
- package/src/messages.ts +31 -0
- package/test/Websocket.test.ts +41 -20
- package/dist/message.d.ts +0 -9
- package/dist/message.d.ts.map +0 -1
- package/src/message.ts +0 -10
- /package/dist/{message.js → messages.js} +0 -0
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
1
|
/// <reference types="ws" />
|
|
3
|
-
import {
|
|
2
|
+
import { NetworkAdapter, PeerId } from "@automerge/automerge-repo";
|
|
4
3
|
import WebSocket from "isomorphic-ws";
|
|
4
|
+
import { FromClientMessage } from "./messages.js";
|
|
5
5
|
declare abstract class WebSocketNetworkAdapter extends NetworkAdapter {
|
|
6
6
|
socket?: WebSocket;
|
|
7
7
|
}
|
|
8
8
|
export declare class BrowserWebSocketClientAdapter extends WebSocketNetworkAdapter {
|
|
9
|
-
timerId?:
|
|
9
|
+
timerId?: ReturnType<typeof setTimeout>;
|
|
10
10
|
url: string;
|
|
11
11
|
constructor(url: string);
|
|
12
12
|
connect(peerId: PeerId): void;
|
|
13
13
|
join(): void;
|
|
14
14
|
leave(): void;
|
|
15
|
-
|
|
15
|
+
send(message: FromClientMessage): void;
|
|
16
16
|
announceConnection(peerId: PeerId): void;
|
|
17
17
|
receiveMessage(message: Uint8Array): void;
|
|
18
18
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BrowserWebSocketClientAdapter.d.ts","sourceRoot":"","sources":["../src/BrowserWebSocketClientAdapter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"BrowserWebSocketClientAdapter.d.ts","sourceRoot":"","sources":["../src/BrowserWebSocketClientAdapter.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAA;AAElE,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;IAEvC,GAAG,EAAE,MAAM,CAAA;gBAEC,GAAG,EAAE,MAAM;IAKvB,OAAO,CAAC,MAAM,EAAE,MAAM;IA8BtB,IAAI;IAoBJ,KAAK;IAOL,IAAI,CAAC,OAAO,EAAE,iBAAiB;IAwB/B,kBAAkB,CAAC,MAAM,EAAE,MAAM;IAUjC,cAAc,CAAC,OAAO,EAAE,UAAU;CA6BnC"}
|
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
import { NetworkAdapter
|
|
1
|
+
import { NetworkAdapter } from "@automerge/automerge-repo";
|
|
2
2
|
import * as CBOR from "cbor-x";
|
|
3
3
|
import WebSocket from "isomorphic-ws";
|
|
4
4
|
import debug from "debug";
|
|
5
|
-
import { ProtocolV1 } from "./protocolVersion";
|
|
5
|
+
import { ProtocolV1 } from "./protocolVersion.js";
|
|
6
|
+
import { isValidMessage } from "@automerge/automerge-repo/dist/network/messages.js";
|
|
6
7
|
const log = debug("WebsocketClient");
|
|
7
8
|
class WebSocketNetworkAdapter extends NetworkAdapter {
|
|
8
9
|
socket;
|
|
9
10
|
}
|
|
10
11
|
export class BrowserWebSocketClientAdapter extends WebSocketNetworkAdapter {
|
|
12
|
+
// Type trickery required for platform independence,
|
|
13
|
+
// see https://stackoverflow.com/questions/45802988/typescript-use-correct-version-of-settimeout-node-vs-window
|
|
11
14
|
timerId;
|
|
12
15
|
url;
|
|
13
16
|
constructor(url) {
|
|
@@ -42,14 +45,14 @@ export class BrowserWebSocketClientAdapter extends WebSocketNetworkAdapter {
|
|
|
42
45
|
throw new Error("WTF, get a socket");
|
|
43
46
|
}
|
|
44
47
|
if (this.socket.readyState === WebSocket.OPEN) {
|
|
45
|
-
this.
|
|
48
|
+
this.send(joinMessage(this.peerId));
|
|
46
49
|
}
|
|
47
50
|
else {
|
|
48
51
|
this.socket.addEventListener("open", () => {
|
|
49
52
|
if (!this.socket) {
|
|
50
53
|
throw new Error("WTF, get a socket");
|
|
51
54
|
}
|
|
52
|
-
this.
|
|
55
|
+
this.send(joinMessage(this.peerId));
|
|
53
56
|
}, { once: true });
|
|
54
57
|
}
|
|
55
58
|
}
|
|
@@ -57,31 +60,23 @@ export class BrowserWebSocketClientAdapter extends WebSocketNetworkAdapter {
|
|
|
57
60
|
if (!this.socket) {
|
|
58
61
|
throw new Error("WTF, get a socket");
|
|
59
62
|
}
|
|
60
|
-
this.
|
|
63
|
+
this.send({ type: "leave", senderId: this.peerId });
|
|
61
64
|
}
|
|
62
|
-
|
|
63
|
-
if (message.byteLength === 0) {
|
|
65
|
+
send(message) {
|
|
66
|
+
if ("data" in message && message.data.byteLength === 0) {
|
|
64
67
|
throw new Error("tried to send a zero-length message");
|
|
65
68
|
}
|
|
66
69
|
if (!this.peerId) {
|
|
67
70
|
throw new Error("Why don't we have a PeerID?");
|
|
68
71
|
}
|
|
69
|
-
const decoded = {
|
|
70
|
-
senderId: this.peerId,
|
|
71
|
-
targetId,
|
|
72
|
-
channelId,
|
|
73
|
-
type: "sync",
|
|
74
|
-
message,
|
|
75
|
-
broadcast,
|
|
76
|
-
};
|
|
77
|
-
const encoded = CBOR.encode(decoded);
|
|
78
|
-
// This incantation deals with websocket sending the whole
|
|
79
|
-
// underlying buffer even if we just have a uint8array view on it
|
|
80
|
-
const arrayBuf = encoded.buffer.slice(encoded.byteOffset, encoded.byteOffset + encoded.byteLength);
|
|
81
72
|
if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {
|
|
82
73
|
throw new Error("Websocket Socket not ready!");
|
|
83
74
|
}
|
|
84
|
-
|
|
75
|
+
const encoded = CBOR.encode(message);
|
|
76
|
+
// This incantation deals with websocket sending the whole
|
|
77
|
+
// underlying buffer even if we just have a uint8array view on it
|
|
78
|
+
const arrayBuf = encoded.buffer.slice(encoded.byteOffset, encoded.byteOffset + encoded.byteLength);
|
|
79
|
+
this.socket?.send(arrayBuf);
|
|
85
80
|
}
|
|
86
81
|
announceConnection(peerId) {
|
|
87
82
|
// return a peer object
|
|
@@ -93,7 +88,7 @@ export class BrowserWebSocketClientAdapter extends WebSocketNetworkAdapter {
|
|
|
93
88
|
}
|
|
94
89
|
receiveMessage(message) {
|
|
95
90
|
const decoded = CBOR.decode(new Uint8Array(message));
|
|
96
|
-
const { type, senderId
|
|
91
|
+
const { type, senderId } = decoded;
|
|
97
92
|
const socket = this.socket;
|
|
98
93
|
if (!socket) {
|
|
99
94
|
throw new Error("Missing socket at receiveMessage");
|
|
@@ -103,19 +98,17 @@ export class BrowserWebSocketClientAdapter extends WebSocketNetworkAdapter {
|
|
|
103
98
|
}
|
|
104
99
|
switch (type) {
|
|
105
100
|
case "peer":
|
|
106
|
-
log(`peer: ${senderId}
|
|
101
|
+
log(`peer: ${senderId}`);
|
|
107
102
|
this.announceConnection(senderId);
|
|
108
103
|
break;
|
|
109
104
|
case "error":
|
|
110
|
-
log(`error: ${decoded.
|
|
105
|
+
log(`error: ${decoded.message}`);
|
|
106
|
+
break;
|
|
111
107
|
default:
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
message: new Uint8Array(messageData),
|
|
117
|
-
broadcast,
|
|
118
|
-
});
|
|
108
|
+
if (!isValidMessage(decoded)) {
|
|
109
|
+
throw new Error("Invalid message received");
|
|
110
|
+
}
|
|
111
|
+
this.emit("message", decoded);
|
|
119
112
|
}
|
|
120
113
|
}
|
|
121
114
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/// <reference types="ws" />
|
|
2
2
|
import { WebSocket, type WebSocketServer } from "isomorphic-ws";
|
|
3
|
-
import {
|
|
3
|
+
import { NetworkAdapter, type PeerId } from "@automerge/automerge-repo";
|
|
4
|
+
import { FromServerMessage } from "./messages.js";
|
|
4
5
|
export declare class NodeWSServerAdapter extends NetworkAdapter {
|
|
5
6
|
server: WebSocketServer;
|
|
6
7
|
sockets: {
|
|
@@ -10,7 +11,7 @@ export declare class NodeWSServerAdapter extends NetworkAdapter {
|
|
|
10
11
|
connect(peerId: PeerId): void;
|
|
11
12
|
join(): void;
|
|
12
13
|
leave(): void;
|
|
13
|
-
|
|
14
|
+
send(message: FromServerMessage): void;
|
|
14
15
|
receiveMessage(message: Uint8Array, socket: WebSocket): void;
|
|
15
16
|
}
|
|
16
17
|
//# sourceMappingURL=NodeWSServerAdapter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NodeWSServerAdapter.d.ts","sourceRoot":"","sources":["../src/NodeWSServerAdapter.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,KAAK,eAAe,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"NodeWSServerAdapter.d.ts","sourceRoot":"","sources":["../src/NodeWSServerAdapter.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,KAAK,eAAe,EAAE,MAAM,eAAe,CAAA;AAM/D,OAAO,EACL,cAAc,EAEd,KAAK,MAAM,EACZ,MAAM,2BAA2B,CAAA;AAClC,OAAO,EAAqB,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAEpE,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;IAmBtB,IAAI;IAIJ,KAAK;IAIL,IAAI,CAAC,OAAO,EAAE,iBAAiB;IAyB/B,cAAc,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS;CAuDtD"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as CBOR from "cbor-x";
|
|
2
2
|
import debug from "debug";
|
|
3
3
|
const log = debug("WebsocketServer");
|
|
4
|
+
import { ProtocolV1 } from "./protocolVersion.js";
|
|
4
5
|
import { NetworkAdapter, } from "@automerge/automerge-repo";
|
|
5
|
-
import { ProtocolV1 } from "./protocolVersion";
|
|
6
6
|
export class NodeWSServerAdapter extends NetworkAdapter {
|
|
7
7
|
server;
|
|
8
8
|
sockets = {};
|
|
@@ -31,41 +31,32 @@ export class NodeWSServerAdapter extends NetworkAdapter {
|
|
|
31
31
|
leave() {
|
|
32
32
|
// throw new Error("The server doesn't join channels.")
|
|
33
33
|
}
|
|
34
|
-
|
|
35
|
-
if (message.byteLength === 0) {
|
|
34
|
+
send(message) {
|
|
35
|
+
if ("data" in message && message.data.byteLength === 0) {
|
|
36
36
|
throw new Error("tried to send a zero-length message");
|
|
37
37
|
}
|
|
38
38
|
const senderId = this.peerId;
|
|
39
39
|
if (!senderId) {
|
|
40
40
|
throw new Error("No peerId set for the websocket server network adapter.");
|
|
41
41
|
}
|
|
42
|
-
if (this.sockets[targetId] === undefined) {
|
|
43
|
-
log(`Tried to send message to disconnected peer: ${targetId}`);
|
|
42
|
+
if (this.sockets[message.targetId] === undefined) {
|
|
43
|
+
log(`Tried to send message to disconnected peer: ${message.targetId}`);
|
|
44
44
|
return;
|
|
45
45
|
}
|
|
46
|
-
const
|
|
47
|
-
senderId,
|
|
48
|
-
targetId,
|
|
49
|
-
channelId,
|
|
50
|
-
type: "sync",
|
|
51
|
-
message,
|
|
52
|
-
broadcast,
|
|
53
|
-
};
|
|
54
|
-
const encoded = CBOR.encode(decoded);
|
|
46
|
+
const encoded = CBOR.encode(message);
|
|
55
47
|
// This incantation deals with websocket sending the whole
|
|
56
48
|
// underlying buffer even if we just have a uint8array view on it
|
|
57
49
|
const arrayBuf = encoded.buffer.slice(encoded.byteOffset, encoded.byteOffset + encoded.byteLength);
|
|
58
|
-
|
|
59
|
-
this.sockets[targetId].send(arrayBuf);
|
|
50
|
+
this.sockets[message.targetId]?.send(arrayBuf);
|
|
60
51
|
}
|
|
61
52
|
receiveMessage(message, socket) {
|
|
62
53
|
const cbor = CBOR.decode(message);
|
|
63
|
-
const { type,
|
|
54
|
+
const { type, senderId } = cbor;
|
|
64
55
|
const myPeerId = this.peerId;
|
|
65
56
|
if (!myPeerId) {
|
|
66
57
|
throw new Error("Missing my peer ID.");
|
|
67
58
|
}
|
|
68
|
-
log(`[${senderId}->${myPeerId}
|
|
59
|
+
log(`[${senderId}->${myPeerId}${"documentId" in cbor ? "@" + cbor.documentId : ""}] ${type} | ${message.byteLength} bytes`);
|
|
69
60
|
switch (type) {
|
|
70
61
|
case "join":
|
|
71
62
|
// Let the rest of the system know that we have a new connection.
|
|
@@ -73,18 +64,24 @@ export class NodeWSServerAdapter extends NetworkAdapter {
|
|
|
73
64
|
this.sockets[senderId] = socket;
|
|
74
65
|
// In this client-server connection, there's only ever one peer: us!
|
|
75
66
|
// (and we pretend to be joined to every channel)
|
|
76
|
-
const selectedProtocolVersion = selectProtocol(supportedProtocolVersions);
|
|
67
|
+
const selectedProtocolVersion = selectProtocol(cbor.supportedProtocolVersions);
|
|
77
68
|
if (selectedProtocolVersion === null) {
|
|
78
|
-
|
|
69
|
+
this.send({
|
|
70
|
+
type: "error",
|
|
71
|
+
senderId: this.peerId,
|
|
72
|
+
message: "unsupported protocol version",
|
|
73
|
+
targetId: senderId,
|
|
74
|
+
});
|
|
79
75
|
this.sockets[senderId].close();
|
|
80
76
|
delete this.sockets[senderId];
|
|
81
77
|
}
|
|
82
78
|
else {
|
|
83
|
-
|
|
79
|
+
this.send({
|
|
84
80
|
type: "peer",
|
|
85
81
|
senderId: this.peerId,
|
|
86
82
|
selectedProtocolVersion: ProtocolV1,
|
|
87
|
-
|
|
83
|
+
targetId: senderId,
|
|
84
|
+
});
|
|
88
85
|
}
|
|
89
86
|
break;
|
|
90
87
|
case "leave":
|
|
@@ -93,21 +90,8 @@ export class NodeWSServerAdapter extends NetworkAdapter {
|
|
|
93
90
|
// TODO: confirm this
|
|
94
91
|
// ?
|
|
95
92
|
break;
|
|
96
|
-
// We accept both "message" and "sync" because a previous version of this
|
|
97
|
-
// codebase sent sync messages in the BrowserWebSocketClientAdapter as
|
|
98
|
-
// type "message" and we want to stay backwards compatible
|
|
99
|
-
case "message":
|
|
100
|
-
case "sync":
|
|
101
|
-
this.emit("message", {
|
|
102
|
-
senderId,
|
|
103
|
-
targetId,
|
|
104
|
-
channelId,
|
|
105
|
-
message: new Uint8Array(data),
|
|
106
|
-
broadcast,
|
|
107
|
-
});
|
|
108
|
-
break;
|
|
109
93
|
default:
|
|
110
|
-
|
|
94
|
+
this.emit("message", cbor);
|
|
111
95
|
break;
|
|
112
96
|
}
|
|
113
97
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type Message, type PeerId } from "@automerge/automerge-repo";
|
|
2
|
+
import { ProtocolVersion } from "./protocolVersion.js";
|
|
3
|
+
export type LeaveMessage = {
|
|
4
|
+
type: "leave";
|
|
5
|
+
senderId: PeerId;
|
|
6
|
+
};
|
|
7
|
+
export type JoinMessage = {
|
|
8
|
+
type: "join";
|
|
9
|
+
senderId: PeerId;
|
|
10
|
+
supportedProtocolVersions: ProtocolVersion[];
|
|
11
|
+
};
|
|
12
|
+
export type PeerMessage = {
|
|
13
|
+
type: "peer";
|
|
14
|
+
senderId: PeerId;
|
|
15
|
+
selectedProtocolVersion: ProtocolVersion;
|
|
16
|
+
targetId: PeerId;
|
|
17
|
+
};
|
|
18
|
+
export type ErrorMessage = {
|
|
19
|
+
type: "error";
|
|
20
|
+
senderId: PeerId;
|
|
21
|
+
message: string;
|
|
22
|
+
targetId: PeerId;
|
|
23
|
+
};
|
|
24
|
+
export type FromClientMessage = JoinMessage | LeaveMessage | Message;
|
|
25
|
+
export type FromServerMessage = PeerMessage | ErrorMessage | Message;
|
|
26
|
+
//# sourceMappingURL=messages.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../src/messages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,2BAA2B,CAAA;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAEtD,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,OAAO,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,yBAAyB,EAAE,eAAe,EAAE,CAAA;CAC7C,CAAA;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,uBAAuB,EAAE,eAAe,CAAA;IACxC,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,OAAO,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAGD,MAAM,MAAM,iBAAiB,GAAG,WAAW,GAAG,YAAY,GAAG,OAAO,CAAA;AACpE,MAAM,MAAM,iBAAiB,GAAG,WAAW,GAAG,YAAY,GAAG,OAAO,CAAA"}
|
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.3",
|
|
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.10"
|
|
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.3",
|
|
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": "0ed108273084319aeea64ceccb49c3d58709f107"
|
|
38
38
|
}
|
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ChannelId,
|
|
3
|
-
InboundMessagePayload,
|
|
4
|
-
NetworkAdapter,
|
|
5
|
-
PeerId,
|
|
6
|
-
} from "@automerge/automerge-repo"
|
|
1
|
+
import { NetworkAdapter, PeerId } from "@automerge/automerge-repo"
|
|
7
2
|
import * as CBOR from "cbor-x"
|
|
8
3
|
import WebSocket from "isomorphic-ws"
|
|
9
4
|
|
|
10
5
|
import debug from "debug"
|
|
11
|
-
|
|
12
|
-
import {
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
FromClientMessage,
|
|
9
|
+
FromServerMessage,
|
|
10
|
+
JoinMessage,
|
|
11
|
+
} from "./messages.js"
|
|
12
|
+
import { ProtocolV1 } from "./protocolVersion.js"
|
|
13
|
+
import { isValidMessage } from "@automerge/automerge-repo/dist/network/messages.js"
|
|
14
|
+
|
|
13
15
|
const log = debug("WebsocketClient")
|
|
14
16
|
|
|
15
17
|
abstract class WebSocketNetworkAdapter extends NetworkAdapter {
|
|
@@ -17,7 +19,10 @@ abstract class WebSocketNetworkAdapter extends NetworkAdapter {
|
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
export class BrowserWebSocketClientAdapter extends WebSocketNetworkAdapter {
|
|
20
|
-
|
|
22
|
+
// Type trickery required for platform independence,
|
|
23
|
+
// see https://stackoverflow.com/questions/45802988/typescript-use-correct-version-of-settimeout-node-vs-window
|
|
24
|
+
timerId?: ReturnType<typeof setTimeout>
|
|
25
|
+
|
|
21
26
|
url: string
|
|
22
27
|
|
|
23
28
|
constructor(url: string) {
|
|
@@ -60,9 +65,7 @@ export class BrowserWebSocketClientAdapter extends WebSocketNetworkAdapter {
|
|
|
60
65
|
throw new Error("WTF, get a socket")
|
|
61
66
|
}
|
|
62
67
|
if (this.socket.readyState === WebSocket.OPEN) {
|
|
63
|
-
this.
|
|
64
|
-
CBOR.encode(joinMessage(this.peerId))
|
|
65
|
-
)
|
|
68
|
+
this.send(joinMessage(this.peerId!))
|
|
66
69
|
} else {
|
|
67
70
|
this.socket.addEventListener(
|
|
68
71
|
"open",
|
|
@@ -70,9 +73,7 @@ export class BrowserWebSocketClientAdapter extends WebSocketNetworkAdapter {
|
|
|
70
73
|
if (!this.socket) {
|
|
71
74
|
throw new Error("WTF, get a socket")
|
|
72
75
|
}
|
|
73
|
-
this.
|
|
74
|
-
CBOR.encode(joinMessage(this.peerId))
|
|
75
|
-
)
|
|
76
|
+
this.send(joinMessage(this.peerId!))
|
|
76
77
|
},
|
|
77
78
|
{ once: true }
|
|
78
79
|
)
|
|
@@ -83,43 +84,31 @@ export class BrowserWebSocketClientAdapter extends WebSocketNetworkAdapter {
|
|
|
83
84
|
if (!this.socket) {
|
|
84
85
|
throw new Error("WTF, get a socket")
|
|
85
86
|
}
|
|
86
|
-
this.
|
|
87
|
+
this.send({ type: "leave", senderId: this.peerId! })
|
|
87
88
|
}
|
|
88
89
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
channelId: ChannelId,
|
|
92
|
-
message: Uint8Array,
|
|
93
|
-
broadcast: boolean
|
|
94
|
-
) {
|
|
95
|
-
if (message.byteLength === 0) {
|
|
90
|
+
send(message: FromClientMessage) {
|
|
91
|
+
if ("data" in message && message.data.byteLength === 0) {
|
|
96
92
|
throw new Error("tried to send a zero-length message")
|
|
97
93
|
}
|
|
94
|
+
|
|
98
95
|
if (!this.peerId) {
|
|
99
96
|
throw new Error("Why don't we have a PeerID?")
|
|
100
97
|
}
|
|
101
98
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
targetId,
|
|
105
|
-
channelId,
|
|
106
|
-
type: "sync",
|
|
107
|
-
message,
|
|
108
|
-
broadcast,
|
|
99
|
+
if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {
|
|
100
|
+
throw new Error("Websocket Socket not ready!")
|
|
109
101
|
}
|
|
110
102
|
|
|
111
|
-
const encoded = CBOR.encode(
|
|
112
|
-
|
|
103
|
+
const encoded = CBOR.encode(message)
|
|
113
104
|
// This incantation deals with websocket sending the whole
|
|
114
105
|
// underlying buffer even if we just have a uint8array view on it
|
|
115
106
|
const arrayBuf = encoded.buffer.slice(
|
|
116
107
|
encoded.byteOffset,
|
|
117
108
|
encoded.byteOffset + encoded.byteLength
|
|
118
109
|
)
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
122
|
-
this.socket.send(arrayBuf)
|
|
110
|
+
|
|
111
|
+
this.socket?.send(arrayBuf)
|
|
123
112
|
}
|
|
124
113
|
|
|
125
114
|
announceConnection(peerId: PeerId) {
|
|
@@ -133,16 +122,9 @@ export class BrowserWebSocketClientAdapter extends WebSocketNetworkAdapter {
|
|
|
133
122
|
}
|
|
134
123
|
|
|
135
124
|
receiveMessage(message: Uint8Array) {
|
|
136
|
-
const decoded:
|
|
125
|
+
const decoded: FromServerMessage = CBOR.decode(new Uint8Array(message))
|
|
137
126
|
|
|
138
|
-
const {
|
|
139
|
-
type,
|
|
140
|
-
senderId,
|
|
141
|
-
targetId,
|
|
142
|
-
channelId,
|
|
143
|
-
message: messageData,
|
|
144
|
-
broadcast,
|
|
145
|
-
} = decoded
|
|
127
|
+
const { type, senderId } = decoded
|
|
146
128
|
|
|
147
129
|
const socket = this.socket
|
|
148
130
|
if (!socket) {
|
|
@@ -155,24 +137,22 @@ export class BrowserWebSocketClientAdapter extends WebSocketNetworkAdapter {
|
|
|
155
137
|
|
|
156
138
|
switch (type) {
|
|
157
139
|
case "peer":
|
|
158
|
-
log(`peer: ${senderId}
|
|
140
|
+
log(`peer: ${senderId}`)
|
|
159
141
|
this.announceConnection(senderId)
|
|
160
142
|
break
|
|
161
143
|
case "error":
|
|
162
|
-
log(`error: ${decoded.
|
|
144
|
+
log(`error: ${decoded.message}`)
|
|
145
|
+
break
|
|
163
146
|
default:
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
message: new Uint8Array(messageData),
|
|
169
|
-
broadcast,
|
|
170
|
-
})
|
|
147
|
+
if (!isValidMessage(decoded)) {
|
|
148
|
+
throw new Error("Invalid message received")
|
|
149
|
+
}
|
|
150
|
+
this.emit("message", decoded)
|
|
171
151
|
}
|
|
172
152
|
}
|
|
173
153
|
}
|
|
174
154
|
|
|
175
|
-
function joinMessage(senderId
|
|
155
|
+
function joinMessage(senderId: PeerId): JoinMessage {
|
|
176
156
|
return {
|
|
177
157
|
type: "join",
|
|
178
158
|
senderId,
|
|
@@ -4,14 +4,13 @@ import { WebSocket, type WebSocketServer } from "isomorphic-ws"
|
|
|
4
4
|
import debug from "debug"
|
|
5
5
|
const log = debug("WebsocketServer")
|
|
6
6
|
|
|
7
|
+
import { ProtocolV1, ProtocolVersion } from "./protocolVersion.js"
|
|
7
8
|
import {
|
|
8
|
-
ChannelId,
|
|
9
|
-
InboundMessagePayload,
|
|
10
9
|
NetworkAdapter,
|
|
11
|
-
|
|
10
|
+
type NetworkAdapterMessage,
|
|
11
|
+
type PeerId,
|
|
12
12
|
} from "@automerge/automerge-repo"
|
|
13
|
-
import {
|
|
14
|
-
import {InboundWebSocketMessage} from "./message"
|
|
13
|
+
import { FromClientMessage, FromServerMessage } from "./messages.js"
|
|
15
14
|
|
|
16
15
|
export class NodeWSServerAdapter extends NetworkAdapter {
|
|
17
16
|
server: WebSocketServer
|
|
@@ -49,34 +48,21 @@ export class NodeWSServerAdapter extends NetworkAdapter {
|
|
|
49
48
|
// throw new Error("The server doesn't join channels.")
|
|
50
49
|
}
|
|
51
50
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
channelId: ChannelId,
|
|
55
|
-
message: Uint8Array,
|
|
56
|
-
broadcast: boolean
|
|
57
|
-
) {
|
|
58
|
-
if (message.byteLength === 0) {
|
|
51
|
+
send(message: FromServerMessage) {
|
|
52
|
+
if ("data" in message && message.data.byteLength === 0) {
|
|
59
53
|
throw new Error("tried to send a zero-length message")
|
|
60
54
|
}
|
|
61
55
|
const senderId = this.peerId
|
|
62
56
|
if (!senderId) {
|
|
63
57
|
throw new Error("No peerId set for the websocket server network adapter.")
|
|
64
58
|
}
|
|
65
|
-
if (this.sockets[targetId] === undefined) {
|
|
66
|
-
log(`Tried to send message to disconnected peer: ${targetId}`)
|
|
67
|
-
return
|
|
68
|
-
}
|
|
69
59
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
channelId,
|
|
74
|
-
type: "sync",
|
|
75
|
-
message,
|
|
76
|
-
broadcast,
|
|
60
|
+
if (this.sockets[message.targetId] === undefined) {
|
|
61
|
+
log(`Tried to send message to disconnected peer: ${message.targetId}`)
|
|
62
|
+
return
|
|
77
63
|
}
|
|
78
|
-
const encoded = CBOR.encode(decoded)
|
|
79
64
|
|
|
65
|
+
const encoded = CBOR.encode(message)
|
|
80
66
|
// This incantation deals with websocket sending the whole
|
|
81
67
|
// underlying buffer even if we just have a uint8array view on it
|
|
82
68
|
const arrayBuf = encoded.buffer.slice(
|
|
@@ -84,32 +70,22 @@ export class NodeWSServerAdapter extends NetworkAdapter {
|
|
|
84
70
|
encoded.byteOffset + encoded.byteLength
|
|
85
71
|
)
|
|
86
72
|
|
|
87
|
-
|
|
88
|
-
`[${senderId}->${targetId}@${channelId}] "sync" | ${arrayBuf.byteLength} bytes`
|
|
89
|
-
)
|
|
90
|
-
|
|
91
|
-
this.sockets[targetId].send(arrayBuf)
|
|
73
|
+
this.sockets[message.targetId]?.send(arrayBuf)
|
|
92
74
|
}
|
|
93
75
|
|
|
94
76
|
receiveMessage(message: Uint8Array, socket: WebSocket) {
|
|
95
|
-
const cbor:
|
|
96
|
-
|
|
97
|
-
const {
|
|
98
|
-
type,
|
|
99
|
-
channelId,
|
|
100
|
-
senderId,
|
|
101
|
-
targetId,
|
|
102
|
-
message: data,
|
|
103
|
-
broadcast,
|
|
104
|
-
supportedProtocolVersions,
|
|
105
|
-
} = cbor
|
|
77
|
+
const cbor: FromClientMessage = CBOR.decode(message)
|
|
78
|
+
|
|
79
|
+
const { type, senderId } = cbor
|
|
106
80
|
|
|
107
81
|
const myPeerId = this.peerId
|
|
108
82
|
if (!myPeerId) {
|
|
109
83
|
throw new Error("Missing my peer ID.")
|
|
110
84
|
}
|
|
111
85
|
log(
|
|
112
|
-
`[${senderId}->${myPeerId}
|
|
86
|
+
`[${senderId}->${myPeerId}${
|
|
87
|
+
"documentId" in cbor ? "@" + cbor.documentId : ""
|
|
88
|
+
}] ${type} | ${message.byteLength} bytes`
|
|
113
89
|
)
|
|
114
90
|
switch (type) {
|
|
115
91
|
case "join":
|
|
@@ -119,19 +95,25 @@ export class NodeWSServerAdapter extends NetworkAdapter {
|
|
|
119
95
|
|
|
120
96
|
// In this client-server connection, there's only ever one peer: us!
|
|
121
97
|
// (and we pretend to be joined to every channel)
|
|
122
|
-
const selectedProtocolVersion = selectProtocol(
|
|
98
|
+
const selectedProtocolVersion = selectProtocol(
|
|
99
|
+
cbor.supportedProtocolVersions
|
|
100
|
+
)
|
|
123
101
|
if (selectedProtocolVersion === null) {
|
|
124
|
-
|
|
102
|
+
this.send({
|
|
103
|
+
type: "error",
|
|
104
|
+
senderId: this.peerId!,
|
|
105
|
+
message: "unsupported protocol version",
|
|
106
|
+
targetId: senderId,
|
|
107
|
+
})
|
|
125
108
|
this.sockets[senderId].close()
|
|
126
109
|
delete this.sockets[senderId]
|
|
127
110
|
} else {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
)
|
|
111
|
+
this.send({
|
|
112
|
+
type: "peer",
|
|
113
|
+
senderId: this.peerId!,
|
|
114
|
+
selectedProtocolVersion: ProtocolV1,
|
|
115
|
+
targetId: senderId,
|
|
116
|
+
})
|
|
135
117
|
}
|
|
136
118
|
break
|
|
137
119
|
case "leave":
|
|
@@ -141,21 +123,8 @@ export class NodeWSServerAdapter extends NetworkAdapter {
|
|
|
141
123
|
// ?
|
|
142
124
|
break
|
|
143
125
|
|
|
144
|
-
// We accept both "message" and "sync" because a previous version of this
|
|
145
|
-
// codebase sent sync messages in the BrowserWebSocketClientAdapter as
|
|
146
|
-
// type "message" and we want to stay backwards compatible
|
|
147
|
-
case "message":
|
|
148
|
-
case "sync":
|
|
149
|
-
this.emit("message", {
|
|
150
|
-
senderId,
|
|
151
|
-
targetId,
|
|
152
|
-
channelId,
|
|
153
|
-
message: new Uint8Array(data),
|
|
154
|
-
broadcast,
|
|
155
|
-
})
|
|
156
|
-
break
|
|
157
126
|
default:
|
|
158
|
-
|
|
127
|
+
this.emit("message", cbor)
|
|
159
128
|
break
|
|
160
129
|
}
|
|
161
130
|
}
|
package/src/messages.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type Message, type PeerId } from "@automerge/automerge-repo"
|
|
2
|
+
import { ProtocolVersion } from "./protocolVersion.js"
|
|
3
|
+
|
|
4
|
+
export type LeaveMessage = {
|
|
5
|
+
type: "leave"
|
|
6
|
+
senderId: PeerId
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type JoinMessage = {
|
|
10
|
+
type: "join"
|
|
11
|
+
senderId: PeerId
|
|
12
|
+
supportedProtocolVersions: ProtocolVersion[]
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export type PeerMessage = {
|
|
16
|
+
type: "peer"
|
|
17
|
+
senderId: PeerId
|
|
18
|
+
selectedProtocolVersion: ProtocolVersion
|
|
19
|
+
targetId: PeerId
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export type ErrorMessage = {
|
|
23
|
+
type: "error"
|
|
24
|
+
senderId: PeerId
|
|
25
|
+
message: string
|
|
26
|
+
targetId: PeerId
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// This adapter doesn't use NetworkAdapterMessage, it has its own idea of how to handle join/leave
|
|
30
|
+
export type FromClientMessage = JoinMessage | LeaveMessage | Message
|
|
31
|
+
export type FromServerMessage = PeerMessage | ErrorMessage | Message
|
package/test/Websocket.test.ts
CHANGED
|
@@ -3,17 +3,30 @@ import { BrowserWebSocketClientAdapter } from "../src/BrowserWebSocketClientAdap
|
|
|
3
3
|
import { NodeWSServerAdapter } from "../src/NodeWSServerAdapter"
|
|
4
4
|
import { startServer } from "./utilities/WebSockets"
|
|
5
5
|
import * as CBOR from "cbor-x"
|
|
6
|
-
import WebSocket, {AddressInfo}
|
|
6
|
+
import WebSocket, { AddressInfo } from "ws"
|
|
7
7
|
import { assert } from "chai"
|
|
8
|
-
import {
|
|
8
|
+
import { PeerId, Repo } from "@automerge/automerge-repo"
|
|
9
9
|
import { once } from "events"
|
|
10
10
|
|
|
11
11
|
describe("Websocket adapters", async () => {
|
|
12
12
|
let port = 8080
|
|
13
13
|
|
|
14
14
|
runAdapterTests(async () => {
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
let socket: WebSocket.Server | undefined = undefined
|
|
16
|
+
let server: any
|
|
17
|
+
|
|
18
|
+
while (socket === undefined) {
|
|
19
|
+
try {
|
|
20
|
+
; ({ socket, server } = await startServer(port))
|
|
21
|
+
} catch (e: any) {
|
|
22
|
+
if (e.code === "EADDRINUSE") {
|
|
23
|
+
port++
|
|
24
|
+
} else {
|
|
25
|
+
throw e
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
17
30
|
const serverAdapter = new NodeWSServerAdapter(socket)
|
|
18
31
|
|
|
19
32
|
const serverUrl = `ws://localhost:${port}`
|
|
@@ -25,19 +38,19 @@ describe("Websocket adapters", async () => {
|
|
|
25
38
|
server.close()
|
|
26
39
|
}
|
|
27
40
|
|
|
28
|
-
return { adapters: [
|
|
41
|
+
return { adapters: [aliceAdapter, serverAdapter, bobAdapter], teardown }
|
|
29
42
|
})
|
|
30
43
|
})
|
|
31
44
|
|
|
32
45
|
describe("The BrowserWebSocketClientAdapter", () => {
|
|
33
46
|
it("should advertise the protocol versions it supports in its join message", async () => {
|
|
34
|
-
const
|
|
47
|
+
const { socket, server } = await startServer(0)
|
|
35
48
|
let port = (server.address()!! as AddressInfo).port
|
|
36
49
|
const serverUrl = `ws://localhost:${port}`
|
|
37
50
|
const helloPromise = firstMessage(socket)
|
|
38
51
|
|
|
39
52
|
const client = new BrowserWebSocketClientAdapter(serverUrl)
|
|
40
|
-
const repo = new Repo({network: [client], peerId: "browser" as PeerId})
|
|
53
|
+
const repo = new Repo({ network: [client], peerId: "browser" as PeerId })
|
|
41
54
|
|
|
42
55
|
const hello = await helloPromise
|
|
43
56
|
|
|
@@ -45,8 +58,8 @@ describe("The BrowserWebSocketClientAdapter", () => {
|
|
|
45
58
|
assert.deepEqual(message, {
|
|
46
59
|
type: "join",
|
|
47
60
|
senderId: "browser",
|
|
48
|
-
supportedProtocolVersions: ["1"]
|
|
49
|
-
})
|
|
61
|
+
supportedProtocolVersions: ["1"],
|
|
62
|
+
})
|
|
50
63
|
})
|
|
51
64
|
})
|
|
52
65
|
|
|
@@ -55,12 +68,13 @@ describe("The NodeWSServerAdapter", () => {
|
|
|
55
68
|
const response = await serverHelloGivenClientHello({
|
|
56
69
|
type: "join",
|
|
57
70
|
senderId: "browser",
|
|
58
|
-
supportedProtocolVersions: ["1"]
|
|
71
|
+
supportedProtocolVersions: ["1"],
|
|
59
72
|
})
|
|
60
73
|
assert.deepEqual<any>(response, {
|
|
61
74
|
type: "peer",
|
|
62
75
|
senderId: "server",
|
|
63
|
-
|
|
76
|
+
targetId: "browser",
|
|
77
|
+
selectedProtocolVersion: "1",
|
|
64
78
|
})
|
|
65
79
|
})
|
|
66
80
|
|
|
@@ -68,11 +82,13 @@ describe("The NodeWSServerAdapter", () => {
|
|
|
68
82
|
const response = await serverHelloGivenClientHello({
|
|
69
83
|
type: "join",
|
|
70
84
|
senderId: "browser",
|
|
71
|
-
supportedProtocolVersions: ["fake"]
|
|
85
|
+
supportedProtocolVersions: ["fake"],
|
|
72
86
|
})
|
|
73
87
|
assert.deepEqual<any>(response, {
|
|
74
88
|
type: "error",
|
|
75
|
-
|
|
89
|
+
senderId: "server",
|
|
90
|
+
targetId: "browser",
|
|
91
|
+
message: "unsupported protocol version",
|
|
76
92
|
})
|
|
77
93
|
})
|
|
78
94
|
|
|
@@ -84,17 +100,20 @@ describe("The NodeWSServerAdapter", () => {
|
|
|
84
100
|
assert.deepEqual<any>(response, {
|
|
85
101
|
type: "peer",
|
|
86
102
|
senderId: "server",
|
|
87
|
-
|
|
103
|
+
targetId: "browser",
|
|
104
|
+
selectedProtocolVersion: "1",
|
|
88
105
|
})
|
|
89
106
|
})
|
|
90
107
|
})
|
|
91
108
|
|
|
92
|
-
async function serverHelloGivenClientHello(
|
|
93
|
-
|
|
109
|
+
async function serverHelloGivenClientHello(
|
|
110
|
+
clientHello: Object
|
|
111
|
+
): Promise<Object | null> {
|
|
112
|
+
const { socket, server } = await startServer(0)
|
|
94
113
|
let port = (server.address()!! as AddressInfo).port
|
|
95
114
|
const serverUrl = `ws://localhost:${port}`
|
|
96
115
|
const adapter = new NodeWSServerAdapter(socket)
|
|
97
|
-
const repo = new Repo({network: [adapter], peerId: "server" as PeerId})
|
|
116
|
+
const repo = new Repo({ network: [adapter], peerId: "server" as PeerId })
|
|
98
117
|
|
|
99
118
|
const clientSocket = new WebSocket(serverUrl)
|
|
100
119
|
await once(clientSocket, "open")
|
|
@@ -107,9 +126,11 @@ async function serverHelloGivenClientHello(clientHello: Object): Promise<Object
|
|
|
107
126
|
return message
|
|
108
127
|
}
|
|
109
128
|
|
|
110
|
-
async function firstMessage(
|
|
129
|
+
async function firstMessage(
|
|
130
|
+
socket: WebSocket.Server<any>
|
|
131
|
+
): Promise<Object | null> {
|
|
111
132
|
return new Promise((resolve, reject) => {
|
|
112
|
-
socket.once("connection",
|
|
133
|
+
socket.once("connection", ws => {
|
|
113
134
|
ws.once("message", (message: any) => {
|
|
114
135
|
resolve(message)
|
|
115
136
|
})
|
|
@@ -117,7 +138,7 @@ async function firstMessage(socket: WebSocket.Server<any>): Promise<Object | nul
|
|
|
117
138
|
reject(error)
|
|
118
139
|
})
|
|
119
140
|
})
|
|
120
|
-
socket.once("error",
|
|
141
|
+
socket.once("error", error => {
|
|
121
142
|
reject(error)
|
|
122
143
|
})
|
|
123
144
|
})
|
package/dist/message.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { type InboundMessagePayload } from "@automerge/automerge-repo";
|
|
2
|
-
import { ProtocolVersion } from "./protocolVersion";
|
|
3
|
-
export interface InboundWebSocketMessage extends InboundMessagePayload {
|
|
4
|
-
supportedProtocolVersions?: ProtocolVersion[];
|
|
5
|
-
}
|
|
6
|
-
export interface OutboundWebSocketMessage extends InboundMessagePayload {
|
|
7
|
-
errorMessage?: string;
|
|
8
|
-
}
|
|
9
|
-
//# sourceMappingURL=message.d.ts.map
|
package/dist/message.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"message.d.ts","sourceRoot":"","sources":["../src/message.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,qBAAqB,EAAC,MAAM,2BAA2B,CAAA;AACpE,OAAO,EAAC,eAAe,EAAC,MAAM,mBAAmB,CAAA;AAEjD,MAAM,WAAW,uBAAwB,SAAQ,qBAAqB;IACpE,yBAAyB,CAAC,EAAE,eAAe,EAAE,CAAA;CAC9C;AAED,MAAM,WAAW,wBAAyB,SAAQ,qBAAqB;IACrE,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB"}
|
package/src/message.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import {type InboundMessagePayload} from "@automerge/automerge-repo"
|
|
2
|
-
import {ProtocolVersion} from "./protocolVersion"
|
|
3
|
-
|
|
4
|
-
export interface InboundWebSocketMessage extends InboundMessagePayload {
|
|
5
|
-
supportedProtocolVersions?: ProtocolVersion[]
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export interface OutboundWebSocketMessage extends InboundMessagePayload {
|
|
9
|
-
errorMessage?: string
|
|
10
|
-
}
|
|
File without changes
|