import * as plugins from './plugins.js'; import * as crypto from 'crypto'; import * as path from 'path'; import * as os from 'os'; import { TsmdbServer } from '../ts_tsmdb/index.js'; /** * Connection information returned by LocalTsmDb.start() */ export interface ILocalTsmDbConnectionInfo { /** The Unix socket file path */ socketPath: string; /** MongoDB connection URI ready for MongoClient */ connectionUri: string; } export interface ILocalTsmDbOptions { /** Required: where to store data */ folderPath: string; /** Optional: custom socket path (default: auto-generated in /tmp) */ socketPath?: string; } /** * LocalTsmDb - Lightweight local MongoDB-compatible database using Unix sockets * * This class wraps TsmdbServer and provides a simple interface for * starting a local file-based MongoDB-compatible server. Returns connection * info that you can use with your own MongoDB driver instance. * * @example * ```typescript * import { LocalTsmDb } from '@push.rocks/smartmongo'; * import { MongoClient } from 'mongodb'; * * const db = new LocalTsmDb({ folderPath: './data' }); * const { connectionUri } = await db.start(); * * // Connect with your own MongoDB client * const client = new MongoClient(connectionUri, { directConnection: true }); * await client.connect(); * * // Use the MongoDB client * const collection = client.db('mydb').collection('users'); * await collection.insertOne({ name: 'Alice' }); * * // When done * await client.close(); * await db.stop(); * ``` */ export class LocalTsmDb { private options: ILocalTsmDbOptions; private server: TsmdbServer | null = null; private generatedSocketPath: string | null = null; constructor(options: ILocalTsmDbOptions) { 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(), `smartmongo-${randomId}.sock`); } /** * Start the local TsmDB server and return connection info */ async start(): Promise { if (this.server) { throw new Error('LocalTsmDb is already running'); } // Use provided socket path or generate one this.generatedSocketPath = this.options.socketPath ?? this.generateSocketPath(); this.server = new TsmdbServer({ 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(): ILocalTsmDbConnectionInfo { if (!this.server || !this.generatedSocketPath) { throw new Error('LocalTsmDb is not running. Call start() first.'); } return { socketPath: this.generatedSocketPath, connectionUri: this.server.getConnectionUri(), }; } /** * Get the underlying TsmdbServer instance (throws if not started) */ getServer(): TsmdbServer { if (!this.server) { throw new Error('LocalTsmDb is not running. Call start() first.'); } return this.server; } /** * Get the connection URI */ getConnectionUri(): string { if (!this.server) { throw new Error('LocalTsmDb 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 TsmDB server */ async stop(): Promise { if (this.server) { await this.server.stop(); this.server = null; this.generatedSocketPath = null; } } }