import { useState } from "react"; import { useSearchParams } from "react-router-dom"; import { useKv, useKvNamespaces } from "../api/hooks.js"; import { formatTime } from "../lib/format.jsx"; const PAGE_SIZE = 50; function previewValue(value) { const json = JSON.stringify(value); if (json == null) return "—"; if (json.length <= 120) return json; return `${json.slice(0, 120)}…`; } export function KvPage() { const [params, setParams] = useSearchParams(); const namespace = params.get("namespace") || ""; const q = params.get("q") || ""; const offset = Math.max(Number(params.get("offset")) || 0, 0); const [expanded, setExpanded] = useState(null); const { data: namespaces = [] } = useKvNamespaces(); const { data, isLoading } = useKv({ namespace: namespace || undefined, q: q || undefined, limit: PAGE_SIZE, offset, }); const items = data?.items ?? []; const total = data?.total ?? 0; const limit = data?.limit ?? PAGE_SIZE; function update(key, value, resetOffset = true) { const next = new URLSearchParams(params); if (value) next.set(key, value); else next.delete(key); if (resetOffset && key !== "offset") next.delete("offset"); setParams(next); setExpanded(null); } function rowId(item) { return `${item.namespace}\0${item.key}`; } return (
No KV entries.
) : ( <>| Namespace | Key | Value | Updated | Expires |
|---|---|---|---|---|
| {item.namespace} | {item.key} |
{open ? (
{JSON.stringify(item.value, null, 2)}
) : (
{previewValue(item.value)}
)}
|
{formatTime(item.updatedAt)} | {item.expiresAt ? formatTime(item.expiresAt) : "—"} |