2025-07-21 14:53:06 -04:00
|
|
|
import { NextRequest, NextResponse } from 'next/server'
|
2025-07-21 17:08:45 -04:00
|
|
|
import { Pool } from 'pg'
|
2025-07-21 16:46:58 -04:00
|
|
|
|
2025-07-21 17:08:45 -04:00
|
|
|
// Create PostgreSQL connection pool
|
|
|
|
|
const pool = new Pool({
|
|
|
|
|
connectionString: process.env.DATABASE_URL,
|
|
|
|
|
ssl: process.env.NODE_ENV === 'production' ? { rejectUnauthorized: false } : false,
|
|
|
|
|
})
|
2025-07-21 14:53:06 -04:00
|
|
|
|
|
|
|
|
interface Card {
|
|
|
|
|
id: number
|
|
|
|
|
name: string
|
|
|
|
|
set_name?: string
|
|
|
|
|
set_code?: string
|
|
|
|
|
card_number?: string
|
|
|
|
|
rarity?: string
|
|
|
|
|
game: string
|
|
|
|
|
mana_cost?: string
|
|
|
|
|
cmc?: number
|
|
|
|
|
card_type?: string
|
|
|
|
|
colors?: string[]
|
|
|
|
|
oracle_text?: string
|
|
|
|
|
flavor_text?: string
|
|
|
|
|
power?: string
|
|
|
|
|
toughness?: string
|
|
|
|
|
artist?: string
|
|
|
|
|
image_url?: string
|
|
|
|
|
stock_image_url?: string
|
|
|
|
|
artwork_crop_coords?: any
|
|
|
|
|
current_price?: number
|
|
|
|
|
market_price?: number
|
|
|
|
|
verified: boolean
|
|
|
|
|
created_at?: string
|
|
|
|
|
updated_at?: string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default async function handler(req: NextRequest) {
|
|
|
|
|
// Enable CORS
|
|
|
|
|
const headers = {
|
|
|
|
|
'Access-Control-Allow-Origin': '*',
|
|
|
|
|
'Access-Control-Allow-Methods': 'GET, OPTIONS',
|
|
|
|
|
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (req.method === 'OPTIONS') {
|
|
|
|
|
return new NextResponse(null, { status: 200, headers })
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-21 16:46:58 -04:00
|
|
|
if (req.method !== 'GET') {
|
|
|
|
|
return new NextResponse(JSON.stringify({ error: 'Method not allowed' }), {
|
|
|
|
|
status: 405,
|
|
|
|
|
headers: {
|
|
|
|
|
...headers,
|
|
|
|
|
'Content-Type': 'application/json',
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-21 14:53:06 -04:00
|
|
|
try {
|
2025-07-21 16:46:58 -04:00
|
|
|
// Extract card ID from URL
|
2025-07-21 14:53:06 -04:00
|
|
|
const url = new URL(req.url)
|
2025-07-21 16:46:58 -04:00
|
|
|
const pathParts = url.pathname.split('/')
|
|
|
|
|
const cardId = pathParts[pathParts.length - 1]
|
2025-07-21 14:53:06 -04:00
|
|
|
|
2025-07-21 16:46:58 -04:00
|
|
|
if (!cardId || isNaN(parseInt(cardId))) {
|
2025-07-21 14:53:06 -04:00
|
|
|
return new NextResponse(JSON.stringify({ error: 'Invalid card ID' }), {
|
|
|
|
|
status: 400,
|
|
|
|
|
headers: {
|
|
|
|
|
...headers,
|
|
|
|
|
'Content-Type': 'application/json',
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-21 16:46:58 -04:00
|
|
|
// Query the database for the specific card
|
2025-07-21 17:08:45 -04:00
|
|
|
const client = await pool.connect()
|
|
|
|
|
try {
|
|
|
|
|
const result = await client.query('SELECT * FROM cards WHERE id = $1', [parseInt(cardId)])
|
2025-07-21 14:53:06 -04:00
|
|
|
|
2025-07-21 17:08:45 -04:00
|
|
|
if (result.rows.length === 0) {
|
|
|
|
|
return new NextResponse(JSON.stringify({ error: 'Card not found' }), {
|
|
|
|
|
status: 404,
|
|
|
|
|
headers: {
|
|
|
|
|
...headers,
|
|
|
|
|
'Content-Type': 'application/json',
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Transform the result to match expected format
|
|
|
|
|
const card = {
|
|
|
|
|
...result.rows[0],
|
|
|
|
|
colors: result.rows[0].colors ? (typeof result.rows[0].colors === 'string' ? JSON.parse(result.rows[0].colors) : result.rows[0].colors) : null,
|
|
|
|
|
artwork_crop_coords: result.rows[0].artwork_crop_coords ?
|
|
|
|
|
(typeof result.rows[0].artwork_crop_coords === 'string' ? JSON.parse(result.rows[0].artwork_crop_coords) : result.rows[0].artwork_crop_coords) : null
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return new NextResponse(JSON.stringify(card), {
|
|
|
|
|
status: 200,
|
2025-07-21 14:53:06 -04:00
|
|
|
headers: {
|
|
|
|
|
...headers,
|
|
|
|
|
'Content-Type': 'application/json',
|
|
|
|
|
},
|
|
|
|
|
})
|
2025-07-21 17:08:45 -04:00
|
|
|
} finally {
|
|
|
|
|
client.release()
|
2025-07-21 14:53:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('API Error:', error)
|
2025-07-21 16:46:58 -04:00
|
|
|
return new NextResponse(JSON.stringify({
|
|
|
|
|
error: 'Internal server error',
|
2025-07-21 16:56:26 -04:00
|
|
|
details: process.env.NODE_ENV === 'development' ? (error as Error).message : undefined
|
2025-07-21 16:46:58 -04:00
|
|
|
}), {
|
2025-07-21 14:53:06 -04:00
|
|
|
status: 500,
|
|
|
|
|
headers: {
|
|
|
|
|
...headers,
|
|
|
|
|
'Content-Type': 'application/json',
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|