import { useT } from "@agent-native/core/client/i18n"; import { IconCheck, IconLoader2, IconDatabase, IconCloud, IconChevronRight, } from "@tabler/icons-react"; import { useState, useRef, useCallback } from "react"; import { Button } from "@/components/ui/button"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, } from "@/components/ui/dialog"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { cn } from "@/lib/utils"; interface CloudUpgradeProps { title?: string; description?: string; onClose?: () => void; } interface Provider { id: string; name?: string; nameKey?: string; descriptionKey: string; urlPrefix: string; needsAuthToken: boolean; steps: string[]; } const PROVIDERS: Provider[] = [ { id: "turso", name: "Turso", descriptionKey: "cloudUpgrade.providerDescriptions.turso", urlPrefix: "libsql://", needsAuthToken: true, steps: [ "Install CLI: curl -sSfL https://get.tur.so/install.sh | bash", "Sign up / login: turso auth login (opens browser)", "Create a database: turso db create my-app", "Copy the URL: turso db show my-app --url → starts with libsql://", "Create an auth token: turso db tokens create my-app → paste below", ], }, { id: "neon", name: "Neon", descriptionKey: "cloudUpgrade.providerDescriptions.neon", urlPrefix: "postgres://", needsAuthToken: false, steps: [ "Go to console.neon.tech and sign up or log in", 'Click "New Project" → pick a name and region → click Create', "On the project dashboard, find the Connection Details panel", 'Select "Connection string" tab → copy the postgres://... URL', "Paste the full connection string (includes password) below", ], }, { id: "supabase", name: "Supabase", descriptionKey: "cloudUpgrade.providerDescriptions.supabase", urlPrefix: "postgres://", needsAuthToken: false, steps: [ "Go to supabase.com/dashboard and sign up or log in", 'Click "New Project" → set a name and database password → click Create', "Wait for the project to finish provisioning (~30 seconds)", "Go to Project Settings → Database → Connection string", 'Select "URI" tab → copy the postgres://... string (replace [YOUR-PASSWORD] with your DB password)', ], }, { id: "d1", nameKey: "cloudUpgrade.providerNames.d1", descriptionKey: "cloudUpgrade.providerDescriptions.d1", urlPrefix: "d1://", needsAuthToken: true, steps: [ "Go to dash.cloudflare.com → Workers & Pages → D1 SQL Database", 'Click "Create" → name your database → click Create', "Copy the Database ID from the database overview page", "For the auth token: go to My Profile → API Tokens → Create Token", 'Select "Edit Cloudflare Workers" template → Create Token → copy it', "Paste as: d1:// with the API token below", ], }, ]; export function CloudUpgrade({ title, description, onClose, }: CloudUpgradeProps) { const t = useT(); const [selectedProvider, setSelectedProvider] = useState(null); const [dbUrl, setDbUrl] = useState(""); const [authToken, setAuthToken] = useState(""); const [status, setStatus] = useState< "idle" | "saving" | "polling" | "success" | "error" >("idle"); const [errorMsg, setErrorMsg] = useState(""); const connectingRef = useRef(false); const provider = PROVIDERS.find((p) => p.id === selectedProvider); const providerName = (provider: Provider) => provider.nameKey ? t(provider.nameKey) : (provider.name ?? provider.id); const handleConnect = useCallback(async () => { if (connectingRef.current) return; connectingRef.current = true; if (!dbUrl.trim()) { setErrorMsg( "Database settings are deployment-level. Configure DATABASE_URL with your host and redeploy the app.", ); setStatus("error"); connectingRef.current = false; return; } try { setStatus("error"); setErrorMsg(""); throw new Error( "Database settings are deployment-level. Configure DATABASE_URL and DATABASE_AUTH_TOKEN with your host, redeploy, then check sharing again.", ); } catch (e) { setErrorMsg( e instanceof Error ? e.message : t("cloudUpgrade.connectionFailed"), ); setStatus("error"); } finally { connectingRef.current = false; } }, [dbUrl, authToken, t]); const isConnecting = status === "saving" || status === "polling"; return ( !open && onClose?.()}>
{title ?? t("cloudUpgrade.sharePublicly")}
{description ?? t("cloudUpgrade.sharePubliclyDescription")}
{/* Provider selection */}
{PROVIDERS.map((p) => ( ))}
{/* Provider setup steps */} {provider && (

{t("cloudUpgrade.setupSteps")}

    {provider.steps.map((step, i) => (
  1. {step}
  2. ))}
)} {/* Credential inputs */}
setDbUrl(e.target.value)} disabled={isConnecting} className="text-sm" />
{(!provider || provider.needsAuthToken) && (
setAuthToken(e.target.value)} disabled={isConnecting} className="text-sm" />
)}
{/* Error message */} {status === "error" && errorMsg && (

{errorMsg}

)} {/* Success message */} {status === "success" && (
{t("cloudUpgrade.connectedReloading")}
)} {/* Connect button */}
); }