Skip to main content
Glama
tinyDb.ts5.45 kB
/** * TinyDB - A simple file-based database for tracking bot usage * * This module provides a lightweight persistence layer to track bot usage across sessions. * It stores recently used bots along with their metadata for enhanced search experiences. */ import fs from 'fs'; import path from 'path'; // Interface for bot metadata in our tiny database export interface BotRecord { id: string; // Bot UUID name?: string; // Bot name if available meetingUrl?: string; // URL of the meeting meetingType?: string; // Type of meeting (e.g., "sales", "standup") createdAt?: string; // When the bot/meeting was created lastAccessedAt: string; // When the bot was last accessed by a user accessCount: number; // How many times this bot has been accessed creator?: string; // Who created/requested the bot participants?: string[]; // Meeting participants if known topics?: string[]; // Key topics discussed in the meeting extra?: Record<string, any>; // Additional metadata from the original API } // Main database class export class TinyDb { private dbPath: string; private data: { recentBots: BotRecord[]; lastUpdated: string; }; constructor(dbFilePath?: string) { // Use provided path or default to the project root this.dbPath = dbFilePath || path.resolve(process.cwd(), 'bot-history.json'); // Initialize with empty data this.data = { recentBots: [], lastUpdated: new Date().toISOString() }; // Try to load existing data this.loadFromFile(); } // Load database from file private loadFromFile(): void { try { if (fs.existsSync(this.dbPath)) { const fileContent = fs.readFileSync(this.dbPath, 'utf-8'); this.data = JSON.parse(fileContent); console.log(`TinyDB: Loaded ${this.data.recentBots.length} bot records from ${this.dbPath}`); } else { console.log(`TinyDB: No existing database found at ${this.dbPath}, starting fresh`); } } catch (error) { console.error(`TinyDB: Error loading database:`, error); // Continue with empty data } } // Save database to file private saveToFile(): void { try { // Update the lastUpdated timestamp this.data.lastUpdated = new Date().toISOString(); // Write to file fs.writeFileSync(this.dbPath, JSON.stringify(this.data, null, 2), 'utf-8'); console.log(`TinyDB: Saved ${this.data.recentBots.length} bot records to ${this.dbPath}`); } catch (error) { console.error(`TinyDB: Error saving database:`, error); } } // Add or update a bot record public trackBot(botData: Partial<BotRecord> & { id: string }): BotRecord { // Find if bot already exists const existingIndex = this.data.recentBots.findIndex(bot => bot.id === botData.id); if (existingIndex >= 0) { // Update existing record const existingBot = this.data.recentBots[existingIndex]; // Preserve existing data while updating with new data const updatedBot: BotRecord = { ...existingBot, ...botData, // Always update these fields lastAccessedAt: new Date().toISOString(), accessCount: (existingBot.accessCount || 0) + 1, }; // Remove from current position this.data.recentBots.splice(existingIndex, 1); // Add to the front (most recent) this.data.recentBots.unshift(updatedBot); // Save changes this.saveToFile(); return updatedBot; } else { // Create new record const newBot: BotRecord = { ...botData, lastAccessedAt: new Date().toISOString(), accessCount: 1, }; // Add to the front (most recent) this.data.recentBots.unshift(newBot); // Trim the list if it gets too long (keeping most recent 50) if (this.data.recentBots.length > 50) { this.data.recentBots = this.data.recentBots.slice(0, 50); } // Save changes this.saveToFile(); return newBot; } } // Get most recent bots (defaults to 5) public getRecentBots(limit: number = 5): BotRecord[] { return this.data.recentBots.slice(0, limit); } // Get most accessed bots (defaults to 5) public getMostAccessedBots(limit: number = 5): BotRecord[] { // Sort by access count (descending) and return top ones return [...this.data.recentBots] .sort((a, b) => (b.accessCount || 0) - (a.accessCount || 0)) .slice(0, limit); } // Search bots by meeting type public getBotsByMeetingType(meetingType: string): BotRecord[] { return this.data.recentBots.filter(bot => bot.meetingType?.toLowerCase() === meetingType.toLowerCase() ); } // Get bot by ID public getBot(id: string): BotRecord | undefined { return this.data.recentBots.find(bot => bot.id === id); } // Update session with recent bot IDs public updateSession(session: any): void { if (!session) return; // Add recentBotIds to session session.recentBotIds = this.getRecentBots(5).map(bot => bot.id); } } // Singleton instance let db: TinyDb | null = null; // Get the singleton instance export function getTinyDb(dbFilePath?: string): TinyDb { if (!db) { db = new TinyDb(dbFilePath); } return 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/Meeting-BaaS/meeting-mcp'

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