DocumentationCore Protocol

Message Types

PaindaProtocol simplifies realtime communication by standardizing how messages are sent and acknowledged. Under the hood, all messages follow a unified PPMessage interface.

The PPMessage Structure

Every message sent over PaindaProtocol is parsed into a simple object:

interface PPMessage<T = unknown> {
  type: string;    // The event name (e.g., "chat", "move", "join")
  payload: T;      // The actual data
}

1. Fire-and-Forget Events

The most common way to send data is a simple, one-way event. The server or client emits an event, and the other side listens for it. No confirmation is sent back.

// Client sends a fire-and-forget event
client.emit("playerMove", { x: 10, y: 20 });

// Server receives it
server.on("playerMove", (client, payload) => {
  // Update state
});

2. Request / Response (Acknowledgements)

If you need to know that the other side received and processed your message, you can use Acknowledgements (Acks). You pass a callback function as the last argument, and the receiver can call it to send a response back.

// Client sends a request expecting a response
client.send({ type: "login", payload: { token: "123" } }, (err, response) => {
  if (err) console.error("Login failed or timed out");
  else console.log("Login successful!", response);
});

// Server handles the request and responds
server.on("login", (client, payload, ack) => {
  const success = verify(payload.token);
  if (success) {
    ack(null, { userId: 1 }); // null = no error, followed by response payload
  } else {
    ack(new Error("Invalid token"));
  }
});

Internal Implementation

Acks are implemented by injecting an internal __ackId property into the message. When the receiver calls the ack() function, PaindaProtocol automatically creates a new message with the type __pp_ack and routes it back to the original sender's pending callback list.