SDK ReferenceCore
Quick Reference
Cheat sheet for Erebus SDK APIs
Quick Reference
Quick reference for common Erebus SDK operations.
Setup & Connection
import { ErebusClient, ErebusClientState } from "@erebus-sh/sdk/client";
// Create client
const client = ErebusClient.createClient({
client: ErebusClientState.PubSub,
authBaseUrl: "https://your-auth.com",
wsBaseUrl: "wss://gateway.erebus.sh" // optional
});
// Connect
client.joinChannel("my-channel");
await client.connect();
// Disconnect
client.close();
Real-Time Messaging
Subscribe
await client.subscribe("topic", (msg) => {
console.log(msg.payload);
});
Publish
// Without ack
await client.publish("topic", "Hello!");
// With ack
await client.publishWithAck(
"topic",
"Hello!",
(ack) => console.log(ack.success ? "Success" : `Failed: ${ack.error?.message}`),
3000 // timeout
);
Unsubscribe
client.unsubscribe("topic");
Advanced Subscribe/Unsubscribe
// Subscribe with ACK and options
client.subscribeWithCallback(
"topic",
(msg) => console.log(msg.payload),
(response) => console.log("Subscribed:", response.success),
10000,
{ streamOldMessages: true }
);
// Unsubscribe with ACK
client.unsubscribeWithCallback(
"topic",
(response) => console.log("Unsubscribed:", response.success)
);
Message History
Get Latest Messages
const history = await client.getHistory("topic");
// Returns 50 newest messages by default
Pagination
const page1 = await client.getHistory("topic", {
limit: 20,
direction: "backward"
});
const page2 = await client.getHistory("topic", {
cursor: page1.nextCursor,
limit: 20,
direction: "backward"
});
Iterator
const getNext = client.createHistoryIterator("topic", { limit: 50 });
const batch1 = await getNext(); // { items: [...], hasMore: true }
const batch2 = await getNext(); // { items: [...], hasMore: false }
const done = await getNext(); // null
All History
let cursor = null;
const all = [];
do {
const page = await client.getHistory("topic", {
cursor,
limit: 1000
});
all.push(...page.items);
cursor = page.nextCursor;
} while (cursor);
Presence Tracking
Subscribe to Presence
await client.onPresence("topic", (presence) => {
console.log(presence.clientId, presence.status);
// status: "online" | "offline"
});
Unsubscribe
client.offPresence("topic", handler);
client.clearPresenceHandlers("topic"); // all handlers
Typed Schema Facade
Setup
import { ErebusPubSubSchemas } from "@erebus-sh/sdk/client";
import { z } from "zod";
const schemas = {
chat: z.object({
text: z.string(),
username: z.string(),
}),
};
const typed = new ErebusPubSubSchemas(client, schemas);
Publish (Typed)
typed.publish("chat", "room-1", {
text: "Hello!",
username: "Alice"
});
Subscribe (Typed)
await typed.subscribe("chat", "room-1", (msg) => {
console.log(msg.payload.text); // ✅ string
console.log(msg.payload.username); // ✅ string
});
History (Typed)
const history = await typed.getHistory("chat", "room-1");
history.items.forEach(msg => {
console.log(msg.payload.text); // ✅ validated & typed
});
Connection State
// Connection state checks
client.isConnected // boolean - WebSocket connected
client.isReadable // boolean - Can receive messages
client.isWritable // boolean - Can send messages
// Connection management
await client.connect(10000); // with timeout
client.close(); // graceful shutdown
// Monitor connection state
setInterval(() => {
if (!client.isConnected) {
console.log("Connection lost - SDK will reconnect automatically");
}
}, 5000);
Message Format
interface MessageBody {
id: string; // Unique message ID
topic: string; // Topic name
senderId: string; // Sender's client ID
seq: string; // Sequence (ULID)
sentAt: Date; // Timestamp
payload: string; // Message content
clientMsgId?: string; // Optional correlation ID
}
Common Patterns
Reconnect Logic
async function connectWithRetry(maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
await client.connect();
return;
} catch (error) {
await new Promise(r => setTimeout(r, 1000 * (i + 1)));
}
}
throw new Error("Failed to connect");
}
Catch-Up After Disconnect
const lastSeq = localStorage.getItem("lastSeq");
const missed = await client.getHistory("topic", {
cursor: lastSeq || undefined,
direction: "forward"
});
missed.items.forEach(msg => process(msg));
await client.subscribe("topic", (msg) => {
process(msg);
localStorage.setItem("lastSeq", msg.seq);
});
Load More Button
let cursor = null;
async function loadMore() {
const history = await client.getHistory("topic", {
cursor,
limit: 20
});
history.items.forEach(msg => appendToUI(msg));
cursor = history.nextCursor;
if (!cursor) {
hideLoadMoreButton();
}
}
Error Handling
try {
await client.connect();
} catch (error) {
if (error.message.includes("Channel must be set")) {
// Call joinChannel() first
} else if (error.message.includes("timeout")) {
// Connection timeout
}
}
Limits & Constraints
Item | Limit |
---|---|
Message retention | 3 days |
Messages per topic | 100 (buffered) |
History page size | 1-1000 messages |
Default page size | 50 messages |
Connection timeout | 30 seconds (default) |
Publish ack timeout | 3 seconds (default) |