feat: lots more improvements
Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
This commit is contained in:
61
src/models/mutation-proxy.ts
Normal file
61
src/models/mutation-proxy.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import { clonePlain } from './clone-plain';
|
||||
|
||||
export class MutationProxy<T extends object> {
|
||||
|
||||
private readonly getOriginal: () => T;
|
||||
private readonly getMutated: () => Partial<T>;
|
||||
|
||||
constructor(
|
||||
getOriginal: () => T,
|
||||
getMutated: () => Partial<T>,
|
||||
) {
|
||||
this.getOriginal = getOriginal;
|
||||
this.getMutated = getMutated;
|
||||
}
|
||||
|
||||
create(): T {
|
||||
return new Proxy({} as T, {
|
||||
get: (_target, prop: string | symbol) => {
|
||||
if (typeof prop !== 'string') {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const key = prop as keyof T;
|
||||
const mutated = this.getMutated();
|
||||
const original = this.getOriginal();
|
||||
return key in mutated ? mutated[key] : original[key];
|
||||
},
|
||||
set: (_target, prop: string | symbol, value: unknown) => {
|
||||
if (typeof prop === 'string') {
|
||||
const key = prop as keyof T;
|
||||
(this.getMutated() as Record<keyof T, unknown>)[key] = clonePlain(value);
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
has: (_target, prop: string | symbol) => {
|
||||
if (typeof prop !== 'string') {
|
||||
return false;
|
||||
}
|
||||
|
||||
const mutated = this.getMutated();
|
||||
const original = this.getOriginal();
|
||||
return prop in mutated || prop in original;
|
||||
},
|
||||
ownKeys: () => {
|
||||
const mutated = this.getMutated();
|
||||
const original = this.getOriginal();
|
||||
|
||||
return Array.from(new Set([
|
||||
...Reflect.ownKeys(original),
|
||||
...Reflect.ownKeys(mutated),
|
||||
]));
|
||||
},
|
||||
getOwnPropertyDescriptor: () => ({
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user