@rshaker/communicator
    Preparing search index...

    @rshaker/communicator

    Communicator

    TypeScript version

    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