Skip to content

feat(server): add onPeerDisconnect, symmetric with onPeerConnect - #166

Open
dvcolomban wants to merge 1 commit into
devframes:mainfrom
dvcolomban:dvcol/on-peer-disconnect
Open

feat(server): add onPeerDisconnect, symmetric with onPeerConnect#166
dvcolomban wants to merge 1 commit into
devframes:mainfrom
dvcolomban:dvcol/on-peer-disconnect

Conversation

@dvcolomban

Copy link
Copy Markdown
Contributor

What

startHttpAndWs's onDisconnected handler consumed the transport's own disconnect entirely — it only fed rpcHost._emitSessionDisconnected(meta) — leaving callers with no way to observe a peer going away. The only socket-close hook that exists is host-functions.ts's _emitSessionDisconnected, and its own docblock says it's @internal and "must not" widen the public surface. Meanwhile onPeerConnect (the connect-time counterpart) is already public.

This adds onPeerDisconnect?: (peer, meta) => void, forwarded verbatim to the underlying startHttpAndWs. Unlike onPeerConnect it receives the raw session meta, not a wrapped session — by the time a peer disconnects there's no live RPC client left to attach.

createDevServer never forwarded either hook down to startHttpAndWs at all, so this also adds a passthrough onPeerConnect option there for parity — today a createDevServer caller has no way to reach either callback.

Why this matters

Any host that tracks per-peer state outside the RPC layer (a registry keyed by connection, a presence list, cleanup for something the peer owned) currently has no first-party way to know a peer left — it either reaches for the internal, explicitly-not-for-this _emitSessionDisconnected, or leaks that state forever.

Tests

Two new cases:

  • packages/devframe/src/node/__tests__/server.test.ts: startHttpAndWs forwards both hooks for the same peer — onPeerConnect fires on open, onPeerDisconnect fires on close with matching session meta (meta.id), and neither fires early.
  • packages/devframe/src/adapters/__tests__/dev.test.ts: createDevServer forwards both options down to startHttpAndWs end to end.

Both verified to fail (0 calls recorded) against the pre-fix code before adding the guard/forwarding.

pnpm --filter devframe exec vitest run — 49 files, 448 tests, all green. tsc --noEmit clean. eslint clean.


🤖 Generated with Claude Code

startHttpAndWs's onDisconnected handler consumed the transport's own
disconnect entirely (emitting the session-disconnected event), leaving
callers with no way to observe a peer going away — the only socket-close
hook is host-functions.ts's _emitSessionDisconnected, and its own
docblock says it is @internal and must not widen the public surface.

Add onPeerDisconnect(peer, meta), forwarded verbatim to the underlying
startHttpAndWs. Unlike onPeerConnect it receives the raw session meta,
not a wrapped session — by the time a peer disconnects there is no live
RPC client left to attach.

createDevServer never forwarded either hook down to startHttpAndWs, so
this also adds a passthrough onPeerConnect option there for parity —
today a createDevServer caller has no way to reach either callback at
all.
Copilot AI lite review requested due to automatic review settings August 5, 2026 16:16
@netlify

netlify Bot commented Aug 5, 2026

Copy link
Copy Markdown

Deploy Preview for devfra ready!

Name Link
🔨 Latest commit d6c894e
🔍 Latest deploy log https://app.netlify.com/projects/devfra/deploys/6a7361e8e41983000849c277
😎 Deploy Preview https://deploy-preview-166--devfra.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

onPeerDisconnect currently receives a meta object after internal disconnect cleanup mutates it, which can undermine the “raw session meta” semantics for consumers.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.

Pull request overview

This PR adds a public disconnect-time peer hook to the devframe node WebSocket server (startHttpAndWs) and plumbs both connect/disconnect peer hooks through createDevServer, enabling hosts to react to peer lifecycle events without reaching into @internal APIs.

Changes:

  • Added onPeerDisconnect to StartHttpAndWsOptions and invoked it from the WS transport onDisconnected handler.
  • Added onPeerConnect/onPeerDisconnect passthrough options to createDevServer.
  • Added vitest coverage for hook forwarding at both the startHttpAndWs and createDevServer layers.
File summaries
File Description
packages/devframe/src/node/server.ts Adds onPeerDisconnect option and wires it into the WS disconnect hook.
packages/devframe/src/node/tests/server.test.ts Verifies startHttpAndWs fires connect + disconnect hooks for the same session.
packages/devframe/src/adapters/dev.ts Exposes and forwards peer hook options through createDevServer.
packages/devframe/src/adapters/tests/dev.test.ts Verifies createDevServer forwards both hooks to startHttpAndWs.
Review details
  • Files reviewed: 4/4 changed files
  • Comments generated: 1
  • Review effort level: Lite

We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.

Comment on lines +234 to 237
onDisconnected: (peer, meta) => {
rpcHost._emitSessionDisconnected(meta)
options.onPeerDisconnect?.(peer, meta)
},
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants