TypeScript SDK
The get-db9 SDK provides typed TypeScript access to DB9 databases — provisioning, SQL execution, filesystem operations, branching, and token management. This is the server-side SDK for Node.js environments.
Client-side? For browser and edge environments, use the
@db9/browserSDK — it provides a query builder with Row-Level Security enforcement and publishable key authentication.
When to Use the SDK
Section titled “When to Use the SDK”| Scenario | Recommended tool |
|---|---|
| One-liner database provisioning in a script or test | SDK — instantDatabase() |
| Programmatic fleet management (create, branch, delete) | SDK — createDb9Client() |
| File read/write from Node.js (RAG, ingestion) | SDK — client.fs.* |
| Interactive SQL from a terminal | CLI — db9 db sql (CLI Reference) |
| ORM or driver connection to an existing database | Raw pgwire — use the connection string (Connect) |
| Agent onboarding (Codex, Claude Code) | CLI — db9 onboard (Agent Workflows) |
Installation
Section titled “Installation”Runtime requirement: Node.js 18+ (native fetch). TypeScript 5+ for full type exports.
npm install get-db9Also available via yarn add get-db9, pnpm add get-db9, or bun add get-db9.
View the package on npm.
The SDK shares the credential store (~/.db9/credentials) with the db9 CLI. If you have logged in via the CLI, the SDK picks up the token automatically.
Framework Integrations
Section titled “Framework Integrations”The SDK works with any Node.js framework. For framework-specific setup guides with connection patterns and best practices:
- Next.js — Server Components, Server Actions, Route Handlers
- Express / Hono — middleware and route patterns
- SvelteKit — server-only load functions
- Nuxt — server API routes
- Remix — loaders and actions
- Astro — SSR mode with Node adapter
For Python, Ruby, Go, and PHP frameworks, use the connection string from instantDatabase() or createDb9Client() with your language’s PostgreSQL driver. See Connect for driver-specific examples.
Quick Start
Section titled “Quick Start”instantDatabase() creates or reuses a database by name. If no name is provided, it defaults to "default".
import { instantDatabase } from 'get-db9';
const db = await instantDatabase({ name: 'myapp', seed: 'CREATE TABLE users (id SERIAL PRIMARY KEY, email TEXT)'});
console.log(db.databaseId);console.log(db.connectionString);console.log(db.adminUser, db.adminPassword);console.log(db.state, db.createdAt);Result shape:
interface InstantDatabaseResult { databaseId: string; connectionString: string; adminUser: string; adminPassword: string; state: string; createdAt: string;}instantDatabase(options?)
Section titled “instantDatabase(options?)”High-level API that wraps createDb9Client(), checks for an existing database by name, creates one if missing, and optionally executes seed SQL. Seed SQL runs only on initial creation — if the database already exists, seed is skipped.
function instantDatabase( options?: InstantDatabaseOptions): Promise<InstantDatabaseResult>;| Option | Type | Description |
|---|---|---|
name | string | Database name. Default: 'default'. |
baseUrl | string | Override API endpoint. Default: https://api.db9.ai or DB9_API_URL env. |
fetch | FetchFn | Custom fetch implementation. |
credentialStore | CredentialStore | Token load/save strategy. |
seed | string | SQL text executed via client.databases.sql() on creation only. |
seedFile | string | SQL file content executed via client.databases.sqlFile() on creation only. |
timeout | number | Request timeout in milliseconds. |
maxRetries | number | Retry count for failed requests (capped at 3). |
retryDelay | number | Delay between retries in milliseconds. |
const db = await instantDatabase({ name: 'analytics', seedFile: ` CREATE TABLE events ( id BIGSERIAL PRIMARY KEY, user_id TEXT NOT NULL, created_at TIMESTAMP DEFAULT NOW() ); `});createDb9Client(options?)
Section titled “createDb9Client(options?)”Low-level typed client exposing grouped APIs: auth, tokens, databases, and fs.
The client lazy-loads the token from the credential store on the first protected call. If no token is found, it throws Db9Error (status 401). Use db9 login or pass a token via options.token before calling protected methods.
function createDb9Client(options?: Db9ClientOptions): Db9Client;| Option | Type | Description |
|---|---|---|
baseUrl | string | Default: https://api.db9.ai (or DB9_API_URL env). |
token | string | Bearer token; skips credential store lookup. |
fetch | FetchFn | Custom HTTP implementation. |
credentialStore | CredentialStore | Load/save token state. |
timeout | number | Request timeout in milliseconds. |
maxRetries | number | Retry count for failed requests (capped at 3). |
retryDelay | number | Delay between retries in milliseconds. |
WebSocket | WebSocketConstructor | Override WebSocket for client.fs operations (see Filesystem). |
wsPort | number | Override the fs9 WebSocket port (default: 5480). |
import { createDb9Client, MemoryCredentialStore } from 'get-db9';
const client = createDb9Client({ baseUrl: 'https://api.db9.ai', credentialStore: new MemoryCredentialStore()});Authentication (client.auth)
Section titled “Authentication (client.auth)”me(): Promise<CustomerResponse>— Get current user profile
The SDK itself does not handle login or registration. Use the CLI for auth:
# Zero-setup trial (auto creates anonymous account + token)db9 create --name quickstart
# Upgrade anonymous account to verified SSO identitydb9 claim
# Human operator login (browser-based)db9 login
# API key login (CI/CD, agents)db9 login --api-key <KEY>
# Create an automation tokendb9 token create --name my-agent --expires-in-days 365
# Agent runtimeexport DB9_API_KEY=<token>Once authenticated via CLI, the SDK picks up the stored token automatically.
Token Management (client.tokens)
Section titled “Token Management (client.tokens)”Create, inspect, and revoke API tokens for CI/CD and programmatic access.
create(req: CreateTokenRequest): Promise<CreateTokenResponse>— Create named token with optional expirylist(): Promise<TokenResponse[]>revoke(tokenId: string): Promise<MessageResponse>
const newToken = await client.tokens.create({ name: 'ci-deploy', expires_in_days: 90});console.log(newToken.token); // Store in secret manager
const tokens = await client.tokens.list();for (const token of tokens) { console.log(token.id, token.name, token.created_at, token.expires_at);}
await client.tokens.revoke(tokens[0].id);Database Management (client.databases)
Section titled “Database Management (client.databases)”Core lifecycle APIs: create, list, get, delete, reset password, retrieve credentials, and read observability metrics.
create(req: CreateDatabaseRequest): Promise<DatabaseResponse>list(): Promise<DatabaseResponse[]>get(databaseId: string): Promise<DatabaseResponse>delete(databaseId: string): Promise<MessageResponse>resetPassword(databaseId: string): Promise<CustomerPasswordResetResponse>credentials(databaseId: string): Promise<CustomerPasswordResetResponse>— Get stored admin credentials without resettingobservability(databaseId: string): Promise<TenantObservabilityResponse>
const db = await client.databases.create({ name: 'billing', region: 'us-west', admin_password: 'StrongAdminPass1'});
const all = await client.databases.list();const current = await client.databases.get(db.id);
const rotated = await client.databases.resetPassword(db.id);const creds = await client.databases.credentials(db.id);const metrics = await client.databases.observability(db.id);
await client.databases.delete(db.id);For programmatic provisioning patterns, see Provisioning.
SQL Execution
Section titled “SQL Execution”Execute SQL strings or SQL file content through the customer API. Both methods return SqlResult.
sql(databaseId: string, query: string): Promise<SqlResult>sqlFile(databaseId: string, fileContent: string): Promise<SqlResult>
const result = await client.databases.sql( databaseId, 'SELECT id, email FROM users ORDER BY id LIMIT 10');
console.log(result.columns);console.log(result.rows);console.log(result.row_count, result.command, result.error);
const fromFile = await client.databases.sqlFile(databaseId, ` CREATE TABLE audit_log (id BIGSERIAL PRIMARY KEY, event TEXT); INSERT INTO audit_log(event) VALUES ('created');`);SqlResult Field | Type | Description |
|---|---|---|
columns | ColumnInfo[] | Column metadata for result rows. |
rows | unknown[][] | Result values matrix. |
row_count | number | Rows affected/returned. |
command | string | Executed command label (SELECT, INSERT, etc.). |
error | string | SqlErrorDetail | Structured error with message, code, detail, hint, and position. |
Schema and Dump
Section titled “Schema and Dump”Introspect schema objects or export SQL dump payloads.
schema(databaseId: string): Promise<SchemaResponse>dump(databaseId: string, req?: DumpRequest): Promise<DumpResponse>
const schema = await client.databases.schema(databaseId);for (const table of schema.tables) { console.log(table.schema, table.name);}
const ddlOnly = await client.databases.dump(databaseId, { ddl_only: true });console.log(ddlOnly.object_count);console.log(ddlOnly.sql);Migrations
Section titled “Migrations”Apply SQL migrations with checksums and inspect migration history.
applyMigration(databaseId: string, req: MigrationApplyRequest): Promise<MigrationApplyResponse>listMigrations(databaseId: string): Promise<MigrationMetadata[]>
await client.databases.applyMigration(databaseId, { name: '20260218_add_users', sql: 'CREATE TABLE users (id SERIAL PRIMARY KEY, email TEXT NOT NULL);', checksum: 'f0b9c43b'});
const applied = await client.databases.listMigrations(databaseId);for (const migration of applied) { console.log(migration.name, migration.applied_at, migration.checksum);}Branching
Section titled “Branching”Create a database branch from an existing database. Branch creation starts in CLONING state — poll with get() until it reaches ACTIVE or CREATE_FAILED.
branch(databaseId: string, req: BranchRequest): Promise<DatabaseResponse>
const featureDb = await client.databases.branch(databaseId, { name: 'feature-auth'});
let current = featureDb;while (current.state === 'CLONING') { await new Promise((resolve) => setTimeout(resolve, 1000)); current = await client.databases.get(featureDb.id);}
if (current.state === 'CREATE_FAILED') { throw new Error('Branch clone failed');}
console.log('Branch ready:', current.id, current.name);For branch workflow patterns, see Multi-Tenant Patterns.
Database Users (client.databases.users)
Section titled “Database Users (client.databases.users)”Manage Postgres users inside a database.
list(databaseId: string): Promise<UserResponse[]>create(databaseId: string, req: CreateUserRequest): Promise<MessageResponse>delete(databaseId: string, username: string): Promise<MessageResponse>
await client.databases.users.create(databaseId, { username: 'app_user', password: 'AppUserPass!'});
const users = await client.databases.users.list(databaseId);users.forEach((u) => { console.log(u.name, u.can_login, u.can_create_db, u.is_superuser);});
await client.databases.users.delete(databaseId, 'app_user');Filesystem (client.fs)
Section titled “Filesystem (client.fs)”Cloud filesystem operations for reading, writing, and managing files attached to each database. Built for RAG pipelines, document ingestion, and agent workflows.
connect(dbId): Promise<FsClient>— Open a persistent WebSocket connection (caller must callclose())list(dbId, path): Promise<FileInfo[]>— List directory contentsread(dbId, path): Promise<string>— Read file content as textreadBinary(dbId, path): Promise<Uint8Array>— Read file as binarywrite(dbId, path, content): Promise<void>— Write a fileappend(dbId, path, content): Promise<number>— Append to a file, returns bytes writtenstat(dbId, path): Promise<FileInfo>— Get file metadataexists(dbId, path): Promise<boolean>— Check if file existsmkdir(dbId, path): Promise<void>— Create a directory recursivelyremove(dbId, path, opts?): Promise<void>— Delete a file or directoryrename(dbId, oldPath, newPath): Promise<void>— Move or rename a path
import { createDb9Client } from 'get-db9';
const client = createDb9Client();const dbId = 'my-database-id';
// Create directory and write a fileawait client.fs.mkdir(dbId, '/data');await client.fs.write(dbId, '/data/hello.txt', 'Hello from db9!');
// Read file contentconst content = await client.fs.read(dbId, '/data/hello.txt');
// List directoryconst files = await client.fs.list(dbId, '/data/');for (const file of files) { console.log(file.path, file.type, file.size);}
// Stat and check existenceconst info = await client.fs.stat(dbId, '/data/hello.txt');console.log(info.type, info.size, info.mtime);
const exists = await client.fs.exists(dbId, '/data/hello.txt');console.log('File exists:', exists);
// Append and renameawait client.fs.append(dbId, '/data/hello.txt', '\nHello again');await client.fs.rename(dbId, '/data/hello.txt', '/data/hello-2.txt');
// Cleanupawait client.fs.remove(dbId, '/data/hello-2.txt');await client.fs.remove(dbId, '/data');FileInfo
Section titled “FileInfo”| Field | Type | Description |
|---|---|---|
path | string | Full file path. |
size | number | File size in bytes. |
type | 'file' | 'dir' | Entry type. |
mode | number | Unix file mode. |
mtime | string | Last modified time as RFC 3339 text. |
FsRemoveOptions
Section titled “FsRemoveOptions”| Option | Type | Description |
|---|---|---|
recursive | boolean | Remove directories recursively (default: false). |
Credential Storage
Section titled “Credential Storage”Credential stores implement a shared async interface used by client auto-auth.
FileCredentialStore(path?)— TOML file store at~/.db9/credentials(shared withdb9CLI)MemoryCredentialStore— Volatile in-memory store for tests and serverlessdefaultCredentialStore()— Factory that returnsnew FileCredentialStore()
import { createDb9Client, FileCredentialStore, MemoryCredentialStore, defaultCredentialStore} from 'get-db9';
const fileStore = new FileCredentialStore();const customStore = new FileCredentialStore('/tmp/db9-credentials.toml');const memStore = new MemoryCredentialStore();
const client = createDb9Client({ credentialStore: fileStore });Error Handling
Section titled “Error Handling”API failures throw named Db9Error subclasses based on HTTP status code.
Db9Error— Base class withstatusCode,message, and optionalresponseDb9AuthError— Status401Db9NotFoundError— Status404Db9ConflictError— Status409(e.g., duplicate database name)
import { createDb9Client, Db9Error, Db9AuthError, Db9NotFoundError, Db9ConflictError} from 'get-db9';
const client = createDb9Client();
try { await client.databases.get('missing-id');} catch (error) { if (error instanceof Db9NotFoundError) { console.error('Database not found'); } else if (error instanceof Db9AuthError) { console.error('Authentication required — run `db9 login` first'); } else if (error instanceof Db9ConflictError) { console.error('Conflict (e.g., duplicate name)'); } else if (error instanceof Db9Error) { console.error(`db9 API error ${error.statusCode}: ${error.message}`); } else { throw error; }}TypeScript Types Reference
Section titled “TypeScript Types Reference”The package re-exports all interfaces from ./types in addition to client, credential, and filesystem types.
Already documented inline:
InstantDatabaseResult(see Quick Start),SqlResultandColumnInfo(see SQL Execution),FileInfoandFsRemoveOptions(see Filesystem).
DatabaseResponse
Section titled “DatabaseResponse”Returned by create(), list(), get(), and branch().
interface DatabaseResponse { id: string; name: string; state: string; parent_database_id?: string; region?: string; endpoints?: Endpoint[]; admin_user?: string; admin_password?: string; created_at: string; connection_string?: string;}| Field | Type | Description |
|---|---|---|
id | string | Unique database identifier. |
name | string | Human-readable database name. |
state | string | Lifecycle state: CREATING, ACTIVE, CLONING, DISABLING, DISABLED, CREATE_FAILED. |
parent_database_id | string? | Source database ID for branch databases. |
region | string? | Deployment region (e.g. us-west). |
endpoints | Endpoint[]? | Connection endpoints (host, port, type). |
admin_user | string? | Admin Postgres username. |
admin_password | string? | Admin Postgres password. Only present on create. |
created_at | string | ISO 8601 creation timestamp. |
connection_string | string? | Full postgresql:// connection URI. |
CustomerResponse
Section titled “CustomerResponse”Returned by client.auth.me().
interface CustomerResponse { id: string; email: string; created_at: string; status: string;}| Field | Type | Description |
|---|---|---|
id | string | Customer account identifier. |
email | string | Account email address. Empty for anonymous accounts. |
created_at | string | ISO 8601 account creation timestamp. |
status | string | Account status: active, anonymous. |
TokenResponse
Section titled “TokenResponse”Returned by client.tokens.list(). Metadata only — does not include the token secret.
interface TokenResponse { id: string; name: string; created_at: string; expires_at?: string;}| Field | Type | Description |
|---|---|---|
id | string | Token identifier. Use this to revoke the token. |
name | string | Human-readable token label. |
created_at | string | ISO 8601 creation timestamp. |
expires_at | string? | ISO 8601 expiry timestamp. undefined means never expires. |
CreateTokenResponse
Section titled “CreateTokenResponse”Returned by client.tokens.create(). Includes the token secret — store it immediately.
interface CreateTokenResponse { id: string; name: string; token: string; created_at: string; expires_at?: string;}| Field | Type | Description |
|---|---|---|
id | string | Token identifier. |
name | string | Human-readable token label. |
token | string | The secret token value. Shown only once — store in a secret manager. |
created_at | string | ISO 8601 creation timestamp. |
expires_at | string? | ISO 8601 expiry timestamp. |
SchemaResponse
Section titled “SchemaResponse”Returned by client.databases.schema().
interface SchemaResponse { tables: TableMetadata[]; views: ViewMetadata[];}| Field | Type | Description |
|---|---|---|
tables | TableMetadata[] | All tables in the database. |
views | ViewMetadata[] | All views in the database. |
TableMetadata
Section titled “TableMetadata”interface TableMetadata { name: string; schema: string; columns: ColumnMetadata[];}| Field | Type | Description |
|---|---|---|
name | string | Table name. |
schema | string | Postgres schema name (e.g. public). |
columns | ColumnMetadata[] | Column definitions for this table. |
ColumnMetadata
Section titled “ColumnMetadata”interface ColumnMetadata { name: string; type: string; nullable: boolean; default_value?: string;}| Field | Type | Description |
|---|---|---|
name | string | Column name. |
type | string | Postgres data type (e.g. text, integer, timestamp). |
nullable | boolean | Whether the column accepts NULL. |
default_value | string? | Default expression, if defined. |
ViewMetadata
Section titled “ViewMetadata”interface ViewMetadata { name: string; schema: string;}| Field | Type | Description |
|---|---|---|
name | string | View name. |
schema | string | Postgres schema name. |
DumpResponse
Section titled “DumpResponse”Returned by client.databases.dump().
interface DumpResponse { sql: string; object_count: number;}| Field | Type | Description |
|---|---|---|
sql | string | Full SQL dump text. |
object_count | number | Number of database objects included in the dump. |
TenantObservabilityResponse
Section titled “TenantObservabilityResponse”Returned by client.databases.observability().
interface TenantObservabilityResponse { summary: ObservabilitySummary; samples: QuerySample[];}| Field | Type | Description |
|---|---|---|
summary | ObservabilitySummary | Aggregate metrics for the observation window. |
samples | QuerySample[] | Per-query performance samples. |
ObservabilitySummary
Section titled “ObservabilitySummary”interface ObservabilitySummary { window_seconds: number; statement_count: number; txn_commit_count: number; error_count: number; qps: number; tps: number; latency_avg_ms: number; latency_p99_ms: number; active_connections: number;}| Field | Type | Description |
|---|---|---|
window_seconds | number | Observation window length in seconds. |
statement_count | number | Total statements executed in the window. |
txn_commit_count | number | Total committed transactions. |
error_count | number | Total statement errors. |
qps | number | Average queries per second. |
tps | number | Average transactions per second. |
latency_avg_ms | number | Mean query latency in milliseconds. |
latency_p99_ms | number | 99th-percentile query latency in milliseconds. |
active_connections | number | Current active connection count. |
QuerySample
Section titled “QuerySample”interface QuerySample { query: string; sample_count: number; error_count: number; latency_avg_ms: number; latency_p99_ms: number; latency_max_ms: number; last_seen_ms_ago: number;}| Field | Type | Description |
|---|---|---|
query | string | Normalized query text (literals replaced with $N). |
sample_count | number | Number of times this query pattern was observed. |
error_count | number | Number of times this query pattern produced an error. |
latency_avg_ms | number | Mean execution latency in milliseconds. |
latency_p99_ms | number | 99th-percentile latency in milliseconds. |
latency_max_ms | number | Maximum observed latency in milliseconds. |
last_seen_ms_ago | number | Milliseconds since this query was last observed. |
CustomerPasswordResetResponse
Section titled “CustomerPasswordResetResponse”Returned by client.databases.resetPassword() and client.databases.credentials().
interface CustomerPasswordResetResponse { admin_user: string; admin_password: string; connection_string: string;}| Field | Type | Description |
|---|---|---|
admin_user | string | Admin Postgres username. |
admin_password | string | Admin Postgres password (new password after reset). |
connection_string | string | Full postgresql:// connection URI. |
UserResponse
Section titled “UserResponse”Returned by client.databases.users.list().
interface UserResponse { name: string; is_superuser: boolean; can_login: boolean; can_create_db: boolean; can_create_role: boolean;}| Field | Type | Description |
|---|---|---|
name | string | Postgres username. |
is_superuser | boolean | Whether the user has superuser privileges. |
can_login | boolean | Whether the user can open connections. |
can_create_db | boolean | Whether the user can create databases. |
can_create_role | boolean | Whether the user can create roles. |
MigrationApplyResponse
Section titled “MigrationApplyResponse”Returned by client.databases.applyMigration().
interface MigrationApplyResponse { status: string; name: string;}| Field | Type | Description |
|---|---|---|
status | string | Migration result: applied or skipped (already applied). |
name | string | Migration name as provided in the request. |
MigrationMetadata
Section titled “MigrationMetadata”Returned by client.databases.listMigrations().
interface MigrationMetadata { name: string; checksum: string; applied_at: string; sql_preview: string;}| Field | Type | Description |
|---|---|---|
name | string | Migration name. |
checksum | string | Checksum provided at apply time. |
applied_at | string | ISO 8601 timestamp when the migration was applied. |
sql_preview | string | Truncated SQL for display purposes. |
MessageResponse
Section titled “MessageResponse”Returned by delete and revoke operations.
interface MessageResponse { message: string;}| Field | Type | Description |
|---|---|---|
message | string | Human-readable confirmation message. |
Request Types
Section titled “Request Types”| Type | Key Fields |
|---|---|
CreateDatabaseRequest | name: string, region?: string, admin_password?: string |
CreateTokenRequest | name?: string, expires_in_days?: number |
BranchRequest | name: string |
DumpRequest | ddl_only?: boolean |
CreateUserRequest | username: string, password?: string |
MigrationApplyRequest | name: string, sql: string, checksum: string |
Other Exported Types
Section titled “Other Exported Types”| Type | Description |
|---|---|
TenantState | Union: 'CREATING' | 'ACTIVE' | 'DISABLING' | 'DISABLED' | 'CREATE_FAILED' |
SqlErrorDetail | Structured SQL error: message, code?, position?, hint?, detail? |
Endpoint | Connection endpoint: host, port, type, region?, priority, enabled |
InstantDatabaseOptions | Options for instantDatabase() — see Quick Start |
Db9ClientOptions | Options for createDb9Client() — see createDb9Client |
CredentialStore | Interface for token load/save — see Credential Storage |
FetchFn | Custom fetch implementation type |
FsListOptions, FsConnectOptions | Filesystem operation options |
Next Steps
Section titled “Next Steps”- Browser SDK — Client-side data access with RLS
- CLI Reference — Terminal-based database management
- Connect — Connection strings, TLS, and driver configuration
- Provisioning — Programmatic fleet management patterns
- Agent Workflows — SDK usage in agent pipelines
- Extensions — fs9, HTTP, vector, pg_cron, and more