UNPKG

@opra/nestjs

Version:
120 lines (119 loc) 6.06 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.RpcControllerFactory = void 0; const tslib_1 = require("tslib"); const common_1 = require("@nestjs/common"); const core_1 = require("@nestjs/core"); const external_context_creator_js_1 = require("@nestjs/core/helpers/external-context-creator.js"); const injector_js_1 = require("@nestjs/core/injector/injector.js"); const index_js_1 = require("@nestjs/core/injector/internal-core-module/index.js"); const request_constants_js_1 = require("@nestjs/core/router/request/request-constants.js"); const constants_js_1 = require("@nestjs/microservices/constants.js"); const common_2 = require("@opra/common"); const opra_nest_utils_js_1 = require("./opra-nest-utils.js"); const rpc_params_factory_js_1 = require("./rpc-params.factory.js"); let RpcControllerFactory = class RpcControllerFactory { constructor(modulesContainer, externalContextCreator) { this.modulesContainer = modulesContainer; this.externalContextCreator = externalContextCreator; this.paramsFactory = new rpc_params_factory_js_1.RpcParamsFactory(); this.injector = new injector_js_1.Injector(); } wrapControllers() { const out = []; for (const { module, wrapper } of this.exploreControllers()) { const instance = wrapper.instance; const sourceClass = instance.constructor; const metadata = Reflect.getMetadata(common_2.RPC_CONTROLLER_METADATA, sourceClass); const isRequestScoped = !wrapper.isDependencyTreeStatic(); /** Create a new controller class */ const newClass = { [sourceClass.name]: class extends sourceClass { }, }[sourceClass.name]; /** Copy metadata keys from source class to new one */ opra_nest_utils_js_1.OpraNestUtils.copyDecoratorMetadata(newClass, sourceClass); (0, common_1.Controller)()(newClass); out.push(newClass); if (metadata.operations) { for (const operationName of Object.keys(metadata.operations)) { // const orgFn: Function = sourceClass.prototype[operationName]; newClass.prototype[operationName] = this._createContextCallback(instance, wrapper, module, operationName, isRequestScoped, 'rpc'); Reflect.defineMetadata(constants_js_1.PARAM_ARGS_METADATA, [core_1.REQUEST], instance.constructor, operationName); } } } return out; } _createContextCallback(instance, wrapper, moduleRef, methodName, isRequestScoped, contextType, options) { const paramsFactory = this.paramsFactory; if (isRequestScoped) { return async (opraContext) => { const contextId = (0, core_1.createContextId)(); Object.defineProperty(opraContext, request_constants_js_1.REQUEST_CONTEXT_ID, { value: contextId, enumerable: false, configurable: false, writable: false, }); this.registerContextProvider(opraContext, contextId); const contextInstance = await this.injector.loadPerContext(instance, moduleRef, moduleRef.providers, contextId); const contextCallback = this.externalContextCreator.create(contextInstance, contextInstance[methodName], methodName, constants_js_1.PARAM_ARGS_METADATA, paramsFactory, contextId, wrapper.id, options, opraContext.protocol); return contextCallback(opraContext); }; } return this.externalContextCreator.create(instance, instance[methodName], methodName, constants_js_1.PARAM_ARGS_METADATA, paramsFactory, undefined, undefined, options, contextType); } registerContextProvider(request, contextId) { if (!this._coreModuleRef) { const coreModuleArray = [...this.modulesContainer.entries()] .filter( // eslint-disable-next-line @typescript-eslint/no-unused-vars ([_, { metatype }]) => metatype && metatype.name === index_js_1.InternalCoreModule.name) // eslint-disable-next-line @typescript-eslint/no-unused-vars .map(([_, value]) => value); this._coreModuleRef = coreModuleArray[0]; } if (!this._coreModuleRef) { return; } const wrapper = this._coreModuleRef.getProviderByKey(core_1.REQUEST); wrapper.setInstanceByContextId(contextId, { instance: request, isResolved: true, }); } exploreControllers() { const scannedModules = new Set(); const controllers = new Set(); const scanModule = (module) => { if (scannedModules.has(module)) return; scannedModules.add(module); for (const mm of module.imports.values()) { scanModule(mm); } for (const wrapper of module.controllers.values()) { if (wrapper.instance && typeof wrapper.instance === 'object' && wrapper.instance.constructor && Reflect.getMetadata(common_2.RPC_CONTROLLER_METADATA, wrapper.instance.constructor) && !controllers.has(wrapper)) { controllers.add({ module, wrapper }); } if (wrapper.host) scanModule(wrapper.host); } }; for (const module of this.modulesContainer.values()) { scanModule(module); } return Array.from(controllers); } }; exports.RpcControllerFactory = RpcControllerFactory; exports.RpcControllerFactory = RpcControllerFactory = tslib_1.__decorate([ (0, common_1.Injectable)(), tslib_1.__metadata("design:paramtypes", [core_1.ModulesContainer, external_context_creator_js_1.ExternalContextCreator]) ], RpcControllerFactory);