import { useCallback, useEffect, useState } from 'react' import { Network, Database, Boxes, RefreshCw, Loader2, DollarSign, ShoppingCart, Users, Activity, Layers, ShieldCheck, ShieldAlert, Server, HardDrive, Play, } from 'lucide-react' import { cn } from '../../lib/utils' type Bucket = { key: string; count: number; value?: number } export type SubTab = 'federated' | 'lake' | 'dictionary' const COLORS = ['#34d399', '#60a5fa', '#f472b6', '#fbbf24', '#a78bfa', '#22d3ee', '#fb7185'] function fmtNum(n?: number | string | null) { if (n == null) return '—' const v = typeof n === 'number' ? n : Number(n) if (Number.isNaN(v)) return String(n) if (Math.abs(v) >= 1e9) return `${(v / 1e9).toFixed(2)}B` if (Math.abs(v) >= 1e6) return `${(v / 1e6).toFixed(1)}M` if (Math.abs(v) >= 1e3) return `${(v / 1e3).toFixed(1)}K` return String(v) } const fmtMoney = (n?: number | string | null) => (n == null ? '—' : `€${fmtNum(n)}`) function Panel({ title, subtitle, icon: Icon, children }: { title: string; subtitle?: string; icon?: typeof Database; children: React.ReactNode }) { return (
{Icon && }

{title}

{subtitle && {subtitle}}
{children}
) } function BarsH({ data, valueKind, colorByIndex }: { data?: Bucket[]; valueKind?: 'money' | 'num'; colorByIndex?: boolean }) { const d = data || [] const useVal = valueKind != null const max = Math.max(1, ...d.map((x) => (useVal && x.value != null ? x.value : x.count))) if (!d.length) return

No data

return (
{d.map((x, i) => { const metric = useVal && x.value != null ? x.value : x.count const pct = Math.max(2, (metric / max) * 100) const label = useVal && x.value != null ? (valueKind === 'money' ? fmtMoney(x.value) : fmtNum(x.value)) : fmtNum(x.count) return (
{x.key ?? '—'}
{label}
) })}
) } function Donut({ data }: { data?: Bucket[] }) { const d = data || [] const total = d.reduce((s, x) => s + x.count, 0) || 1 let acc = 0 const r = 42 const c = 2 * Math.PI * r if (!d.length) return

No data

return (
{d.map((x, i) => { const dash = (x.count / total) * c const seg = acc += dash return seg })}
{d.slice(0, 7).map((x, i) => (
{x.key ?? '—'} {((x.count / total) * 100).toFixed(0)}%
))}
) } function Kpi({ icon: Icon, label, value, sub, accent }: { icon: typeof Users; label: string; value: string; sub?: string; accent: string }) { return (

{label}

{value}

{sub &&

{sub}

}
) } export function TrinoFederationView({ embedded = false, activeTab }: { embedded?: boolean; activeTab?: SubTab } = {}) { const [tabState, setTab] = useState('federated') const tab = embedded ? activeTab ?? 'federated' : tabState const [catalogs, setCatalogs] = useState(null) const [marquee, setMarquee] = useState(null) const [lake, setLake] = useState(null) const [dict, setDict] = useState(null) const [loading, setLoading] = useState(false) const [matRunning, setMatRunning] = useState(false) const loadFederated = useCallback(async () => { setLoading(true) try { const [c, m] = await Promise.all([ fetch('/api/federated/catalogs').then((r) => (r.ok ? r.json() : null)), fetch('/api/federated/marquee').then((r) => (r.ok ? r.json() : null)), ]) setCatalogs(c) setMarquee(m) } catch { /* */ } finally { setLoading(false) } }, []) const loadLake = useCallback(async () => { setLoading(true) try { const r = await fetch('/api/federated/lake') if (r.ok) setLake(await r.json()) const ms = await fetch('/api/federated/materialize/status').then((x) => (x.ok ? x.json() : null)) setMatRunning(!!ms?.running) } catch { /* */ } finally { setLoading(false) } }, []) const loadDict = useCallback(async () => { setLoading(true) try { const r = await fetch('/api/federated/dictionary') if (r.ok) setDict(await r.json()) } catch { /* */ } finally { setLoading(false) } }, []) useEffect(() => { if (tab === 'federated') loadFederated() else if (tab === 'lake') loadLake() else loadDict() }, [tab, loadFederated, loadLake, loadDict]) // poll marquee while it is computing useEffect(() => { if (tab !== 'federated' || !marquee?.running) return const t = setTimeout(loadFederated, 5000) return () => clearTimeout(t) }, [tab, marquee, loadFederated]) // poll materialize while running useEffect(() => { if (tab !== 'lake' || !matRunning) return const t = setTimeout(loadLake, 6000) return () => clearTimeout(t) }, [tab, matRunning, loadLake]) const rebuildLake = async () => { await fetch('/api/federated/materialize', { method: 'POST' }) setMatRunning(true) setTimeout(loadLake, 2000) } const refreshMarquee = async () => { await fetch('/api/federated/marquee/refresh', { method: 'POST' }) setTimeout(loadFederated, 1500) } const m = marquee?.marquee const totals = catalogs?.source_totals || {} const mxRows: any[] = m?.matrix?.rows || [] const mxMax = Math.max(1, ...mxRows.map((r) => Number(r.records) || 0)) const mxCatalogs: string[] = m?.matrix?.catalogs || ['postgres_sales', 'mysql_hr', 'mongodb_supplychain', 'cassandra_telemetry', 'iceberg'] const body = ( <> {/* ───────── FEDERATED ───────── */} {tab === 'federated' && ( <>
{(catalogs?.catalogs || []).map((c: any) => (
{c.label} {c.catalog} {c.desc} {c.rows != null && {fmtNum(c.rows)} rows}
))}

A single Trino query fanned out to five engines at once — relational, document, wide-column and the Hadoop lakehouse — no copies, no ETL.

{mxCatalogs.map((c) => ( {c} ))}
{m?.matrix?.sql}
{mxRows.length ? (
{mxRows.map((r, i) => { const isMoney = /revenue|value/i.test(r.metric_label || '') const pct = Math.max(3, (Number(r.records) / mxMax) * 100) const color = COLORS[i % COLORS.length] return ( ) })}
Source Catalog · dataset Records Headline metric
{r.source} {r.catalog} · {r.dataset}
{fmtNum(r.records)}
{isMoney ? fmtMoney(r.metric) : fmtNum(r.metric)} {r.metric_label}
) : (

{marquee?.running ? <> Federating across all databases… : 'No result yet — click re-run.'}

)}
{(m?.catalogs || ['postgres_sales', 'mysql_hr', 'mongodb_supplychain']).map((c: string) => ( {c} ))}
{marquee?.sql || m?.sql}
{marquee?.running && !m?.rows?.length ? (

Federating across live sources… (~1–2 min, cached afterwards)

) : m?.rows?.length ? (
{m.rows.map((r: any, i: number) => ( ))}
Region Orders Revenue HR events Supply events
{r.region} {fmtNum(r.orders)} {fmtMoney(r.revenue)} {fmtNum(r.hr_events)} {fmtNum(r.supply_events)}
{m.generated_at &&

as of {new Date(m.generated_at).toLocaleString()} · joined live across PostgreSQL + MySQL + MongoDB

}
) : (

{m?.error || 'No result yet — click re-run.'}

)}
)} {/* ───────── HADOOP LAKE ───────── */} {tab === 'lake' && ( <>

All federated business data materialized as external Iceberg tables on HDFS — queried live (fast).

{(lake?.tables || []).map((t: any) => (

{t.table}

{fmtNum(t.rows)}

))} {!lake?.tables?.length &&

No external tables yet — click “Rebuild external tables”.

}
)} {/* ───────── DICTIONARY ───────── */} {tab === 'dictionary' && ( <>

This is exactly what the assistant knows about your data — every column, its type, and whether it is masked or visible.

{(dict?.tables || []).map((t: any) => (

{t.engine} · {t.desc}

{t.columns.map((c: any) => ( {c.masked && } {!c.masked && c.pii && } {c.name} ))}
))}
)} {loading && !catalogs && !lake && !dict && (
)} ) if (embedded) return body return (

Trino Federation & Hadoop Lakehouse

One SQL engine over every source — federated business analytics, mirrored into Hadoop as external Iceberg tables

{([ { id: 'federated', label: 'Federated', icon: Network }, { id: 'lake', label: 'Hadoop Lake', icon: HardDrive }, { id: 'dictionary', label: 'Data Dictionary', icon: ShieldCheck }, ] as { id: SubTab; label: string; icon: typeof Network }[]).map(({ id, label, icon: Icon }) => ( ))}
{body}
) }