Skip to main content
Glama
connection.ts4.44 kB
/** * Database connection management and utilities */ import { existsSync, mkdirSync } from 'fs'; import { dirname } from 'path'; import type { DbDriver } from './db-driver.js'; import { createDriverFromEnv } from './driver-factory.js'; import { initializeSchema, createViews, optimizeDatabase, getDatabaseStats, type DatabaseStats, } from './schema.js'; import { DatabaseError } from '../types/index.js'; let dbInstance: DbDriver | null = null; /** * Get or create database connection */ export function getDatabase(path: string): DbDriver { if (dbInstance) { return dbInstance; } try { // Ensure directory exists const dir = dirname(path); if (!existsSync(dir)) { mkdirSync(dir, { recursive: true }); } // Open database using driver factory (respects MEMORY_DB_DRIVER env var) dbInstance = createDriverFromEnv({ path, options: { verbose: process.env['NODE_ENV'] === 'development' ? () => {} : undefined, }, }); // Initialize schema initializeSchema(dbInstance); // Create views createViews(dbInstance); // Optimize optimizeDatabase(dbInstance); return dbInstance; } catch (error) { throw new DatabaseError('Failed to initialize database', { path, error: error instanceof Error ? error.message : String(error), }); } } /** * Close database connection */ export function closeDatabase(): void { if (dbInstance) { dbInstance.close(); dbInstance = null; } } /** * Execute a transaction */ export function transaction<T>(db: DbDriver, fn: () => T): T { const txn = db.transaction(fn); return txn(); } /** * Serialize metadata to JSON string */ export function serializeMetadata(metadata: Record<string, unknown>): string { return JSON.stringify(metadata); } /** * Deserialize metadata from JSON string */ export function deserializeMetadata(json: string): Record<string, unknown> { try { return JSON.parse(json) as Record<string, unknown>; } catch { return {}; } } /** * Generate unique ID */ export function generateId(prefix: string = 'mem'): string { const timestamp = Date.now().toString(36); const random = Math.random().toString(36).substring(2, 9); return `${prefix}_${timestamp}${random}`; } /** * Get current timestamp in milliseconds */ export function now(): number { return Date.now(); } /** * Prune expired and deleted memories */ export interface PruneResult { expired_count: number; deleted_count: number; total_pruned: number; } export function pruneMemories( db: DbDriver, olderThanDays: number = 0, dryRun: boolean = false ): PruneResult { const threshold = now() - olderThanDays * 24 * 60 * 60 * 1000; // Count expired memories const expiredCount = db .prepare( ` SELECT COUNT(*) FROM memories WHERE is_deleted = 0 AND expires_at IS NOT NULL AND expires_at <= ? ` ) .pluck() .get(threshold) as number; // Count soft-deleted memories const deletedCount = db .prepare( ` SELECT COUNT(*) FROM memories WHERE is_deleted = 1 AND created_at <= ? ` ) .pluck() .get(threshold) as number; if (dryRun) { return { expired_count: expiredCount, deleted_count: deletedCount, total_pruned: 0, }; } // Permanently delete expired memories const expiredDeleted = db .prepare( ` DELETE FROM memories WHERE is_deleted = 0 AND expires_at IS NOT NULL AND expires_at <= ? ` ) .run(threshold); // Permanently delete soft-deleted memories const softDeleted = db .prepare( ` DELETE FROM memories WHERE is_deleted = 1 AND created_at <= ? ` ) .run(threshold); // Clean up orphaned entities (not linked to any memory) db.prepare( ` DELETE FROM entities WHERE id NOT IN (SELECT DISTINCT entity_id FROM memory_entities) ` ).run(); return { expired_count: expiredCount, deleted_count: deletedCount, total_pruned: expiredDeleted.changes + softDeleted.changes, }; } /** * Get database statistics */ export function getStats(db: DbDriver): DatabaseStats { return getDatabaseStats(db); }

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/WhenMoon-afk/claude-memory-mcp'

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