import { NextResponse } from "next/server"; import { createSupabaseRouteClient } from "@/lib/supabase/server"; import type { MediaAsset } from "@/types/media"; import { isConvexEnabled } from "@/lib/convex/enabled"; import { HttpError, requireAuthContext } from "@/lib/auth/authContext"; import { api } from "@/lib/convex/api"; import { getConvexHttpClient } from "@/lib/convex/server"; export const dynamic = "force-dynamic"; export async function GET(request: Request) { if (isConvexEnabled()) { let auth; try { auth = requireAuthContext(); } catch (err) { if (err instanceof HttpError) { return NextResponse.json({ error: "未登录" }, { status: err.status }); } return NextResponse.json({ error: "未登录" }, { status: 401 }); } const { searchParams } = new URL(request.url); const workspaceId = searchParams.get("workspaceId"); const limit = Number.parseInt(searchParams.get("limit") ?? "12", 10); const assetType = searchParams.get("assetType") ?? undefined; if (!workspaceId) { return NextResponse.json({ error: "缺少 workspaceId" }, { status: 400 }); } const client = getConvexHttpClient(); const items = await client.query(api.mediaAssets.listByWorkspace, { userId: auth.userId, workspaceId, assetType, includeDeleted: false, limit: Number.isNaN(limit) ? 12 : limit, }); return NextResponse.json({ items: (items ?? []) as MediaAsset[] }); } const supabase = await createSupabaseRouteClient(); const { data: { user }, error: authError, } = await supabase.auth.getUser(); if (authError || !user) { return NextResponse.json({ error: "未登录" }, { status: 401 }); } const { searchParams } = new URL(request.url); const workspaceId = searchParams.get("workspaceId"); const limit = Number.parseInt(searchParams.get("limit") ?? "12", 10); if (!workspaceId) { return NextResponse.json({ error: "缺少 workspaceId" }, { status: 400 }); } let query = supabase .from("media_assets") .select("*") .eq("workspace_id", workspaceId) .is("deleted_at", null) .order("created_at", { ascending: false }) .limit(Number.isNaN(limit) ? 12 : limit); const assetType = searchParams.get("assetType"); if (assetType) { query = query.eq("asset_type", assetType); } const { data, error } = await query; if (error) { return NextResponse.json({ error: error.message }, { status: 500 }); } return NextResponse.json({ items: (data ?? []) as MediaAsset[] }); } export async function POST(request: Request) { if (isConvexEnabled()) { let auth; try { auth = requireAuthContext(); } catch (err) { if (err instanceof HttpError) { return NextResponse.json({ error: "未登录" }, { status: err.status }); } return NextResponse.json({ error: "未登录" }, { status: 401 }); } const payload = (await request.json()) as { workspaceId: string; documentId: string; fileUrl: string; thumbnailUrl?: string; assetType?: string; fileName?: string; fileSize?: number; mimeType?: string; }; if (!payload.workspaceId || !payload.documentId || !payload.fileUrl) { return NextResponse.json({ error: "参数不完整" }, { status: 400 }); } const assetId = typeof crypto.randomUUID === "function" ? crypto.randomUUID() : `${Date.now()}_${Math.random().toString(16).slice(2)}`; const now = new Date().toISOString(); const asset: MediaAsset = { id: assetId, workspace_id: payload.workspaceId, document_id: payload.documentId, file_url: payload.fileUrl, thumbnail_url: payload.thumbnailUrl ?? payload.fileUrl, asset_type: payload.assetType ?? "image", file_name: payload.fileName ?? null, file_size: payload.fileSize ?? null, mime_type: payload.mimeType ?? null, ocr_text: null, ocr_status: null, created_at: now, updated_at: now, }; const client = getConvexHttpClient(); await client.mutation(api.mediaAssets.create, { userId: auth.userId, asset: { id: asset.id, workspace_id: asset.workspace_id, document_id: asset.document_id, asset_type: asset.asset_type, file_url: asset.file_url, thumbnail_url: asset.thumbnail_url, bucket: null, storage_path: null, file_name: asset.file_name, file_size: asset.file_size, mime_type: asset.mime_type, }, }); return NextResponse.json({ asset }); } const supabase = await createSupabaseRouteClient(); const { data: { user }, error: authError, } = await supabase.auth.getUser(); if (authError || !user) { return NextResponse.json({ error: "未登录" }, { status: 401 }); } const payload = (await request.json()) as { workspaceId: string; documentId: string; fileUrl: string; thumbnailUrl?: string; assetType?: string; fileName?: string; fileSize?: number; mimeType?: string; }; if (!payload.workspaceId || !payload.documentId || !payload.fileUrl) { return NextResponse.json({ error: "参数不完整" }, { status: 400 }); } const { data, error } = await supabase .from("media_assets") .insert({ workspace_id: payload.workspaceId, document_id: payload.documentId, file_url: payload.fileUrl, thumbnail_url: payload.thumbnailUrl ?? payload.fileUrl, asset_type: payload.assetType ?? "image", file_name: payload.fileName, file_size: payload.fileSize ?? null, mime_type: payload.mimeType ?? null, created_by: user.id, }) .select("*") .single(); if (error) { return NextResponse.json({ error: error.message }, { status: 500 }); } return NextResponse.json({ asset: data as MediaAsset }); }