Skip to main content
Glama
index.ts5.02 kB
import Database from 'better-sqlite3'; import { join, dirname, isAbsolute } from 'path'; import { existsSync } from 'fs'; import { initDB } from './db.js'; import { migrate } from './migrations.js'; let dbInstance: Database.Database | null = null; let configuredDbPath: string | null = null; /** * Get the default database path. * Uses environment variable, CLI argument, or falls back to user data directory. * * For Tauri sidecar usage: * - Production: rpg.db is bundled alongside the executable * - Dev mode: rpg.db is in src-tauri/binaries/ (need to search up from target/debug/) */ function getDefaultDbPath(): string { // Check for environment variable first if (process.env.RPG_MCP_DB_PATH) { return process.env.RPG_MCP_DB_PATH; } // Check for CLI argument --db-path const args = process.argv; const dbPathIndex = args.indexOf('--db-path'); if (dbPathIndex !== -1 && args[dbPathIndex + 1]) { return args[dbPathIndex + 1]; } // Fall back to executable directory or current working directory // For bundled executables, use the directory containing the executable const exePath = process.execPath; const exeDir = dirname(exePath); // Check if we're running as a bundled executable (pkg/esbuild bundle) // The bundled executable will have a snapshot filesystem // Use type assertion since 'pkg' is added by the pkg bundler at runtime if ((process as unknown as { pkg?: unknown }).pkg || exePath.includes('rpg-mcp-server')) { // First, check if rpg.db exists next to the executable (production mode) const prodPath = join(exeDir, 'rpg.db'); if (existsSync(prodPath)) { return prodPath; } // Tauri dev mode: executable is in target/debug/ or target/release/ // but the database is in src-tauri/binaries/ // Search up the directory tree for src-tauri/binaries/rpg.db let searchDir = exeDir; for (let i = 0; i < 5; i++) { const tauriDevPath = join(searchDir, 'binaries', 'rpg.db'); if (existsSync(tauriDevPath)) { console.error(`[Database] Found database at Tauri dev path: ${tauriDevPath}`); return tauriDevPath; } // Also check for src-tauri/binaries pattern const srcTauriPath = join(searchDir, 'src-tauri', 'binaries', 'rpg.db'); if (existsSync(srcTauriPath)) { console.error(`[Database] Found database at src-tauri path: ${srcTauriPath}`); return srcTauriPath; } searchDir = dirname(searchDir); } // Fall back to executable directory (will create new DB if not found) console.error(`[Database] No existing database found, will create at: ${prodPath}`); return prodPath; } // For development, use current working directory return join(process.cwd(), 'rpg.db'); } /** * Resolve database path, ensuring it's absolute. */ function resolveDbPath(path?: string): string { const dbPath = path || configuredDbPath || getDefaultDbPath(); // Special case: SQLite in-memory database if (dbPath === ':memory:') { return dbPath; } if (isAbsolute(dbPath)) { return dbPath; } // Make relative paths absolute based on CWD return join(process.cwd(), dbPath); } /** * Configure the database path before initialization. * Call this before getDb() to set a custom path. */ export function configureDbPath(path: string): void { if (dbInstance) { throw new Error('Cannot configure database path after database has been initialized'); } configuredDbPath = isAbsolute(path) ? path : join(process.cwd(), path); } /** * Get the configured or default database path (for logging/debugging). */ export function getDbPath(): string { return resolveDbPath(); } export function getDb(path?: string): Database.Database { if (!dbInstance) { const resolvedPath = resolveDbPath(path); console.error(`[Database] Initializing database at: ${resolvedPath}`); dbInstance = initDB(resolvedPath); migrate(dbInstance); } return dbInstance; } export function setDb(database: Database.Database) { dbInstance = database; } /** * Close the database with proper WAL checkpoint. * This ensures all WAL data is written to the main database file. */ export function closeDb() { if (dbInstance) { try { // Checkpoint WAL to ensure all changes are written to main database dbInstance.pragma('wal_checkpoint(TRUNCATE)'); console.error('[Database] WAL checkpoint completed'); } catch (e) { console.error('[Database] WAL checkpoint failed:', (e as Error).message); } dbInstance.close(); dbInstance = null; console.error('[Database] Database closed'); } } export * from './db.js'; export * from './migrations.js'; export * from './audit.repo.js';

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Mnehmos/rpg-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server