@bool-ts/core 1.7.16 → 1.8.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/.prettierrc +1 -1
- package/__test/controller.ts +1 -1
- package/__test/index.ts +4 -1
- package/__test/module.ts +3 -1
- package/__test/tsconfig.json +109 -0
- package/__test/webSocket.ts +37 -0
- package/__test/webSocketClient.ts +23 -0
- package/dist/decorators/controller.d.ts +3 -3
- package/dist/decorators/controller.js +1 -2
- package/dist/decorators/dispatcher.d.ts +1 -1
- package/dist/decorators/http.d.ts +12 -12
- package/dist/decorators/http.js +1 -1
- package/dist/decorators/index.d.ts +5 -0
- package/dist/decorators/index.js +3 -0
- package/dist/decorators/module.d.ts +3 -1
- package/dist/decorators/module.js +9 -2
- package/dist/decorators/webSocket.d.ts +25 -0
- package/dist/decorators/webSocket.js +40 -0
- package/dist/decorators/webSocketArguments.d.ts +22 -0
- package/dist/decorators/webSocketArguments.js +49 -0
- package/dist/decorators/webSocketEvent.d.ts +15 -0
- package/dist/decorators/webSocketEvent.js +24 -0
- package/dist/decorators/zodSchema.js +3 -3
- package/dist/entities/{route.d.ts → httpRoute.d.ts} +12 -12
- package/dist/entities/{route.js → httpRoute.js} +27 -25
- package/dist/entities/httpRouter.d.ts +10 -0
- package/dist/entities/{router.js → httpRouter.js} +7 -5
- package/dist/entities/{routerGroup.d.ts → httpRouterGroup.d.ts} +4 -4
- package/dist/entities/{routerGroup.js → httpRouterGroup.js} +1 -1
- package/dist/entities/index.d.ts +7 -4
- package/dist/entities/index.js +6 -3
- package/dist/entities/webSocketRoute.d.ts +10 -0
- package/dist/entities/webSocketRoute.js +15 -0
- package/dist/entities/webSocketRouter.d.ts +31 -0
- package/dist/entities/webSocketRouter.js +54 -0
- package/dist/entities/webSocketRouterGroup.d.ts +25 -0
- package/dist/entities/webSocketRouterGroup.js +51 -0
- package/dist/hooks/factory.d.ts +1 -39
- package/dist/hooks/factory.js +450 -76
- package/dist/hooks/injector.js +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/interfaces/index.d.ts +1 -0
- package/dist/interfaces/webSocket.d.ts +2 -0
- package/dist/interfaces/webSocket.js +1 -0
- package/dist/keys/index.d.ts +10 -1
- package/dist/keys/index.js +21 -12
- package/dist/ultils/colors.d.ts +30 -0
- package/dist/ultils/colors.js +41 -0
- package/dist/ultils/index.d.ts +2 -0
- package/dist/ultils/index.js +2 -0
- package/dist/ultils/socket.d.ts +1 -0
- package/dist/ultils/socket.js +7 -0
- package/package.json +8 -7
- package/src/decorators/controller.ts +5 -4
- package/src/decorators/dispatcher.ts +2 -1
- package/src/decorators/guard.ts +1 -0
- package/src/decorators/http.ts +3 -3
- package/src/decorators/index.ts +10 -0
- package/src/decorators/middleware.ts +1 -0
- package/src/decorators/module.ts +14 -3
- package/src/decorators/webSocket.ts +81 -0
- package/src/decorators/webSocketArguments.ts +144 -0
- package/src/decorators/webSocketEvent.ts +56 -0
- package/src/decorators/zodSchema.ts +5 -3
- package/src/entities/{route.ts → httpRoute.ts} +71 -57
- package/src/entities/{router.ts → httpRouter.ts} +8 -6
- package/src/entities/{routerGroup.ts → httpRouterGroup.ts} +4 -4
- package/src/entities/index.ts +7 -4
- package/src/entities/webSocketRoute.ts +27 -0
- package/src/entities/webSocketRouter.ts +64 -0
- package/src/entities/webSocketRouterGroup.ts +64 -0
- package/src/hooks/factory.ts +704 -112
- package/src/hooks/injector.ts +2 -2
- package/src/index.ts +1 -1
- package/src/interfaces/index.ts +1 -0
- package/src/interfaces/webSocket.ts +1 -0
- package/src/keys/index.ts +22 -12
- package/src/ultils/colors.ts +56 -0
- package/src/ultils/index.ts +3 -1
- package/src/ultils/socket.ts +9 -0
- package/test.ts +0 -0
- package/tsconfig.json +3 -2
- package/bun.lockb +0 -0
- package/dist/entities/router.d.ts +0 -10
package/dist/hooks/injector.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import "reflect-metadata";
|
|
2
|
-
import { controllerKey, dispatcherKey, guardKey, injectableKey, injectKey, middlewareKey } from "../keys";
|
|
2
|
+
import { controllerKey, dispatcherKey, guardKey, injectableKey, injectKey, middlewareKey, webSocketKey } from "../keys";
|
|
3
3
|
export class Injector {
|
|
4
4
|
_mapper = new Map();
|
|
5
5
|
/**
|
|
@@ -14,7 +14,7 @@ export class Injector {
|
|
|
14
14
|
return undefined;
|
|
15
15
|
}
|
|
16
16
|
const ownMetadataKeys = Reflect.getMetadataKeys(definition);
|
|
17
|
-
if (![injectableKey, controllerKey, middlewareKey, guardKey, dispatcherKey].some((value) => ownMetadataKeys.includes(value))) {
|
|
17
|
+
if (![injectableKey, controllerKey, middlewareKey, guardKey, dispatcherKey, webSocketKey].some((value) => ownMetadataKeys.includes(value))) {
|
|
18
18
|
throw Error("Missing dependency declaration, please check @Injectable() used on dependency(ies).");
|
|
19
19
|
}
|
|
20
20
|
// Initialize dependencies injection
|
package/dist/index.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/keys/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export declare const argumentsKey: unique symbol;
|
|
2
|
+
export declare const webSocketEventArgumentsKey: unique symbol;
|
|
2
3
|
export declare const configKey: unique symbol;
|
|
3
4
|
export declare const controllerKey: unique symbol;
|
|
4
5
|
export declare const dispatcherKey: unique symbol;
|
|
@@ -8,7 +9,15 @@ export declare const injectKey: unique symbol;
|
|
|
8
9
|
export declare const injectableKey: unique symbol;
|
|
9
10
|
export declare const middlewareKey: unique symbol;
|
|
10
11
|
export declare const moduleKey: unique symbol;
|
|
11
|
-
export declare const
|
|
12
|
+
export declare const zodSchemaKey: unique symbol;
|
|
13
|
+
export declare const webSocketKey: unique symbol;
|
|
14
|
+
export declare const webSocketEventKey: unique symbol;
|
|
15
|
+
export declare const webSocketServerArgsKey: unique symbol;
|
|
16
|
+
export declare const webSocketConnectionArgsKey: unique symbol;
|
|
17
|
+
export declare const webSocketMessageArgsKey: unique symbol;
|
|
18
|
+
export declare const webSocketCloseCodeArgsKey: unique symbol;
|
|
19
|
+
export declare const webSocketCloseReasonArgsKey: unique symbol;
|
|
20
|
+
export declare const httpServerArgsKey: unique symbol;
|
|
12
21
|
export declare const requestHeadersArgsKey: unique symbol;
|
|
13
22
|
export declare const requestHeaderArgsKey: unique symbol;
|
|
14
23
|
export declare const requestBodyArgsKey: unique symbol;
|
package/dist/keys/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export const argumentsKey = Symbol("__bool:arguments__");
|
|
2
|
+
export const webSocketEventArgumentsKey = Symbol("__bool:webSocketEventArguments__");
|
|
2
3
|
export const configKey = Symbol("__bool:config__");
|
|
3
4
|
export const controllerKey = Symbol("__bool:controller__");
|
|
4
5
|
export const dispatcherKey = Symbol("__bool:dispatcher__");
|
|
@@ -8,15 +9,23 @@ export const injectKey = Symbol("__bool:inject__");
|
|
|
8
9
|
export const injectableKey = Symbol("__bool:injectable__");
|
|
9
10
|
export const middlewareKey = Symbol("__bool:middleware__");
|
|
10
11
|
export const moduleKey = Symbol("__bool:module__");
|
|
11
|
-
export const
|
|
12
|
-
export const
|
|
13
|
-
export const
|
|
14
|
-
export const
|
|
15
|
-
export const
|
|
16
|
-
export const
|
|
17
|
-
export const
|
|
18
|
-
export const
|
|
19
|
-
export const
|
|
20
|
-
export const
|
|
21
|
-
export const
|
|
22
|
-
export const
|
|
12
|
+
export const zodSchemaKey = Symbol("__bool:zodSchema__");
|
|
13
|
+
export const webSocketKey = Symbol("__bool:webSocket__");
|
|
14
|
+
export const webSocketEventKey = Symbol("__bool:webSocket:event__");
|
|
15
|
+
export const webSocketServerArgsKey = Symbol("__bool:webSocketArguments:server__");
|
|
16
|
+
export const webSocketConnectionArgsKey = Symbol("__bool:webSocketArguments:connection__");
|
|
17
|
+
export const webSocketMessageArgsKey = Symbol("__bool:webSocketArguments:message__");
|
|
18
|
+
export const webSocketCloseCodeArgsKey = Symbol("__bool:webSocketArguments:closeCode__");
|
|
19
|
+
export const webSocketCloseReasonArgsKey = Symbol("__bool:webSocketArguments:closeReason__");
|
|
20
|
+
export const httpServerArgsKey = Symbol("__bool:httpArguments:server__");
|
|
21
|
+
export const requestHeadersArgsKey = Symbol("__bool:httpArguments:requestHeaders__");
|
|
22
|
+
export const requestHeaderArgsKey = Symbol("__bool:httpArguments:requestHeader__");
|
|
23
|
+
export const requestBodyArgsKey = Symbol("__bool:httpArguments:requestBody__");
|
|
24
|
+
export const paramsArgsKey = Symbol("__bool:httpArguments:params__");
|
|
25
|
+
export const paramArgsKey = Symbol("__bool:httpArguments:param__");
|
|
26
|
+
export const queryArgsKey = Symbol("__bool:httpArguments:query__");
|
|
27
|
+
export const requestArgsKey = Symbol("__bool:httpArguments:request__");
|
|
28
|
+
export const responseHeadersArgsKey = Symbol("__bool:httpArguments:responseHeaders__");
|
|
29
|
+
export const contextArgsKey = Symbol("__bool:httpArguments:context__");
|
|
30
|
+
export const routeModelArgsKey = Symbol("__bool:httpArguments:routeModel__");
|
|
31
|
+
export const responseBodyArgsKey = Symbol("__bool:httpArguments:responseBody__");
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
type AnsiOptions = {
|
|
2
|
+
color?: keyof typeof ansiColors;
|
|
3
|
+
backgroundColor?: keyof typeof backgroundColors;
|
|
4
|
+
bold?: boolean;
|
|
5
|
+
underline?: boolean;
|
|
6
|
+
};
|
|
7
|
+
declare const ansiColors: Readonly<{
|
|
8
|
+
black: 30;
|
|
9
|
+
red: 31;
|
|
10
|
+
green: 32;
|
|
11
|
+
yellow: 33;
|
|
12
|
+
blue: 34;
|
|
13
|
+
magenta: 35;
|
|
14
|
+
cyan: 36;
|
|
15
|
+
white: 37;
|
|
16
|
+
gray: 90;
|
|
17
|
+
}>;
|
|
18
|
+
declare const backgroundColors: Readonly<{
|
|
19
|
+
black: 40;
|
|
20
|
+
red: 41;
|
|
21
|
+
green: 42;
|
|
22
|
+
yellow: 43;
|
|
23
|
+
blue: 44;
|
|
24
|
+
magenta: 45;
|
|
25
|
+
cyan: 46;
|
|
26
|
+
white: 47;
|
|
27
|
+
gray: 100;
|
|
28
|
+
}>;
|
|
29
|
+
export declare const ansiText: (text: string, options?: AnsiOptions) => string;
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const ansiColors = Object.freeze({
|
|
2
|
+
black: 30,
|
|
3
|
+
red: 31,
|
|
4
|
+
green: 32,
|
|
5
|
+
yellow: 33,
|
|
6
|
+
blue: 34,
|
|
7
|
+
magenta: 35,
|
|
8
|
+
cyan: 36,
|
|
9
|
+
white: 37,
|
|
10
|
+
gray: 90
|
|
11
|
+
});
|
|
12
|
+
const backgroundColors = Object.freeze({
|
|
13
|
+
black: 40,
|
|
14
|
+
red: 41,
|
|
15
|
+
green: 42,
|
|
16
|
+
yellow: 43,
|
|
17
|
+
blue: 44,
|
|
18
|
+
magenta: 45,
|
|
19
|
+
cyan: 46,
|
|
20
|
+
white: 47,
|
|
21
|
+
gray: 100
|
|
22
|
+
});
|
|
23
|
+
export const ansiText = (text, options = {}) => {
|
|
24
|
+
const { color, backgroundColor, bold, underline } = options;
|
|
25
|
+
let ansiCode = "";
|
|
26
|
+
if (bold) {
|
|
27
|
+
ansiCode += "\x1b[1m"; // Mã ANSI cho in đậm
|
|
28
|
+
}
|
|
29
|
+
if (underline) {
|
|
30
|
+
ansiCode += "\x1b[4m"; // Mã ANSI cho gạch chân
|
|
31
|
+
}
|
|
32
|
+
if (color && ansiColors[color]) {
|
|
33
|
+
ansiCode += `\x1b[${ansiColors[color]}m`;
|
|
34
|
+
}
|
|
35
|
+
// Màu nền
|
|
36
|
+
if (backgroundColor && backgroundColors[backgroundColor]) {
|
|
37
|
+
ansiCode += `\x1b[${backgroundColors[backgroundColor]}m`;
|
|
38
|
+
}
|
|
39
|
+
// Kết quả với reset
|
|
40
|
+
return `${ansiCode}${text}\x1b[0m`;
|
|
41
|
+
};
|
package/dist/ultils/index.d.ts
CHANGED
package/dist/ultils/index.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const isWebSocketUpgrade: (request: Request) => boolean;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export const isWebSocketUpgrade = (request) => {
|
|
2
|
+
const headers = request.headers;
|
|
3
|
+
const method = request.method;
|
|
4
|
+
const upgrade = headers.get("upgrade")?.toLowerCase() || "";
|
|
5
|
+
const connection = headers.get("connection")?.toLowerCase() || "";
|
|
6
|
+
return method === "GET" && upgrade?.toLowerCase() === "websocket" && connection?.toLowerCase().includes("upgrade");
|
|
7
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bool-ts/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -18,14 +18,15 @@
|
|
|
18
18
|
},
|
|
19
19
|
"homepage": "https://github.com/BoolTS/core#readme",
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"
|
|
22
|
-
"qs": "^6.13.
|
|
21
|
+
"@bool-ts/date-time": "^1.0.0",
|
|
22
|
+
"qs": "^6.13.1",
|
|
23
23
|
"reflect-metadata": "^0.2.2",
|
|
24
|
-
"zod": "^3.
|
|
24
|
+
"zod": "^3.24.1"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@types/bun": "latest",
|
|
28
|
-
"@types/qs": "^6.9.
|
|
29
|
-
"typescript": "^5.
|
|
30
|
-
}
|
|
28
|
+
"@types/qs": "^6.9.17",
|
|
29
|
+
"typescript": "^5.7.2"
|
|
30
|
+
},
|
|
31
|
+
"private": "false"
|
|
31
32
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type { IController } from "../interfaces
|
|
1
|
+
import type { IController } from "../interfaces";
|
|
2
|
+
import type { THttpMetadata } from "./http";
|
|
3
|
+
|
|
2
4
|
import { controllerHttpKey, controllerKey } from "../keys";
|
|
3
|
-
import { type THttpMetadata } from "./http";
|
|
4
5
|
|
|
5
6
|
export type TControllerMetadata = Required<{
|
|
6
7
|
prefix: string;
|
|
@@ -8,10 +9,10 @@ export type TControllerMetadata = Required<{
|
|
|
8
9
|
}>;
|
|
9
10
|
|
|
10
11
|
export const Controller =
|
|
11
|
-
(prefix
|
|
12
|
+
(prefix?: string) =>
|
|
12
13
|
<T extends { new (...args: any[]): IController }>(target: T) => {
|
|
13
14
|
const metadata: TControllerMetadata = {
|
|
14
|
-
prefix: !prefix
|
|
15
|
+
prefix: !prefix?.startsWith("/") ? `/${prefix || ""}` : prefix,
|
|
15
16
|
httpMetadata: [...(Reflect.getOwnMetadata(controllerHttpKey, target.constructor) || [])]
|
|
16
17
|
};
|
|
17
18
|
|
package/src/decorators/guard.ts
CHANGED
package/src/decorators/http.ts
CHANGED
|
@@ -4,15 +4,15 @@ export type TRoute = {
|
|
|
4
4
|
path: string;
|
|
5
5
|
httpMethod: "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "OPTIONS";
|
|
6
6
|
methodName: string;
|
|
7
|
-
descriptor:
|
|
7
|
+
descriptor: TypedPropertyDescriptor<any>;
|
|
8
8
|
};
|
|
9
9
|
|
|
10
10
|
export type THttpMetadata = Array<TRoute>;
|
|
11
11
|
|
|
12
12
|
const defaultDecorator =
|
|
13
13
|
(path: string, method: "Get" | "Post" | "Put" | "Patch" | "Delete" | "Options") =>
|
|
14
|
-
(target: Object, methodName: string, descriptor:
|
|
15
|
-
if (!(descriptor
|
|
14
|
+
(target: Object, methodName: string | symbol, descriptor: TypedPropertyDescriptor<any>) => {
|
|
15
|
+
if (!(descriptor?.value instanceof Function)) {
|
|
16
16
|
throw Error(`${method} decorator only use for class method.`);
|
|
17
17
|
}
|
|
18
18
|
|
package/src/decorators/index.ts
CHANGED
|
@@ -18,6 +18,14 @@ export { Inject } from "./inject";
|
|
|
18
18
|
export { Injectable } from "./injectable";
|
|
19
19
|
export { Middleware } from "./middleware";
|
|
20
20
|
export { Module } from "./module";
|
|
21
|
+
export { WebSocket } from "./webSocket";
|
|
22
|
+
export {
|
|
23
|
+
WebSocketCloseCode,
|
|
24
|
+
WebSocketCloseReason,
|
|
25
|
+
WebSocketConnection,
|
|
26
|
+
WebSocketServer
|
|
27
|
+
} from "./webSocketArguments";
|
|
28
|
+
export { WebSocketEvent } from "./webSocketEvent";
|
|
21
29
|
export { ZodSchema } from "./zodSchema";
|
|
22
30
|
|
|
23
31
|
export type { TArgumentsMetadata } from "./arguments";
|
|
@@ -27,3 +35,5 @@ export type { TGuardMetadata } from "./guard";
|
|
|
27
35
|
export type { THttpMetadata } from "./http";
|
|
28
36
|
export type { TMiddlewareMetadata } from "./middleware";
|
|
29
37
|
export type { TModuleMetadata, TModuleOptions } from "./module";
|
|
38
|
+
export type { TWebSocketMetadata } from "./webSocket";
|
|
39
|
+
export type { TWebSocketEventHandlerMetadata, TWebSocketEventMetadata } from "./webSocketEvent";
|
package/src/decorators/module.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type { IModule } from "../interfaces
|
|
2
|
-
|
|
1
|
+
import type { IModule } from "../interfaces";
|
|
2
|
+
|
|
3
|
+
import { controllerKey, dispatcherKey, guardKey, injectableKey, middlewareKey, moduleKey, webSocketKey } from "../keys";
|
|
3
4
|
|
|
4
5
|
type TInstances = Array<new (...args: any[]) => any>;
|
|
5
6
|
type TLoaders<TConfig extends {} = {}> = Record<
|
|
@@ -17,6 +18,7 @@ export type TModuleOptions<TConfig extends {} = {}> =
|
|
|
17
18
|
guards: TInstances;
|
|
18
19
|
controllers: TInstances;
|
|
19
20
|
dispatchers: TInstances;
|
|
21
|
+
webSockets: TInstances;
|
|
20
22
|
}>
|
|
21
23
|
| undefined;
|
|
22
24
|
|
|
@@ -30,13 +32,14 @@ export type TModuleMetadata<TConfig extends {} = {}> =
|
|
|
30
32
|
guards: TInstances;
|
|
31
33
|
controllers: TInstances;
|
|
32
34
|
dispatchers: TInstances;
|
|
35
|
+
webSockets: TInstances;
|
|
33
36
|
}>
|
|
34
37
|
| undefined;
|
|
35
38
|
|
|
36
39
|
export const Module =
|
|
37
40
|
<TConfig extends {} = {}>(args?: TModuleOptions<TConfig>) =>
|
|
38
41
|
<T extends { new (...args: any[]): IModule }>(target: T) => {
|
|
39
|
-
const { middlewares, guards, dispatchers, controllers, dependencies } = args || {};
|
|
42
|
+
const { middlewares, guards, dispatchers, controllers, dependencies, webSockets } = args || {};
|
|
40
43
|
|
|
41
44
|
if (middlewares) {
|
|
42
45
|
for (let i = 0; i < middlewares.length; i++) {
|
|
@@ -78,6 +81,14 @@ export const Module =
|
|
|
78
81
|
}
|
|
79
82
|
}
|
|
80
83
|
|
|
84
|
+
if (webSockets) {
|
|
85
|
+
for (let i = 0; i < webSockets.length; i++) {
|
|
86
|
+
if (!Reflect.getOwnMetadataKeys(webSockets[i]).includes(webSocketKey)) {
|
|
87
|
+
throw Error(`${webSockets[i].name} is not a websocket gateway.`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
81
92
|
Reflect.defineMetadata(moduleKey, args, target);
|
|
82
93
|
};
|
|
83
94
|
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type { Server } from "bun";
|
|
2
|
+
import type { IWebSocket } from "../interfaces";
|
|
3
|
+
import type { TWebSocketEventMetadata } from "./webSocketEvent";
|
|
4
|
+
|
|
5
|
+
import { webSocketEventKey, webSocketKey } from "../keys";
|
|
6
|
+
|
|
7
|
+
export type TWebSocketHttpRouteMetadata = {
|
|
8
|
+
path: string;
|
|
9
|
+
httpMethod: "GET" | "POST";
|
|
10
|
+
methodName: symbol;
|
|
11
|
+
descriptor: PropertyDescriptor;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export type TWebSocketUpgradeData = {
|
|
15
|
+
pathname: string;
|
|
16
|
+
method: string;
|
|
17
|
+
query: Record<string, unknown>;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export type TWebSocketHttpMetadata = TWebSocketHttpRouteMetadata[];
|
|
21
|
+
|
|
22
|
+
export type TWebSocketMetadata = Required<{
|
|
23
|
+
prefix: string;
|
|
24
|
+
events: TWebSocketEventMetadata;
|
|
25
|
+
http: TWebSocketHttpMetadata;
|
|
26
|
+
}>;
|
|
27
|
+
|
|
28
|
+
const upgradeHandlerSymbol = Symbol("__bool:webSocket.upgrade__");
|
|
29
|
+
|
|
30
|
+
const upgradeHandler = (server: Server, request: Request, query: Record<string, unknown>) => {
|
|
31
|
+
const url = new URL(request.url);
|
|
32
|
+
|
|
33
|
+
return server.upgrade<TWebSocketUpgradeData>(request, {
|
|
34
|
+
data: {
|
|
35
|
+
method: request.method.toUpperCase(),
|
|
36
|
+
pathname: url.pathname,
|
|
37
|
+
query: query
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export const WebSocket =
|
|
43
|
+
(
|
|
44
|
+
args?: Partial<{
|
|
45
|
+
prefix: string;
|
|
46
|
+
}>
|
|
47
|
+
) =>
|
|
48
|
+
<T extends { new (...args: any[]): IWebSocket }>(target: T) => {
|
|
49
|
+
const { prefix } = args || {};
|
|
50
|
+
|
|
51
|
+
target.prototype[upgradeHandlerSymbol] = upgradeHandler;
|
|
52
|
+
|
|
53
|
+
const descriptor = Object.getOwnPropertyDescriptor(target.prototype, upgradeHandlerSymbol);
|
|
54
|
+
|
|
55
|
+
const httpMetadata: TWebSocketHttpMetadata = !descriptor
|
|
56
|
+
? []
|
|
57
|
+
: [
|
|
58
|
+
{
|
|
59
|
+
path: "/",
|
|
60
|
+
httpMethod: "GET",
|
|
61
|
+
methodName: upgradeHandlerSymbol,
|
|
62
|
+
descriptor: descriptor
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
path: "/",
|
|
66
|
+
httpMethod: "POST",
|
|
67
|
+
methodName: upgradeHandlerSymbol,
|
|
68
|
+
descriptor: descriptor
|
|
69
|
+
}
|
|
70
|
+
];
|
|
71
|
+
|
|
72
|
+
const metadata: TWebSocketMetadata = {
|
|
73
|
+
prefix: !prefix?.startsWith("/") ? `/${prefix || ""}` : prefix,
|
|
74
|
+
events: Reflect.getOwnMetadata(webSocketEventKey, target) || {},
|
|
75
|
+
http: httpMetadata
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
Reflect.defineMetadata(webSocketKey, metadata, target);
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export default WebSocket;
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import {
|
|
2
|
+
webSocketCloseCodeArgsKey,
|
|
3
|
+
webSocketCloseReasonArgsKey,
|
|
4
|
+
webSocketConnectionArgsKey,
|
|
5
|
+
webSocketEventArgumentsKey,
|
|
6
|
+
webSocketMessageArgsKey,
|
|
7
|
+
webSocketServerArgsKey
|
|
8
|
+
} from "../keys";
|
|
9
|
+
|
|
10
|
+
export type TWebsocketArgumentsMetadata =
|
|
11
|
+
| {
|
|
12
|
+
index: number;
|
|
13
|
+
type: typeof webSocketConnectionArgsKey;
|
|
14
|
+
}
|
|
15
|
+
| {
|
|
16
|
+
index: number;
|
|
17
|
+
type: typeof webSocketMessageArgsKey;
|
|
18
|
+
}
|
|
19
|
+
| {
|
|
20
|
+
index: number;
|
|
21
|
+
type: typeof webSocketServerArgsKey;
|
|
22
|
+
}
|
|
23
|
+
| {
|
|
24
|
+
index: number;
|
|
25
|
+
type: typeof webSocketCloseCodeArgsKey;
|
|
26
|
+
}
|
|
27
|
+
| {
|
|
28
|
+
index: number;
|
|
29
|
+
type: typeof webSocketCloseReasonArgsKey;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export type TWebsocketArgumentsMetadataGroup = Record<string, TWebsocketArgumentsMetadata>;
|
|
33
|
+
|
|
34
|
+
export const WebSocketConnection =
|
|
35
|
+
() => (target: Object, methodName: string | symbol | undefined, parameterIndex: number) => {
|
|
36
|
+
if (!methodName) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const webSocketEventArgumentsMetadata: TWebsocketArgumentsMetadataGroup =
|
|
41
|
+
Reflect.getOwnMetadata(webSocketEventArgumentsKey, target.constructor, methodName) ||
|
|
42
|
+
{};
|
|
43
|
+
|
|
44
|
+
webSocketEventArgumentsMetadata[`argumentIndexes.${parameterIndex}`] = {
|
|
45
|
+
index: parameterIndex,
|
|
46
|
+
type: webSocketConnectionArgsKey
|
|
47
|
+
} satisfies Extract<
|
|
48
|
+
TWebsocketArgumentsMetadata,
|
|
49
|
+
{
|
|
50
|
+
type: typeof webSocketConnectionArgsKey;
|
|
51
|
+
}
|
|
52
|
+
>;
|
|
53
|
+
|
|
54
|
+
Reflect.defineMetadata(
|
|
55
|
+
webSocketEventArgumentsKey,
|
|
56
|
+
webSocketEventArgumentsMetadata,
|
|
57
|
+
target.constructor,
|
|
58
|
+
methodName
|
|
59
|
+
);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export const WebSocketServer =
|
|
63
|
+
() => (target: Object, methodName: string | symbol | undefined, parameterIndex: number) => {
|
|
64
|
+
if (!methodName) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const webSocketEventArgumentsMetadata: TWebsocketArgumentsMetadataGroup =
|
|
69
|
+
Reflect.getOwnMetadata(webSocketEventArgumentsKey, target.constructor, methodName) ||
|
|
70
|
+
{};
|
|
71
|
+
|
|
72
|
+
webSocketEventArgumentsMetadata[`argumentIndexes.${parameterIndex}`] = {
|
|
73
|
+
index: parameterIndex,
|
|
74
|
+
type: webSocketServerArgsKey
|
|
75
|
+
} satisfies Extract<
|
|
76
|
+
TWebsocketArgumentsMetadata,
|
|
77
|
+
{
|
|
78
|
+
type: typeof webSocketServerArgsKey;
|
|
79
|
+
}
|
|
80
|
+
>;
|
|
81
|
+
|
|
82
|
+
Reflect.defineMetadata(
|
|
83
|
+
webSocketEventArgumentsKey,
|
|
84
|
+
webSocketEventArgumentsMetadata,
|
|
85
|
+
target.constructor,
|
|
86
|
+
methodName
|
|
87
|
+
);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export const WebSocketCloseCode =
|
|
91
|
+
() => (target: Object, methodName: string | symbol | undefined, parameterIndex: number) => {
|
|
92
|
+
if (!methodName) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const webSocketEventArgumentsMetadata: TWebsocketArgumentsMetadataGroup =
|
|
97
|
+
Reflect.getOwnMetadata(webSocketEventArgumentsKey, target.constructor, methodName) ||
|
|
98
|
+
{};
|
|
99
|
+
|
|
100
|
+
webSocketEventArgumentsMetadata[`argumentIndexes.${parameterIndex}`] = {
|
|
101
|
+
index: parameterIndex,
|
|
102
|
+
type: webSocketCloseCodeArgsKey
|
|
103
|
+
} satisfies Extract<
|
|
104
|
+
TWebsocketArgumentsMetadata,
|
|
105
|
+
{
|
|
106
|
+
type: typeof webSocketCloseCodeArgsKey;
|
|
107
|
+
}
|
|
108
|
+
>;
|
|
109
|
+
|
|
110
|
+
Reflect.defineMetadata(
|
|
111
|
+
webSocketEventArgumentsKey,
|
|
112
|
+
webSocketEventArgumentsMetadata,
|
|
113
|
+
target.constructor,
|
|
114
|
+
methodName
|
|
115
|
+
);
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
export const WebSocketCloseReason =
|
|
119
|
+
() => (target: Object, methodName: string | symbol | undefined, parameterIndex: number) => {
|
|
120
|
+
if (!methodName) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const webSocketEventArgumentsMetadata: TWebsocketArgumentsMetadataGroup =
|
|
125
|
+
Reflect.getOwnMetadata(webSocketEventArgumentsKey, target.constructor, methodName) ||
|
|
126
|
+
{};
|
|
127
|
+
|
|
128
|
+
webSocketEventArgumentsMetadata[`argumentIndexes.${parameterIndex}`] = {
|
|
129
|
+
index: parameterIndex,
|
|
130
|
+
type: webSocketCloseReasonArgsKey
|
|
131
|
+
} satisfies Extract<
|
|
132
|
+
TWebsocketArgumentsMetadata,
|
|
133
|
+
{
|
|
134
|
+
type: typeof webSocketCloseReasonArgsKey;
|
|
135
|
+
}
|
|
136
|
+
>;
|
|
137
|
+
|
|
138
|
+
Reflect.defineMetadata(
|
|
139
|
+
webSocketEventArgumentsKey,
|
|
140
|
+
webSocketEventArgumentsMetadata,
|
|
141
|
+
target.constructor,
|
|
142
|
+
methodName
|
|
143
|
+
);
|
|
144
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
TWebsocketArgumentsMetadata,
|
|
3
|
+
TWebsocketArgumentsMetadataGroup
|
|
4
|
+
} from "./webSocketArguments";
|
|
5
|
+
|
|
6
|
+
import { webSocketEventArgumentsKey, webSocketEventKey } from "../keys";
|
|
7
|
+
|
|
8
|
+
export type TWebSocketEventHandlerMetadata = Required<{
|
|
9
|
+
methodName: string;
|
|
10
|
+
descriptor: PropertyDescriptor;
|
|
11
|
+
}> &
|
|
12
|
+
Partial<{
|
|
13
|
+
arguments: Record<string, TWebsocketArgumentsMetadata>;
|
|
14
|
+
}>;
|
|
15
|
+
|
|
16
|
+
export type TWebSocketEventMetadata = Record<
|
|
17
|
+
"open" | "close" | "message" | "drain" | "ping" | "pong",
|
|
18
|
+
TWebSocketEventHandlerMetadata
|
|
19
|
+
>;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
*
|
|
23
|
+
* @param path
|
|
24
|
+
* @returns
|
|
25
|
+
*/
|
|
26
|
+
export const WebSocketEvent =
|
|
27
|
+
(eventName: "open" | "close" | "message" | "drain" | "ping" | "pong") =>
|
|
28
|
+
(target: Object, methodName: string, descriptor: PropertyDescriptor) => {
|
|
29
|
+
if (!(descriptor.value instanceof Function)) {
|
|
30
|
+
throw Error("WebSocketEvent decorator only use for class's method.");
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const webSocketEventArgumentsMetadata: TWebsocketArgumentsMetadataGroup | undefined =
|
|
34
|
+
Reflect.getOwnMetadata(webSocketEventArgumentsKey, target.constructor, methodName);
|
|
35
|
+
|
|
36
|
+
const webSocketEventMetadata: TWebSocketEventHandlerMetadata = Object.freeze({
|
|
37
|
+
methodName: methodName,
|
|
38
|
+
descriptor: descriptor,
|
|
39
|
+
arguments: webSocketEventArgumentsMetadata
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
const webSocketMetadata: TWebSocketEventMetadata = {
|
|
43
|
+
...(Reflect.getOwnMetadata(webSocketEventKey, target.constructor) || undefined),
|
|
44
|
+
[eventName]: webSocketEventMetadata
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
Reflect.defineMetadata(
|
|
48
|
+
webSocketEventKey,
|
|
49
|
+
webSocketEventMetadata,
|
|
50
|
+
target.constructor,
|
|
51
|
+
methodName
|
|
52
|
+
);
|
|
53
|
+
Reflect.defineMetadata(webSocketEventKey, webSocketMetadata, target.constructor);
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export default WebSocket;
|