Skip to main content
Version: 0.3.36

Connection & Authentication

Connect, authenticate, and manage the client lifecycle.

RaisinClient

Constructor

new RaisinClient(url: string, options?: ClientOptions)
ParameterTypeDescription
urlstringWebSocket URL: a bare host (ws://localhost:8080, combined with options.repository) or a full path (ws://localhost:8080/ws/myrepo, wss://host/sys/{tenant}/{repo})
optionsClientOptionsOptional configuration
interface ClientOptions {
repository?: string;
tenantId?: string;
defaultBranch?: string;
requestTimeout?: number;
connection?: ConnectionOptions;
tokenStorage?: TokenStorage;
logLevel?: LogLevel;
httpBaseUrl?: string;
}
OptionDefaultDescription
repositoryextracted from the URLWith a bare host URL the client builds the /ws/{repository} route. With a path URL it overrides the repository extracted from it (used for repository-scoped auth).
tenantIdfrom the URL, else 'default'Rarely needed. The server resolves the tenant for /ws/{repo} connections; use the /sys/{tenant}/{repo} URL form to target a tenant explicitly.
defaultBranch'main'Branch used for all operations unless overridden with onBranch().
requestTimeout30000Per-request timeout in milliseconds; exceeding it rejects with RaisinTimeoutError.
connectionautoReconnect (default true), reconnectOptions, heartbeatInterval (default 30000, 0 disables), heartbeatTimeout (default 5000), protocols, headers (upgrade headers, Node.js only).
tokenStorageMemoryTokenStorageWhere tokens are persisted (see Token Storage).
logLevelLogLevel.InfoSilent, Error, Warn, Info, Debug.
httpBaseUrlderived from the WS URLHTTP base URL used for identity auth, uploads and flows.

connect()

await client.connect(): Promise<void>

disconnect()

client.disconnect(): void

database()

client.database(name: string): Database

The Database carries the repository and exposes:

MemberReturnsReference
workspace(name)WorkspaceClient with nodes(), events(), onBranch(), atRevision(), transaction(), uploadsNode Operations
executeSql(sql, params?), sql`...`SqlResult { columns, rows, row_count }SQL
onBranch(branch), atRevision(revision)a Database scoped to that branch or revisionBranches
branches(), nodeTypes(), archetypes(), elementTypes(), tags(), scheduler()management APIs over WebSocketSchema Management
conversationsConversationManagerChat & Conversations
flowFlowClient (HTTP with SSE streaming)Flows
flows()FlowsApi (WebSocket)Flows
functions()FunctionsApiFunctions
inboxInboxApiFlows

Accessors are created lazily and cached with the correct base URL, repository and auth manager.

const db = client.database('myapp');
const convo = await db.conversations.create({ participant: '/agents/support' });
const result = await db.flow.runAndWait('/flows/process-order', { orderId: '123' });
const { tasks } = await db.inbox.listTasks({ status: 'pending' });

Authentication

authenticate()

await client.authenticate(credentials: Credentials): Promise<void>

Credentials is one of:

{ username: string; password: string }   // admin user
{ type: 'jwt'; token: string } // an existing JWT or API key

loginWithEmail()

await client.loginWithEmail(email: string, password: string, repository: string): Promise<IdentityUser>

registerWithEmail()

await client.registerWithEmail(email: string, password: string, repository: string, displayName?: string): Promise<IdentityUser>

initSession()

Restore a session from a stored token. Returns the user, or null when there is no valid token.

await client.initSession(repository: string): Promise<IdentityUser | null>

refreshToken()

await client.refreshToken(): Promise<IdentityUser | null>

logout()

await client.logout(options?: { disconnect?: boolean; reconnect?: boolean }): Promise<void>

Session and user info

client.isAuthenticated(): boolean
client.isReady(): boolean // connected and authenticated
client.getCurrentUser(): CurrentUser | null // { userId, roles?, anonymous, node? }
client.getCurrentUserId(): string | null
client.getCurrentUserPath(): string | null
client.getSession(): { user: IdentityUser | null; accessToken: string | null } | null
client.getUser(): IdentityUser | null // getSession()?.user
client.getStoredUser(): IdentityUser | null
client.hasStoredToken(): boolean
await client.fetchUserNode(repository): Promise<UserNode | null>

After authenticate() with admin credentials, getCurrentUser() returns { userId: 'admin', anonymous: false }; the identity methods fill in email, roles and home.


State listeners

Every listener returns an unsubscribe function.

onAuthStateChange()

client.onAuthStateChange((change: AuthStateChange) => void): () => void

interface AuthStateChange {
event: 'SIGNED_IN' | 'SIGNED_OUT' | 'TOKEN_REFRESHED' | 'SESSION_EXPIRED' | 'USER_UPDATED';
session: { user: IdentityUser | null; accessToken: string | null };
}

Fires for identity flows (loginWithEmail, registerWithEmail, initSession, refreshToken, logout); admin authenticate() does not emit it.

onConnectionStateChange()

client.onConnectionStateChange((state: ConnectionState) => void): () => void
// 'disconnected' | 'connecting' | 'connected' | 'reconnecting' | 'closed'

onReadyStateChange()

client.onReadyStateChange((ready: boolean) => void): () => void

onReconnected()

Fires after the connection, authentication and subscription restore have all succeeded.

client.onReconnected(() => void): () => void

onUserChange()

Fires when the user's home node is updated.

client.onUserChange((event: UserChangeEvent) => void): () => void

The client is also an EventEmitter: client.on('subscription_restore_failed', handler) reports a subscription that could not be restored after a reconnect.


Connection info

client.isConnected(): boolean
client.getConnectionState(): ConnectionState
client.getBranch(): string
client.setBranch(branch: string): void
client.getTenantId(): string
client.httpBaseUrl: string

Reconnection and request queueing

The client reconnects with exponential backoff and re-authenticates with the stored token. Requests issued while reconnecting are queued and flushed afterwards, so short network interruptions do not surface as errors. The queue holds 100 requests; beyond that a request rejects immediately with Request queue is full.

Active subscriptions are restored with retries; a permanent failure emits subscription_restore_failed (see Realtime Subscriptions & Inbox).

ErrorThrown when
RaisinTimeoutErrorA request exceeds requestTimeout (carries timeoutMs)
RaisinAuthErrorAuthentication or token refresh fails (carries code, status)
RaisinConnectionErrorThe connection drops unrecoverably
RaisinAbortErrorA request was aborted through its AbortSignal

HTTP client (SSR)

For server-side rendering, or wherever WebSocket is unavailable:

const http = RaisinClient.forSSR('http://localhost:8080', options?: HttpClientOptions): RaisinHttpClient
// alias
const http = RaisinClient.createHttpClient('http://localhost:8080', options);

RaisinHttpClient shares authenticate(), database(), executeSql(), repository and workspace management, uploads and signAssetUrl() with the WebSocket client, and adds the identity-auth surface (auth(repo), setIdentityTokens(), clearIdentityTokens(), see Identity Authentication). Its workspace object is smaller: getNode(id), getNodeByPath(path), createNode(payload), updateNode(id, properties), deleteNode(id). Real-time events and the WebSocket flow API are not available; db.flow (HTTP) is.


Token storage

interface TokenStorage {
getAccessToken(): string | null;
setAccessToken(token: string): void;
getRefreshToken(): string | null;
setRefreshToken(token: string): void;
clear(): void;
}
ClassStorageUse case
MemoryTokenStorageIn memoryDefault; server-side
LocalStorageTokenStorage(prefix = 'raisindb')localStorageBrowser persistence across reloads

Types

interface IdentityUser {
id: string;
email: string;
displayName?: string;
avatarUrl?: string;
emailVerified?: boolean;
home?: string;
}