@prsm/keepalive-ws
TypeScript icon, indicating that this package has built-in type declarations

1.0.3 • Public • Published

keepalive-ws

NPM version

A command server and client for simplified WebSocket communication, with built-in ping and latency messaging. Provides reliable, Promise-based communication with automatic reconnection and command queueing.

For a TCP-based, node-only solution with a similar API, see duplex.

Features

  • Promise-based API - All operations return Promises for easy async/await usage
  • Command queueing - Commands are automatically queued when offline
  • Reliable connections - Robust error handling and reconnection
  • Bidirectional communication - Full-duplex WebSocket communication
  • Latency monitoring - Built-in ping/pong and latency measurement
  • Room-based messaging - Group connections into rooms for targeted broadcasts
  • Lightweight - Minimal dependencies

Server

import { KeepAliveServer, WSContext } from "@prsm/keepalive-ws/server";

// Create a server instance
const server = new KeepAliveServer({
  port: 8080,
  pingInterval: 30000,
  latencyInterval: 5000,
  // Multi-instance room support (optional):
  // roomBackend: "redis",
  // redisOptions: { host: "localhost", port: 6379 }
});

// Register command handlers
server.registerCommand("echo", async (context) => {
  return `Echo: ${context.payload}`;
});

// Error handling
server.registerCommand("throws", async () => {
  throw new Error("Something went wrong");
});

// Room-based messaging
server.registerCommand("join-room", async (context) => {
  const { roomName } = context.payload;
  await server.addToRoom(roomName, context.connection);
  await server.broadcastRoom(roomName, "user-joined", {
    id: context.connection.id
  });
  return { success: true };
});

// Broadcasting to all clients
server.registerCommand("broadcast", async (context) => {
  server.broadcast("announcement", context.payload);
  return { sent: true };
});

Client

import { KeepAliveClient } from "@prsm/keepalive-ws/client";

// Create a client instance
const client = new KeepAliveClient("ws://localhost:8080", {
  pingTimeout: 30000,
  maxLatency: 2000,
  shouldReconnect: true,
  reconnectInterval: 2000,
  maxReconnectAttempts: Infinity,
});

// Connect to the server (returns a Promise)
await client.connect();

// Using Promise-based API
try {
  const response = await client.command("echo", "Hello world", 5000);
  console.log("Response:", response);
} catch (error) {
  console.error("Error:", error);
}

// Join a room
await client.command("join-room", { roomName: "lobby" });

// Listen for events
client.on("user-joined", (event) => {
  console.log("User joined:", event.detail.id);
});

// Monitor latency
client.on("latency", (event) => {
  console.log("Current latency:", event.detail.latency, "ms");
});

// Graceful shutdown
await client.close();

Extended Server API

Room Management

// Add a connection to a room (async)
await server.addToRoom("roomName", connection);

// Remove a connection from a room (async)
await server.removeFromRoom("roomName", connection);

// Get all connections in a room (async)
const roomConnections = await server.getRoom("roomName");

// Clear all connections from a room (async)
await server.clearRoom("roomName");

Broadcasting

// Broadcast to all connections
server.broadcast("eventName", payload);

// Broadcast to specific connections
server.broadcast("eventName", payload, connections);

// Broadcast to all connections except one
server.broadcastExclude(connection, "eventName", payload);

// Broadcast to all connections in a room
server.broadcastRoom("roomName", "eventName", payload);

// Broadcast to all connections in a room except one
server.broadcastRoomExclude("roomName", "eventName", payload, connection);

// Broadcast to all connections with the same IP
server.broadcastRemoteAddress(connection, "eventName", payload);

Middleware

// Global middleware for all commands
server.globalMiddlewares.push(async (context) => {
  // Validate authentication, etc.
  if (!isAuthenticated(context)) {
    throw new Error("Unauthorized");
  }
});

// Command-specific middleware
server.registerCommand(
  "protected-command",
  async (context) => {
    return "Protected data";
  },
  [
    async (context) => {
      // Command-specific validation
      if (!hasPermission(context)) {
        throw new Error("Forbidden");
      }
    }
  ]
);

Multi-Instance Room Support

To enable multi-instance room support (so rooms are shared across all server instances), configure the server with roomBackend: "redis" and provide redisOptions:

import { KeepAliveServer } from "@prsm/keepalive-ws/server";

const server = new KeepAliveServer({
  port: 8080,
  roomBackend: "redis",
  redisOptions: { host: "localhost", port: 6379 }
});

All room management methods become async and must be awaited.

Graceful Shutdown

// Close client connection
await client.close();

// Close server
server.close();

Readme

Keywords

none

Package Sidebar

Install

npm i @prsm/keepalive-ws

Weekly Downloads

42

Version

1.0.3

License

Apache-2.0

Unpacked Size

56 kB

Total Files

11

Last publish

Collaborators

  • nvmsy