Skip to content

Node.js SDK

The Node.js SDK provides programmatic control over the SyncRabbit engine for custom backends.

Installation

bash
npm install @syncrabbit/node

When to Use

  • You have a custom Node.js backend (Express, Fastify, Koa, etc.)
  • You need programmatic control over the engine lifecycle
  • You want to get the WebSocket URL dynamically for client connections

Basic Usage

ensureEngine

The simplest way to start the engine:

typescript
import { ensureEngine } from "@syncrabbit/node";

async function main() {
  const wsUrl = await ensureEngine({
    databaseUrl: process.env.DATABASE_URL,
  });

  console.log(`Clients can connect to: ${wsUrl}`);
  // ws://127.0.0.1:4500/ws
}

main();

With Express

typescript
import express from "express";
import { ensureEngine } from "@syncrabbit/node";

const app = express();

app.get("/api/syncrabbit-url", async (req, res) => {
  const wsUrl = await ensureEngine();
  res.json({ wsUrl });
});

app.listen(3000);

Advanced Usage

EngineManager

For more control over the engine lifecycle:

typescript
import { EngineManager } from "@syncrabbit/node";

const engine = new EngineManager({
  databaseUrl: process.env.DATABASE_URL,
  port: 4500,
  host: "127.0.0.1",
});

// Start the engine
const info = await engine.ensureRunning();
console.log(info.wsUrl); // ws://127.0.0.1:4500/ws
console.log(info.pid); // Process ID

// Later: shutdown gracefully
await engine.shutdown();

Singleton Pattern

Safe for hot-reload environments (like Next.js dev mode):

typescript
import { getOrCreateEngine } from "@syncrabbit/node";

// Returns existing instance or creates new one
const engine = getOrCreateEngine({
  databaseUrl: process.env.DATABASE_URL,
});

const info = await engine.ensureRunning();

Configuration Options

typescript
interface EngineOptions {
  databaseUrl?: string; // PostgreSQL connection string (defaults to DATABASE_URL env)
  port?: number; // WebSocket port (defaults to 4500)
  host?: string; // Bind address (defaults to "127.0.0.1")
  slotName?: string; // Replication slot name (defaults to "syncrabbit_slot")
  publicationName?: string; // Publication name (defaults to "syncrabbit_pub")
  debug?: boolean; // Enable debug logging
}

Return Types

typescript
interface EngineInfo {
  wsUrl: string; // WebSocket URL for client connections
  pid: number; // Engine process ID
}

Example: Full Backend Setup

typescript
import express from "express";
import { Pool } from "pg";
import { ensureEngine } from "@syncrabbit/node";

const app = express();
const pool = new Pool({ connectionString: process.env.DATABASE_URL });

// Start engine when server starts
let wsUrl: string;

app.get("/api/users", async (req, res) => {
  const result = await pool.query("SELECT * FROM users");
  res.json(result.rows);
});

app.post("/api/users", async (req, res) => {
  const { name, email } = req.body;
  const result = await pool.query(
    "INSERT INTO users (name, email) VALUES ($1, $2) RETURNING *",
    [name, email]
  );
  res.json(result.rows[0]);
});

// Endpoint to get WebSocket URL for frontend
app.get("/api/config", (req, res) => {
  res.json({ wsUrl });
});

async function start() {
  wsUrl = await ensureEngine({
    databaseUrl: process.env.DATABASE_URL,
  });

  app.listen(3000, () => {
    console.log("Server running on port 3000");
    console.log(`SyncRabbit WebSocket: ${wsUrl}`);
  });
}

start();

Released under the MIT License.