import { events } from "@minecraft-account-manager/database"; import { desc, inArray } from "drizzle-orm"; import Link from "next/link"; import { db } from "@/lib/database"; import { eventCategory, eventCategoryValues, normalizeEventCategory, normalizeSelectedEventTypes } from "@/lib/event-filters"; import { eventIpSummary } from "@/lib/event-ip-summary"; export const dynamic = "force-dynamic"; function values(value: string | string[] | undefined) { return Array.isArray(value) ? value : value ? [value] : []; } export default async function EventsPage({ searchParams, }: { searchParams: Promise>; }) { const query = await searchParams; const typeRows = await db.select({ type: events.type }).from(events).groupBy(events.type).orderBy(events.type); const availableTypes = typeRows.map((row) => row.type); const category = normalizeEventCategory(values(query.category)[0]); const selectedTypes = normalizeSelectedEventTypes(query.type, availableTypes); const categoryTypes = category === "all" ? availableTypes : availableTypes.filter((type) => eventCategory(type) === category); const filteredTypes = selectedTypes.length ? selectedTypes.filter((type) => categoryTypes.includes(type)) : categoryTypes; const recentEvents = filteredTypes.length ? await db.select().from(events).where(inArray(events.type, filteredTypes)).orderBy(desc(events.time)).limit(100) : []; return (

CloudEvents ledger

Event explorer

Filter the immutable audit ledger, then open an event to inspect its complete CloudEvents envelope and data.

Event types
0}> {selectedTypes.length ? `${selectedTypes.length} selected` : "All types in this view"}
{availableTypes.map((type) => ( ))}
Clear filters

Showing {recentEvents.length} most recent matching events

{recentEvents.map((event) => { const ip = eventIpSummary(event.data); return ( ); })} {!recentEvents.length && }
Filtered account manager events
TimeTypeSubjectIPNetwork
{event.type} {event.subject ?? "—"} {event.ipAddress ?? "—"}
{ip.classification ?? "—"}
{ip.location ?? "Location unavailable"}
No events match these filters.
); }