Skip to content

WrpcType-safe WebSocket RPC

End-to-end type safety for real-time applications

Installation

bash
npm install @wrpc/core @wrpc/server @wrpc/client

Quick Start

1. Define your schema

typescript
import { defineWrpc, defineWrpcRoom } from "@wrpc/core";
import { z } from "zod";

const chat = defineWrpcRoom({
  state: z.object({
    messages: z.array(z.string()),
  }),
  initialState: {
    messages: [],
  },
  broadcasts: {
    message: {
      input: z.object({
        text: z.string(),
      }),
    },
  },
  events: {
    sendMessage: {
      input: z.object({
        text: z.string(),
      }),
    },
  },
});

export const wrpc = defineWrpc({
  rooms: { chat },
});

2. Create the server

typescript
import { createWrpcServer } from "@wrpc/server";
import { wrpc } from "./wrpc";

const wrpcServer = createWrpcServer(wrpc);

const chat = wrpcServer.rooms.chat({
  events: {
    sendMessage: ({ state, input, broadcast }) => {
      state.messages.push(input.text);
      broadcast("message", { text: input.text });
    },
  },
});

const handler = wrpcServer.handler({
  rooms: { chat },
});

3. Connect from the client

typescript
import { createWrpcClient } from "@wrpc/client";
import { wrpc } from "./wrpc";

const client = createWrpcClient(wrpc, {
  url: "ws://localhost:3000/wrpc",
});

const room = await client.rooms.chat.join("room-1");

room.on("message", ({ text }) => {
  console.log("New message:", text);
});

room.sendEvent("sendMessage", { text: "Hello!" });

Features

Room Inheritance

Extend rooms to inherit behaviors and add new functionality:

typescript
const baseRoom = defineWrpcRoom({
  state: z.object({ count: z.number() }),
  initialState: { count: 0 },
});

const extendedRoom = baseRoom.extend(() => ({
  events: {
    increment: {
      input: z.object({}),
    },
  },
}));

Nested Rooms

Create hierarchical room structures:

typescript
const card = defineWrpcRoom({
  abstract: true,
});

const game = defineWrpcRoom({
  rooms: { card },
});

Groups

Organize connections within rooms:

typescript
const room = wrpcServer.rooms.game({
  onJoin: ({ client, groups }) => {
    groups.addToGroup(client.id, "team-red");
  },
  events: {
    attack: ({ broadcast, groups }) => {
      const targets = groups.getGroupMembers("team-blue");
      broadcast("attacked", {}, { include: Array.from(targets) });
    },
  },
});

License

MIT