pluv.io is in preview! Please wait for a v1.0.0 stable release before using this in production.

API Reference

createIO

Returns a PluvIO instance.

Creates a server-side PluvIO client that can be used to create event procedures, routers and servers. Below will show an example configuration for createIO. To learn more about createIO, read Authorization, Cloudflare Workers, Node.js and PubSub.

import { yjs } from "@pluv/crdt-yjs";
import { createIO } from "@pluv/io";
import { platformNode } from "@pluv/platform-node";
import { z } from "zod";
import { Database } from "./db";

const io = createIO({
    // Optional: if provided, defines authorization for rooms created by io
    authorize: {
        // If required is false, users can authenticate for a room to
        // attach an identity to their presence. Otherwise they will be
        // anonymous.
        required: true,
        // The secret for generating your JWT
        secret: process.env.PLUV_AUTH_SECRET!,
        // The shape of your user object. `id` must always be required.
        user: z.object({
            id: z.string(),
            // Here is an additional field we wish to add.
            name: z.string(),
        }),
    },
    // Optional: if provided, this context will be made available in event
    // handlers and procedures
    context: () => ({
        db: new Database(process.env.DATABASE_URL),
    }),
    // Optional. Specify to use Yjs CRDT for storage.
    // This is required only if/when you wish to use storage features.
    crdt: yjs,
    // Enable @pluv/io for Node.js
    platform: platformNode(),
});

PluvIO

This is the client returned by createIO.

createToken

Returns Promise<string>.

Creates a JWT for a user trying to connect to a room. This should be called within a custom authentication endpoint you define. See Authorization for more information.

const token = await io.createToken({
    // If using @platform/node
    req: req as IncomingMessage,

    // If using @platform/cloudflare
    // This is the env from the Cloudflare worker handler's fetch function
    env: env as Env,
    request: request as Request,

    // ...
    room: "my-example-room",
    user: {
        id: "abc123",
        name: "leedavidcs",
    },
});

procedure

Creates a new type-safe event procedure to be broadcasted from PluvClient. See Define Events for more information.

import { createIO } from "@pluv/io";
import { platformNode } from "@pluv/platform-node";
import { z } from "zod";

const io = createIO({ platform: platformNode() });

const sendMessage = io.procedure
    .input(z.object({ message: z.string() }))
    .broadcast(({ message }) => ({ receiveMessage: { message } }));

const doubleValue = io.procedure
    .input(z.object({ value: z.number() }))
    .broadcast(({ value }) => ({ receiveValue: { value: value * 2 } }));

const wave = io.procedure
    .broadcast(() => ({ receiveMessage: { message: "Hello world!" } }));

router

Creates a new type-safe event procedure router to attach events and connect to a PluvServer.

import { createIO } from "@pluv/io";
import { platformNode } from "@pluv/platform-node";
import { z } from "zod";

const io = createIO({ platform: platformNode() });

const sendMessage = io.procedure
    .input(z.object({ message: z.string() }))
    .broadcast(({ message }) => ({ receiveMessage: { message } }));

const doubleValue = io.procedure
    .input(z.object({ value: z.number() }))
    .broadcast(({ value }) => ({ receiveValue: { value: value * 2 } }));

const wave = io.procedure
    .broadcast(() => ({ receiveMessage: { message: "Hello world!" } }));

const router = io.router({
    sendMessage,
    doubleValue,
    wave,
});

server

Creates a PluvServer that will create rooms to register your websockets to.

import { createIO } from "@pluv/io";
import { platformNode } from "@pluv/platform-node";
import { z } from "zod";

const io = createIO({ platform: platformNode() });
const router = io.router({ /* ... */ });

const server = io.server({
    // Optional. Only needed to load persisted storage for rooms.
    // Load storage for a newly created room.
    getInitialStorage: async ({ room }) => {
        const existingRoom = await db.room.findUnique({ where: { room } });

        return existingRoom?.encodedState ?? null;
    },
    // Optional. Only needed for persisting storage for rooms.
    // Before the room is destroyed, persist the state to a database to load
    // when the room is re-created.
    onRoomDeleted: async ({ encodedState, room }) => {
        await db.room.upsert({
            where: { room },
            create: { encodedState, room },
            update: { encodedState },
        });
    },
    // Optional. It is unnecessary to save the storage state in this listener.
    // If a room already exists, users will load the currently active storage
    // before the storage from initialStorage.
    onStorageUpdated: ({ encodedState, room }) => {
        console.log(room, encodedState);
    },
    // Optional. Only needed if specifying events
    router,
});

// Can also be created without a router, if events are unneeded
const server = io.server();

PluvServer

createRoom

Returns IORoom.

Creates a room with the specified id.

const room = server.createRoom("my-example-room");

IORoom

This is the room returned by PluvServer.createRoom. This is what websockets are registered to.

broadcast

Returns void.

Broadcasts an event to all connected websockets to the room.

// The below 2 statements are equivalent
room.broadcast("sendMessage", { message: "Hello world~!" });

room.broadcast.sendMessage({ message: "Hello world~!" });

id

Type of string.

This is the id of the room, when the room was created.

const roomId = room.id;

register

Returns Promise<void>.

Registers a websocket to the room. Accepts a secondary options parameter to pass-in a token for authorizing the room. Read Cloudflare Workers, Node.js and Authorization to learn more.

// const token: string = ...

room.register(webSocket, { token });