/* eslint-disable security/detect-object-injection */ /* eslint-disable @typescript-eslint/ban-types */ import isPlainObject from 'lodash/isPlainObject'; const getAllProperties = (object: object): Set<[object, string]> => { const properties: Set<[object, string]> = new Set(); do { for (const key of Reflect.ownKeys(object) as string[]) { properties.add([object, key]); } } while ((object = Reflect.getPrototypeOf(object)) && object !== Object.prototype); return properties; }; interface IPatterns { include?: (RegExp | string)[]; exclude?: (RegExp | string)[]; } const autoBind = (self: T, inclExcl: IPatterns = {}, thisValue?: T): T => { const { include, exclude } = inclExcl; const filter = (key) => { const match = (pattern: string | RegExp) => (typeof pattern === 'string' ? key === pattern : pattern.test(key)); if (include) { return include.some(match); } if (exclude) { return !exclude.some(match); } return true; }; for (const [object, key] of getAllProperties(self)) { if (key === 'constructor' || !filter(key)) { continue; } const descriptor = Reflect.getOwnPropertyDescriptor(object, key); if (descriptor && typeof descriptor.value === 'function') { self[key] = (self[key] as Function).bind(thisValue || self); } if (isPlainObject(self[key])) { autoBind(self[key], inclExcl, self); } } return self; }; const autobind = autoBind; export { autobind, autoBind }; export default autobind;