@wxn0brp/gloves-link-server 0.0.4 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.d.ts +5 -7
- package/dist/index.js +42 -26
- package/dist/namespace.d.ts +17 -0
- package/dist/namespace.js +30 -0
- package/dist/room.d.ts +1 -1
- package/dist/socket.d.ts +2 -0
- package/dist/socket.js +6 -2
- package/dist/types.d.ts +5 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -28,7 +28,7 @@ npm i @wxn0brp/gloves-link-server @wxn0brp/falcon-frame
|
|
|
28
28
|
## Usage
|
|
29
29
|
|
|
30
30
|
```typescript
|
|
31
|
-
import { GlovesLinkServer } from '@wxn0brp/gloves-link
|
|
31
|
+
import { GlovesLinkServer } from '@wxn0brp/gloves-link-server';
|
|
32
32
|
import { FalconFrame } from '@wxn0brp/falcon-frame';
|
|
33
33
|
|
|
34
34
|
const app = new FalconFrame();
|
package/dist/index.d.ts
CHANGED
|
@@ -3,23 +3,21 @@ import { Server_Opts } from "./types.js";
|
|
|
3
3
|
import { GLSocket } from "./socket.js";
|
|
4
4
|
import FalconFrame from "@wxn0brp/falcon-frame";
|
|
5
5
|
import { Room, Rooms } from "./room.js";
|
|
6
|
+
import { Namespace } from "./namespace.js";
|
|
6
7
|
export declare class GlovesLinkServer {
|
|
7
8
|
wss: WebSocketServer;
|
|
8
|
-
private onConnectEvent;
|
|
9
9
|
logs: boolean;
|
|
10
10
|
opts: Server_Opts;
|
|
11
11
|
initStatusTemp: {
|
|
12
12
|
[key: string]: number;
|
|
13
13
|
};
|
|
14
14
|
rooms: Rooms;
|
|
15
|
-
|
|
15
|
+
private namespaces;
|
|
16
16
|
constructor(opts: Partial<Server_Opts>);
|
|
17
17
|
private saveSocketStatus;
|
|
18
|
-
|
|
19
|
-
broadcast(event: string, ...args: any[]): void;
|
|
18
|
+
of(path: string): Namespace;
|
|
20
19
|
broadcastRoom(roomName: string, event: string, ...args: any[]): void;
|
|
21
|
-
broadcastWithoutSelf(socket: GLSocket, event: string, ...args: any[]): void;
|
|
22
20
|
room(name: string): Room;
|
|
23
|
-
falconFrame(app: FalconFrame, clientDir?: string): void;
|
|
21
|
+
falconFrame(app: FalconFrame, clientDir?: string | false): void;
|
|
24
22
|
}
|
|
25
|
-
export { GLSocket };
|
|
23
|
+
export { GLSocket, Namespace, Server_Opts };
|
package/dist/index.js
CHANGED
|
@@ -2,19 +2,18 @@ import { WebSocketServer } from "ws";
|
|
|
2
2
|
import { GLSocket } from "./socket.js";
|
|
3
3
|
import { Router } from "@wxn0brp/falcon-frame";
|
|
4
4
|
import { Room } from "./room.js";
|
|
5
|
+
import { Namespace } from "./namespace.js";
|
|
5
6
|
export class GlovesLinkServer {
|
|
6
7
|
wss;
|
|
7
|
-
onConnectEvent;
|
|
8
8
|
logs = false;
|
|
9
9
|
opts;
|
|
10
10
|
initStatusTemp = {};
|
|
11
11
|
rooms = new Map();
|
|
12
|
-
|
|
12
|
+
namespaces = new Map();
|
|
13
13
|
constructor(opts) {
|
|
14
14
|
this.opts = {
|
|
15
15
|
server: null,
|
|
16
16
|
logs: false,
|
|
17
|
-
authFn: () => true,
|
|
18
17
|
...opts
|
|
19
18
|
};
|
|
20
19
|
if (!this.opts?.server) {
|
|
@@ -29,9 +28,17 @@ export class GlovesLinkServer {
|
|
|
29
28
|
const url = new URL(request.url, `http://${request.headers.host}`);
|
|
30
29
|
const token = url.searchParams.get("token");
|
|
31
30
|
socketSelfId = url.searchParams.get("id");
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
const { pathname } = url;
|
|
32
|
+
const namespace = this.namespaces.get(pathname);
|
|
33
|
+
if (!namespace) {
|
|
34
|
+
this.saveSocketStatus(socketSelfId, pathname, 404);
|
|
35
|
+
socket.write("HTTP/1.1 404 Not Found\r\n\r\n");
|
|
36
|
+
socket.destroy();
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const authResult = await namespace.authFn({ headers, url, token, request, socket, head });
|
|
40
|
+
if (!authResult) {
|
|
41
|
+
this.saveSocketStatus(socketSelfId, pathname, 401);
|
|
35
42
|
socket.write("HTTP/1.1 401 Unauthorized\r\n\r\n");
|
|
36
43
|
socket.destroy();
|
|
37
44
|
return;
|
|
@@ -39,12 +46,14 @@ export class GlovesLinkServer {
|
|
|
39
46
|
this.wss.handleUpgrade(request, socket, head, (ws) => {
|
|
40
47
|
const glSocket = new GLSocket(ws, this);
|
|
41
48
|
glSocket.logs = this.logs;
|
|
42
|
-
|
|
43
|
-
|
|
49
|
+
if (typeof authResult === "object" && authResult !== null)
|
|
50
|
+
glSocket.user = authResult;
|
|
51
|
+
glSocket.namespace = pathname;
|
|
52
|
+
namespace.room.join(glSocket);
|
|
53
|
+
namespace.onConnectHandler(glSocket);
|
|
44
54
|
ws.on("close", () => {
|
|
45
55
|
glSocket.handlers?.disconnect?.();
|
|
46
|
-
|
|
47
|
-
this.globalRoom.leave(glSocket);
|
|
56
|
+
namespace.room.leave(glSocket);
|
|
48
57
|
});
|
|
49
58
|
});
|
|
50
59
|
}
|
|
@@ -53,25 +62,28 @@ export class GlovesLinkServer {
|
|
|
53
62
|
console.error("[GlovesLinkServer]", err);
|
|
54
63
|
if (this.logs)
|
|
55
64
|
console.warn("[auth] Error during authentication:", err);
|
|
56
|
-
this.saveSocketStatus(socketSelfId, 500);
|
|
65
|
+
this.saveSocketStatus(socketSelfId, "/", 500);
|
|
57
66
|
socket.write("HTTP/1.1 500 Internal Server Error\r\n\r\n");
|
|
58
67
|
socket.destroy();
|
|
59
68
|
}
|
|
60
69
|
});
|
|
61
70
|
}
|
|
62
|
-
saveSocketStatus(socketSelfId, status) {
|
|
71
|
+
saveSocketStatus(socketSelfId, namespace, status) {
|
|
63
72
|
if (!socketSelfId)
|
|
64
73
|
return;
|
|
65
|
-
|
|
74
|
+
const id = namespace + "-" + socketSelfId;
|
|
75
|
+
this.initStatusTemp[id] = status;
|
|
66
76
|
setTimeout(() => {
|
|
67
|
-
delete this.initStatusTemp[
|
|
77
|
+
delete this.initStatusTemp[id];
|
|
68
78
|
}, 10_000);
|
|
69
79
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
80
|
+
of(path) {
|
|
81
|
+
let namespace = this.namespaces.get(path);
|
|
82
|
+
if (!namespace) {
|
|
83
|
+
namespace = new Namespace(path, this);
|
|
84
|
+
this.namespaces.set(path, namespace);
|
|
85
|
+
}
|
|
86
|
+
return namespace;
|
|
75
87
|
}
|
|
76
88
|
broadcastRoom(roomName, event, ...args) {
|
|
77
89
|
const room = this.room(roomName);
|
|
@@ -79,24 +91,24 @@ export class GlovesLinkServer {
|
|
|
79
91
|
return;
|
|
80
92
|
room.emit(event, ...args);
|
|
81
93
|
}
|
|
82
|
-
broadcastWithoutSelf(socket, event, ...args) {
|
|
83
|
-
this.globalRoom.emitWithoutSelf(socket, event, ...args);
|
|
84
|
-
}
|
|
85
94
|
room(name) {
|
|
86
95
|
return this.rooms.get(name) || this.rooms.set(name, new Room()).get(name);
|
|
87
96
|
}
|
|
88
97
|
falconFrame(app, clientDir) {
|
|
89
|
-
clientDir = clientDir || "node_modules/@wxn0brp/gloves-link-client/dist/";
|
|
90
98
|
const router = new Router();
|
|
91
99
|
app.use("/gloves-link", router);
|
|
92
|
-
router.static("/", clientDir);
|
|
93
100
|
router.get("/status", (req, res) => {
|
|
94
101
|
const id = req.query.id;
|
|
95
102
|
if (!id) {
|
|
96
103
|
res.status(400).json({ err: true, msg: "No id provided" });
|
|
97
104
|
return;
|
|
98
105
|
}
|
|
99
|
-
const
|
|
106
|
+
const path = req.query.path;
|
|
107
|
+
if (!path) {
|
|
108
|
+
res.status(400).json({ err: true, msg: "No path provided" });
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
const status = this.initStatusTemp[path + "-" + id];
|
|
100
112
|
if (status === undefined) {
|
|
101
113
|
res.status(404).json({ err: true, msg: "Socket not found" });
|
|
102
114
|
return;
|
|
@@ -104,10 +116,14 @@ export class GlovesLinkServer {
|
|
|
104
116
|
res.json({ status });
|
|
105
117
|
delete this.initStatusTemp[id];
|
|
106
118
|
});
|
|
119
|
+
if (clientDir === false)
|
|
120
|
+
return;
|
|
121
|
+
clientDir = clientDir || "node_modules/@wxn0brp/gloves-link-client/dist/";
|
|
122
|
+
router.static("/", clientDir);
|
|
107
123
|
router.get("/*", (req, res) => {
|
|
108
124
|
res.redirect("/gloves-link/GlovesLinkClient.js");
|
|
109
125
|
res.end();
|
|
110
126
|
});
|
|
111
127
|
}
|
|
112
128
|
}
|
|
113
|
-
export { GLSocket };
|
|
129
|
+
export { GLSocket, Namespace };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { AuthFn } from "./types.js";
|
|
2
|
+
import { GLSocket } from "./socket.js";
|
|
3
|
+
import { Room } from "./room.js";
|
|
4
|
+
import { GlovesLinkServer } from "./index.js";
|
|
5
|
+
export declare class Namespace {
|
|
6
|
+
name: string;
|
|
7
|
+
private server;
|
|
8
|
+
private onConnectEvent;
|
|
9
|
+
authFn: AuthFn;
|
|
10
|
+
room: Room;
|
|
11
|
+
constructor(name: string, server: GlovesLinkServer);
|
|
12
|
+
onConnect(handler: (ws: GLSocket) => void): this;
|
|
13
|
+
auth(authFn: AuthFn): this;
|
|
14
|
+
get onConnectHandler(): (ws: GLSocket) => void;
|
|
15
|
+
emit(event: string, ...args: any[]): void;
|
|
16
|
+
emitWithoutSelf(socket: GLSocket, event: string, ...args: any[]): void;
|
|
17
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export class Namespace {
|
|
2
|
+
name;
|
|
3
|
+
server;
|
|
4
|
+
onConnectEvent = () => { };
|
|
5
|
+
authFn = () => false;
|
|
6
|
+
room;
|
|
7
|
+
constructor(name, server) {
|
|
8
|
+
this.name = name;
|
|
9
|
+
this.server = server;
|
|
10
|
+
const roomName = `gls-namespace-${name}`;
|
|
11
|
+
this.room = this.server.room(roomName);
|
|
12
|
+
}
|
|
13
|
+
onConnect(handler) {
|
|
14
|
+
this.onConnectEvent = handler;
|
|
15
|
+
return this;
|
|
16
|
+
}
|
|
17
|
+
auth(authFn) {
|
|
18
|
+
this.authFn = authFn;
|
|
19
|
+
return this;
|
|
20
|
+
}
|
|
21
|
+
get onConnectHandler() {
|
|
22
|
+
return this.onConnectEvent;
|
|
23
|
+
}
|
|
24
|
+
emit(event, ...args) {
|
|
25
|
+
this.room.emit(event, ...args);
|
|
26
|
+
}
|
|
27
|
+
emitWithoutSelf(socket, event, ...args) {
|
|
28
|
+
this.room.emitWithoutSelf(socket, event, ...args);
|
|
29
|
+
}
|
|
30
|
+
}
|
package/dist/room.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { GLSocket } from "./socket.js";
|
|
|
3
3
|
export type Rooms = Map<string, Room>;
|
|
4
4
|
export declare class Room {
|
|
5
5
|
clients: Set<GLSocket>;
|
|
6
|
-
eventEmitter: EventEmitter<
|
|
6
|
+
eventEmitter: EventEmitter<any>;
|
|
7
7
|
join(socket: GLSocket): void;
|
|
8
8
|
leave(socket: GLSocket): void;
|
|
9
9
|
leaveAll(): void;
|
package/dist/socket.d.ts
CHANGED
package/dist/socket.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { joinSocketToRoom,
|
|
1
|
+
import { joinSocketToRoom, leaveSocketFromRoom } from "./room.js";
|
|
2
2
|
export class GLSocket {
|
|
3
3
|
ws;
|
|
4
4
|
server;
|
|
5
5
|
id;
|
|
6
|
+
user = {};
|
|
7
|
+
namespace;
|
|
6
8
|
ackIdCounter = 1;
|
|
7
9
|
ackCallbacks = new Map();
|
|
8
10
|
logs = false;
|
|
@@ -85,7 +87,9 @@ export class GLSocket {
|
|
|
85
87
|
this.rooms.delete(roomName);
|
|
86
88
|
}
|
|
87
89
|
leaveAllRooms() {
|
|
88
|
-
|
|
90
|
+
for (const roomName of this.rooms) {
|
|
91
|
+
leaveSocketFromRoom(this, roomName);
|
|
92
|
+
}
|
|
89
93
|
this.rooms.clear();
|
|
90
94
|
}
|
|
91
95
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import http from "http";
|
|
2
|
+
import Stream from "stream";
|
|
2
3
|
export interface Server_Opts {
|
|
3
4
|
server: http.Server;
|
|
4
5
|
logs: boolean;
|
|
5
|
-
authFn: AuthFn;
|
|
6
6
|
}
|
|
7
7
|
export interface Server_DataEvent {
|
|
8
8
|
evt: string;
|
|
@@ -17,5 +17,8 @@ export interface Server_Auth_Opts {
|
|
|
17
17
|
headers: http.IncomingHttpHeaders;
|
|
18
18
|
url: URL;
|
|
19
19
|
token?: string;
|
|
20
|
+
request: http.IncomingMessage;
|
|
21
|
+
socket: Stream.Duplex;
|
|
22
|
+
head: Buffer<ArrayBufferLike>;
|
|
20
23
|
}
|
|
21
|
-
export type AuthFn = (data: Server_Auth_Opts) => boolean |
|
|
24
|
+
export type AuthFn = (data: Server_Auth_Opts) => (Promise<object | boolean> | object | boolean);
|