import * as crypto from 'crypto'; import * as path from 'path'; import * as os from 'os'; import { SmartdbServer } from '../ts_smartdb/index.js'; /** * Connection information returned by LocalSmartDb.start() */ export interface ILocalSmartDbConnectionInfo { /** The Unix socket file path */ socketPath: string; /** Connection URI (mongodb:// scheme) ready for MongoClient */ connectionUri: string; } export interface ILocalSmartDbOptions { /** Required: where to store data */ folderPath: string; /** Optional: custom socket path (default: auto-generated in /tmp) */ socketPath?: string; } /** * LocalSmartDb - Lightweight local MongoDB-compatible database using Unix sockets * * This class wraps SmartdbServer and provides a simple interface for * starting a local file-based database server. Returns connection * info that you can use with any compatible driver instance. * * @example * ```typescript * import { LocalSmartDb } from '@push.rocks/smartdb'; * import { MongoClient } from 'mongodb'; * * const db = new LocalSmartDb({ folderPath: './data' }); * const { connectionUri } = await db.start(); * * // Connect with the driver * const client = new MongoClient(connectionUri, { directConnection: true }); * await client.connect(); * * // Use the client * const collection = client.db('mydb').collection('users'); * await collection.insertOne({ name: 'Alice' }); * * // When done * await client.close(); * await db.stop(); * ``` */ export class LocalSmartDb { private options: ILocalSmartDbOptions; private server: SmartdbServer | null = null; private generatedSocketPath: string | null = null; constructor(options: ILocalSmartDbOptions) { this.options = options; } /** * Generate a unique socket path in /tmp */ private generateSocketPath(): string { const randomId = crypto.randomBytes(8).toString('hex'); return path.join(os.tmpdir(), `smartdb-${randomId}.sock`); } /** * Start the local SmartDB server and return connection info */ async start(): Promise { if (this.server) { throw new Error('LocalSmartDb is already running'); } // Use provided socket path or generate one this.generatedSocketPath = this.options.socketPath ?? this.generateSocketPath(); this.server = new SmartdbServer({ socketPath: this.generatedSocketPath, storage: 'file', storagePath: this.options.folderPath, }); await this.server.start(); return { socketPath: this.generatedSocketPath, connectionUri: this.server.getConnectionUri(), }; } /** * Get connection info (throws if not started) */ getConnectionInfo(): ILocalSmartDbConnectionInfo { if (!this.server || !this.generatedSocketPath) { throw new Error('LocalSmartDb is not running. Call start() first.'); } return { socketPath: this.generatedSocketPath, connectionUri: this.server.getConnectionUri(), }; } /** * Get the underlying SmartdbServer instance (throws if not started) */ getServer(): SmartdbServer { if (!this.server) { throw new Error('LocalSmartDb is not running. Call start() first.'); } return this.server; } /** * Get the connection URI */ getConnectionUri(): string { if (!this.server) { throw new Error('LocalSmartDb is not running. Call start() first.'); } return this.server.getConnectionUri(); } /** * Check if the server is running */ get running(): boolean { return this.server !== null && this.server.running; } /** * Stop the local SmartDB server */ async stop(): Promise { if (this.server) { await this.server.stop(); this.server = null; this.generatedSocketPath = null; } } }