-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathveil.ts
52 lines (47 loc) · 1.42 KB
/
veil.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/**
* Wraps a target object with provided presets object
* and when trying to access the provided presets methods on the veil object
* it passes them throuhg, until the veil object is pierced, meaning the use methods
* not listed in the provided preset object
*/
class Veil<T = any> {
private pierced: boolean;
constructor(
private readonly target: T,
private readonly presets: Map<keyof T, any>
) {
this.target = target;
this.presets = new Map(Object.entries(presets) as [keyof T, any][]);
this.pierced = false;
Object.getOwnPropertyNames(
Object.getPrototypeOf(this.target)
)
.slice(1)
.forEach(
methodName => {
if (typeof (this.target as any)[methodName] === 'function') {
(this as any)[methodName] = this.wrapMethod(methodName as keyof T);
}
}
);
};
wrapMethod(methodName: keyof T) {
return (...args: any[]) => {
if (!this.pierced && this.presets.has(methodName)) {
return this.presets.get(methodName);
}
if (!this.pierced) {
this.pierce();
}
const targetMethod = (this.target as any)[methodName];
if (typeof targetMethod === 'function') {
return targetMethod.apply(this.target, args);
}
throw new Error(`Method "${String(methodName)}" does not exist on the target object.`);
};
}
pierce(): void {
this.pierced = true;
}
};
export default Veil;