Hosting on Node.js
@pluv/io
can be hosted on the Node.js runtime. You can define your handler and websocket server manually if you need more control. If you only need a basic server, you can use createPluvHandler to get started quicky.
Using with Node.js (manual)
Let's step through how we'd put together a real-time API for Node.js.
Install dependencies
# For the server
npm install @pluv/io @pluv/platform-node
# Server peer-dependencies
npm install ws zod
Create PluvIO instance
Define an io (websocket client) instance on the server codebase:
// backend/io.ts
import { createIO } from "@pluv/io";
import { platformNode } from "@pluv/platform-node";
export const io = createIO(platformNode());
export const ioServer = io.server();
Integrate PluvIO with ws
Integrate with ws on your Node.js server.
// backend/server.ts
import type { InferIORoom } from "@pluv/io";
import express from "express";
import Http from "http";
import WebSocket from "ws";
import { ioServer } from "./io";
const PORT = 3000;
const app = express();
const server = Http.createServer(app);
const wsServer = new WebSocket.Server({ server });
const parseRoomId = (url: string): string => {
/* get room from req.url */
};
const rooms = new Map<string, InferIORoom<typeof ioServer>>();
const getRoom = (roomId: string): InferIORoom<typeof ioServer> => {
const existing = rooms.get(roomId);
if (existing) return existing;
const room = ioServer.createRoom(roomId, {
onDelete: (event) => {
rooms.delete(event.room);
},
});
rooms.set(roomId, room);
return room;
};
wsServer.on("connection", async (ws, req) => {
const roomId = parseRoomId(req.url);
const room = getRoom(roomId);
// Only needed if you have configured authentication
const token = new URL(req.url).searchParams.get("token");
await room.register(
ws,
// Only needed if you have configured authentication
{ token },
);
});
server.listen(PORT, () => {
console.log(`Server is listening on port: ${port}`);
});
createPluvHandler
If you don't need to modify your websocket server or handler too particularly, @pluv/platform-node also provides a function createPluvHandler
to create a websocket server and handler more concisely.
import { createIO } from "@pluv/io";
import { createPluvHandler, platformNode } from "@pluv/platform-node";
import bodyParser from "body-parser";
import cors from "cors";
import express from "express";
import Http from "http";
import WS from "ws";
import { Database } from "./database";
const db = new Database(process.env.DATABASE_URL);
const io = createIO(
platformNode({
context: () => ({ db }),
})
);
const ioServer = io.server();
const app = express();
const server = Http.createServer(app);
const Pluv = createPluvHandler({
// Your PluvServer instance
io: ioServer,
// Optional: Specify the base path from which endpoints are defined
endpoint: "/api/pluv", // defaults to "/api/pluv"
// Your Http.Server instance
server,
// If your PluvIO instance defines authorization, add your authorization
// logic here. Return a user if authorized, return null or throw an error
// if not authorized.
async authorize({ req, room }) {
return {
id: "abc123",
name: "pluvrt",
};
},
});
// Create your WS.Server instance, which listens to "connection" events
const wsServer = Pluv.createWsServer();
// Alternatively, define your own websocket server
const wsServer = new WS.Server({ server });
wsServer.on("connection", async (ws, req) => {
const { matched } = await Pluv.wsHandler(ws, req);
if (matched) return;
// didn't match with the Pluv handler, add your own logic
// ...
});
app.use(bodyParser.json());
app.use(cors({ origin: "*" }));
app.use(Pluv.handler);
server.listen(3000);