@pluv/io 0.24.1 → 0.25.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 +9 -9
- package/CHANGELOG.md +49 -0
- package/README.md +2 -2
- package/dist/index.d.mts +37 -15
- package/dist/index.d.ts +37 -15
- package/dist/index.js +61 -43
- package/dist/index.mjs +60 -42
- package/package.json +5 -5
- package/src/{AbstractPersistance.ts → AbstractPersistence.ts} +1 -1
- package/src/AbstractPlatform.ts +10 -6
- package/src/AbstractWebSocket.ts +6 -6
- package/src/IORoom.ts +28 -20
- package/src/{Persistance.ts → Persistence.ts} +2 -2
- package/src/PluvIO.ts +1 -1
- package/src/PluvRouter.ts +5 -5
- package/src/PluvServer.ts +18 -12
- package/src/index.ts +1 -1
- package/src/version.generated.ts +1 -1
package/dist/index.mjs
CHANGED
|
@@ -50,12 +50,12 @@ var __async = (__this, __arguments, generator) => {
|
|
|
50
50
|
});
|
|
51
51
|
};
|
|
52
52
|
|
|
53
|
-
// src/
|
|
54
|
-
var
|
|
53
|
+
// src/AbstractPersistence.ts
|
|
54
|
+
var AbstractPersistence = class {
|
|
55
55
|
};
|
|
56
56
|
|
|
57
|
-
// src/
|
|
58
|
-
var
|
|
57
|
+
// src/Persistence.ts
|
|
58
|
+
var Persistence = class extends AbstractPersistence {
|
|
59
59
|
constructor() {
|
|
60
60
|
super(...arguments);
|
|
61
61
|
this._storages = /* @__PURE__ */ new Map();
|
|
@@ -176,12 +176,15 @@ var PubSub = class extends AbstractPubSub {
|
|
|
176
176
|
var AbstractPlatform = class {
|
|
177
177
|
constructor(config = {}) {
|
|
178
178
|
this._initialized = false;
|
|
179
|
-
const { context,
|
|
179
|
+
const { context, persistence, pubSub } = config;
|
|
180
180
|
context && (this._ioContext = context);
|
|
181
181
|
context && (this._roomContext = context);
|
|
182
|
-
this.
|
|
182
|
+
this.persistence = persistence != null ? persistence : new Persistence();
|
|
183
183
|
this.pubSub = pubSub != null ? pubSub : new PubSub();
|
|
184
184
|
}
|
|
185
|
+
get _meta() {
|
|
186
|
+
return void 0;
|
|
187
|
+
}
|
|
185
188
|
_initialize() {
|
|
186
189
|
if (this._initialized) throw new Error("Platform is already initialized");
|
|
187
190
|
this._initialized = true;
|
|
@@ -201,8 +204,8 @@ var AbstractWebSocket = class {
|
|
|
201
204
|
/** The connection is closed. */
|
|
202
205
|
this.CLOSED = 3;
|
|
203
206
|
this._user = null;
|
|
204
|
-
const {
|
|
205
|
-
this.
|
|
207
|
+
const { persistence, room } = config;
|
|
208
|
+
this.persistence = persistence;
|
|
206
209
|
this.room = room;
|
|
207
210
|
this.webSocket = webSocket;
|
|
208
211
|
}
|
|
@@ -212,7 +215,7 @@ var AbstractWebSocket = class {
|
|
|
212
215
|
const sessionId = this.sessionId;
|
|
213
216
|
const state = this.state;
|
|
214
217
|
const room = state.room;
|
|
215
|
-
const user = (_a = this._user) != null ? _a : yield this.
|
|
218
|
+
const user = (_a = this._user) != null ? _a : yield this.persistence.getUser(room, sessionId);
|
|
216
219
|
this._user = user;
|
|
217
220
|
return __spreadProps(__spreadValues({}, state), {
|
|
218
221
|
id: sessionId,
|
|
@@ -300,11 +303,11 @@ var PluvProcedure = class _PluvProcedure {
|
|
|
300
303
|
// src/PluvRouter.ts
|
|
301
304
|
var PluvRouter = class _PluvRouter {
|
|
302
305
|
constructor(events) {
|
|
303
|
-
this.
|
|
304
|
-
this.
|
|
306
|
+
this._defs = { events: {} };
|
|
307
|
+
this._defs = { events };
|
|
305
308
|
}
|
|
306
309
|
static merge(...routers) {
|
|
307
|
-
const events = Object.assign(/* @__PURE__ */ Object.create(null), ...routers.map((router) => router.
|
|
310
|
+
const events = Object.assign(/* @__PURE__ */ Object.create(null), ...routers.map((router) => router._defs.events));
|
|
308
311
|
return new _PluvRouter(events);
|
|
309
312
|
}
|
|
310
313
|
};
|
|
@@ -353,8 +356,8 @@ var PING_TIMEOUT_MS = 3e4;
|
|
|
353
356
|
// src/IORoom.ts
|
|
354
357
|
var IORoom = class {
|
|
355
358
|
constructor(id, config) {
|
|
356
|
-
this._authorize = null;
|
|
357
359
|
this._uninitialize = null;
|
|
360
|
+
this._authorize = null;
|
|
358
361
|
this._sessions = /* @__PURE__ */ new Map();
|
|
359
362
|
const { authorize: authorize2, context, crdt = noop, debug, onDestroy, onMessage, platform, router } = config;
|
|
360
363
|
this.id = id;
|
|
@@ -381,8 +384,18 @@ var IORoom = class {
|
|
|
381
384
|
this._doc = doc;
|
|
382
385
|
this._uninitialize = uninitialize;
|
|
383
386
|
}
|
|
384
|
-
|
|
385
|
-
|
|
387
|
+
/**
|
|
388
|
+
* @ignore
|
|
389
|
+
* @readonly
|
|
390
|
+
* @deprecated Internal use only. Changes to this will never be marked as breaking.
|
|
391
|
+
*/
|
|
392
|
+
get _defs() {
|
|
393
|
+
return {
|
|
394
|
+
authorize: this._authorize,
|
|
395
|
+
context: this._context,
|
|
396
|
+
events: this._router._defs.events,
|
|
397
|
+
platform: this._platform
|
|
398
|
+
};
|
|
386
399
|
}
|
|
387
400
|
get broadcast() {
|
|
388
401
|
const _broadcast = (event, data) => {
|
|
@@ -459,7 +472,7 @@ var IORoom = class {
|
|
|
459
472
|
return;
|
|
460
473
|
}
|
|
461
474
|
this._sessions.set(pluvWs.sessionId, pluvWs);
|
|
462
|
-
yield this._platform.
|
|
475
|
+
yield this._platform.persistence.addUser(this.id, pluvWs.sessionId, user != null ? user : {});
|
|
463
476
|
if (this._platform._registrationMode === "attached") {
|
|
464
477
|
const onClose = this._onClose(pluvWs).bind(this);
|
|
465
478
|
const onMessage = this._onMessage(pluvWs).bind(this);
|
|
@@ -563,7 +576,7 @@ var IORoom = class {
|
|
|
563
576
|
_getInitialDoc() {
|
|
564
577
|
return __async(this, null, function* () {
|
|
565
578
|
const doc = this._docFactory.getEmpty();
|
|
566
|
-
const encodedState = yield this._platform.
|
|
579
|
+
const encodedState = yield this._platform.persistence.getStorageState(this.id);
|
|
567
580
|
if (typeof encodedState === "string") doc.applyEncodedState({ update: encodedState });
|
|
568
581
|
return doc;
|
|
569
582
|
});
|
|
@@ -576,7 +589,7 @@ var IORoom = class {
|
|
|
576
589
|
}
|
|
577
590
|
_getProcedure(message) {
|
|
578
591
|
var _a;
|
|
579
|
-
return (_a = this._router.
|
|
592
|
+
return (_a = this._router._defs.events[message.type]) != null ? _a : null;
|
|
580
593
|
}
|
|
581
594
|
_getProcedureInputs(message) {
|
|
582
595
|
const procedure = this._getProcedure(message);
|
|
@@ -638,11 +651,11 @@ var IORoom = class {
|
|
|
638
651
|
const encodedState = doc2.getEncodedState();
|
|
639
652
|
doc2.destroy();
|
|
640
653
|
this._doc = Promise.resolve(this._docFactory.getEmpty());
|
|
641
|
-
this._listeners.onDestroy({
|
|
654
|
+
this._listeners.onDestroy(__spreadProps(__spreadValues({}, this._platform._meta ? { _meta: this._platform._meta } : {}), {
|
|
642
655
|
context: this._context,
|
|
643
656
|
encodedState,
|
|
644
657
|
room: this.id
|
|
645
|
-
});
|
|
658
|
+
}));
|
|
646
659
|
this._uninitialize = null;
|
|
647
660
|
});
|
|
648
661
|
return { doc, uninitialize };
|
|
@@ -660,7 +673,7 @@ var IORoom = class {
|
|
|
660
673
|
webSocket.state = __spreadProps(__spreadValues({}, webSocket.state), { quit: true });
|
|
661
674
|
this._logDebug(`${colors.blue(`Unregistering connection for room ${this.id}:`)} ${webSocket.sessionId}`);
|
|
662
675
|
this._sessions.delete(webSocket.sessionId);
|
|
663
|
-
this._platform.
|
|
676
|
+
this._platform.persistence.deleteUser(this.id, webSocket.sessionId).finally(() => __async(this, null, function* () {
|
|
664
677
|
yield this._broadcast({
|
|
665
678
|
message: {
|
|
666
679
|
type: "$EXIT",
|
|
@@ -704,6 +717,13 @@ var IORoom = class {
|
|
|
704
717
|
const message = this._parseMessage(event);
|
|
705
718
|
if (!message) return;
|
|
706
719
|
const procedure = this._getProcedure(message);
|
|
720
|
+
this._listeners.onMessage(__spreadProps(__spreadValues({}, this._platform._meta ? { _meta: this._platform._meta } : {}), {
|
|
721
|
+
context: this._context,
|
|
722
|
+
encodedState: doc.getEncodedState(),
|
|
723
|
+
message,
|
|
724
|
+
room: this.id,
|
|
725
|
+
user: session.user
|
|
726
|
+
}));
|
|
707
727
|
if (!procedure) return;
|
|
708
728
|
let inputs;
|
|
709
729
|
try {
|
|
@@ -775,16 +795,7 @@ var IORoom = class {
|
|
|
775
795
|
}
|
|
776
796
|
_sendMessage(pluvWs, message) {
|
|
777
797
|
return __async(this, null, function* () {
|
|
778
|
-
const { data, type } = message;
|
|
779
798
|
if (!(yield this._initialized)) return;
|
|
780
|
-
const doc = yield this._doc;
|
|
781
|
-
this._listeners.onMessage({
|
|
782
|
-
context: this._context,
|
|
783
|
-
encodedState: doc.getEncodedState(),
|
|
784
|
-
message: { data, type },
|
|
785
|
-
room: this.id,
|
|
786
|
-
user: message.user
|
|
787
|
-
});
|
|
788
799
|
yield Promise.resolve(pluvWs.sendMessage(message));
|
|
789
800
|
});
|
|
790
801
|
}
|
|
@@ -864,7 +875,7 @@ var IORoom = class {
|
|
|
864
875
|
};
|
|
865
876
|
|
|
866
877
|
// src/version.generated.ts
|
|
867
|
-
var version = "0.
|
|
878
|
+
var version = "0.25.1";
|
|
868
879
|
|
|
869
880
|
// src/PluvServer.ts
|
|
870
881
|
var PluvServer = class {
|
|
@@ -905,7 +916,7 @@ var PluvServer = class {
|
|
|
905
916
|
};
|
|
906
917
|
}).self((_0, _1) => __async(this, [_0, _1], function* (data, { context, doc, room }) {
|
|
907
918
|
var _a, _b;
|
|
908
|
-
const oldState = yield this._platform.
|
|
919
|
+
const oldState = yield this._platform.persistence.getStorageState(room);
|
|
909
920
|
const update = data == null ? void 0 : data.update;
|
|
910
921
|
const updates = [
|
|
911
922
|
oldState ? null : yield (_a = this._getInitialStorage) == null ? void 0 : _a.call(this, __spreadProps(__spreadValues({}, context), { room })),
|
|
@@ -913,10 +924,10 @@ var PluvServer = class {
|
|
|
913
924
|
];
|
|
914
925
|
if (updates.some((_update) => !!_update)) {
|
|
915
926
|
const encodedState = doc.batchApplyEncodedState(updates).getEncodedState();
|
|
916
|
-
yield this._platform.
|
|
927
|
+
yield this._platform.persistence.setStorageState(room, encodedState);
|
|
917
928
|
this._listeners.onStorageUpdated({ context, encodedState, room });
|
|
918
929
|
}
|
|
919
|
-
const state = (_b = yield this._platform.
|
|
930
|
+
const state = (_b = yield this._platform.persistence.getStorageState(room)) != null ? _b : doc.getEncodedState();
|
|
920
931
|
return { $STORAGE_RECEIVED: { state } };
|
|
921
932
|
})),
|
|
922
933
|
$PING: this._procedure.self((data, { session }) => {
|
|
@@ -944,7 +955,7 @@ var PluvServer = class {
|
|
|
944
955
|
if (origin === "$INITIALIZED" && Object.keys(doc.toJson()).length) return {};
|
|
945
956
|
const updated = update === null ? doc : doc.applyEncodedState({ update });
|
|
946
957
|
const encodedState = updated.getEncodedState();
|
|
947
|
-
this._platform.
|
|
958
|
+
this._platform.persistence.setStorageState(room, encodedState).then(() => {
|
|
948
959
|
this._listeners.onStorageUpdated({
|
|
949
960
|
context,
|
|
950
961
|
encodedState,
|
|
@@ -981,11 +992,18 @@ var PluvServer = class {
|
|
|
981
992
|
onStorageUpdated: (event) => onStorageUpdated == null ? void 0 : onStorageUpdated(event)
|
|
982
993
|
};
|
|
983
994
|
}
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
995
|
+
/**
|
|
996
|
+
* @ignore
|
|
997
|
+
* @readonly
|
|
998
|
+
* @deprecated Internal use only. Changes to this will never be marked as breaking.
|
|
999
|
+
*/
|
|
1000
|
+
get _defs() {
|
|
1001
|
+
return {
|
|
1002
|
+
authorize: this._authorize,
|
|
1003
|
+
context: this._context,
|
|
1004
|
+
events: this._router._defs.events,
|
|
1005
|
+
platform: this._platform
|
|
1006
|
+
};
|
|
989
1007
|
}
|
|
990
1008
|
get _procedure() {
|
|
991
1009
|
return new PluvProcedure();
|
|
@@ -1006,7 +1024,7 @@ var PluvServer = class {
|
|
|
1006
1024
|
this._logDebug(`${colors2.blue("Deleting empty room:")} ${room}`);
|
|
1007
1025
|
yield Promise.resolve(onDestroy == null ? void 0 : onDestroy(event));
|
|
1008
1026
|
yield Promise.resolve(this._listeners.onRoomDeleted(event));
|
|
1009
|
-
yield this._platform.
|
|
1027
|
+
yield this._platform.persistence.deleteStorageState(room);
|
|
1010
1028
|
this._logDebug(`${colors2.blue("Deleted room:")} ${room}`);
|
|
1011
1029
|
}),
|
|
1012
1030
|
onMessage: (event) => __async(this, null, function* () {
|
|
@@ -1094,7 +1112,7 @@ var createIO = (params) => {
|
|
|
1094
1112
|
});
|
|
1095
1113
|
};
|
|
1096
1114
|
export {
|
|
1097
|
-
|
|
1115
|
+
AbstractPersistence,
|
|
1098
1116
|
AbstractPlatform,
|
|
1099
1117
|
AbstractPubSub,
|
|
1100
1118
|
AbstractWebSocket,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pluv/io",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.1",
|
|
4
4
|
"description": "@pluv/io server-side websocket manager",
|
|
5
5
|
"author": "leedavidcs",
|
|
6
6
|
"license": "MIT",
|
|
@@ -21,16 +21,16 @@
|
|
|
21
21
|
"jose": "^5.7.0",
|
|
22
22
|
"kleur": "^4.1.5",
|
|
23
23
|
"wonka": "^6.3.4",
|
|
24
|
-
"@pluv/crdt": "^0.
|
|
25
|
-
"@pluv/types": "^0.
|
|
24
|
+
"@pluv/crdt": "^0.25.1",
|
|
25
|
+
"@pluv/types": "^0.25.1"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"eslint": "^8.57.0",
|
|
29
29
|
"genversion": "^3.2.0",
|
|
30
30
|
"tsup": "^8.2.4",
|
|
31
31
|
"typescript": "^5.5.4",
|
|
32
|
-
"@pluv/tsconfig": "^0.
|
|
33
|
-
"eslint-config-pluv": "^0.
|
|
32
|
+
"@pluv/tsconfig": "^0.25.1",
|
|
33
|
+
"eslint-config-pluv": "^0.25.1"
|
|
34
34
|
},
|
|
35
35
|
"scripts": {
|
|
36
36
|
"build": "pnpm run version && tsup src/index.ts --format esm,cjs --dts",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { JsonObject } from "@pluv/types";
|
|
2
2
|
|
|
3
|
-
export abstract class
|
|
3
|
+
export abstract class AbstractPersistence {
|
|
4
4
|
public abstract addUser(room: string, connectionId: string, user: JsonObject | null): Promise<void>;
|
|
5
5
|
|
|
6
6
|
public abstract deleteStorageState(room: string): Promise<void>;
|
package/src/AbstractPlatform.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { AbstractPersistence } from "./AbstractPersistence";
|
|
2
2
|
import type { AbstractPubSub } from "./AbstractPubSub";
|
|
3
3
|
import type { AbstractWebSocket, InferWebSocketSource } from "./AbstractWebSocket";
|
|
4
|
-
import {
|
|
4
|
+
import { Persistence } from "./Persistence";
|
|
5
5
|
import { PubSub } from "./PubSub";
|
|
6
6
|
import type { WebSocketSerializedState } from "./types";
|
|
7
7
|
|
|
@@ -26,7 +26,7 @@ export type AbstractPlatformConfig<
|
|
|
26
26
|
TRoomContext extends Record<string, any> = {},
|
|
27
27
|
> = {
|
|
28
28
|
context?: TPlatformContext & TRoomContext;
|
|
29
|
-
|
|
29
|
+
persistence?: AbstractPersistence;
|
|
30
30
|
pubSub?: AbstractPubSub;
|
|
31
31
|
};
|
|
32
32
|
|
|
@@ -44,21 +44,25 @@ export abstract class AbstractPlatform<
|
|
|
44
44
|
|
|
45
45
|
private _initialized: boolean = false;
|
|
46
46
|
|
|
47
|
-
public
|
|
47
|
+
public persistence: AbstractPersistence;
|
|
48
48
|
public pubSub: AbstractPubSub;
|
|
49
49
|
|
|
50
50
|
public abstract readonly _registrationMode: WebSocketRegistrationMode;
|
|
51
51
|
|
|
52
52
|
constructor(config: AbstractPlatformConfig<TPlatformContext, TRoomContext> = {}) {
|
|
53
|
-
const { context,
|
|
53
|
+
const { context, persistence, pubSub } = config;
|
|
54
54
|
|
|
55
55
|
context && (this._ioContext = context);
|
|
56
56
|
context && (this._roomContext = context);
|
|
57
57
|
|
|
58
|
-
this.
|
|
58
|
+
this.persistence = persistence ?? new Persistence();
|
|
59
59
|
this.pubSub = pubSub ?? new PubSub();
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
+
public get _meta(): any {
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
|
|
62
66
|
public abstract acceptWebSocket(webSocket: AbstractWebSocket): Promise<void>;
|
|
63
67
|
|
|
64
68
|
public abstract convertWebSocket(
|
package/src/AbstractWebSocket.ts
CHANGED
|
@@ -6,7 +6,7 @@ import type {
|
|
|
6
6
|
JsonObject,
|
|
7
7
|
MaybePromise,
|
|
8
8
|
} from "@pluv/types";
|
|
9
|
-
import type {
|
|
9
|
+
import type { AbstractPersistence } from "./AbstractPersistence";
|
|
10
10
|
import type { WebSocketSerializedState, WebSocketSession } from "./types";
|
|
11
11
|
|
|
12
12
|
export type AbstractEvent = {};
|
|
@@ -48,7 +48,7 @@ export type InferWebSocketSource<TAbstractWebSocket extends AbstractWebSocket> =
|
|
|
48
48
|
TAbstractWebSocket extends AbstractWebSocket<infer IWebSocket> ? IWebSocket : never;
|
|
49
49
|
|
|
50
50
|
export interface AbstractWebSocketConfig {
|
|
51
|
-
|
|
51
|
+
persistence: AbstractPersistence;
|
|
52
52
|
room: string;
|
|
53
53
|
}
|
|
54
54
|
|
|
@@ -62,7 +62,7 @@ export abstract class AbstractWebSocket<TWebSocket = any> {
|
|
|
62
62
|
/** The connection is closed. */
|
|
63
63
|
public readonly CLOSED = 3;
|
|
64
64
|
|
|
65
|
-
public readonly
|
|
65
|
+
public readonly persistence: AbstractPersistence;
|
|
66
66
|
public readonly room: string;
|
|
67
67
|
public readonly webSocket: TWebSocket;
|
|
68
68
|
|
|
@@ -75,9 +75,9 @@ export abstract class AbstractWebSocket<TWebSocket = any> {
|
|
|
75
75
|
public abstract set state(state: WebSocketSerializedState);
|
|
76
76
|
|
|
77
77
|
constructor(webSocket: TWebSocket, config: AbstractWebSocketConfig) {
|
|
78
|
-
const {
|
|
78
|
+
const { persistence, room } = config;
|
|
79
79
|
|
|
80
|
-
this.
|
|
80
|
+
this.persistence = persistence;
|
|
81
81
|
this.room = room;
|
|
82
82
|
this.webSocket = webSocket;
|
|
83
83
|
}
|
|
@@ -105,7 +105,7 @@ export abstract class AbstractWebSocket<TWebSocket = any> {
|
|
|
105
105
|
const state = this.state;
|
|
106
106
|
const room = state.room;
|
|
107
107
|
|
|
108
|
-
const user = this._user ?? (await this.
|
|
108
|
+
const user = this._user ?? (await this.persistence.getUser(room, sessionId));
|
|
109
109
|
|
|
110
110
|
this._user = user as BaseUser;
|
|
111
111
|
|
package/src/IORoom.ts
CHANGED
|
@@ -88,11 +88,11 @@ export class IORoom<
|
|
|
88
88
|
> implements IOLike<TAuthorize, TEvents>
|
|
89
89
|
{
|
|
90
90
|
public readonly id: string;
|
|
91
|
-
public readonly _authorize: TAuthorize | null = null;
|
|
92
91
|
|
|
93
92
|
private _doc: Promise<AbstractCrdtDoc<any>>;
|
|
94
93
|
private _uninitialize: Promise<() => Promise<void>> | null = null;
|
|
95
94
|
|
|
95
|
+
private readonly _authorize: TAuthorize | null = null;
|
|
96
96
|
private readonly _context: TContext & InferRoomContextType<TPlatform>;
|
|
97
97
|
private readonly _debug: boolean;
|
|
98
98
|
private readonly _docFactory: AbstractCrdtDocFactory<any>;
|
|
@@ -101,8 +101,18 @@ export class IORoom<
|
|
|
101
101
|
private readonly _router: PluvRouter<TPlatform, TAuthorize, TContext, TEvents>;
|
|
102
102
|
private readonly _sessions = new Map<string, AbstractWebSocket>();
|
|
103
103
|
|
|
104
|
-
|
|
105
|
-
|
|
104
|
+
/**
|
|
105
|
+
* @ignore
|
|
106
|
+
* @readonly
|
|
107
|
+
* @deprecated Internal use only. Changes to this will never be marked as breaking.
|
|
108
|
+
*/
|
|
109
|
+
public get _defs() {
|
|
110
|
+
return {
|
|
111
|
+
authorize: this._authorize,
|
|
112
|
+
context: this._context,
|
|
113
|
+
events: this._router._defs.events,
|
|
114
|
+
platform: this._platform,
|
|
115
|
+
};
|
|
106
116
|
}
|
|
107
117
|
|
|
108
118
|
public get broadcast(): BroadcastProxy<this> {
|
|
@@ -254,7 +264,7 @@ export class IORoom<
|
|
|
254
264
|
|
|
255
265
|
this._sessions.set(pluvWs.sessionId, pluvWs);
|
|
256
266
|
|
|
257
|
-
await this._platform.
|
|
267
|
+
await this._platform.persistence.addUser(this.id, pluvWs.sessionId, user ?? {});
|
|
258
268
|
|
|
259
269
|
if (this._platform._registrationMode === "attached") {
|
|
260
270
|
const onClose = this._onClose(pluvWs).bind(this);
|
|
@@ -379,7 +389,7 @@ export class IORoom<
|
|
|
379
389
|
|
|
380
390
|
private async _getInitialDoc(): Promise<AbstractCrdtDoc<any>> {
|
|
381
391
|
const doc = this._docFactory.getEmpty();
|
|
382
|
-
const encodedState = await this._platform.
|
|
392
|
+
const encodedState = await this._platform.persistence.getStorageState(this.id);
|
|
383
393
|
|
|
384
394
|
if (typeof encodedState === "string") doc.applyEncodedState({ update: encodedState });
|
|
385
395
|
|
|
@@ -400,8 +410,8 @@ export class IORoom<
|
|
|
400
410
|
|
|
401
411
|
private _getProcedure(
|
|
402
412
|
message: EventMessage<string, any>,
|
|
403
|
-
): (typeof this._router)["
|
|
404
|
-
return this._router.
|
|
413
|
+
): (typeof this._router)["_defs"]["events"][keyof (typeof this._router)["_defs"]["events"]] | null {
|
|
414
|
+
return this._router._defs.events[message.type as keyof (typeof this._router)["_defs"]["events"]] ?? null;
|
|
405
415
|
}
|
|
406
416
|
|
|
407
417
|
private _getProcedureInputs(message: EventMessage<string, any>): InferIOInput<this>[keyof TEvents] {
|
|
@@ -477,6 +487,7 @@ export class IORoom<
|
|
|
477
487
|
this._doc = Promise.resolve(this._docFactory.getEmpty());
|
|
478
488
|
|
|
479
489
|
this._listeners.onDestroy({
|
|
490
|
+
...(this._platform._meta ? { _meta: this._platform._meta } : {}),
|
|
480
491
|
context: this._context,
|
|
481
492
|
encodedState,
|
|
482
493
|
room: this.id,
|
|
@@ -507,7 +518,7 @@ export class IORoom<
|
|
|
507
518
|
this._logDebug(`${colors.blue(`Unregistering connection for room ${this.id}:`)} ${webSocket.sessionId}`);
|
|
508
519
|
this._sessions.delete(webSocket.sessionId);
|
|
509
520
|
|
|
510
|
-
this._platform.
|
|
521
|
+
this._platform.persistence.deleteUser(this.id, webSocket.sessionId).finally(async () => {
|
|
511
522
|
await this._broadcast({
|
|
512
523
|
message: {
|
|
513
524
|
type: "$EXIT",
|
|
@@ -565,6 +576,15 @@ export class IORoom<
|
|
|
565
576
|
|
|
566
577
|
const procedure = this._getProcedure(message);
|
|
567
578
|
|
|
579
|
+
this._listeners.onMessage({
|
|
580
|
+
...(this._platform._meta ? { _meta: this._platform._meta } : {}),
|
|
581
|
+
context: this._context,
|
|
582
|
+
encodedState: doc.getEncodedState(),
|
|
583
|
+
message: message as InferEventMessage<InferEventsOutput<TEvents>, keyof InferEventsOutput<TEvents>>,
|
|
584
|
+
room: this.id,
|
|
585
|
+
user: session.user,
|
|
586
|
+
});
|
|
587
|
+
|
|
568
588
|
if (!procedure) return;
|
|
569
589
|
|
|
570
590
|
let inputs: InferIOInput<this>[keyof TEvents];
|
|
@@ -657,20 +677,8 @@ export class IORoom<
|
|
|
657
677
|
}
|
|
658
678
|
|
|
659
679
|
private async _sendMessage(pluvWs: AbstractWebSocket<any>, message: IOEventMessage<any>): Promise<void> {
|
|
660
|
-
const { data, type } = message;
|
|
661
|
-
|
|
662
680
|
if (!(await this._initialized)) return;
|
|
663
681
|
|
|
664
|
-
const doc = await this._doc;
|
|
665
|
-
|
|
666
|
-
this._listeners.onMessage({
|
|
667
|
-
context: this._context,
|
|
668
|
-
encodedState: doc.getEncodedState(),
|
|
669
|
-
message: { data, type } as InferEventMessage<InferEventsOutput<TEvents>, keyof InferEventsOutput<TEvents>>,
|
|
670
|
-
room: this.id,
|
|
671
|
-
user: message.user,
|
|
672
|
-
});
|
|
673
|
-
|
|
674
682
|
await Promise.resolve(pluvWs.sendMessage(message));
|
|
675
683
|
}
|
|
676
684
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { JsonObject } from "@pluv/types";
|
|
2
|
-
import {
|
|
2
|
+
import { AbstractPersistence } from "./AbstractPersistence";
|
|
3
3
|
|
|
4
|
-
export class
|
|
4
|
+
export class Persistence extends AbstractPersistence {
|
|
5
5
|
private _storages = new Map<string, string>();
|
|
6
6
|
private _users = new Map<string, Map<string, JsonObject | null>>();
|
|
7
7
|
|
package/src/PluvIO.ts
CHANGED
|
@@ -39,8 +39,8 @@ export class PluvIO<
|
|
|
39
39
|
TContext extends JsonObject = {},
|
|
40
40
|
> {
|
|
41
41
|
public readonly version: string = __PLUV_VERSION as any;
|
|
42
|
-
public readonly _authorize: TAuthorize | null = null;
|
|
43
42
|
|
|
43
|
+
private readonly _authorize: TAuthorize | null = null;
|
|
44
44
|
private readonly _context: TContext = {} as TContext;
|
|
45
45
|
private readonly _crdt: { doc: (value: any) => AbstractCrdtDocFactory<any> };
|
|
46
46
|
private readonly _debug: boolean;
|
package/src/PluvRouter.ts
CHANGED
|
@@ -13,12 +13,12 @@ export type MergedRouter<
|
|
|
13
13
|
TPlatform extends AbstractPlatform<any> = AbstractPlatform<any>,
|
|
14
14
|
TAuthorize extends IOAuthorize<any, any, InferRoomContextType<TPlatform>> = BaseIOAuthorize,
|
|
15
15
|
TContext extends JsonObject = {},
|
|
16
|
-
TRoot extends TRouters[0]["
|
|
16
|
+
TRoot extends TRouters[0]["_defs"]["events"] = {},
|
|
17
17
|
> = TRouters extends [
|
|
18
18
|
infer IHead extends PluvRouter<TPlatform, TAuthorize, TContext, any>,
|
|
19
19
|
...infer ITail extends PluvRouter<TPlatform, TAuthorize, TContext, any>[],
|
|
20
20
|
]
|
|
21
|
-
? MergedRouter<ITail, TPlatform, TAuthorize, TContext, TRoot & IHead["
|
|
21
|
+
? MergedRouter<ITail, TPlatform, TAuthorize, TContext, TRoot & IHead["_defs"]["events"]>
|
|
22
22
|
: PluvRouter<TPlatform, TAuthorize, TContext, TRoot>;
|
|
23
23
|
|
|
24
24
|
export class PluvRouter<
|
|
@@ -28,16 +28,16 @@ export class PluvRouter<
|
|
|
28
28
|
TEvents extends PluvRouterEventConfig<TPlatform, TAuthorize, TContext> = {},
|
|
29
29
|
> implements IORouterLike<TEvents>
|
|
30
30
|
{
|
|
31
|
-
readonly
|
|
31
|
+
readonly _defs: { events: TEvents } = { events: {} as TEvents };
|
|
32
32
|
|
|
33
33
|
constructor(events: TEvents) {
|
|
34
|
-
this.
|
|
34
|
+
this._defs = { events };
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
public static merge<TRouters extends PluvRouter<any, any, any, any>[]>(
|
|
38
38
|
...routers: TRouters
|
|
39
39
|
): MergedRouter<TRouters> {
|
|
40
|
-
const events = Object.assign(Object.create(null), ...routers.map((router) => router.
|
|
40
|
+
const events = Object.assign(Object.create(null), ...routers.map((router) => router._defs.events));
|
|
41
41
|
|
|
42
42
|
return new PluvRouter<any, any, any, any>(events) as MergedRouter<TRouters>;
|
|
43
43
|
}
|
package/src/PluvServer.ts
CHANGED
|
@@ -76,8 +76,8 @@ export class PluvServer<
|
|
|
76
76
|
public _listeners: PluvIOListeners<TPlatform, TAuthorize, TContext, TEvents>;
|
|
77
77
|
|
|
78
78
|
public readonly version: string = __PLUV_VERSION as any;
|
|
79
|
-
public readonly _authorize: TAuthorize | null = null;
|
|
80
79
|
|
|
80
|
+
private readonly _authorize: TAuthorize | null = null;
|
|
81
81
|
private readonly _baseRouter: PluvRouter<TPlatform, TAuthorize, TContext, {}> = new PluvRouter({
|
|
82
82
|
$GET_OTHERS: this._procedure.sync((data, { room, session, sessions }) => {
|
|
83
83
|
const currentTime = new Date().getTime();
|
|
@@ -128,7 +128,7 @@ export class PluvServer<
|
|
|
128
128
|
};
|
|
129
129
|
})
|
|
130
130
|
.self(async (data, { context, doc, room }) => {
|
|
131
|
-
const oldState = await this._platform.
|
|
131
|
+
const oldState = await this._platform.persistence.getStorageState(room);
|
|
132
132
|
const update = (data as any)?.update as Maybe<string>;
|
|
133
133
|
|
|
134
134
|
const updates: readonly Maybe<string>[] = [
|
|
@@ -139,12 +139,12 @@ export class PluvServer<
|
|
|
139
139
|
if (updates.some((_update) => !!_update)) {
|
|
140
140
|
const encodedState = doc.batchApplyEncodedState(updates).getEncodedState();
|
|
141
141
|
|
|
142
|
-
await this._platform.
|
|
142
|
+
await this._platform.persistence.setStorageState(room, encodedState);
|
|
143
143
|
|
|
144
144
|
this._listeners.onStorageUpdated({ context, encodedState, room });
|
|
145
145
|
}
|
|
146
146
|
|
|
147
|
-
const state = (await this._platform.
|
|
147
|
+
const state = (await this._platform.persistence.getStorageState(room)) ?? doc.getEncodedState();
|
|
148
148
|
|
|
149
149
|
return { $STORAGE_RECEIVED: { state } };
|
|
150
150
|
}),
|
|
@@ -184,7 +184,7 @@ export class PluvServer<
|
|
|
184
184
|
const updated = update === null ? doc : doc.applyEncodedState({ update });
|
|
185
185
|
const encodedState = updated.getEncodedState();
|
|
186
186
|
|
|
187
|
-
this._platform.
|
|
187
|
+
this._platform.persistence.setStorageState(room, encodedState).then(() => {
|
|
188
188
|
this._listeners.onStorageUpdated({
|
|
189
189
|
context,
|
|
190
190
|
encodedState,
|
|
@@ -202,12 +202,18 @@ export class PluvServer<
|
|
|
202
202
|
private readonly _platform: TPlatform;
|
|
203
203
|
private readonly _router: PluvRouter<TPlatform, TAuthorize, TContext, TEvents>;
|
|
204
204
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
205
|
+
/**
|
|
206
|
+
* @ignore
|
|
207
|
+
* @readonly
|
|
208
|
+
* @deprecated Internal use only. Changes to this will never be marked as breaking.
|
|
209
|
+
*/
|
|
210
|
+
public get _defs() {
|
|
211
|
+
return {
|
|
212
|
+
authorize: this._authorize,
|
|
213
|
+
context: this._context,
|
|
214
|
+
events: this._router._defs.events,
|
|
215
|
+
platform: this._platform,
|
|
216
|
+
};
|
|
211
217
|
}
|
|
212
218
|
|
|
213
219
|
private get _procedure(): PluvProcedure<TPlatform, TAuthorize, TContext, {}, {}> {
|
|
@@ -274,7 +280,7 @@ export class PluvServer<
|
|
|
274
280
|
|
|
275
281
|
await Promise.resolve(onDestroy?.(event));
|
|
276
282
|
await Promise.resolve(this._listeners.onRoomDeleted(event));
|
|
277
|
-
await this._platform.
|
|
283
|
+
await this._platform.persistence.deleteStorageState(room);
|
|
278
284
|
|
|
279
285
|
this._logDebug(`${colors.blue("Deleted room:")} ${room}`);
|
|
280
286
|
},
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export type { BaseUser, EventMessage, EventRecord, IOEventMessage } from "@pluv/types";
|
|
2
|
-
export {
|
|
2
|
+
export { AbstractPersistence } from "./AbstractPersistence";
|
|
3
3
|
export { AbstractPlatform } from "./AbstractPlatform";
|
|
4
4
|
export type {
|
|
5
5
|
AbstractPlatformConfig,
|
package/src/version.generated.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Generated by genversion.
|
|
2
|
-
export const version = '0.
|
|
2
|
+
export const version = '0.25.1'
|