63 lines
1.8 KiB
TypeScript
63 lines
1.8 KiB
TypeScript
import { NextResponse } from 'next/server';
|
|
import { db, nodes } from '@/db';
|
|
import { eq } from 'drizzle-orm';
|
|
|
|
export const dynamic = 'force-dynamic';
|
|
|
|
export async function GET() {
|
|
try {
|
|
if (!db) {
|
|
return NextResponse.json({ error: 'Database not available' }, { status: 500 });
|
|
}
|
|
|
|
const domain = process.env.NEXT_PUBLIC_NODE_DOMAIN || 'localhost:43821';
|
|
|
|
// 1. Try exact match
|
|
let node = await db.query.nodes.findFirst({
|
|
where: { domain: domain },
|
|
});
|
|
|
|
// 2. Fallback: If not found, check if there is exactly ONE node in the system
|
|
if (!node) {
|
|
const allNodes = await db.query.nodes.findMany({ limit: 2 });
|
|
if (allNodes.length === 1) {
|
|
node = allNodes[0];
|
|
}
|
|
}
|
|
|
|
// Check if we have favicon data
|
|
if (!node?.faviconData) {
|
|
return NextResponse.json({ error: 'Favicon not found' }, { status: 404 });
|
|
}
|
|
|
|
// Parse the data URL to extract MIME type and base64 data
|
|
const dataUrl = node.faviconData;
|
|
const match = dataUrl.match(/^data:([^;]+);base64,(.+)$/);
|
|
|
|
if (!match) {
|
|
// If not a proper data URL, try to serve as-is (backward compatibility)
|
|
return NextResponse.json({ error: 'Invalid favicon data' }, { status: 500 });
|
|
}
|
|
|
|
const mimeType = match[1];
|
|
const base64Data = match[2];
|
|
const buffer = Buffer.from(base64Data, 'base64');
|
|
|
|
// Return the image with proper headers
|
|
return new NextResponse(buffer, {
|
|
status: 200,
|
|
headers: {
|
|
'Content-Type': mimeType,
|
|
'Cache-Control': 'no-store, max-age=0',
|
|
Pragma: 'no-cache',
|
|
Expires: '0',
|
|
'Content-Length': buffer.length.toString(),
|
|
},
|
|
});
|
|
|
|
} catch (error) {
|
|
console.error('Favicon serve error:', error);
|
|
return NextResponse.json({ error: 'Failed to serve favicon' }, { status: 500 });
|
|
}
|
|
}
|