JSPM

@ekaone/telepath

0.0.1
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 7
  • Score
    100M100P100Q43023F
  • License MIT

Message passing library for Node.js and the browser.

Package Exports

  • @ekaone/telepath

Readme

@ekaone/telepath

Typed cross-context message bus for browser environments.

Designed for horizontal communication across tabs, windows, iframes, and workers instead of within a single runtime.

Tab A  ──telepath──  Tab B
             │
         Web Worker

Install

npm install @ekaone/telepath

// or with pnpm

pnpm add @ekaone/telepath

Quick Start

import { createChannel } from "@ekaone/telepath"

type AppEvents = {
  "user:logout": { reason: string }
  "cart:update": { items: number }
}

const ch = createChannel<AppEvents>("my-app")

// subscribe
ch.on("user:logout", (payload) => {
  console.log("logged out:", payload.reason)
})

// emit — typed, typos caught at compile time
ch.emit("user:logout", { reason: "session-expired" })

// teardown
ch.close()

API

createChannel<TMap>(name, options?)

Creates a named channel. All same-origin contexts using the same name share the channel.

// strict — full type safety (recommended)
const ch = createChannel<AppEvents>("my-app")

// flexible — no schema, payload is unknown
const ch = createChannel("my-app")

Options

Option Type Default Description
transport "broadcast" | "memory" auto-detect Force a specific transport adapter

Auto-detection: uses BroadcastChannel if available, falls back to in-memory.


ch.emit(event, payload)

Broadcast a typed event to all subscribers on this channel across all contexts.

ch.emit("cart:update", { items: 3 })

ch.on(event, listener)unsubscribe

Subscribe to a specific event or wildcard pattern. Returns an unsubscribe function.

// exact match
const unsub = ch.on("cart:update", (payload) => {
  console.log(payload.items)
})

// wildcard — receives event name + payload
ch.on("user:*", (event, payload) => {
  console.log(event, payload)
})

// unsubscribe
unsub()

Wildcard patterns

Pattern Matches
* every event
user:* user:login, user:logout, …
cart:* cart:update, cart:clear, …

ch.close()

Tear down the channel and release all underlying resources.

ch.close()

Transports

Adapter When used
BroadcastTransport Browser — crosses tabs, windows, workers
MemoryTransport No BroadcastChannel detected, or forced

Force a transport explicitly:

// always in-memory (useful in tests)
const ch = createChannel("app", { transport: "memory" })

// always BroadcastChannel
const ch = createChannel("app", { transport: "broadcast" })

Testing with Vitest

No DOM setup needed. Use the memory transport:

import { createChannel } from "@ekaone/telepath"
import { describe, expect, it, vi } from "vitest"

type Events = { "ping": { id: number } }

describe("my feature", () => {
  it("receives events", () => {
    const ch = createChannel<Events>("test", { transport: "memory" })
    const listener = vi.fn()

    ch.on("ping", listener)
    ch.emit("ping", { id: 1 })

    expect(listener).toHaveBeenCalledWith({ id: 1 })
    ch.close()
  })
})

Relationship to @ekaone/hermes

Package Scope Transport
@ekaone/hermes In-process event bus In-memory only
@ekaone/telepath Cross-context message bus BroadcastChannel

They are composable. A createBridge(hermes, telepath) utility is planned for v0.2.0.


Roadmap

v0.1.0createChannel(), typed events, wildcards, BroadcastTransport, MemoryTransport

v0.2.0createBridge(hermes, telepath), leader election, once()

v0.3.0 — Node cross-process adapter, @ekaone/telepath-devtools


Requirements

  • Node ≥ 18
  • Browser with BroadcastChannel support (all modern browsers)

License

MIT © Eka Prasetia


⭐ If this library helps you, please consider giving it a star on GitHub!