@rljson/server 0.0.3 → 0.0.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.architecture.md +1116 -0
- package/README.blog.md +9 -1
- package/README.contributors.md +47 -13
- package/README.md +70 -11
- package/README.public.md +204 -2
- package/README.trouble.md +50 -0
- package/dist/README.architecture.md +1116 -0
- package/dist/README.blog.md +9 -1
- package/dist/README.contributors.md +47 -13
- package/dist/README.md +70 -11
- package/dist/README.public.md +204 -2
- package/dist/README.trouble.md +50 -0
- package/dist/client.d.ts +6 -3
- package/dist/server.d.ts +8 -3
- package/dist/server.js +75 -39
- package/dist/socket-bundle.d.ts +16 -0
- package/package.json +12 -12
package/dist/server.js
CHANGED
|
@@ -743,21 +743,23 @@ class BsPeerBridge {
|
|
|
743
743
|
this._socket = _socket;
|
|
744
744
|
}
|
|
745
745
|
_eventHandlers = /* @__PURE__ */ new Map();
|
|
746
|
+
_handleConnectBound = this._handleConnect.bind(this);
|
|
747
|
+
_handleDisconnectBound = this._handleDisconnect.bind(this);
|
|
746
748
|
/**
|
|
747
749
|
* Starts the bridge by setting up connection event handlers and
|
|
748
750
|
* automatically registering all Bs methods.
|
|
749
751
|
*/
|
|
750
752
|
start() {
|
|
751
|
-
this._socket.on("connect",
|
|
752
|
-
this._socket.on("disconnect",
|
|
753
|
+
this._socket.on("connect", this._handleConnectBound);
|
|
754
|
+
this._socket.on("disconnect", this._handleDisconnectBound);
|
|
753
755
|
this._registerBsMethods();
|
|
754
756
|
}
|
|
755
757
|
/**
|
|
756
758
|
* Stops the bridge by removing all event handlers.
|
|
757
759
|
*/
|
|
758
760
|
stop() {
|
|
759
|
-
this._socket.off("connect",
|
|
760
|
-
this._socket.off("disconnect",
|
|
761
|
+
this._socket.off("connect", this._handleConnectBound);
|
|
762
|
+
this._socket.off("disconnect", this._handleDisconnectBound);
|
|
761
763
|
for (const [eventName, handler] of this._eventHandlers) {
|
|
762
764
|
this._socket.off(eventName, handler);
|
|
763
765
|
}
|
|
@@ -768,14 +770,11 @@ class BsPeerBridge {
|
|
|
768
770
|
*/
|
|
769
771
|
_registerBsMethods() {
|
|
770
772
|
const bsMethods = [
|
|
771
|
-
"setBlob",
|
|
772
773
|
"getBlob",
|
|
773
774
|
"getBlobStream",
|
|
774
|
-
"deleteBlob",
|
|
775
775
|
"blobExists",
|
|
776
776
|
"getBlobProperties",
|
|
777
|
-
"listBlobs"
|
|
778
|
-
"generateSignedUrl"
|
|
777
|
+
"listBlobs"
|
|
779
778
|
];
|
|
780
779
|
for (const methodName of bsMethods) {
|
|
781
780
|
this.registerEvent(methodName);
|
|
@@ -797,17 +796,17 @@ class BsPeerBridge {
|
|
|
797
796
|
`Method "${methodName}" not found on Bs instance`
|
|
798
797
|
);
|
|
799
798
|
if (typeof callback === "function") {
|
|
800
|
-
callback(
|
|
799
|
+
callback(error, null);
|
|
801
800
|
}
|
|
802
801
|
return;
|
|
803
802
|
}
|
|
804
803
|
bsMethod.apply(this._bs, methodArgs).then((result) => {
|
|
805
804
|
if (typeof callback === "function") {
|
|
806
|
-
callback(
|
|
805
|
+
callback(null, result);
|
|
807
806
|
}
|
|
808
807
|
}).catch((error) => {
|
|
809
808
|
if (typeof callback === "function") {
|
|
810
|
-
callback(
|
|
809
|
+
callback(error, null);
|
|
811
810
|
}
|
|
812
811
|
});
|
|
813
812
|
};
|
|
@@ -855,9 +854,9 @@ class BsPeerBridge {
|
|
|
855
854
|
throw new Error(`Method "${bsMethodName}" not found on Bs instance`);
|
|
856
855
|
}
|
|
857
856
|
const result = await bsMethod.apply(this._bs, args);
|
|
858
|
-
this._socket.emit(socketEventName,
|
|
857
|
+
this._socket.emit(socketEventName, null, result);
|
|
859
858
|
} catch (error) {
|
|
860
|
-
this._socket.emit(socketEventName,
|
|
859
|
+
this._socket.emit(socketEventName, error, null);
|
|
861
860
|
}
|
|
862
861
|
}
|
|
863
862
|
/* v8 ignore next -- @preserve */
|
|
@@ -978,11 +977,24 @@ class BaseNode {
|
|
|
978
977
|
await this._localDb.core.import(data);
|
|
979
978
|
}
|
|
980
979
|
}
|
|
980
|
+
function normalizeSocketBundle(socket) {
|
|
981
|
+
const bundle = socket;
|
|
982
|
+
if (bundle.ioUp && bundle.ioDown && bundle.bsUp && bundle.bsDown) {
|
|
983
|
+
return bundle;
|
|
984
|
+
}
|
|
985
|
+
const single = socket;
|
|
986
|
+
return {
|
|
987
|
+
ioUp: single,
|
|
988
|
+
ioDown: single,
|
|
989
|
+
bsUp: single,
|
|
990
|
+
bsDown: single
|
|
991
|
+
};
|
|
992
|
+
}
|
|
981
993
|
class Client extends BaseNode {
|
|
982
994
|
// ...........................................................................
|
|
983
995
|
/**
|
|
984
996
|
* Creates a Client instance
|
|
985
|
-
* @param _socketToServer - Socket to connect to server
|
|
997
|
+
* @param _socketToServer - Socket or namespace bundle to connect to server
|
|
986
998
|
* @param _localIo - Local Io for local storage
|
|
987
999
|
* @param _localBs - Local Bs for local blob storage
|
|
988
1000
|
*/
|
|
@@ -1043,6 +1055,7 @@ class Client extends BaseNode {
|
|
|
1043
1055
|
* Builds the Io multi with local and peer layers.
|
|
1044
1056
|
*/
|
|
1045
1057
|
async _setupIo() {
|
|
1058
|
+
const sockets = normalizeSocketBundle(this._socketToServer);
|
|
1046
1059
|
this._ioMultiIos.push({
|
|
1047
1060
|
io: this._localIo,
|
|
1048
1061
|
dump: true,
|
|
@@ -1050,9 +1063,9 @@ class Client extends BaseNode {
|
|
|
1050
1063
|
write: true,
|
|
1051
1064
|
priority: 1
|
|
1052
1065
|
});
|
|
1053
|
-
const ioPeerBridge = new IoPeerBridge(this._localIo,
|
|
1066
|
+
const ioPeerBridge = new IoPeerBridge(this._localIo, sockets.ioUp);
|
|
1054
1067
|
ioPeerBridge.start();
|
|
1055
|
-
const ioPeer = await this._createIoPeer();
|
|
1068
|
+
const ioPeer = await this._createIoPeer(sockets.ioDown);
|
|
1056
1069
|
this._ioMultiIos.push({
|
|
1057
1070
|
io: ioPeer,
|
|
1058
1071
|
dump: false,
|
|
@@ -1068,15 +1081,16 @@ class Client extends BaseNode {
|
|
|
1068
1081
|
* Builds the Bs multi with local and peer layers.
|
|
1069
1082
|
*/
|
|
1070
1083
|
async _setupBs() {
|
|
1084
|
+
const sockets = normalizeSocketBundle(this._socketToServer);
|
|
1071
1085
|
this._bsMultiBss.push({
|
|
1072
1086
|
bs: this._localBs,
|
|
1073
1087
|
read: true,
|
|
1074
1088
|
write: true,
|
|
1075
1089
|
priority: 1
|
|
1076
1090
|
});
|
|
1077
|
-
const bsPeerBridge = new BsPeerBridge(this._localBs,
|
|
1091
|
+
const bsPeerBridge = new BsPeerBridge(this._localBs, sockets.bsUp);
|
|
1078
1092
|
bsPeerBridge.start();
|
|
1079
|
-
const bsPeer = await this._createBsPeer();
|
|
1093
|
+
const bsPeer = await this._createBsPeer(sockets.bsDown);
|
|
1080
1094
|
this._bsMultiBss.push({
|
|
1081
1095
|
bs: bsPeer,
|
|
1082
1096
|
read: true,
|
|
@@ -1088,18 +1102,20 @@ class Client extends BaseNode {
|
|
|
1088
1102
|
}
|
|
1089
1103
|
/**
|
|
1090
1104
|
* Creates and initializes a downstream Io peer.
|
|
1105
|
+
* @param socket - Downstream socket to the server Io namespace.
|
|
1091
1106
|
*/
|
|
1092
|
-
async _createIoPeer() {
|
|
1093
|
-
const ioPeer = new IoPeer(
|
|
1107
|
+
async _createIoPeer(socket) {
|
|
1108
|
+
const ioPeer = new IoPeer(socket);
|
|
1094
1109
|
await ioPeer.init();
|
|
1095
1110
|
await ioPeer.isReady();
|
|
1096
1111
|
return ioPeer;
|
|
1097
1112
|
}
|
|
1098
1113
|
/**
|
|
1099
1114
|
* Creates and initializes a downstream Bs peer.
|
|
1115
|
+
* @param socket - Downstream socket to the server Bs namespace.
|
|
1100
1116
|
*/
|
|
1101
|
-
async _createBsPeer() {
|
|
1102
|
-
const bsPeer = new BsPeer(
|
|
1117
|
+
async _createBsPeer(socket) {
|
|
1118
|
+
const bsPeer = new BsPeer(socket);
|
|
1103
1119
|
await bsPeer.init();
|
|
1104
1120
|
return bsPeer;
|
|
1105
1121
|
}
|
|
@@ -1167,12 +1183,25 @@ class Server extends BaseNode {
|
|
|
1167
1183
|
* @returns The server instance.
|
|
1168
1184
|
*/
|
|
1169
1185
|
async addSocket(socket) {
|
|
1186
|
+
const sockets = normalizeSocketBundle(socket);
|
|
1170
1187
|
const clientId = `client_${this._clients.size}_${Math.random().toString(36).slice(2)}`;
|
|
1171
|
-
|
|
1172
|
-
const
|
|
1173
|
-
const
|
|
1174
|
-
|
|
1175
|
-
|
|
1188
|
+
const ioUp = sockets.ioUp;
|
|
1189
|
+
const ioDown = sockets.ioDown;
|
|
1190
|
+
const bsUp = sockets.bsUp;
|
|
1191
|
+
const bsDown = sockets.bsDown;
|
|
1192
|
+
ioUp.__clientId = clientId;
|
|
1193
|
+
ioDown.__clientId = clientId;
|
|
1194
|
+
bsUp.__clientId = clientId;
|
|
1195
|
+
bsDown.__clientId = clientId;
|
|
1196
|
+
const ioPeer = await this._createIoPeer(ioUp);
|
|
1197
|
+
const bsPeer = await this._createBsPeer(bsUp);
|
|
1198
|
+
this._registerClient(
|
|
1199
|
+
clientId,
|
|
1200
|
+
{ ioUp, ioDown, bsUp, bsDown },
|
|
1201
|
+
ioPeer,
|
|
1202
|
+
bsPeer
|
|
1203
|
+
);
|
|
1204
|
+
this._pendingSockets.push({ ioDown, bsDown });
|
|
1176
1205
|
this._queueIoPeer(ioPeer);
|
|
1177
1206
|
this._queueBsPeer(bsPeer);
|
|
1178
1207
|
await this._queueRefresh();
|
|
@@ -1185,16 +1214,17 @@ class Server extends BaseNode {
|
|
|
1185
1214
|
* Removes all listeners from all connected clients.
|
|
1186
1215
|
*/
|
|
1187
1216
|
_removeAllListeners() {
|
|
1188
|
-
for (const {
|
|
1189
|
-
|
|
1217
|
+
for (const { ioUp } of this._clients.values()) {
|
|
1218
|
+
ioUp.removeAllListeners(this._route.flat);
|
|
1190
1219
|
}
|
|
1191
1220
|
}
|
|
1192
1221
|
// ...........................................................................
|
|
1193
1222
|
/**
|
|
1194
1223
|
* Broadcasts incoming payloads from any client to all other connected clients.
|
|
1224
|
+
* Ensures the sender is filtered out when broadcasting.
|
|
1195
1225
|
*/
|
|
1196
1226
|
_multicastRefs = () => {
|
|
1197
|
-
for (const {
|
|
1227
|
+
for (const [clientIdA, { ioUp: socketA }] of this._clients.entries()) {
|
|
1198
1228
|
socketA.on(this._route.flat, (payload) => {
|
|
1199
1229
|
const ref = payload.r;
|
|
1200
1230
|
if (this._multicastedRefs.has(ref)) {
|
|
@@ -1205,10 +1235,13 @@ class Server extends BaseNode {
|
|
|
1205
1235
|
if (p && p.__origin) {
|
|
1206
1236
|
return;
|
|
1207
1237
|
}
|
|
1208
|
-
for (const
|
|
1209
|
-
|
|
1238
|
+
for (const [
|
|
1239
|
+
clientIdB,
|
|
1240
|
+
{ ioDown: socketB }
|
|
1241
|
+
] of this._clients.entries()) {
|
|
1242
|
+
if (clientIdA !== clientIdB) {
|
|
1210
1243
|
const forwarded = Object.assign({}, payload, {
|
|
1211
|
-
__origin:
|
|
1244
|
+
__origin: clientIdA
|
|
1212
1245
|
});
|
|
1213
1246
|
socketB.emit(this._route.flat, forwarded);
|
|
1214
1247
|
}
|
|
@@ -1259,13 +1292,16 @@ class Server extends BaseNode {
|
|
|
1259
1292
|
/**
|
|
1260
1293
|
* Registers the client socket and peers.
|
|
1261
1294
|
* @param clientId - Stable client identifier.
|
|
1262
|
-
* @param
|
|
1295
|
+
* @param sockets - Directional sockets to register.
|
|
1263
1296
|
* @param io - Io peer associated with the client.
|
|
1264
1297
|
* @param bs - Bs peer associated with the client.
|
|
1265
1298
|
*/
|
|
1266
|
-
_registerClient(clientId,
|
|
1299
|
+
_registerClient(clientId, sockets, io, bs) {
|
|
1267
1300
|
this._clients.set(clientId, {
|
|
1268
|
-
|
|
1301
|
+
ioUp: sockets.ioUp,
|
|
1302
|
+
ioDown: sockets.ioDown,
|
|
1303
|
+
bsUp: sockets.bsUp,
|
|
1304
|
+
bsDown: sockets.bsDown,
|
|
1269
1305
|
io,
|
|
1270
1306
|
bs
|
|
1271
1307
|
});
|
|
@@ -1311,9 +1347,9 @@ class Server extends BaseNode {
|
|
|
1311
1347
|
async _refreshServers() {
|
|
1312
1348
|
this._ioServer._io = this._ioMulti;
|
|
1313
1349
|
this._bsServer._bs = this._bsMulti;
|
|
1314
|
-
for (const
|
|
1315
|
-
await this._ioServer.addSocket(
|
|
1316
|
-
await this._bsServer.addSocket(
|
|
1350
|
+
for (const pending of this._pendingSockets) {
|
|
1351
|
+
await this._ioServer.addSocket(pending.ioDown);
|
|
1352
|
+
await this._bsServer.addSocket(pending.bsDown);
|
|
1317
1353
|
}
|
|
1318
1354
|
this._pendingSockets = [];
|
|
1319
1355
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Socket } from '@rljson/io';
|
|
2
|
+
export type SocketNamespaceBundle = {
|
|
3
|
+
ioUp: Socket;
|
|
4
|
+
ioDown: Socket;
|
|
5
|
+
bsUp: Socket;
|
|
6
|
+
bsDown: Socket;
|
|
7
|
+
};
|
|
8
|
+
export type SocketLike = Socket | SocketNamespaceBundle;
|
|
9
|
+
/**
|
|
10
|
+
* Normalizes a socket input into a full namespace bundle used by the server/client constructors.
|
|
11
|
+
* - If you pass a single Socket (classic setup), it is reused for all namespaces (ioUp/ioDown/bsUp/bsDown).
|
|
12
|
+
* - If you pass an explicit bundle (namespaces already split), the bundle is returned as-is.
|
|
13
|
+
* @param socket - Single socket or pre-split namespace bundle.
|
|
14
|
+
* @returns Normalized namespace bundle for Io/Bs up/down channels.
|
|
15
|
+
*/
|
|
16
|
+
export declare function normalizeSocketBundle(socket: SocketLike): SocketNamespaceBundle;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rljson/server",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"description": "Rljson server description",
|
|
5
5
|
"homepage": "https://github.com/rljson/server",
|
|
6
6
|
"bugs": "https://github.com/rljson/server/issues",
|
|
@@ -20,35 +20,35 @@
|
|
|
20
20
|
],
|
|
21
21
|
"type": "module",
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"@types/node": "^25.0
|
|
24
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
25
|
-
"@typescript-eslint/parser": "^8.
|
|
23
|
+
"@types/node": "^25.1.0",
|
|
24
|
+
"@typescript-eslint/eslint-plugin": "^8.54.0",
|
|
25
|
+
"@typescript-eslint/parser": "^8.54.0",
|
|
26
26
|
"@vitest/coverage-v8": "^4.0.18",
|
|
27
27
|
"cross-env": "^10.1.0",
|
|
28
28
|
"eslint": "^9.39.2",
|
|
29
|
-
"eslint-plugin-jsdoc": "^62.
|
|
29
|
+
"eslint-plugin-jsdoc": "^62.5.0",
|
|
30
30
|
"eslint-plugin-tsdoc": "^0.5.0",
|
|
31
|
-
"globals": "^17.
|
|
31
|
+
"globals": "^17.2.0",
|
|
32
32
|
"jsdoc": "^4.0.5",
|
|
33
33
|
"read-pkg": "^10.0.0",
|
|
34
34
|
"socket.io": "^4.8.3",
|
|
35
35
|
"socket.io-client": "^4.8.3",
|
|
36
36
|
"typescript": "~5.9.3",
|
|
37
|
-
"typescript-eslint": "^8.
|
|
37
|
+
"typescript-eslint": "^8.54.0",
|
|
38
38
|
"vite": "^7.3.1",
|
|
39
39
|
"vite-node": "^5.3.0",
|
|
40
40
|
"vite-plugin-dts": "^4.5.4",
|
|
41
|
-
"vite-tsconfig-paths": "^6.0.
|
|
41
|
+
"vite-tsconfig-paths": "^6.0.5",
|
|
42
42
|
"vitest": "^4.0.18",
|
|
43
43
|
"vitest-dom": "^0.1.1"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@rljson/bs": "^0.0.
|
|
47
|
-
"@rljson/db": "^0.0.
|
|
46
|
+
"@rljson/bs": "^0.0.20",
|
|
47
|
+
"@rljson/db": "^0.0.13",
|
|
48
48
|
"@rljson/hash": "^0.0.18",
|
|
49
|
-
"@rljson/io": "^0.0.
|
|
49
|
+
"@rljson/io": "^0.0.65",
|
|
50
50
|
"@rljson/json": "^0.0.23",
|
|
51
|
-
"@rljson/rljson": "^0.0.
|
|
51
|
+
"@rljson/rljson": "^0.0.75"
|
|
52
52
|
},
|
|
53
53
|
"scripts": {
|
|
54
54
|
"build": "pnpx vite build && tsc && node scripts/copy-readme-to-dist.js",
|