SDK
SDK Overview
Client SDK for browser and Node.js — subscribe to topics, manage documents, and send messages.
The Realtime Platform SDK (@smarterservices/realtime) provides a unified client for all three platform services: domain subscriptions, sync documents, and socket messaging.
Installation
npm install @smarterservices/realtimeQuick Start
import { RealtimeClient } from '@smarterservices/realtime';
const realtime = new RealtimeClient({
url: 'http://localhost:3000',
token: 'your-jwt-token',
});
// Subscribe to a domain topic
const subId = realtime.subscribe({ topic: 'session.status' });
// Listen for events
realtime.on('event', (event) => {
console.log('Received:', event.topic, event.payload);
});
// Topic-specific listener
realtime.on('event:session.status', (event) => {
console.log('Session update:', event.payload);
});Constructor
new RealtimeClient(options: RealtimeClientOptions)RealtimeClientOptions
| Option | Type | Required | Default | Description |
|---|---|---|---|---|
url | string | Yes | — | Backend API base URL (e.g. "http://localhost:3000") |
token | string | Yes | — | JWT authentication token used for the WebSocket handshake and API requests |
autoConnect | boolean | No | true | If true, the client connects immediately on construction. Set to false to connect manually via connect() |
reconnection | boolean | No | true | Enable automatic reconnection on disconnect |
reconnectionAttempts | number | No | 10 | Maximum number of reconnection attempts before giving up |
reconnectionDelay | number | No | 1000 | Base delay in milliseconds between reconnection attempts |
const realtime = new RealtimeClient({
url: 'http://localhost:3000',
token: 'your-jwt-token',
autoConnect: false, // Don't connect until we call connect()
reconnection: true,
reconnectionAttempts: 20,
reconnectionDelay: 2000,
});
realtime.connect(); // Connect manuallyService Accessors
The client exposes two sub-clients as read-only properties:
| Property | Type | Description |
|---|---|---|
realtime.sync | SyncClient | Document CRUD with revision tracking — see Sync Client |
realtime.socketClient | SocketClient | Channel messaging and direct messages — see Socket Client |
Methods
connect()
Open the WebSocket connection. Called automatically unless autoConnect is false.
connect(): voidReturns: void — sets the connection state to 'connecting'.
realtime.connect();disconnect()
Close the WebSocket connection. Does not clear subscriptions — they are re-established on reconnect.
disconnect(): voidReturns: void — sets the connection state to 'disconnected'.
realtime.disconnect();subscribe(options)
Subscribe to a domain topic. Events matching the topic (and optional filter) are delivered to your event listeners. Subscriptions are automatically re-established after reconnection.
subscribe(options: SubscribeOptions): string| Parameter | Type | Required | Description |
|---|---|---|---|
options | SubscribeOptions | Yes | Subscription configuration object (see below) |
SubscribeOptions:
| Field | Type | Required | Description |
|---|---|---|---|
topic | string | Yes | Domain topic to subscribe to (e.g. "session.status", "order.updated") |
filter | SubscriptionFilter | No | Key-value filter — only events whose payload matches the filter are delivered. Supports equality and in operators |
Returns: string — a unique subscription ID (e.g. "sub_1") used to unsubscribe later.
// Simple subscription
const subId = realtime.subscribe({ topic: 'session.status' });
// With a filter — only receive events where campusId = 12
const filtered = realtime.subscribe({
topic: 'session.status',
filter: { campusId: 12 },
});unsubscribe(subscriptionId)
Remove a subscription by its ID. The server stops delivering events for this subscription.
unsubscribe(subscriptionId: string): void| Parameter | Type | Required | Description |
|---|---|---|---|
subscriptionId | string | Yes | The subscription ID returned by subscribe() |
Returns: void
realtime.unsubscribe('sub_1');on(event, handler)
Register an event listener.
on(event: string, handler: EventHandler): void| Parameter | Type | Required | Description |
|---|---|---|---|
event | string | Yes | Event name to listen for (see event names below) |
handler | EventHandler | Yes | Callback function (data: unknown) => void |
Event Names:
| Event | Payload | Description |
|---|---|---|
'event' | RealtimeEvent | Fires for every event from any subscribed topic |
'event:<topic>' | RealtimeEvent | Fires only for events matching the specific topic (e.g. 'event:session.status') |
'connection' | { state: ConnectionState, reason?: string } | Fires on connection state changes |
'error' | unknown | Fires on connection or protocol errors |
realtime.on('event:session.status', (event) => {
console.log(event.payload);
});
realtime.on('connection', ({ state }) => {
console.log('State:', state); // 'connecting' | 'connected' | 'disconnected' | 'reconnecting'
});
realtime.on('error', (err) => {
console.error('Error:', err);
});off(event, handler)
Remove a previously registered event listener.
off(event: string, handler: EventHandler): void| Parameter | Type | Required | Description |
|---|---|---|---|
event | string | Yes | Event name to stop listening for |
handler | EventHandler | Yes | The exact same function reference passed to on() |
Returns: void
const handler = (event) => console.log(event);
realtime.on('event:session.status', handler);
// Later...
realtime.off('event:session.status', handler);destroy()
Disconnect, clear all subscriptions, and remove all event listeners. Call this when you're done with the client to release resources.
destroy(): voidReturns: void
realtime.destroy();Read-Only Properties
| Property | Type | Description |
|---|---|---|
realtime.state | ConnectionState | Current connection state: 'disconnected', 'connecting', 'connected', or 'reconnecting' |
realtime.connected | boolean | true if the connection state is 'connected' |
if (realtime.connected) {
console.log('We are live');
}
console.log('Current state:', realtime.state);Event Envelope: RealtimeEvent
All events received by the client follow the RealtimeEvent envelope:
interface RealtimeEvent {
id: string; // Unique event ID
topic: string; // Domain topic (e.g. "session.status")
source: 'database' | 'sync' | 'socket'; // Which service produced the event
type: string; // Event type (e.g. "database.update")
payload: Record<string, unknown>; // Event data
metadata: {
timestamp: number; // Unix timestamp (ms)
table?: string; // Source table (database events)
operation?: 'insert' | 'update' | 'delete'; // DB operation type
revision?: number; // Document revision (sync events)
};
}Server-Side Utilities
The SDK also includes utilities for server-side use:
| Export | Description |
|---|---|
WebhookReceiver | Verify and parse incoming webhook deliveries with HMAC-SHA256 signature validation and replay protection — see Webhook Receiver |
verifyWebhook() | Standalone function for one-off webhook verification |
WebhookVerificationError | Typed error thrown when webhook verification fails |
import { WebhookReceiver } from '@smarterservices/realtime';
const receiver = new WebhookReceiver('whsec_your_secret');
const { event } = receiver.verify(rawBody, headers);TypeScript Support
The SDK is written in TypeScript and ships with full type definitions. All public APIs are typed, including event payloads and options.
import type {
RealtimeClientOptions,
SubscribeOptions,
ConnectionState,
WebhookReceiverOptions,
WebhookEvent,
} from '@smarterservices/realtime';
import type {
RealtimeEvent,
SubscriptionFilter,
} from '@realtime/shared-types';