@nestjs/websockets 12.0.0-alpha.4 → 12.0.0-alpha.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 +25 -45
- package/adapters/ws-adapter.js +4 -0
- package/context/exception-filters-context.d.ts +1 -1
- package/context/exception-filters-context.js +3 -3
- package/context/ws-context-creator.d.ts +1 -1
- package/context/ws-context-creator.js +6 -6
- package/gateway-metadata-explorer.js +1 -1
- package/package.json +4 -4
- package/socket-module.d.ts +4 -2
- package/socket-module.js +23 -10
- package/utils/param.utils.js +4 -9
- package/web-sockets-controller.d.ts +17 -5
- package/web-sockets-controller.js +154 -20
package/Readme.md
CHANGED
|
@@ -59,11 +59,11 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
|
|
|
59
59
|
|
|
60
60
|
<table style="text-align:center;">
|
|
61
61
|
<tr>
|
|
62
|
-
<td><a href="https://trilon.io" target="_blank"><img src="https://nestjs.com/img/trilon.svg" width="200" valign="middle" /></a></td>
|
|
63
|
-
<td><a href="https://microsoft.com/" target="_blank"><img src="https://nestjs.com/img/
|
|
64
|
-
<td><a href="https://mojam.co" target="_blank"><img src="https://
|
|
62
|
+
<td><a href="https://trilon.io" target="_blank"><img src="https://nestjs.com/img/github/trilon-logo.svg" width="200" valign="middle" /></a></td>
|
|
63
|
+
<td><a href="https://microsoft.com/" target="_blank"><img src="https://nestjs.com/img/github/microsoft-logo.png" width="180" valign="middle" /></a></td>
|
|
64
|
+
<td><a href="https://mojam.co" target="_blank"><img src="https://images.opencollective.com/mojamco/981e9de/logo/256.png?height=256" width="80" valign="middle" /></a></td>
|
|
65
65
|
<td><a href="https://valor-software.com/" target="_blank"><img src="https://docs.nestjs.com/assets/sponsors/valor-software.png" width="170" valign="middle" /></a></td>
|
|
66
|
-
<td><a href="https://serpapi.com/" target="_blank"><img src="https://nestjs.com/img/
|
|
66
|
+
<td><a href="https://serpapi.com/" target="_blank"><img src="https://nestjs.com/img/github/serpapi-logo.png" width="150" valign="middle" /></a></td>
|
|
67
67
|
</tr>
|
|
68
68
|
</table>
|
|
69
69
|
|
|
@@ -71,15 +71,15 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
|
|
|
71
71
|
|
|
72
72
|
<table style="text-align:center;">
|
|
73
73
|
<tr>
|
|
74
|
-
<td><a href="https://www.redhat.com" target="_blank"><img src="https://nestjs.com/img/
|
|
75
|
-
<td><a href="https://github.com/Sanofi-IADC" target="_blank"><img src="https://docs.nestjs.com/assets/sponsors/sanofi.png" width="
|
|
76
|
-
<td><a href="https://nx.dev" target="_blank"><img src="https://nestjs.com/img/
|
|
77
|
-
<td><a href="https://intrinsic.ventures/" target="_blank"><img src="https://nestjs.com/img/
|
|
78
|
-
<td><a href="https://jetbrains.com/" target="_blank"><img src="https://nestjs.com/img/
|
|
74
|
+
<td><a href="https://www.redhat.com" target="_blank"><img src="https://nestjs.com/img/github/red-hat-logo.svg" width="150" valign="middle" /></a></td>
|
|
75
|
+
<td><a href="https://github.com/Sanofi-IADC" target="_blank"><img src="https://docs.nestjs.com/assets/sponsors/sanofi.png" width="120" valign="middle" /></a></td>
|
|
76
|
+
<td><a href="https://nx.dev" target="_blank"><img src="https://nestjs.com/img/github/nx-logo.png" height="45" valign="middle" /></a></td>
|
|
77
|
+
<td><a href="https://intrinsic.ventures/" target="_blank"><img src="https://nestjs.com/img/github/intrinisic-logo.png" width="150" valign="middle" /></a></td>
|
|
78
|
+
<td><a href="https://jetbrains.com/" target="_blank"><img src="https://nestjs.com/img/github/jetbrains-logo.svg" width="70" valign="middle" /></a></td>
|
|
79
79
|
</tr>
|
|
80
80
|
<tr>
|
|
81
|
-
<td><a href="https://snyk.co/nestjs" target="_blank"><img src="https://nestjs.com/img/
|
|
82
|
-
<td><a href="https://www.movavi.com/imovie-for-windows.html" target="_blank"><img src="https://
|
|
81
|
+
<td><a href="https://snyk.co/nestjs" target="_blank"><img src="https://nestjs.com/img/github/snyk-logo-black.png" width="125" valign="middle" /></a></td>
|
|
82
|
+
<td align="center"><a href="https://www.movavi.com/imovie-for-windows.html" target="_blank"><img src="https://images.opencollective.com/movavi/1fb15e5/avatar/256.png?height=256" width="60" valign="middle" /></a></td>
|
|
83
83
|
</tr>
|
|
84
84
|
</table>
|
|
85
85
|
|
|
@@ -87,15 +87,15 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
|
|
|
87
87
|
|
|
88
88
|
<table style="text-align:center;">
|
|
89
89
|
<tr>
|
|
90
|
-
<td><a href="https://www.mercedes-benz.com/" target="_blank"><img src="https://nestjs.com/img/
|
|
91
|
-
<td><a href="https://
|
|
92
|
-
<td><a href="https://
|
|
93
|
-
<td align="center" valign="middle"><a href="https://
|
|
94
|
-
<td align="center" valign="middle"><a href="https://
|
|
95
|
-
<td align="center" valign="middle"><a href="https://crawljobs.com" target="_blank"><img src="https://nestjs.com/img/logos/crawljobs-logo.svg" width="130" valign="middle" /></a></td>
|
|
90
|
+
<td><a href="https://www.mercedes-benz.com/" target="_blank"><img src="https://nestjs.com/img/github/mercedes-logo.png" width="100" valign="middle" /></a></td>
|
|
91
|
+
<td><a href="https://handsontable.com/docs/react-data-grid/?utm_source=NestJS_GH&utm_medium=sponsorship&utm_campaign=library_sponsorship_2024" target="_blank"><img src="https://nestjs.com/img/github/handsontable-dark-logo.svg#2" width="150" valign="middle" /></a></td>
|
|
92
|
+
<td align="center" valign="middle"><a href="https://www.itflashcards.com/" target="_blank"><img src="https://nestjs.com/img/github/it_flashcards-logo.png" width="170" valign="middle" /></a></td>
|
|
93
|
+
<td align="center" valign="middle"><a href="https://arcjet.com/?ref=nestjs" target="_blank"><img src="https://nestjs.com/img/github/arcjet-logo.svg" width="170" valign="middle" /></a></td>
|
|
94
|
+
<td align="center" valign="middle"><a href="https://pandektes.com" target="_blank"><img src="https://nestjs.com/img/github/pandektes-logo.png" width="65" valign="middle" /></a></td>
|
|
96
95
|
</tr><tr>
|
|
97
|
-
<td align="center" valign="middle"><a href="https://
|
|
98
|
-
<td align="center" valign="middle"><a href="https://
|
|
96
|
+
<td align="center" valign="middle"><a href="https://www.fintechcrafts.com/" target="_blank"><img src="https://opencollective-production.s3.us-west-1.amazonaws.com/account-avatar/935813df-48a9-4b41-b923-7d70b5621c6b/2026-05-06%2010%2021%2033.png" width="65" valign="middle" /></a></td>
|
|
97
|
+
<td align="center" valign="middle"><a href="https://talordata.com/?campaignid=Ya5Xpw2gmhyee6Tg&utm_source=nestjs&utm_term=nestjs" target="_blank"><img src="https://images.opencollective.com/elowen/9ccac7f/avatar/512.png" width="65" valign="middle" /></a></td>
|
|
98
|
+
<td align="center" valign="middle"><a href="https://memory2.co/" target="_blank"><img src="https://images.opencollective.com/memory-squared/bbe37f5/avatar/256.png?height=50" width="65" valign="middle" /></a></td>
|
|
99
99
|
</tr>
|
|
100
100
|
</table>
|
|
101
101
|
|
|
@@ -103,32 +103,12 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
|
|
|
103
103
|
|
|
104
104
|
<table>
|
|
105
105
|
<tr>
|
|
106
|
-
<td align="center" valign="middle"><a href="https://
|
|
107
|
-
<td align="center" valign="middle"><a href="https://
|
|
108
|
-
<td align="center" valign="middle"><a href="https://
|
|
109
|
-
<td align="center" valign="middle"><a href="https://
|
|
110
|
-
<td align="center" valign="middle"><a href="https://
|
|
111
|
-
<td align="center" valign="middle"><a href="https://
|
|
112
|
-
</tr>
|
|
113
|
-
<tr>
|
|
114
|
-
<td align="center" valign="middle"><a href="https://vpn-review.com/vpn-for-torrenting" target="_blank"><img src="https://nestjs.com/img/logos/vpn-review-logo.png" width="85" valign="middle" /></a></td>
|
|
115
|
-
<td align="center" valign="middle"><a href="https://lambda-it.ch/" target="_blank"><img src="https://nestjs.com/img/logos/lambda-it-logo.svg" width="115" valign="middle" /></a></td>
|
|
116
|
-
<td align="center" valign="middle"><a href="https://rocketech.it/cases/?utm_source=google&utm_medium=badge&utm_campaign=nestjs" target="_blank"><img src="https://nestjs.com/img/logos/rocketech-logo.svg" width="110" valign="middle" /></a></td>
|
|
117
|
-
<td align="center" valign="middle"><a href="https://www.anonymistic.com/" target="_blank"><img src="https://nestjs.com/img/logos/anonymistic-logo.png" width="125" valign="middle" /></a></td>
|
|
118
|
-
<td align="center" valign="middle"><a href="https://www.naologic.com/" target="_blank"><img src="https://nestjs.com/img/logos/naologic-logo.svg" width="125" valign="middle" /></a></td>
|
|
119
|
-
<td align="center" valign="middle"><a href="https://triplecore.io" target="_blank"><img src="https://nestjs.com/img/logos/triplecore-logo.svg" width="50" valign="middle" /></a></td>
|
|
120
|
-
</tr>
|
|
121
|
-
<tr>
|
|
122
|
-
<td align="center" valign="middle"><a href="https://polygon-software.ch/" target="_blank"><img src="https://nestjs.com/img/logos/polygon-logo.svg" width="120" valign="middle" /></a></td>
|
|
123
|
-
<td align="center" valign="middle"><a href="https://boringowl.io/" target="_blank"><img src="https://nestjs.com/img/logos/boringowl-logo.svg" width="120" valign="middle" /></a></td>
|
|
124
|
-
<td align="center" valign="middle"><a href="https://nordbot.app/" target="_blank"><img src="https://nestjs.com/img/logos/nordbot-logo.png" width="120" valign="middle" /></a></td>
|
|
125
|
-
<td align="center" valign="middle"><a href="https://doppio.sh/" target="_blank"><img src="https://nestjs.com/img/logos/dopiosh-logo.png" width="50" valign="middle" /></a></td>
|
|
126
|
-
<td align="center" valign="middle"><a href="https://www.hingehealth.com/" target="_blank"><img src="https://nestjs.com/img/logos/hinge-health-logo.svg" width="100" valign="middle" /></a></td>
|
|
127
|
-
<td align="center" valign="middle"><a href="https://www.tripoffice.com/" target="_blank"><img src="https://nestjs.com/img/logos/tripoffice-logo.png" width="140" valign="middle" /></a></td>
|
|
128
|
-
</tr>
|
|
129
|
-
<tr>
|
|
130
|
-
<td align="center" valign="middle"><a href="https://solcellsforetag.se/" target="_blank"><img src="https://nestjs.com/img/logos/solcellsforetag-logo.svg" width="140" valign="middle" /></a></td>
|
|
131
|
-
<td align="center" valign="middle"><a href="https://www.route4me.com/" target="_blank"><img src="https://nestjs.com/img/logos/route4me-logo.svg" width="100" valign="middle" /></a></td>
|
|
106
|
+
<td align="center" valign="middle"><a href="https://mantro.net/" target="_blank"><img src="https://nestjs.com/img/github/mantro-logo.svg" width="95" valign="middle" /></a></td>
|
|
107
|
+
<td align="center" valign="middle"><a href="https://triplebyte.com/" target="_blank"><img src="https://nestjs.com/img/github/triplebyte-logo.png" width="107" valign="middle" /></a></td>
|
|
108
|
+
<td align="center" valign="middle"><a href="https://nearpod.com/" target="_blank"><img src="https://nestjs.com/img/github/nearpod-logo.svg" width="100" valign="middle" /></a></td>
|
|
109
|
+
<td align="center" valign="middle"><a href="https://www.naologic.com/" target="_blank"><img src="https://nestjs.com/img/github/naologic-logo.svg" width="125" valign="middle" /></a></td>
|
|
110
|
+
<td align="center" valign="middle"><a href="https://triplecore.io" target="_blank"><img src="https://nestjs.com/img/github/triplecore-logo.svg" width="50" valign="middle" /></a>
|
|
111
|
+
<td align="center" valign="middle"><a href="https://www.hingehealth.com/" target="_blank"><img src="https://nestjs.com/img/github/hinge-health-logo.svg" width="100" valign="middle" /></a></td>
|
|
132
112
|
</tr>
|
|
133
113
|
</table>
|
|
134
114
|
|
package/adapters/ws-adapter.js
CHANGED
|
@@ -22,6 +22,10 @@ export class AbstractWsAdapter {
|
|
|
22
22
|
server.on(CONNECTION_EVENT, callback);
|
|
23
23
|
}
|
|
24
24
|
bindClientDisconnect(client, callback) {
|
|
25
|
+
if (typeof client.once === 'function') {
|
|
26
|
+
client.once(DISCONNECT_EVENT, callback);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
25
29
|
client.on(DISCONNECT_EVENT, callback);
|
|
26
30
|
}
|
|
27
31
|
async close(server) {
|
|
@@ -6,6 +6,6 @@ import type { NestContainer } from '@nestjs/core';
|
|
|
6
6
|
*/
|
|
7
7
|
export declare class ExceptionFiltersContext extends BaseExceptionFilterContext {
|
|
8
8
|
constructor(container: NestContainer);
|
|
9
|
-
create(instance: object, callback: <TClient>(client: TClient, data: any) => any, moduleKey: string): WsExceptionsHandler;
|
|
9
|
+
create(instance: object, callback: <TClient>(client: TClient, data: any) => any, moduleKey: string, contextId?: import("@nestjs/core").ContextId, inquirerId?: string): WsExceptionsHandler;
|
|
10
10
|
getGlobalMetadata<T extends any[]>(): T;
|
|
11
11
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { WsExceptionsHandler } from '../exceptions/ws-exceptions-handler.js';
|
|
2
2
|
import { EXCEPTION_FILTERS_METADATA, isEmptyArray, } from '@nestjs/common/internal';
|
|
3
|
-
import { BaseExceptionFilterContext } from '@nestjs/core/internal';
|
|
3
|
+
import { BaseExceptionFilterContext, STATIC_CONTEXT, } from '@nestjs/core/internal';
|
|
4
4
|
/**
|
|
5
5
|
* @publicApi
|
|
6
6
|
*/
|
|
@@ -8,10 +8,10 @@ export class ExceptionFiltersContext extends BaseExceptionFilterContext {
|
|
|
8
8
|
constructor(container) {
|
|
9
9
|
super(container);
|
|
10
10
|
}
|
|
11
|
-
create(instance, callback, moduleKey) {
|
|
11
|
+
create(instance, callback, moduleKey, contextId = STATIC_CONTEXT, inquirerId) {
|
|
12
12
|
this.moduleContext = moduleKey;
|
|
13
13
|
const exceptionHandler = new WsExceptionsHandler();
|
|
14
|
-
const filters = this.createContext(instance, callback, EXCEPTION_FILTERS_METADATA);
|
|
14
|
+
const filters = this.createContext(instance, callback, EXCEPTION_FILTERS_METADATA, contextId, inquirerId);
|
|
15
15
|
if (isEmptyArray(filters)) {
|
|
16
16
|
return exceptionHandler;
|
|
17
17
|
}
|
|
@@ -25,7 +25,7 @@ export declare class WsContextCreator {
|
|
|
25
25
|
private readonly wsParamsFactory;
|
|
26
26
|
private readonly handlerMetadataStorage;
|
|
27
27
|
constructor(wsProxy: WsProxy, exceptionFiltersContext: ExceptionFiltersContext, pipesContextCreator: PipesContextCreator, pipesConsumer: PipesConsumer, guardsContextCreator: GuardsContextCreator, guardsConsumer: GuardsConsumer, interceptorsContextCreator: InterceptorsContextCreator, interceptorsConsumer: InterceptorsConsumer);
|
|
28
|
-
create<T extends ParamsMetadata = ParamsMetadata>(instance: Controller, callback: (...args: unknown[]) => void, moduleKey: string, methodName: string): (...args: any[]) => Promise<void>;
|
|
28
|
+
create<T extends ParamsMetadata = ParamsMetadata>(instance: Controller, callback: (...args: unknown[]) => void, moduleKey: string, methodName: string, contextId?: import("@nestjs/core").ContextId, inquirerId?: string): (...args: any[]) => Promise<void>;
|
|
29
29
|
reflectCallbackParamtypes(instance: Controller, callback: (...args: any[]) => any): any[];
|
|
30
30
|
reflectCallbackPattern(callback: (...args: any[]) => any): string;
|
|
31
31
|
createGuardsFn<TContext extends string = ContextType>(guards: any[], instance: Controller, callback: (...args: unknown[]) => any, contextType?: TContext): Function | null;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CUSTOM_ROUTE_ARGS_METADATA, isEmptyArray, PARAMTYPES_METADATA, } from '@nestjs/common/internal';
|
|
2
|
-
import { ContextUtils, FORBIDDEN_MESSAGE, HandlerMetadataStorage, } from '@nestjs/core/internal';
|
|
2
|
+
import { ContextUtils, FORBIDDEN_MESSAGE, HandlerMetadataStorage, STATIC_CONTEXT, } from '@nestjs/core/internal';
|
|
3
3
|
import { MESSAGE_METADATA, PARAM_ARGS_METADATA } from '../constants.js';
|
|
4
4
|
import { WsException } from '../errors/ws-exception.js';
|
|
5
5
|
import { WsParamsFactory } from '../factories/ws-params-factory.js';
|
|
@@ -26,13 +26,13 @@ export class WsContextCreator {
|
|
|
26
26
|
this.interceptorsContextCreator = interceptorsContextCreator;
|
|
27
27
|
this.interceptorsConsumer = interceptorsConsumer;
|
|
28
28
|
}
|
|
29
|
-
create(instance, callback, moduleKey, methodName) {
|
|
29
|
+
create(instance, callback, moduleKey, methodName, contextId = STATIC_CONTEXT, inquirerId) {
|
|
30
30
|
const contextType = 'ws';
|
|
31
31
|
const { argsLength, paramtypes, getParamsMetadata } = this.getMetadata(instance, methodName, contextType);
|
|
32
|
-
const exceptionHandler = this.exceptionFiltersContext.create(instance, callback, moduleKey);
|
|
33
|
-
const pipes = this.pipesContextCreator.create(instance, callback, moduleKey);
|
|
34
|
-
const guards = this.guardsContextCreator.create(instance, callback, moduleKey);
|
|
35
|
-
const interceptors = this.interceptorsContextCreator.create(instance, callback, moduleKey);
|
|
32
|
+
const exceptionHandler = this.exceptionFiltersContext.create(instance, callback, moduleKey, contextId, inquirerId);
|
|
33
|
+
const pipes = this.pipesContextCreator.create(instance, callback, moduleKey, contextId, inquirerId);
|
|
34
|
+
const guards = this.guardsContextCreator.create(instance, callback, moduleKey, contextId, inquirerId);
|
|
35
|
+
const interceptors = this.interceptorsContextCreator.create(instance, callback, moduleKey, contextId, inquirerId);
|
|
36
36
|
const paramsMetadata = getParamsMetadata(moduleKey);
|
|
37
37
|
const paramsOptions = paramsMetadata
|
|
38
38
|
? this.contextUtils.mergeParamsMetatypes(paramsMetadata, paramtypes)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nestjs/websockets",
|
|
3
|
-
"version": "12.0.0-alpha.
|
|
3
|
+
"version": "12.0.0-alpha.6",
|
|
4
4
|
"description": "Nest - modern, fast, powerful node.js web framework (@websockets)",
|
|
5
5
|
"author": "Kamil Mysliwiec",
|
|
6
6
|
"license": "MIT",
|
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
"tslib": "2.8.1"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@nestjs/common": "^12.0.0-alpha.
|
|
30
|
-
"@nestjs/core": "^12.0.0-alpha.
|
|
29
|
+
"@nestjs/common": "^12.0.0-alpha.6",
|
|
30
|
+
"@nestjs/core": "^12.0.0-alpha.6"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"@nestjs/common": "^11.0.0",
|
|
@@ -41,5 +41,5 @@
|
|
|
41
41
|
"optional": true
|
|
42
42
|
}
|
|
43
43
|
},
|
|
44
|
-
"gitHead": "
|
|
44
|
+
"gitHead": "4c38a5ab100f1d2a0d50602998968a25509525c7"
|
|
45
45
|
}
|
package/socket-module.d.ts
CHANGED
|
@@ -7,10 +7,12 @@ export declare class SocketModule<THttpServer = any, TAppOptions extends NestApp
|
|
|
7
7
|
private applicationConfig;
|
|
8
8
|
private webSocketsController;
|
|
9
9
|
private isAdapterInitialized;
|
|
10
|
+
private adapterInitPromise;
|
|
10
11
|
private httpServer;
|
|
11
12
|
private appOptions;
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
private injector;
|
|
14
|
+
register(container: NestContainer, applicationConfig: ApplicationConfig, graphInspector: GraphInspector, appOptions: TAppOptions, httpServer?: THttpServer): Promise<void[][]>;
|
|
15
|
+
connectAllGateways(providers: Map<InjectionToken, InstanceWrapper<Injectable>>, moduleName: string): Promise<void[]>;
|
|
14
16
|
connectGatewayToServer(wrapper: InstanceWrapper<Injectable>, moduleName: string): Promise<void>;
|
|
15
17
|
close(): Promise<any>;
|
|
16
18
|
private initializeAdapter;
|
package/socket-module.js
CHANGED
|
@@ -6,28 +6,38 @@ import { WsProxy } from './context/ws-proxy.js';
|
|
|
6
6
|
import { SocketServerProvider } from './socket-server-provider.js';
|
|
7
7
|
import { SocketsContainer } from './sockets-container.js';
|
|
8
8
|
import { WebSocketsController } from './web-sockets-controller.js';
|
|
9
|
-
import { GuardsConsumer, GuardsContextCreator, loadAdapter, InterceptorsConsumer, InterceptorsContextCreator, PipesConsumer, PipesContextCreator, } from '@nestjs/core/internal';
|
|
9
|
+
import { Injector, GuardsConsumer, GuardsContextCreator, loadAdapter, InterceptorsConsumer, InterceptorsContextCreator, PipesConsumer, PipesContextCreator, } from '@nestjs/core/internal';
|
|
10
10
|
export class SocketModule {
|
|
11
11
|
socketsContainer = new SocketsContainer();
|
|
12
12
|
applicationConfig;
|
|
13
13
|
webSocketsController;
|
|
14
14
|
isAdapterInitialized;
|
|
15
|
+
adapterInitPromise = null;
|
|
15
16
|
httpServer;
|
|
16
17
|
appOptions;
|
|
18
|
+
injector;
|
|
17
19
|
register(container, applicationConfig, graphInspector, appOptions, httpServer) {
|
|
18
20
|
this.applicationConfig = applicationConfig;
|
|
19
21
|
this.appOptions = appOptions;
|
|
20
22
|
this.httpServer = httpServer;
|
|
21
|
-
|
|
23
|
+
this.injector = new Injector({
|
|
24
|
+
preview: container.contextOptions?.preview,
|
|
25
|
+
instanceDecorator: container.contextOptions?.instrument?.instanceDecorator,
|
|
26
|
+
});
|
|
27
|
+
const exceptionFiltersContext = new ExceptionFiltersContext(container);
|
|
28
|
+
const contextCreator = this.getContextCreator(container, applicationConfig, exceptionFiltersContext);
|
|
22
29
|
const serverProvider = new SocketServerProvider(this.socketsContainer, applicationConfig);
|
|
23
|
-
this.webSocketsController = new WebSocketsController(serverProvider, applicationConfig, contextCreator, graphInspector, this.appOptions);
|
|
30
|
+
this.webSocketsController = new WebSocketsController(serverProvider, applicationConfig, contextCreator, container, this.injector, exceptionFiltersContext, graphInspector, this.appOptions);
|
|
24
31
|
const modules = container.getModules();
|
|
25
|
-
|
|
32
|
+
return Promise.all(iterate(modules.entries())
|
|
33
|
+
.map(([moduleName, { providers }]) => this.connectAllGateways(providers, moduleName))
|
|
34
|
+
.toArray());
|
|
26
35
|
}
|
|
27
36
|
connectAllGateways(providers, moduleName) {
|
|
28
|
-
iterate(providers.values())
|
|
37
|
+
return Promise.all(iterate(providers.values())
|
|
29
38
|
.filter(wrapper => wrapper && !wrapper.isNotMetatype)
|
|
30
|
-
.
|
|
39
|
+
.map(wrapper => this.connectGatewayToServer(wrapper, moduleName))
|
|
40
|
+
.toArray());
|
|
31
41
|
}
|
|
32
42
|
async connectGatewayToServer(wrapper, moduleName) {
|
|
33
43
|
const { instance, metatype } = wrapper;
|
|
@@ -36,9 +46,12 @@ export class SocketModule {
|
|
|
36
46
|
return;
|
|
37
47
|
}
|
|
38
48
|
if (!this.isAdapterInitialized) {
|
|
39
|
-
|
|
49
|
+
// Memoize the initialization promise so concurrent gateway connections
|
|
50
|
+
// share a single adapter instead of racing to create their own.
|
|
51
|
+
this.adapterInitPromise ??= this.initializeAdapter();
|
|
52
|
+
await this.adapterInitPromise;
|
|
40
53
|
}
|
|
41
|
-
this.webSocketsController.connectGatewayToServer(
|
|
54
|
+
this.webSocketsController.connectGatewayToServer(wrapper, moduleName);
|
|
42
55
|
}
|
|
43
56
|
async close() {
|
|
44
57
|
if (!this.applicationConfig) {
|
|
@@ -71,7 +84,7 @@ export class SocketModule {
|
|
|
71
84
|
this.applicationConfig.setIoAdapter(ioAdapter);
|
|
72
85
|
this.isAdapterInitialized = true;
|
|
73
86
|
}
|
|
74
|
-
getContextCreator(container) {
|
|
75
|
-
return new WsContextCreator(new WsProxy(),
|
|
87
|
+
getContextCreator(container, config, exceptionFiltersContext) {
|
|
88
|
+
return new WsContextCreator(new WsProxy(), exceptionFiltersContext, new PipesContextCreator(container, config), new PipesConsumer(), new GuardsContextCreator(container, config), new GuardsConsumer(), new InterceptorsContextCreator(container, config), new InterceptorsConsumer());
|
|
76
89
|
}
|
|
77
90
|
}
|
package/utils/param.utils.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { assignMetadata } from '@nestjs/common';
|
|
2
|
-
import { isNil, isString } from '@nestjs/common/internal';
|
|
2
|
+
import { isNil, isParameterDecoratorOptions, isString, } from '@nestjs/common/internal';
|
|
3
3
|
import 'reflect-metadata';
|
|
4
4
|
import { PARAM_ARGS_METADATA } from '../constants.js';
|
|
5
5
|
export function createWsParamDecorator(paramtype) {
|
|
@@ -11,10 +11,7 @@ export function createWsParamDecorator(paramtype) {
|
|
|
11
11
|
}
|
|
12
12
|
export const createPipesWsParamDecorator = (paramtype) => (data, optionsOrPipe, ...pipes) => (target, key, index) => {
|
|
13
13
|
const args = Reflect.getMetadata(PARAM_ARGS_METADATA, target.constructor, key) || {};
|
|
14
|
-
const isDataOptions = data
|
|
15
|
-
typeof data === 'object' &&
|
|
16
|
-
!('transform' in data) &&
|
|
17
|
-
('schema' in data || 'pipes' in data);
|
|
14
|
+
const isDataOptions = isParameterDecoratorOptions(data);
|
|
18
15
|
if (isDataOptions) {
|
|
19
16
|
const opts = data;
|
|
20
17
|
Reflect.defineMetadata(PARAM_ARGS_METADATA, assignMetadata(args, paramtype, index, {
|
|
@@ -25,12 +22,10 @@ export const createPipesWsParamDecorator = (paramtype) => (data, optionsOrPipe,
|
|
|
25
22
|
}
|
|
26
23
|
const hasParamData = isNil(data) || isString(data);
|
|
27
24
|
const paramData = hasParamData ? data : undefined;
|
|
28
|
-
const isOptions = optionsOrPipe
|
|
29
|
-
typeof optionsOrPipe === 'object' &&
|
|
30
|
-
('schema' in optionsOrPipe || 'pipes' in optionsOrPipe);
|
|
25
|
+
const isOptions = isParameterDecoratorOptions(optionsOrPipe);
|
|
31
26
|
let paramPipes;
|
|
32
27
|
if (isOptions) {
|
|
33
|
-
paramPipes = optionsOrPipe.pipes ?? [];
|
|
28
|
+
paramPipes = [...(optionsOrPipe.pipes ?? []), ...pipes];
|
|
34
29
|
}
|
|
35
30
|
else if (hasParamData) {
|
|
36
31
|
paramPipes = [optionsOrPipe, ...pipes].filter(Boolean);
|
|
@@ -7,26 +7,38 @@ import { ServerAndEventStreamsHost } from './interfaces/server-and-event-streams
|
|
|
7
7
|
import { SocketServerProvider } from './socket-server-provider.js';
|
|
8
8
|
import type { NestApplicationContextOptions } from '@nestjs/common/internal';
|
|
9
9
|
import { type Type } from '@nestjs/common';
|
|
10
|
-
import { type ApplicationConfig, type GraphInspector } from '@nestjs/core';
|
|
10
|
+
import { type ApplicationConfig, type ContextId, type GraphInspector, type NestContainer } from '@nestjs/core';
|
|
11
|
+
import { type Injector, type InstanceWrapper, type Module } from '@nestjs/core/internal';
|
|
12
|
+
import { ExceptionFiltersContext } from './context/exception-filters-context.js';
|
|
11
13
|
export declare class WebSocketsController {
|
|
12
14
|
private readonly socketServerProvider;
|
|
13
15
|
private readonly config;
|
|
14
16
|
private readonly contextCreator;
|
|
17
|
+
private readonly container;
|
|
18
|
+
private readonly injector;
|
|
19
|
+
private readonly exceptionFiltersContext;
|
|
15
20
|
private readonly graphInspector;
|
|
16
21
|
private readonly appOptions;
|
|
17
22
|
private readonly logger;
|
|
18
23
|
private readonly metadataExplorer;
|
|
19
|
-
|
|
24
|
+
private readonly exceptionFiltersCache;
|
|
25
|
+
constructor(socketServerProvider: SocketServerProvider, config: ApplicationConfig, contextCreator: WsContextCreator, container: NestContainer, injector: Injector, exceptionFiltersContext: ExceptionFiltersContext, graphInspector: GraphInspector, appOptions?: NestApplicationContextOptions);
|
|
26
|
+
connectGatewayToServer(instanceWrapper: InstanceWrapper<NestGateway>, moduleKey: string): void;
|
|
20
27
|
connectGatewayToServer(instance: NestGateway, metatype: Type<unknown> | Function, moduleKey: string, instanceWrapperId: string): void;
|
|
28
|
+
subscribeToServerEvents<T extends GatewayMetadata>(instanceWrapper: InstanceWrapper<NestGateway>, options: T, port: number, moduleKey: string, instanceWrapperId: string): void;
|
|
21
29
|
subscribeToServerEvents<T extends GatewayMetadata>(instance: NestGateway, options: T, port: number, moduleKey: string, instanceWrapperId: string): void;
|
|
22
|
-
subscribeEvents(
|
|
30
|
+
subscribeEvents(instanceWrapper: InstanceWrapper<NestGateway>, subscribersMap: MessageMappingProperties[], observableServer: ServerAndEventStreamsHost, connectionHandler?: Function, disconnectHandler?: Function): void;
|
|
23
31
|
getConnectionHandler(context: WebSocketsController, instance: NestGateway, subscribersMap: MessageMappingProperties[], disconnect: Subject<any>, connection: Subject<any>): (...args: unknown[]) => void;
|
|
24
32
|
subscribeInitEvent(instance: NestGateway, event: Subject<any>): void;
|
|
25
|
-
subscribeConnectionEvent(
|
|
26
|
-
subscribeDisconnectEvent(
|
|
33
|
+
subscribeConnectionEvent(handlerOrGateway: Function | NestGateway | undefined, event: Subject<any>): void;
|
|
34
|
+
subscribeDisconnectEvent(handlerOrGateway: Function | NestGateway | undefined, event: Subject<any>): void;
|
|
27
35
|
subscribeMessages<T = any>(subscribersMap: MessageMappingProperties[], client: T, instance: NestGateway): void;
|
|
28
36
|
pickResult(deferredResult: Promise<any>): Promise<Observable<any>>;
|
|
29
37
|
inspectEntrypointDefinitions(instance: NestGateway, port: number, messageHandlers: MessageMappingProperties[], instanceWrapperId: string): void;
|
|
38
|
+
createRequestScopedHandler(instanceWrapper: InstanceWrapper<NestGateway>, moduleRef: Module, moduleKey: string, methodName: string): (...args: unknown[]) => Promise<void>;
|
|
39
|
+
createRequestScopedEventHandler(instanceWrapper: InstanceWrapper<NestGateway>, moduleRef: Module, moduleKey: string, methodName: 'handleConnection' | 'handleDisconnect', server: object): (...args: unknown[]) => Promise<unknown>;
|
|
40
|
+
getContextId<T extends Record<any, unknown> = any>(request: T, isTreeDurable: boolean): ContextId;
|
|
41
|
+
private cleanupRequestScopedContext;
|
|
30
42
|
private assignServerToProperties;
|
|
31
43
|
private printSubscriptionLogs;
|
|
32
44
|
}
|
|
@@ -5,38 +5,84 @@ import { InvalidSocketPortException } from './errors/invalid-socket-port.excepti
|
|
|
5
5
|
import { GatewayMetadataExplorer, } from './gateway-metadata-explorer.js';
|
|
6
6
|
import { compareElementAt } from './utils/compare-element.util.js';
|
|
7
7
|
import { Logger } from '@nestjs/common';
|
|
8
|
-
import { MetadataScanner, } from '@nestjs/core';
|
|
8
|
+
import { ContextIdFactory, MetadataScanner, } from '@nestjs/core';
|
|
9
|
+
import { ExecutionContextHost, REQUEST_CONTEXT_ID, STATIC_CONTEXT, } from '@nestjs/core/internal';
|
|
9
10
|
export class WebSocketsController {
|
|
10
11
|
socketServerProvider;
|
|
11
12
|
config;
|
|
12
13
|
contextCreator;
|
|
14
|
+
container;
|
|
15
|
+
injector;
|
|
16
|
+
exceptionFiltersContext;
|
|
13
17
|
graphInspector;
|
|
14
18
|
appOptions;
|
|
15
19
|
logger = new Logger(WebSocketsController.name, {
|
|
16
20
|
timestamp: true,
|
|
17
21
|
});
|
|
18
22
|
metadataExplorer = new GatewayMetadataExplorer(new MetadataScanner());
|
|
19
|
-
|
|
23
|
+
exceptionFiltersCache = new WeakMap();
|
|
24
|
+
constructor(socketServerProvider, config, contextCreator, container, injector, exceptionFiltersContext, graphInspector, appOptions = {}) {
|
|
20
25
|
this.socketServerProvider = socketServerProvider;
|
|
21
26
|
this.config = config;
|
|
22
27
|
this.contextCreator = contextCreator;
|
|
28
|
+
this.container = container;
|
|
29
|
+
this.injector = injector;
|
|
30
|
+
this.exceptionFiltersContext = exceptionFiltersContext;
|
|
23
31
|
this.graphInspector = graphInspector;
|
|
24
32
|
this.appOptions = appOptions;
|
|
25
33
|
}
|
|
26
|
-
connectGatewayToServer(
|
|
27
|
-
const
|
|
28
|
-
|
|
34
|
+
connectGatewayToServer(instanceOrWrapper, metatypeOrModuleKey, moduleKey, instanceWrapperId) {
|
|
35
|
+
const isInstanceWrapper = typeof metatypeOrModuleKey === 'string' &&
|
|
36
|
+
'instance' in instanceOrWrapper;
|
|
37
|
+
const instance = isInstanceWrapper
|
|
38
|
+
? instanceOrWrapper.instance
|
|
39
|
+
: instanceOrWrapper;
|
|
40
|
+
const metatype = isInstanceWrapper
|
|
41
|
+
? instanceOrWrapper.metatype
|
|
42
|
+
: metatypeOrModuleKey;
|
|
43
|
+
const targetModuleKey = isInstanceWrapper
|
|
44
|
+
? metatypeOrModuleKey
|
|
45
|
+
: moduleKey;
|
|
46
|
+
const targetInstanceWrapperId = isInstanceWrapper
|
|
47
|
+
? instanceOrWrapper.id
|
|
48
|
+
: instanceWrapperId;
|
|
49
|
+
const instanceWrapper = isInstanceWrapper
|
|
50
|
+
? instanceOrWrapper
|
|
51
|
+
: {
|
|
52
|
+
instance,
|
|
53
|
+
metatype,
|
|
54
|
+
id: targetInstanceWrapperId,
|
|
55
|
+
isDependencyTreeStatic: () => true,
|
|
56
|
+
isDependencyTreeDurable: () => false,
|
|
57
|
+
};
|
|
58
|
+
const gatewayMetatype = metatype ?? instance.constructor;
|
|
59
|
+
const options = Reflect.getMetadata(GATEWAY_OPTIONS, gatewayMetatype) || {};
|
|
60
|
+
const port = Reflect.getMetadata(PORT_METADATA, gatewayMetatype) || 0;
|
|
29
61
|
if (!Number.isInteger(port)) {
|
|
30
|
-
throw new InvalidSocketPortException(port,
|
|
62
|
+
throw new InvalidSocketPortException(port, gatewayMetatype);
|
|
31
63
|
}
|
|
32
|
-
this.subscribeToServerEvents(
|
|
64
|
+
this.subscribeToServerEvents(instanceWrapper, options, port, targetModuleKey, targetInstanceWrapperId);
|
|
33
65
|
}
|
|
34
|
-
subscribeToServerEvents(
|
|
66
|
+
subscribeToServerEvents(instanceOrWrapper, options, port, moduleKey, instanceWrapperId) {
|
|
67
|
+
const instanceWrapper = 'instance' in instanceOrWrapper
|
|
68
|
+
? instanceOrWrapper
|
|
69
|
+
: {
|
|
70
|
+
instance: instanceOrWrapper,
|
|
71
|
+
metatype: instanceOrWrapper.constructor,
|
|
72
|
+
id: instanceWrapperId,
|
|
73
|
+
isDependencyTreeStatic: () => true,
|
|
74
|
+
isDependencyTreeDurable: () => false,
|
|
75
|
+
};
|
|
76
|
+
const { instance } = instanceWrapper;
|
|
35
77
|
const nativeMessageHandlers = this.metadataExplorer.explore(instance);
|
|
78
|
+
const isStatic = instanceWrapper.isDependencyTreeStatic();
|
|
79
|
+
const moduleRef = this.container.getModuleByKey(moduleKey);
|
|
36
80
|
const messageHandlers = nativeMessageHandlers.map(({ callback, isAckHandledManually, message, methodName }) => ({
|
|
37
81
|
message,
|
|
38
82
|
methodName,
|
|
39
|
-
callback:
|
|
83
|
+
callback: isStatic
|
|
84
|
+
? this.contextCreator.create(instance, callback, moduleKey, methodName, STATIC_CONTEXT)
|
|
85
|
+
: this.createRequestScopedHandler(instanceWrapper, moduleRef, moduleKey, methodName),
|
|
40
86
|
isAckHandledManually,
|
|
41
87
|
}));
|
|
42
88
|
this.inspectEntrypointDefinitions(instance, port, messageHandlers, instanceWrapperId);
|
|
@@ -45,14 +91,19 @@ export class WebSocketsController {
|
|
|
45
91
|
}
|
|
46
92
|
const observableServer = this.socketServerProvider.scanForSocketServer(options, port);
|
|
47
93
|
this.assignServerToProperties(instance, observableServer.server);
|
|
48
|
-
this.subscribeEvents(
|
|
94
|
+
this.subscribeEvents(instanceWrapper, messageHandlers, observableServer, isStatic
|
|
95
|
+
? instance.handleConnection?.bind(instance)
|
|
96
|
+
: this.createRequestScopedEventHandler(instanceWrapper, moduleRef, moduleKey, 'handleConnection', observableServer.server), isStatic
|
|
97
|
+
? instance.handleDisconnect?.bind(instance)
|
|
98
|
+
: this.createRequestScopedEventHandler(instanceWrapper, moduleRef, moduleKey, 'handleDisconnect', observableServer.server));
|
|
49
99
|
}
|
|
50
|
-
subscribeEvents(
|
|
100
|
+
subscribeEvents(instanceWrapper, subscribersMap, observableServer, connectionHandler, disconnectHandler) {
|
|
101
|
+
const { instance } = instanceWrapper;
|
|
51
102
|
const { init, disconnect, connection, server } = observableServer;
|
|
52
103
|
const adapter = this.config.getIoAdapter();
|
|
53
104
|
this.subscribeInitEvent(instance, init);
|
|
54
|
-
this.subscribeConnectionEvent(
|
|
55
|
-
this.subscribeDisconnectEvent(
|
|
105
|
+
this.subscribeConnectionEvent(connectionHandler, connection);
|
|
106
|
+
this.subscribeDisconnectEvent(disconnectHandler, disconnect);
|
|
56
107
|
const handler = this.getConnectionHandler(this, instance, subscribersMap, disconnect, connection);
|
|
57
108
|
adapter.bindClientConnect(server, handler);
|
|
58
109
|
this.printSubscriptionLogs(instance, subscribersMap);
|
|
@@ -73,15 +124,21 @@ export class WebSocketsController {
|
|
|
73
124
|
event.subscribe(instance.afterInit.bind(instance));
|
|
74
125
|
}
|
|
75
126
|
}
|
|
76
|
-
subscribeConnectionEvent(
|
|
77
|
-
|
|
127
|
+
subscribeConnectionEvent(handlerOrGateway, event) {
|
|
128
|
+
const handler = typeof handlerOrGateway === 'function'
|
|
129
|
+
? handlerOrGateway
|
|
130
|
+
: handlerOrGateway?.handleConnection?.bind(handlerOrGateway);
|
|
131
|
+
if (handler) {
|
|
78
132
|
event
|
|
79
133
|
.pipe(distinctUntilChanged((prev, curr) => compareElementAt(prev, curr, 0)))
|
|
80
|
-
.subscribe((args) =>
|
|
134
|
+
.subscribe((args) => handler(...args));
|
|
81
135
|
}
|
|
82
136
|
}
|
|
83
|
-
subscribeDisconnectEvent(
|
|
84
|
-
|
|
137
|
+
subscribeDisconnectEvent(handlerOrGateway, event) {
|
|
138
|
+
const handler = typeof handlerOrGateway === 'function'
|
|
139
|
+
? handlerOrGateway
|
|
140
|
+
: handlerOrGateway?.handleDisconnect?.bind(handlerOrGateway);
|
|
141
|
+
if (handler) {
|
|
85
142
|
event
|
|
86
143
|
.pipe(distinctUntilChanged((prev, curr) => {
|
|
87
144
|
const prevClient = prev?.client || prev;
|
|
@@ -90,11 +147,11 @@ export class WebSocketsController {
|
|
|
90
147
|
}))
|
|
91
148
|
.subscribe((data) => {
|
|
92
149
|
if (data && typeof data === 'object' && 'client' in data) {
|
|
93
|
-
|
|
150
|
+
handler(data.client, data.reason);
|
|
94
151
|
}
|
|
95
152
|
else {
|
|
96
153
|
// Backward compatibility: if it's just the client
|
|
97
|
-
|
|
154
|
+
handler(data);
|
|
98
155
|
}
|
|
99
156
|
});
|
|
100
157
|
}
|
|
@@ -133,6 +190,83 @@ export class WebSocketsController {
|
|
|
133
190
|
}, instanceWrapperId);
|
|
134
191
|
});
|
|
135
192
|
}
|
|
193
|
+
createRequestScopedHandler(instanceWrapper, moduleRef, moduleKey, methodName) {
|
|
194
|
+
const { instance } = instanceWrapper;
|
|
195
|
+
const collection = moduleRef.providers;
|
|
196
|
+
const isTreeDurable = instanceWrapper.isDependencyTreeDurable();
|
|
197
|
+
return async (...args) => {
|
|
198
|
+
const [client] = args;
|
|
199
|
+
try {
|
|
200
|
+
const contextId = this.getContextId(client, isTreeDurable);
|
|
201
|
+
const contextInstance = await this.injector.loadPerContext(instance, moduleRef, collection, contextId);
|
|
202
|
+
return this.contextCreator.create(contextInstance, contextInstance[methodName], moduleKey, methodName, contextId, instanceWrapper.id)(...args);
|
|
203
|
+
}
|
|
204
|
+
catch (err) {
|
|
205
|
+
let exceptionFilter = this.exceptionFiltersCache.get(instance[methodName]);
|
|
206
|
+
if (!exceptionFilter) {
|
|
207
|
+
exceptionFilter = this.exceptionFiltersContext.create(instance, instance[methodName], moduleKey);
|
|
208
|
+
this.exceptionFiltersCache.set(instance[methodName], exceptionFilter);
|
|
209
|
+
}
|
|
210
|
+
const host = new ExecutionContextHost(args);
|
|
211
|
+
host.setType('ws');
|
|
212
|
+
exceptionFilter.handle(err, host);
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
createRequestScopedEventHandler(instanceWrapper, moduleRef, moduleKey, methodName, server) {
|
|
217
|
+
const { instance } = instanceWrapper;
|
|
218
|
+
const collection = moduleRef.providers;
|
|
219
|
+
const isTreeDurable = instanceWrapper.isDependencyTreeDurable();
|
|
220
|
+
const targetCallback = instance[methodName];
|
|
221
|
+
return async (...args) => {
|
|
222
|
+
const [client] = args;
|
|
223
|
+
let contextId;
|
|
224
|
+
try {
|
|
225
|
+
contextId = this.getContextId(client, isTreeDurable);
|
|
226
|
+
const contextInstance = await this.injector.loadPerContext(instance, moduleRef, collection, contextId);
|
|
227
|
+
this.assignServerToProperties(contextInstance, server);
|
|
228
|
+
const scopedMethod = contextInstance[methodName];
|
|
229
|
+
return scopedMethod?.apply(contextInstance, args);
|
|
230
|
+
}
|
|
231
|
+
catch (err) {
|
|
232
|
+
if (!targetCallback) {
|
|
233
|
+
throw err;
|
|
234
|
+
}
|
|
235
|
+
let exceptionFilter = this.exceptionFiltersCache.get(targetCallback);
|
|
236
|
+
if (!exceptionFilter) {
|
|
237
|
+
exceptionFilter = this.exceptionFiltersContext.create(instance, targetCallback, moduleKey);
|
|
238
|
+
this.exceptionFiltersCache.set(targetCallback, exceptionFilter);
|
|
239
|
+
}
|
|
240
|
+
const host = new ExecutionContextHost(args);
|
|
241
|
+
host.setType('ws');
|
|
242
|
+
exceptionFilter.handle(err, host);
|
|
243
|
+
}
|
|
244
|
+
finally {
|
|
245
|
+
if (methodName === 'handleDisconnect' && contextId) {
|
|
246
|
+
this.cleanupRequestScopedContext(instanceWrapper, contextId, client);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
getContextId(request, isTreeDurable) {
|
|
252
|
+
const contextId = ContextIdFactory.getByRequest(request);
|
|
253
|
+
if (!request[REQUEST_CONTEXT_ID]) {
|
|
254
|
+
Object.defineProperty(request, REQUEST_CONTEXT_ID, {
|
|
255
|
+
value: contextId,
|
|
256
|
+
enumerable: false,
|
|
257
|
+
writable: false,
|
|
258
|
+
configurable: true,
|
|
259
|
+
});
|
|
260
|
+
const requestProviderValue = isTreeDurable
|
|
261
|
+
? contextId.payload
|
|
262
|
+
: Object.assign(request, contextId.payload);
|
|
263
|
+
this.container.registerRequestProvider(requestProviderValue, contextId);
|
|
264
|
+
}
|
|
265
|
+
return contextId;
|
|
266
|
+
}
|
|
267
|
+
cleanupRequestScopedContext(_instanceWrapper, _contextId, request) {
|
|
268
|
+
Reflect.deleteProperty(request, REQUEST_CONTEXT_ID);
|
|
269
|
+
}
|
|
136
270
|
assignServerToProperties(instance, server) {
|
|
137
271
|
for (const propertyKey of this.metadataExplorer.scanForServerHooks(instance)) {
|
|
138
272
|
Reflect.set(instance, propertyKey, server);
|