@pluv/io 0.20.0 → 0.21.0
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 +72 -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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pluv/io",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.0",
|
|
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.6.3",
|
|
22
22
|
"kleur": "^4.1.5",
|
|
23
23
|
"wonka": "^6.3.4",
|
|
24
|
-
"@pluv/crdt": "^0.
|
|
25
|
-
"@pluv/types": "^0.
|
|
24
|
+
"@pluv/crdt": "^0.21.0",
|
|
25
|
+
"@pluv/types": "^0.21.0"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"eslint": "^8.57.0",
|
|
29
29
|
"genversion": "^3.2.0",
|
|
30
|
-
"tsup": "^8.
|
|
31
|
-
"typescript": "^5.4
|
|
32
|
-
"@pluv/tsconfig": "^0.
|
|
33
|
-
"eslint-config-pluv": "^0.
|
|
30
|
+
"tsup": "^8.2.4",
|
|
31
|
+
"typescript": "^5.5.4",
|
|
32
|
+
"@pluv/tsconfig": "^0.21.0",
|
|
33
|
+
"eslint-config-pluv": "^0.21.0"
|
|
34
34
|
},
|
|
35
35
|
"scripts": {
|
|
36
36
|
"build": "pnpm run version && tsup src/index.ts --format esm,cjs --dts",
|
package/src/AbstractPlatform.ts
CHANGED
|
@@ -1,48 +1,92 @@
|
|
|
1
|
-
import { AbstractPersistance } from "./AbstractPersistance";
|
|
1
|
+
import type { AbstractPersistance } from "./AbstractPersistance";
|
|
2
2
|
import type { AbstractPubSub } from "./AbstractPubSub";
|
|
3
|
-
import type { AbstractWebSocket,
|
|
3
|
+
import type { AbstractWebSocket, InferWebSocketSource } from "./AbstractWebSocket";
|
|
4
4
|
import { Persistance } from "./Persistance";
|
|
5
5
|
import { PubSub } from "./PubSub";
|
|
6
|
+
import type { WebSocketSerializedState } from "./types";
|
|
7
|
+
|
|
8
|
+
export type WebSocketRegistrationMode = "attached" | "detached";
|
|
6
9
|
|
|
7
10
|
export type InferPlatformWebSocketType<TPlatform extends AbstractPlatform> =
|
|
8
|
-
TPlatform extends AbstractPlatform<infer
|
|
11
|
+
TPlatform extends AbstractPlatform<infer IAbstractWebSocket> ? IAbstractWebSocket : never;
|
|
9
12
|
|
|
10
|
-
export type
|
|
11
|
-
TPlatform extends AbstractPlatform<
|
|
13
|
+
export type InferPlatformWebSocketSource<TPlatform> =
|
|
14
|
+
TPlatform extends AbstractPlatform<infer IAbstractWebSocket> ? InferWebSocketSource<IAbstractWebSocket> : never;
|
|
12
15
|
|
|
13
|
-
export type
|
|
14
|
-
TPlatform extends AbstractPlatform<any,
|
|
16
|
+
export type InferPlatformContextType<TPlatform extends AbstractPlatform> =
|
|
17
|
+
TPlatform extends AbstractPlatform<any, infer IPlatformContext> ? IPlatformContext : never;
|
|
15
18
|
|
|
16
|
-
export type
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
pubSub: AbstractPubSub;
|
|
21
|
-
};
|
|
19
|
+
export type InferRoomContextType<TPlatform extends AbstractPlatform> =
|
|
20
|
+
TPlatform extends AbstractPlatform<any, infer IPlatformContext, infer IRoomContext>
|
|
21
|
+
? IPlatformContext & IRoomContext
|
|
22
|
+
: never;
|
|
22
23
|
|
|
23
|
-
export type
|
|
24
|
+
export type AbstractPlatformConfig<
|
|
25
|
+
TPlatformContext extends Record<string, any> = {},
|
|
26
|
+
TRoomContext extends Record<string, any> = {},
|
|
27
|
+
> = {
|
|
28
|
+
context?: TPlatformContext & TRoomContext;
|
|
29
|
+
persistance?: AbstractPersistance;
|
|
30
|
+
pubSub?: AbstractPubSub;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export interface ConvertWebSocketConfig {
|
|
34
|
+
room: string;
|
|
35
|
+
}
|
|
24
36
|
|
|
25
37
|
export abstract class AbstractPlatform<
|
|
26
|
-
TWebSocket =
|
|
27
|
-
|
|
38
|
+
TWebSocket extends AbstractWebSocket = AbstractWebSocket,
|
|
39
|
+
TPlatformContext extends Record<string, any> = {},
|
|
28
40
|
TRoomContext extends Record<string, any> = {},
|
|
29
41
|
> {
|
|
30
|
-
|
|
42
|
+
private _initialized: boolean = false;
|
|
43
|
+
|
|
44
|
+
readonly _ioContext: TPlatformContext | undefined;
|
|
31
45
|
readonly _roomContext: TRoomContext | undefined;
|
|
32
46
|
|
|
47
|
+
abstract readonly _registrationMode: WebSocketRegistrationMode;
|
|
48
|
+
|
|
33
49
|
public persistance: AbstractPersistance;
|
|
34
50
|
public pubSub: AbstractPubSub;
|
|
35
51
|
|
|
36
|
-
constructor(config: AbstractPlatformConfig = {}) {
|
|
37
|
-
const { persistance, pubSub } = config;
|
|
52
|
+
constructor(config: AbstractPlatformConfig<TPlatformContext, TRoomContext> = {}) {
|
|
53
|
+
const { context, persistance, pubSub } = config;
|
|
54
|
+
|
|
55
|
+
context && (this._ioContext = context);
|
|
56
|
+
context && (this._roomContext = context);
|
|
38
57
|
|
|
39
58
|
this.persistance = persistance ?? new Persistance();
|
|
40
59
|
this.pubSub = pubSub ?? new PubSub();
|
|
41
60
|
}
|
|
42
61
|
|
|
43
|
-
public abstract
|
|
62
|
+
public abstract acceptWebSocket(webSocket: AbstractWebSocket): Promise<void>;
|
|
63
|
+
|
|
64
|
+
public abstract convertWebSocket(
|
|
65
|
+
webSocket: InferWebSocketSource<TWebSocket>,
|
|
66
|
+
config: ConvertWebSocketConfig,
|
|
67
|
+
): AbstractWebSocket;
|
|
68
|
+
|
|
69
|
+
public abstract getLastPing(webSocket: AbstractWebSocket): number | null;
|
|
70
|
+
|
|
71
|
+
public abstract getSerializedState(webSocket: AbstractWebSocket): WebSocketSerializedState | null;
|
|
72
|
+
|
|
73
|
+
public abstract getSessionId(webSocket: InferWebSocketSource<TWebSocket>): string | null;
|
|
74
|
+
|
|
75
|
+
public abstract getWebSockets(): readonly InferWebSocketSource<TWebSocket>[];
|
|
76
|
+
|
|
77
|
+
public abstract initialize(config: AbstractPlatformConfig<TPlatformContext, TRoomContext>): this;
|
|
44
78
|
|
|
45
79
|
public abstract parseData(data: string | ArrayBuffer): Record<string, any>;
|
|
46
80
|
|
|
47
81
|
public abstract randomUUID(): string;
|
|
82
|
+
|
|
83
|
+
public abstract setSerializedState(webSocket: AbstractWebSocket, state: WebSocketSerializedState): void;
|
|
84
|
+
|
|
85
|
+
protected _initialize(): this {
|
|
86
|
+
if (this._initialized) throw new Error("Platform is already initialized");
|
|
87
|
+
|
|
88
|
+
this._initialized = true;
|
|
89
|
+
|
|
90
|
+
return this;
|
|
91
|
+
}
|
|
48
92
|
}
|
package/src/AbstractWebSocket.ts
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
1
|
+
import type {
|
|
2
|
+
BaseUser,
|
|
3
|
+
InferIOAuthorizeUser,
|
|
4
|
+
IOAuthorize,
|
|
5
|
+
IOEventMessage,
|
|
6
|
+
JsonObject,
|
|
7
|
+
MaybePromise,
|
|
8
|
+
} from "@pluv/types";
|
|
9
|
+
import type { AbstractPersistance } from "./AbstractPersistance";
|
|
10
|
+
import type { WebSocketSerializedState, WebSocketSession } from "./types";
|
|
3
11
|
|
|
4
12
|
export type AbstractEvent = {};
|
|
5
13
|
|
|
@@ -14,7 +22,7 @@ export type AbstractMessageEvent<T = any> = AbstractEvent & {
|
|
|
14
22
|
|
|
15
23
|
export type AbstractErrorEvent = AbstractEvent & {
|
|
16
24
|
error: unknown;
|
|
17
|
-
message
|
|
25
|
+
message?: string;
|
|
18
26
|
};
|
|
19
27
|
|
|
20
28
|
export interface AbstractEventMap {
|
|
@@ -28,6 +36,7 @@ export type EventType = keyof AbstractEventMap;
|
|
|
28
36
|
export interface AbstractWebSocketHandleErrorParams {
|
|
29
37
|
error: unknown;
|
|
30
38
|
message?: string;
|
|
39
|
+
room: string;
|
|
31
40
|
session?: WebSocketSession<any>;
|
|
32
41
|
}
|
|
33
42
|
|
|
@@ -35,13 +44,15 @@ export type AbstractListener<TType extends keyof AbstractEventMap> = (
|
|
|
35
44
|
event: AbstractEventMap[TType],
|
|
36
45
|
) => MaybePromise<void>;
|
|
37
46
|
|
|
47
|
+
export type InferWebSocketSource<TAbstractWebSocket extends AbstractWebSocket> =
|
|
48
|
+
TAbstractWebSocket extends AbstractWebSocket<infer IWebSocket> ? IWebSocket : never;
|
|
49
|
+
|
|
38
50
|
export interface AbstractWebSocketConfig {
|
|
51
|
+
persistance: AbstractPersistance;
|
|
39
52
|
room: string;
|
|
40
|
-
sessionId: string;
|
|
41
|
-
userId: string | null;
|
|
42
53
|
}
|
|
43
54
|
|
|
44
|
-
export abstract class AbstractWebSocket {
|
|
55
|
+
export abstract class AbstractWebSocket<TWebSocket = any> {
|
|
45
56
|
/** The connection is not yet open. */
|
|
46
57
|
public readonly CONNECTING = 0;
|
|
47
58
|
/** The connection is open and ready to communicate. */
|
|
@@ -51,16 +62,23 @@ export abstract class AbstractWebSocket {
|
|
|
51
62
|
/** The connection is closed. */
|
|
52
63
|
public readonly CLOSED = 3;
|
|
53
64
|
|
|
54
|
-
public
|
|
55
|
-
public
|
|
65
|
+
public readonly persistance: AbstractPersistance;
|
|
66
|
+
public readonly room: string;
|
|
67
|
+
public readonly webSocket: TWebSocket;
|
|
56
68
|
|
|
69
|
+
private _user: BaseUser | null = null;
|
|
70
|
+
|
|
71
|
+
public abstract set presence(presence: JsonObject | null);
|
|
57
72
|
public abstract get readyState(): 0 | 1 | 2 | 3;
|
|
73
|
+
public abstract get sessionId(): string;
|
|
74
|
+
public abstract get state(): WebSocketSerializedState;
|
|
58
75
|
|
|
59
|
-
constructor(config: AbstractWebSocketConfig) {
|
|
60
|
-
const {
|
|
76
|
+
constructor(webSocket: TWebSocket, config: AbstractWebSocketConfig) {
|
|
77
|
+
const { persistance, room } = config;
|
|
61
78
|
|
|
79
|
+
this.persistance = persistance;
|
|
62
80
|
this.room = room;
|
|
63
|
-
this.
|
|
81
|
+
this.webSocket = webSocket;
|
|
64
82
|
}
|
|
65
83
|
|
|
66
84
|
/**
|
|
@@ -77,21 +95,37 @@ export abstract class AbstractWebSocket {
|
|
|
77
95
|
|
|
78
96
|
public abstract close(code?: number | undefined, reason?: string | undefined): void;
|
|
79
97
|
|
|
80
|
-
public abstract initialize(): Promise<() => void>;
|
|
81
|
-
|
|
82
98
|
public abstract send(message: ArrayBuffer | ArrayBufferView | string): void;
|
|
83
99
|
|
|
84
100
|
public abstract terminate(): void;
|
|
85
101
|
|
|
102
|
+
public async getSession<TAuthorize extends IOAuthorize<any, any, any>>(): Promise<WebSocketSession<TAuthorize>> {
|
|
103
|
+
const sessionId = this.sessionId;
|
|
104
|
+
const state = this.state;
|
|
105
|
+
const room = state.room;
|
|
106
|
+
|
|
107
|
+
const user = this._user ?? (await this.persistance.getUser(room, sessionId));
|
|
108
|
+
|
|
109
|
+
this._user = user as BaseUser;
|
|
110
|
+
|
|
111
|
+
return {
|
|
112
|
+
...state,
|
|
113
|
+
id: sessionId,
|
|
114
|
+
user: user as InferIOAuthorizeUser<TAuthorize>,
|
|
115
|
+
webSocket: this,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
86
119
|
public handleError(params: AbstractWebSocketHandleErrorParams): void {
|
|
87
|
-
const { error, message
|
|
120
|
+
const { error, message: _message, room, session } = params;
|
|
88
121
|
|
|
89
|
-
const
|
|
122
|
+
const message = error instanceof Error ? error.message : "Unexpected error";
|
|
123
|
+
const stack: string | null = error instanceof Error ? (error.stack ?? null) : null;
|
|
90
124
|
|
|
91
125
|
return this.sendMessage({
|
|
92
126
|
connectionId: session?.id ?? null,
|
|
93
127
|
data: { message, stack },
|
|
94
|
-
room
|
|
128
|
+
room,
|
|
95
129
|
type: "$ERROR",
|
|
96
130
|
user: session?.user ?? null,
|
|
97
131
|
});
|