TypeScript 97.4%
SQL 1%
JavaScript 0.9%
CSS 0.6%
1import { z } from "zod";2import { withUser, parseBody, json, ApiError } from "@/lib/api";3import { listConnections, upsertConnection, deleteConnection, validateConnection } from "@/lib/providers/keys";4import { syncProvider } from "@/lib/ai/registry";5import { getDecryptedKey } from "@/lib/providers/keys";6import { isProviderId } from "@/lib/ai/core/types";7import { LIMITS } from "@/lib/rate-limit";89export const dynamic = "force-dynamic";1011export const GET = withUser(async ({ user }) => json({ connections: await listConnections(user.id) }));1213const putSchema = z.object({ provider: z.string(), apiKey: z.string().min(8).max(512) });1415/** PUT /api/providers — add or replace a key (validated against the provider, then encrypted). */16export const PUT = withUser(17 async ({ req, user, ip }) => {18 const body = await parseBody(req, putSchema, 8_000);19 if (!isProviderId(body.provider)) throw new ApiError(400, "Unknown provider");20 const result = await upsertConnection(user.id, body.provider, body.apiKey, { validate: true, ip });21 // Refresh this provider's model list with the new key (best-effort, non-blocking for the UI).22 if (result.ok) {23 const key = await getDecryptedKey(user.id, body.provider);24 if (key) void syncProvider(body.provider, key, "user").catch(() => {});25 }26 const connections = await listConnections(user.id);27 return json({ ...result, connections });28 },29 { limit: { ...LIMITS.keySave, key: "provider-save" } },30);3132export const POST = withUser(33 async ({ req, user }) => {34 const body = await parseBody(req, z.object({ action: z.literal("validate"), provider: z.string() }));35 if (!isProviderId(body.provider)) throw new ApiError(400, "Unknown provider");36 const res = await validateConnection(user.id, body.provider);37 if (res.ok) {38 const key = await getDecryptedKey(user.id, body.provider);39 if (key) void syncProvider(body.provider, key, "user").catch(() => {});40 }41 return json({ ok: res.ok, error: res.error, modelsAvailable: res.modelsAvailable, latencyMs: res.latencyMs, connections: await listConnections(user.id) });42 },43 { limit: { ...LIMITS.keyValidate, key: "provider-validate" } },44);4546export const DELETE = withUser(async ({ req, user, ip }) => {47 const provider = new URL(req.url).searchParams.get("provider");48 if (!provider || !isProviderId(provider)) throw new ApiError(400, "Unknown provider");49 await deleteConnection(user.id, provider, ip);50 return json({ connections: await listConnections(user.id) });51});52