JavaScript SDK
Package: @fastpubsub-sdk/client
npm install @fastpubsub-sdk/client
Works in the browser and in Node.js over WebSocket. Browser WebTransport is implemented. Node.js without a WebTransport global is not supported.
Session, token, socket
import {
CreateAccessTokenBuilder,
TenantGrant,
open,
} from "@fastpubsub-sdk/client";
const session = open("globaltest");
const token = await session.createAccessToken(
process.env.FPS_MASTER_TOKEN,
new CreateAccessTokenBuilder()
.createdBy("backend")
.expiresAt("+1h")
.addTenantGrant(
new TenantGrant(["app"])
.allowPub(["public.#"])
.allowSub(["public.#"])
)
.build()
);
const client = await session.webSocket(token.token)
.pingIntervalSec(3)
.build();
const queue = await client.subscribe("app", "public.#");
await client.publish("app", "public.chat", "hello");
const message = await queue.recv();
Mint tokens on the backend. Browsers should receive only AT_....
createAccessToken and webSocket(...).build() resolve a nearby edge when needed. To pre-warm discovery:
const edge = await session.resolveEdge({ cache: "prefer" });
Cached edges live up to 24 hours. About once per hour the SDK re-checks RTT; if latency grew more than 50%, it rediscovers (typical after a VPN change).
Publish modes
publish() sends a broadcast (legacy v1 frame).
await client.publishWithOptions("app", "public.chat", data, {
delivery: "deliverOneLowLatency",
});
delivery | Behaviour |
|---|---|
"broadcast" | All matching subscribers |
"deliverOneLowLatency" | One overlay node with the lowest inter-node latency among nodes that have subscribers, then one local connection |
"deliverOneRandom" | One random overlay node with subscribers, then one local connection |
If there are no subscribers, deliver-one does nothing.
Link quality
GET /pingduring edge selection measures which edge to use.- After connect,
.pingIntervalSec(1 | 3 | 5)sends applicationPINGand readsPONG. Omit it to disable.
client.linkQuality(30); // { lastRttMs, medianRttMs }
The edge only answers PONG. It does not store your RTT.
Refresh and revoke
Backend only. Needs the master token.
import { accessTokenId } from "@fastpubsub-sdk/client";
await session.refreshAccessTokenFromAt(masterToken, token.token, "+23h");
await session.revokeAccessToken(masterToken, token.token);
Filters and WebTransport
Import a single filter when you want a smaller bundle:
import { CompressedFilter } from "@fastpubsub-sdk/client/filters/compressed";