/** * アプリケーション全体で使用するカスタムエラー。 * 各エラーは HTTP ステータスコードを保持し、Route Handler でレスポンスへの変換が容易。 */ export class AppError extends Error { constructor( message: string, public readonly status: number ) { super(message); this.name = this.constructor.name; } } export class ValidationError extends AppError { constructor( message: string, public readonly field?: string ) { super(message, 400); this.name = 'ValidationError'; } } export class UnauthorizedError extends AppError { constructor(message: string = '認証が必要です') { super(message, 401); this.name = 'UnauthorizedError'; } } export class ForbiddenError extends AppError { constructor(message: string = 'この操作を行う権限がありません') { super(message, 403); this.name = 'ForbiddenError'; } } export class NotFoundError extends AppError { constructor( public readonly resource: string, public readonly id: number | string ) { super(`${resource} not found: ${id}`, 404); this.name = 'NotFoundError'; } } export class ConflictError extends AppError { constructor(message: string) { super(message, 409); this.name = 'ConflictError'; } }