import { NextResponse } from "next/server"; import { createSupabaseRouteClient } from "@/lib/supabase/server"; 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"; interface EmptyTrashPayload { workspaceId?: string; } function resolveGraceSeconds(): number { const raw = process.env.DELETE_GRACE_SECONDS ?? process.env.NEXT_PUBLIC_DELETE_GRACE_SECONDS ?? "600"; const parsed = Number(raw); if (!Number.isFinite(parsed) || parsed <= 0) { return 600; } return Math.floor(parsed); } function makeExpiredDeletedAt(): string { const graceSeconds = resolveGraceSeconds(); return new Date(Date.now() - (graceSeconds + 5) * 1000).toISOString(); } export async function POST(request: Request) { if (isConvexEnabled()) { let auth; try { auth = await requireAuthContext(); } catch (err) { if (err instanceof HttpError) { return NextResponse.json({ error: "未登录" }, { status: err.status }); } return NextResponse.json({ error: "未登录" }, { status: 401 }); } const { workspaceId }: EmptyTrashPayload = await request.json().catch(() => ({})); if (!workspaceId) { return NextResponse.json({ error: "缺少 workspaceId" }, { status: 400 }); } const client = getConvexHttpClient(); const res = await client.mutation(api.mediaAssets.emptyTrashByWorkspace, { userId: auth.userId, workspaceId, expiredDeletedAt: makeExpiredDeletedAt(), }); return NextResponse.json({ success: true, ...(res as any) }); } const supabase = await createSupabaseRouteClient(); const { data: { session }, } = await supabase.auth.getSession(); if (!session) { return NextResponse.json({ error: "未登录" }, { status: 401 }); } const { workspaceId }: EmptyTrashPayload = await request.json().catch(() => ({})); if (!workspaceId) { return NextResponse.json({ error: "缺少 workspaceId" }, { status: 400 }); } const { data: membership, error: membershipError } = await supabase .from("workspace_members") .select("workspace_id") .eq("workspace_id", workspaceId) .eq("user_id", session.user.id) .limit(1); if (membershipError) { return NextResponse.json({ error: membershipError.message }, { status: 500 }); } if (!membership || membership.length === 0) { return NextResponse.json({ error: "无权操作该工作空间" }, { status: 403 }); } const { data: assets, error: fetchError } = await supabase .from("media_assets") .select("id") .eq("workspace_id", workspaceId) .not("deleted_at", "is", null) .is("purged_at", null) .limit(2000); if (fetchError) { return NextResponse.json({ error: fetchError.message }, { status: 500 }); } const assetIds = (assets ?? []).map((row) => row.id).filter(Boolean); if (assetIds.length === 0) { return NextResponse.json({ success: true, updated: 0 }); } const { error: updateError } = await supabase .from("media_assets") .update({ deleted_at: makeExpiredDeletedAt(), deleted_by: session.user.id, }) .in("id", assetIds); if (updateError) { return NextResponse.json({ error: updateError.message }, { status: 500 }); } return NextResponse.json({ success: true, updated: assetIds.length }); }