Files
record-app-next/lib/utils/api-response.ts
2025-07-31 17:05:07 +08:00

112 lines
2.3 KiB
TypeScript

import { NextResponse } from "next/server";
import { AppError } from "../errors/app-error";
export interface ApiResponse<T = unknown> {
success: boolean;
data?: T;
error?: {
message: string;
code?: string;
details?: unknown;
};
meta?: {
timestamp: string;
requestId?: string;
};
}
export class ApiResponseHandler {
/**
* 成功响应
*/
static success<T>(
data: T,
statusCode: number = 200,
meta?: { requestId?: string }
): NextResponse<ApiResponse<T>> {
const response: ApiResponse<T> = {
success: true,
data,
meta: {
timestamp: new Date().toISOString(),
...meta,
},
};
return NextResponse.json(response, { status: statusCode });
}
/**
* 错误响应
*/
static error(
error: AppError | Error,
meta?: { requestId?: string }
): NextResponse<ApiResponse> {
const isAppError = error instanceof AppError;
const statusCode = isAppError ? error.statusCode : 500;
const code = isAppError ? error.code : "INTERNAL_SERVER_ERROR";
const response: ApiResponse = {
success: false,
error: {
message: error.message,
code,
details: isAppError && !error.isOperational ? error.stack : undefined,
},
meta: {
timestamp: new Date().toISOString(),
...meta,
},
};
return NextResponse.json(response, { status: statusCode });
}
/**
* 分页响应
*/
static paginated<T>(
data: T[],
pagination: {
page: number;
limit: number;
total: number;
totalPages: number;
},
meta?: { requestId?: string }
): NextResponse<ApiResponse<{ data: T[]; pagination: typeof pagination }>> {
const response: ApiResponse<{ data: T[]; pagination: typeof pagination }> =
{
success: true,
data: {
data,
pagination,
},
meta: {
timestamp: new Date().toISOString(),
...meta,
},
};
return NextResponse.json(response, { status: 200 });
}
/**
* 创建响应
*/
static created<T>(
data: T,
meta?: { requestId?: string }
): NextResponse<ApiResponse<T>> {
return this.success(data, 201, meta);
}
/**
* 无内容响应
*/
static noContent(): NextResponse {
return new NextResponse(null, { status: 204 });
}
}