Setup
Available from 1.7.0-rc
Arkos WebSockets are built directly on top of socket.io. If you already know socket.io, most of what follows is familiar — Arkos adds structure (validation, auth, dedup, rate limiting) around it, it doesn't replace it.
Creating a Gateway
import { ArkosGateway } from "arkos/websockets";
const gateway = ArkosGateway({
name: "/",
authentication: true,
});config.name becomes the Socket.io namespace. It defaults to "/" if omitted.
Registering it
import arkos from "arkos";
import { Server } from "socket.io";
import http from "node:http";
import gateway from "@/src/gateway";
const app = arkos()
await app.listen()
const server = http.createServer(app)
const io = new Server(httpServer);
gateway.register(io);
app.listen(server)register(io, options?) can only be called once per io instance — call it on your root Gateway and compose the rest with .use() (see below). Calling it twice throws.
gateway.register(io, {
store: myRedisStore, // optional — defaults to an in-memory store
});The store option backs both rate limiting and deduplication. See Stores and Scaling if you're running more than one instance.
Attaching connection middleware or nesting Gateways — .use()
.use() accepts either a raw Socket.io connection middleware, or another Gateway to nest under this one:
gateway.use((socket, next) => {
console.log("incoming connection", socket.id);
next();
});
// nested gateway — inherits this gateway's name as a namespace prefix,
// plus its authentication and rateLimit config
gateway.use(adminGateway);A nested Gateway's namespace becomes ${parent.name}/${child.name}. It inherits the parent's authentication and rateLimit unless it sets its own, and it inherits all of the parent's lifecycle hooks. It does not automatically inherit the parent's .pipe() middlewares — those are scoped to the Gateway that registered them.
Attaching an event handler — .on()
gateway.on({ event: "send_message" }, (socket, data) => {
socket.to(data.room).emit("receive_message", data);
});This is the shallow version — .on() takes a full event config (validation, authorization, rateLimit, ack, dedup, maxAge, disabled). The full breakdown, including how it interacts with .pipe(), is in Handling Events.
Minimal end-to-end example
import { ArkosGateway } from "arkos/websockets";
const gateway = ArkosGateway({ name: "/" });
gateway.on({ event: "send_message" }, (socket, data) => {
socket.to(data.room).emit("receive_message", data);
});
export default gateway;import { Server } from "socket.io";
import http from "http";
import app from "@/src/app";
import gateway from "@/src/gateway";
await app.build();
const server = http.createServer(app);
const io = new Server(server);
gateway.register(io);
app.listen(server);Next: Handling Events for the full .on() config, or Authentication if your Gateway needs socket.currentUser.