Type-safe RPC toolkit for communication across Workers, iframes, and network boundaries.
npm install @bigmistqke/rpc- Type-safe: Full TypeScript support with inferred types
- Multiple transports: Works with Web Workers, iframes, fetch, and streams
- Nested methods: Support for deeply nested method calls
- Lightweight: Minimal dependencies
Request-response RPC over postMessage for Workers and iframes.
Worker:
import { expose } from '@bigmistqke/rpc/messenger'
const methods = {
greet: (name: string) => `Hello, ${name}!`,
add: (a: number, b: number) => a + b,
math: {
square: (n: number) => n * n,
factorial: (n: number): number => (n <= 1 ? 1 : n * methods.math.factorial(n - 1)),
},
}
expose(methods)
export type Methods = typeof methodsMain thread:
import { rpc } from '@bigmistqke/rpc/messenger'
import type { Methods } from './worker'
const worker = new Worker('./worker.ts', { type: 'module' })
const proxy = rpc<Methods>(worker)
await proxy.greet('World') // "Hello, World!"
await proxy.add(2, 3) // 5
await proxy.math.square(4) // 16RPC over HTTP fetch requests.
Server (e.g., Cloudflare Worker):
import { expose, isFetchRequest } from '@bigmistqke/rpc/fetch'
const methods = {
hello: () => 'Hello from server!',
echo: (msg: string) => msg,
}
export default {
async fetch(request: Request) {
if (isFetchRequest({ request })) {
return expose(methods)({ request })
}
return new Response('Not found', { status: 404 })
},
}
export type Methods = typeof methodsClient:
import { rpc } from '@bigmistqke/rpc/fetch'
import type { Methods } from './server'
const proxy = rpc<Methods>('https://api.example.com')
await proxy.hello() // "Hello from server!"
await proxy.echo('test') // "test"Bidirectional RPC over streams for persistent connections.
Server:
import { server, isStreamRequest } from '@bigmistqke/rpc/stream'
const serverMethods = {
ping: () => 'pong',
}
export default {
async fetch(request: Request) {
if (isStreamRequest({ request })) {
const { proxy, response } = server<ClientMethods, typeof serverMethods>(
request.body!,
serverMethods,
)
// Call client methods
await proxy.clientMethod()
return response
}
},
}Client:
import { client } from '@bigmistqke/rpc/stream'
const clientMethods = {
clientMethod: () => 'called from server',
}
const { proxy } = client<ServerMethods, typeof clientMethods>(
'https://api.example.com',
clientMethods,
)
await proxy.ping() // "pong"Check out the live demo to see all modules in action.
MIT