JavaScript SDK
The @boltstore/client SDK provides a type-safe, promise-based interface to interact with your Boltstore databases. HTTP-only — no realtime, no offline sync, no client-side cache. Works in Node.js, Bun, Deno, and browsers.
Installation
# npm npm install @boltstore/client # yarn yarn add @boltstore/client # bun bun install @boltstore/client
Initialization
import { BoltstoreClient } from '@boltstore/client'; const client = new BoltstoreClient({ url: 'http://localhost:8080', database: 'my-app', key: 'boltstore_...', // per-database API key, or admin session token }); // Update the key later client.setKey('boltstore_...');
The key is sent as Authorization: Bearer <key> on every request. Use a per-database API key for data access, or an admin session token (from POST /api/admin/login) for admin methods.
Tables
// List all tables const tables = await client.tables.list(); // Create a table with column definitions await client.tables.create('posts', [ { name: 'id', type: 'integer', primary_key: true, auto_increment: true }, { name: 'title', type: 'text', nullable: false }, { name: 'views', type: 'integer', default: '0' }, ]); // Get table schema const schema = await client.tables.get('posts'); // Rename, add/drop columns await client.tables.update('posts', { name: 'articles', add_columns: [{ name: 'body', type: 'text' }], }); // Drop a table await client.tables.delete('articles');
Typed Records
const posts = client.table<{ id: number; title: string; views: number }>('posts'); // Create const created = await posts.create({ title: 'Hello World', views: 0 }); // Get by ID const fetched = await posts.get(created.id); // Update await posts.update(created.id, { views: 1 }); // Delete await posts.delete(created.id); // List with filter, sort, pagination const result = await posts.list({ filter: { title: 'Hello%' }, sort: '-id', limit: 10, offset: 0, });
Query Builder
const list = await posts .query() .where('title', 'like', 'Hello%') .orWhere('views', 'gt', 100) .orderBy('id', 'desc') .limit(10) .get(); // Get first match const first = await posts.query().where('title', 'eq', 'Hello').first(); // Paginate const page = await posts.query().paginate(1, 20);
Supported operators: eq, ne, gt, gte, lt, lte, in, like, glob.
Raw SQL
// SELECT only for non-admin keys; DDL/DML requires admin const rows = await client.sql<{ id: number; title: string }>( 'SELECT id, title FROM posts WHERE views > ? ORDER BY id', [0], );
Admin Operations
These methods require an admin session token or admin API key:
// Database info / delete / export const info = await client.info(); await client.delete(); const blob = await client.export(); // Per-database config const config = await client.config.get(); await client.config.update({ cors_origins: ['https://myapp.com'] }); // API key management const keys = await client.keys.list(); const newKey = await client.keys.create('Production Backend'); await client.keys.rotate(newKey.id); await client.keys.revoke(newKey.id);
Health Check
const health = await client.health(); // { status: "ok", version: "1.0.0", databases: 3 }
Authentication Model
The SDK holds a single key used for every request. Methods that hit admin routes (info, delete, export, config.*, keys.*) require an admin session token. Methods that hit data routes (tables.*, table(), records, sql) accept either a per-database API key or an admin credential.
If you only have a per-database API key, use tables, table(), list, and sql(). Calling info() or keys.list() will return 401 Unauthorized.
Known Issues
PaginatedResult.totalis currently broken.list()andpaginate()returntotalas the current page's row count, not the total matching rows. Do not rely ontotalfor pagination page-count math until fixed.QueryBuilder.whereopis not validated client-side. An unsupportedopis silently dropped by the server. Stick to the supported operators listed above.