dt-common-device
Version: 
A secure and robust device management library for IoT applications
118 lines (117 loc) • 4.3 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.validateServiceUrl = validateServiceUrl;
exports.createAxiosInstance = createAxiosInstance;
exports.getDeviceServiceAxiosInstance = getDeviceServiceAxiosInstance;
exports.retryRequest = retryRequest;
const config_1 = require("../config/config");
const axios_1 = __importDefault(require("axios"));
/**
 * Validates if a URL is properly formatted and accessible
 */
function validateServiceUrl(url) {
    try {
        const parsedUrl = new URL(url);
        return parsedUrl.protocol === "http:" || parsedUrl.protocol === "https:";
    }
    catch (error) {
        (0, config_1.getConfig)().LOGGER.error(`Invalid service URL: ${url}`, error);
        return false;
    }
}
/**
 * Creates a properly configured axios instance with error handling
 */
function createAxiosInstance(baseURL) {
    const instance = axios_1.default.create({
        baseURL,
        timeout: 30000, // 30 seconds timeout
        maxRedirects: 5,
        validateStatus: (status) => status < 500, // Don't throw on 4xx errors
        headers: {
            "Content-Type": "application/json",
            "User-Agent": "dt-common-device/1.3.0",
        },
    });
    // Add request interceptor for logging
    instance.interceptors.request.use((config) => {
        const logger = (0, config_1.getConfig)().LOGGER;
        logger.info(`Making request to: ${config.method?.toUpperCase()} ${config.url}`, {
            baseURL: config.baseURL,
            timeout: config.timeout,
        });
        return config;
    }, (error) => {
        (0, config_1.getConfig)().LOGGER.error("Request interceptor error:", error);
        return Promise.reject(error);
    });
    // Add response interceptor for error handling
    instance.interceptors.response.use((response) => {
        return response;
    }, (error) => {
        const logger = (0, config_1.getConfig)().LOGGER;
        const errorInfo = {
            url: error.config?.url,
            method: error.config?.method,
            status: error.response?.status,
            statusText: error.response?.statusText,
            message: error.message,
            code: error.code,
            baseURL: error.config?.baseURL,
        };
        logger.error("HTTP request failed:", errorInfo);
        // Log additional details for network errors
        if (error.code === "ECONNREFUSED" || error.code === "ENOTFOUND") {
            logger.error("Network connectivity issue detected. Please check:", {
                serviceUrl: error.config?.baseURL,
                errorCode: error.code,
                errorMessage: error.message,
            });
        }
        return Promise.reject(error);
    });
    return instance;
}
/**
 * Centralized axios instance for device service
 */
let deviceServiceAxiosInstance = null;
function getDeviceServiceAxiosInstance() {
    if (!deviceServiceAxiosInstance) {
        const { DEVICE_SERVICE } = (0, config_1.getConfig)();
        if (!DEVICE_SERVICE) {
            throw new Error("DEVICE_SERVICE is not configured. Call initialize() first with DEVICE_SERVICE.");
        }
        deviceServiceAxiosInstance = createAxiosInstance(DEVICE_SERVICE);
    }
    return deviceServiceAxiosInstance;
}
/**
 * Retry function for failed HTTP requests
 */
async function retryRequest(requestFn, maxRetries = 3, delay = 1000) {
    let lastError;
    for (let attempt = 1; attempt <= maxRetries; attempt++) {
        try {
            return await requestFn();
        }
        catch (error) {
            lastError = error;
            if (attempt === maxRetries) {
                (0, config_1.getConfig)().LOGGER.error(`Request failed after ${maxRetries} attempts:`, error);
                throw error;
            }
            (0, config_1.getConfig)().LOGGER.warn(`Request attempt ${attempt} failed, retrying in ${delay}ms:`, {
                error: error.message,
                attempt,
                maxRetries,
            });
            await new Promise((resolve) => setTimeout(resolve, delay));
            delay *= 2; // Exponential backoff
        }
    }
    throw lastError;
}