@wxn0brp/gloves-link-server 0.0.4 → 0.0.5

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 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/server';
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
- globalRoom: Room;
15
+ private namespaces;
16
16
  constructor(opts: Partial<Server_Opts>);
17
17
  private saveSocketStatus;
18
- onConnect(handler: (ws: GLSocket) => void): void;
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
- globalRoom = new Room();
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 isAuthenticated = await this.opts.authFn({ headers, url, token });
33
- if (!isAuthenticated) {
34
- this.saveSocketStatus(socketSelfId, 401);
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
- this.globalRoom.join(glSocket);
43
- this.onConnectEvent(glSocket);
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
- glSocket.leaveAllRooms();
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
- this.initStatusTemp[socketSelfId] = status;
74
+ const id = namespace + "-" + socketSelfId;
75
+ this.initStatusTemp[id] = status;
66
76
  setTimeout(() => {
67
- delete this.initStatusTemp[socketSelfId];
77
+ delete this.initStatusTemp[id];
68
78
  }, 10_000);
69
79
  }
70
- onConnect(handler) {
71
- this.onConnectEvent = handler;
72
- }
73
- broadcast(event, ...args) {
74
- this.globalRoom.emit(event, ...args);
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 status = this.initStatusTemp[id];
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<[never]>;
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
@@ -4,6 +4,8 @@ export declare class GLSocket {
4
4
  ws: WebSocket;
5
5
  server: GlovesLinkServer;
6
6
  id: string;
7
+ user: any;
8
+ namespace: string;
7
9
  ackIdCounter: number;
8
10
  ackCallbacks: Map<number, Function>;
9
11
  logs: boolean;
package/dist/socket.js CHANGED
@@ -1,8 +1,10 @@
1
- import { joinSocketToRoom, leaveAllSocketFromRoom, leaveSocketFromRoom } from "./room.js";
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
- leaveAllSocketFromRoom(this);
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 | Promise<boolean>;
24
+ export type AuthFn = (data: Server_Auth_Opts) => (Promise<object | boolean> | object | boolean);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wxn0brp/gloves-link-server",
3
- "version": "0.0.4",
3
+ "version": "0.0.5",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "author": "wxn0brP",