SPB Git forge

spb/fetcha

Public
11commits 1branches 0releases
1.5 MBsize
maindefault branch
16 days agolast push
TypeScript 97.5% SQL 1.4% Python 0.8%
2.8 KB · 64 lines typescript
Raw Blame History
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