@tsed/socketio 8.0.1 → 8.0.3

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.
Files changed (65) hide show
  1. package/package.json +16 -15
  2. package/src/SocketIOModule.spec.ts +87 -0
  3. package/src/SocketIOModule.ts +113 -0
  4. package/src/class/SocketHandlersBuilder.spec.ts +988 -0
  5. package/src/class/SocketHandlersBuilder.ts +266 -0
  6. package/src/class/SocketProviderMetadata.ts +57 -0
  7. package/src/class/SocketSessionData.spec.ts +190 -0
  8. package/src/class/SocketSessionData.ts +81 -0
  9. package/src/constants/constants.ts +1 -0
  10. package/src/decorators/args.spec.ts +57 -0
  11. package/src/decorators/args.ts +60 -0
  12. package/src/decorators/broadcast.spec.ts +23 -0
  13. package/src/decorators/broadcast.ts +28 -0
  14. package/src/decorators/broadcastOthers.spec.ts +23 -0
  15. package/src/decorators/broadcastOthers.ts +28 -0
  16. package/src/decorators/emit.spec.ts +23 -0
  17. package/src/decorators/emit.ts +28 -0
  18. package/src/decorators/input.spec.ts +22 -0
  19. package/src/decorators/input.ts +33 -0
  20. package/src/decorators/inputAndBroadcast.spec.ts +25 -0
  21. package/src/decorators/inputAndBroadcast.ts +28 -0
  22. package/src/decorators/inputAndBroadcastOthers.spec.ts +24 -0
  23. package/src/decorators/inputAndBroadcastOthers.ts +28 -0
  24. package/src/decorators/inputAndEmit.spec.ts +24 -0
  25. package/src/decorators/inputAndEmit.ts +28 -0
  26. package/src/decorators/io.ts +34 -0
  27. package/src/decorators/nsp.spec.ts +70 -0
  28. package/src/decorators/nsp.ts +101 -0
  29. package/src/decorators/reason.spec.ts +26 -0
  30. package/src/decorators/reason.ts +30 -0
  31. package/src/decorators/socket.spec.ts +26 -0
  32. package/src/decorators/socket.ts +32 -0
  33. package/src/decorators/socketErr.spec.ts +25 -0
  34. package/src/decorators/socketErr.ts +26 -0
  35. package/src/decorators/socketEventName.spec.ts +25 -0
  36. package/src/decorators/socketEventName.ts +26 -0
  37. package/src/decorators/socketFilter.ts +27 -0
  38. package/src/decorators/socketMiddleware.spec.ts +21 -0
  39. package/src/decorators/socketMiddleware.ts +72 -0
  40. package/src/decorators/socketMiddlewareError.spec.ts +22 -0
  41. package/src/decorators/socketMiddlewareError.ts +70 -0
  42. package/src/decorators/socketNsp.spec.ts +26 -0
  43. package/src/decorators/socketNsp.ts +32 -0
  44. package/src/decorators/socketReturns.ts +25 -0
  45. package/src/decorators/socketService.spec.ts +44 -0
  46. package/src/decorators/socketService.ts +24 -0
  47. package/src/decorators/socketSession.spec.ts +47 -0
  48. package/src/decorators/socketSession.ts +53 -0
  49. package/src/decorators/socketUseAfter.spec.ts +38 -0
  50. package/src/decorators/socketUseAfter.ts +69 -0
  51. package/src/decorators/socketUseBefore.spec.ts +34 -0
  52. package/src/decorators/socketUseBefore.ts +73 -0
  53. package/src/index.ts +41 -0
  54. package/src/interfaces/OnNamespaceInit.ts +8 -0
  55. package/src/interfaces/SocketFilters.ts +14 -0
  56. package/src/interfaces/SocketHandlerMetadata.ts +17 -0
  57. package/src/interfaces/SocketInjectableNsp.ts +4 -0
  58. package/src/interfaces/SocketParamMetadata.ts +9 -0
  59. package/src/interfaces/SocketProviderTypes.ts +7 -0
  60. package/src/interfaces/SocketReturnsTypes.ts +8 -0
  61. package/src/interfaces/interfaces.ts +9 -0
  62. package/src/services/SocketIOServer.spec.ts +33 -0
  63. package/src/services/SocketIOServer.ts +15 -0
  64. package/src/services/SocketIOService.spec.ts +54 -0
  65. package/src/services/SocketIOService.ts +69 -0
