guardz-axios
Version:
Type-safe HTTP client built on top of Axios with runtime validation using guardz. Part of the guardz ecosystem for comprehensive TypeScript type safety.
143 lines • 6.23 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.executeRequest = executeRequest;
const axios_1 = __importDefault(require("axios"));
const guardz_1 = require("guardz");
const axios_error_guards_1 = require("../../guards/axios-error-guards");
const axios_response_guards_1 = require("../../guards/axios-response-guards");
const status_types_1 = require("../../types/status-types");
const isRetryableError_1 = require("./isRetryableError");
/**
* Core execution function with retry logic and comprehensive error handling
*/
async function executeRequest(axiosConfig, safeConfig) {
const { guard, tolerance = false, identifier, onTypeMismatch, axiosInstance = axios_1.default, validateResponse = true, retry, timeout, } = safeConfig;
const finalConfig = {
...axiosConfig,
timeout: timeout || axiosConfig.timeout,
};
const url = finalConfig.url || "";
const method = (finalConfig.method || "GET").toUpperCase();
let attempt = 0;
const maxAttempts = retry?.attempts || 1;
while (attempt < maxAttempts) {
attempt++;
try {
// Add delay for retries
if (attempt > 1 && retry) {
const delay = retry.backoff === "exponential"
? retry.delay * Math.pow(2, attempt - 2)
: retry.delay * (attempt - 1);
await new Promise((resolve) => setTimeout(resolve, delay));
}
const response = await axiosInstance.request(finalConfig);
// Validate response structure if requested
if (validateResponse && !(0, axios_response_guards_1.isAxiosResponse)(response)) {
const errorMsg = "Invalid response structure";
const context = {
type: "validation",
url,
method,
originalError: response,
};
onTypeMismatch?.(errorMsg, context);
if (!tolerance) {
return { status: status_types_1.Status.ERROR, code: 500, message: errorMsg };
}
}
// Validate response data
let validatedData;
let isValidated = true;
let validationErrors = [];
if (tolerance) {
// Use tolerance mode
const errorMessages = [];
const toleranceConfig = {
identifier: identifier || url,
callbackOnError: (errorMessage) => {
errorMessages.push(errorMessage);
onTypeMismatch?.(errorMessage, {
type: "validation",
url,
method,
originalError: response.data,
});
},
};
validatedData = (0, guardz_1.guardWithTolerance)(response.data, guard, toleranceConfig);
if (errorMessages.length > 0) {
isValidated = false;
validationErrors = errorMessages;
}
}
else {
// Strict mode
const errorMessages = [];
const strictConfig = {
identifier: identifier || url,
callbackOnError: (errorMessage) => {
errorMessages.push(errorMessage);
},
};
if (guard(response.data, strictConfig)) {
validatedData = response.data;
}
else {
const errorMsg = errorMessages.length > 0
? `Response data validation failed: ${errorMessages.join(", ")}`
: "Response data validation failed";
const context = {
type: "validation",
url,
method,
originalError: response.data,
};
onTypeMismatch?.(errorMsg, context);
return { status: status_types_1.Status.ERROR, code: 500, message: errorMsg };
}
}
return { status: status_types_1.Status.SUCCESS, data: validatedData };
}
catch (error) {
// Check if we should retry
const shouldRetry = attempt < maxAttempts &&
Boolean(retry?.retryOn ? retry.retryOn(error) : (0, isRetryableError_1.isRetryableError)(error));
if (!shouldRetry) {
// Handle final error
let errorType = "unknown";
let statusCode;
if ((0, axios_error_guards_1.isAxiosError)(error)) {
const categorized = (0, axios_error_guards_1.categorizeAxiosError)(error);
errorType =
categorized.category === "network"
? "network"
: categorized.category === "timeout"
? "timeout"
: "unknown";
statusCode = categorized.statusCode;
}
const context = {
type: errorType,
url,
method,
statusCode,
originalError: error,
};
const errorMsg = error instanceof Error ? error.message : "Unknown error";
onTypeMismatch?.(errorMsg, context);
return { status: status_types_1.Status.ERROR, code: 500, message: errorMsg };
}
// If shouldRetry is true, continue to next iteration
}
}
// This should never be reached, but TypeScript requires it
return {
status: status_types_1.Status.ERROR,
code: 500,
message: "Maximum retry attempts exceeded",
};
}
//# sourceMappingURL=executeRequest.js.map