basant307/AI_Governance_Project
048
1import { findPropertySource } from './findPropertySource'2 3export interface ProxyOptions<Target extends Record<string, any>> {4 constructorCall?(args: Array<unknown>, next: NextFunction<Target>): Target5 6 methodCall?<F extends keyof Target>(7 this: Target,8 data: [methodName: F, args: Array<unknown>],9 next: NextFunction<void>10 ): void11 12 setProperty?(13 data: [propertyName: string | symbol, nextValue: unknown],14 next: NextFunction<boolean>15 ): boolean16 17 getProperty?(18 data: [propertyName: string | symbol, receiver: Target],19 next: NextFunction<void>20 ): void21}22 23export type NextFunction<ReturnType> = () => ReturnType24 25export function createProxy<Target extends object>(26 target: Target,27 options: ProxyOptions<Target>28): Target {29 const proxy = new Proxy(target, optionsToProxyHandler(options))30 31 return proxy32}33 34function optionsToProxyHandler<T extends Record<string, any>>(35 options: ProxyOptions<T>36): ProxyHandler<T> {37 const { constructorCall, methodCall, getProperty, setProperty } = options38 const handler: ProxyHandler<T> = {}39 40 if (typeof constructorCall !== 'undefined') {41 handler.construct = function (target, args, newTarget) {42 const next = Reflect.construct.bind(null, target as any, args, newTarget)43 return constructorCall.call(newTarget, args, next)44 }45 }46 47 handler.set = function (target, propertyName, nextValue) {48 const next = () => {49 const propertySource = findPropertySource(target, propertyName) || target50 const ownDescriptors = Reflect.getOwnPropertyDescriptor(51 propertySource,52 propertyName53 )54 55 // Respect any custom setters present for this property.56 if (typeof ownDescriptors?.set !== 'undefined') {57 ownDescriptors.set.apply(target, [nextValue])58 return true59 }60 61 // Otherwise, set the property on the source.62 return Reflect.defineProperty(propertySource, propertyName, {63 writable: true,64 enumerable: true,65 configurable: true,66 value: nextValue,67 })68 }69 70 if (typeof setProperty !== 'undefined') {71 return setProperty.call(target, [propertyName, nextValue], next)72 }73 74 return next()75 }76 77 handler.get = function (target, propertyName, receiver) {78 /**79 * @note Using `Reflect.get()` here causes "TypeError: Illegal invocation".80 */81 const next = () => target[propertyName as any]82 83 const value =84 typeof getProperty !== 'undefined'85 ? getProperty.call(target, [propertyName, receiver], next)86 : next()87 88 if (typeof value === 'function') {89 return (...args: Array<any>) => {90 const next = value.bind(target, ...args)91 92 if (typeof methodCall !== 'undefined') {93 return methodCall.call(target, [propertyName as any, args], next)94 }95 96 return next()97 }98 }99 100 return value101 }102 103 return handler104}105 