File: /www/wwwroot/oura.mlazu.com/20260313/server.ts
import express from 'express';
import { createServer as createViteServer } from 'vite';
import path from 'path';
import axios from 'axios';
import dotenv from 'dotenv';
dotenv.config();
async function startServer() {
const app = express();
const PORT = 3000;
app.use(express.json());
// Hardcoded Oura PAT for direct access
const OURA_PAT = "BZH3BQQWD4XINFO3Y7AW7O2HXKHLFEZH";
// API Routes
app.get('/api/user/status', (req, res) => {
res.json({
connected: true,
isPat: true
});
});
app.get('/api/oura/data', async (req, res) => {
const token = OURA_PAT;
try {
const today = new Date().toISOString().split('T')[0];
const sevenDaysAgo = new Date(Date.now() - 7 * 86400000).toISOString().split('T')[0];
// Fetch readiness, sleep summary, sleep periods, and activity for the last 7 days
const [readiness, dailySleep, sleepPeriods, activity] = await Promise.all([
axios.get(`https://api.ouraring.com/v2/usercollection/daily_readiness?start_date=${sevenDaysAgo}&end_date=${today}`, {
headers: { Authorization: `Bearer ${token}` }
}),
axios.get(`https://api.ouraring.com/v2/usercollection/daily_sleep?start_date=${sevenDaysAgo}&end_date=${today}`, {
headers: { Authorization: `Bearer ${token}` }
}),
axios.get(`https://api.ouraring.com/v2/usercollection/sleep?start_date=${sevenDaysAgo}&end_date=${today}`, {
headers: { Authorization: `Bearer ${token}` }
}),
axios.get(`https://api.ouraring.com/v2/usercollection/daily_activity?start_date=${sevenDaysAgo}&end_date=${today}`, {
headers: { Authorization: `Bearer ${token}` }
})
]);
// Merge sleep period data (like average_hrv) into daily sleep summary efficiently
const periodMap = new Map(sleepPeriods.data.data.map((p: any) => [p.day, p]));
const mergedSleep = dailySleep.data.data.map((ds: any) => {
const period = periodMap.get(ds.day) || {};
return { ...(ds as object), ...(period as object) };
});
res.json({
readiness: readiness.data.data,
sleep: mergedSleep,
activity: activity.data.data
});
} catch (error: any) {
console.error('Oura API Error:', error.response?.data || error.message);
res.status(500).json({ error: 'Failed to fetch Oura data' });
}
});
app.post('/api/auth/logout', (req, res) => {
res.json({ success: true });
});
// Vite middleware for development
if (process.env.NODE_ENV !== 'production') {
const vite = await createViteServer({
server: { middlewareMode: true },
appType: 'spa',
});
app.use(vite.middlewares);
} else {
const distPath = path.join(process.cwd(), 'dist');
app.use(express.static(distPath));
app.get('*', (req, res) => {
res.sendFile(path.join(distPath, 'index.html'));
});
}
app.listen(PORT, '0.0.0.0', () => {
console.log(`Server running on http://localhost:${PORT}`);
});
}
startServer();