import { NextResponse } from "next/server"; export type ApiErrorCode = | "AUTH_REQUIRED" | "VALIDATION_ERROR" | "CONFIG_ERROR" | "PROVIDER_ERROR" | "RATE_LIMITED" | "INTERNAL_ERROR"; export function isAuthRequiredMessage(message: string): boolean { const normalized = message.trim().toLowerCase(); if (!normalized) return false; return ( normalized.includes("please login") || normalized.includes("please log in") || normalized.includes("login first") || normalized.includes("log in first") || normalized.includes("not logged in") || normalized.includes("session expired") || normalized.includes("token expired") || message.includes("请先登录") || message.includes("請先登入") || message.includes("未登录") || message.includes("未登入") || message.includes("登录已过期") || message.includes("登入已過期") ); } export class ApiError extends Error { readonly status: number; readonly code: ApiErrorCode; constructor(status: number, code: ApiErrorCode, message: string) { super(message); this.name = "ApiError"; this.status = status; this.code = code; } static unauthorized(message = "请先登录"): ApiError { return new ApiError(401, "AUTH_REQUIRED", message); } static badRequest(message: string): ApiError { return new ApiError(400, "VALIDATION_ERROR", message); } static config(message: string, status = 401): ApiError { return new ApiError(status, "CONFIG_ERROR", message); } static provider(message: string, status = 500): ApiError { if (isAuthRequiredMessage(message)) { return ApiError.unauthorized(message); } return new ApiError(status, "PROVIDER_ERROR", message); } } export interface ApiErrorPayload { success: false; requestId?: string; code: ApiErrorCode; error: string; } export function apiErrorResponse( error: unknown, requestId?: string, fallbackMessage = "Request failed" ): NextResponse { if (error instanceof ApiError) { return NextResponse.json( { success: false, requestId, code: error.code, error: error.message, }, { status: error.status } ); } const message = error instanceof Error ? error.message : fallbackMessage; if (isAuthRequiredMessage(message)) { return NextResponse.json( { success: false, requestId, code: "AUTH_REQUIRED", error: message, }, { status: 401 } ); } const isRateLimited = message.includes("429"); return NextResponse.json( { success: false, requestId, code: isRateLimited ? "RATE_LIMITED" : "INTERNAL_ERROR", error: isRateLimited ? "Rate limit reached. Please wait and try again." : message, }, { status: isRateLimited ? 429 : 500 } ); }