From 8c2ebe8dfa5056b56373aa99a4e1f62fed061a77 Mon Sep 17 00:00:00 2001 From: Rim Date: Wed, 16 Apr 2025 16:19:43 -0400 Subject: [PATCH] chore(backend.js): better error handling --- src/js/serverUtils.js | 107 +++++++++++++++++++++++++++++------------- 1 file changed, 75 insertions(+), 32 deletions(-) diff --git a/src/js/serverUtils.js b/src/js/serverUtils.js index 6445fb8..a1ebb76 100644 --- a/src/js/serverUtils.js +++ b/src/js/serverUtils.js @@ -128,10 +128,10 @@ const activeSessions = new Map(); // Utility function to create a timeout promise const timeoutPromise = (ms) => { - return new Promise((_, reject) => { - setTimeout(() => reject(new Error(`Request timed out after ${ms}ms`)), ms); - }); -}; + return new Promise((_, reject) => { + setTimeout(() => reject(new ApiTimeoutError(`Request timed out after ${ms}ms`)), ms); + }); + }; // Helper function to ensure login const ensureLogin = async (ssoToken) => { @@ -154,35 +154,78 @@ const ensureLogin = async (ssoToken) => { }; // Helper function to handle API errors -const handleApiError = (error, res) => { - logger.error('API Error:', error); - logger.error(`Error Stack: ${error.stack}`); - logger.error(`Error Time: ${global.Utils.toIsoString(new Date())}`); - - // Try to extract more useful information from the error - let errorMessage = error.message || 'Unknown API error'; - let errorName = error.name || 'ApiError'; - - // Handle the specific JSON parsing error - if (errorName === 'SyntaxError' && errorMessage.includes('JSON')) { - logger.debug('JSON parsing error detected'); - return res.status(200).json({ - status: 'error', - message: - 'Failed to parse API response. This usually means the SSO token is invalid or expired.', - error_type: 'InvalidResponseError', - timestamp: global.Utils.toIsoString(new Date()), - }); +class ApiTimeoutError extends Error { + constructor(message = 'API request timed out') { + super(message); + this.name = 'ApiTimeoutError'; + } } - - // Send a more graceful response - return res.status(200).json({ - status: 'error', - message: errorMessage, - error_type: errorName, - timestamp: global.Utils.toIsoString(new Date()), - }); -}; + + class ApiAuthError extends Error { + constructor(message = 'Authentication failed') { + super(message); + this.name = 'ApiAuthError'; + } + } + + class ApiDataError extends Error { + constructor(message = 'Data processing error') { + super(message); + this.name = 'ApiDataError'; + } + } + + // Helper function to handle API errors + const handleApiError = (error, res) => { + logger.error('API Error:', error); + logger.error(`Error Stack: ${error.stack}`); + logger.error(`Error Time: ${global.Utils.toIsoString(new Date())}`); + + // Map error types to appropriate responses + const errorResponses = { + 'ApiTimeoutError': { + status: 200, + body: { + status: 'error', + message: 'The request timed out. Please try again.', + error_type: 'timeout', + timestamp: global.Utils.toIsoString(new Date()) + } + }, + 'ApiAuthError': { + status: 200, + body: { + status: 'error', + message: 'Authentication failed. Please check your SSO token.', + error_type: 'auth_failure', + timestamp: global.Utils.toIsoString(new Date()) + } + }, + 'SyntaxError': { + status: 200, + body: { + status: 'error', + message: 'Failed to parse API response. This usually means the SSO token is invalid or expired.', + error_type: 'InvalidResponseError', + timestamp: global.Utils.toIsoString(new Date()) + } + }, + 'default': { + status: 200, + body: { + status: 'error', + message: error.message || 'An unknown error occurred', + error_type: error.name || 'UnknownError', + timestamp: global.Utils.toIsoString(new Date()) + } + } + }; + + // Get the appropriate response or use default + const response = errorResponses[error.name] || errorResponses.default; + + return res.status(response.status).json(response.body); + }; // Helper function to remove sensitive data from headers function sanitizeHeaders(headers) {