birpc

Message based Two-way remote procedure call

MIT 38 个版本
安装
npm install birpc
yarn add birpc
pnpm add birpc
bun add birpc
README

birpc

NPM version

Message-based two-way remote procedure call. Useful for WebSockets and Workers communication.

Features

  • Intuitive - call remote functions just like locals, with Promise to get the response
  • TypeScript - safe function calls for arguments and returns
  • Protocol agonostic - WebSocket, MessageChannel, any protocols with messages communication would work!
  • Zero deps, ~0.5KB

Examples

Using WebSocket

When using WebSocket, you need to pass your custom serializer and deserializer.

Client

import type { ServerFunctions } from './types'

const ws = new WebSocket('ws://url')

const clientFunctions: ClientFunctions = {
  hey(name: string) {
    return `Hey ${name} from client`
  }
}

const rpc = createBirpc<ServerFunctions>(
  clientFunctions,
  {
    post: data => ws.send(data),
    on: fn => ws.on('message', fn),
    // these are required when using WebSocket
    serialize: v => JSON.stringify(v),
    deserialize: v => JSON.parse(v),
  },
)

await rpc.hi('Client') // Hi Client from server

Server

import type { ClientFunctions } from './types'
import { WebSocketServer } from 'ws'

const serverFunctions: ServerFunctions = {
  hi(name: string) {
    return `Hi ${name} from server`
  }
}

const wss = new WebSocketServer()

wss.on('connection', (ws) => {
  const rpc = createBirpc<ClientFunctions>(
    serverFunctions,
    {
      post: data => ws.send(data),
      on: fn => ws.on('message', fn),
      serialize: v => JSON.stringify(v),
      deserialize: v => JSON.parse(v),
    },
  )

  await rpc.hey('Server') // Hey Server from client
})

Circular References

As JSON.stringify does not supporting circular references, we recommend using structured-clone-es as the serializer when you expect to have circular references.

import { parse, stringify } from 'structured-clone-es'

const rpc = createBirpc<ServerFunctions>(
  functions,
  {
    post: data => ws.send(data),
    on: fn => ws.on('message', fn),
    // use structured-clone-es as serializer
    serialize: v => stringify(v),
    deserialize: v => parse(v),
  },
)

Using MessageChannel

MessageChannel will automatically serialize the message and support circular references out-of-box.

export const channel = new MessageChannel()

Bob

import type { AliceFunctions } from './types'
import { channel } from './channel'

const Bob: BobFunctions = {
  hey(name: string) {
    return `Hey ${name}, I am Bob`
  }
}

const rpc = createBirpc<AliceFunctions>(
  Bob,
  {
    post: data => channel.port1.postMessage(data),
    on: fn => channel.port1.on('message', fn),
  },
)

await rpc.hi('Bob') // Hi Bob, I am Alice

Alice

import type { BobFunctions } from './types'
import { channel } from './channel'

const Alice: AliceFunctions = {
  hi(name: string) {
    return `Hi ${name}, I am Alice`
  }
}

const rpc = createBirpc<BobFunctions>(
  Alice,
  {
    post: data => channel.port2.postMessage(data),
    on: fn => channel.port2.on('message', fn),
  },
)

await rpc.hey('Alice') // Hey Alice, I am Bob

One-to-multiple Communication

Refer to ./test/group.test.ts as an example.

Sponsors

License

MIT License © 2021 Anthony Fu

版本列表
4.0.0 2025-12-13
3.0.0 2025-12-03
2.9.0 2025-12-03
2.8.0 2025-11-09
2.7.0 2025-11-04
2.6.1 2025-09-23
2.6.0 2025-09-23
2.5.0 2025-07-14
2.4.0 2025-06-14
2.3.0 2025-03-25
2.2.0 2025-02-04
2.1.0 2025-02-04
2.0.19 2025-01-09
0.2.19 2024-10-08
0.2.18 2024-10-08
0.2.17 2024-02-21
0.2.16 2024-02-19
0.2.15 2024-01-26
0.2.14 2023-09-04
0.2.13 2023-08-21
0.2.12 2023-05-29
0.2.11 2023-04-06
0.2.10 2023-03-16
0.2.9 2023-03-16
0.2.8 2023-03-15
0.2.7 2023-03-13
0.2.6 2023-03-10
0.2.5 2023-02-27
0.2.4 2023-02-18
0.2.3 2022-05-16
0.2.2 2022-03-26
0.2.1 2022-03-26
0.2.0 2022-03-26
0.1.1 2022-03-26
0.1.0 2022-01-10
0.0.2 2021-12-26
0.0.1 2021-12-26
0.0.0 2021-12-26