@opra/nestjs
Version:
Opra NestJS module
120 lines (119 loc) • 6.06 kB
JavaScript
;
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);