import { createServerFn } from "@tanstack/react-start"; import { z } from "zod"; import { requireSupabaseAuth } from "@/integrations/supabase/auth-middleware"; // Publishes a caller-owned CodeHub project to Cloudflare Pages (one Pages project per CodeHub project). export const deployCodeProject = createServerFn({ method: "POST" }) .middleware([requireSupabaseAuth]) .validator((input: unknown) => z.object({ projectId: z.string().uuid() }).parse(input)) .handler(async ({ data, context }) => { const { data: project, error } = await context.supabase.from("code_projects").select("id, files").eq("id", data.projectId).maybeSingle(); if (error || !project) return { error: "That project wasn't found in your account." } as const; const { validateFiles } = await import("./codehub"); const files = (project.files ?? {}) as Record; if (!files["index.html"]) return { error: "Add an index.html file at the top level before publishing." } as const; const invalid = validateFiles(files); if (invalid) return { error: invalid } as const; const { deployToPages } = await import("./cloudflare-deploy.server"); const result = await deployToPages(`hub-${project.id.replace(/-/g, "").slice(0, 12)}`, files); if (!("url" in result) || !result.url) return { error: "error" in result && result.error ? result.error : "Publishing failed." } as const; await context.supabase.from("code_projects").update({ deployed_url: result.url }).eq("id", project.id); return { url: result.url } as const; }); const domainSchema = z.string().trim().toLowerCase().max(253) .transform((d) => d.replace(/^https?:\/\//, "").replace(/\/.*$/, "")) .refine((d) => /^(?!-)([a-z0-9-]{1,63}\.)+[a-z]{2,63}$/.test(d), "Enter a domain like mywebsite.com"); // Connects a custom domain to a caller-owned published site (Echo session or CodeHub project). export const connectCustomDomain = createServerFn({ method: "POST" }) .middleware([requireSupabaseAuth]) .validator((input: unknown) => z.object({ kind: z.enum(["echo", "hub"]), id: z.string().uuid(), domain: domainSchema }).parse(input)) .handler(async ({ data, context }) => { let pagesName: string; if (data.kind === "hub") { const { data: p } = await context.supabase.from("code_projects").select("id, deployed_url").eq("id", data.id).maybeSingle(); if (!p) return { error: "That project wasn't found in your account." } as const; if (!p.deployed_url) return { error: "Publish this project first, then connect your domain." } as const; pagesName = `hub-${p.id.replace(/-/g, "").slice(0, 12)}`; } else { const { data: b } = await context.supabase.from("voice_builds").select("session_id").eq("session_id", data.id).not("deployed_url", "is", null).limit(1).maybeSingle(); if (!b) return { error: "Publish this website first, then connect your domain." } as const; pagesName = `echo-${b.session_id.replace(/-/g, "").slice(0, 12)}`; } const { connectPagesDomain } = await import("./cloudflare-deploy.server"); return connectPagesDomain(pagesName, data.domain); });