TypeScript 97.5%
SQL 1.4%
Python 0.8%
1"use server";23import { PLAN_LIMITS, fetchRequestSchema, normalizePlan, type FetchResponseBody } from "@fetcha/core";4import { getWorkspace } from "@/lib/session";5import { internalApi, InternalApiError } from "@/lib/api";67export interface PlaygroundError {8 code: string;9 message: string;10 requestId: string | null;11 details?: Record<string, unknown>;12}1314export type PlaygroundResult = { ok: true; data: FetchResponseBody; requestId: string } | { ok: false; error: PlaygroundError };1516/**17 * Run a request from the dashboard Playground. Validates with the shared schema, clamps the timeout18 * to the plan maximum and forwards to the API service (source = "playground", scoped to the current19 * project). Never throws to the client: every failure is returned as `{ ok: false, error }`.20 */21export async function runPlayground(input: unknown): Promise<PlaygroundResult> {22 // Outside the try/catch: an unauthenticated caller must still be redirected to /login.23 const ws = await getWorkspace();2425 try {26 const parsed = fetchRequestSchema.safeParse(input);27 if (!parsed.success) {28 const issues = parsed.error.issues.map((i) => ({ path: i.path.join("."), message: i.message }));29 const first = issues[0];30 return {31 ok: false,32 error: {33 code: "INVALID_REQUEST",34 message: first ? `${first.path ? `${first.path}: ` : ""}${first.message}` : "The request is invalid.",35 requestId: null,36 details: { issues },37 },38 };39 }4041 const request = parsed.data;42 const limits = PLAN_LIMITS[normalizePlan(ws.organization.plan)];43 if (request.timeout > limits.max_timeout_ms) request.timeout = limits.max_timeout_ms;44 if (request.retries !== undefined && request.retries > limits.max_retries) request.retries = limits.max_retries;45 if (request.network !== "auto" && !limits.networks.includes(request.network)) {46 return {47 ok: false,48 error: { code: "NETWORK_UNAVAILABLE", message: `The "${request.network}" network is not included in the ${limits.label} plan.`, requestId: null },49 };50 }51 const data = (await internalApi.playgroundFetch(ws.project.id, ws.user.id, request)) as FetchResponseBody;52 if (!data || typeof data !== "object" || typeof data.request_id !== "string") {53 return { ok: false, error: { code: "INTERNAL_ERROR", message: "The API returned an unexpected response.", requestId: null } };54 }55 return { ok: true, data, requestId: data.request_id };56 } catch (e) {57 if (e instanceof InternalApiError) {58 return { ok: false, error: { code: e.code, message: e.message, requestId: e.requestId, details: e.details } };59 }60 console.error("[playground] unexpected error", e);61 return { ok: false, error: { code: "INTERNAL_ERROR", message: "An internal error occurred. Please try again.", requestId: null } };62 }63}64