UNPKG

trainingpeaks-sdk

Version:
212 lines (211 loc) 8.56 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createUserFriendlyMessage = exports.withClientResponseHandling = exports.transformToClientError = exports.withClientErrorHandling = exports.ClientError = void 0; const http_errors_1 = require("../adapters/errors/http-errors.js"); const domain_errors_1 = require("../domain/errors/domain-errors.js"); const error_codes_1 = require("../domain/errors/error-codes.js"); const sdk_error_1 = require("../domain/errors/sdk-error.js"); class ClientError extends sdk_error_1.SDKError { constructor(message, code, operation, options = {}) { super(message, code, { ...options.context, originalError: options.originalError, }); this.name = 'ClientError'; this.operation = operation; this.suggestions = options.suggestions || []; this.isRetryable = options.isRetryable || false; this.httpStatus = options.httpStatus; } } exports.ClientError = ClientError; const withClientErrorHandling = async (operation, operationName, context = {}) => { try { return await operation(); } catch (error) { throw (0, exports.transformToClientError)(error, operationName, context); } }; exports.withClientErrorHandling = withClientErrorHandling; const transformToClientError = (error, operation, context = {}) => { if (error instanceof domain_errors_1.AuthenticationError) { return new ClientError(error.message, error_codes_1.ERROR_CODES.AUTH_FAILED, operation, { suggestions: getSuggestionsForCode(error_codes_1.ERROR_CODES.AUTH_FAILED), isRetryable: false, originalError: error, context, }); } if (error instanceof domain_errors_1.ValidationError) { return new ClientError(error.message, error_codes_1.ERROR_CODES.VALIDATION_FAILED, operation, { suggestions: getSuggestionsForCode(error_codes_1.ERROR_CODES.VALIDATION_FAILED), isRetryable: false, originalError: error, context, }); } if (error instanceof domain_errors_1.NetworkError) { return new ClientError(error.message, error_codes_1.ERROR_CODES.NETWORK_REQUEST_FAILED, operation, { suggestions: getSuggestionsForCode(error_codes_1.ERROR_CODES.NETWORK_TIMEOUT), isRetryable: true, originalError: error, context, }); } if (error instanceof domain_errors_1.UserError) { return new ClientError(error.message, error.code, operation, { suggestions: getSuggestionsForCode(error.code), isRetryable: false, originalError: error, context, }); } if (error instanceof http_errors_1.HttpError) { return new ClientError(error.message, error.code, operation, { suggestions: getSuggestionsForHttpError(error), isRetryable: error.status >= 500 || error.status === 429, httpStatus: error.status, originalError: error, context: { ...context, url: error.url, method: error.method }, }); } if (error instanceof sdk_error_1.SDKError) { return new ClientError(error.message, error.code, operation, { suggestions: getSuggestionsForCode(error.code), originalError: error, context, }); } return new ClientError(`${operation} failed: ${error.message}`, error_codes_1.ERROR_CODES.UNKNOWN_ERROR, operation, { suggestions: [ 'Check network connection', 'Verify API credentials', 'Try again later', ], originalError: error, context, }); }; exports.transformToClientError = transformToClientError; const getSuggestionsForHttpError = (error) => { switch (error.status) { case 400: return [ 'Check request parameters for valid format', 'Ensure all required fields are included', 'Verify data types match API expectations', ]; case 401: return [ 'Check if your authentication token is valid', 'Try refreshing your authentication token', 'Verify your API credentials are correct', ]; case 403: return [ 'Verify you have permission to access this resource', 'Check if your account has the required subscription plan', 'Contact support if you believe this is an error', ]; case 404: return [ 'Verify the resource ID exists', 'Check if the resource has been deleted', 'Ensure you have access to this resource', ]; case 408: case 504: return [ 'The request timed out - try again', 'Check your network connection', 'Consider increasing timeout settings', ]; case 429: return [ 'You have exceeded the rate limit', 'Wait before making another request', 'Consider implementing exponential backoff', 'Check your subscription plan for higher limits', ]; case 500: case 502: case 503: return [ 'This is a temporary server error', 'Try again in a few moments', 'Check the service status page', 'Contact support if the issue persists', ]; default: return [ 'Check the HTTP status code for specific guidance', 'Verify your request format', 'Try again if this seems like a temporary issue', ]; } }; const getSuggestionsForCode = (code) => { switch (code) { case error_codes_1.ERROR_CODES.AUTH_FAILED: case error_codes_1.ERROR_CODES.AUTH_TOKEN_INVALID: return [ 'Verify your authentication credentials', 'Check if your token has expired', 'Try re-authenticating', ]; case error_codes_1.ERROR_CODES.NETWORK_TIMEOUT: return [ 'Check your network connection', 'Try again with a longer timeout', 'Verify the service is available', ]; case error_codes_1.ERROR_CODES.NETWORK_RATE_LIMITED: return [ 'Reduce the frequency of your requests', 'Implement exponential backoff', 'Check your rate limit allowance', ]; case error_codes_1.ERROR_CODES.VALIDATION_FAILED: return [ 'Check your input parameters', 'Ensure required fields are provided', 'Verify data formats are correct', ]; default: return ['Check the error code documentation for specific guidance']; } }; const withClientResponseHandling = async (operation, operationName, errorResponseFactory, context = {}) => { try { return await (0, exports.withClientErrorHandling)(operation, operationName, context); } catch (error) { const clientError = error; return errorResponseFactory(clientError.message, clientError.code); } }; exports.withClientResponseHandling = withClientResponseHandling; const createUserFriendlyMessage = (error) => { const baseMessage = `Operation "${error.operation}" failed`; if (error.httpStatus) { switch (error.httpStatus) { case 401: return `${baseMessage}: Authentication required. Please check your credentials.`; case 403: return `${baseMessage}: Access denied. You may not have permission for this resource.`; case 404: return `${baseMessage}: Resource not found. Please verify the ID is correct.`; case 429: return `${baseMessage}: Rate limit exceeded. Please wait before trying again.`; case 500: case 502: case 503: return `${baseMessage}: Server error. This is likely temporary - please try again.`; default: return `${baseMessage}: ${error.message}`; } } return `${baseMessage}: ${error.message}`; }; exports.createUserFriendlyMessage = createUserFriendlyMessage;