Connection Setup
The client automatically establishes a secure WebSocket connection:
<script type="module">
import createClient from './sdkmod.js';
// ============================================
// PATTERN 1: Full client object
// ============================================
const db = await createClient();
// Use methods with db. prefix
await db.set(['users', 'john'], { name: 'John', age: 30 });
const user = await db.get(['users', 'john']);
// ============================================
// PATTERN 2: Destructured methods (recommended)
// All examples below use this pattern
// ============================================
const { set, get, update, increment, remove, query,
getSub, querySub, getSubChanged, querySubChanged,
getFile, setFile, listFiles, removeFile, fileUrl,
callableFunction, reconnect, onConnectionChange,
login, logout, createUser, changePassword, magicLink } = await createClient();
console.log("Connected and ready to use NukeBase");
// Use methods directly without prefix
await set(['users', 'alice'], { name: 'Alice', age: 28 });
const userData = await get(['users', 'alice']);
// ============================================
// PATTERN 3: Attach to window (global access)
// Useful for multi-file apps or console debugging
// ============================================
const client = await createClient();
// Attach full client object
window.db = client;
// Optional: expose individual helpers directly
Object.assign(window, client);
// Now use from anywhere: window.db.get(...) or just get(...)
</script>
Important: The example above shows all three patterns for demonstration. In practice, choose ONE pattern for your application. Each pattern creates its own WebSocket connection, so using multiple would create multiple connections.
Key Features:
- Promise-based initialization:
createClient()resolves once connected, or with an offline client if the first attempt fails (it keeps trying) - Automatic Reconnection: Retries after about half a second, then backs off to 30 seconds, with a little randomness so every open tab doesn't reconnect at once
- Subscription Restoration: Restores all active subscriptions after reconnect, including ones made while offline
- Dead-connection detection: A heartbeat notices a connection that looks open but has stopped working (a phone switching networks) within about 15 seconds
- Tab and network recovery: Reconnects straight away when the tab becomes visible or the device gets its connection back
- Opens offline:
createClient()registers the service worker, whose page cache opens the app instantly from the last copy seen and opens it at all with no signal. Data still needs the socket —client.onlinesays whether it is there — unless the app opts in to offline mode, which answers reads from a local cache and queues writes to replay - Encapsulated State: Multiple client instances can coexist independently
Connecting elsewhere. createClient() with no argument derives the WebSocket URL from the current page (wss:// on HTTPS, ws:// otherwise), preserving the path and query string. Pass an explicit URL to connect to a different project: await createClient('wss://other-project.nukebase.com').
Options. A second argument (or a first, when there is no URL) takes { pageCache: false } to turn off the service worker's page cache for this app. It is on by default: createClient() registers /sw.js on every page. { offline: { enabled: true } } turns on offline mode for data — cached reads, cached first payloads for subscriptions, and a replayed queue for writes made offline. That one is off by default.
Requests never hang on a lost connection. A request made while disconnected resolves { status: "Offline" } at once, and requests still waiting when the connection drops resolve the same way. Offline means the SDK doesn't know whether the server received the request: a write may or may not have happened, so check with a read or a subscription once back online.
Requests time out after 30 seconds when the connection is up but the server doesn't answer. The promise then rejects with Request timeout: <action> <requestId>. Subscriptions are exempt — they have no single reply to wait for.
reconnect() and cookies. The admin context of a WebSocket is fixed at the moment the socket is upgraded, so a session established after connecting is invisible to the existing socket. login(), logout() and createUser() therefore call reconnect() for you on success. If you establish a session some other way — a magic-link redirect, a custom endpoint — call reconnect() yourself, or the socket keeps operating as the previous identity.
Connection State
client.online is true while the client is connected and hearing from the server. client.onConnectionChange(fn) calls fn(true) or fn(false) on every change, and once straight away with the current state. It returns a function that stops listening.
const client = await createClient();
client.onConnectionChange((online) => {
document.querySelector("#offline-banner").hidden = online;
document.querySelector("#book").disabled = !online;
});
document.querySelector("#book").onclick = async () => {
const r = await client.callableFunction("bookSlot", { time: "3pm" });
if (r.status === "Offline") showMessage("You need a connection to book");
};
Read client.online from the client, don't destructure it. const { online } = client copies the value once and never changes. onConnectionChange is fine to destructure.
online is for the screen, not a guarantee. The connection can drop between checking it and sending. The status the request resolves with (Success, Failed or Offline) is what actually happened.