Skip to main content
Glama
database.ts4.31 kB
import sqlite3 from 'sqlite3'; export interface HealthData { user_id: string; day: string; steps?: number; resting_hr?: number; calories?: number; sleep_seconds?: number; body_battery_min?: number; body_battery_max?: number; payload: any; created_at: string; updated_at: string; } export class Database { private db: sqlite3.Database; private dbPath: string; constructor(dbPath: string = '/data/garmin_health.db') { this.dbPath = dbPath; this.db = new sqlite3.Database(dbPath); this.init(); } private async init(): Promise<void> { return new Promise((resolve, reject) => { this.db.serialize(() => { this.db.run(` CREATE TABLE IF NOT EXISTS health_data ( user_id TEXT NOT NULL, day TEXT NOT NULL, steps INTEGER, resting_hr INTEGER, calories INTEGER, sleep_seconds INTEGER, body_battery_min INTEGER, body_battery_max INTEGER, payload TEXT, created_at TEXT NOT NULL, updated_at TEXT NOT NULL, PRIMARY KEY (user_id, day) ) `, (err) => { if (err) { console.error('Error creating table:', err); reject(err); } else { console.log('Database initialized successfully'); resolve(); } }); }); }); } async upsertHealthData(data: Omit<HealthData, 'created_at' | 'updated_at'>): Promise<void> { return new Promise((resolve, reject) => { const now = new Date().toISOString(); const stmt = this.db.prepare(` INSERT INTO health_data (user_id, day, steps, resting_hr, calories, sleep_seconds, body_battery_min, body_battery_max, payload, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT(user_id, day) DO UPDATE SET steps = excluded.steps, resting_hr = excluded.resting_hr, calories = excluded.calories, sleep_seconds = excluded.sleep_seconds, body_battery_min = excluded.body_battery_min, body_battery_max = excluded.body_battery_max, payload = excluded.payload, updated_at = excluded.updated_at `); stmt.run( data.user_id, data.day, data.steps, data.resting_hr, data.calories, data.sleep_seconds, data.body_battery_min, data.body_battery_max, JSON.stringify(data.payload), now, now, (err: any) => { if (err) { console.error('Error upserting health data:', err); reject(err); } else { resolve(); } } ); stmt.finalize(); }); } async getHealthData(userId: string, date: string): Promise<HealthData | null> { return new Promise((resolve, reject) => { this.db.get( 'SELECT * FROM health_data WHERE user_id = ? AND day = ?', [userId, date], (err: any, row: any) => { if (err) { console.error('Error getting health data:', err); reject(err); } else if (row) { resolve({ ...row, payload: JSON.parse(row.payload) } as HealthData); } else { resolve(null); } } ); }); } async getRecentHealthData(userId: string, days: number): Promise<HealthData[]> { return new Promise((resolve, reject) => { this.db.all( 'SELECT * FROM health_data WHERE user_id = ? ORDER BY day DESC LIMIT ?', [userId, days], (err: any, rows: any[]) => { if (err) { console.error('Error getting recent health data:', err); reject(err); } else { resolve(rows.map(row => ({ ...row, payload: JSON.parse(row.payload) } as HealthData))); } } ); }); } async close(): Promise<void> { return new Promise((resolve, reject) => { this.db.close((err) => { if (err) { console.error('Error closing database:', err); reject(err); } else { resolve(); } }); }); } }

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/zjromani/garmin-mcp'

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