fIx: smaller nits
This commit is contained in:
155
frontend/src/lib/errorHandling.ts
Normal file
155
frontend/src/lib/errorHandling.ts
Normal file
@@ -0,0 +1,155 @@
|
||||
/**
|
||||
* Error handling utilities for consistent error management.
|
||||
* Provides centralized error handling logic across the application.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Error kind for categorizing errors
|
||||
*/
|
||||
export type ErrorKind =
|
||||
| 'render'
|
||||
| 'network'
|
||||
| 'validation'
|
||||
| 'authentication'
|
||||
| 'authorization'
|
||||
| 'notFound'
|
||||
| 'server'
|
||||
| 'unknown'
|
||||
|
||||
/**
|
||||
* Error object with kind and message
|
||||
*/
|
||||
export type AppError = {
|
||||
kind: ErrorKind
|
||||
message: string
|
||||
details?: Record<string, unknown>
|
||||
timestamp: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an error object with consistent structure
|
||||
*/
|
||||
export function createAppError(
|
||||
kind: ErrorKind,
|
||||
message: string,
|
||||
details?: Record<string, unknown>
|
||||
): AppError {
|
||||
return {
|
||||
kind,
|
||||
message,
|
||||
details,
|
||||
timestamp: Date.now(),
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract error message from unknown error
|
||||
*/
|
||||
export function getErrorMessage(error: unknown): string {
|
||||
if (error instanceof Error) {
|
||||
return error.message
|
||||
}
|
||||
if (typeof error === 'string') {
|
||||
return error
|
||||
}
|
||||
if (typeof error === 'object' && error !== null && 'message' in error) {
|
||||
return String(error.message)
|
||||
}
|
||||
return 'An unknown error occurred'
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract error kind from error
|
||||
*/
|
||||
export function getErrorKind(error: unknown): ErrorKind {
|
||||
if (error instanceof Error) {
|
||||
const message = error.message.toLowerCase()
|
||||
if (message.includes('network')) return 'network'
|
||||
if (message.includes('validation') || message.includes('invalid')) return 'validation'
|
||||
if (message.includes('auth')) return 'authentication'
|
||||
if (message.includes('forbidden') || message.includes('unauthorized')) return 'authorization'
|
||||
if (message.includes('not found') || message.includes('404')) return 'notFound'
|
||||
if (message.includes('server') || message.includes('500')) return 'server'
|
||||
}
|
||||
return 'unknown'
|
||||
}
|
||||
|
||||
/**
|
||||
* Format error for display
|
||||
*/
|
||||
export function formatError(error: AppError | Error | string): string {
|
||||
if (typeof error === 'string') {
|
||||
return error
|
||||
}
|
||||
if (error instanceof Error) {
|
||||
return error.message
|
||||
}
|
||||
return error.message
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if error is recoverable
|
||||
*/
|
||||
export function isRecoverableError(error: AppError | Error | string): boolean {
|
||||
if (typeof error === 'string') return false
|
||||
if (error instanceof Error) {
|
||||
const message = error.message.toLowerCase()
|
||||
return ['network', 'timeout', 'connection'].some((term) => message.includes(term))
|
||||
}
|
||||
// error is AppError at this point
|
||||
return ['network', 'server'].includes((error as AppError).kind)
|
||||
}
|
||||
|
||||
/**
|
||||
* Update error state consistently
|
||||
*/
|
||||
export function updateErrorState<T extends { error?: unknown }>(
|
||||
state: T,
|
||||
setError: (error: null | { kind: string; message: string }) => void,
|
||||
error: unknown
|
||||
): void {
|
||||
setError({
|
||||
kind: 'render',
|
||||
message: getErrorMessage(error),
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear error state
|
||||
*/
|
||||
export function clearErrorState<T extends { error?: unknown }>(
|
||||
state: T,
|
||||
setError: (error: null) => void
|
||||
): void {
|
||||
setError(null)
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle error with consistent logging
|
||||
*/
|
||||
export function handleError(
|
||||
error: unknown,
|
||||
context?: Record<string, unknown>
|
||||
): AppError {
|
||||
const appError = createAppError(
|
||||
getErrorKind(error),
|
||||
getErrorMessage(error),
|
||||
context
|
||||
)
|
||||
|
||||
console.error('[Error]', appError, context)
|
||||
return appError
|
||||
}
|
||||
|
||||
/**
|
||||
* Create error handler for async functions
|
||||
*/
|
||||
export function createErrorHandler<T>(
|
||||
onError?: (error: AppError) => void
|
||||
): (error: unknown) => T {
|
||||
return (error: unknown) => {
|
||||
const appError = handleError(error)
|
||||
onError?.(appError)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user