Skip to main content
Glama
cameronsjo

MCP Server Template

by cameronsjo
database.ts3.35 kB
/** * SQLite database connection using sql.js (WebAssembly) * * Provides cross-platform SQLite without native dependencies. * Initializes schema on first connection and provides singleton access. */ import { mkdirSync, existsSync, readFileSync, writeFileSync } from 'node:fs'; import { dirname } from 'node:path'; import initSqlJs, { type Database, type SqlJsStatic } from 'sql.js'; import { getConfig } from '../config/index.js'; import { createLogger } from '../shared/logger.js'; import { CacheError } from '../shared/errors.js'; const logger = createLogger('db'); let db: Database | null = null; let sqlPromise: Promise<SqlJsStatic> | null = null; /** * Schema definition for the cache table */ const SCHEMA = ` CREATE TABLE IF NOT EXISTS cache ( key TEXT PRIMARY KEY, value TEXT NOT NULL, expires_at INTEGER NOT NULL, created_at INTEGER NOT NULL, hit_count INTEGER DEFAULT 0 ); CREATE INDEX IF NOT EXISTS idx_cache_expires ON cache(expires_at); `; /** * Initialize sql.js WebAssembly module (cached) */ async function getSql(): Promise<SqlJsStatic> { if (!sqlPromise) { sqlPromise = initSqlJs(); } return sqlPromise; } /** * Ensure the database directory exists */ function ensureDbDir(dbPath: string): void { const dir = dirname(dbPath); if (!existsSync(dir)) { mkdirSync(dir, { recursive: true }); logger.debug('Created database directory', { dir }); } } /** * Initialize database connection and schema */ export async function initDatabase(): Promise<Database> { if (db) { return db; } const config = getConfig(); const dbPath = config.dbPath; try { const SQL = await getSql(); ensureDbDir(dbPath); // Load existing database or create new one if (existsSync(dbPath)) { const buffer = readFileSync(dbPath); db = new SQL.Database(buffer); logger.info('Loaded existing database', { path: dbPath }); } else { db = new SQL.Database(); logger.info('Created new database', { path: dbPath }); } // Initialize schema db.run(SCHEMA); // Cleanup expired entries on startup const now = Date.now(); db.run('DELETE FROM cache WHERE expires_at < ?', [now]); logger.debug('Database initialized'); return db; } catch (error) { throw new CacheError('Failed to initialize database', error as Error); } } /** * Get the database instance (must call initDatabase first) */ export function getDatabase(): Database { if (!db) { throw new CacheError('Database not initialized. Call initDatabase() first.'); } return db; } /** * Persist database to disk */ export function saveDatabase(): void { if (!db) { return; } const config = getConfig(); try { const data = db.export(); const buffer = Buffer.from(data); writeFileSync(config.dbPath, buffer); logger.debug('Database saved to disk'); } catch (error) { logger.error('Failed to save database', { error: String(error) }); } } /** * Close database connection and save to disk */ export function closeDatabase(): void { if (db) { saveDatabase(); db.close(); db = null; logger.info('Database closed'); } } /** * Reset database (for testing) */ export async function resetDatabase(): Promise<void> { closeDatabase(); db = null; await initDatabase(); }

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/cameronsjo/mcp-server-template'

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