/** * ToonDB Embedded Database * * Direct database access via IPC to the ToonDB server. * This provides the same API as the Python SDK's Database class. * * @packageDocumentation */ import { Query } from './query'; /** * Configuration options for the Database. */ export interface DatabaseConfig { /** Path to the database directory */ path: string; /** Whether to create the database if it doesn't exist (default: true) */ createIfMissing?: boolean; /** Enable WAL (Write-Ahead Logging) for durability (default: true) */ walEnabled?: boolean; /** Sync mode: 'full' | 'normal' | 'off' (default: 'normal') */ syncMode?: 'full' | 'normal' | 'off'; /** Maximum size of the memtable before flushing (default: 64MB) */ memtableSizeBytes?: number; /** * Whether to automatically start an embedded server (default: true) * Set to false if connecting to an existing external server */ embedded?: boolean; } /** * Result of a SQL query execution. */ export interface SQLQueryResult { /** Result rows */ rows: Array>; /** Column names */ columns: string[]; /** Number of rows affected (for INSERT/UPDATE/DELETE) */ rowsAffected: number; } /** * Transaction handle for atomic operations. */ export declare class Transaction { private _db; private _txnId; private _committed; private _aborted; constructor(db: Database); /** * Begin the transaction. * @internal */ begin(): Promise; /** * Get a value by key within this transaction. */ get(key: Buffer | string): Promise; /** * Put a key-value pair within this transaction. */ put(key: Buffer | string, value: Buffer | string): Promise; /** * Delete a key within this transaction. */ delete(key: Buffer | string): Promise; /** * Scan keys with a prefix within this transaction. * @param prefix - The prefix to scan for * @param end - Optional end boundary (exclusive) */ scan(prefix: string | Buffer, end?: string | Buffer): AsyncGenerator<[Buffer, Buffer]>; /** * Get a value by path within this transaction. */ getPath(pathStr: string): Promise; /** * Put a value at a path within this transaction. */ putPath(pathStr: string, value: Buffer | string): Promise; /** * Commit the transaction. * * After committing, an optional checkpoint is triggered to ensure writes * are durable. This prevents race conditions where subsequent reads might * not see committed data due to async flush timing. */ commit(): Promise; /** * Abort/rollback the transaction. */ abort(): Promise; private _ensureActive; } /** * ToonDB Database client. * * Provides access to ToonDB with full transaction support. * * @example * ```typescript * import { Database } from '@sushanth/toondb'; * * // Open a database * const db = await Database.open('./my_database'); * * // Simple key-value operations * await db.put(Buffer.from('user:123'), Buffer.from('{"name": "Alice"}')); * const value = await db.get(Buffer.from('user:123')); * * // Path-native API * await db.putPath('users/alice/email', Buffer.from('alice@example.com')); * const email = await db.getPath('users/alice/email'); * * // Transactions * await db.withTransaction(async (txn) => { * await txn.put(Buffer.from('key1'), Buffer.from('value1')); * await txn.put(Buffer.from('key2'), Buffer.from('value2')); * }); * * // Clean up * await db.close(); * ``` */ export declare class Database { private _client; private _config; private _closed; private _embeddedServerStarted; private constructor(); /** * Open a database at the specified path. * * @param pathOrConfig - Path to the database directory or configuration object * @returns A new Database instance * * @example * ```typescript * // Simple usage (embedded mode - starts server automatically) * const db = await Database.open('./my_database'); * * // With configuration * const db = await Database.open({ * path: './my_database', * walEnabled: true, * syncMode: 'full', * }); * * // Connect to existing external server * const db = await Database.open({ * path: './my_database', * embedded: false, // Don't start embedded server * }); * ``` */ static open(pathOrConfig: string | DatabaseConfig): Promise; /** * Get a value by key. * * @param key - The key to look up (Buffer or string) * @returns The value as a Buffer, or null if not found */ get(key: Buffer | string): Promise; /** * Put a key-value pair. * * @param key - The key (Buffer or string) * @param value - The value (Buffer or string) */ put(key: Buffer | string, value: Buffer | string): Promise; /** * Delete a key. * * @param key - The key to delete (Buffer or string) */ delete(key: Buffer | string): Promise; /** * Get a value by path. * * @param pathStr - The path (e.g., "users/alice/email") * @returns The value as a Buffer, or null if not found */ getPath(pathStr: string): Promise; /** * Put a value at a path. * * @param pathStr - The path (e.g., "users/alice/email") * @param value - The value (Buffer or string) */ putPath(pathStr: string, value: Buffer | string): Promise; /** * Create a query builder for the given path prefix. * * @param pathPrefix - The path prefix to query (e.g., "users/") * @returns A Query builder instance * * @example * ```typescript * const results = await db.query('users/') * .limit(10) * .select(['name', 'email']) * .execute(); * ``` */ query(pathPrefix: string): Query; /** * Scan for keys with a prefix, returning key-value pairs. * This is the preferred method for simple prefix-based iteration. * * @param prefix - The prefix to scan for (e.g., "users/", "tenants/tenant1/") * @returns Array of key-value pairs * * @example * ```typescript * const results = await db.scan('tenants/tenant1/'); * for (const { key, value } of results) { * console.log(`${key.toString()}: ${value.toString()}`); * } * ``` */ scan(prefix: string): Promise>; /** * Scan for keys with a prefix using an async generator. * This allows for memory-efficient iteration over large result sets. * * @param prefix - The prefix to scan for * @param end - Optional end boundary (exclusive) * @returns Async generator yielding [key, value] tuples * * @example * ```typescript * for await (const [key, value] of db.scanGenerator('users/')) { * console.log(`${key.toString()}: ${value.toString()}`); * } * ``` */ scanGenerator(prefix: string | Buffer, end?: string | Buffer): AsyncGenerator<[Buffer, Buffer]>; /** * Execute operations within a transaction. * * The transaction automatically commits on success or aborts on error. * * @param fn - Async function that receives a Transaction object * * @example * ```typescript * await db.withTransaction(async (txn) => { * await txn.put(Buffer.from('key1'), Buffer.from('value1')); * await txn.put(Buffer.from('key2'), Buffer.from('value2')); * // Automatically commits * }); * ``` */ withTransaction(fn: (txn: Transaction) => Promise): Promise; /** * Create a new transaction. * * @returns A new Transaction instance * @deprecated Use withTransaction() for automatic commit/abort handling */ transaction(): Promise; /** * Force a checkpoint to persist memtable to disk. */ checkpoint(): Promise; /** * Get storage statistics. */ stats(): Promise<{ memtableSizeBytes: number; walSizeBytes: number; activeTransactions: number; }>; /** * Execute a SQL query. * * ToonDB supports a subset of SQL for relational data stored on top of * the key-value engine. Tables and rows are stored as: * - Schema: _sql/tables/{table_name}/schema * - Rows: _sql/tables/{table_name}/rows/{row_id} * * Supported SQL: * - CREATE TABLE table_name (col1 TYPE, col2 TYPE, ...) * - DROP TABLE table_name * - INSERT INTO table_name (cols) VALUES (vals) * - SELECT cols FROM table_name [WHERE ...] [ORDER BY ...] [LIMIT ...] * - UPDATE table_name SET col=val [WHERE ...] * - DELETE FROM table_name [WHERE ...] * * Supported types: INT, TEXT, FLOAT, BOOL, BLOB * * @param sql - SQL query string * @returns SQLQueryResult with rows and metadata * * @example * ```typescript * // Create a table * await db.execute("CREATE TABLE users (id INT PRIMARY KEY, name TEXT, age INT)"); * * // Insert data * await db.execute("INSERT INTO users (id, name, age) VALUES (1, 'Alice', 30)"); * * // Query data * const result = await db.execute("SELECT * FROM users WHERE age > 26"); * result.rows.forEach(row => console.log(row)); * ``` */ execute(sql: string): Promise; /** * Convert records to TOON format for token-efficient LLM context. * * TOON format achieves 40-66% token reduction compared to JSON by using * a columnar text format with minimal syntax. * * @param tableName - Name of the table/collection * @param records - Array of objects with the data * @param fields - Optional array of field names to include * @returns TOON-formatted string * * @example * ```typescript * const records = [ * { id: 1, name: 'Alice', email: 'alice@ex.com' }, * { id: 2, name: 'Bob', email: 'bob@ex.com' } * ]; * console.log(Database.toToon('users', records, ['name', 'email'])); * // users[2]{name,email}:Alice,alice@ex.com;Bob,bob@ex.com * ``` */ static toToon(tableName: string, records: Array>, fields?: string[]): string; /** * Convert records to JSON format for easy application decoding. * * While TOON format is optimized for LLM context (40-66% token reduction), * JSON is often easier for applications to parse. Use this method when * the output will be consumed by application code rather than LLMs. * * @param tableName - Name of the table/collection * @param records - Array of objects with the data * @param fields - Optional array of field names to include * @param compact - If true (default), outputs minified JSON * @returns JSON-formatted string * * @example * ```typescript * const records = [ * { id: 1, name: 'Alice' }, * { id: 2, name: 'Bob' } * ]; * console.log(Database.toJson('users', records)); * // {"table":"users","count":2,"records":[{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}]} * ``` */ static toJson(tableName: string, records: Array>, fields?: string[], compact?: boolean): string; /** * Parse a JSON format string back to structured data. * * @param jsonStr - JSON-formatted string (from toJson) * @returns Object with table, fields, and records */ static fromJson(jsonStr: string): { table: string; fields: string[]; records: Array>; }; /** * Add a node to the graph overlay. * * @param namespace - Namespace for the graph * @param nodeId - Unique node identifier * @param nodeType - Type of node (e.g., "person", "document", "concept") * @param properties - Optional node properties * * @example * ```typescript * await db.addNode('default', 'alice', 'person', { role: 'engineer' }); * await db.addNode('default', 'project_x', 'project', { status: 'active' }); * ``` */ addNode(namespace: string, nodeId: string, nodeType: string, properties?: Record): Promise; /** * Add an edge between nodes in the graph overlay. * * @param namespace - Namespace for the graph * @param fromId - Source node ID * @param edgeType - Type of relationship * @param toId - Target node ID * @param properties - Optional edge properties * * @example * ```typescript * await db.addEdge('default', 'alice', 'works_on', 'project_x'); * await db.addEdge('default', 'alice', 'knows', 'bob', { since: '2020' }); * ``` */ addEdge(namespace: string, fromId: string, edgeType: string, toId: string, properties?: Record): Promise; /** * Traverse the graph from a starting node. * * @param namespace - Namespace for the graph * @param startNode - Node ID to start traversal from * @param maxDepth - Maximum traversal depth (default: 10) * @param order - "bfs" for breadth-first, "dfs" for depth-first * @returns Object with nodes and edges arrays * * @example * ```typescript * const { nodes, edges } = await db.traverse('default', 'alice', 2); * for (const node of nodes) { * console.log(`Node: ${node.id} (${node.node_type})`); * } * ``` */ traverse(namespace: string, startNode: string, maxDepth?: number, order?: 'bfs' | 'dfs'): Promise<{ nodes: any[]; edges: any[]; }>; /** * Store a value in the semantic cache with its embedding. * * @param cacheName - Name of the cache * @param key - Cache key (for display/debugging) * @param value - Value to cache * @param embedding - Embedding vector for similarity matching * @param ttlSeconds - Time-to-live in seconds (0 = no expiry) * * @example * ```typescript * await db.cachePut( * 'llm_responses', * 'What is Python?', * 'Python is a programming language...', * [0.1, 0.2, 0.3, ...], // 384-dim * 3600 * ); * ``` */ cachePut(cacheName: string, key: string, value: string, embedding: number[], ttlSeconds?: number): Promise; /** * Look up a value in the semantic cache by embedding similarity. * * @param cacheName - Name of the cache * @param queryEmbedding - Query embedding to match against * @param threshold - Minimum cosine similarity threshold (0.0 to 1.0) * @returns Cached value if similarity >= threshold, null otherwise * * @example * ```typescript * const result = await db.cacheGet( * 'llm_responses', * [0.12, 0.18, ...], // Similar to "What is Python?" * 0.85 * ); * if (result) { * console.log(`Cache hit: ${result}`); * } * ``` */ cacheGet(cacheName: string, queryEmbedding: number[], threshold?: number): Promise; private _cosineSimilarity; /** * Start a new trace. * * @param name - Name of the trace (e.g., "user_request", "batch_job") * @returns Object with traceId and rootSpanId * * @example * ```typescript * const { traceId, rootSpanId } = await db.startTrace('user_query'); * // ... do work ... * await db.endSpan(traceId, rootSpanId, 'ok'); * ``` */ startTrace(name: string): Promise<{ traceId: string; rootSpanId: string; }>; /** * Start a child span within a trace. * * @param traceId - ID of the parent trace * @param parentSpanId - ID of the parent span * @param name - Name of this span * @returns The new span ID * * @example * ```typescript * const { traceId, rootSpanId } = await db.startTrace('user_query'); * const dbSpan = await db.startSpan(traceId, rootSpanId, 'database_lookup'); * // ... do database work ... * const duration = await db.endSpan(traceId, dbSpan, 'ok'); * ``` */ startSpan(traceId: string, parentSpanId: string, name: string): Promise; /** * End a span and record its duration. * * @param traceId - ID of the trace * @param spanId - ID of the span to end * @param status - "ok", "error", or "unset" * @returns Duration in microseconds * * @example * ```typescript * const duration = await db.endSpan(traceId, spanId, 'ok'); * console.log(`Operation took ${duration}µs`); * ``` */ endSpan(traceId: string, spanId: string, status?: 'ok' | 'error' | 'unset'): Promise; /** * Close the database connection. * If running in embedded mode, also stops the embedded server. */ close(): Promise; private _beginTransaction; private _commitTransaction; private _abortTransaction; private _ensureOpen; } //# sourceMappingURL=database.d.ts.map