story-research-zapwall/lib/errorClassification.ts
2026-01-15 11:31:09 +01:00

143 lines
3.8 KiB
TypeScript

/**
* Error classification system for actionable error messages
*/
export type ErrorType = 'network' | 'payment' | 'validation' | 'loading' | 'unknown'
export interface ErrorClassification {
type: ErrorType
message: string
suggestion?: string
canRetry: boolean
canCheckConnection: boolean
needsDocumentation: boolean
}
function isNetworkError(lowerMessage: string): boolean {
return (
lowerMessage.includes('network') ||
lowerMessage.includes('fetch') ||
lowerMessage.includes('timeout') ||
lowerMessage.includes('timed out') ||
lowerMessage.includes('econnreset') ||
lowerMessage.includes('econnrefused') ||
lowerMessage.includes('enotfound') ||
lowerMessage.includes('eai_again') ||
lowerMessage.includes('dns') ||
lowerMessage.includes('failed to fetch')
)
}
function isPaymentError(lowerMessage: string): boolean {
return (
lowerMessage.includes('payment') ||
lowerMessage.includes('invoice') ||
lowerMessage.includes('webln') ||
lowerMessage.includes('alby') ||
lowerMessage.includes('insufficient funds') ||
lowerMessage.includes('funds')
)
}
function isValidationError(lowerMessage: string): boolean {
return (
lowerMessage.includes('invalid') ||
lowerMessage.includes('validation') ||
lowerMessage.includes('required') ||
lowerMessage.includes('missing')
)
}
function isLoadingError(lowerMessage: string): boolean {
return (
lowerMessage.includes('loading') ||
lowerMessage.includes('failed to load') ||
lowerMessage.includes('could not load')
)
}
function createNetworkClassification(errorMessage: string): ErrorClassification {
return {
type: 'network',
message: errorMessage,
suggestion: 'errors.network.suggestion',
canRetry: true,
canCheckConnection: true,
needsDocumentation: false,
}
}
function createPaymentClassification(errorMessage: string): ErrorClassification {
return {
type: 'payment',
message: errorMessage,
suggestion: 'errors.payment.suggestion',
canRetry: true,
canCheckConnection: false,
needsDocumentation: true,
}
}
function createValidationClassification(errorMessage: string): ErrorClassification {
return {
type: 'validation',
message: errorMessage,
suggestion: 'errors.validation.suggestion',
canRetry: false,
canCheckConnection: false,
needsDocumentation: false,
}
}
function createLoadingClassification(errorMessage: string): ErrorClassification {
return {
type: 'loading',
message: errorMessage,
suggestion: 'errors.loading.suggestion',
canRetry: true,
canCheckConnection: true,
needsDocumentation: false,
}
}
function createUnknownClassification(errorMessage: string): ErrorClassification {
return {
type: 'unknown',
message: errorMessage,
suggestion: 'errors.unknown.suggestion',
canRetry: true,
canCheckConnection: false,
needsDocumentation: false,
}
}
/**
* Classify an error to determine appropriate recovery actions
*/
export function classifyError(error: unknown): ErrorClassification {
const errorMessage = error instanceof Error ? error.message : String(error)
const lowerMessage = errorMessage.toLowerCase()
if (isNetworkError(lowerMessage)) {
return createNetworkClassification(errorMessage)
}
if (isPaymentError(lowerMessage)) {
return createPaymentClassification(errorMessage)
}
if (isValidationError(lowerMessage)) {
return createValidationClassification(errorMessage)
}
if (isLoadingError(lowerMessage)) {
return createLoadingClassification(errorMessage)
}
return createUnknownClassification(errorMessage)
}
/**
* Get user-friendly error message based on classification
*/
export function getUserFriendlyMessage(classification: ErrorClassification): string {
return classification.message
}