import { ImageResponse } from 'next/og'; import type { NextRequest } from 'next/server'; import { Wallpaper } from '@/components/brand/og'; import { defaultModeFor, GRAPH_MODES, isGraphMode } from '@/components/graph/modes'; import { api, apiD3, safe } from '@/lib/api'; import { fmtInt } from '@/lib/format'; import { typeLabel } from '@/lib/site'; export const runtime = 'nodejs'; export const revalidate = 3600; /** Dynamic Open Graph image for /graph?node=&mode=&depth= (query routes cannot use the opengraph-image convention). */ export async function GET(req: NextRequest): Promise { const sp = req.nextUrl.searchParams; const node = sp.get('node'); const size = { width: 1200, height: 630 }; const d = node ? await safe(api.entity(node)) : null; if (!d) return new ImageResponse(, size); const mode = isGraphMode(sp.get('mode')) ? (sp.get('mode') as ReturnType) : defaultModeFor(d.entity_type); const depth: 1 | 2 = sp.get('depth') === '2' ? 2 : 1; const g = await safe(apiD3.graphExplore(d.slug, mode, depth, 150)); const label = GRAPH_MODES.find((m) => m.mode === mode)?.label ?? 'Graph'; const counters: [string, string][] = g ? [['Nodes', fmtInt(g.counts?.nodes ?? g.nodes.length)], ['Edges', fmtInt(g.counts?.edges ?? g.edges.length)], ['Depth', String(g.depth)], ...(g.truncated ? ([['Truncated', 'yes']] as [string, string][]) : [])] : []; return new ImageResponse(, size); }