import type { OutgoingContext } from '../messages'; import type { PropertyConfig } from '../server/PropertyConfig'; import type { ClientActionBox } from './ClientActionBox'; import type { ClientSpecialProperty } from './ClientSpecialProperty'; export class ClientContext { public special: Record = {}; public contextData: Record = {}; constructor(public readonly actionBox: ClientActionBox, public readonly isStatic = false) { } public has(propertyName: string): boolean { if (this.getPropertyConfig(propertyName)) { return true; } if (this.special[propertyName]) { return true; } if (!this.isStatic) { return this.actionBox.staticContext.has(propertyName); } return false; } public get(propertyName: string): any { const propertyConfig = this.getPropertyConfig(propertyName); if (this.special[propertyName]) { return this.special[propertyName]; } if (propertyConfig && this.isStatic === propertyConfig.static) { return this.contextData[propertyName]; } if (!this.isStatic) { return this.actionBox.staticContext.get(propertyName); } return undefined; } public set(propertyName: string, value: any): boolean { const propertyConfig = this.getPropertyConfig(propertyName); if (propertyConfig && this.isStatic === propertyConfig.static) { this.contextData[propertyName] = value; return true; } return this.actionBox.staticContext.set(propertyName, value) || false; } public keys(): string[] { return [ ...Object.keys(this.special), ...Object.keys(this.contextData), ]; } public setContext(data: OutgoingContext, hard = false) { // if (!this.isStatic) { // this.actionBox.staticContext.setContext(data, hard); // } if (!this.isStatic) { const { staticContext } = this.actionBox; const { properties } = this.actionBox.config; Object.entries(properties).forEach(([name, cfg]) => { // eslint-disable-next-line no-prototype-builtins if (!cfg.out || (!hard && !data.hasOwnProperty(name))) { return; } if (cfg.static) { staticContext.setValue(name, data[name]); } else { this.setValue(name, data[name]); } }); } Object.entries(data).forEach(([prop, value]) => this.setValue(prop, value)); } public getOutgoingContext(): any { const result: any = {}; Object.entries(this.actionBox.config.properties).forEach(([propertyName, cfg]) => { if (cfg.in) { result[propertyName] = this.get(propertyName); } }); return result; } public async initSpecial(instance: any) { if (this.isStatic) { return; } const { client } = this.actionBox; const { specialProperties } = this.actionBox.config; if (specialProperties) { const all: Array | void> = []; Object.entries(specialProperties).forEach(([prop, cfg]) => { const factory = client.getSpecialFactory(cfg.typeName); const sp = factory(); sp.action = instance; if (sp.init) { all.push(sp.init()); } this.special[prop] = sp; }); await Promise.all(all); } } private getPropertyConfig(propertyName: string): PropertyConfig | undefined { return this.actionBox.config.properties[propertyName]; } private setValue(prop: string, value: any) { const propCfg = this.actionBox.config.properties[prop]; if (propCfg && propCfg.static === this.isStatic) { this.contextData[prop] = value; } } }