DocumentationCore Protocol

Migrating from Socket.io

PaindaProtocol (PP) was heavily inspired by Socket.io and purposefully adopts an identical API surface for its core features. This makes migrating the majority of your business logic trivial.

1. Installation

- npm uninstall socket.io socket.io-client
+ npm install @painda/core @painda/client

2. Server Setup

Socket.io creates its own HTTP server automatically if you pass a port. PaindaProtocol does the same. If you previously wrapped an Express server, you can do this identically via attachTo.

Socket.io

import { Server } from "socket.io";
import { createServer } from "http";

const httpServer = createServer(app);
const io = new Server(httpServer, {
  cors: { origin: "*" }
});

PaindaProtocol

import { PPServer } from "@painda/core";
import { createServer } from "http";

const httpServer = createServer(app);
const io = PPServer.attachTo(httpServer, {
  allowedOrigins: ["*"] 
});

3. Client Setup & Auth

In Socket.io you pass auth: { token } which gets evaluated once. PaindaProtocol uses a dynamic getToken callback so that your token is freshly gathered on every subsequent reconnect. This forces the client to automatically fetch a new token if the JWT expired while disconnected.

Socket.io

import { io } from "socket.io-client";

const socket = io("ws://localhost:3000", {
  auth: {
    token: "my-jwt-token"
  }
});

PaindaProtocol

import { PPClient } from "@painda/client";

const socket = new PPClient({
  url: "ws://localhost:3000",
  // Called initially and on EVERY reconnect
  getToken: async () => localStorage.getItem("token")
});

4. Namespaces & Broadcasts (Zero Changes)

The massive upside of migrating to PaindaProtocol is that almost all your socket interaction logic remains untouched.

// Works identically in both libraries:
io.on("connection", (socket) => {
  
  // Join rooms
  socket.join("lobby-1");
  
  // Broadcast to room
  io.to("lobby-1").emit("chat", "Hello Room!");
  
  // Broadcast to all except sender
  socket.broadcast.emit("player_join", socket.id);
  
  // Event listeners
  socket.on("action", (data) => {
     console.log(data);
  });
  
  // Disconnect
  socket.on("disconnect", () => {
    console.log("Left!");
  });
});

5. Upgrade to Delta-State Sync

Once migrated, you can instantly benefit from the Delta Engine without altering your data format. Instead of broadcasting full states:

import { patchImmutable } from "@painda/gaming";

// Server
io.to(room).emitDelta("update", oldState, newState);

// React Client
client.on("update", (delta) => {
  setGameState(prev => patchImmutable(prev, delta));
});