import { useMutation, useQuery } from "@tanstack/react-query"; import Ansi from "ansi-to-react"; import { createId } from "@paralleldrive/cuid2"; import { useProjectContext } from "../context/project"; import { api } from "~/lib/api"; import Spinner from "~/components/ui/spinner"; import { useEffect, useState } from "react"; import { BASE_URL } from "~/lib/consts"; import { useSSE } from "~/hooks/useSSE"; import Divider from "~/components/ui/divider"; import { Button } from "~/components/ui/button"; import { FaCopy, FaExternalLinkAlt, FaTimes } from "react-icons/fa"; import ActionButton from "~/components/ui/action-button"; import { copy, getUrl } from "~/lib/utils"; const APIManager = () => { const { project } = useProjectContext(); const stats = useQuery({ queryKey: ["sandbox/stats", project.slug], queryFn: () => api(`/sandbox/${project.slug}/stats`), refetchInterval: 5000, retry: false, }); const start = useMutation({ mutationFn: () => api(`/sandbox/${project.slug}/start`, { method: "POST" }), onSuccess: () => stats.refetch(), }); useEffect(() => { if (stats.error && (stats.error as any).code === 404 && start.isIdle) { start.mutate(); } }, [stats.error, start.isIdle]); const onRetry = () => { if (start.isError) { start.mutate(); } else if (!stats.data) { stats.refetch(); } }; if (stats.isLoading || start.isPending) { return (

{start.isPending ? "Starting up development sandbox..." : "Please wait..."}

); } if (!stats.data || start.isError) { return (

Cannot load dev sandbox :(

{start.error?.message ? (

{start.error.message}

) : null}
); } return (

Output:

); }; const Actions = ({ stats }: any) => { const { project } = useProjectContext(); const restart = useMutation({ mutationFn: () => { return api(`/sandbox/${project.slug}/restart`, { method: "POST" }); }, onSuccess: () => stats.refetch(), }); const proxyUrl = `/api/sandbox/${project.slug}/proxy`; return (
copy(proxyUrl)} /> window.open(getUrl(proxyUrl), "_blank")} />
); }; const Stats = ({ data }: any) => { const { cpu, mem, memUsage, network, status, addr } = data; const [memUsed, memTotal] = memUsage || []; return (

Status: {status}

Address: {addr}

CPU: {cpu}%

Memory: {memUsed != null ? `${memUsed} / ${memTotal} (${mem}%)` : "-"}

); }; const Logs = () => { const { project } = useProjectContext(); const url = BASE_URL + `/api/sandbox/${project.slug}/logs`; const [logs, setLogs] = useState<{ log: string; time: number; id: string }[]>( [] ); function onData(data: any) { setLogs((l) => [ { ...data, log: data.log.replace(/[^\x00-\x7F]/g, ""), id: createId() }, ...l, ]); } useSSE(url, onData); useEffect(() => { setLogs([]); }, [url]); return (
setLogs([])} /> {logs.map((log) => (
{log.log.split("\n").map((line, idx) => ( {line} ))}
))}
); }; export default APIManager;