UNPKG

@manuth/interceptor

Version:

Provides a convenient way to intercept method- property- and accessor-calls of an object.

175 lines 5.6 kB
import cloneDeep from "lodash.clonedeep"; import { InterceptionCollection } from "./InterceptionCollection.js"; /** * Provides the functionality to intercept methods of an object. * * @template T * The type of the target of the {@linkcode Interceptor}. */ // eslint-disable-next-line @typescript-eslint/ban-types export class Interceptor { /** * Initializes a new instance of the {@linkcode Interceptor} class. * * @param target * The target of the interceptor. * * @param freeze * A value indicating whether the interceptor should ignore future changes made to the {@linkcode target}. */ constructor(target, freeze) { /** * The interceptions. */ this.interceptions = new InterceptionCollection(); /** * A value indicating whether the interceptor is disposed. */ this.disposed = false; if (freeze) { let clone = cloneDeep(target); this.target = clone; for (let property of Object.getOwnPropertyNames(target)) { if (property in target) { let descriptor = Object.getOwnPropertyDescriptor(target, property); if (descriptor) { Object.defineProperty(this.target, property, descriptor); } } } Object.assign(this.target, Object.assign({}, clone)); } else { this.target = target; } this.proxy = new Proxy(this.target, { has: (target, property) => { var _a, _b; if (!this.Disposed) { if (this.interceptions.has(property)) { let properties = [ "Get", "Set" ]; let interception = this.interceptions.get(property); return (_b = (_a = interception === null || interception === void 0 ? void 0 : interception.Has) === null || _a === void 0 ? void 0 : _a.call(interception, target, property)) !== null && _b !== void 0 ? _b : properties.some((property) => interception === null || interception === void 0 ? void 0 : interception[property]); } else { return property in target; } } else { return property in this.target; } }, get: (target, property) => { var _a, _b; if (!this.Disposed) { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return (_b = (_a = this.interceptions.get(property)) === null || _a === void 0 ? void 0 : _a.Get(target, property)) !== null && _b !== void 0 ? _b : target[property]; } else { return this.target[property]; } }, set: (target, property, value) => { var _a; if (!this.Disposed && this.interceptions.has(property)) { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion (_a = this.interceptions.get(property)) === null || _a === void 0 ? void 0 : _a.Set(target, property, value); } else { this.target[property] = value; } return true; } }); } /** * Gets the target of the interceptor. */ get Target() { return this.target; } /** * Gets the installed interceptions. */ get Interceptions() { return new Map(this.interceptions); } /** * Gets the proxy for intercepting calls. */ get Proxy() { return this.proxy; } /** * Gets a value indicating whether the interceptor is disposed. */ get Disposed() { return this.disposed; } /** * Adds a new property-interception. * * @template TKey * The type of the specified {@linkcode key}. * * @param key * The key of the interception to add. * * @param interception * The interception to add. */ AddProperty(key, interception) { if (!this.interceptions.has(key)) { this.interceptions.set(key, interception); } else { throw new RangeError(`An interception with the key \`${key.toString()}\` already exists!`); } } /** * Adds a new interception. * * @template TKey * The type of the specified {@linkcode key}. * * @param key * The key of the interception to add. * * @param interception * The interception to add. */ AddMethod(key, interception) { this.AddProperty(key, { Get: (target, key) => { return ((...args) => interception(target, target[key], ...args)); } }); } /** * Deletes an interception. * * @param key * The key of the interception to delete. */ Delete(key) { this.interceptions.delete(key); } /** * Clears all interceptions. */ Clear() { this.interceptions.clear(); } /** * Disposes the interceptor. */ Dispose() { this.disposed = true; this.interceptions.clear(); } } //# sourceMappingURL=Interceptor.js.map