swarm-keydb

WebSocket Gateway

SwarmKeyDb can expose Redis-compatible commands over WebSockets so browser apps can subscribe to Pub/Sub and Streams without a TCP Redis client.

Configuration

JSON commands (RESP2 default)

Send frames as:

{"cmd":"SUBSCRIBE","args":["my-channel"]}

When no protocol upgrade is requested, responses are JSON:

RESP3 negotiation

WebSocket connections start in RESP2 mode. You can upgrade with either JSON-array commands or raw RESP frames:

["HELLO","3"]

Successful HELLO 3 returns a JSON map (object), for example:

{"server":"swarmkeydb","version":"7.0.0","proto":3,"id":1,"mode":"standalone","role":"master","modules":[]}

HELLO 2 downgrades back to RESP2 shapes, and RESET restores factory state (RESP2, no tracking/subscriptions/transaction/auth context).

CLIENT TRACKING push invalidation

Enable server-assisted caching over WebSocket:

["CLIENT","TRACKING","ON"]

After another connection mutates a tracked key, the same socket receives:

{"type":"push","data":["invalidate",["my-key"]]}

Disable with:

["CLIENT","TRACKING","OFF"]

Browser example

<script>
const ws = new WebSocket("ws://localhost:8765/");
ws.onmessage = (event) => {
  const msg = JSON.parse(event.data);
  if (msg.type === "push") {
    console.log("invalidation:", msg.data);
    return;
  }
  console.log("reply:", msg);
};
ws.onopen = () => {
  ws.send(JSON.stringify(["HELLO", "3"]));
  ws.send(JSON.stringify(["CLIENT", "TRACKING", "ON"]));
  ws.send(JSON.stringify(["GET", "profile:alice"]));
};
</script>

Node.js example

import WebSocket from "ws";
const ws = new WebSocket("ws://localhost:8765/");
ws.on("open", () => ws.send(JSON.stringify({ cmd: "PING" })));
ws.on("message", (data) => console.log(data.toString()));

React hook (useSwarmKeyDb) example

import { useEffect, useMemo, useState } from "react";

export function useSwarmKeyDb(url: string, channel: string) {
  const [messages, setMessages] = useState<string[]>([]);
  const ws = useMemo(() => new WebSocket(url), [url]);

  useEffect(() => {
    ws.onopen = () => ws.send(JSON.stringify({ cmd: "SUBSCRIBE", args: [channel] }));
    ws.onmessage = (event) => setMessages((prev) => [...prev, event.data.toString()]);
    return () => ws.close();
  }, [ws, channel]);

  return messages;
}