@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.mjs
CHANGED
|
@@ -175,15 +175,23 @@ var PubSub = class extends AbstractPubSub {
|
|
|
175
175
|
// src/AbstractPlatform.ts
|
|
176
176
|
var AbstractPlatform = class {
|
|
177
177
|
constructor(config = {}) {
|
|
178
|
-
|
|
178
|
+
this._initialized = false;
|
|
179
|
+
const { context, persistance, pubSub } = config;
|
|
180
|
+
context && (this._ioContext = context);
|
|
181
|
+
context && (this._roomContext = context);
|
|
179
182
|
this.persistance = persistance != null ? persistance : new Persistance();
|
|
180
183
|
this.pubSub = pubSub != null ? pubSub : new PubSub();
|
|
181
184
|
}
|
|
185
|
+
_initialize() {
|
|
186
|
+
if (this._initialized) throw new Error("Platform is already initialized");
|
|
187
|
+
this._initialized = true;
|
|
188
|
+
return this;
|
|
189
|
+
}
|
|
182
190
|
};
|
|
183
191
|
|
|
184
192
|
// src/AbstractWebSocket.ts
|
|
185
193
|
var AbstractWebSocket = class {
|
|
186
|
-
constructor(config) {
|
|
194
|
+
constructor(webSocket, config) {
|
|
187
195
|
/** The connection is not yet open. */
|
|
188
196
|
this.CONNECTING = 0;
|
|
189
197
|
/** The connection is open and ready to communicate. */
|
|
@@ -192,18 +200,36 @@ var AbstractWebSocket = class {
|
|
|
192
200
|
this.CLOSING = 2;
|
|
193
201
|
/** The connection is closed. */
|
|
194
202
|
this.CLOSED = 3;
|
|
195
|
-
|
|
203
|
+
this._user = null;
|
|
204
|
+
const { persistance, room } = config;
|
|
205
|
+
this.persistance = persistance;
|
|
196
206
|
this.room = room;
|
|
197
|
-
this.
|
|
207
|
+
this.webSocket = webSocket;
|
|
208
|
+
}
|
|
209
|
+
getSession() {
|
|
210
|
+
return __async(this, null, function* () {
|
|
211
|
+
var _a;
|
|
212
|
+
const sessionId = this.sessionId;
|
|
213
|
+
const state = this.state;
|
|
214
|
+
const room = state.room;
|
|
215
|
+
const user = (_a = this._user) != null ? _a : yield this.persistance.getUser(room, sessionId);
|
|
216
|
+
this._user = user;
|
|
217
|
+
return __spreadProps(__spreadValues({}, state), {
|
|
218
|
+
id: sessionId,
|
|
219
|
+
user,
|
|
220
|
+
webSocket: this
|
|
221
|
+
});
|
|
222
|
+
});
|
|
198
223
|
}
|
|
199
224
|
handleError(params) {
|
|
200
225
|
var _a, _b, _c;
|
|
201
|
-
const { error, message
|
|
226
|
+
const { error, message: _message, room, session } = params;
|
|
227
|
+
const message = error instanceof Error ? error.message : "Unexpected error";
|
|
202
228
|
const stack = error instanceof Error ? (_a = error.stack) != null ? _a : null : null;
|
|
203
229
|
return this.sendMessage({
|
|
204
230
|
connectionId: (_b = session == null ? void 0 : session.id) != null ? _b : null,
|
|
205
231
|
data: { message, stack },
|
|
206
|
-
room
|
|
232
|
+
room,
|
|
207
233
|
type: "$ERROR",
|
|
208
234
|
user: (_c = session == null ? void 0 : session.user) != null ? _c : null
|
|
209
235
|
});
|
|
@@ -321,8 +347,10 @@ var authorize = (params) => {
|
|
|
321
347
|
return { decode, encode };
|
|
322
348
|
};
|
|
323
349
|
|
|
324
|
-
// src/
|
|
350
|
+
// src/constants.ts
|
|
325
351
|
var PING_TIMEOUT_MS = 3e4;
|
|
352
|
+
|
|
353
|
+
// src/IORoom.ts
|
|
326
354
|
var IORoom = class {
|
|
327
355
|
constructor(id, config) {
|
|
328
356
|
this._sessions = /* @__PURE__ */ new Map();
|
|
@@ -334,12 +362,21 @@ var IORoom = class {
|
|
|
334
362
|
this._docFactory = crdt.doc(() => ({}));
|
|
335
363
|
this._doc = this._docFactory.getEmpty();
|
|
336
364
|
this._router = router;
|
|
337
|
-
this._platform = platform;
|
|
365
|
+
this._platform = platform.initialize({ context });
|
|
338
366
|
this.id = id;
|
|
339
367
|
this._listeners = {
|
|
340
368
|
onDestroy: (event) => onDestroy == null ? void 0 : onDestroy(event)
|
|
341
369
|
};
|
|
342
370
|
if (authorize2) this._authorize = authorize2;
|
|
371
|
+
const webSockets = this._platform.getWebSockets();
|
|
372
|
+
if (!webSockets.length) return;
|
|
373
|
+
webSockets.forEach((webSocket) => {
|
|
374
|
+
const deserialized = this._platform.getSerializedState(webSocket);
|
|
375
|
+
const sessionId = this._platform.getSessionId(webSocket);
|
|
376
|
+
if (!deserialized) return;
|
|
377
|
+
if (typeof sessionId !== "string") return;
|
|
378
|
+
this._sessions.set(sessionId, this._platform.convertWebSocket(webSocket, { room: this.id }));
|
|
379
|
+
});
|
|
343
380
|
}
|
|
344
381
|
get _events() {
|
|
345
382
|
return this._router._events;
|
|
@@ -357,111 +394,135 @@ var IORoom = class {
|
|
|
357
394
|
}
|
|
358
395
|
getSize() {
|
|
359
396
|
const currentTime = (/* @__PURE__ */ new Date()).getTime();
|
|
360
|
-
return Array.from(this._sessions.values()).reduce((count,
|
|
361
|
-
|
|
362
|
-
|
|
397
|
+
return Array.from(this._sessions.values()).reduce((count, pluvWs) => {
|
|
398
|
+
var _a;
|
|
399
|
+
if (pluvWs.state.quit) return count;
|
|
400
|
+
const pingTime = (_a = this._platform.getLastPing(pluvWs)) != null ? _a : pluvWs.state.timers.ping;
|
|
401
|
+
return currentTime - pingTime > PING_TIMEOUT_MS ? count : count + 1;
|
|
363
402
|
}, 0);
|
|
364
403
|
}
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
404
|
+
onClose(webSocket) {
|
|
405
|
+
this._ensureDetached();
|
|
406
|
+
const wsSession = this._getAbstractWs(webSocket);
|
|
407
|
+
if (!wsSession) return () => void 0;
|
|
408
|
+
return this._onClose(wsSession);
|
|
409
|
+
}
|
|
410
|
+
onError(webSocket) {
|
|
411
|
+
this._ensureDetached();
|
|
412
|
+
const wsSession = this._getAbstractWs(webSocket);
|
|
413
|
+
if (!wsSession) return () => void 0;
|
|
414
|
+
return this._onClose(wsSession);
|
|
415
|
+
}
|
|
416
|
+
onMessage(webSocket) {
|
|
417
|
+
this._ensureDetached();
|
|
418
|
+
const wsSession = this._getAbstractWs(webSocket);
|
|
419
|
+
if (!wsSession) return () => void 0;
|
|
420
|
+
return this._onMessage(wsSession);
|
|
421
|
+
}
|
|
422
|
+
register(_0) {
|
|
423
|
+
return __async(this, arguments, function* (webSocket, options = {}) {
|
|
424
|
+
const { token } = options;
|
|
370
425
|
if (!this._uninitialize) yield this._initialize();
|
|
371
|
-
const user = yield this._getAuthorizedUser(token
|
|
372
|
-
const
|
|
373
|
-
const pluvWs = this._platform.convertWebSocket(webSocket, {
|
|
374
|
-
room: this.id,
|
|
375
|
-
sessionId,
|
|
376
|
-
userId: (_b = user == null ? void 0 : user.id) != null ? _b : null
|
|
377
|
-
});
|
|
378
|
-
this._logDebug(`${colors.blue(`Registering connection for room ${this.id}:`)} ${sessionId}`);
|
|
379
|
-
const uninitializeWs = yield pluvWs.initialize();
|
|
380
|
-
const ioAuthorize = this._getIOAuthorize(options);
|
|
426
|
+
const user = yield this._getAuthorizedUser(token);
|
|
427
|
+
const ioAuthorize = this._getIOAuthorize();
|
|
381
428
|
const isUnauthorized = !!(ioAuthorize == null ? void 0 : ioAuthorize.required) && !user;
|
|
382
|
-
const isTokenInUse = !!user &&
|
|
383
|
-
var
|
|
384
|
-
return ((
|
|
385
|
-
});
|
|
429
|
+
const isTokenInUse = !!user && (yield this._getSessions().then((sessions) => sessions.some((session) => {
|
|
430
|
+
var _a;
|
|
431
|
+
return ((_a = session.user) == null ? void 0 : _a.id) === user.id;
|
|
432
|
+
})));
|
|
433
|
+
const pluvWs = yield this._platform.convertWebSocket(webSocket, { room: this.id });
|
|
434
|
+
this._logDebug(`${colors.blue(`Registering connection for room ${this.id}:`)} ${pluvWs.sessionId}`);
|
|
435
|
+
yield this._platform.acceptWebSocket(pluvWs);
|
|
386
436
|
if (isUnauthorized || isTokenInUse) {
|
|
387
|
-
this._logDebug(`${colors.blue("Authorization failed for connection:")} ${sessionId}`);
|
|
388
|
-
pluvWs.handleError({ error: new Error("Not authorized") });
|
|
437
|
+
this._logDebug(`${colors.blue("Authorization failed for connection:")} ${pluvWs.sessionId}`);
|
|
438
|
+
pluvWs.handleError({ error: new Error("Not authorized"), room: this.id });
|
|
389
439
|
pluvWs.close(3e3, "WebSocket unauthorized.");
|
|
390
440
|
return;
|
|
391
441
|
}
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
};
|
|
404
|
-
this._sessions.set(session.id, session);
|
|
405
|
-
yield this._platform.persistance.addUser(this.id, sessionId, user != null ? user : {});
|
|
406
|
-
const onClose = this._onClose(session, uninitializeWs).bind(this);
|
|
407
|
-
const onMessage = this._onMessage(session, platformEventContext).bind(this);
|
|
408
|
-
pluvWs.addEventListener("close", onClose);
|
|
409
|
-
pluvWs.addEventListener("error", onClose);
|
|
410
|
-
pluvWs.addEventListener("message", onMessage);
|
|
411
|
-
this._emitRegistered(session);
|
|
412
|
-
this._logDebug(`${colors.blue(`Registered connection for room ${this.id}:`)} ${sessionId}`);
|
|
442
|
+
this._sessions.set(pluvWs.sessionId, pluvWs);
|
|
443
|
+
yield this._platform.persistance.addUser(this.id, pluvWs.sessionId, user != null ? user : {});
|
|
444
|
+
if (this._platform._registrationMode === "attached") {
|
|
445
|
+
const onClose = this._onClose(pluvWs).bind(this);
|
|
446
|
+
const onMessage = this._onMessage(pluvWs).bind(this);
|
|
447
|
+
pluvWs.addEventListener("close", onClose);
|
|
448
|
+
pluvWs.addEventListener("error", onClose);
|
|
449
|
+
pluvWs.addEventListener("message", onMessage);
|
|
450
|
+
}
|
|
451
|
+
yield this._emitRegistered(pluvWs);
|
|
452
|
+
this._logDebug(`${colors.blue(`Registered connection for room ${this.id}:`)} ${pluvWs.sessionId}`);
|
|
413
453
|
const size = this.getSize();
|
|
414
454
|
this._logDebug(`${colors.blue(`Room ${this.id} size:`)} ${size}`);
|
|
415
455
|
});
|
|
416
456
|
}
|
|
417
457
|
_broadcast(params) {
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
(
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
458
|
+
return __async(this, null, function* () {
|
|
459
|
+
var _a, _b, _c;
|
|
460
|
+
const { message, senderId } = params;
|
|
461
|
+
const sender = senderId ? (_a = this._sessions.get(senderId)) != null ? _a : null : null;
|
|
462
|
+
const session = (_b = yield sender == null ? void 0 : sender.getSession()) != null ? _b : null;
|
|
463
|
+
const user = (_c = session == null ? void 0 : session.user) != null ? _c : null;
|
|
464
|
+
this._platform.pubSub.publish(this.id, __spreadValues({
|
|
465
|
+
connectionId: senderId != null ? senderId : null,
|
|
466
|
+
room: this.id,
|
|
467
|
+
user
|
|
468
|
+
}, message));
|
|
427
469
|
});
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
this._broadcast({
|
|
438
|
-
message: {
|
|
439
|
-
type: "$EXIT",
|
|
440
|
-
data: { sessionId: quitter.id }
|
|
441
|
-
},
|
|
442
|
-
senderId: quitter.id
|
|
470
|
+
}
|
|
471
|
+
_emitQuitters() {
|
|
472
|
+
return __async(this, null, function* () {
|
|
473
|
+
const currentTime = (/* @__PURE__ */ new Date()).getTime();
|
|
474
|
+
const quitters = Array.from(this._sessions.values()).filter(
|
|
475
|
+
(pluvWs) => pluvWs.state.quit || currentTime - pluvWs.state.timers.ping > PING_TIMEOUT_MS
|
|
476
|
+
);
|
|
477
|
+
quitters.forEach((pluvWs) => {
|
|
478
|
+
this._sessions.delete(pluvWs.sessionId);
|
|
443
479
|
});
|
|
480
|
+
const promises = quitters.map((quitter) => __async(this, null, function* () {
|
|
481
|
+
yield this._broadcast({
|
|
482
|
+
message: {
|
|
483
|
+
type: "$EXIT",
|
|
484
|
+
data: { sessionId: quitter.sessionId }
|
|
485
|
+
},
|
|
486
|
+
senderId: quitter.sessionId
|
|
487
|
+
});
|
|
488
|
+
}));
|
|
489
|
+
yield Promise.all(promises);
|
|
444
490
|
});
|
|
445
491
|
}
|
|
446
|
-
_emitRegistered(
|
|
447
|
-
this
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
},
|
|
452
|
-
|
|
453
|
-
);
|
|
492
|
+
_emitRegistered(pluvWs) {
|
|
493
|
+
return __async(this, null, function* () {
|
|
494
|
+
const session = yield pluvWs.getSession();
|
|
495
|
+
const sessionId = session.id;
|
|
496
|
+
const user = session.user;
|
|
497
|
+
yield this._sendSelfMessage({ type: "$REGISTERED", data: { sessionId } }, { sessionId, user });
|
|
498
|
+
});
|
|
454
499
|
}
|
|
455
|
-
|
|
456
|
-
if (
|
|
457
|
-
|
|
500
|
+
_ensureDetached() {
|
|
501
|
+
if (this._platform._registrationMode === "detached") return;
|
|
502
|
+
throw new Error("Platform must use detached mode");
|
|
503
|
+
}
|
|
504
|
+
_getAbstractWs(webSocket) {
|
|
505
|
+
var _a, _b;
|
|
506
|
+
if (webSocket instanceof AbstractWebSocket) return webSocket;
|
|
507
|
+
const sessionId = this._platform.getSessionId(webSocket);
|
|
508
|
+
if (typeof sessionId === "string") {
|
|
509
|
+
const session = (_a = this._sessions.get(sessionId)) != null ? _a : null;
|
|
510
|
+
if (session) return session;
|
|
458
511
|
}
|
|
459
|
-
|
|
512
|
+
const sessions = Array.from(this._sessions.values());
|
|
513
|
+
return (_b = sessions.find((pluvWs) => pluvWs.webSocket === webSocket)) != null ? _b : null;
|
|
460
514
|
}
|
|
461
|
-
|
|
515
|
+
_getSession(webSocket) {
|
|
516
|
+
return __async(this, null, function* () {
|
|
517
|
+
const pluvWs = this._getAbstractWs(webSocket);
|
|
518
|
+
if (!pluvWs) throw new Error("Session could not be found");
|
|
519
|
+
return yield pluvWs.getSession();
|
|
520
|
+
});
|
|
521
|
+
}
|
|
522
|
+
_getAuthorizedUser(token) {
|
|
462
523
|
return __async(this, null, function* () {
|
|
463
524
|
var _a;
|
|
464
|
-
const ioAuthorize = this._getIOAuthorize(
|
|
525
|
+
const ioAuthorize = this._getIOAuthorize();
|
|
465
526
|
if (!ioAuthorize) return null;
|
|
466
527
|
if (!token) return null;
|
|
467
528
|
const payload = yield authorize({
|
|
@@ -487,6 +548,12 @@ var IORoom = class {
|
|
|
487
548
|
}
|
|
488
549
|
});
|
|
489
550
|
}
|
|
551
|
+
_getIOAuthorize() {
|
|
552
|
+
if (typeof this._authorize === "function") {
|
|
553
|
+
return this._authorize(this._context);
|
|
554
|
+
}
|
|
555
|
+
return this._authorize;
|
|
556
|
+
}
|
|
490
557
|
_getProcedure(message) {
|
|
491
558
|
var _a;
|
|
492
559
|
return (_a = this._router._events[message.type]) != null ? _a : null;
|
|
@@ -496,6 +563,14 @@ var IORoom = class {
|
|
|
496
563
|
if (!procedure) return message.data;
|
|
497
564
|
return procedure.config.input ? procedure.config.input.parse(message.data) : message.data;
|
|
498
565
|
}
|
|
566
|
+
_getSessions() {
|
|
567
|
+
return __async(this, null, function* () {
|
|
568
|
+
const promises = Array.from(this._sessions.values()).map((pluvWs) => __async(this, null, function* () {
|
|
569
|
+
return yield pluvWs.getSession();
|
|
570
|
+
}));
|
|
571
|
+
return yield Promise.all(promises);
|
|
572
|
+
});
|
|
573
|
+
}
|
|
499
574
|
_initialize() {
|
|
500
575
|
return __async(this, null, function* () {
|
|
501
576
|
this._logDebug(`${colors.blue(`Initializing room ${this.id}:`)}`);
|
|
@@ -503,14 +578,15 @@ var IORoom = class {
|
|
|
503
578
|
yield this._uninitialize();
|
|
504
579
|
this._uninitialize = null;
|
|
505
580
|
}
|
|
506
|
-
const pubSubId = yield this._platform.pubSub.subscribe(
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
581
|
+
const pubSubId = yield this._platform.pubSub.subscribe(
|
|
582
|
+
this.id,
|
|
583
|
+
(_a) => __async(this, null, function* () {
|
|
584
|
+
var _b = _a, { options = {} } = _b, message = __objRest(_b, ["options"]);
|
|
585
|
+
const sessionId = message.connectionId;
|
|
586
|
+
const user = message.user;
|
|
587
|
+
yield this._sendMessage(message, { sessionId, user }, options);
|
|
588
|
+
})
|
|
589
|
+
);
|
|
514
590
|
this._uninitialize = () => __async(this, null, function* () {
|
|
515
591
|
this._platform.pubSub.unsubscribe(pubSubId);
|
|
516
592
|
const encodedState = this._doc.getEncodedState();
|
|
@@ -527,43 +603,48 @@ var IORoom = class {
|
|
|
527
603
|
_logDebug(...data) {
|
|
528
604
|
this._debug && console.log(...data);
|
|
529
605
|
}
|
|
530
|
-
_onClose(
|
|
606
|
+
_onClose(webSocket) {
|
|
531
607
|
return () => {
|
|
532
608
|
if (!this._uninitialize) return;
|
|
533
|
-
|
|
534
|
-
this._logDebug(`${colors.blue(`
|
|
535
|
-
this._sessions.delete(
|
|
536
|
-
this._platform.persistance.deleteUser(this.id,
|
|
609
|
+
webSocket.state.quit = true;
|
|
610
|
+
this._logDebug(`${colors.blue(`Unregistering connection for room ${this.id}:`)} ${webSocket.sessionId}`);
|
|
611
|
+
this._sessions.delete(webSocket.sessionId);
|
|
612
|
+
this._platform.persistance.deleteUser(this.id, webSocket.sessionId).finally(() => __async(this, null, function* () {
|
|
537
613
|
var _a;
|
|
538
|
-
this._broadcast({
|
|
614
|
+
yield this._broadcast({
|
|
539
615
|
message: {
|
|
540
616
|
type: "$EXIT",
|
|
541
|
-
data: { sessionId:
|
|
617
|
+
data: { sessionId: webSocket.sessionId }
|
|
542
618
|
},
|
|
543
|
-
senderId:
|
|
619
|
+
senderId: webSocket.sessionId
|
|
544
620
|
});
|
|
545
|
-
callback == null ? void 0 : callback();
|
|
546
621
|
const size = this.getSize();
|
|
547
|
-
this._logDebug(`${colors.blue(`Unregistered connection for room ${this.id}:`)} ${
|
|
622
|
+
this._logDebug(`${colors.blue(`Unregistered connection for room ${this.id}:`)} ${webSocket.sessionId}`);
|
|
548
623
|
this._logDebug(`${colors.blue(`Room ${this.id} size:`)} ${size}`);
|
|
549
624
|
if (size) return;
|
|
550
625
|
(_a = this._uninitialize) == null ? void 0 : _a.call(this);
|
|
551
|
-
});
|
|
626
|
+
}));
|
|
552
627
|
};
|
|
553
628
|
}
|
|
554
|
-
_onMessage(
|
|
555
|
-
return (event) => {
|
|
629
|
+
_onMessage(webSocket) {
|
|
630
|
+
return (event) => __async(this, null, function* () {
|
|
556
631
|
var _a, _b, _c, _d, _e, _f;
|
|
632
|
+
const pluvWs = this._getAbstractWs(webSocket);
|
|
633
|
+
if (!pluvWs) throw new Error("Could not get session");
|
|
634
|
+
const [session, sessions] = yield Promise.all([
|
|
635
|
+
this._getSession(pluvWs),
|
|
636
|
+
this._getSessions()
|
|
637
|
+
]);
|
|
557
638
|
const baseContext = {
|
|
558
639
|
context: this._context,
|
|
559
640
|
doc: this._doc,
|
|
560
641
|
room: this.id,
|
|
561
642
|
session,
|
|
562
|
-
sessions
|
|
643
|
+
sessions
|
|
563
644
|
};
|
|
564
645
|
if (!this._uninitialize) return;
|
|
565
|
-
if (
|
|
566
|
-
|
|
646
|
+
if (pluvWs.state.quit) {
|
|
647
|
+
pluvWs.close(1011, "WebSocket broken.");
|
|
567
648
|
return;
|
|
568
649
|
}
|
|
569
650
|
const message = this._parseMessage(event);
|
|
@@ -574,47 +655,52 @@ var IORoom = class {
|
|
|
574
655
|
try {
|
|
575
656
|
inputs = this._getProcedureInputs(message);
|
|
576
657
|
} catch (error) {
|
|
577
|
-
|
|
658
|
+
pluvWs.handleError({
|
|
578
659
|
error,
|
|
579
660
|
message: "Invalid input",
|
|
661
|
+
room: this.id,
|
|
580
662
|
session
|
|
581
663
|
});
|
|
582
664
|
return;
|
|
583
665
|
}
|
|
584
|
-
const extendedContext = __spreadProps(__spreadValues({}, baseContext), {
|
|
585
|
-
context: __spreadValues(__spreadValues({}, this._context), platformEventContext)
|
|
586
|
-
});
|
|
666
|
+
const extendedContext = __spreadProps(__spreadValues({}, baseContext), { context: __spreadValues({}, this._context) });
|
|
587
667
|
Promise.all([
|
|
588
668
|
(_b = (_a = procedure.config).broadcast) == null ? void 0 : _b.call(_a, inputs, extendedContext),
|
|
589
669
|
(_d = (_c = procedure.config).self) == null ? void 0 : _d.call(_c, inputs, extendedContext),
|
|
590
670
|
(_f = (_e = procedure.config).sync) == null ? void 0 : _f.call(_e, inputs, baseContext)
|
|
591
|
-
]).then(([broadcast, self, sync])
|
|
671
|
+
]).then((_0) => __async(this, [_0], function* ([broadcast, self, sync]) {
|
|
672
|
+
const sessionId = session.id;
|
|
673
|
+
const user = session.user;
|
|
592
674
|
if (broadcast) {
|
|
593
675
|
Object.entries(broadcast).forEach(([type, data]) => {
|
|
594
676
|
this._broadcast({
|
|
595
677
|
message: { data, type },
|
|
596
|
-
senderId:
|
|
678
|
+
senderId: sessionId
|
|
597
679
|
});
|
|
598
680
|
});
|
|
599
681
|
}
|
|
600
682
|
if (self) {
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
683
|
+
yield Promise.all(
|
|
684
|
+
Object.entries(self).map((_02) => __async(this, [_02], function* ([type, data]) {
|
|
685
|
+
yield this._sendSelfMessage({ data, type }, { sessionId, user });
|
|
686
|
+
}))
|
|
687
|
+
);
|
|
604
688
|
}
|
|
605
689
|
if (sync) {
|
|
606
690
|
this._platform.pubSub.publish(this.id, __spreadValues({
|
|
607
691
|
connectionId: session.id,
|
|
608
692
|
options: { type: "sync" },
|
|
609
693
|
room: this.id,
|
|
610
|
-
user
|
|
694
|
+
user
|
|
611
695
|
}, message));
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
696
|
+
yield Promise.all(
|
|
697
|
+
Object.entries(sync).map((_02) => __async(this, [_02], function* ([type, data]) {
|
|
698
|
+
yield this._sendSelfMessage({ data, type }, { sessionId, user });
|
|
699
|
+
}))
|
|
700
|
+
);
|
|
615
701
|
}
|
|
616
|
-
});
|
|
617
|
-
};
|
|
702
|
+
}));
|
|
703
|
+
});
|
|
618
704
|
}
|
|
619
705
|
_parseMessage(message) {
|
|
620
706
|
try {
|
|
@@ -627,80 +713,93 @@ var IORoom = class {
|
|
|
627
713
|
return null;
|
|
628
714
|
}
|
|
629
715
|
}
|
|
630
|
-
_sendMessage(
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
716
|
+
_sendMessage(_0, _1) {
|
|
717
|
+
return __async(this, arguments, function* (message, sender, options = {}) {
|
|
718
|
+
switch (options.type) {
|
|
719
|
+
case "self": {
|
|
720
|
+
yield this._sendSelfMessage(message, sender);
|
|
721
|
+
return;
|
|
722
|
+
}
|
|
723
|
+
case "sync": {
|
|
724
|
+
yield this._sendSyncMessage(message, sender);
|
|
725
|
+
return;
|
|
726
|
+
}
|
|
727
|
+
case "broadcast":
|
|
728
|
+
default: {
|
|
729
|
+
const sessionIds = options.sessionIds;
|
|
730
|
+
yield this._sendBroadcastMessage(message, sender, sessionIds);
|
|
731
|
+
}
|
|
644
732
|
}
|
|
645
|
-
}
|
|
733
|
+
});
|
|
646
734
|
}
|
|
647
735
|
_sendBroadcastMessage(message, sender, sessionIds) {
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
const
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
736
|
+
return __async(this, null, function* () {
|
|
737
|
+
var _a, _b;
|
|
738
|
+
const { data, type } = message;
|
|
739
|
+
const connectionId = (_a = sender == null ? void 0 : sender.sessionId) != null ? _a : null;
|
|
740
|
+
const room = this.id;
|
|
741
|
+
const webSockets = (_b = sessionIds == null ? void 0 : sessionIds.reduce((dict, id) => {
|
|
742
|
+
const pluvWs = this._sessions.get(id);
|
|
743
|
+
return pluvWs ? dict.set(id, pluvWs) : dict;
|
|
744
|
+
}, /* @__PURE__ */ new Map())) != null ? _b : this._sessions;
|
|
745
|
+
const promises = Array.from(webSockets.values()).map((pluvWs) => __async(this, null, function* () {
|
|
746
|
+
var _a2;
|
|
747
|
+
const session = yield pluvWs.getSession();
|
|
748
|
+
const user = (_a2 = session.user) != null ? _a2 : null;
|
|
749
|
+
pluvWs.sendMessage({ connectionId, data, room, type, user });
|
|
750
|
+
}));
|
|
751
|
+
yield Promise.all(promises);
|
|
752
|
+
});
|
|
753
|
+
}
|
|
754
|
+
_sendSelfMessage(message, sender) {
|
|
755
|
+
return __async(this, null, function* () {
|
|
756
|
+
var _a, _b;
|
|
757
|
+
const senderId = (_a = sender == null ? void 0 : sender.sessionId) != null ? _a : null;
|
|
758
|
+
if (typeof senderId !== "string") return;
|
|
759
|
+
const pluvWs = this._sessions.get(senderId);
|
|
760
|
+
if (!pluvWs) return;
|
|
761
|
+
if (message.type === "$PONG") yield this._emitQuitters();
|
|
762
|
+
const session = yield pluvWs.getSession();
|
|
763
|
+
const user = (_b = session.user) != null ? _b : null;
|
|
764
|
+
pluvWs.sendMessage(__spreadValues({
|
|
656
765
|
connectionId: senderId,
|
|
657
766
|
room: this.id,
|
|
658
|
-
user
|
|
767
|
+
user
|
|
659
768
|
}, message));
|
|
660
769
|
});
|
|
661
770
|
}
|
|
662
|
-
_sendSelfMessage(message, sender) {
|
|
663
|
-
const senderId = sender == null ? void 0 : sender.id;
|
|
664
|
-
if (!senderId) return;
|
|
665
|
-
const session = this._sessions.get(senderId);
|
|
666
|
-
if (!session) return;
|
|
667
|
-
session.webSocket.sendMessage(__spreadValues({
|
|
668
|
-
connectionId: sender.id,
|
|
669
|
-
room: this.id,
|
|
670
|
-
user: sender.user
|
|
671
|
-
}, message));
|
|
672
|
-
}
|
|
673
771
|
_sendSyncMessage(message, sender) {
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
772
|
+
return __async(this, null, function* () {
|
|
773
|
+
var _a;
|
|
774
|
+
if (!sender) return;
|
|
775
|
+
const context = {
|
|
776
|
+
context: this._context,
|
|
777
|
+
doc: this._doc,
|
|
778
|
+
room: this.id,
|
|
779
|
+
session: null,
|
|
780
|
+
sessions: yield this._getSessions()
|
|
781
|
+
};
|
|
782
|
+
const resolver = (_a = this._getProcedure(message)) == null ? void 0 : _a.config.sync;
|
|
783
|
+
if (!resolver) return;
|
|
784
|
+
let inputs;
|
|
785
|
+
try {
|
|
786
|
+
inputs = this._getProcedureInputs(message);
|
|
787
|
+
} catch (e) {
|
|
788
|
+
return;
|
|
789
|
+
}
|
|
790
|
+
Promise.resolve(resolver(inputs, context)).then((output) => {
|
|
791
|
+
if (!output) return;
|
|
792
|
+
Object.keys(output).forEach((type) => {
|
|
793
|
+
var _a2, _b;
|
|
794
|
+
const data = (_a2 = output[type]) != null ? _a2 : {};
|
|
795
|
+
this._platform.pubSub.publish(this.id, {
|
|
796
|
+
connectionId: sender.sessionId,
|
|
797
|
+
data,
|
|
798
|
+
options: { type: "self" },
|
|
799
|
+
room: this.id,
|
|
800
|
+
type,
|
|
801
|
+
user: (_b = sender.user) != null ? _b : null
|
|
802
|
+
});
|
|
704
803
|
});
|
|
705
804
|
});
|
|
706
805
|
});
|
|
@@ -708,7 +807,7 @@ var IORoom = class {
|
|
|
708
807
|
};
|
|
709
808
|
|
|
710
809
|
// src/version.generated.ts
|
|
711
|
-
var version = "0.
|
|
810
|
+
var version = "0.21.1";
|
|
712
811
|
|
|
713
812
|
// src/PluvServer.ts
|
|
714
813
|
var PluvServer = class {
|
|
@@ -741,6 +840,9 @@ var PluvServer = class {
|
|
|
741
840
|
get _events() {
|
|
742
841
|
return this._router._events;
|
|
743
842
|
}
|
|
843
|
+
get _registrationMode() {
|
|
844
|
+
return this._platform._registrationMode;
|
|
845
|
+
}
|
|
744
846
|
createToken(params) {
|
|
745
847
|
return __async(this, null, function* () {
|
|
746
848
|
if (!this._authorize) {
|
|
@@ -754,9 +856,9 @@ var PluvServer = class {
|
|
|
754
856
|
}).encode(params);
|
|
755
857
|
});
|
|
756
858
|
}
|
|
757
|
-
getRoom(room, options) {
|
|
758
|
-
var
|
|
759
|
-
const _a = options, { debug } =
|
|
859
|
+
getRoom(room, ...options) {
|
|
860
|
+
var _a, _c;
|
|
861
|
+
const _b = (_a = options[0]) != null ? _a : {}, { debug } = _b, platformRoomContext = __objRest(_b, ["debug"]);
|
|
760
862
|
this._purgeEmptyRooms();
|
|
761
863
|
if (!/^[a-z0-9]+[a-z0-9\-_]+[a-z0-9]+$/i.test(room)) {
|
|
762
864
|
throw new Error("Unsupported room name");
|
|
@@ -766,24 +868,25 @@ var PluvServer = class {
|
|
|
766
868
|
if (oldRoom) return oldRoom;
|
|
767
869
|
const roomContext = __spreadValues(__spreadValues({}, this._context), platformRoomContext);
|
|
768
870
|
const newRoom = new IORoom(room, {
|
|
769
|
-
authorize: (
|
|
871
|
+
authorize: (_c = this._authorize) != null ? _c : void 0,
|
|
770
872
|
context: roomContext,
|
|
771
873
|
crdt: this._crdt,
|
|
772
874
|
debug: debug != null ? debug : this._debug,
|
|
773
|
-
onDestroy: ({ encodedState, room: room2 })
|
|
875
|
+
onDestroy: (_0) => __async(this, [_0], function* ({ encodedState, room: room2 }) {
|
|
774
876
|
this._logDebug(`${colors2.blue("Deleting empty room:")} ${room2}`);
|
|
775
877
|
const roomContext2 = __spreadValues({
|
|
776
878
|
room: room2,
|
|
777
879
|
encodedState
|
|
778
880
|
}, platformRoomContext);
|
|
779
881
|
this._rooms.delete(room2);
|
|
780
|
-
this._listeners.onRoomDeleted(roomContext2);
|
|
882
|
+
yield Promise.resolve(this._listeners.onRoomDeleted(roomContext2));
|
|
883
|
+
yield this._platform.persistance.deleteStorageState(room2);
|
|
781
884
|
if (this._debug) {
|
|
782
885
|
const rooms = Array.from(this._rooms.keys());
|
|
783
886
|
this._logDebug(`${colors2.blue("Deleted room:")} ${room2}`);
|
|
784
887
|
this._logDebug(`${colors2.blue("Rooms available:")} ${rooms.join(", ")}`);
|
|
785
888
|
}
|
|
786
|
-
},
|
|
889
|
+
}),
|
|
787
890
|
platform,
|
|
788
891
|
router: this._router
|
|
789
892
|
});
|
|
@@ -812,10 +915,16 @@ var PluvIO = class {
|
|
|
812
915
|
constructor(options) {
|
|
813
916
|
this._router = new PluvRouter({
|
|
814
917
|
$GET_OTHERS: this.procedure.sync((data, { room, session, sessions }) => {
|
|
815
|
-
const
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
918
|
+
const currentTime = (/* @__PURE__ */ new Date()).getTime();
|
|
919
|
+
const others = sessions.filter((wsSession) => {
|
|
920
|
+
if (wsSession.id === (session == null ? void 0 : session.id)) return false;
|
|
921
|
+
if (wsSession.quit) return false;
|
|
922
|
+
if (currentTime - wsSession.timers.ping > PING_TIMEOUT_MS) return false;
|
|
923
|
+
return true;
|
|
924
|
+
}).reduce(
|
|
925
|
+
(acc, { id, presence, user }) => __spreadProps(__spreadValues({}, acc), {
|
|
926
|
+
[id]: {
|
|
927
|
+
connectionId: id,
|
|
819
928
|
presence,
|
|
820
929
|
room,
|
|
821
930
|
user
|
|
@@ -863,8 +972,9 @@ var PluvIO = class {
|
|
|
863
972
|
$UPDATE_PRESENCE: this.procedure.broadcast((data, { session }) => {
|
|
864
973
|
const presence = data == null ? void 0 : data.presence;
|
|
865
974
|
if (!session) return {};
|
|
866
|
-
|
|
867
|
-
|
|
975
|
+
const updated = Object.assign(/* @__PURE__ */ Object.create(null), session.presence, presence);
|
|
976
|
+
session.webSocket.presence = updated;
|
|
977
|
+
return { $PRESENCE_UPDATED: { presence: updated } };
|
|
868
978
|
}),
|
|
869
979
|
$UPDATE_STORAGE: this.procedure.broadcast((data, { context, doc, room }) => {
|
|
870
980
|
var _a;
|
|
@@ -912,14 +1022,15 @@ var PluvIO = class {
|
|
|
912
1022
|
get _events() {
|
|
913
1023
|
return this._router._events;
|
|
914
1024
|
}
|
|
1025
|
+
get _registrationMode() {
|
|
1026
|
+
return this._platform._registrationMode;
|
|
1027
|
+
}
|
|
915
1028
|
get procedure() {
|
|
916
1029
|
return new PluvProcedure();
|
|
917
1030
|
}
|
|
918
1031
|
createToken(params) {
|
|
919
1032
|
return __async(this, null, function* () {
|
|
920
|
-
if (!this._authorize)
|
|
921
|
-
throw new Error("IO does not specify authorize during initialization.");
|
|
922
|
-
}
|
|
1033
|
+
if (!this._authorize) throw new Error("IO does not specify authorize during initialization.");
|
|
923
1034
|
const ioAuthorize = typeof this._authorize === "function" ? this._authorize(params) : this._authorize;
|
|
924
1035
|
const secret = ioAuthorize.secret;
|
|
925
1036
|
return yield authorize({
|