Communicator is an experimental, Node.js package for inter-context messaging in Chromium-based browsers. The library is designed to work in main, isolated, background, and extension page contexts. Persistent data storage is available from any of these contexts via either direct IndexedDB access, or by an asynchronous messaging-based API.
- Cross-context Messaging – Type-safe messaging between background, content, and extension pages
- Request-Reply Pattern – Message correlation and reply support using unique message IDs
- Pluggable Storage – Built-in IndexedDB, in-memory, and messaging-based providers
- TypeScript-first – Full type safety and modern async/await APIs
- Extensible & Lightweight – Minimal dependencies, easy to integrate and extend
npm install @rshaker/communicator
The CommMgr
singleton automatically detects the current browser context and registers listeners for incoming messages. Usage is identical in each extension context:
import { CommMgr, CommMsg } from "@rshaker/communicator";
import { detectContext } from "@rshaker/context-detect";
console.info(`Startup in context: ${detectContext()}`);
const commMgr = CommMgr.getInstance<CommMsg>();
commMgr.addListener((message) => {
console.log(`Handled message from ${message?.fromContext}`, message);
});
import { CommMgr, CommMsg } from "@rshaker/communicator";
import { detectContext, BrowserContextType } from "@rshaker/context-detect";
const commMgr = CommMgr.getInstance<CommMsg>();
const currentContext = detectContext();
if (currentContext === BrowserContextType.MAIN_WORLD) {
// Report mouse coordinates to the background context
document.addEventListener("mousemove", ({ clientX, clientY }) => {
const msg: CommMsg = {
type: "ping",
id: "pointer-coordinates",
toContext: BrowserContextType.BACKGROUND_WORKER,
payload: { entry: { clientX, clientY, timestamp: Date.now() } },
};
commMgr.sendMessage(msg);
});
} else if (currentContext === BrowserContextType.BACKGROUND_WORKER) {
commMgr.addListener((msg: CommMsg) => {
if (msg.type === "ping" && msg.id === "pointer-coordinates") {
console.log("Pointer coordinates received:", msg.payload.entry);
}
});
}
Suppose you want to allow content scripts or main-world pages to persist data, but only the background worker has direct access to IndexedDB. You can use MessagingProvider
in the main-world, and have the background worker act as a bridge to IndexedDB.
In the background worker:
import { CommMgr, MessagingProvider, IndexedDBProvider } from "@rshaker/communicator";
// Set up the physical IndexedDB provider
const idbStorage = new IndexedDBProvider("communicator", "test");
// Set up the comm manager and messaging provider
const commMgr = CommMgr.getInstance();
const _messagingProvider = new MessagingProvider(commMgr, { idbProvider: idbStorage });
In the main-world (or content script):
import { CommMgr, MessagingProvider } from "@rshaker/communicator";
// Set up the comm manager
const commMgr = CommMgr.getInstance();
// Use MessagingProvider to proxy storage requests to the background worker
const msgStorage = new MessagingProvider(commMgr);
// Add an entry
const id = await msgStorage.add({
data: {
message: "User action recorded",
timestamp: Date.now(),
level: "info",
},
});
// List all entries
const entries = await msgStorage.list();
console.log("All entries:", entries);
// Retrieve the entry by its actual ID
const entry = await msgStorage.get(id);
Communicator is organized into several core modules:
- CommMgr: Singleton manager for cross-context messaging
- PersistProvider: Interface for pluggable storage providers
- IndexedDBProvider: Persistent storage using browser IndexedDB
- InMemoryProvider: Volatile storage using JavaScript Map
- MessagingProvider: Storage provider using extension messaging (for ephemeral or remote storage)
- Context Utilities: Helpers for detecting and working with browser extension contexts
- Node.js (22.12.0+)
- npm (10.9+) or yarn
# Clone the repository
git clone https://github.com/rshaker/communicator.git
cd communicator
# Use the correct node version
nvm use
# Install dependencies
npm install
# Generate API documentation
npm run docs
# Build (development library)
npm run build:dev
# Build (web extension)
npm run build:webext
# Run all tests
npm test
Full API documentation (generated with TypeDoc) is available under the docs directory. Auto-generated docs contains class, interface, and type details for all modules.
MIT