1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.ListenersController = void 0;
|
4 | const shared_utils_1 = require("@nestjs/common/utils/shared.utils");
|
5 | const context_id_factory_1 = require("@nestjs/core/helpers/context-id-factory");
|
6 | const execution_context_host_1 = require("@nestjs/core/helpers/execution-context-host");
|
7 | const constants_1 = require("@nestjs/core/injector/constants");
|
8 | const metadata_scanner_1 = require("@nestjs/core/metadata-scanner");
|
9 | const request_constants_1 = require("@nestjs/core/router/request/request-constants");
|
10 | const rxjs_1 = require("rxjs");
|
11 | const request_context_host_1 = require("./context/request-context-host");
|
12 | const rpc_metadata_constants_1 = require("./context/rpc-metadata-constants");
|
13 | const listener_metadata_explorer_1 = require("./listener-metadata-explorer");
|
14 | const server_1 = require("./server");
|
15 | class ListenersController {
|
16 | constructor(clientsContainer, contextCreator, container, injector, clientFactory, exceptionFiltersContext) {
|
17 | this.clientsContainer = clientsContainer;
|
18 | this.contextCreator = contextCreator;
|
19 | this.container = container;
|
20 | this.injector = injector;
|
21 | this.clientFactory = clientFactory;
|
22 | this.exceptionFiltersContext = exceptionFiltersContext;
|
23 | this.metadataExplorer = new listener_metadata_explorer_1.ListenerMetadataExplorer(new metadata_scanner_1.MetadataScanner());
|
24 | this.exceptionFiltersCache = new WeakMap();
|
25 | }
|
26 | registerPatternHandlers(instanceWrapper, server, moduleKey) {
|
27 | const { instance } = instanceWrapper;
|
28 | const isStatic = instanceWrapper.isDependencyTreeStatic();
|
29 | const patternHandlers = this.metadataExplorer.explore(instance);
|
30 | const moduleRef = this.container.getModuleByKey(moduleKey);
|
31 | const defaultCallMetadata = server instanceof server_1.ServerGrpc
|
32 | ? rpc_metadata_constants_1.DEFAULT_GRPC_CALLBACK_METADATA
|
33 | : rpc_metadata_constants_1.DEFAULT_CALLBACK_METADATA;
|
34 | patternHandlers
|
35 | .filter(({ transport }) => (0, shared_utils_1.isUndefined)(transport) ||
|
36 | (0, shared_utils_1.isUndefined)(server.transportId) ||
|
37 | transport === server.transportId)
|
38 | .forEach(({ pattern, targetCallback, methodKey, extras, isEventHandler }) => {
|
39 | if (isStatic) {
|
40 | const proxy = this.contextCreator.create(instance, targetCallback, moduleKey, methodKey, constants_1.STATIC_CONTEXT, undefined, defaultCallMetadata);
|
41 | if (isEventHandler) {
|
42 | const eventHandler = (...args) => {
|
43 | var _a;
|
44 | const originalArgs = args;
|
45 | const [dataOrContextHost] = originalArgs;
|
46 | if (dataOrContextHost instanceof request_context_host_1.RequestContextHost) {
|
47 | args = args.slice(1, args.length);
|
48 | }
|
49 | const originalReturnValue = proxy(...args);
|
50 | const returnedValueWrapper = (_a = eventHandler.next) === null || _a === void 0 ? void 0 : _a.call(eventHandler, ...originalArgs);
|
51 | returnedValueWrapper === null || returnedValueWrapper === void 0 ? void 0 : returnedValueWrapper.then(returnedValue => this.connectIfStream(returnedValue));
|
52 | return originalReturnValue;
|
53 | };
|
54 | return server.addHandler(pattern, eventHandler, isEventHandler, extras);
|
55 | }
|
56 | else {
|
57 | return server.addHandler(pattern, proxy, isEventHandler, extras);
|
58 | }
|
59 | }
|
60 | const asyncHandler = this.createRequestScopedHandler(instanceWrapper, pattern, moduleRef, moduleKey, methodKey, defaultCallMetadata);
|
61 | server.addHandler(pattern, asyncHandler, isEventHandler, extras);
|
62 | });
|
63 | }
|
64 | assignClientsToProperties(instance) {
|
65 | for (const { property, metadata, } of this.metadataExplorer.scanForClientHooks(instance)) {
|
66 | const client = this.clientFactory.create(metadata);
|
67 | this.clientsContainer.addClient(client);
|
68 | this.assignClientToInstance(instance, property, client);
|
69 | }
|
70 | }
|
71 | assignClientToInstance(instance, property, client) {
|
72 | Reflect.set(instance, property, client);
|
73 | }
|
74 | createRequestScopedHandler(wrapper, pattern, moduleRef, moduleKey, methodKey, defaultCallMetadata = rpc_metadata_constants_1.DEFAULT_CALLBACK_METADATA) {
|
75 | const collection = moduleRef.controllers;
|
76 | const { instance } = wrapper;
|
77 | const requestScopedHandler = async (...args) => {
|
78 | var _a;
|
79 | try {
|
80 | let contextId;
|
81 | let [dataOrContextHost] = args;
|
82 | if (dataOrContextHost instanceof request_context_host_1.RequestContextHost) {
|
83 | contextId = this.getContextId(dataOrContextHost);
|
84 | args.shift();
|
85 | }
|
86 | else {
|
87 | const [data, reqCtx] = args;
|
88 | const request = request_context_host_1.RequestContextHost.create(pattern, data, reqCtx);
|
89 | contextId = this.getContextId(request);
|
90 | this.container.registerRequestProvider(request, contextId);
|
91 | dataOrContextHost = request;
|
92 | }
|
93 | const contextInstance = await this.injector.loadPerContext(instance, moduleRef, collection, contextId);
|
94 | const proxy = this.contextCreator.create(contextInstance, contextInstance[methodKey], moduleKey, methodKey, contextId, wrapper.id, defaultCallMetadata);
|
95 | (_a = requestScopedHandler.next) === null || _a === void 0 ? void 0 : _a.call(requestScopedHandler, dataOrContextHost, ...args);
|
96 | return proxy(...args);
|
97 | }
|
98 | catch (err) {
|
99 | let exceptionFilter = this.exceptionFiltersCache.get(instance[methodKey]);
|
100 | if (!exceptionFilter) {
|
101 | exceptionFilter = this.exceptionFiltersContext.create(instance, instance[methodKey], moduleKey);
|
102 | this.exceptionFiltersCache.set(instance[methodKey], exceptionFilter);
|
103 | }
|
104 | const host = new execution_context_host_1.ExecutionContextHost(args);
|
105 | host.setType('rpc');
|
106 | return exceptionFilter.handle(err, host);
|
107 | }
|
108 | };
|
109 | return requestScopedHandler;
|
110 | }
|
111 | getContextId(request) {
|
112 | const contextId = context_id_factory_1.ContextIdFactory.getByRequest(request);
|
113 | if (!request[request_constants_1.REQUEST_CONTEXT_ID]) {
|
114 | Object.defineProperty(request, request_constants_1.REQUEST_CONTEXT_ID, {
|
115 | value: contextId,
|
116 | enumerable: false,
|
117 | writable: false,
|
118 | configurable: false,
|
119 | });
|
120 | this.container.registerRequestProvider(request, contextId);
|
121 | }
|
122 | return contextId;
|
123 | }
|
124 | connectIfStream(source) {
|
125 | if (!source) {
|
126 | return;
|
127 | }
|
128 | const connectableSource = (0, rxjs_1.connectable)(source, {
|
129 | connector: () => new rxjs_1.Subject(),
|
130 | resetOnDisconnect: false,
|
131 | });
|
132 | connectableSource.connect();
|
133 | }
|
134 | }
|
135 | exports.ListenersController = ListenersController;
|