- Add /api/migrate endpoint to populate Neon database with existing JSON data - Update /api/v1/cards/ to query Neon database instead of JSON file - Update /api/v1/cards/[id] to fetch single cards from Neon - Add proper error handling and development debugging - Maintain backward compatibility with existing API interface - Ready to migrate card data to PostgreSQL
114 lines
3 KiB
TypeScript
114 lines
3 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server'
|
|
import { neon } from '@neondatabase/serverless'
|
|
|
|
// Initialize Neon client
|
|
const sql = neon(process.env.DATABASE_URL!)
|
|
|
|
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 })
|
|
}
|
|
|
|
if (req.method !== 'GET') {
|
|
return new NextResponse(JSON.stringify({ error: 'Method not allowed' }), {
|
|
status: 405,
|
|
headers: {
|
|
...headers,
|
|
'Content-Type': 'application/json',
|
|
},
|
|
})
|
|
}
|
|
|
|
try {
|
|
// Extract card ID from URL
|
|
const url = new URL(req.url)
|
|
const pathParts = url.pathname.split('/')
|
|
const cardId = pathParts[pathParts.length - 1]
|
|
|
|
if (!cardId || isNaN(parseInt(cardId))) {
|
|
return new NextResponse(JSON.stringify({ error: 'Invalid card ID' }), {
|
|
status: 400,
|
|
headers: {
|
|
...headers,
|
|
'Content-Type': 'application/json',
|
|
},
|
|
})
|
|
}
|
|
|
|
// Query the database for the specific card
|
|
const result = await sql`SELECT * FROM cards WHERE id = ${parseInt(cardId)}`
|
|
|
|
if (result.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[0],
|
|
colors: result[0].colors ? (typeof result[0].colors === 'string' ? JSON.parse(result[0].colors) : result[0].colors) : null,
|
|
artwork_crop_coords: result[0].artwork_crop_coords ?
|
|
(typeof result[0].artwork_crop_coords === 'string' ? JSON.parse(result[0].artwork_crop_coords) : result[0].artwork_crop_coords) : null
|
|
}
|
|
|
|
return new NextResponse(JSON.stringify(card), {
|
|
status: 200,
|
|
headers: {
|
|
...headers,
|
|
'Content-Type': 'application/json',
|
|
},
|
|
})
|
|
|
|
} catch (error) {
|
|
console.error('API Error:', error)
|
|
return new NextResponse(JSON.stringify({
|
|
error: 'Internal server error',
|
|
details: process.env.NODE_ENV === 'development' ? error.message : undefined
|
|
}), {
|
|
status: 500,
|
|
headers: {
|
|
...headers,
|
|
'Content-Type': 'application/json',
|
|
},
|
|
})
|
|
}
|
|
}
|