import { BEAN_META, DYNAMIC_INJECT_META_KEY, FILE_PROPERTY_KEY, META_DI_RESOLVER_MAP, NEW_PROPERTY_KEY, PARAMETER_META_KEY, PROPERTY_META_KEY, REQUEST_OBJ_PROPERTY_KEY, REQUEST_PROPERTY_KEY, RESPONSE_OBJ_PROPERTY_KEY, SESSION_PROPERTY_KEY, SINGLETON_PROPERTY_KEY } from "../@types/DynamicInject"; import DiSupplier from "../injection/DiSupplier"; import {applicationContext} from "../context/ApplicationContext"; import TSExceptionBuilder from "../exception/TSException"; export const TransactionServiceInjector = (target: any, name: string, descriptor: any) => { Reflect.defineMetadata(DYNAMIC_INJECT_META_KEY, true, target, name); const original = descriptor.value; descriptor.value = async (...args: any[]) => { let targetName = target.constructor.name; if (!args || args.length != 2) { //dynamic inject에 넘겨줄 parameter args0 , 생성해서 넘겨줄 parameter args1 throw new TSExceptionBuilder().msg(" transaction service [%s] : inject initialize failed ").build(targetName); } // transaction service 는 singleton이므로 바로 bean에서 찾아온다 let bindThis = applicationContext.getBean(targetName, {SCOPE:"singleton"}) if(!bindThis) { throw new TSExceptionBuilder().msg(" transaction service [%s] : not exist ").build(targetName); } let assignedThisObject:any = {}; let thisKeys = Object.keys(bindThis) for(let thisIdx = 0; thisIdx < thisKeys.length; thisIdx++) { let thisKey = thisKeys[thisIdx]; if(typeof bindThis[thisKey] === "function") { // function type일 때는 set 안되게? Object.defineProperty(assignedThisObject, thisKey, { get() { if(!bindThis) return undefined; return bindThis[thisKey]; }, enumerable: true, configurable: true, }); } else { Object.defineProperty(assignedThisObject, thisKey, { get() { if(!bindThis) return undefined; return bindThis[thisKey]; }, set(_value) { if(!bindThis) return; bindThis[thisKey]= _value }, enumerable: true, configurable: true, }); } } let injectMetas = Reflect.getMetadataKeys(target, PROPERTY_META_KEY); if(injectMetas) { for (let idx = 0; idx < injectMetas.length; idx++) { let metaKey = injectMetas[idx]; let metaData: BEAN_META = Reflect.getMetadata(metaKey, target, PROPERTY_META_KEY); let propKey = metaData.target!.name; assignedThisObject[propKey] = await metaData.injectTargets[0].runner!(args[0][0]); } } let scopeMetas = Reflect.getMetadataKeys(target, PARAMETER_META_KEY); // if (!scopeMetas) { // //metadata없을 떄 그냥 기존 함수 실행 // const result = await original.apply(this, args); // return result; // } let metaMap: META_DI_RESOLVER_MAP = DiSupplier.DEFUALT_META_DI_RESOLVER_MAP // let metaScopeMap:META_DI_RESOLVER[] = [] for (let idx = 0; idx < scopeMetas.length; idx++) { let metaKey = scopeMetas[idx]; let metaData: BEAN_META = Reflect.getMetadata(metaKey, target, PARAMETER_META_KEY); if(metaData.target?.name != name) { continue; } let targetScopeMap; switch (metaData.type) { case REQUEST_PROPERTY_KEY: targetScopeMap = metaMap.requestScope; break; case SINGLETON_PROPERTY_KEY: targetScopeMap = metaMap.singletonScope; break; case NEW_PROPERTY_KEY: targetScopeMap = metaMap.newScope; break; case SESSION_PROPERTY_KEY: targetScopeMap = metaMap.session; break; case FILE_PROPERTY_KEY: targetScopeMap = metaMap.file; break; case REQUEST_OBJ_PROPERTY_KEY: targetScopeMap = metaMap.request; break; case RESPONSE_OBJ_PROPERTY_KEY: targetScopeMap = metaMap.response; break; } if (!targetScopeMap) continue; if (targetScopeMap.maxLength < metaData.target.index! + 1) targetScopeMap.maxLength = metaData.target.index! + 1; targetScopeMap.metas[metaData.target.index!] = metaData } let outputArg: any[] = args[1]; let metaMapKeys = Object.keys(metaMap); for (let scopeIdx = 0; scopeIdx < metaMapKeys.length; scopeIdx++) { let metaScope = metaMap[metaMapKeys[scopeIdx]]; outputArg = await metaScope.argsGenerateFun(args[0], outputArg, metaScope); } const result = await original.apply(assignedThisObject, outputArg); return result; } }