Skip to content

Latest commit

 

History

21 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

shared-ipc

A simple JavaScript library providing an asynchronous method call interface for Workers, Iframes and cross-window contexts using postMessage.

Installation

npm install shared-ipc

Usage

Basic Setup

import { 
  makeIpcRequest, 
  sendIpcMessage, 
  addMessageHandler, 
  handleMessage 
} from "shared-ipc";

// In both frames/workers:
window.addEventListener("message", handleMessage);

// Add message handlers
addMessageHandler("greet", (name) => {
  return `Hello ${name}!`;
});

// In parent frame communicating with iframe:
const iframe = document.getElementById("my-iframe");
await makeIpcRequest(iframe, "greet", "World"); // Returns "Hello World!"

// Or send a message without waiting for response
sendIpcMessage(iframe, "notification", { type: "alert" });

API

makeIpcRequest(target:IpcTarget, call:string, data:any)

Makes an IPC request and returns a promise that resolves with the response.

sendIpcMessage(target:IpcTarget, call:string, data:any)

Sends an IPC message without waiting for a response.

addIpcMessageHandler(name:string, handler:Function)

Adds a handler function for a specific message type.

handleIpcMessage(data:IpcEventData)

The message event handler that processes incoming messages.

PublicPromise

Utility class used internally for managing promise resolution.

Strict endpoint API

createStrictIpcEndpoint(port, options) creates an opt-in endpoint bound to one MessagePort. It uses construction-time incoming/outgoing command registries, consumer validators, exact envelopes, sequenced traffic, random request IDs, timeouts, abort cleanup and explicit disposal. It never uses the legacy global handler registry or global-function fallback.

import { createStrictIpcEndpoint } from "shared-ipc";

const endpoint = createStrictIpcEndpoint(port, {
  channelId: crypto.randomUUID(),
  incoming: new Map([
    ["notify", {
      kind: "message",
      validate: value => typeof value === "string",
      handler: value => console.log(value)
    }]
  ]),
  outgoing: new Map([
    ["lookup", {
      kind: "request",
      validate: value => typeof value === "string",
      validateResult: value => typeof value === "string"
    }]
  ])
});

const value = await endpoint.request("lookup", "key", {
  timeoutMs: 1000,
  signal: abortController.signal
});
endpoint.dispose();

Application command names, schemas and lifecycle policy remain the consumer's responsibility. Strict endpoints are separate from the existing API, whose default behavior remains unchanged.

Incoming and outgoing registries are copied and retained only inside the local endpoint. They are never transmitted or exposed through an enumeration API. Each peer must construct its own validators; applications should not share one bidirectional schema object merely for convenience. Commands may use non-empty strings or non-negative safe integers, allowing consumers to use compact or transformed identifiers.

Remote handler exception details are redacted as Remote handler failed by default. Tests or development tools may set exposeRemoteErrors: true on the receiving endpoint, but production receivers should retain the safe default. Detailed onReject diagnostics are local to the endpoint and are never sent to its peer.

IpcTarget compatibility matrix:

Type Window (Browser) Worker (Browser) MessagePort (Node)
Window (Browser) ✅ Yes ✅ Yes ❌ No
Worker (Browser) ✅ Yes ✅ Yes ❌ No
Iframe (Browser) ✅ Yes ✅ Yes ❌ No
MessagePort (Node) ❌ No ❌ No ✅ Yes
Worker (Node) ❌ No ❌ No ✅ Yes

License

MIT

About

A simple JavaScript library providing an asynchronous method call interface for Workers, Iframes and cross-window contexts

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages