@evolu/nodejs 1.0.1-preview.7 → 1.0.1-preview.8
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/Evolu/Relay.d.ts.map +1 -1
- package/dist/Evolu/Relay.js +50 -11
- package/package.json +6 -4
- package/src/Evolu/Relay.ts +55 -15
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Relay.d.ts","sourceRoot":"","sources":["../../src/Evolu/Relay.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EAQX,MAAM,eAAe,CAAC;AACvB,OAAO,EAKL,KAAK,EACL,WAAW,EAEZ,MAAM,qBAAqB,CAAC;AAK7B,MAAM,WAAW,iBAAkB,SAAQ,WAAW;IACpD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,eAAO,MAAM,iBAAiB,GAC3B,MAAM,UAAU,MACV,QAAQ,iBAAiB,KAAG,OAAO,CAAC,KAAK,
|
|
1
|
+
{"version":3,"file":"Relay.d.ts","sourceRoot":"","sources":["../../src/Evolu/Relay.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EAQX,MAAM,eAAe,CAAC;AACvB,OAAO,EAKL,KAAK,EACL,WAAW,EAEZ,MAAM,qBAAqB,CAAC;AAK7B,MAAM,WAAW,iBAAkB,SAAQ,WAAW;IACpD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,eAAO,MAAM,iBAAiB,GAC3B,MAAM,UAAU,MACV,QAAQ,iBAAiB,KAAG,OAAO,CAAC,KAAK,CA+I/C,CAAC"}
|
package/dist/Evolu/Relay.js
CHANGED
|
@@ -4,7 +4,7 @@ import { WebSocket, WebSocketServer } from "ws";
|
|
|
4
4
|
import { createBetterSqliteDriver } from "../BetterSqliteDriver.js";
|
|
5
5
|
import { createTimingSafeEqual } from "../Crypto.js";
|
|
6
6
|
export const createNodeJsRelay = (deps) => async (config) => {
|
|
7
|
-
const { port = 443, name =
|
|
7
|
+
const { port = 443, name = SimpleName.orThrow("evolu-relay"), enableLogging = false, } = config;
|
|
8
8
|
deps.console.enabled = true;
|
|
9
9
|
deps.console.log(`Evolu Relay started on port ${port}`);
|
|
10
10
|
deps.console.enabled = enableLogging;
|
|
@@ -19,7 +19,7 @@ export const createNodeJsRelay = (deps) => async (config) => {
|
|
|
19
19
|
};
|
|
20
20
|
const storage = getOrThrow(createRelayStorage(relaySqliteStorageDeps)({
|
|
21
21
|
onStorageError: (error) => {
|
|
22
|
-
deps.console.error("[relay]", "
|
|
22
|
+
deps.console.error("[relay]", "storage", error);
|
|
23
23
|
},
|
|
24
24
|
}));
|
|
25
25
|
const wss = new WebSocketServer({
|
|
@@ -28,34 +28,73 @@ export const createNodeJsRelay = (deps) => async (config) => {
|
|
|
28
28
|
});
|
|
29
29
|
const ownerSocketsMap = createManyToManyMap();
|
|
30
30
|
wss.on("connection", (ws) => {
|
|
31
|
-
|
|
31
|
+
deps.console.log("[relay]", "connection", {
|
|
32
|
+
clientCount: wss.clients.size,
|
|
33
|
+
});
|
|
34
|
+
ws.on("error", (error) => {
|
|
35
|
+
deps.console.warn("[relay]", "error", { error });
|
|
36
|
+
deps.console.error(error);
|
|
37
|
+
});
|
|
32
38
|
const options = {
|
|
33
39
|
subscribe: (ownerId) => {
|
|
34
40
|
ownerSocketsMap.add(ownerId, ws);
|
|
41
|
+
deps.console.log("[relay]", "subscribe", {
|
|
42
|
+
ownerId,
|
|
43
|
+
subscriberCount: ownerSocketsMap.getValues(ownerId)?.size ?? 0,
|
|
44
|
+
});
|
|
45
|
+
},
|
|
46
|
+
unsubscribe: (ownerId) => {
|
|
47
|
+
ownerSocketsMap.remove(ownerId, ws);
|
|
48
|
+
deps.console.log("[relay]", "unsubscribe", {
|
|
49
|
+
ownerId,
|
|
50
|
+
subscriberCount: ownerSocketsMap.getValues(ownerId)?.size ?? 0,
|
|
51
|
+
});
|
|
35
52
|
},
|
|
36
53
|
broadcast: (ownerId, message) => {
|
|
37
54
|
const sockets = ownerSocketsMap.getValues(ownerId);
|
|
55
|
+
if (!sockets)
|
|
56
|
+
return;
|
|
57
|
+
let broadcastCount = 0;
|
|
38
58
|
for (const socket of sockets) {
|
|
39
59
|
if (socket !== ws && socket.readyState === WebSocket.OPEN) {
|
|
40
60
|
socket.send(message, { binary: true });
|
|
61
|
+
broadcastCount++;
|
|
41
62
|
}
|
|
42
63
|
}
|
|
64
|
+
deps.console.log("[relay]", "broadcast", {
|
|
65
|
+
ownerId,
|
|
66
|
+
broadcastCount,
|
|
67
|
+
totalSubscribers: sockets.size,
|
|
68
|
+
});
|
|
43
69
|
},
|
|
44
70
|
};
|
|
45
71
|
ws.on("message", (message) => {
|
|
46
72
|
if (!Uint8Array.is(message))
|
|
47
73
|
return;
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
74
|
+
deps.console.log("[relay]", "on message", {
|
|
75
|
+
messageSize: message.length,
|
|
76
|
+
});
|
|
77
|
+
applyProtocolMessageAsRelay({ storage })(message, options)
|
|
78
|
+
.then((response) => {
|
|
79
|
+
if (!response.ok) {
|
|
80
|
+
deps.console.error("[relay]", "protocol", response.error);
|
|
81
|
+
deps.console.error(response.error);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
ws.send(response.value.message, { binary: true });
|
|
85
|
+
deps.console.log("[relay]", "response", {
|
|
86
|
+
responseSize: response.value.message.length,
|
|
87
|
+
});
|
|
88
|
+
})
|
|
89
|
+
.catch((error) => {
|
|
90
|
+
deps.console.error("[relay]", "applyProtocolMessageAsRelay", error);
|
|
91
|
+
});
|
|
56
92
|
});
|
|
57
93
|
ws.on("close", () => {
|
|
58
94
|
ownerSocketsMap.deleteValue(ws);
|
|
95
|
+
deps.console.log("[relay]", "close", {
|
|
96
|
+
clientCount: wss.clients.size,
|
|
97
|
+
});
|
|
59
98
|
});
|
|
60
99
|
});
|
|
61
100
|
const disposeWss = () => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@evolu/nodejs",
|
|
3
|
-
"version": "1.0.1-preview.
|
|
3
|
+
"version": "1.0.1-preview.8",
|
|
4
4
|
"description": "Evolu for Node.js",
|
|
5
5
|
"author": "Daniel Steigerwald <daniel@steigerwald.cz>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -26,13 +26,15 @@
|
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@types/better-sqlite3": "^7.6.13",
|
|
28
28
|
"@types/node": "^22.17.1",
|
|
29
|
+
"@types/ws": "^8.18.1",
|
|
30
|
+
"shx": "^0.4.0",
|
|
29
31
|
"typescript": "^5.9.2",
|
|
30
|
-
"vitest": "^
|
|
31
|
-
"@evolu/common": "6.0.1-preview.
|
|
32
|
+
"vitest": "^4.0.4",
|
|
33
|
+
"@evolu/common": "6.0.1-preview.20",
|
|
32
34
|
"@evolu/tsconfig": "0.0.2"
|
|
33
35
|
},
|
|
34
36
|
"peerDependencies": {
|
|
35
|
-
"@evolu/common": "^6.0.1-preview.
|
|
37
|
+
"@evolu/common": "^6.0.1-preview.20"
|
|
36
38
|
},
|
|
37
39
|
"engines": {
|
|
38
40
|
"node": ">=22.0.0"
|
package/src/Evolu/Relay.ts
CHANGED
|
@@ -30,7 +30,7 @@ export const createNodeJsRelay =
|
|
|
30
30
|
async (config: NodeJsRelayConfig): Promise<Relay> => {
|
|
31
31
|
const {
|
|
32
32
|
port = 443,
|
|
33
|
-
name =
|
|
33
|
+
name = SimpleName.orThrow("evolu-relay"),
|
|
34
34
|
enableLogging = false,
|
|
35
35
|
} = config;
|
|
36
36
|
|
|
@@ -54,7 +54,7 @@ export const createNodeJsRelay =
|
|
|
54
54
|
const storage = getOrThrow(
|
|
55
55
|
createRelayStorage(relaySqliteStorageDeps)({
|
|
56
56
|
onStorageError: (error) => {
|
|
57
|
-
deps.console.error("[relay]", "
|
|
57
|
+
deps.console.error("[relay]", "storage", error);
|
|
58
58
|
},
|
|
59
59
|
}),
|
|
60
60
|
);
|
|
@@ -67,42 +67,82 @@ export const createNodeJsRelay =
|
|
|
67
67
|
const ownerSocketsMap = createManyToManyMap<OwnerId, WebSocket>();
|
|
68
68
|
|
|
69
69
|
wss.on("connection", (ws) => {
|
|
70
|
-
|
|
70
|
+
deps.console.log("[relay]", "connection", {
|
|
71
|
+
clientCount: wss.clients.size,
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
ws.on("error", (error) => {
|
|
75
|
+
deps.console.warn("[relay]", "error", { error });
|
|
76
|
+
deps.console.error(error);
|
|
77
|
+
});
|
|
71
78
|
|
|
72
79
|
const options: ApplyProtocolMessageAsRelayOptions = {
|
|
73
80
|
subscribe: (ownerId) => {
|
|
74
81
|
ownerSocketsMap.add(ownerId, ws);
|
|
82
|
+
deps.console.log("[relay]", "subscribe", {
|
|
83
|
+
ownerId,
|
|
84
|
+
subscriberCount: ownerSocketsMap.getValues(ownerId)?.size ?? 0,
|
|
85
|
+
});
|
|
75
86
|
},
|
|
87
|
+
|
|
88
|
+
unsubscribe: (ownerId) => {
|
|
89
|
+
ownerSocketsMap.remove(ownerId, ws);
|
|
90
|
+
deps.console.log("[relay]", "unsubscribe", {
|
|
91
|
+
ownerId,
|
|
92
|
+
subscriberCount: ownerSocketsMap.getValues(ownerId)?.size ?? 0,
|
|
93
|
+
});
|
|
94
|
+
},
|
|
95
|
+
|
|
76
96
|
broadcast: (ownerId, message) => {
|
|
77
|
-
const sockets = ownerSocketsMap.getValues(ownerId)
|
|
97
|
+
const sockets = ownerSocketsMap.getValues(ownerId);
|
|
98
|
+
if (!sockets) return;
|
|
99
|
+
|
|
100
|
+
let broadcastCount = 0;
|
|
78
101
|
for (const socket of sockets) {
|
|
79
102
|
if (socket !== ws && socket.readyState === WebSocket.OPEN) {
|
|
80
103
|
socket.send(message, { binary: true });
|
|
104
|
+
broadcastCount++;
|
|
81
105
|
}
|
|
82
106
|
}
|
|
107
|
+
|
|
108
|
+
deps.console.log("[relay]", "broadcast", {
|
|
109
|
+
ownerId,
|
|
110
|
+
broadcastCount,
|
|
111
|
+
totalSubscribers: sockets.size,
|
|
112
|
+
});
|
|
83
113
|
},
|
|
84
114
|
};
|
|
85
115
|
|
|
86
116
|
ws.on("message", (message) => {
|
|
87
117
|
if (!Uint8Array.is(message)) return;
|
|
88
118
|
|
|
89
|
-
|
|
90
|
-
message,
|
|
91
|
-
|
|
92
|
-
);
|
|
119
|
+
deps.console.log("[relay]", "on message", {
|
|
120
|
+
messageSize: message.length,
|
|
121
|
+
});
|
|
93
122
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
123
|
+
applyProtocolMessageAsRelay({ storage })(message, options)
|
|
124
|
+
.then((response) => {
|
|
125
|
+
if (!response.ok) {
|
|
126
|
+
deps.console.error("[relay]", "protocol", response.error);
|
|
127
|
+
deps.console.error(response.error);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
98
130
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
131
|
+
ws.send(response.value.message, { binary: true });
|
|
132
|
+
deps.console.log("[relay]", "response", {
|
|
133
|
+
responseSize: response.value.message.length,
|
|
134
|
+
});
|
|
135
|
+
})
|
|
136
|
+
.catch((error: unknown) => {
|
|
137
|
+
deps.console.error("[relay]", "applyProtocolMessageAsRelay", error);
|
|
138
|
+
});
|
|
102
139
|
});
|
|
103
140
|
|
|
104
141
|
ws.on("close", () => {
|
|
105
142
|
ownerSocketsMap.deleteValue(ws);
|
|
143
|
+
deps.console.log("[relay]", "close", {
|
|
144
|
+
clientCount: wss.clients.size,
|
|
145
|
+
});
|
|
106
146
|
});
|
|
107
147
|
});
|
|
108
148
|
|