dt-common-device
Version:
A secure and robust device management library for IoT applications
148 lines (147 loc) • 5.47 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.getAccessServiceAxiosInstance = getAccessServiceAxiosInstance;
exports.getCloudServiceAxiosInstance = getCloudServiceAxiosInstance;
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;
}
/**
* Centralized axios instance for access service
*/
let accessServiceAxiosInstance = null;
function getAccessServiceAxiosInstance() {
if (!accessServiceAxiosInstance) {
const { ACCESS_SERVICE } = (0, config_1.getConfig)();
if (!ACCESS_SERVICE) {
throw new Error("ACCESS_SERVICE is not configured. Call initialize() first with ACCESS_SERVICE.");
}
accessServiceAxiosInstance = createAxiosInstance(ACCESS_SERVICE);
}
return accessServiceAxiosInstance;
}
/**
* Centralized axios instance for cloud service (smart-cloud)
*/
let cloudServiceAxiosInstance = null;
function getCloudServiceAxiosInstance() {
const { ADMIN_SERVICE } = (0, config_1.getConfig)();
if (!cloudServiceAxiosInstance) {
if (!ADMIN_SERVICE) {
throw new Error("ADMIN_SERVICE is not configured. Call initialize() first with ADMIN_SERVICE.");
}
cloudServiceAxiosInstance = createAxiosInstance(ADMIN_SERVICE);
}
return cloudServiceAxiosInstance;
}
/**
* 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;
}