Skip to content

feat(core): add WebSocket RPC protocol and browser API client#97

Merged
mgks merged 4 commits intodocmd-io:mainfrom
svallory:feat/websocket-rpc
Apr 9, 2026
Merged

feat(core): add WebSocket RPC protocol and browser API client#97
mgks merged 4 commits intodocmd-io:mainfrom
svallory:feat/websocket-rpc

Conversation

@svallory
Copy link
Copy Markdown
Contributor

@svallory svallory commented Apr 5, 2026

Summary

  • Upgrades the dev server WebSocket to handle JSON-based RPC alongside the existing 'reload' string protocol
  • Adds docmd-api.js browser client with docmd.call(), docmd.send(), docmd.on(), docmd.afterReload(), docmd.scheduleReload()
  • Injects git user identity (window.__docmd_dev) for plugin auth features
  • Backwards compatible — the browser API still handles plain 'reload' messages

Context

Part of the plugin API infrastructure discussed in #73. Depends on #95 and #96.

This is the final piece that wires the action dispatcher into the dev server. The browser API replaces the inline live-reload script with a served file at /__dev/docmd-api.js that handles both live-reload and plugin RPC.

Wire protocol

// call (client → server)
{"id": "a1b2", "type": "call", "action": "threads:add-thread", "payload": {...}}
// response (server → client)  
{"id": "a1b2", "type": "response", "result": {...}, "reload": false}
// event (either direction)
{"type": "event", "name": "threads:comment-added", "data": {...}}

Note: reload: false in responses — file changes are detected by chokidar which triggers rebuild + broadcastReload, preventing double-reload.

Changes

File Change
packages/core/src/commands/dev.ts WebSocket message handling, action dispatch, /__dev/ route, git identity injection
packages/ui/assets/js/docmd-api.js New: browser-side RPC client (IIFE)

Test plan

  • Start dev server, connect WebSocket, send call message, verify response
  • Verify 'reload' string messages still trigger page reload (backwards compat)
  • Verify /__dev/docmd-api.js is served with correct Content-Type
  • Run pnpm test

svallory added 3 commits April 3, 2026 17:23
Plugins can now export `actions` (for WebSocket RPC handlers) and
`events` (for fire-and-forget handlers) alongside existing build-time
hooks. Also defines PluginModule, ActionContext, and SourceTools types
for the plugin API contract.
Action dispatcher routes WebSocket RPC calls and events to plugin
handlers with a sandboxed ActionContext. Source-tools translate
rendered-output references (block positions, text offsets) back to
raw markdown source positions for safe file editing.

- Port action-dispatcher.js to TypeScript/ESM with async fs.promises
- Port source-tools.js to TypeScript/ESM with async fs.promises
- Import createMarkdownProcessor from @docmd/parser (upstream export)
- safePath rejects any path traversal outside projectRoot
- Export both modules from @docmd/core barrel
The dev server now handles JSON-based WebSocket messages for plugin
action calls (RPC) and events alongside the existing live-reload.
The browser API (docmd-api.js) provides docmd.call(), docmd.send(),
docmd.on(), docmd.afterReload(), and docmd.scheduleReload() for
plugin-server communication. Also injects git user info for plugin
identity features.

Changes:
- New file: packages/ui/assets/js/docmd-api.js — browser-side IIFE
  that manages WebSocket connection, RPC calls with promise-based
  responses, fire-and-forget events, server event subscriptions,
  and sessionStorage-backed reload context stashing. Backwards
  compatible with plain 'reload' string messages.
- Modified: packages/core/src/commands/dev.ts — replaced inline
  live-reload script injection with external docmd-api.js served
  from /__dev/docmd-api.js route. Added WebSocket message handler
  that dispatches JSON RPC calls to plugin action handlers via
  createActionDispatcher. Added getGitDevInfo() helper that reads
  git config and computes Gravatar URL for dev identity injection.
…er API

- Use const for non-reassigned loop variable (prefer-const)
- Add comments to empty catch blocks (no-empty)
- Declare browser globals for docmd-api.js (no-undef)
@svallory svallory mentioned this pull request Apr 5, 2026
@mgks mgks merged commit 0663170 into docmd-io:main Apr 9, 2026
1 check passed
@mgks mgks added the Feature / Enhancement New feature addition or request/suggestion label Apr 9, 2026
@mgks
Copy link
Copy Markdown
Member

mgks commented Apr 9, 2026

Merged! WebSocket RPC is now integrated with our native fs.watch file watcher (we replaced chokidar since 0.6.6). Both systems coexist cleanly. 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Feature / Enhancement New feature addition or request/suggestion

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants