"use server"; import { PLAN_LIMITS, fetchRequestSchema, normalizePlan, type FetchResponseBody } from "@fetcha/core"; import { getWorkspace } from "@/lib/session"; import { internalApi, InternalApiError } from "@/lib/api"; export interface PlaygroundError { code: string; message: string; requestId: string | null; details?: Record; } export type PlaygroundResult = { ok: true; data: FetchResponseBody; requestId: string } | { ok: false; error: PlaygroundError }; /** * Run a request from the dashboard Playground. Validates with the shared schema, clamps the timeout * to the plan maximum and forwards to the API service (source = "playground", scoped to the current * project). Never throws to the client: every failure is returned as `{ ok: false, error }`. */ export async function runPlayground(input: unknown): Promise { // Outside the try/catch: an unauthenticated caller must still be redirected to /login. const ws = await getWorkspace(); try { const parsed = fetchRequestSchema.safeParse(input); if (!parsed.success) { const issues = parsed.error.issues.map((i) => ({ path: i.path.join("."), message: i.message })); const first = issues[0]; return { ok: false, error: { code: "INVALID_REQUEST", message: first ? `${first.path ? `${first.path}: ` : ""}${first.message}` : "The request is invalid.", requestId: null, details: { issues }, }, }; } const request = parsed.data; const limits = PLAN_LIMITS[normalizePlan(ws.organization.plan)]; if (request.timeout > limits.max_timeout_ms) request.timeout = limits.max_timeout_ms; if (request.retries !== undefined && request.retries > limits.max_retries) request.retries = limits.max_retries; if (request.network !== "auto" && !limits.networks.includes(request.network)) { return { ok: false, error: { code: "NETWORK_UNAVAILABLE", message: `The "${request.network}" network is not included in the ${limits.label} plan.`, requestId: null }, }; } const data = (await internalApi.playgroundFetch(ws.project.id, ws.user.id, request)) as FetchResponseBody; if (!data || typeof data !== "object" || typeof data.request_id !== "string") { return { ok: false, error: { code: "INTERNAL_ERROR", message: "The API returned an unexpected response.", requestId: null } }; } return { ok: true, data, requestId: data.request_id }; } catch (e) { if (e instanceof InternalApiError) { return { ok: false, error: { code: e.code, message: e.message, requestId: e.requestId, details: e.details } }; } console.error("[playground] unexpected error", e); return { ok: false, error: { code: "INTERNAL_ERROR", message: "An internal error occurred. Please try again.", requestId: null } }; } }