gitdataai/admin/src/app/api/admin/projects/[id]/route.ts
ZhenYi 3773fdc780 feat(admin): add structured error logger for all API routes
Replace bare console.error() calls with logError() utility across all
47 API route handlers. logError() prints timestamp + context + message
+ stack trace + extra request data to stderr, and redacts sensitive
fields (password, token, secret, key, etc.) from logged objects.
2026-04-23 09:55:35 +08:00

64 lines
1.9 KiB
TypeScript

import { logError } from "@/lib/logger";
import { NextRequest, NextResponse } from "next/server";
import { query } from "@/lib/db";
export const runtime = "nodejs";
export async function GET(
_req: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) {
try {
const { id } = await params;
const [projectRows, membersRows, billingRows, billingHistoryRows] = await Promise.all([
query(
`SELECT p.*, w.name as workspace_name, w.slug as workspace_slug, w.plan as workspace_plan,
COALESCE(pb.balance, 0)::text as balance, COALESCE(pb.currency, 'USD') as currency
FROM project p
LEFT JOIN workspace w ON w.id = p.workspace_id
LEFT JOIN project_billing pb ON pb.project_uuid = p.id
WHERE p.id = $1`,
[id]
),
query(
`SELECT pm.id, u.uid, u.username, u.display_name, u.avatar_url,
pm.scope as role, pm.joined_at
FROM project_members pm
JOIN "user" u ON u.uid = pm.user_uuid
WHERE pm.project_uuid = $1
ORDER BY pm.joined_at DESC`,
[id]
),
query(
`SELECT pb.balance::text as balance, pb.currency, pb.updated_at
FROM project_billing pb
WHERE pb.project_uuid = $1`,
[id]
),
query(
`SELECT reason, amount, extra as description, created_at
FROM project_billing_history
WHERE project = $1
ORDER BY created_at DESC
LIMIT 50`,
[id]
),
]);
if (!projectRows.rows.length) {
return NextResponse.json({ error: "项目不存在" }, { status: 404 });
}
return NextResponse.json({
project: projectRows.rows[0],
members: membersRows.rows,
billing: billingRows.rows[0] || null,
billingHistory: billingHistoryRows.rows,
});
} catch (e) {
logError("Project detail error:", e);
return NextResponse.json({ error: "服务器错误" }, { status: 500 });
}
}