|
| 1 | +--- |
| 2 | +outline: deep |
| 3 | +--- |
| 4 | + |
| 5 | +# Hub Events Reference |
| 6 | + |
| 7 | +The hub carries change notifications across three distinct channels. What separates them is **direction and reach**: an in-process event bus that never leaves the node process, server RPC methods a client calls, and server-pushed broadcasts and shared state a client reads. |
| 8 | + |
| 9 | +Two naming prefixes mark the wire surface: `hub:` for hub-layer server RPC (client → server actions), and `devframe:` for the client-facing devframe protocol (broadcasts, shared state, and streams pushed server → client). The internal event bus mirrors the same plural subsystem vocabulary (`docks`, `terminals`, `messages`, `commands`), so each internal event lines up with its wire counterpart — `docks:activate` fans out to `devframe:docks:activate`. |
| 10 | + |
| 11 | +## Internal node event bus |
| 12 | + |
| 13 | +Each subsystem host emits on `ctx.<subsystem>.events`. These fire and are consumed **inside the same node process** — chiefly by `createHubContext`, which fans them out onto the wire. They never cross to the browser. |
| 14 | + |
| 15 | +| Event | Emitted by | Consumed by | Payload | |
| 16 | +|---|---|---|---| |
| 17 | +| `docks:entry:updated` | `DocksHost.register` / `update` | context → `devframe:docks` shared state | `DevframeDockUserEntry` | |
| 18 | +| `docks:activate` | `DocksHost.activate()` | context → broadcast + `devframe:docks:active` | `DevframeDockActivation` | |
| 19 | +| `terminals:session:updated` | `TerminalsHost` register / update / remove / status change | context → `devframe:terminals:updated`; terminals plugin | `DevframeTerminalSession` | |
| 20 | +| `messages:added` / `messages:updated` / `messages:removed` / `messages:cleared` | `MessagesHost` mutations | context → `devframe:messages:updated`; messages plugin | entry / entry / id / — | |
| 21 | +| `commands:registered` / `commands:unregistered` | `CommandsHost` register / update / unregister | context → `devframe:commands` shared state | entry / id | |
| 22 | + |
| 23 | +The `docks:entry:updated` and `terminals:session:updated` middle nouns (`entry`, `session`) name the specific record type; the messages and commands subsystems imply their record in the subsystem name, so they carry the verb directly. |
| 24 | + |
| 25 | +## Server RPC methods — client → server |
| 26 | + |
| 27 | +A connected client (any mounted iframe or panel, on its own RPC client) calls these; the hub node handles them. Carry the `hub:` prefix. |
| 28 | + |
| 29 | +| Method | Signature | Purpose | |
| 30 | +|---|---|---| |
| 31 | +| `hub:docks:activate` | `({ dockId, params? }) => void` | Ask the viewer to switch its active dock — see [Deep Linking](./deep-linking). | |
| 32 | +| `hub:commands:execute` | `(id, ...args) => unknown` | Invoke a registered server command by id. | |
| 33 | +| `hub:messages:add` | `(input) => DevframeMessageEntry` | Add a message to the feed (marked `from: 'browser'`). | |
| 34 | +| `hub:messages:update` | `(id, patch) => DevframeMessageEntry \| undefined` | Patch a message by id. | |
| 35 | +| `hub:messages:remove` | `(id) => void` | Remove a message by id. | |
| 36 | +| `hub:messages:clear` | `() => void` | Remove every message. | |
| 37 | +| `hub:terminals:write` | `(id, data) => void` | Send input to an interactive PTY session. | |
| 38 | +| `hub:terminals:resize` | `(id, cols, rows) => void` | Resize an interactive PTY session. | |
| 39 | +| `hub:terminals:terminate` | `(id) => void` | Kill a session's process, keeping it registered. | |
| 40 | +| `hub:terminals:restart` | `(id) => void` | Re-run a session's command in place. | |
| 41 | +| `hub:terminals:remove` | `(id) => void` | Kill a session's process and drop it from the registry. | |
| 42 | + |
| 43 | +## Broadcasts & shared state — server → client |
| 44 | + |
| 45 | +The server pushes these; a hub-aware client reads or subscribes. Carry the `devframe:` prefix. A UI subscribes to broadcasts via `rpc.client.register(...)`; the [client host](./client-context) registers the `devframe:docks:activate` handler for you. |
| 46 | + |
| 47 | +| Name | Kind | Carries | |
| 48 | +|---|---|---| |
| 49 | +| `devframe:docks:activate` | broadcast | Live "switch active dock" request — the client host calls its local `switchEntry`. | |
| 50 | +| `devframe:terminals:updated` | broadcast | Terminal sessions changed; re-read terminal state. | |
| 51 | +| `devframe:messages:updated` | broadcast | Message list changed; re-read message state. | |
| 52 | +| `devframe:docks` | shared state | Projected dock entry list (`DevframeDockEntry[]`). | |
| 53 | +| `devframe:docks:active` | shared state | Most recent `DevframeDockActivation`, so a dock that mounts in response still converges on it. | |
| 54 | +| `devframe:commands` | shared state | Serializable command list, handlers stripped (`DevframeServerCommandEntry[]`). | |
| 55 | +| `devframe:user-settings` | shared state | Persisted per-workspace hub settings (`DevframeDocksUserSettings`). | |
| 56 | +| `devframe:terminals` | streaming channel | Live terminal output stream, keyed by session id. | |
| 57 | + |
| 58 | +The [`devframe:docks:active`](./shared-state) mirror pairs with the `devframe:docks:activate` broadcast: the broadcast reaches docks already on screen, while the mirror lets a dock that mounts *because* of the switch converge on the same request instead of missing it. |
0 commit comments