feat(hub): expose panel state through client context - #281
Conversation
42b2944 to
2900b4a
Compare
|
@dvcolomban is attempting to deploy a commit to the NuxtLabs Team on Vercel. A member of the Team first needs to authorize it. |
There was a problem hiding this comment.
Pull request overview
This PR adds a hub-level, per-RPC-connection lifecycle signal for dock panel open/close state so Node-side hub consumers can observe when a given viewer connects, changes open state, or disconnects, keyed by the server-minted RPC session id.
Changes:
- Introduces
docks:panel:stateas a typed hub bus event (connected/changed/disconnected) backed by server-tracked state per RPC session id. - Adds the internal RPC method
hub:docks:panel-stateplus a client helperreportDockPanelState()and wires reporting from both the headless hub client host and hub-ui viewer. - Adds unit/integration coverage and updates events documentation + public API snapshots.
Reviewed changes
Copilot reviewed 18 out of 23 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| tests/snapshots/tsnapi/@devframes/hub/types.snapshot.d.ts | Snapshot: exports DevframeDockPanelStateEvent. |
| tests/snapshots/tsnapi/@devframes/hub/node.snapshot.js | Snapshot: exports hubDocksPanelState. |
| tests/snapshots/tsnapi/@devframes/hub/node.snapshot.d.ts | Snapshot: adds typed hubDocksPanelState RPC definition. |
| tests/snapshots/tsnapi/@devframes/hub/index.snapshot.d.ts | Snapshot: adds docks:panel:state event + DevframeDockPanelStateEvent type. |
| tests/snapshots/tsnapi/@devframes/hub/constants.snapshot.d.ts | Snapshot: adds HUB_EVENTS.bus.docksPanelState + HUB_EVENTS.rpc.docksPanelState. |
| tests/snapshots/tsnapi/@devframes/hub/client.snapshot.js | Snapshot: exports reportDockPanelState. |
| tests/snapshots/tsnapi/@devframes/hub/client.snapshot.d.ts | Snapshot: types reportDockPanelState(rpc, open). |
| packages/hub/src/types/docks.ts | Extends docks host event surface and introduces DevframeDockPanelStateEvent. |
| packages/hub/src/node/rpc-builtins.ts | Adds hub:docks:panel-state RPC builtin and registers it. |
| packages/hub/src/node/panel-state.ts | Implements per-docks-host tracking + dedup + disconnect cleanup + event emission. |
| packages/hub/src/node/initiate.ts | Hooks RPC peer disconnect to emit disconnected and clear tracked state. |
| packages/hub/src/node/context.ts | Adds module augmentation for hub:docks:panel-state (internal RPC). |
| packages/hub/src/node/tests/rpc-builtins.test.ts | Verifies session id derivation via handler context. |
| packages/hub/src/node/tests/initiate.test.ts | Integration test for per-connection tracking + disconnect semantics. |
| packages/hub/src/node/tests/host-docks.test.ts | Unit tests for dedupe, independent sessions, and disconnect behavior. |
| packages/hub/src/events.ts | Adds centralized bus + RPC names for panel state reporting. |
| packages/hub/src/client/panel-state.ts | Adds client helper for reporting open/close state to hub. |
| packages/hub/src/client/index.ts | Re-exports the new client helper. |
| packages/hub/src/client/host.ts | Reports initial state and subsequent panel.session.open changes from the headless client host. |
| packages/hub/src/client/tests/host.test.ts | Tests initial report and later open-state assignments. |
| packages/hub-ui/src/client/state/context.ts | Reports restored initial state and subsequent open transitions from hub-ui viewer after initialization. |
| packages/hub-ui/src/client/state/context.test.ts | Tests restored state report and later transitions. |
| docs/content/1.guide/20.events.md | Documents the new bus event and RPC method. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 18 out of 23 changed files in this pull request and generated no new comments.
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
packages/hub-ui/src/client/state/context.ts:670
reportPanelStateAfterInitialization()awaitsrestoreAfterInitialization()without handling rejection. If the restore path throws (e.g. a restored dock’sexecuteSetupScript()fails), the promise rejects, thewatch()is never installed, and the hub will stop receiving panel-state reports for that viewer connection (plus this becomes an unhandled promise rejection).
const reportPanelStateAfterInitialization = async (): Promise<void> => {
await restoreAfterInitialization()
watch(
() => sessionStore.value.open,
open => void reportDockPanelState(rpc, open).catch(() => {}),
281aecc to
078fbc0
Compare
| export function createMessagesClient(_, _) {} | ||
| export function getDevframeClientContext() {} | ||
| export function parseRemoteConnection(_) {} | ||
| export async function reportDockPanelState(_, _) {} |
There was a problem hiding this comment.
This should avoid to be a public api
antfu
left a comment
There was a problem hiding this comment.
I feel this PR is a bit over complex, as this is not a common use case, I think I prefer us to only emit client context event, so if user want it in the server side, they can chain it with custom rpc that harvest from the client side.
390bae4 to
a5ed1aa
Compare
|
Reworked this around the client context as suggested. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 11 out of 15 changed files in this pull request and generated no new comments.
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
docs/content/1.guide/17.client-context.md:52
- The docs example uses
void context.rpc.call(...)without handling rejections. If the custom RPC isn’t registered/available yet, this can produce unhandled promise rejections for readers who copy-paste the snippet. Consider adding a.catch(...)(or usingawaitinside anasyncsetup function) to make the example safe.
void context.rpc.call('my-devframe:panel-state', context.panel.state)
context.panel.events.on(
HUB_EVENTS.client.docksPanelStateChanged,
panelState => void context.rpc.call('my-devframe:panel-state', panelState),
)
What changed
DevframeDockPanelStatewithopen,closed, andhiddenstates plus an optionalselectedDockIdctx.panel.statepanel:state:changedupdates throughctx.panel.eventshiddenwhile the embedded hub UI element is detached, preservingselectedDockIdWhy
Panel visibility is client-local and only some devframes need it on the node side. Keeping it in the client context provides the current snapshot and later changes without adding server session machinery.
A client script that needs node-side reporting can forward the initial state and later events through its own RPC.
Contract
ctx.panel.stateis the current{ state, selectedDockId? }snapshot. Client scripts read it when loading.ctx.panel.eventsemits only subsequent changes.selectedDockIdis omitted when no dock is selected.hiddentakes precedence while the embedded hub UI element is detached and retains the selected dock. Related changes are coalesced, and identical snapshots are suppressed. The headless runtime reportsopenorclosed.Routes, storage contents, and dock-owned state remain outside this change.
Validation
pnpm lintpnpm knippnpm test(121 files, 1,329 passed, 9 skipped)pnpm typecheck(38 tasks)pnpm build(27 tasks)Part of #229.