PartyServer for Cloudflare Durable Objects

0.4.1 · active · verified Tue Apr 21

PartyServer is a TypeScript library for building real-time applications on Cloudflare Durable Objects, inspired by PartyKit. It extends Durable Objects with features like room-based routing, lifecycle hooks (`onConnect`, `onMessage`, `onClose`), a unified API for managing hibernated and non-hibernated Durable Objects, and easy broadcasting. Key differentiators from PartyKit include decoupling the URL from the server name, omitting built-in bindings for other Cloudflare services (encouraging `wrangler`'s native support), and requiring manual Durable Object bindings and migrations in `wrangler.jsonc`. The current stable version is 0.4.1, with frequent patch and minor releases, indicating active development. It is primarily designed for the Cloudflare Workers environment and leverages WebSockets for real-time communication.

Common errors

Warnings

Install

Imports

Quickstart

Demonstrates a basic PartyServer setup with a Durable Object and its lifecycle hooks, along with the necessary `wrangler.jsonc` configuration and a client-side `PartySocket` example.

import { routePartykitRequest, Server } from "partyserver";
import { PartySocket } from "partysocket";

interface Env {
  MyServer: DurableObjectNamespace;
}

// Define your Server logic
export class MyServer extends Server {
  onConnect(connection: WebSocket, context: any) {
    console.log(`Connected ${connection.id} to server ${this.name}`);
  }

  onMessage(connection: WebSocket, message: string | ArrayBuffer) {
    console.log(`Message from ${connection.id}:`, message);
    // Broadcast the message to all other connections in the room
    this.broadcast(message, [connection.id]);
  }

  onClose(connection: WebSocket, code: number, reason: string, wasClean: boolean) {
    console.log(`Connection ${connection.id} closed. Clean: ${wasClean}`);
  }
}

// Worker entry point to route requests to Durable Objects
export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    return (
      (await routePartykitRequest(request, env)) ||
      new Response("Not Found", { status: 404 })
    );
  }
} satisfies ExportedHandler<Env>;

// === Minimal wrangler.jsonc configuration ===
/*
{
  "name": "my-partyserver-app",
  "main": "index.ts",
  "durable_objects": {
    "bindings": [
      {
        "name": "MyServer",
        "class_name": "MyServer"
      }
    ]
  },
  "migrations": [
    {
      "tag": "v1",
      "new_sqlite_classes": ["MyServer"]
    }
  ]
}
*/

// === Client-side connection example (requires 'partysocket') ===
/*
const socket = new PartySocket({
  host: "https://my-partyserver-app.threepointone.workers.dev",
  party: "my-server", // 'my-server' corresponds to the kebab-cased Durable Object class name 'MyServer'
  room: "my-room",
  onOpen: () => console.log("Client connected!"),
  onMessage: (event) => console.log("Client received message:", event.data),
  onClose: () => console.log("Client disconnected"),
  onError: (event) => console.error("Client error:", event)
});

// To send a message from the client
// socket.send("Hello from client!");
*/

view raw JSON →