@tsed/socketio 8.0.0 → 8.0.2
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/package.json +16 -15
- package/src/SocketIOModule.spec.ts +87 -0
- package/src/SocketIOModule.ts +113 -0
- package/src/class/SocketHandlersBuilder.spec.ts +988 -0
- package/src/class/SocketHandlersBuilder.ts +266 -0
- package/src/class/SocketProviderMetadata.ts +57 -0
- package/src/class/SocketSessionData.spec.ts +190 -0
- package/src/class/SocketSessionData.ts +81 -0
- package/src/constants/constants.ts +1 -0
- package/src/decorators/args.spec.ts +57 -0
- package/src/decorators/args.ts +60 -0
- package/src/decorators/broadcast.spec.ts +23 -0
- package/src/decorators/broadcast.ts +28 -0
- package/src/decorators/broadcastOthers.spec.ts +23 -0
- package/src/decorators/broadcastOthers.ts +28 -0
- package/src/decorators/emit.spec.ts +23 -0
- package/src/decorators/emit.ts +28 -0
- package/src/decorators/input.spec.ts +22 -0
- package/src/decorators/input.ts +33 -0
- package/src/decorators/inputAndBroadcast.spec.ts +25 -0
- package/src/decorators/inputAndBroadcast.ts +28 -0
- package/src/decorators/inputAndBroadcastOthers.spec.ts +24 -0
- package/src/decorators/inputAndBroadcastOthers.ts +28 -0
- package/src/decorators/inputAndEmit.spec.ts +24 -0
- package/src/decorators/inputAndEmit.ts +28 -0
- package/src/decorators/io.ts +34 -0
- package/src/decorators/nsp.spec.ts +70 -0
- package/src/decorators/nsp.ts +101 -0
- package/src/decorators/reason.spec.ts +26 -0
- package/src/decorators/reason.ts +30 -0
- package/src/decorators/socket.spec.ts +26 -0
- package/src/decorators/socket.ts +32 -0
- package/src/decorators/socketErr.spec.ts +25 -0
- package/src/decorators/socketErr.ts +26 -0
- package/src/decorators/socketEventName.spec.ts +25 -0
- package/src/decorators/socketEventName.ts +26 -0
- package/src/decorators/socketFilter.ts +27 -0
- package/src/decorators/socketMiddleware.spec.ts +21 -0
- package/src/decorators/socketMiddleware.ts +72 -0
- package/src/decorators/socketMiddlewareError.spec.ts +22 -0
- package/src/decorators/socketMiddlewareError.ts +70 -0
- package/src/decorators/socketNsp.spec.ts +26 -0
- package/src/decorators/socketNsp.ts +32 -0
- package/src/decorators/socketReturns.ts +25 -0
- package/src/decorators/socketService.spec.ts +44 -0
- package/src/decorators/socketService.ts +24 -0
- package/src/decorators/socketSession.spec.ts +47 -0
- package/src/decorators/socketSession.ts +53 -0
- package/src/decorators/socketUseAfter.spec.ts +38 -0
- package/src/decorators/socketUseAfter.ts +69 -0
- package/src/decorators/socketUseBefore.spec.ts +34 -0
- package/src/decorators/socketUseBefore.ts +73 -0
- package/src/index.ts +41 -0
- package/src/interfaces/OnNamespaceInit.ts +8 -0
- package/src/interfaces/SocketFilters.ts +14 -0
- package/src/interfaces/SocketHandlerMetadata.ts +17 -0
- package/src/interfaces/SocketInjectableNsp.ts +4 -0
- package/src/interfaces/SocketParamMetadata.ts +9 -0
- package/src/interfaces/SocketProviderTypes.ts +7 -0
- package/src/interfaces/SocketReturnsTypes.ts +8 -0
- package/src/interfaces/interfaces.ts +9 -0
- package/src/services/SocketIOServer.spec.ts +33 -0
- package/src/services/SocketIOServer.ts +15 -0
- package/src/services/SocketIOService.spec.ts +54 -0
- package/src/services/SocketIOService.ts +69 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import {Store} from "@tsed/core";
|
|
2
|
+
|
|
3
|
+
import {SocketUseAfter} from "../index.js";
|
|
4
|
+
|
|
5
|
+
describe("@SocketUseAfter", () => {
|
|
6
|
+
describe("when the decorator is used on a class", () => {
|
|
7
|
+
beforeAll(() => {});
|
|
8
|
+
|
|
9
|
+
it("should store metadata", () => {
|
|
10
|
+
class Test {}
|
|
11
|
+
|
|
12
|
+
const middleware: any = () => {};
|
|
13
|
+
SocketUseAfter(middleware)(Test);
|
|
14
|
+
|
|
15
|
+
expect(Store.from(Test).get("socketIO")).toEqual({
|
|
16
|
+
useAfter: [middleware]
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
describe("when the decorator is used on a method", () => {
|
|
22
|
+
it("should store metadata", () => {
|
|
23
|
+
class Test {}
|
|
24
|
+
|
|
25
|
+
const middleware: any = () => {};
|
|
26
|
+
|
|
27
|
+
SocketUseAfter(middleware)(Test, "test", {});
|
|
28
|
+
|
|
29
|
+
expect(Store.from(Test).get("socketIO")).toEqual({
|
|
30
|
+
handlers: {
|
|
31
|
+
test: {
|
|
32
|
+
useAfter: [middleware]
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
});
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import {Store, Type} from "@tsed/core";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Attach a Socket Middleware to a method or a class.
|
|
5
|
+
*
|
|
6
|
+
* ### Example
|
|
7
|
+
*
|
|
8
|
+
* A middleware can be also used on a `SocketService` either on a class or on a method.
|
|
9
|
+
*
|
|
10
|
+
* Here an example of a middleware:
|
|
11
|
+
*
|
|
12
|
+
* ```typescript
|
|
13
|
+
* import {SocketMiddlewareError, SocketErr, Socket, Args} from "@tsed/socketio";
|
|
14
|
+
*
|
|
15
|
+
* @SocketMiddlewareError()
|
|
16
|
+
* export class ErrorHandlerSocketMiddleware {
|
|
17
|
+
* async use(@SocketErr() err: any, @Socket socket: SocketIO.Socket) {
|
|
18
|
+
* console.error(err);
|
|
19
|
+
* socket.emit("error", {message: "An error has occured"})
|
|
20
|
+
* }
|
|
21
|
+
* }
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* Then:
|
|
25
|
+
*
|
|
26
|
+
* ```typescript
|
|
27
|
+
* import {SocketService, SocketUseAfter, SocketUseBefore, Emit, Input, Args} from "@tsed/socketio";
|
|
28
|
+
* import {ErrorHandlerSocketMiddleware} from "../middlewares.js";
|
|
29
|
+
* import {User} from "../models/User.js";
|
|
30
|
+
*
|
|
31
|
+
* @SocketService("/my-namespace")
|
|
32
|
+
* @SocketUseAfter(ErrorHandlerSocketMiddleware) // global version
|
|
33
|
+
* export class MySocketService {
|
|
34
|
+
*
|
|
35
|
+
* @Input("eventName")
|
|
36
|
+
* @Emit("responseEventName") // or Broadcast or BroadcastOthers
|
|
37
|
+
* @SocketUseAfter(ErrorHandlerSocketMiddleware)
|
|
38
|
+
* async myMethod(@Args(0) userName: User) {
|
|
39
|
+
*
|
|
40
|
+
* console.log(user);
|
|
41
|
+
* throw new Error("Error");
|
|
42
|
+
*
|
|
43
|
+
* return user;
|
|
44
|
+
* }
|
|
45
|
+
* }
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
* @returns {(target: any, propertyKey?: string, descriptor?: PropertyDescriptor) => void}
|
|
49
|
+
* @decorator
|
|
50
|
+
* @experimental
|
|
51
|
+
* @param middlewares
|
|
52
|
+
*/
|
|
53
|
+
export function SocketUseAfter(...middlewares: Type<any>[]) {
|
|
54
|
+
return (target: any, propertyKey?: string, descriptor?: PropertyDescriptor) => {
|
|
55
|
+
if (propertyKey) {
|
|
56
|
+
Store.from(target).merge("socketIO", {
|
|
57
|
+
handlers: {
|
|
58
|
+
[propertyKey]: {
|
|
59
|
+
useAfter: middlewares
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
} else {
|
|
64
|
+
Store.from(target).merge("socketIO", {
|
|
65
|
+
useAfter: middlewares
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import {Store} from "@tsed/core";
|
|
2
|
+
|
|
3
|
+
import {SocketUseBefore} from "../index.js";
|
|
4
|
+
|
|
5
|
+
describe("@SocketUseBefore", () => {
|
|
6
|
+
describe("when the decorator is used on a class", () => {
|
|
7
|
+
it("should store metadata", () => {
|
|
8
|
+
class Test {}
|
|
9
|
+
const middleware: any = () => {};
|
|
10
|
+
SocketUseBefore(middleware)(Test);
|
|
11
|
+
|
|
12
|
+
expect(Store.from(Test).get("socketIO")).toEqual({
|
|
13
|
+
useBefore: [middleware]
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
describe("when the decorator is used on a method", () => {
|
|
19
|
+
it("should store metadata", () => {
|
|
20
|
+
class Test {}
|
|
21
|
+
const middleware: any = () => {};
|
|
22
|
+
|
|
23
|
+
SocketUseBefore(middleware)(Test, "test", {});
|
|
24
|
+
|
|
25
|
+
expect(Store.from(Test).get("socketIO")).toEqual({
|
|
26
|
+
handlers: {
|
|
27
|
+
test: {
|
|
28
|
+
useBefore: [middleware]
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
});
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import {Store, Type} from "@tsed/core";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Attach a Socket Middleware to a method or a class.
|
|
5
|
+
*
|
|
6
|
+
* ### Example
|
|
7
|
+
*
|
|
8
|
+
* A middleware can be also used on a `SocketService` either on a class or on a method.
|
|
9
|
+
*
|
|
10
|
+
* Here an example of a middleware:
|
|
11
|
+
*
|
|
12
|
+
* ```typescript
|
|
13
|
+
* @SocketMiddleware()
|
|
14
|
+
* export class UserConverterSocketMiddleware {
|
|
15
|
+
* constructor(private converterService: ConverterService) {
|
|
16
|
+
* }
|
|
17
|
+
* async use(@Args() args: any[]) {
|
|
18
|
+
*
|
|
19
|
+
* let [user] = args;
|
|
20
|
+
* // update Arguments
|
|
21
|
+
* user = ConverterService.deserialize(user, User);
|
|
22
|
+
*
|
|
23
|
+
* return [user];
|
|
24
|
+
* }
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
* > The user instance will be forwarded to the next middleware and to your decorated method.
|
|
28
|
+
*
|
|
29
|
+
* Then:
|
|
30
|
+
*
|
|
31
|
+
* ```typescript
|
|
32
|
+
* import {SocketService, SocketUseAfter, SocketUseBefore, Emit, Input, Args} from "@tsed/socketio";
|
|
33
|
+
* import {UserConverterSocketMiddleware} from "../middlewares.js";
|
|
34
|
+
* import {User} from "../models/User.js";
|
|
35
|
+
*
|
|
36
|
+
* @SocketService("/my-namespace")
|
|
37
|
+
* @SocketUseBefore(UserConverterSocketMiddleware) // global version
|
|
38
|
+
* export class MySocketService {
|
|
39
|
+
*
|
|
40
|
+
* @Input("eventName")
|
|
41
|
+
* @Emit("responseEventName") // or Broadcast or BroadcastOthers
|
|
42
|
+
* @SocketUseBefore(UserConverterSocketMiddleware)
|
|
43
|
+
* async myMethod(@Args(0) user: User) {
|
|
44
|
+
*
|
|
45
|
+
* console.log(user);
|
|
46
|
+
*
|
|
47
|
+
* return user;
|
|
48
|
+
* }
|
|
49
|
+
* }
|
|
50
|
+
* ```
|
|
51
|
+
*
|
|
52
|
+
* @returns {(target: any, propertyKey?: string, descriptor?: PropertyDescriptor) => void}
|
|
53
|
+
* @decorator
|
|
54
|
+
* @experimental
|
|
55
|
+
* @param middlewares
|
|
56
|
+
*/
|
|
57
|
+
export function SocketUseBefore(...middlewares: Type<any>[]) {
|
|
58
|
+
return (target: any, propertyKey?: string, descriptor?: PropertyDescriptor) => {
|
|
59
|
+
if (propertyKey) {
|
|
60
|
+
Store.from(target).merge("socketIO", {
|
|
61
|
+
handlers: {
|
|
62
|
+
[propertyKey]: {
|
|
63
|
+
useBefore: middlewares
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
} else {
|
|
68
|
+
Store.from(target).merge("socketIO", {
|
|
69
|
+
useBefore: middlewares
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Automatically generated by @tsed/barrels.
|
|
3
|
+
*/
|
|
4
|
+
export * from "./class/SocketHandlersBuilder.js";
|
|
5
|
+
export * from "./class/SocketProviderMetadata.js";
|
|
6
|
+
export * from "./class/SocketSessionData.js";
|
|
7
|
+
export * from "./constants/constants.js";
|
|
8
|
+
export * from "./decorators/args.js";
|
|
9
|
+
export * from "./decorators/broadcast.js";
|
|
10
|
+
export * from "./decorators/broadcastOthers.js";
|
|
11
|
+
export * from "./decorators/emit.js";
|
|
12
|
+
export * from "./decorators/input.js";
|
|
13
|
+
export * from "./decorators/inputAndBroadcast.js";
|
|
14
|
+
export * from "./decorators/inputAndBroadcastOthers.js";
|
|
15
|
+
export * from "./decorators/inputAndEmit.js";
|
|
16
|
+
export * from "./decorators/io.js";
|
|
17
|
+
export * from "./decorators/nsp.js";
|
|
18
|
+
export * from "./decorators/reason.js";
|
|
19
|
+
export * from "./decorators/socket.js";
|
|
20
|
+
export * from "./decorators/socketErr.js";
|
|
21
|
+
export * from "./decorators/socketEventName.js";
|
|
22
|
+
export * from "./decorators/socketFilter.js";
|
|
23
|
+
export * from "./decorators/socketMiddleware.js";
|
|
24
|
+
export * from "./decorators/socketMiddlewareError.js";
|
|
25
|
+
export * from "./decorators/socketNsp.js";
|
|
26
|
+
export * from "./decorators/socketReturns.js";
|
|
27
|
+
export * from "./decorators/socketService.js";
|
|
28
|
+
export * from "./decorators/socketSession.js";
|
|
29
|
+
export * from "./decorators/socketUseAfter.js";
|
|
30
|
+
export * from "./decorators/socketUseBefore.js";
|
|
31
|
+
export * from "./interfaces/interfaces.js";
|
|
32
|
+
export * from "./interfaces/OnNamespaceInit.js";
|
|
33
|
+
export * from "./interfaces/SocketFilters.js";
|
|
34
|
+
export * from "./interfaces/SocketHandlerMetadata.js";
|
|
35
|
+
export * from "./interfaces/SocketInjectableNsp.js";
|
|
36
|
+
export * from "./interfaces/SocketParamMetadata.js";
|
|
37
|
+
export * from "./interfaces/SocketProviderTypes.js";
|
|
38
|
+
export * from "./interfaces/SocketReturnsTypes.js";
|
|
39
|
+
export * from "./services/SocketIOServer.js";
|
|
40
|
+
export * from "./services/SocketIOService.js";
|
|
41
|
+
export * from "./SocketIOModule.js";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @ignore
|
|
3
|
+
*/
|
|
4
|
+
export enum SocketFilters {
|
|
5
|
+
ARGS = "args",
|
|
6
|
+
SOCKET = "socket",
|
|
7
|
+
EVENT_NAME = "eventName",
|
|
8
|
+
NSP = "nsp",
|
|
9
|
+
SESSION = "session",
|
|
10
|
+
RAW_SESSION = "raw_session",
|
|
11
|
+
ERR = "error",
|
|
12
|
+
SOCKET_NSP = "socket_nsp",
|
|
13
|
+
REASON = "reason"
|
|
14
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import {SocketParamMetadata} from "./SocketParamMetadata.js";
|
|
2
|
+
import {SocketReturnsTypes} from "./SocketReturnsTypes.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
*/
|
|
7
|
+
export interface SocketHandlerMetadata {
|
|
8
|
+
eventName?: string;
|
|
9
|
+
methodClassName: string;
|
|
10
|
+
useBefore?: any[];
|
|
11
|
+
useAfter?: any[];
|
|
12
|
+
parameters?: {[key: number]: SocketParamMetadata};
|
|
13
|
+
returns?: {
|
|
14
|
+
type: SocketReturnsTypes;
|
|
15
|
+
eventName: string;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import {PlatformTest} from "@tsed/platform-http/testing";
|
|
2
|
+
|
|
3
|
+
import {Server, SocketIOServer} from "./SocketIOServer.js";
|
|
4
|
+
|
|
5
|
+
describe("SocketIOServer", () => {
|
|
6
|
+
describe("when there is configuration", () => {
|
|
7
|
+
beforeEach(() =>
|
|
8
|
+
PlatformTest.create({
|
|
9
|
+
socketIO: {
|
|
10
|
+
path: "/api/ws"
|
|
11
|
+
}
|
|
12
|
+
})
|
|
13
|
+
);
|
|
14
|
+
afterEach(PlatformTest.reset);
|
|
15
|
+
|
|
16
|
+
it("should inject the SocketIO server", () => {
|
|
17
|
+
const server = PlatformTest.get<SocketIOServer>(SocketIOServer);
|
|
18
|
+
|
|
19
|
+
expect(server).toBeInstanceOf(Server);
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
describe("when there is no configuration", () => {
|
|
24
|
+
beforeEach(() => PlatformTest.create({}));
|
|
25
|
+
afterEach(PlatformTest.reset);
|
|
26
|
+
|
|
27
|
+
it("should inject the SocketIO server", () => {
|
|
28
|
+
const server = PlatformTest.get<SocketIOServer>(SocketIOServer);
|
|
29
|
+
|
|
30
|
+
expect(server).toBeInstanceOf(Server);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {constant, injectable} from "@tsed/di";
|
|
2
|
+
import {Server, type ServerOptions} from "socket.io";
|
|
3
|
+
|
|
4
|
+
export type SocketIOServer = Server;
|
|
5
|
+
|
|
6
|
+
// tslint:disable-next-line: variable-name
|
|
7
|
+
export const SocketIOServer = Server;
|
|
8
|
+
|
|
9
|
+
injectable(Server).factory(() => {
|
|
10
|
+
const socketIO = constant<Partial<ServerOptions>>("socketIO");
|
|
11
|
+
|
|
12
|
+
return new Server(socketIO);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
export {Server};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import {PlatformTest} from "@tsed/platform-http/testing";
|
|
2
|
+
|
|
3
|
+
import {SocketIOService} from "../index.js";
|
|
4
|
+
import {Server} from "./SocketIOServer.js";
|
|
5
|
+
|
|
6
|
+
async function createServiceFixture() {
|
|
7
|
+
const namespace = {
|
|
8
|
+
on: vi.fn()
|
|
9
|
+
};
|
|
10
|
+
const ioStub = {
|
|
11
|
+
of: vi.fn().mockReturnValue(namespace)
|
|
12
|
+
};
|
|
13
|
+
const instance = {
|
|
14
|
+
onConnection: vi.fn(),
|
|
15
|
+
onDisconnect: vi.fn()
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const socket = {
|
|
19
|
+
on: vi.fn()
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const service = await PlatformTest.invoke(SocketIOService, [
|
|
23
|
+
{
|
|
24
|
+
token: Server,
|
|
25
|
+
use: ioStub
|
|
26
|
+
}
|
|
27
|
+
]);
|
|
28
|
+
const reason = "transport error";
|
|
29
|
+
|
|
30
|
+
return {namespace, ioStub, service, instance, socket, reason};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
describe("SocketIOService", () => {
|
|
34
|
+
beforeEach(() => PlatformTest.create());
|
|
35
|
+
afterEach(() => PlatformTest.reset());
|
|
36
|
+
|
|
37
|
+
describe("getNsp", () => {
|
|
38
|
+
it.each([{input: "/"}, {input: /test/}])("should call io.of with $input and create namespace", async ({input}) => {
|
|
39
|
+
const {service, namespace, ioStub, socket, instance, reason} = await createServiceFixture();
|
|
40
|
+
|
|
41
|
+
const nspConf = service.getNsp(input);
|
|
42
|
+
nspConf.instances.push(instance);
|
|
43
|
+
|
|
44
|
+
namespace.on.mock.calls[0][1](socket);
|
|
45
|
+
socket.on.mock.calls[0][1](reason);
|
|
46
|
+
|
|
47
|
+
expect(ioStub.of).toHaveBeenCalledWith(input);
|
|
48
|
+
expect(namespace.on).toHaveBeenCalledWith("connection", expect.any(Function));
|
|
49
|
+
expect(instance.onConnection).toHaveBeenCalledWith(socket, namespace);
|
|
50
|
+
expect(socket.on).toHaveBeenCalledWith("disconnect", expect.any(Function));
|
|
51
|
+
expect(instance.onDisconnect).toHaveBeenCalledWith(socket, namespace, reason);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
});
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import {InjectorService, Provider, Service} from "@tsed/di";
|
|
2
|
+
import * as SocketIO from "socket.io"; // tslint:disable-line: no-unused-variable
|
|
3
|
+
|
|
4
|
+
import {SocketHandlersBuilder} from "../class/SocketHandlersBuilder.js";
|
|
5
|
+
import {SocketProviderMetadata} from "../class/SocketProviderMetadata.js";
|
|
6
|
+
import {IO} from "../decorators/io.js";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
*
|
|
10
|
+
*/
|
|
11
|
+
@Service()
|
|
12
|
+
export class SocketIOService {
|
|
13
|
+
/**
|
|
14
|
+
*
|
|
15
|
+
* @type {Map<any, any>}
|
|
16
|
+
*/
|
|
17
|
+
private namespaces: Map<string | RegExp, {nsp: SocketIO.Namespace; instances: any}> = new Map();
|
|
18
|
+
|
|
19
|
+
constructor(
|
|
20
|
+
private injector: InjectorService,
|
|
21
|
+
@IO private io: SocketIO.Server
|
|
22
|
+
) {}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
*
|
|
26
|
+
* @param {string} namespace
|
|
27
|
+
* @returns {SocketIO.Namespace}
|
|
28
|
+
*/
|
|
29
|
+
public getNsp(namespace: string | RegExp = "/"): {nsp: SocketIO.Namespace; instances: any[]} {
|
|
30
|
+
if (!this.namespaces.has(namespace)) {
|
|
31
|
+
const conf = {nsp: this.io.of(namespace), instances: []};
|
|
32
|
+
|
|
33
|
+
this.namespaces.set(namespace, conf);
|
|
34
|
+
|
|
35
|
+
conf.nsp.on("connection", (socket) => {
|
|
36
|
+
conf.instances.forEach((builder: SocketHandlersBuilder) => {
|
|
37
|
+
builder.onConnection(socket, conf.nsp);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
socket.on("disconnect", (reason: string) => {
|
|
41
|
+
conf.instances.forEach((builder: SocketHandlersBuilder) => {
|
|
42
|
+
builder.onDisconnect(socket, conf.nsp, reason);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return this.namespaces.get(namespace)!;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
*
|
|
53
|
+
* @param {Provider<any>} provider
|
|
54
|
+
*/
|
|
55
|
+
public addSocketProvider(provider: Provider<any>) {
|
|
56
|
+
const wsConfig: SocketProviderMetadata = new SocketProviderMetadata(provider.store.get("socketIO"));
|
|
57
|
+
|
|
58
|
+
const nspConfig = this.getNsp(wsConfig.namespace);
|
|
59
|
+
const nsps = new Map();
|
|
60
|
+
|
|
61
|
+
this.namespaces.forEach((value, nsp) => {
|
|
62
|
+
nsps.set(nsp, value.nsp);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
const builder = new SocketHandlersBuilder(provider, this.injector).build(nsps);
|
|
66
|
+
|
|
67
|
+
nspConfig.instances.push(builder);
|
|
68
|
+
}
|
|
69
|
+
}
|