Skip to main content
Glama
test-clients.tsβ€’5.45 kB
#!/usr/bin/env tsx /** * Test script to verify API client integrations * Run with: npm run test:clients */ import { WhoopClient } from '../clients/whoop.js'; import { IntervalsClient } from '../clients/intervals.js'; import { TrainerRoadClient } from '../clients/trainerroad.js'; async function testWhoop() { console.log('\nπŸ‹οΈ Testing Whoop API...\n'); const clientId = process.env.WHOOP_CLIENT_ID; const clientSecret = process.env.WHOOP_CLIENT_SECRET; if (!clientId || !clientSecret) { console.log(' ⏭️ Skipped: WHOOP_CLIENT_ID or WHOOP_CLIENT_SECRET not set'); return; } try { const client = new WhoopClient({ accessToken: '', // Will be loaded from Redis refreshToken: '', clientId, clientSecret, }); // Test today's recovery console.log(' Fetching today\'s recovery...'); const recovery = await client.getTodayRecovery(); if (recovery) { console.log(` βœ… Recovery score: ${recovery.recovery_score}%`); console.log(` HRV: ${recovery.hrv_rmssd.toFixed(1)} ms`); console.log(` RHR: ${recovery.resting_heart_rate} bpm`); console.log(` Sleep: ${recovery.sleep_duration_hours.toFixed(1)} hours`); } else { console.log(' ⚠️ No recovery data for today'); } // Test recent strain const today = new Date().toISOString().split('T')[0]; const weekAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString().split('T')[0]; console.log('\n Fetching recent strain data...'); const strain = await client.getStrainData(weekAgo, today); console.log(` βœ… Found ${strain.length} days of strain data`); if (strain.length > 0) { const latest = strain[strain.length - 1]; console.log(` Latest strain: ${latest.strain_score.toFixed(1)}`); console.log(` Activities: ${latest.activities.length}`); } } catch (error) { console.error(' ❌ Whoop error:', error instanceof Error ? error.message : error); } } async function testIntervals() { console.log('\n🚴 Testing Intervals.icu API...\n'); const apiKey = process.env.INTERVALS_API_KEY; const athleteId = process.env.INTERVALS_ATHLETE_ID; if (!apiKey || !athleteId) { console.log(' ⏭️ Skipped: INTERVALS_API_KEY or INTERVALS_ATHLETE_ID not set'); return; } try { const client = new IntervalsClient({ apiKey, athleteId }); // Test recent activities const today = new Date().toISOString().split('T')[0]; const weekAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString().split('T')[0]; console.log(' Fetching recent activities...'); const activities = await client.getActivities(weekAgo, today); console.log(` βœ… Found ${activities.length} activities`); if (activities.length > 0) { const latest = activities[0]; console.log(` Latest: ${latest.name || latest.activity_type}`); console.log(` Duration: ${Math.round(latest.duration_seconds / 60)} min`); if (latest.tss) console.log(` TSS: ${latest.tss}`); } // Test fitness data console.log('\n Fetching fitness metrics...'); const fitness = await client.getFitnessMetrics(weekAgo, today); console.log(` βœ… Found ${fitness.length} days of fitness data`); if (fitness.length > 0) { const latest = fitness[fitness.length - 1]; console.log(` CTL (Fitness): ${latest.ctl.toFixed(1)}`); console.log(` ATL (Fatigue): ${latest.atl.toFixed(1)}`); console.log(` TSB (Form): ${latest.tsb.toFixed(1)}`); } } catch (error) { console.error(' ❌ Intervals.icu error:', error instanceof Error ? error.message : error); } } async function testTrainerRoad() { console.log('\nπŸ“… Testing TrainerRoad Calendar...\n'); const calendarUrl = process.env.TRAINERROAD_CALENDAR_URL; if (!calendarUrl) { console.log(' ⏭️ Skipped: TRAINERROAD_CALENDAR_URL not set'); return; } try { const client = new TrainerRoadClient({ calendarUrl }); // Test upcoming workouts console.log(' Fetching upcoming workouts...'); const workouts = await client.getUpcomingWorkouts(7); console.log(` βœ… Found ${workouts.length} workouts in next 7 days`); for (const workout of workouts.slice(0, 3)) { const date = new Date(workout.date).toLocaleDateString(); console.log(` ${date}: ${workout.name}`); if (workout.discipline) console.log(` Discipline: ${workout.discipline}`); if (workout.duration_human) console.log(` Duration: ${workout.duration_human}`); if (workout.expected_tss) console.log(` TSS: ${workout.expected_tss}`); } } catch (error) { console.error(' ❌ TrainerRoad error:', error instanceof Error ? error.message : error); } } async function main() { console.log('╔════════════════════════════════════════╗'); console.log('β•‘ Domestique Client Integration β•‘'); console.log('β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•'); await testWhoop(); await testIntervals(); await testTrainerRoad(); console.log('\n✨ Done!\n'); process.exit(0); } main().catch((error) => { console.error('Unexpected error:', error); process.exit(1); });

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/gesteves/domestique'

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