JavaScript / TypeScript SDK
Zero-dependency ESM client for walkindb. Works in Node 18+, Bun, Deno, Cloudflare Workers, and modern browsers — anywhere globalThis.fetch exists.
npm install walkindb ·
npm: npmjs.com/package/walkindb ·
Current version: 0.1.0 ·
License: Apache-2.0
Install
npm install walkindb # or pnpm add walkindb # or bun add walkindb # or (Deno) deno add npm:walkindb
The package is ESM only (no CommonJS build), ships TypeScript types inline (index.d.ts), and has zero runtime dependencies. It uses globalThis.fetch, so any runtime that implements the standard Fetch API is supported:
- Node.js 18+
- Bun 1.0+
- Deno 1.35+
- Cloudflare Workers
- Modern browsers (Chrome 85+, Firefox 90+, Safari 14+)
- Any environment where you can inject a custom
fetchvia the constructor option
60-second example
import { Client } from "walkindb"; const db = new Client(); // First call provisions a new walk-in; Client captures the session token // and transparently reuses it on subsequent calls. await db.execute("CREATE TABLE notes(id INTEGER PRIMARY KEY, body TEXT)"); await db.execute("INSERT INTO notes(body) VALUES('hello')"); const result = await db.execute("SELECT * FROM notes"); console.log(result.columns); // ['id', 'body'] console.log(result.rows); // [[1, 'hello']] console.log(result.rowsAffected); // 0 on SELECT console.log(db.session); // 'wkn_AZ159u9PdmS97ks7FnSm...' console.log(db.expiresAt); // unix timestamp when the walk-in will be deleted
TypeScript
Types ship in the package; no @types/walkindb needed.
import { Client, WalkinDBError, type Result, type ClientOptions } from "walkindb"; const opts: ClientOptions = { baseUrl: "https://api.walkindb.com", timeoutMs: 5000, }; const db = new Client(opts); try { const result: Result = await db.execute("SELECT 1"); console.log(result.rows); } catch (e) { if (e instanceof WalkinDBError) { console.error(`walkindb ${e.status}: ${e.error}`); } }
Client
Stateful client. Captures the X-Walkin-Session token returned on the first call and reuses it on subsequent calls. Each Client instance is one walk-in.
new Client(opts?: ClientOptions)
interface ClientOptions { baseUrl?: string; // default: "https://api.walkindb.com" session?: string; // pre-existing token to resume with timeoutMs?: number; // default: 10_000 userAgent?: string; // default: "walkindb-js/0.1.0" fetch?: typeof fetch; // inject a custom fetch (tests, proxies, alt runtimes) }
| Option | Type | Default | Description |
|---|---|---|---|
baseUrl | string | "https://api.walkindb.com" | API base URL. Trailing slashes are stripped. |
session | string | undefined | Pre-existing wkn_... token to resume. Useful for session handoff between processes. |
timeoutMs | number | 10_000 | Per-request timeout, implemented via AbortSignal.timeout(). |
userAgent | string | "walkindb-js/0.1.0" | User-Agent string the client sends. |
fetch | typeof fetch | globalThis.fetch | Inject a custom fetch. Constructor throws if globalThis.fetch is missing and no override is provided. |
Client.execute(sql: string, args?: unknown[]): Promise<Result>
Execute one SQL statement against the current walk-in instance.
// Simple query const r = await db.execute("SELECT 1 AS hello"); // Multiple statements in one call await db.execute(` CREATE TABLE kv(k TEXT PRIMARY KEY, v TEXT); INSERT INTO kv VALUES('greeting', 'hello'); INSERT INTO kv VALUES('farewell', 'goodbye'); `); // Bound parameters (reserved; serialized on the wire but ignored server-side) await db.execute("INSERT INTO notes(body) VALUES(?)", ["hello"]);
Returns: Promise<Result>.
Throws: WalkinDBError on any non-2xx response or network error.
Client.healthz(): Promise<boolean>
Returns true if GET /healthz responds 2xx. Catches all exceptions and returns false on error. Does not consume rate-limit budget.
if (!await db.healthz()) { throw new Error("walkindb unreachable"); }
Client.resetSession(): void
Forget the current session. The next execute() provisions a fresh walk-in.
db.resetSession(); await db.execute("SELECT 1"); // fresh instance
Client.session: string | null (read-only)
The current wkn_-prefixed session token, or null if no instance has been provisioned.
Client.expiresAt: number | null (read-only)
Unix timestamp (seconds) at which the current instance will be deleted, or null.
Result
interface Result { columns: string[]; // column names; empty array for non-SELECT rows: unknown[][]; // row data in column order rowsAffected: number; // 0 on SELECT, N on INSERT/UPDATE/DELETE truncated: boolean; // true if capped at 10k rows / ~1 MB }
rows_affected and truncated as JSON fields. The Client converts them to rowsAffected / truncated to match JS conventions. If you need the raw snake_case shape, use the REST API directly.
WalkinDBError
class WalkinDBError extends Error { readonly status: number; // HTTP status code; 0 for network errors readonly error: string; // server-provided error message readonly retryAfter?: number; // seconds to wait (from Retry-After header) }
Error-handling recipe:
try { await db.execute("SELECT * FROM notes"); } catch (e) { if (!(e instanceof WalkinDBError)) throw e; switch (e.status) { case 400: console.error("bad sql:", e.error); break; case 404: db.resetSession(); // start a new walk-in break; case 408: console.error("query timed out"); break; case 429: await new Promise(r => setTimeout(r, (e.retryAfter ?? 10) * 1000)); break; case 507: db.resetSession(); // instance quota full; provision a new walk-in break; default: throw e; } }
See the full Error codes reference for every status the server returns.
Cloudflare Workers
walkindb works out of the box in Workers — fetch is already global. Just import and go:
import { Client } from "walkindb"; export default { async fetch(request) { const db = new Client(); const result = await db.execute("SELECT 1 AS hello"); return new Response(JSON.stringify(result), { headers: { "content-type": "application/json" }, }); }, };
Deno
import { Client } from "npm:walkindb"; const db = new Client(); console.log(await db.execute("SELECT 1"));
Bun
import { Client } from "walkindb"; const db = new Client(); console.log(await db.execute("SELECT 1"));
Browsers
walkindb's CORS headers are open (*), and the session headers are exposed, so the client works directly from a browser tab:
import { Client } from "https://esm.sh/[email protected]"; const db = new Client(); const result = await db.execute("SELECT 'hello from the browser'"); console.log(result.rows);
Don't put PII in walk-ins from browser code either — see the AUP.
Also see
- Python SDK — same API, Python flavor
- REST API reference
- Error codes
- Agent patterns
- walkindb on npm