# State Management ## Where to Store What | Data Type | Location | Reason | |-----------|----------|--------| | Business state (maps, sets, caches) | `globalThis` | Module vars reset on hot reload | | Event dedup (WeakSet/Set) | `globalThis` | Same | | Gateway lifecycle flags | `globalThis` | Prevent double init | | Connection flags (WebSocket/TCP) | `globalThis` | Prevent duplicate connections | | Runtime references | `globalThis` | Closures need living instance | | Cross-plugin API objects (`__pluginId`) | `globalThis` | Other plugins access via globalThis | | Pure utility functions | Module-level | No state needed | | Persistent data | File + memory cache | Survives gateway restart | ## Cross-Plugin API Pattern ### Provider side ```typescript const _G = globalThis as Record; // Init shared objects once if (!(_G["_myRegistry"] instanceof MyRegistry)) { _G["_myRegistry"] = new MyRegistry(); } // Overwrite public API every register() (updates closures) _G["__myPlugin"] = { registry: _G["_myRegistry"], send: (msg) => (_G["_myRuntime"] as Runtime)?.send(msg) ?? false, }; ``` ### Consumer side ```typescript const provider = (globalThis as any)["__myPlugin"]; if (!provider) { console.error("[consumer] __myPlugin not found"); return; } provider.registry.register("my_rule", handler); ``` ### Load Order Provider must be listed before consumer in `plugins.allow`. Consumer must defend against provider not being loaded.