@lbaumorg/iframer
v1.0.3
Published
A tiny, fully typed communication library for **parent ↔ iframe** messaging.
Maintainers
Readme
Iframer
A tiny, fully typed communication library for parent ↔ iframe messaging.
Iframer provides a simple, type-safe API on top of window.postMessage() for communicating between a parent window and an iframe.
- ✨ Tiny & dependency-free
- 🔒 Origin-aware
- 💪 Fully typed with TypeScript
- 📡 Event-based messaging
- 🔄 Request/response (RPC) support
- 🧹 Automatic cleanup
Installation
npm install @lbaumorg/iframerpnpm add @lbaumorg/iframeryarn add @lbaumorg/iframerFeatures
- Parent → iframe communication
- Iframe → parent communication
- Typed events
- Typed request/response
- Promise-based RPC
- Zero dependencies
- Works with any framework
Quick Start
Define your protocol
interface ParentToIframe {
setTheme: {
theme: "light" | "dark";
};
ping: void;
}
interface IframeToParent {
ready: void;
save: {
text: string;
};
}Parent
import { Iframer } from "iframer";
const iframe = document.querySelector("iframe")!;
const bus = new Iframer<
ParentToIframe,
IframeToParent
>(
iframe.contentWindow!,
"https://iframe.example.com",
);
bus.on("ready", () => {
console.log("Iframe is ready");
});
bus.on("save", ({ text }) => {
console.log(text);
});
bus.emit("setTheme", {
theme: "dark",
});Iframe
import { Iframer } from "iframer";
const bus = new Iframer<
IframeToParent,
ParentToIframe
>(
window.parent,
"https://parent.example.com",
);
bus.on("setTheme", ({ theme }) => {
document.documentElement.dataset.theme = theme;
});
bus.emit("ready", undefined);API
new Iframer(target, origin?)
Creates a new communication channel.
const bus = new Iframer(targetWindow, origin);Parameters
| Name | Type | Description |
|------|------|-------------|
| target | Window | Target window (window.parent or iframe.contentWindow) |
| origin | string | Allowed origin (* by default) |
emit(event, payload)
Send an event without expecting a response.
bus.emit("save", {
text: "Hello!",
});on(event, handler)
Register an event listener.
bus.on("save", payload => {
console.log(payload.text);
});Returns a cleanup function.
const unsubscribe = bus.on("save", handler);
unsubscribe();request(event, payload)
Send a request and await a response.
const result = await bus.request<
"ping",
{ time: number }
>("ping", undefined);Receiver:
bus.on("ping", () => {
return {
time: Date.now(),
};
});Supports async handlers as well.
bus.on("user", async ({ id }) => {
return await fetchUser(id);
});destroy()
Removes all event listeners.
bus.destroy();Call this when the communication channel is no longer needed.
Type Safety
Iframer uses two generic types:
Iframer<
OutgoingEvents,
IncomingEvents
>Example:
interface Outgoing {
login: {
token: string;
};
}
interface Incoming {
ready: void;
}
const bus = new Iframer<
Outgoing,
Incoming
>(...);This gives full autocomplete and compile-time validation for every event.
How it works
Iframer is a lightweight wrapper around the browser's native window.postMessage() API.
Internally it provides:
- event dispatching
- request/response IDs
- promise resolution
- typed payloads
without exposing any protocol details.
Browser Support
Works in all modern browsers supporting:
window.postMessagePromisecrypto.randomUUID()(or a compatible polyfill)
Roadmap
Planned features include:
- Origin validation
- Request timeouts
once()listeners- Middleware
- Automatic handshake
- Message queue before iframe load
- Multiple targets
- Debug mode
Why Iframer?
Using window.postMessage() directly quickly becomes repetitive:
- Manual message parsing
- Event routing
- Request IDs
- Promise management
- Type casting
- Cleanup
Iframer handles those concerns while keeping the API small and predictable.
License
MIT
