1
|
|
|
import { logger } from '@/core'; |
2
|
|
|
import { ExpressBean } from '@/ExpressBeansTypes'; |
3
|
|
|
|
4
|
|
|
function getSingleton<T>(singletonClass: T & ExpressBean): T & ExpressBean { |
5
|
|
|
if (singletonClass) { |
6
|
|
|
if (singletonClass._instance) { |
7
|
|
|
return singletonClass._instance; |
8
|
|
|
} |
9
|
|
|
const className = Reflect.getOwnPropertyDescriptor(singletonClass, 'name')?.value; |
10
|
|
|
if (!className) { |
11
|
|
|
throw new Error(`Cannot get instance for a class without name: ${JSON.stringify(singletonClass)}`); |
12
|
|
|
} |
13
|
|
|
throw new Error(`Cannot get instance from ${className}. Make sure that ${className} has @Bean as class decorator`); |
14
|
|
|
} |
15
|
|
|
|
16
|
|
|
if (!hasName(singletonClass)) { |
17
|
|
|
throw new Error(`Cannot get instance for ${JSON.stringify(singletonClass)}: it is not an ExpressBean`); |
18
|
|
|
} |
19
|
|
|
|
20
|
|
|
if (!isABean(singletonClass)) { |
21
|
|
|
const className = (singletonClass as any).name; |
22
|
|
|
throw new Error(`Cannot get instance from ${className}. Make sure that ${className} has @Bean as class decorator`); |
23
|
|
|
} |
24
|
|
|
|
25
|
|
|
const bean = singletonClass as unknown as ExpressBean; |
26
|
|
|
return bean._instance; |
27
|
|
|
} |
28
|
|
|
|
29
|
|
|
/** |
30
|
|
|
* Gets singleton instance by its static property |
31
|
|
|
* @decorator |
32
|
|
|
* @param singletonClass |
33
|
|
|
*/ |
34
|
|
|
export function InjectBean<T extends object>(singletonClass: NonNullable<T>) { |
35
|
|
|
return (_value: unknown, _context: ClassFieldDecoratorContext) => () => new Proxy<T>( |
36
|
|
|
singletonClass ?? {}, |
37
|
|
|
{ |
38
|
|
|
get: (target, property) => { |
39
|
|
|
if (property === '_beanUUID' || property === '_className') { |
40
|
|
|
return (target as ExpressBean)[property]; |
41
|
|
|
} |
42
|
|
|
const singletonInstance = getSingleton(singletonClass); |
43
|
|
|
const className = (singletonInstance as unknown as ExpressBean)._className; |
44
|
|
|
logger.debug(`proxying ${className}.${String(property)}`); |
45
|
|
|
return (singletonInstance as any)[property]; |
46
|
|
|
}, |
47
|
|
|
}, |
48
|
|
|
) as any; |
49
|
|
|
} |
50
|
|
|
|