UNPKG

dt-common-device

Version:

A secure and robust device management library for IoT applications

118 lines (117 loc) 4.3 kB
"use strict"; 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; }