import type { IFieldConfig, ILabel } from "../IShrimpType" import { Shrimp } from "./Shrimp" import { RootShrimpPower, ShrimpPower } from "./ShrimpPower" type ShrimpEventHandler = (...args: any[]) => Promise export class ShrimpEvent { constructor(public name: string, public handler: ShrimpEventHandler, public power: RootShrimpPower) { } } export interface IShrimpModuleOptions { icon?: string ownerKey?: string } export class ShrimpModule

= Record> { power: RootShrimpPower root: Shrimp modules: Map = new Map() events: Map = new Map() icon?: string ownerKey?: string constructor(public parent: Shrimp | ShrimpModule, public moduleKey: string, public label: ILabel, power?: RootShrimpPower, options?: IShrimpModuleOptions) { if (power == null) { if (parent instanceof Shrimp) { power = new RootShrimpPower(moduleKey, label) } else { power = new ShrimpPower(parent.power, moduleKey, label) } } this.power = power this.icon = options?.icon this.ownerKey = options?.ownerKey parent.modules.set(this.moduleKey, this) this.root = parent.root } addEvent(name: K, label: ILabel): this addEvent(name: K, power: RootShrimpPower): this addEvent(name: K, powerOrLabel: RootShrimpPower | ILabel) { const handler = (this as any)[name] if (typeof handler !== 'function') { throw new Error(`Method "${name}" not found on ${this.moduleKey}`) } let power: RootShrimpPower if (powerOrLabel instanceof RootShrimpPower) { power = powerOrLabel } else { power = new ShrimpPower(this.power, name, powerOrLabel) } this.events.set(name, new ShrimpEvent(name, handler.bind(this), power)) return this } async call(path: string[], ...args: any[]): Promise { if (path.length > 1) { let module = this.modules.get(path[0]) if (module == null) { throw new Error(`Module "${path[0]}" not found`) } return await module.call(path.slice(1), ...args) } else { const event = this.events.get(path[0]) if (event == null) { throw new Error(`Event "${path[0]}" not found`) } return await event.handler(...args) } } getEventInfo(powers: Set): string[] { let events: string[] = [] this.events.forEach(event => { if (powers.has(event.power.key)) { events.push(event.name) } }) return events } checkEvent(powers: Set, path: string[]): boolean { if (path.length > 1) { let module = this.modules.get(path[0]) if (module == null) return false return module.checkEvent(powers, path.slice(1)) } else { const event = this.events.get(path[0]) if (event == null) return false return powers.has(event.power.key) } } getFields(): IFieldConfig[] { return [] } }