import { Handle, Position } from '@xyflow/react' const METHOD_COLORS = { GET: { bg: '#0d4429', color: '#4ade80' }, POST: { bg: '#172554', color: '#60a5fa' }, PUT: { bg: '#451a03', color: '#fb923c' }, PATCH: { bg: '#2e1065', color: '#c084fc' }, DELETE: { bg: '#450a0a', color: '#f87171' }, OPTIONS: { bg: '#1c1917', color: '#a8a29e' }, HEAD: { bg: '#1c1917', color: '#a8a29e' }, } // Handles for LR layout: parent flows in from the LEFT, children exit to the RIGHT const TARGET_HANDLE = const SOURCE_HANDLE = /** * Unified handler node — three modes: ABSTRACT, CONCRETE, LAMBDA. * Handles are Left (in) / Right (out) for Left-to-Right DAG layout. */ export default function HandlerNode({ data, selected }) { // ── ABSTRACT ────────────────────────────────────────────────────────── if (data.isAbstract) { return (
{TARGET_HANDLE} {SOURCE_HANDLE}
ABSTRACT
{data.name}
) } // ── LAMBDA ──────────────────────────────────────────────────────────── if (data.isLambda) { const method = data.method || 'GET' const path = data.path || '/' const m = METHOD_COLORS[method] || METHOD_COLORS.OPTIONS const pathHtml = path.replace(/\{([^}]+)\}/g, '{$1}') return (
{TARGET_HANDLE} {SOURCE_HANDLE}
LAMBDA
{method}
{data.middleware?.length > 0 && (
{data.middleware.map(mw => ( {mw} ))}
)}
) } // ── CONCRETE ────────────────────────────────────────────────────────── return (
{TARGET_HANDLE} {SOURCE_HANDLE} {/* Header */}
HANDLER
{data.name}
{/* Routes */}
0 ? 8 : 0 }}> {data.routes?.map((route, i) => { const m = METHOD_COLORS[route.method] || METHOD_COLORS.OPTIONS const pathHtml = (route.path || '/').replace( /\{([^}]+)\}/g, '{$1}' ) return (
{route.method}
) })}
{/* Middleware */} {data.middleware?.length > 0 && (
{data.middleware.map(mw => ( {mw} ))}
)}
) }