refactor(backup): extract error classification helper function

- Extract classifyBackupError() helper for consistent error handling
- Improve JSON parse error detection using SyntaxError and regex
- Add case-insensitive error message matching
- Reduce code duplication across restore functions
This commit is contained in:
GeorgeDong32 2025-12-27 23:10:11 +08:00 committed by George·Dong
parent 9e0cbcf3b3
commit 7564b5fb58
No known key found for this signature in database

View File

@ -62,6 +62,21 @@ async function deleteWebdavFileWithRetry(fileName: string, webdavConfig: WebDavC
return false
}
// Helper function to classify backup errors
function classifyBackupError(error: any): 'file_locked' | 'file_not_found' | 'format' | 'unknown' {
const errorCode = error.code || ''
const errorMessage = String(error.message || '').toLowerCase()
if (errorCode === 'EBUSY' || errorMessage.includes('ebusy') || errorMessage.includes('locked')) {
return 'file_locked'
} else if (errorCode === 'ENOENT' || errorMessage.includes('no such file')) {
return 'file_not_found'
} else if (error instanceof SyntaxError || /Unexpected token|in JSON at position|JSON\.parse/i.test(errorMessage)) {
return 'format'
}
return 'unknown'
}
export async function backup(skipBackupFile: boolean) {
const filename = `cherry-studio.${dayjs().format('YYYYMMDDHHmm')}.zip`
const fileContnet = await getBackupData()
@ -103,19 +118,21 @@ export async function restore() {
} catch (error: any) {
logger.error('restore: Error restoring backup file:', error as Error)
// Distinguish different error types for better user experience
const errorCode = error.code || ''
const errorMessage = error.message || ''
// Use helper function for consistent error classification
const errorType = classifyBackupError(error)
if (errorCode === 'EBUSY' || errorMessage.includes('EBUSY') || errorMessage.includes('locked')) {
window.toast.error(i18n.t('error.backup.file_locked'))
} else if (errorCode === 'ENOENT' || errorMessage.includes('no such file')) {
window.toast.error(i18n.t('error.backup.file_not_found'))
} else if (errorMessage.includes('JSON')) {
window.toast.error(i18n.t('error.backup.file_format'))
} else {
// Show detailed error message for debugging
window.toast.error(i18n.t('error.backup.file_format') + ': ' + errorMessage)
switch (errorType) {
case 'file_locked':
window.toast.error(i18n.t('error.backup.file_locked'))
break
case 'file_not_found':
window.toast.error(i18n.t('error.backup.file_not_found'))
break
case 'format':
window.toast.error(i18n.t('error.backup.file_format'))
break
default:
window.toast.error(i18n.t('error.backup.file_format') + ': ' + error.message)
}
}
}
@ -331,19 +348,21 @@ export async function restoreFromWebdav(fileName?: string) {
} catch (error: any) {
logger.error('[Backup] Error downloading file from WebDAV:', error as Error)
// Distinguish different error types for better user experience
const errorCode = error.code || ''
const errorMessage = error.message || ''
// Use helper function for consistent error classification
const errorType = classifyBackupError(error)
if (errorCode === 'EBUSY' || errorMessage.includes('EBUSY') || errorMessage.includes('locked')) {
window.toast.error(i18n.t('error.backup.file_locked'))
} else if (errorCode === 'ENOENT' || errorMessage.includes('no such file')) {
window.toast.error(i18n.t('error.backup.file_not_found'))
} else if (errorMessage.includes('JSON')) {
window.toast.error(i18n.t('error.backup.file_format'))
} else {
// Show detailed error message for debugging
window.toast.error(i18n.t('error.backup.file_format') + ': ' + errorMessage)
switch (errorType) {
case 'file_locked':
window.toast.error(i18n.t('error.backup.file_locked'))
break
case 'file_not_found':
window.toast.error(i18n.t('error.backup.file_not_found'))
break
case 'format':
window.toast.error(i18n.t('error.backup.file_format'))
break
default:
window.toast.error(i18n.t('error.backup.file_format') + ': ' + error.message)
}
}
}
@ -1102,19 +1121,21 @@ export async function restoreFromLocal(fileName: string) {
} catch (error: any) {
logger.error('[LocalBackup] Restore failed:', error as Error)
// Distinguish different error types for better user experience
const errorCode = error.code || ''
const errorMessage = error.message || ''
// Use helper function for consistent error classification
const errorType = classifyBackupError(error)
if (errorCode === 'EBUSY' || errorMessage.includes('EBUSY') || errorMessage.includes('locked')) {
window.toast.error(i18n.t('error.backup.file_locked'))
} else if (errorCode === 'ENOENT' || errorMessage.includes('no such file')) {
window.toast.error(i18n.t('error.backup.file_not_found'))
} else if (errorMessage.includes('JSON')) {
window.toast.error(i18n.t('error.backup.file_format'))
} else {
// Show detailed error message for debugging
window.toast.error(i18n.t('error.backup.file_format') + ': ' + errorMessage)
switch (errorType) {
case 'file_locked':
window.toast.error(i18n.t('error.backup.file_locked'))
break
case 'file_not_found':
window.toast.error(i18n.t('error.backup.file_not_found'))
break
case 'format':
window.toast.error(i18n.t('error.backup.file_format'))
break
default:
window.toast.error(i18n.t('error.backup.file_format') + ': ' + error.message)
}
throw error