vscode-extension-messaging-framework
v1.0.0
Published
A TypeScript library that wraps VS Code's postMessage API with request/response semantics
Maintainers
Readme
vscode-extension-messaging-framework
A TypeScript library that wraps VS Code's postMessage API with typed request/response semantics, timeout handling, and error propagation.
Why
VS Code webview communication via postMessage is untyped and fire-and-forget. There's no built-in way to send a request and wait for a response, handle timeouts, or propagate errors. You end up writing boilerplate to correlate messages, track pending requests, and serialize errors.
This library gives you:
- Request/response - send a request,
awaitthe result - Notifications - fire-and-forget messages
- Bidirectional - both extension and webview can send requests to each other
- Type safety - define a schema once, get compile-time checks on method names, params, and results
- Timeout handling - configurable per-request or per-messenger, with automatic cleanup
- Error propagation - errors thrown in handlers are serialized, sent across the boundary, and re-thrown as
MessagingErroron the caller side
Install
npm install vscode-extension-messaging-frameworkUsage
1. Define a schema
Create a shared schema that both your extension and webview code can import:
import type { DefineRequest, DefineNotification, MessageSchema } from 'vscode-extension-messaging-framework/shared';
type GetUser = DefineRequest<'getUser', { id: string }, { name: string; email: string }>;
type SaveDraft = DefineRequest<'saveDraft', { content: string }, { saved: boolean }>;
type ThemeChanged = DefineNotification<'themeChanged', { theme: 'light' | 'dark' }>;
export interface MySchema extends MessageSchema {
webviewRequests: GetUser | SaveDraft; // webview -> extension
extensionRequests: never; // extension -> webview (none in this example)
webviewNotifications: never;
extensionNotifications: ThemeChanged;
}2. Extension side
import { ExtensionMessenger } from 'vscode-extension-messaging-framework/extension';
import type { MySchema } from './shared/schema';
const messenger = new ExtensionMessenger<MySchema>(panel.webview, {
defaultTimeout: 5000,
});
// Handle requests from the webview
messenger.onRequest('getUser', async ({ id }) => {
const user = await db.findUser(id);
return { name: user.name, email: user.email };
});
// Send a notification to the webview
messenger.notify('themeChanged', { theme: 'dark' });3. Webview side
import { WebviewMessenger } from 'vscode-extension-messaging-framework/webview';
import type { MySchema } from '../shared/schema';
const messenger = new WebviewMessenger<MySchema>();
messenger.start();
// Send a request to the extension
const user = await messenger.request('getUser', { id: '123' });
console.log(user.name);
// Listen for notifications
messenger.onNotification('themeChanged', ({ theme }) => {
document.body.className = theme;
});Error handling
Errors thrown in handlers are automatically propagated to the caller:
import { MessagingError, ErrorCode } from 'vscode-extension-messaging-framework/shared';
// Extension side
messenger.onRequest('saveDraft', ({ content }) => {
if (!content) {
throw new MessagingError(ErrorCode.InvalidParams, 'Content cannot be empty');
}
return { saved: true };
});
// Webview side
try {
await messenger.request('saveDraft', { content: '' });
} catch (err) {
// err is a MessagingError with code, message, and optional data
}Requests that exceed the timeout throw a MessagingError with ErrorCode.Timeout. You can override the timeout per request:
const result = await messenger.request('saveDraft', { content }, { timeout: 10000 });Cleanup
Both messengers implement dispose() which removes listeners and cancels pending requests:
messenger.dispose();Demo
The demo/ directory contains a working VS Code extension that exercises the main features of the library:
- Request/response - increment a counter by sending typed requests from the webview to the extension
- Bidirectional requests - the extension requests an input value from the webview
- Timeout handling - a slow operation that succeeds (2s) vs one that exceeds the 5s timeout
- Error propagation - a handler that intentionally throws, demonstrating error serialization across the boundary
- Notifications - real-time counter updates and log messages pushed from the extension to the webview
To run the demo:
cd demo
npm install
npm run buildThen press F5 in VS Code to launch the Extension Development Host, and run the Messaging Demo: Show Panel command.