@@ -0,0 +1,266 @@
1
+ import {isFunction, Store} from "@tsed/core";
2
+ import {DIContext, InjectorService, Provider, runInContext} from "@tsed/di";
3
+ import {deserialize} from "@tsed/json-mapper";
4
+ import {$log} from "@tsed/logger";
5
+ import {Namespace, Socket} from "socket.io";
6
+ import {v4} from "uuid";
7
+
8
+ import {SocketFilters} from "../interfaces/SocketFilters.js";
9
+ import {SocketHandlerMetadata} from "../interfaces/SocketHandlerMetadata.js";
10
+ import {SocketInjectableNsp} from "../interfaces/SocketInjectableNsp.js";
11
+ import {SocketParamMetadata} from "../interfaces/SocketParamMetadata.js";
12
+ import {SocketProviderTypes} from "../interfaces/SocketProviderTypes.js";
13
+ import {SocketReturnsTypes} from "../interfaces/SocketReturnsTypes.js";
14
+ import {SocketProviderMetadata} from "./SocketProviderMetadata.js";
15
+ import {SocketSessionData} from "./SocketSessionData.js";
16
+
17
+ /**
18
+ * @ignore
19
+ */
20
+ export class SocketHandlersBuilder {
21
+ private readonly socketProviderMetadata: SocketProviderMetadata;
22
+
23
+ constructor(
24
+ private readonly provider: Provider,
25
+ private readonly injector: InjectorService
26
+ ) {
27
+ this.socketProviderMetadata = new SocketProviderMetadata(this.provider.store.get("socketIO"));
28
+ }
29
+
30
+ /**
31
+ *
32
+ * @param {SocketHandlerMetadata} handlerMetadata
33
+ * @param scope
34
+ * @returns {(data) => void}
35
+ */
36
+ private static bindResponseMiddleware(handlerMetadata: SocketHandlerMetadata, scope: any) {
37
+ const {returns} = handlerMetadata;
38
+
39
+ return (response: any): void => {
40
+ if (returns) {
41
+ switch (returns.type) {
42
+ case SocketReturnsTypes.BROADCAST:
43
+ scope.nsp.emit(returns.eventName, response);
44
+ break;
45
+ case SocketReturnsTypes.BROADCAST_OTHERS:
46
+ scope.socket.broadcast.emit(returns.eventName, response);
47
+ break;
48
+ case SocketReturnsTypes.EMIT:
49
+ scope.socket.emit(returns.eventName, response);
50
+ break;
51
+ }
52
+ } else {
53
+ const cb = scope.args.at(-1);
54
+ if (cb && isFunction(cb)) {
55
+ cb(response);
56
+ }
57
+ }
58
+ };
59
+ }
60
+
61
+ /**
62
+ *
63
+ * @returns {any}
64
+ */
65
+ public build(nsps: Map<string | RegExp, Namespace>) {
66
+ const instance = this.injector.get(this.provider.token);
67
+ const {injectNamespaces, namespace} = this.socketProviderMetadata;
68
+ const nsp = nsps.get(namespace);
69
+
70
+ instance.$onConnection && this.socketProviderMetadata.createHook("$onConnection", "connection");
71
+ instance.$onDisconnect && this.socketProviderMetadata.createHook("$onDisconnect", "disconnect");
72
+
73
+ injectNamespaces.forEach((setting: SocketInjectableNsp) => {
74
+ instance[setting.propertyKey] = nsps.get(setting.nsp || namespace);
75
+ });
76
+
77
+ instance["nsp"] = nsp;
78
+
79
+ if (instance.$onNamespaceInit) {
80
+ instance.$onNamespaceInit(nsp);
81
+ }
82
+
83
+ return this;
84
+ }
85
+
86
+ /**
87
+ *
88
+ * @param {Socket} socket
89
+ * @param {Namespace} nsp
90
+ */
91
+ public async onConnection(socket: Socket, nsp: Namespace) {
92
+ const {socketProviderMetadata} = this;
93
+ const instance = this.injector.get(this.provider.token);
94
+
95
+ this.buildHandlers(socket, nsp);
96
+
97
+ if (instance.$onConnection) {
98
+ const ctx = this.createContext(socket, nsp);
99
+ await runInContext(ctx, () => this.invoke(instance, socketProviderMetadata.$onConnection, {socket, nsp}), this.injector);
100
+ }
101
+ }
102
+
103
+ public async onDisconnect(socket: Socket, nsp: Namespace, reason?: string) {
104
+ const instance = this.injector.get(this.provider.token);
105
+ const {socketProviderMetadata} = this;
106
+
107
+ if (instance.$onDisconnect) {
108
+ const ctx = this.createContext(socket, nsp);
109
+ await runInContext(ctx, () => this.invoke(instance, socketProviderMetadata.$onDisconnect, {socket, nsp, reason}), this.injector);
110
+ }
111
+ }
112
+
113
+ private buildHandlers(socket: Socket, nsp: Namespace) {
114
+ const {socketProviderMetadata} = this;
115
+
116
+ socketProviderMetadata.getHandlers().forEach((handler) => {
117
+ const {eventName} = handler;
118
+
119
+ if (eventName) {
120
+ socket.on(eventName, async (...args) => {
121
+ const ctx = this.createContext(socket, nsp);
122
+ await runInContext(ctx, () => this.runQueue(handler, args, socket, nsp), this.injector);
123
+ });
124
+ }
125
+ });
126
+ }
127
+
128
+ private runQueue(handlerMetadata: SocketHandlerMetadata, args: any[], socket: Socket, nsp: Namespace) {
129
+ const instance = this.injector.get(this.provider.token);
130
+ const {useBefore, useAfter} = this.socketProviderMetadata;
131
+ const scope = {
132
+ args,
133
+ socket,
134
+ nsp,
135
+ eventName: handlerMetadata.eventName
136
+ };
137
+
138
+ let promise = Promise.resolve().then(() => this.deserialize(handlerMetadata, scope));
139
+
140
+ if (useBefore) {
141
+ useBefore.forEach((target: any) => (promise = this.bindMiddleware(target, scope, promise)));
142
+ }
143
+
144
+ if (handlerMetadata.useBefore) {
145
+ handlerMetadata.useBefore.forEach((target) => (promise = this.bindMiddleware(target, scope, promise)));
146
+ }
147
+
148
+ promise = promise
149
+ .then(() => this.invoke(instance, handlerMetadata, scope))
150
+ .then(SocketHandlersBuilder.bindResponseMiddleware(handlerMetadata, scope));
151
+
152
+ if (handlerMetadata.useAfter) {
153
+ handlerMetadata.useAfter.forEach((target) => (promise = this.bindMiddleware(target, scope, promise)));
154
+ }
155
+
156
+ if (useAfter) {
157
+ useAfter.forEach((target: any) => (promise = this.bindMiddleware(target, scope, promise)));
158
+ }
159
+
160
+ return promise.catch((er: any) => {
161
+ /* istanbul ignore next */
162
+ $log.error(handlerMetadata.eventName, er);
163
+ });
164
+ }
165
+
166
+ private deserialize(handlerMetadata: SocketHandlerMetadata, scope: any) {
167
+ const {parameters} = handlerMetadata;
168
+ Object.keys(parameters || []).forEach((index: any) => {
169
+ const {filter, useMapper, mapIndex, type, collectionType} = parameters![index];
170
+ let value = scope.args[mapIndex!];
171
+
172
+ if (filter === SocketFilters.ARGS) {
173
+ if (useMapper && typeof value !== "function") {
174
+ value = deserialize(value, {
175
+ type,
176
+ collectionType,
177
+ useAlias: true
178
+ });
179
+ }
180
+ scope.args[mapIndex!] = value;
181
+ }
182
+ });
183
+ }
184
+
185
+ private bindMiddleware(target: any, scope: any, promise: Promise<any>): Promise<any> {
186
+ const instance = this.injector.get(target);
187
+
188
+ if (instance) {
189
+ const handlerMetadata: SocketProviderMetadata = new SocketProviderMetadata(Store.from(instance).get("socketIO"));
190
+
191
+ if (handlerMetadata.type === SocketProviderTypes.MIDDLEWARE) {
192
+ if (handlerMetadata.error) {
193
+ return promise.catch((error: any) => this.invoke(instance, handlerMetadata.useHandler, {error, ...scope}));
194
+ }
195
+
196
+ return promise
197
+ .then(() => this.invoke(instance, handlerMetadata.useHandler, scope))
198
+ .then((result: any) => {
199
+ if (result) {
200
+ scope.args = [].concat(result);
201
+ }
202
+ });
203
+ }
204
+ }
205
+
206
+ return promise;
207
+ }
208
+
209
+ private invoke(instance: any, handlerMetadata: SocketHandlerMetadata, scope: any): Promise<any> {
210
+ const {methodClassName, parameters} = handlerMetadata;
211
+
212
+ return instance[methodClassName](...this.buildParameters(parameters!, scope));
213
+ }
214
+
215
+ private buildParameters(parameters: {[key: number]: SocketParamMetadata}, scope: any): any[] {
216
+ return Object.keys(parameters || []).map((index: any) => {
217
+ const param: SocketParamMetadata = parameters[index];
218
+
219
+ switch (param.filter) {
220
+ case SocketFilters.ARGS:
221
+ if (param.mapIndex !== undefined) {
222
+ return scope.args[param.mapIndex];
223
+ }
224
+
225
+ return scope.args;
226
+
227
+ case SocketFilters.EVENT_NAME:
228
+ return scope.eventName;
229
+
230
+ case SocketFilters.SOCKET:
231
+ return scope.socket;
232
+
233
+ case SocketFilters.NSP:
234
+ return scope.nsp;
235
+
236
+ case SocketFilters.ERR:
237
+ return scope.error;
238
+
239
+ case SocketFilters.SESSION:
240
+ return new SocketSessionData(scope.socket.data);
241
+
242
+ case SocketFilters.RAW_SESSION:
243
+ return scope.socket.data;
244
+
245
+ case SocketFilters.SOCKET_NSP:
246
+ return scope.socket.nsp;
247
+
248
+ case SocketFilters.REASON:
249
+ return scope.reason;
250
+ }
251
+ });
252
+ }
253
+
254
+ private createContext(socket: Socket, nsp: Namespace): DIContext {
255
+ return new DIContext({
256
+ injector: this.injector,
257
+ id: v4().split("-").join(""),
258
+ logger: this.injector.logger,
259
+ additionalProps: {
260
+ module: "socket.io",
261
+ sid: socket.id,
262
+ namespace: nsp.name
263
+ }
264
+ });
265
+ }
266
+ }
@@ -0,0 +1,57 @@
1
+ import {SocketHandlerMetadata} from "../interfaces/SocketHandlerMetadata.js";
2
+ import {SocketInjectableNsp} from "../interfaces/SocketInjectableNsp.js";
3
+ import {SocketProviderTypes} from "../interfaces/SocketProviderTypes.js";
4
+
5
+ export class SocketProviderMetadata {
6
+ public type: SocketProviderTypes;
7
+ public namespace: string | RegExp;
8
+ public error: boolean = false;
9
+ public injectNamespaces: SocketInjectableNsp[] = [];
10
+ public useBefore: any[] = [];
11
+ public useAfter: any[] = [];
12
+ public handlers: Record<string, SocketHandlerMetadata> = {};
13
+
14
+ constructor(options: Partial<SocketProviderMetadata> = {}) {
15
+ options.type && (this.type = options.type);
16
+ options.namespace && (this.namespace = options.namespace);
17
+ options.error && (this.error = options.error);
18
+ options.injectNamespaces && (this.injectNamespaces = options.injectNamespaces);
19
+ options.useBefore && (this.useBefore = options.useBefore);
20
+ options.useAfter && (this.useAfter = options.useAfter);
21
+ options.handlers && (this.handlers = options.handlers);
22
+ }
23
+
24
+ get useHandler() {
25
+ return this.get("use");
26
+ }
27
+
28
+ get $onConnection() {
29
+ return this.get("$onConnection");
30
+ }
31
+
32
+ get $onDisconnect() {
33
+ return this.get("$onDisconnect");
34
+ }
35
+
36
+ get(key: string): SocketHandlerMetadata {
37
+ return this.handlers[key];
38
+ }
39
+
40
+ set(key: string, metadata: SocketHandlerMetadata): void {
41
+ this.handlers[key] = metadata;
42
+ }
43
+
44
+ getHandlers() {
45
+ return Object.entries(this.handlers)
46
+ .filter(([key]) => ["$onConnection", "$onDisconnect"].indexOf(key) === -1)
47
+ .map(([, handler]) => handler);
48
+ }
49
+
50
+ createHook(hook: string, eventName: string): void {
51
+ this.set(hook, {
52
+ ...(this.get(hook) || {}),
53
+ eventName,
54
+ methodClassName: hook
55
+ });
56
+ }
57
+ }
@@ -0,0 +1,190 @@
1
+ import {SocketSessionData} from "./SocketSessionData.js";
2
+
3
+ describe("SocketSessionData", () => {
4
+ let socketSessionData!: SocketSessionData;
5
+ let data!: Record<string, unknown>;
6
+
7
+ beforeEach(() => {
8
+ data = {
9
+ key1: "value1",
10
+ key2: "value2"
11
+ };
12
+ socketSessionData = new SocketSessionData(data);
13
+ });
14
+
15
+ describe("Symbol.species", () => {
16
+ it("should return Map constructor", () => {
17
+ // act
18
+ const result = SocketSessionData[Symbol.species];
19
+
20
+ // assert
21
+ expect(result).toBe(Map);
22
+ });
23
+ });
24
+
25
+ describe("instanceof", () => {
26
+ it("should return true when right side is an reference ot Map type", () => {
27
+ // act
28
+ const result = socketSessionData instanceof Map;
29
+
30
+ // assert
31
+ expect(result).toBe(true);
32
+ });
33
+ });
34
+
35
+ describe("size", () => {
36
+ it("should return the size of session data", () => {
37
+ // act
38
+ const size = socketSessionData.size;
39
+
40
+ // assert
41
+ expect(size).toBe(2);
42
+ });
43
+ });
44
+
45
+ describe("clear", () => {
46
+ it("should remove all entries from session data", () => {
47
+ // act
48
+ socketSessionData.clear();
49
+
50
+ // assert
51
+ expect(socketSessionData.size).toBe(0);
52
+ expect(data).toEqual({});
53
+ });
54
+ });
55
+
56
+ describe("delete", () => {
57
+ it("should remove an entry from session data if it exists", () => {
58
+ // arrange
59
+ const keyToDelete = "key1";
60
+
61
+ // act
62
+ const deleted = socketSessionData.delete(keyToDelete);
63
+
64
+ // assert
65
+ expect(deleted).toBe(true);
66
+ expect(socketSessionData.size).toBe(1);
67
+ expect(socketSessionData.has(keyToDelete)).toBe(false);
68
+ expect(data).not.toHaveProperty(keyToDelete);
69
+ });
70
+
71
+ it("should return false if the entry does not exist in session data", () => {
72
+ // arrange
73
+ const keyToDelete = "nonExistentKey";
74
+ const expected = {...data};
75
+
76
+ // act
77
+ const deleted = socketSessionData.delete(keyToDelete);
78
+
79
+ // assert
80
+ expect(deleted).toBe(false);
81
+ expect(socketSessionData.size).toBe(2);
82
+ expect(data).toEqual(expected);
83
+ });
84
+ });
85
+
86
+ describe("get", () => {
87
+ it("should return the value associated with the given key", () => {
88
+ // arrange
89
+ const key = "key2";
90
+
91
+ // act
92
+ const value = socketSessionData.get(key);
93
+
94
+ // assert
95
+ expect(value).toBe("value2");
96
+ });
97
+
98
+ it("should return undefined if the key does not exist", () => {
99
+ // arrange
100
+ const key = "nonExistentKey";
101
+
102
+ // act
103
+ const value = socketSessionData.get(key);
104
+
105
+ // assert
106
+ expect(value).toBeUndefined();
107
+ });
108
+ });
109
+
110
+ describe("set", () => {
111
+ it("should return this", () => {
112
+ // act
113
+ const result = socketSessionData.set("key3", "value3");
114
+
115
+ // assert
116
+ expect(result).toBe(socketSessionData);
117
+ });
118
+
119
+ it("should set the value by the key", () => {
120
+ // arrange
121
+ const key = "key3";
122
+ const value = "value3";
123
+
124
+ // act
125
+ socketSessionData.set(key, value);
126
+
127
+ // assert
128
+ expect([...socketSessionData]).toMatchObject(expect.arrayContaining([[key, value]]));
129
+ });
130
+ });
131
+
132
+ describe("forEach", () => {
133
+ it("should call the callback function for each key-value pair", () => {
134
+ // arrange
135
+ const callbackFn = vi.fn();
136
+
137
+ // act
138
+ socketSessionData.forEach(callbackFn);
139
+
140
+ // assert
141
+ expect(callbackFn).toHaveBeenCalledTimes(2);
142
+ expect(callbackFn).toHaveBeenCalledWith("value1", "key1", socketSessionData);
143
+ expect(callbackFn).toHaveBeenCalledWith("value2", "key2", socketSessionData);
144
+ });
145
+
146
+ it("should call the callback function with the specified thisArg", () => {
147
+ // arrange
148
+ const thisArg = {customProp: "customValue"};
149
+ const callbackFn = vi.fn(function () {
150
+ expect(this).toBe(thisArg);
151
+ });
152
+
153
+ // act
154
+ socketSessionData.forEach(callbackFn, thisArg);
155
+ });
156
+ });
157
+
158
+ describe("values", () => {
159
+ it("should return an iterator for the values", () => {
160
+ // act
161
+ const values = socketSessionData.values();
162
+
163
+ // assert
164
+ expect([...values]).toEqual(["value1", "value2"]);
165
+ });
166
+ });
167
+
168
+ describe("keys", () => {
169
+ it("should return an iterator for the keys", () => {
170
+ // act
171
+ const keys = socketSessionData.keys();
172
+
173
+ // assert
174
+ expect([...keys]).toEqual(["key1", "key2"]);
175
+ });
176
+ });
177
+
178
+ describe("entries", () => {
179
+ it("should return an iterator for the key-value pairs", () => {
180
+ // act
181
+ const entries = [...socketSessionData.entries()];
182
+
183
+ // assert
184
+ expect(entries).toEqual([
185
+ ["key1", "value1"],
186
+ ["key2", "value2"]
187
+ ]);
188
+ });
189
+ });
190
+ });
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Represents session data associated with a socket connection, providing a compatibility layer with Ts.ED v7 by wrapping a `socket.data` which is used to archive recoverability and resiliency to a `Map` instance.
3
+ *
4
+ * This class implements the `Map<string, unknown>` interface and provides methods and properties to manage and manipulate session data.
5
+ *
6
+ * @internal This class is designed for internal use.
7
+ */
8
+ export class SocketSessionData extends Map<string, unknown> {
9
+ readonly #data: Record<string, unknown>;
10
+
11
+ get size(): number {
12
+ return Object.keys(this.#data).length;
13
+ }
14
+
15
+ static get [Symbol.species]() {
16
+ return Map;
17
+ }
18
+
19
+ constructor(data: Record<string, unknown>) {
20
+ super();
21
+ this.#data = data;
22
+ }
23
+
24
+ public *[Symbol.iterator](): IterableIterator<[string, unknown]> {
25
+ for (const key in this.#data) {
26
+ yield [key, this.#data[key]];
27
+ }
28
+ }
29
+
30
+ public clear(): void {
31
+ for (const key in this.#data) {
32
+ delete this.#data[key];
33
+ }
34
+ }
35
+
36
+ public delete(key: string): boolean {
37
+ const hasKey = key in this.#data;
38
+ if (hasKey) {
39
+ delete this.#data[key];
40
+ return true;
41
+ }
42
+ return false;
43
+ }
44
+
45
+ public *entries(): IterableIterator<[string, unknown]> {
46
+ for (const key in this.#data) {
47
+ yield [key, this.#data[key]];
48
+ }
49
+ }
50
+
51
+ public forEach(callbackfn: (value: unknown, key: string, map: Map<string, unknown>) => void, thisArg?: any): void {
52
+ for (const key in this.#data) {
53
+ callbackfn.call(thisArg, this.#data[key], key, this);
54
+ }
55
+ }
56
+
57
+ public get(key: string): unknown | undefined {
58
+ return this.#data[key];
59
+ }
60
+
61
+ public has(key: string): boolean {
62
+ return key in this.#data;
63
+ }
64
+
65
+ public *keys(): IterableIterator<string> {
66
+ for (const key in this.#data) {
67
+ yield key;
68
+ }
69
+ }
70
+
71
+ public set(key: string, value: unknown): this {
72
+ this.#data[key] = value;
73
+ return this;
74
+ }
75
+
76
+ public *values(): IterableIterator<unknown> {
77
+ for (const key in this.#data) {
78
+ yield this.#data[key];
79
+ }
80
+ }
81
+ }
@@ -0,0 +1 @@
1
+ export const PROVIDER_TYPE_SOCKET_SERVICE = "socketService";
@@ -0,0 +1,57 @@
1
+ import {Store} from "@tsed/core";
2
+
3
+ import {Args} from "../index.js";
4
+
5
+ describe("Args", () => {
6
+ describe("without parameters", () => {
7
+ beforeAll(() => {});
8
+
9
+ it("should set metadata", () => {
10
+ class Test {}
11
+
12
+ Args()(Test, "test", 0);
13
+
14
+ const store = Store.from(Test);
15
+
16
+ expect(store.get("socketIO")).toEqual({
17
+ handlers: {
18
+ test: {
19
+ parameters: {
20
+ "0": {
21
+ filter: "args",
22
+ useMapper: false
23
+ }
24
+ }
25
+ }
26
+ }
27
+ });
28
+ });
29
+ });
30
+
31
+ describe("with parameters", () => {
32
+ beforeAll(() => {});
33
+
34
+ it("should set metadata", () => {
35
+ class Test {}
36
+
37
+ Args(1)(Test, "test", 1);
38
+ const store = Store.from(Test);
39
+
40
+ expect(store.get("socketIO")).toEqual({
41
+ handlers: {
42
+ test: {
43
+ parameters: {
44
+ "1": {
45
+ collectionType: undefined,
46
+ filter: "args",
47
+ mapIndex: 1,
48
+ type: undefined,
49
+ useMapper: true
50
+ }
51
+ }
52
+ }
53
+ }
54
+ });
55
+ });
56
+ });
57
+ });