Skip to content

docs(devframe): rpc/ folder + WeakMap context pattern#25

Merged
antfu merged 4 commits into
mainfrom
antfu/skills-rpc-structure
May 22, 2026
Merged

docs(devframe): rpc/ folder + WeakMap context pattern#25
antfu merged 4 commits into
mainfrom
antfu/skills-rpc-structure

Conversation

@antfu
Copy link
Copy Markdown
Contributor

@antfu antfu commented May 22, 2026

Summary

Establishes a recommended project layout for non-trivial devframes — one file per RPC under src/rpc/, with a sibling src/context.ts exposing a WeakMap<DevToolsNodeContext, T> for sharing setup-time state (channels, shared state handles, loaders) across per-file RPCs. The skill and the RPC guide previously implied this layout in code samples but never stated the convention; the three examples now follow it (streaming-chat demonstrates the WeakMap context for its shared channel + history).

Includes a framework fix: definition.__resolved is now keyed per-context via WeakMap, so module-level RPC defs registered into multiple contexts in the same process (multi-server tests, hot-reload teardown/replay) no longer share a handler closed over the first context's state. This unlocks the new pattern in tests without requiring user-side workarounds.

As a side effect of the type-safe client registry barrels (const serverFunctions = [...] as const + RpcDefinitionsToFunctions), every rpc.call(... as any) cast in the example clients is gone.

antfu added 2 commits May 22, 2026 19:07
Module-level RPC defs registered into multiple contexts in the same
process (multi-server tests, hot-reload teardown/replay) previously
shared a handler closed over the first context's state. Cache by
context object so each context gets its own setup result.
Skill and rpc guide now describe the one-file-per-RPC layout under
src/rpc/ and the WeakMap-based src/context.ts for sharing setup-time
state across files. All three examples adopt the pattern, with
streaming-chat demonstrating the WeakMap context for its shared
channel + history.
Copilot AI review requested due to automatic review settings May 22, 2026 10:08
@netlify
Copy link
Copy Markdown

netlify Bot commented May 22, 2026

Deploy Preview for devfra ready!

Name Link
🔨 Latest commit e279aa3
🔍 Latest deploy log https://app.netlify.com/projects/devfra/deploys/6a102e65ac289c00080431ad
😎 Deploy Preview https://deploy-preview-25--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.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR documents and codifies a recommended RPC project layout (src/rpc/ + optional src/context.ts WeakMap pattern) for non-trivial devframes, updates examples to follow it, and fixes a framework-level caching bug so module-level RPC definitions can safely be registered into multiple node contexts within the same process.

Changes:

  • Add/clarify documentation for the src/rpc/ per-function layout, plus src/context.ts WeakMap context-sharing pattern.
  • Refactor the streaming-chat, next-runtime-snapshot, and files-inspector examples to use the new layout and type-safe client registry (removing rpc.call(... as any) casts).
  • Change RPC setup-result caching from a single global slot to a per-context WeakMap cache (getRpcResolvedSetupResult + public type snapshots).

Reviewed changes

Copilot reviewed 27 out of 28 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/snapshots/tsnapi/devframe/recipes/open-helpers.snapshot.d.ts Updates public API snapshot to reflect new per-context setup caching fields.
skills/devframe/SKILL.md Documents recommended src/rpc/ layout and WeakMap context-sharing pattern with examples.
docs/guide/rpc.md Adds a concise recommendation for per-RPC files + serverFunctions barrel + WeakMap context.
packages/devframe/src/rpc/types.ts Replaces __resolved with __cache (WeakMap) + __promise fallback in RPC definition types.
packages/devframe/src/rpc/handler.ts Implements per-context setup-result caching using WeakMap keyed by context object.
examples/streaming-chat/src/devframe.ts Registers RPCs via serverFunctions and uses setStreamingChatContext for shared setup state.
examples/streaming-chat/src/context.ts Introduces WeakMap-backed context store for sharing channel/history across RPC modules.
examples/streaming-chat/src/rpc/* Splits RPCs into per-file modules and barrels them in src/rpc/index.ts.
examples/streaming-chat/src/types.ts Extracts shared-state typing into a dedicated types module.
examples/streaming-chat/src/constants.ts Extracts constants used across server/client/types.
examples/streaming-chat/src/client/app.tsx Removes unsafe as any casts by relying on the typed registry + shared constants/types.
examples/next-runtime-snapshot/src/devframe.ts Registers RPCs via serverFunctions and re-exports types from per-RPC files.
examples/next-runtime-snapshot/src/rpc/* Introduces per-file RPCs and a serverFunctions barrel with module augmentation.
examples/next-runtime-snapshot/src/client/app/components/* Removes as any casts from RPC calls now that names are typed.
examples/files-inspector/src/devframe.ts Registers RPCs via serverFunctions barrel instead of inline definitions.
examples/files-inspector/src/rpc/* Introduces per-file RPCs and a serverFunctions barrel with module augmentation.
examples/files-inspector/src/client/routes/* Removes as any casts from RPC calls now that names are typed.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread examples/streaming-chat/src/types.ts Outdated
@@ -0,0 +1,22 @@
import type { HISTORY_KEY } from './constants'
Comment on lines +96 to +104
for (const token of fakeTokens(prompt)) {
if (stream.signal.aborted) {
cancelled = true
break
}
stream.write(token)
acc += token
await new Promise(r => setTimeout(r, intervalMs))
}
antfu added 2 commits May 22, 2026 19:13
Mirrors @vitejs/devtools-kit conventions and leaves room for sibling
files like rpc/utils.ts next to rpc/index.ts as the rpc surface grows.
Node native ESM (bin.mjs -> src/devframe.ts) doesn't auto-resolve
directory or extension-less imports — only the bundler-backed test
harness did. Add explicit .ts extensions so the playwright e2e
webserver can boot the examples.
Copilot AI review requested due to automatic review settings May 22, 2026 10:22
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 27 out of 28 changed files in this pull request and generated 1 comment.

Comment on lines +18 to +21
declare module 'devframe/types' {
interface DevToolsRpcSharedStates {
[HISTORY_KEY]: ChatHistory
}
@antfu antfu merged commit 6b58132 into main May 22, 2026
13 checks passed
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