import { toast } from 'sonner'; import { logger } from './logger'; export type ErrorContext = { action: string; userId?: string; metadata?: Record; }; export class AppError extends Error { constructor( message: string, public code: string, public userMessage?: string ) { super(message); this.name = 'AppError'; } } export const handleError = ( error: unknown, context: ErrorContext ): void => { const errorMessage = error instanceof AppError ? error.userMessage || error.message : error instanceof Error ? error.message : 'An unexpected error occurred'; // Log to console/monitoring logger.error('Error occurred', { ...context, error: error instanceof Error ? error.message : String(error), stack: error instanceof Error ? error.stack : undefined }); // Show user-friendly toast toast.error(context.action, { description: errorMessage, duration: 5000 }); }; export const handleSuccess = ( title: string, description?: string ): void => { toast.success(title, { description, duration: 3000 }); }; export const handleInfo = ( title: string, description?: string ): void => { toast.info(title, { description, duration: 4000 }); }; /** * Type-safe error message extraction utility * Use this instead of `error: any` in catch blocks */ export function getErrorMessage(error: unknown): string { if (error instanceof Error) { return error.message; } if (typeof error === 'string') { return error; } if (error && typeof error === 'object' && 'message' in error) { return String(error.message); } return 'An unexpected error occurred'; } /** * Type guard to check if error has a code property */ export function hasErrorCode(error: unknown): error is { code: string } { return ( error !== null && typeof error === 'object' && 'code' in error && typeof (error as { code: unknown }).code === 'string' ); }