deckhearth/api/test-db.ts
Randall Stillwell 323d6a3dd3 Add health check and improve database test endpoint
🔧 Improvements:
- Add /api/health endpoint for basic API functionality testing
- Improve /api/test-db with timeout handling and better error reporting
- Add environment variable checks before database operations
- Add connection timeouts to prevent function timeouts
- Better error handling and logging

🧪 Testing Endpoints:
- /api/health - Simple API health check (no DB required)
- /api/test-db - Database connectivity test with timeout protection

These changes should help identify whether the issue is with API routing, environment variables, or database connectivity.
2025-07-22 06:36:13 -05:00

111 lines
No EOL
3.3 KiB
TypeScript

import { NextRequest, NextResponse } from 'next/server';
import { Pool } from 'pg';
export default async function handler(req: NextRequest) {
if (req.method !== 'GET') {
return new NextResponse(JSON.stringify({ error: 'Method not allowed' }), {
status: 405,
headers: { 'Content-Type': 'application/json' },
});
}
// Check environment variables first
if (!process.env.DATABASE_URL) {
return new NextResponse(JSON.stringify({
success: false,
error: 'DATABASE_URL environment variable not set',
environment: process.env.NODE_ENV || 'unknown'
}), {
status: 500,
headers: { 'Content-Type': 'application/json' },
});
}
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
ssl: process.env.NODE_ENV === 'production' ? { rejectUnauthorized: false } : false,
connectionTimeoutMillis: 10000, // 10 seconds
query_timeout: 10000, // 10 seconds
});
let client: any;
try {
console.log('Testing database connection...');
// Set a timeout for the entire operation
const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => reject(new Error('Database operation timed out')), 15000);
});
const dbOperation = async () => {
client = await pool.connect();
// Test basic connection
const result = await client.query('SELECT NOW() as current_time, version() as postgres_version');
// Check if users table exists
const tableCheck = await client.query(`
SELECT EXISTS (
SELECT FROM information_schema.tables
WHERE table_schema = 'public'
AND table_name = 'users'
) as users_table_exists;
`);
// Check if cards table exists
const cardsCheck = await client.query(`
SELECT EXISTS (
SELECT FROM information_schema.tables
WHERE table_schema = 'public'
AND table_name = 'cards'
) as cards_table_exists;
`);
return {
current_time: result.rows[0].current_time,
postgres_version: result.rows[0].postgres_version,
users_table_exists: tableCheck.rows[0].users_table_exists,
cards_table_exists: cardsCheck.rows[0].cards_table_exists
};
};
const dbResult = await Promise.race([dbOperation(), timeoutPromise]);
return new NextResponse(JSON.stringify({
success: true,
message: 'Database connection successful',
database_info: dbResult
}), {
status: 200,
headers: { 'Content-Type': 'application/json' },
});
} catch (error) {
console.error('Database connection failed:', error);
return new NextResponse(JSON.stringify({
success: false,
error: 'Database connection failed',
details: (error as Error).message,
database_url_exists: !!process.env.DATABASE_URL,
database_url_preview: process.env.DATABASE_URL ?
process.env.DATABASE_URL.substring(0, 20) + '...' : 'not set'
}), {
status: 500,
headers: { 'Content-Type': 'application/json' },
});
} finally {
if (client) {
try {
client.release();
} catch (e) {
console.error('Error releasing client:', e);
}
}
try {
await pool.end();
} catch (e) {
console.error('Error ending pool:', e);
}
}
}