get-db9
v0.6.1
Published
TypeScript SDK for db9-server — instant PostgreSQL databases
Downloads
881
Maintainers
Readme
get-db9
TypeScript SDK for db9-backend — instant PostgreSQL-compatible databases on TiKV.
Install
npm install get-db9Quick Start
One-liner: Get a database instantly
import { instantDatabase } from 'get-db9';
const db = await instantDatabase();
console.log(db.connectionString);
// postgresql://tenant.admin:password@host:5433/postgresWith seeding
const db = await instantDatabase({
name: 'myapp',
seed: 'CREATE TABLE users (id SERIAL PRIMARY KEY, name TEXT)',
});Db9 Client
Full typed client for the API — databases, SQL, file storage, tokens, migrations, and more.
import { createDb9Client } from 'get-db9';
// Uses the credential store if present, or auto-registers an anonymous session.
const client = createDb9Client();
// Create a database
const db = await client.databases.create({ name: 'myapp' });
// Execute SQL
const result = await client.databases.sql(db.id, 'SELECT * FROM users');
console.log(result.columns, result.rows);
// Schema inspection
const schema = await client.databases.schema(db.id);
// Migrations
await client.databases.applyMigration(db.id, {
name: 'add_users',
sql: 'CREATE TABLE users (id SERIAL PRIMARY KEY)',
checksum: 'abc123',
});File Storage (fs9)
Each database includes a built-in file system accessible via WebSocket. The SDK connects to the fs9 WebSocket server, authenticates, and provides a high-level API for file operations.
Note: File storage requires a WebSocket implementation. Browsers, Deno, Bun, and Node 21+ have native
WebSocket. For Node 18–20, install thewspackage and pass it via theWebSocketoption.
import { createDb9Client } from 'get-db9';
import WebSocket from 'ws'; // Node 18–20 only
const client = createDb9Client({ WebSocket: WebSocket as any });
const dbId = 'your-database-id';
// Write a file (string, ArrayBuffer, or Uint8Array)
await client.fs.write(dbId, '/data/hello.txt', 'Hello, world!');
// Read file as text
const text = await client.fs.read(dbId, '/data/hello.txt');
// Read file as raw bytes (Uint8Array)
const bytes = await client.fs.readBinary(dbId, '/data/image.png');
// List files in a directory
const files = await client.fs.list(dbId, '/data');
// Check if file exists
const exists = await client.fs.exists(dbId, '/data/hello.txt');
// Get file metadata (type, size, mode, mtime)
const stat = await client.fs.stat(dbId, '/data/hello.txt');
console.log(stat.type, stat.size); // 'file', 1024
// Create directory (recursive)
await client.fs.mkdir(dbId, '/data/nested/dir');
// Append to a file
await client.fs.append(dbId, '/data/log.txt', 'new line\n');
// Rename (move) a file
await client.fs.rename(dbId, '/data/old.txt', '/data/new.txt');
// Delete a file
await client.fs.remove(dbId, '/data/hello.txt');
// Delete a directory recursively
await client.fs.remove(dbId, '/data/old-dir', { recursive: true });Persistent Connection
For multiple operations on the same database, use fs.connect() to hold a
single WebSocket connection and avoid reconnecting per-call:
const fs = await client.fs.connect(dbId);
try {
await fs.mkdir('/batch');
await fs.writeFile('/batch/a.txt', 'file A');
await fs.writeFile('/batch/b.txt', 'file B');
const entries = await fs.readdir('/batch');
console.log(entries); // [{path: '/batch/a.txt', ...}, ...]
} finally {
await fs.close();
}Token Management
const client = createDb9Client();
// Create a named API token
const token = await client.tokens.create({
name: 'ci-deploy',
expires_in_days: 90,
});
console.log(token.token); // Use this for CI/CD
// List all tokens
const tokens = await client.tokens.list();
// Revoke a token
await client.tokens.revoke(token.id);Anonymous + Claim
If no credentials are available, the SDK auto-registers an anonymous session on the first authenticated call and stores token, is_anonymous, anonymous_id, and anonymous_secret in the configured credential store (~/.db9/credentials by default).
- Run
db9 claim(ordb9 claim --id-token <AUTH0_ID_TOKEN>) to upgrade that account to a verified Auth0 identity. - After claim, continue using the stored token or create named API tokens for CI/CD and agents.
Database Credentials
Retrieve stored admin credentials without resetting the password:
const client = createDb9Client();
const dbId = 'your-database-id';
// Get stored credentials (no password reset)
const creds = await client.databases.credentials(dbId);
console.log(creds.admin_user); // admin username
console.log(creds.admin_password); // current password
console.log(creds.connection_string); // full connection stringSQL Error Handling
SQL results include structured error details when queries fail:
const result = await client.databases.sql(dbId, 'SELECT * FROM nonexistent');
if (result.error) {
// result.error is a SqlErrorDetail object:
// {
// message: "relation \"nonexistent\" does not exist",
// code: "42P01", // PostgreSQL error code
// detail: "...", // optional
// hint: "...", // optional
// position: 15 // optional cursor position
// }
console.log(result.error.message);
console.log(result.error.code);
}Configuration
instantDatabase options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| name | string | 'default' | Database name |
| baseUrl | string | Production URL | API endpoint |
| fetch | FetchFn | globalThis.fetch | Custom fetch |
| credentialStore | CredentialStore | FileCredentialStore | Credential storage |
| seed | string | — | SQL to run after creation |
| seedFile | string | — | SQL file content to run |
| timeout | number | — | Request timeout in ms |
| maxRetries | number | 3 (max) | Retry count for failed requests |
| retryDelay | number | — | Delay between retries in ms |
Db9 client options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| baseUrl | string | Production URL | API endpoint |
| token | string | — | Bearer token (optional) |
| fetch | FetchFn | globalThis.fetch | Custom fetch |
| credentialStore | CredentialStore | FileCredentialStore | Load/save token |
| timeout | number | — | Request timeout in ms |
| maxRetries | number | 3 (max) | Retry count for failed requests |
| retryDelay | number | — | Delay between retries in ms |
| WebSocket | WebSocketConstructor | globalThis.WebSocket | WebSocket impl for fs operations |
| wsPort | number | 5480 | WebSocket port for fs9 server |
Zero-config client
import { createDb9Client } from 'get-db9';
// Loads existing credentials or auto-registers an anonymous session
const client = createDb9Client();
const db = await client.databases.create({ name: 'myapp' });Error Handling
import {
createDb9Client,
Db9Error,
Db9AuthError,
Db9NotFoundError,
} from 'get-db9';
const client = createDb9Client();
try {
await client.databases.get('nonexistent');
} catch (err) {
if (err instanceof Db9NotFoundError) {
console.log('Database not found');
} else if (err instanceof Db9AuthError) {
console.log('Authentication failed');
} else if (err instanceof Db9Error) {
console.log(`API error ${err.statusCode}: ${err.message}`);
}
}Note: If you rely on
instanceof, importcreateDb9Clientand the error classes from the same entrypoint:get-db9.
Credential Storage
Credentials are stored in ~/.db9/credentials (TOML format), shared with the db9 CLI.
import { FileCredentialStore, MemoryCredentialStore } from 'get-db9';
// File-based (default, shared with CLI)
const fileStore = new FileCredentialStore();
// Custom path
const customStore = new FileCredentialStore('/path/to/credentials');
// In-memory (for testing or serverless)
const memStore = new MemoryCredentialStore();API Reference
client.auth
| Method | Description |
|--------|-------------|
| me() | Get current user profile |
client.tokens
| Method | Description |
|--------|-------------|
| create(req) | Create a named API token ({ name?, expires_in_days? }) |
| list() | List all tokens |
| revoke(tokenId) | Revoke a token by ID |
client.databases
| Method | Description |
|--------|-------------|
| create(req) | Create a new database |
| list() | List all databases |
| get(id) | Get database details |
| delete(id) | Delete a database |
| resetPassword(id) | Reset admin password |
| credentials(id) | Get stored admin credentials without resetting |
| observability(id) | Get TPS, latency, connection stats |
| sql(id, query) | Execute SQL query (errors returned as SqlErrorDetail) |
| sqlFile(id, content) | Execute SQL from file content |
| schema(id) | Get schema metadata |
| dump(id, req?) | Export schema/data as SQL |
| applyMigration(id, req) | Apply a migration |
| listMigrations(id) | List applied migrations |
| branch(id, req) | Create a database branch |
| users.list(id) | List database users |
| users.create(id, req) | Create database user |
| users.delete(id, username) | Delete database user |
client.fs
All methods auto-resolve database credentials and connect via WebSocket.
| Method | Description |
|--------|-------------|
| connect(dbId) | Open a persistent FsClient WebSocket connection |
| read(dbId, path) | Read file as text (UTF-8) |
| readBinary(dbId, path) | Read file as Uint8Array |
| write(dbId, path, content) | Write file (string, ArrayBuffer, or Uint8Array) |
| append(dbId, path, content) | Append to a file, returns bytes written |
| list(dbId, path) | List directory contents (returns FileInfo[]) |
| stat(dbId, path) | Get file metadata (FileInfo) |
| exists(dbId, path) | Check if file exists (returns boolean) |
| mkdir(dbId, path) | Create directory recursively |
| remove(dbId, path, opts?) | Remove file or directory ({ recursive?: boolean }) |
| rename(dbId, old, new) | Rename (move) a file or directory |
Requirements
- Node.js >= 18 (native fetch)
- TypeScript >= 5.0 (for type exports)
License
Apache-2.0
