UNPKG

trainingpeaks-sdk

Version:
177 lines (176 loc) 8.02 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.handleRepositoryError = exports.throwTokenExpiredError = exports.throwCookieNotFoundError = exports.throwAuthError = exports.throwServerError = exports.throwMissingDataError = exports.throwValidationError = exports.throwHttpErrorFromResponse = exports.isRetryableError = exports.isServerError = exports.isClientError = exports.isHttpError = exports.createHttpError = exports.HttpError = void 0; const error_codes_1 = require("../../domain/errors/error-codes.js"); const sdk_error_1 = require("../../domain/errors/sdk-error.js"); class HttpError extends sdk_error_1.SDKError { constructor(message, code, context, options) { super(message, code, context, options); this.name = 'HttpError'; this.code = code; this.status = context.status; this.statusText = context.statusText; this.url = context.url; this.method = context.method; this.requestId = context.requestId; } } exports.HttpError = HttpError; const createHttpError = (response, context = {}, cause) => { const { status, statusText, data } = response; const { url, method, requestData, requestId } = context; const errorContext = { status, statusText, url, method, requestData, responseData: data, headers: response.headers, requestId, }; switch (status) { case 400: return new HttpError(`Bad Request: ${getErrorMessage(data) || statusText}`, error_codes_1.ERROR_CODES.VALIDATION_FAILED, errorContext, cause ? { cause } : undefined); case 401: return new HttpError(`Authentication failed: ${getErrorMessage(data) || statusText}`, error_codes_1.ERROR_CODES.AUTH_TOKEN_INVALID, errorContext, cause ? { cause } : undefined); case 403: return new HttpError(`Access forbidden: ${getErrorMessage(data) || statusText}`, error_codes_1.ERROR_CODES.AUTH_FAILED, errorContext, cause ? { cause } : undefined); case 404: return new HttpError(`Resource not found: ${getErrorMessage(data) || statusText}`, error_codes_1.ERROR_CODES.WORKOUT_NOT_FOUND, errorContext, cause ? { cause } : undefined); case 408: case 504: return new HttpError(`Request timeout: ${getErrorMessage(data) || statusText}`, error_codes_1.ERROR_CODES.NETWORK_TIMEOUT, errorContext, cause ? { cause } : undefined); case 409: return new HttpError(`Conflict: ${getErrorMessage(data) || statusText}`, error_codes_1.ERROR_CODES.VALIDATION_FAILED, errorContext, cause ? { cause } : undefined); case 422: return new HttpError(`Validation error: ${getErrorMessage(data) || statusText}`, error_codes_1.ERROR_CODES.VALIDATION_FAILED, errorContext, cause ? { cause } : undefined); case 429: return new HttpError(`Rate limit exceeded: ${getErrorMessage(data) || statusText}`, error_codes_1.ERROR_CODES.NETWORK_RATE_LIMITED, errorContext, cause ? { cause } : undefined); case 500: return new HttpError(`Server error: ${getErrorMessage(data) || statusText}`, error_codes_1.ERROR_CODES.NETWORK_SERVER_ERROR, errorContext, cause ? { cause } : undefined); case 502: return new HttpError(`Bad gateway: ${getErrorMessage(data) || statusText}`, error_codes_1.ERROR_CODES.NETWORK_RESPONSE_INVALID, errorContext, cause ? { cause } : undefined); case 503: return new HttpError(`Service unavailable: ${getErrorMessage(data) || statusText}`, error_codes_1.ERROR_CODES.NETWORK_SERVICE_UNAVAILABLE, errorContext, cause ? { cause } : undefined); default: return new HttpError(`HTTP Error ${status}: ${getErrorMessage(data) || statusText}`, error_codes_1.ERROR_CODES.NETWORK_REQUEST_FAILED, errorContext, cause ? { cause } : undefined); } }; exports.createHttpError = createHttpError; const getErrorMessage = (data) => { if (!data || typeof data !== 'object') return null; const errorData = data; return (errorData.message || errorData.error || errorData.detail || errorData.description || null); }; const isHttpError = (error) => { return error instanceof HttpError; }; exports.isHttpError = isHttpError; const isClientError = (error) => { return (0, exports.isHttpError)(error) && error.status >= 400 && error.status < 500; }; exports.isClientError = isClientError; const isServerError = (error) => { return (0, exports.isHttpError)(error) && error.status >= 500; }; exports.isServerError = isServerError; const isRetryableError = (error) => { if (!(0, exports.isHttpError)(error)) return false; return (error.status >= 500 || error.status === 408 || error.status === 429 || error.status === 502 || error.status === 503 || error.status === 504); }; exports.isRetryableError = isRetryableError; const throwHttpErrorFromResponse = (response, operation, context) => { if (response.error && (0, exports.isHttpError)(response.error)) { throw response.error; } const errorMessage = response.error ? response.error instanceof Error ? response.error.message : String(response.error) : `${operation} failed`; const httpErrorResponse = { status: 500, statusText: 'Unknown Error', data: { message: errorMessage }, }; throw (0, exports.createHttpError)(httpErrorResponse, context); }; exports.throwHttpErrorFromResponse = throwHttpErrorFromResponse; const throwValidationError = (message, context) => { const httpErrorResponse = { status: 400, statusText: 'Bad Request', data: { message }, }; throw (0, exports.createHttpError)(httpErrorResponse, context); }; exports.throwValidationError = throwValidationError; const throwMissingDataError = (message, context) => { const httpErrorResponse = { status: 502, statusText: 'Bad Gateway', data: { message }, }; throw (0, exports.createHttpError)(httpErrorResponse, context); }; exports.throwMissingDataError = throwMissingDataError; const throwServerError = (error, fallbackMessage, context) => { if ((0, exports.isHttpError)(error)) { throw error; } const httpErrorResponse = { status: 500, statusText: 'Internal Server Error', data: { message: error instanceof Error ? error.message : fallbackMessage, }, }; throw (0, exports.createHttpError)(httpErrorResponse, context, error); }; exports.throwServerError = throwServerError; const throwAuthError = (message, context) => { const httpErrorResponse = { status: 401, statusText: 'Unauthorized', data: { message }, }; throw (0, exports.createHttpError)(httpErrorResponse, context); }; exports.throwAuthError = throwAuthError; const throwCookieNotFoundError = (cookieName, context) => { const httpErrorResponse = { status: 401, statusText: 'Unauthorized', data: { message: `${cookieName} cookie not found` }, }; throw (0, exports.createHttpError)(httpErrorResponse, context); }; exports.throwCookieNotFoundError = throwCookieNotFoundError; const throwTokenExpiredError = (context) => { const httpErrorResponse = { status: 401, statusText: 'Unauthorized', data: { message: 'Received expired token from TrainingPeaks API' }, }; throw (0, exports.createHttpError)(httpErrorResponse, context); }; exports.throwTokenExpiredError = throwTokenExpiredError; const handleRepositoryError = (error, operation, context, logger, params) => { logger.error(`Failed to ${operation}`, { error, params }); if ((0, exports.isHttpError)(error)) throw error; (0, exports.throwServerError)(error, `Failed to ${operation}`, context); }; exports.handleRepositoryError = handleRepositoryError;