@pluv/io 0.20.0 → 0.21.1
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/.turbo/turbo-build.log +16 -16
- package/CHANGELOG.md +79 -0
- package/dist/index.d.mts +115 -83
- package/dist/index.d.ts +115 -83
- package/dist/index.js +323 -212
- package/dist/index.mjs +323 -212
- package/package.json +7 -7
- package/src/AbstractPlatform.ts +64 -20
- package/src/AbstractWebSocket.ts +50 -16
- package/src/IORoom.ts +262 -176
- package/src/PluvIO.ts +27 -14
- package/src/PluvProcedure.ts +11 -29
- package/src/PluvRouter.ts +4 -4
- package/src/PluvServer.ts +27 -12
- package/src/authorize.ts +2 -2
- package/src/constants.ts +1 -0
- package/src/createIO.ts +4 -4
- package/src/index.ts +7 -5
- package/src/types.ts +24 -11
- package/src/version.generated.ts +1 -1
package/dist/index.js
CHANGED
|
@@ -216,15 +216,23 @@ var PubSub = class extends AbstractPubSub {
|
|
|
216
216
|
// src/AbstractPlatform.ts
|
|
217
217
|
var AbstractPlatform = class {
|
|
218
218
|
constructor(config = {}) {
|
|
219
|
-
|
|
219
|
+
this._initialized = false;
|
|
220
|
+
const { context, persistance, pubSub } = config;
|
|
221
|
+
context && (this._ioContext = context);
|
|
222
|
+
context && (this._roomContext = context);
|
|
220
223
|
this.persistance = persistance != null ? persistance : new Persistance();
|
|
221
224
|
this.pubSub = pubSub != null ? pubSub : new PubSub();
|
|
222
225
|
}
|
|
226
|
+
_initialize() {
|
|
227
|
+
if (this._initialized) throw new Error("Platform is already initialized");
|
|
228
|
+
this._initialized = true;
|
|
229
|
+
return this;
|
|
230
|
+
}
|
|
223
231
|
};
|
|
224
232
|
|
|
225
233
|
// src/AbstractWebSocket.ts
|
|
226
234
|
var AbstractWebSocket = class {
|
|
227
|
-
constructor(config) {
|
|
235
|
+
constructor(webSocket, config) {
|
|
228
236
|
/** The connection is not yet open. */
|
|
229
237
|
this.CONNECTING = 0;
|
|
230
238
|
/** The connection is open and ready to communicate. */
|
|
@@ -233,18 +241,36 @@ var AbstractWebSocket = class {
|
|
|
233
241
|
this.CLOSING = 2;
|
|
234
242
|
/** The connection is closed. */
|
|
235
243
|
this.CLOSED = 3;
|
|
236
|
-
|
|
244
|
+
this._user = null;
|
|
245
|
+
const { persistance, room } = config;
|
|
246
|
+
this.persistance = persistance;
|
|
237
247
|
this.room = room;
|
|
238
|
-
this.
|
|
248
|
+
this.webSocket = webSocket;
|
|
249
|
+
}
|
|
250
|
+
getSession() {
|
|
251
|
+
return __async(this, null, function* () {
|
|
252
|
+
var _a;
|
|
253
|
+
const sessionId = this.sessionId;
|
|
254
|
+
const state = this.state;
|
|
255
|
+
const room = state.room;
|
|
256
|
+
const user = (_a = this._user) != null ? _a : yield this.persistance.getUser(room, sessionId);
|
|
257
|
+
this._user = user;
|
|
258
|
+
return __spreadProps(__spreadValues({}, state), {
|
|
259
|
+
id: sessionId,
|
|
260
|
+
user,
|
|
261
|
+
webSocket: this
|
|
262
|
+
});
|
|
263
|
+
});
|
|
239
264
|
}
|
|
240
265
|
handleError(params) {
|
|
241
266
|
var _a, _b, _c;
|
|
242
|
-
const { error, message
|
|
267
|
+
const { error, message: _message, room, session } = params;
|
|
268
|
+
const message = error instanceof Error ? error.message : "Unexpected error";
|
|
243
269
|
const stack = error instanceof Error ? (_a = error.stack) != null ? _a : null : null;
|
|
244
270
|
return this.sendMessage({
|
|
245
271
|
connectionId: (_b = session == null ? void 0 : session.id) != null ? _b : null,
|
|
246
272
|
data: { message, stack },
|
|
247
|
-
room
|
|
273
|
+
room,
|
|
248
274
|
type: "$ERROR",
|
|
249
275
|
user: (_c = session == null ? void 0 : session.user) != null ? _c : null
|
|
250
276
|
});
|
|
@@ -362,8 +388,10 @@ var authorize = (params) => {
|
|
|
362
388
|
return { decode, encode };
|
|
363
389
|
};
|
|
364
390
|
|
|
365
|
-
// src/
|
|
391
|
+
// src/constants.ts
|
|
366
392
|
var PING_TIMEOUT_MS = 3e4;
|
|
393
|
+
|
|
394
|
+
// src/IORoom.ts
|
|
367
395
|
var IORoom = class {
|
|
368
396
|
constructor(id, config) {
|
|
369
397
|
this._sessions = /* @__PURE__ */ new Map();
|
|
@@ -375,12 +403,21 @@ var IORoom = class {
|
|
|
375
403
|
this._docFactory = crdt.doc(() => ({}));
|
|
376
404
|
this._doc = this._docFactory.getEmpty();
|
|
377
405
|
this._router = router;
|
|
378
|
-
this._platform = platform;
|
|
406
|
+
this._platform = platform.initialize({ context });
|
|
379
407
|
this.id = id;
|
|
380
408
|
this._listeners = {
|
|
381
409
|
onDestroy: (event) => onDestroy == null ? void 0 : onDestroy(event)
|
|
382
410
|
};
|
|
383
411
|
if (authorize2) this._authorize = authorize2;
|
|
412
|
+
const webSockets = this._platform.getWebSockets();
|
|
413
|
+
if (!webSockets.length) return;
|
|
414
|
+
webSockets.forEach((webSocket) => {
|
|
415
|
+
const deserialized = this._platform.getSerializedState(webSocket);
|
|
416
|
+
const sessionId = this._platform.getSessionId(webSocket);
|
|
417
|
+
if (!deserialized) return;
|
|
418
|
+
if (typeof sessionId !== "string") return;
|
|
419
|
+
this._sessions.set(sessionId, this._platform.convertWebSocket(webSocket, { room: this.id }));
|
|
420
|
+
});
|
|
384
421
|
}
|
|
385
422
|
get _events() {
|
|
386
423
|
return this._router._events;
|
|
@@ -398,111 +435,135 @@ var IORoom = class {
|
|
|
398
435
|
}
|
|
399
436
|
getSize() {
|
|
400
437
|
const currentTime = (/* @__PURE__ */ new Date()).getTime();
|
|
401
|
-
return Array.from(this._sessions.values()).reduce((count,
|
|
402
|
-
|
|
403
|
-
|
|
438
|
+
return Array.from(this._sessions.values()).reduce((count, pluvWs) => {
|
|
439
|
+
var _a;
|
|
440
|
+
if (pluvWs.state.quit) return count;
|
|
441
|
+
const pingTime = (_a = this._platform.getLastPing(pluvWs)) != null ? _a : pluvWs.state.timers.ping;
|
|
442
|
+
return currentTime - pingTime > PING_TIMEOUT_MS ? count : count + 1;
|
|
404
443
|
}, 0);
|
|
405
444
|
}
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
445
|
+
onClose(webSocket) {
|
|
446
|
+
this._ensureDetached();
|
|
447
|
+
const wsSession = this._getAbstractWs(webSocket);
|
|
448
|
+
if (!wsSession) return () => void 0;
|
|
449
|
+
return this._onClose(wsSession);
|
|
450
|
+
}
|
|
451
|
+
onError(webSocket) {
|
|
452
|
+
this._ensureDetached();
|
|
453
|
+
const wsSession = this._getAbstractWs(webSocket);
|
|
454
|
+
if (!wsSession) return () => void 0;
|
|
455
|
+
return this._onClose(wsSession);
|
|
456
|
+
}
|
|
457
|
+
onMessage(webSocket) {
|
|
458
|
+
this._ensureDetached();
|
|
459
|
+
const wsSession = this._getAbstractWs(webSocket);
|
|
460
|
+
if (!wsSession) return () => void 0;
|
|
461
|
+
return this._onMessage(wsSession);
|
|
462
|
+
}
|
|
463
|
+
register(_0) {
|
|
464
|
+
return __async(this, arguments, function* (webSocket, options = {}) {
|
|
465
|
+
const { token } = options;
|
|
411
466
|
if (!this._uninitialize) yield this._initialize();
|
|
412
|
-
const user = yield this._getAuthorizedUser(token
|
|
413
|
-
const
|
|
414
|
-
const pluvWs = this._platform.convertWebSocket(webSocket, {
|
|
415
|
-
room: this.id,
|
|
416
|
-
sessionId,
|
|
417
|
-
userId: (_b = user == null ? void 0 : user.id) != null ? _b : null
|
|
418
|
-
});
|
|
419
|
-
this._logDebug(`${import_kleur.default.blue(`Registering connection for room ${this.id}:`)} ${sessionId}`);
|
|
420
|
-
const uninitializeWs = yield pluvWs.initialize();
|
|
421
|
-
const ioAuthorize = this._getIOAuthorize(options);
|
|
467
|
+
const user = yield this._getAuthorizedUser(token);
|
|
468
|
+
const ioAuthorize = this._getIOAuthorize();
|
|
422
469
|
const isUnauthorized = !!(ioAuthorize == null ? void 0 : ioAuthorize.required) && !user;
|
|
423
|
-
const isTokenInUse = !!user &&
|
|
424
|
-
var
|
|
425
|
-
return ((
|
|
426
|
-
});
|
|
470
|
+
const isTokenInUse = !!user && (yield this._getSessions().then((sessions) => sessions.some((session) => {
|
|
471
|
+
var _a;
|
|
472
|
+
return ((_a = session.user) == null ? void 0 : _a.id) === user.id;
|
|
473
|
+
})));
|
|
474
|
+
const pluvWs = yield this._platform.convertWebSocket(webSocket, { room: this.id });
|
|
475
|
+
this._logDebug(`${import_kleur.default.blue(`Registering connection for room ${this.id}:`)} ${pluvWs.sessionId}`);
|
|
476
|
+
yield this._platform.acceptWebSocket(pluvWs);
|
|
427
477
|
if (isUnauthorized || isTokenInUse) {
|
|
428
|
-
this._logDebug(`${import_kleur.default.blue("Authorization failed for connection:")} ${sessionId}`);
|
|
429
|
-
pluvWs.handleError({ error: new Error("Not authorized") });
|
|
478
|
+
this._logDebug(`${import_kleur.default.blue("Authorization failed for connection:")} ${pluvWs.sessionId}`);
|
|
479
|
+
pluvWs.handleError({ error: new Error("Not authorized"), room: this.id });
|
|
430
480
|
pluvWs.close(3e3, "WebSocket unauthorized.");
|
|
431
481
|
return;
|
|
432
482
|
}
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
};
|
|
445
|
-
this._sessions.set(session.id, session);
|
|
446
|
-
yield this._platform.persistance.addUser(this.id, sessionId, user != null ? user : {});
|
|
447
|
-
const onClose = this._onClose(session, uninitializeWs).bind(this);
|
|
448
|
-
const onMessage = this._onMessage(session, platformEventContext).bind(this);
|
|
449
|
-
pluvWs.addEventListener("close", onClose);
|
|
450
|
-
pluvWs.addEventListener("error", onClose);
|
|
451
|
-
pluvWs.addEventListener("message", onMessage);
|
|
452
|
-
this._emitRegistered(session);
|
|
453
|
-
this._logDebug(`${import_kleur.default.blue(`Registered connection for room ${this.id}:`)} ${sessionId}`);
|
|
483
|
+
this._sessions.set(pluvWs.sessionId, pluvWs);
|
|
484
|
+
yield this._platform.persistance.addUser(this.id, pluvWs.sessionId, user != null ? user : {});
|
|
485
|
+
if (this._platform._registrationMode === "attached") {
|
|
486
|
+
const onClose = this._onClose(pluvWs).bind(this);
|
|
487
|
+
const onMessage = this._onMessage(pluvWs).bind(this);
|
|
488
|
+
pluvWs.addEventListener("close", onClose);
|
|
489
|
+
pluvWs.addEventListener("error", onClose);
|
|
490
|
+
pluvWs.addEventListener("message", onMessage);
|
|
491
|
+
}
|
|
492
|
+
yield this._emitRegistered(pluvWs);
|
|
493
|
+
this._logDebug(`${import_kleur.default.blue(`Registered connection for room ${this.id}:`)} ${pluvWs.sessionId}`);
|
|
454
494
|
const size = this.getSize();
|
|
455
495
|
this._logDebug(`${import_kleur.default.blue(`Room ${this.id} size:`)} ${size}`);
|
|
456
496
|
});
|
|
457
497
|
}
|
|
458
498
|
_broadcast(params) {
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
(
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
499
|
+
return __async(this, null, function* () {
|
|
500
|
+
var _a, _b, _c;
|
|
501
|
+
const { message, senderId } = params;
|
|
502
|
+
const sender = senderId ? (_a = this._sessions.get(senderId)) != null ? _a : null : null;
|
|
503
|
+
const session = (_b = yield sender == null ? void 0 : sender.getSession()) != null ? _b : null;
|
|
504
|
+
const user = (_c = session == null ? void 0 : session.user) != null ? _c : null;
|
|
505
|
+
this._platform.pubSub.publish(this.id, __spreadValues({
|
|
506
|
+
connectionId: senderId != null ? senderId : null,
|
|
507
|
+
room: this.id,
|
|
508
|
+
user
|
|
509
|
+
}, message));
|
|
468
510
|
});
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
this._broadcast({
|
|
479
|
-
message: {
|
|
480
|
-
type: "$EXIT",
|
|
481
|
-
data: { sessionId: quitter.id }
|
|
482
|
-
},
|
|
483
|
-
senderId: quitter.id
|
|
511
|
+
}
|
|
512
|
+
_emitQuitters() {
|
|
513
|
+
return __async(this, null, function* () {
|
|
514
|
+
const currentTime = (/* @__PURE__ */ new Date()).getTime();
|
|
515
|
+
const quitters = Array.from(this._sessions.values()).filter(
|
|
516
|
+
(pluvWs) => pluvWs.state.quit || currentTime - pluvWs.state.timers.ping > PING_TIMEOUT_MS
|
|
517
|
+
);
|
|
518
|
+
quitters.forEach((pluvWs) => {
|
|
519
|
+
this._sessions.delete(pluvWs.sessionId);
|
|
484
520
|
});
|
|
521
|
+
const promises = quitters.map((quitter) => __async(this, null, function* () {
|
|
522
|
+
yield this._broadcast({
|
|
523
|
+
message: {
|
|
524
|
+
type: "$EXIT",
|
|
525
|
+
data: { sessionId: quitter.sessionId }
|
|
526
|
+
},
|
|
527
|
+
senderId: quitter.sessionId
|
|
528
|
+
});
|
|
529
|
+
}));
|
|
530
|
+
yield Promise.all(promises);
|
|
485
531
|
});
|
|
486
532
|
}
|
|
487
|
-
_emitRegistered(
|
|
488
|
-
this
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
},
|
|
493
|
-
|
|
494
|
-
);
|
|
533
|
+
_emitRegistered(pluvWs) {
|
|
534
|
+
return __async(this, null, function* () {
|
|
535
|
+
const session = yield pluvWs.getSession();
|
|
536
|
+
const sessionId = session.id;
|
|
537
|
+
const user = session.user;
|
|
538
|
+
yield this._sendSelfMessage({ type: "$REGISTERED", data: { sessionId } }, { sessionId, user });
|
|
539
|
+
});
|
|
495
540
|
}
|
|
496
|
-
|
|
497
|
-
if (
|
|
498
|
-
|
|
541
|
+
_ensureDetached() {
|
|
542
|
+
if (this._platform._registrationMode === "detached") return;
|
|
543
|
+
throw new Error("Platform must use detached mode");
|
|
544
|
+
}
|
|
545
|
+
_getAbstractWs(webSocket) {
|
|
546
|
+
var _a, _b;
|
|
547
|
+
if (webSocket instanceof AbstractWebSocket) return webSocket;
|
|
548
|
+
const sessionId = this._platform.getSessionId(webSocket);
|
|
549
|
+
if (typeof sessionId === "string") {
|
|
550
|
+
const session = (_a = this._sessions.get(sessionId)) != null ? _a : null;
|
|
551
|
+
if (session) return session;
|
|
499
552
|
}
|
|
500
|
-
|
|
553
|
+
const sessions = Array.from(this._sessions.values());
|
|
554
|
+
return (_b = sessions.find((pluvWs) => pluvWs.webSocket === webSocket)) != null ? _b : null;
|
|
501
555
|
}
|
|
502
|
-
|
|
556
|
+
_getSession(webSocket) {
|
|
557
|
+
return __async(this, null, function* () {
|
|
558
|
+
const pluvWs = this._getAbstractWs(webSocket);
|
|
559
|
+
if (!pluvWs) throw new Error("Session could not be found");
|
|
560
|
+
return yield pluvWs.getSession();
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
_getAuthorizedUser(token) {
|
|
503
564
|
return __async(this, null, function* () {
|
|
504
565
|
var _a;
|
|
505
|
-
const ioAuthorize = this._getIOAuthorize(
|
|
566
|
+
const ioAuthorize = this._getIOAuthorize();
|
|
506
567
|
if (!ioAuthorize) return null;
|
|
507
568
|
if (!token) return null;
|
|
508
569
|
const payload = yield authorize({
|
|
@@ -528,6 +589,12 @@ var IORoom = class {
|
|
|
528
589
|
}
|
|
529
590
|
});
|
|
530
591
|
}
|
|
592
|
+
_getIOAuthorize() {
|
|
593
|
+
if (typeof this._authorize === "function") {
|
|
594
|
+
return this._authorize(this._context);
|
|
595
|
+
}
|
|
596
|
+
return this._authorize;
|
|
597
|
+
}
|
|
531
598
|
_getProcedure(message) {
|
|
532
599
|
var _a;
|
|
533
600
|
return (_a = this._router._events[message.type]) != null ? _a : null;
|
|
@@ -537,6 +604,14 @@ var IORoom = class {
|
|
|
537
604
|
if (!procedure) return message.data;
|
|
538
605
|
return procedure.config.input ? procedure.config.input.parse(message.data) : message.data;
|
|
539
606
|
}
|
|
607
|
+
_getSessions() {
|
|
608
|
+
return __async(this, null, function* () {
|
|
609
|
+
const promises = Array.from(this._sessions.values()).map((pluvWs) => __async(this, null, function* () {
|
|
610
|
+
return yield pluvWs.getSession();
|
|
611
|
+
}));
|
|
612
|
+
return yield Promise.all(promises);
|
|
613
|
+
});
|
|
614
|
+
}
|
|
540
615
|
_initialize() {
|
|
541
616
|
return __async(this, null, function* () {
|
|
542
617
|
this._logDebug(`${import_kleur.default.blue(`Initializing room ${this.id}:`)}`);
|
|
@@ -544,14 +619,15 @@ var IORoom = class {
|
|
|
544
619
|
yield this._uninitialize();
|
|
545
620
|
this._uninitialize = null;
|
|
546
621
|
}
|
|
547
|
-
const pubSubId = yield this._platform.pubSub.subscribe(
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
622
|
+
const pubSubId = yield this._platform.pubSub.subscribe(
|
|
623
|
+
this.id,
|
|
624
|
+
(_a) => __async(this, null, function* () {
|
|
625
|
+
var _b = _a, { options = {} } = _b, message = __objRest(_b, ["options"]);
|
|
626
|
+
const sessionId = message.connectionId;
|
|
627
|
+
const user = message.user;
|
|
628
|
+
yield this._sendMessage(message, { sessionId, user }, options);
|
|
629
|
+
})
|
|
630
|
+
);
|
|
555
631
|
this._uninitialize = () => __async(this, null, function* () {
|
|
556
632
|
this._platform.pubSub.unsubscribe(pubSubId);
|
|
557
633
|
const encodedState = this._doc.getEncodedState();
|
|
@@ -568,43 +644,48 @@ var IORoom = class {
|
|
|
568
644
|
_logDebug(...data) {
|
|
569
645
|
this._debug && console.log(...data);
|
|
570
646
|
}
|
|
571
|
-
_onClose(
|
|
647
|
+
_onClose(webSocket) {
|
|
572
648
|
return () => {
|
|
573
649
|
if (!this._uninitialize) return;
|
|
574
|
-
|
|
575
|
-
this._logDebug(`${import_kleur.default.blue(`
|
|
576
|
-
this._sessions.delete(
|
|
577
|
-
this._platform.persistance.deleteUser(this.id,
|
|
650
|
+
webSocket.state.quit = true;
|
|
651
|
+
this._logDebug(`${import_kleur.default.blue(`Unregistering connection for room ${this.id}:`)} ${webSocket.sessionId}`);
|
|
652
|
+
this._sessions.delete(webSocket.sessionId);
|
|
653
|
+
this._platform.persistance.deleteUser(this.id, webSocket.sessionId).finally(() => __async(this, null, function* () {
|
|
578
654
|
var _a;
|
|
579
|
-
this._broadcast({
|
|
655
|
+
yield this._broadcast({
|
|
580
656
|
message: {
|
|
581
657
|
type: "$EXIT",
|
|
582
|
-
data: { sessionId:
|
|
658
|
+
data: { sessionId: webSocket.sessionId }
|
|
583
659
|
},
|
|
584
|
-
senderId:
|
|
660
|
+
senderId: webSocket.sessionId
|
|
585
661
|
});
|
|
586
|
-
callback == null ? void 0 : callback();
|
|
587
662
|
const size = this.getSize();
|
|
588
|
-
this._logDebug(`${import_kleur.default.blue(`Unregistered connection for room ${this.id}:`)} ${
|
|
663
|
+
this._logDebug(`${import_kleur.default.blue(`Unregistered connection for room ${this.id}:`)} ${webSocket.sessionId}`);
|
|
589
664
|
this._logDebug(`${import_kleur.default.blue(`Room ${this.id} size:`)} ${size}`);
|
|
590
665
|
if (size) return;
|
|
591
666
|
(_a = this._uninitialize) == null ? void 0 : _a.call(this);
|
|
592
|
-
});
|
|
667
|
+
}));
|
|
593
668
|
};
|
|
594
669
|
}
|
|
595
|
-
_onMessage(
|
|
596
|
-
return (event) => {
|
|
670
|
+
_onMessage(webSocket) {
|
|
671
|
+
return (event) => __async(this, null, function* () {
|
|
597
672
|
var _a, _b, _c, _d, _e, _f;
|
|
673
|
+
const pluvWs = this._getAbstractWs(webSocket);
|
|
674
|
+
if (!pluvWs) throw new Error("Could not get session");
|
|
675
|
+
const [session, sessions] = yield Promise.all([
|
|
676
|
+
this._getSession(pluvWs),
|
|
677
|
+
this._getSessions()
|
|
678
|
+
]);
|
|
598
679
|
const baseContext = {
|
|
599
680
|
context: this._context,
|
|
600
681
|
doc: this._doc,
|
|
601
682
|
room: this.id,
|
|
602
683
|
session,
|
|
603
|
-
sessions
|
|
684
|
+
sessions
|
|
604
685
|
};
|
|
605
686
|
if (!this._uninitialize) return;
|
|
606
|
-
if (
|
|
607
|
-
|
|
687
|
+
if (pluvWs.state.quit) {
|
|
688
|
+
pluvWs.close(1011, "WebSocket broken.");
|
|
608
689
|
return;
|
|
609
690
|
}
|
|
610
691
|
const message = this._parseMessage(event);
|
|
@@ -615,47 +696,52 @@ var IORoom = class {
|
|
|
615
696
|
try {
|
|
616
697
|
inputs = this._getProcedureInputs(message);
|
|
617
698
|
} catch (error) {
|
|
618
|
-
|
|
699
|
+
pluvWs.handleError({
|
|
619
700
|
error,
|
|
620
701
|
message: "Invalid input",
|
|
702
|
+
room: this.id,
|
|
621
703
|
session
|
|
622
704
|
});
|
|
623
705
|
return;
|
|
624
706
|
}
|
|
625
|
-
const extendedContext = __spreadProps(__spreadValues({}, baseContext), {
|
|
626
|
-
context: __spreadValues(__spreadValues({}, this._context), platformEventContext)
|
|
627
|
-
});
|
|
707
|
+
const extendedContext = __spreadProps(__spreadValues({}, baseContext), { context: __spreadValues({}, this._context) });
|
|
628
708
|
Promise.all([
|
|
629
709
|
(_b = (_a = procedure.config).broadcast) == null ? void 0 : _b.call(_a, inputs, extendedContext),
|
|
630
710
|
(_d = (_c = procedure.config).self) == null ? void 0 : _d.call(_c, inputs, extendedContext),
|
|
631
711
|
(_f = (_e = procedure.config).sync) == null ? void 0 : _f.call(_e, inputs, baseContext)
|
|
632
|
-
]).then(([broadcast, self, sync])
|
|
712
|
+
]).then((_0) => __async(this, [_0], function* ([broadcast, self, sync]) {
|
|
713
|
+
const sessionId = session.id;
|
|
714
|
+
const user = session.user;
|
|
633
715
|
if (broadcast) {
|
|
634
716
|
Object.entries(broadcast).forEach(([type, data]) => {
|
|
635
717
|
this._broadcast({
|
|
636
718
|
message: { data, type },
|
|
637
|
-
senderId:
|
|
719
|
+
senderId: sessionId
|
|
638
720
|
});
|
|
639
721
|
});
|
|
640
722
|
}
|
|
641
723
|
if (self) {
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
724
|
+
yield Promise.all(
|
|
725
|
+
Object.entries(self).map((_02) => __async(this, [_02], function* ([type, data]) {
|
|
726
|
+
yield this._sendSelfMessage({ data, type }, { sessionId, user });
|
|
727
|
+
}))
|
|
728
|
+
);
|
|
645
729
|
}
|
|
646
730
|
if (sync) {
|
|
647
731
|
this._platform.pubSub.publish(this.id, __spreadValues({
|
|
648
732
|
connectionId: session.id,
|
|
649
733
|
options: { type: "sync" },
|
|
650
734
|
room: this.id,
|
|
651
|
-
user
|
|
735
|
+
user
|
|
652
736
|
}, message));
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
737
|
+
yield Promise.all(
|
|
738
|
+
Object.entries(sync).map((_02) => __async(this, [_02], function* ([type, data]) {
|
|
739
|
+
yield this._sendSelfMessage({ data, type }, { sessionId, user });
|
|
740
|
+
}))
|
|
741
|
+
);
|
|
656
742
|
}
|
|
657
|
-
});
|
|
658
|
-
};
|
|
743
|
+
}));
|
|
744
|
+
});
|
|
659
745
|
}
|
|
660
746
|
_parseMessage(message) {
|
|
661
747
|
try {
|
|
@@ -668,80 +754,93 @@ var IORoom = class {
|
|
|
668
754
|
return null;
|
|
669
755
|
}
|
|
670
756
|
}
|
|
671
|
-
_sendMessage(
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
757
|
+
_sendMessage(_0, _1) {
|
|
758
|
+
return __async(this, arguments, function* (message, sender, options = {}) {
|
|
759
|
+
switch (options.type) {
|
|
760
|
+
case "self": {
|
|
761
|
+
yield this._sendSelfMessage(message, sender);
|
|
762
|
+
return;
|
|
763
|
+
}
|
|
764
|
+
case "sync": {
|
|
765
|
+
yield this._sendSyncMessage(message, sender);
|
|
766
|
+
return;
|
|
767
|
+
}
|
|
768
|
+
case "broadcast":
|
|
769
|
+
default: {
|
|
770
|
+
const sessionIds = options.sessionIds;
|
|
771
|
+
yield this._sendBroadcastMessage(message, sender, sessionIds);
|
|
772
|
+
}
|
|
685
773
|
}
|
|
686
|
-
}
|
|
774
|
+
});
|
|
687
775
|
}
|
|
688
776
|
_sendBroadcastMessage(message, sender, sessionIds) {
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
const
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
777
|
+
return __async(this, null, function* () {
|
|
778
|
+
var _a, _b;
|
|
779
|
+
const { data, type } = message;
|
|
780
|
+
const connectionId = (_a = sender == null ? void 0 : sender.sessionId) != null ? _a : null;
|
|
781
|
+
const room = this.id;
|
|
782
|
+
const webSockets = (_b = sessionIds == null ? void 0 : sessionIds.reduce((dict, id) => {
|
|
783
|
+
const pluvWs = this._sessions.get(id);
|
|
784
|
+
return pluvWs ? dict.set(id, pluvWs) : dict;
|
|
785
|
+
}, /* @__PURE__ */ new Map())) != null ? _b : this._sessions;
|
|
786
|
+
const promises = Array.from(webSockets.values()).map((pluvWs) => __async(this, null, function* () {
|
|
787
|
+
var _a2;
|
|
788
|
+
const session = yield pluvWs.getSession();
|
|
789
|
+
const user = (_a2 = session.user) != null ? _a2 : null;
|
|
790
|
+
pluvWs.sendMessage({ connectionId, data, room, type, user });
|
|
791
|
+
}));
|
|
792
|
+
yield Promise.all(promises);
|
|
793
|
+
});
|
|
794
|
+
}
|
|
795
|
+
_sendSelfMessage(message, sender) {
|
|
796
|
+
return __async(this, null, function* () {
|
|
797
|
+
var _a, _b;
|
|
798
|
+
const senderId = (_a = sender == null ? void 0 : sender.sessionId) != null ? _a : null;
|
|
799
|
+
if (typeof senderId !== "string") return;
|
|
800
|
+
const pluvWs = this._sessions.get(senderId);
|
|
801
|
+
if (!pluvWs) return;
|
|
802
|
+
if (message.type === "$PONG") yield this._emitQuitters();
|
|
803
|
+
const session = yield pluvWs.getSession();
|
|
804
|
+
const user = (_b = session.user) != null ? _b : null;
|
|
805
|
+
pluvWs.sendMessage(__spreadValues({
|
|
697
806
|
connectionId: senderId,
|
|
698
807
|
room: this.id,
|
|
699
|
-
user
|
|
808
|
+
user
|
|
700
809
|
}, message));
|
|
701
810
|
});
|
|
702
811
|
}
|
|
703
|
-
_sendSelfMessage(message, sender) {
|
|
704
|
-
const senderId = sender == null ? void 0 : sender.id;
|
|
705
|
-
if (!senderId) return;
|
|
706
|
-
const session = this._sessions.get(senderId);
|
|
707
|
-
if (!session) return;
|
|
708
|
-
session.webSocket.sendMessage(__spreadValues({
|
|
709
|
-
connectionId: sender.id,
|
|
710
|
-
room: this.id,
|
|
711
|
-
user: sender.user
|
|
712
|
-
}, message));
|
|
713
|
-
}
|
|
714
812
|
_sendSyncMessage(message, sender) {
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
813
|
+
return __async(this, null, function* () {
|
|
814
|
+
var _a;
|
|
815
|
+
if (!sender) return;
|
|
816
|
+
const context = {
|
|
817
|
+
context: this._context,
|
|
818
|
+
doc: this._doc,
|
|
819
|
+
room: this.id,
|
|
820
|
+
session: null,
|
|
821
|
+
sessions: yield this._getSessions()
|
|
822
|
+
};
|
|
823
|
+
const resolver = (_a = this._getProcedure(message)) == null ? void 0 : _a.config.sync;
|
|
824
|
+
if (!resolver) return;
|
|
825
|
+
let inputs;
|
|
826
|
+
try {
|
|
827
|
+
inputs = this._getProcedureInputs(message);
|
|
828
|
+
} catch (e) {
|
|
829
|
+
return;
|
|
830
|
+
}
|
|
831
|
+
Promise.resolve(resolver(inputs, context)).then((output) => {
|
|
832
|
+
if (!output) return;
|
|
833
|
+
Object.keys(output).forEach((type) => {
|
|
834
|
+
var _a2, _b;
|
|
835
|
+
const data = (_a2 = output[type]) != null ? _a2 : {};
|
|
836
|
+
this._platform.pubSub.publish(this.id, {
|
|
837
|
+
connectionId: sender.sessionId,
|
|
838
|
+
data,
|
|
839
|
+
options: { type: "self" },
|
|
840
|
+
room: this.id,
|
|
841
|
+
type,
|
|
842
|
+
user: (_b = sender.user) != null ? _b : null
|
|
843
|
+
});
|
|
745
844
|
});
|
|
746
845
|
});
|
|
747
846
|
});
|
|
@@ -749,7 +848,7 @@ var IORoom = class {
|
|
|
749
848
|
};
|
|
750
849
|
|
|
751
850
|
// src/version.generated.ts
|
|
752
|
-
var version = "0.
|
|
851
|
+
var version = "0.21.1";
|
|
753
852
|
|
|
754
853
|
// src/PluvServer.ts
|
|
755
854
|
var PluvServer = class {
|
|
@@ -782,6 +881,9 @@ var PluvServer = class {
|
|
|
782
881
|
get _events() {
|
|
783
882
|
return this._router._events;
|
|
784
883
|
}
|
|
884
|
+
get _registrationMode() {
|
|
885
|
+
return this._platform._registrationMode;
|
|
886
|
+
}
|
|
785
887
|
createToken(params) {
|
|
786
888
|
return __async(this, null, function* () {
|
|
787
889
|
if (!this._authorize) {
|
|
@@ -795,9 +897,9 @@ var PluvServer = class {
|
|
|
795
897
|
}).encode(params);
|
|
796
898
|
});
|
|
797
899
|
}
|
|
798
|
-
getRoom(room, options) {
|
|
799
|
-
var
|
|
800
|
-
const _a = options, { debug } =
|
|
900
|
+
getRoom(room, ...options) {
|
|
901
|
+
var _a, _c;
|
|
902
|
+
const _b = (_a = options[0]) != null ? _a : {}, { debug } = _b, platformRoomContext = __objRest(_b, ["debug"]);
|
|
801
903
|
this._purgeEmptyRooms();
|
|
802
904
|
if (!/^[a-z0-9]+[a-z0-9\-_]+[a-z0-9]+$/i.test(room)) {
|
|
803
905
|
throw new Error("Unsupported room name");
|
|
@@ -807,24 +909,25 @@ var PluvServer = class {
|
|
|
807
909
|
if (oldRoom) return oldRoom;
|
|
808
910
|
const roomContext = __spreadValues(__spreadValues({}, this._context), platformRoomContext);
|
|
809
911
|
const newRoom = new IORoom(room, {
|
|
810
|
-
authorize: (
|
|
912
|
+
authorize: (_c = this._authorize) != null ? _c : void 0,
|
|
811
913
|
context: roomContext,
|
|
812
914
|
crdt: this._crdt,
|
|
813
915
|
debug: debug != null ? debug : this._debug,
|
|
814
|
-
onDestroy: ({ encodedState, room: room2 })
|
|
916
|
+
onDestroy: (_0) => __async(this, [_0], function* ({ encodedState, room: room2 }) {
|
|
815
917
|
this._logDebug(`${import_kleur2.default.blue("Deleting empty room:")} ${room2}`);
|
|
816
918
|
const roomContext2 = __spreadValues({
|
|
817
919
|
room: room2,
|
|
818
920
|
encodedState
|
|
819
921
|
}, platformRoomContext);
|
|
820
922
|
this._rooms.delete(room2);
|
|
821
|
-
this._listeners.onRoomDeleted(roomContext2);
|
|
923
|
+
yield Promise.resolve(this._listeners.onRoomDeleted(roomContext2));
|
|
924
|
+
yield this._platform.persistance.deleteStorageState(room2);
|
|
822
925
|
if (this._debug) {
|
|
823
926
|
const rooms = Array.from(this._rooms.keys());
|
|
824
927
|
this._logDebug(`${import_kleur2.default.blue("Deleted room:")} ${room2}`);
|
|
825
928
|
this._logDebug(`${import_kleur2.default.blue("Rooms available:")} ${rooms.join(", ")}`);
|
|
826
929
|
}
|
|
827
|
-
},
|
|
930
|
+
}),
|
|
828
931
|
platform,
|
|
829
932
|
router: this._router
|
|
830
933
|
});
|
|
@@ -853,10 +956,16 @@ var PluvIO = class {
|
|
|
853
956
|
constructor(options) {
|
|
854
957
|
this._router = new PluvRouter({
|
|
855
958
|
$GET_OTHERS: this.procedure.sync((data, { room, session, sessions }) => {
|
|
856
|
-
const
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
959
|
+
const currentTime = (/* @__PURE__ */ new Date()).getTime();
|
|
960
|
+
const others = sessions.filter((wsSession) => {
|
|
961
|
+
if (wsSession.id === (session == null ? void 0 : session.id)) return false;
|
|
962
|
+
if (wsSession.quit) return false;
|
|
963
|
+
if (currentTime - wsSession.timers.ping > PING_TIMEOUT_MS) return false;
|
|
964
|
+
return true;
|
|
965
|
+
}).reduce(
|
|
966
|
+
(acc, { id, presence, user }) => __spreadProps(__spreadValues({}, acc), {
|
|
967
|
+
[id]: {
|
|
968
|
+
connectionId: id,
|
|
860
969
|
presence,
|
|
861
970
|
room,
|
|
862
971
|
user
|
|
@@ -904,8 +1013,9 @@ var PluvIO = class {
|
|
|
904
1013
|
$UPDATE_PRESENCE: this.procedure.broadcast((data, { session }) => {
|
|
905
1014
|
const presence = data == null ? void 0 : data.presence;
|
|
906
1015
|
if (!session) return {};
|
|
907
|
-
|
|
908
|
-
|
|
1016
|
+
const updated = Object.assign(/* @__PURE__ */ Object.create(null), session.presence, presence);
|
|
1017
|
+
session.webSocket.presence = updated;
|
|
1018
|
+
return { $PRESENCE_UPDATED: { presence: updated } };
|
|
909
1019
|
}),
|
|
910
1020
|
$UPDATE_STORAGE: this.procedure.broadcast((data, { context, doc, room }) => {
|
|
911
1021
|
var _a;
|
|
@@ -953,14 +1063,15 @@ var PluvIO = class {
|
|
|
953
1063
|
get _events() {
|
|
954
1064
|
return this._router._events;
|
|
955
1065
|
}
|
|
1066
|
+
get _registrationMode() {
|
|
1067
|
+
return this._platform._registrationMode;
|
|
1068
|
+
}
|
|
956
1069
|
get procedure() {
|
|
957
1070
|
return new PluvProcedure();
|
|
958
1071
|
}
|
|
959
1072
|
createToken(params) {
|
|
960
1073
|
return __async(this, null, function* () {
|
|
961
|
-
if (!this._authorize)
|
|
962
|
-
throw new Error("IO does not specify authorize during initialization.");
|
|
963
|
-
}
|
|
1074
|
+
if (!this._authorize) throw new Error("IO does not specify authorize during initialization.");
|
|
964
1075
|
const ioAuthorize = typeof this._authorize === "function" ? this._authorize(params) : this._authorize;
|
|
965
1076
|
const secret = ioAuthorize.secret;
|
|
966
1077
|
return yield authorize({
|