Passed
Push — main ( 238ec8...50243d )
by Lorenzo
03:03
created

Bean.ts ➔ Bean   C

Complexity

Conditions 7

Size

Total Lines 85
Code Lines 59

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 47
CRAP Score 7

Importance

Changes 0
Metric Value
eloc 59
dl 0
loc 85
c 0
b 0
f 0
rs 6.9418
ccs 47
cts 47
cp 1
cc 7
crap 7

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1 9
import {
2
  registeredMethods, logger, registeredBeans,
3
} from '@/core';
4
5 52
const getMethods = (singleton: any) => Reflect.ownKeys(Object.getPrototypeOf(singleton))
6 94
  .filter((method) => method !== 'constructor')
7 42
  .map(methodName => [singleton[methodName], methodName] as const);
8
9
/**
10
 * Instantiates a new instance of the singleton and registers it
11
 * @decorator
12
 * @param target
13
 * @param _context
14
 */
15 9
export function Bean(target: any, _context: ClassDecoratorContext) {
16 26
  logger.debug(`Registering singleton: ${target.name}`);
17 26
  Reflect.defineProperty(target, '_className', {
18 4
    get: () => target.name,
19
  });
20 26
  Reflect.defineProperty(target, '_instance', {
21 65
    get: () => registeredBeans.get(target.name),
22
  });
23 26
  Reflect.defineProperty(target, '_beanUUID', {
24
    value: crypto.randomUUID(),
25
  });
26
27 26
  const interceptors: Map<string, (target: unknown, prop: string) => unknown> = new Map();
28 26
  const mappers: Map<string, (original: unknown) => any> = new Map();
29
30 26
  const handlerConfig = {
31
    getInterceptor: (t: any, p: string) => {
32 18
      const interceptor = interceptors.get(p);
33 18
      if (interceptor) {
34 4
        return interceptor(t, p);
35
      }
36 14
      return t[p];
37
    },
38
    getMapper: (_t: any, p: string) => {
39 16
      const mapper = mappers.get(p);
40 16
      if (mapper) {
41 2
        return mapper;
42
      }
43 14
      return (...args: unknown[]) => {
44 14
        return args;
45
      };
46
    }
47
  };
48 26
  const instance: typeof target = Reflect.construct(target, []);
49 26
  const preComputedMethods = new Map<string | symbol, (...args: unknown[]) => any>();
50 26
  const singleton: any = new Proxy(instance, {
51
    get(targetProxy, prop) {
52 127
      if (typeof targetProxy[prop] === 'function') {
53 40
        if (preComputedMethods.has(prop)) {
54 19
          return preComputedMethods.get(prop);
55
        }
56 21
        const methodName = String(prop);
57
        let handlerFunction;
58
59 21
        handlerFunction = (...args: unknown[]) => {
60 18
          const result = handlerConfig.getInterceptor(targetProxy, methodName).apply(targetProxy, args);
61 17
          if (result instanceof Promise) {
62 4
            return result.then(res => handlerConfig.getMapper(targetProxy, methodName)(res));
63
          }
64 13
          return handlerConfig.getMapper(targetProxy, methodName)(result);
65
        };
66
67 21
        preComputedMethods.set(prop, handlerFunction);
68 21
        return handlerFunction;
69
      }
70 87
      return targetProxy[prop];
71
    }
72
  });
73 26
  Reflect.defineProperty(singleton, '_className', {
74 60
    get: () => target.name,
75
  });
76 26
  getMethods(instance)
77
    .forEach(([classMethod, methodName]) => {
78 21
      logger.debug(`registering method ${target.name}.${String(methodName)}`);
79 21
      registeredMethods.set(classMethod, singleton);
80
    });
81 26
  getMethods(singleton)
82
    .forEach(([classMethod, methodName]) => {
83 21
      logger.debug(`registering method ${target.name}.${String(methodName)}`);
84 21
      registeredMethods.set(classMethod, singleton);
85
    });
86 26
  Reflect.defineProperty(singleton, '_interceptors', {
87 6
    get: () => interceptors,
88
  });
89 26
  Reflect.defineProperty(singleton, '_mappers', {
90 4
    get: () => mappers,
91
  });
92 26
  registeredBeans.set(target.name, singleton);
93
}
94