import type { Context } from '../Context'; import type { ActionInstance } from '../ActionInstance'; import { fireOnBeforeCreateInstance } from './fireOnBeforeCreateInstance'; export const actionContext = Symbol('get proxy context'); function getPropName(p: string | Symbol): string { if (typeof p !== 'string') { throw new Error(`Context: unknown system property ${p.description}`); } return p; } export async function createActionProxy(context: Context): Promise { const { originalInstance } = context.actionBox; await fireOnBeforeCreateInstance(context); await context.init(); const proxy = new Proxy(originalInstance, { get(target: T, p: string | symbol): any { if (p === 'then') { return undefined; } if (p === actionContext) { return context; } const prop = getPropName(p); if (context.has(prop)) { return context.get(prop); } if (context.hasOperationalValue(prop)) { return context.getOperationalValue(prop); } if (context.actionBox.config.shared.has(prop)) { return target[prop as keyof T]; } const actionBoxValue = target[prop as keyof T]; if (typeof actionBoxValue === 'object' && !Object.isFrozen(actionBoxValue)) { Object.freeze(actionBoxValue); } return actionBoxValue; }, set(target: T, p: string | symbol, value: any): boolean { const prop = getPropName(p); if (context.has(prop)) { return context.set(prop, value); } if (context.actionBox.config.shared.has(prop)) { // eslint-disable-next-line no-param-reassign target[prop as keyof T] = value; // only for share return true; } context.setOperationalValue(prop, value); return true; }, has(target: T, p: string | symbol): boolean { if (p === actionContext) { return true; } if (context.has(p as string)) { return true; } // eslint-disable-next-line no-prototype-builtins return target.hasOwnProperty(p); }, }); await context.initSpecial(proxy); return proxy; } export function getContext(instance: ActionInstance): Context { return instance[actionContext]; }