const axios = require("axios"); const { createObjectCsvWriter } = require("csv-writer"); const moment = require("moment"); const fs = require("fs"); const https = require("https"); const CONFIG = { API_URL: "https://dropship.ecomzone.eu/api/catalog", API_KEY: "klRyAdrXaxL0s6PEUp7LDlH6T8aPSCtBY8NiEHsHiWpc6646K2TZPi5KMxUg", MAX_RETRIES: 3, RETRY_DELAY: 10000, OUTPUT_DIR: "./output", LOG_DIR: "./logs", }; function ensureDirectories() { if (!fs.existsSync(CONFIG.OUTPUT_DIR)) { fs.mkdirSync(CONFIG.OUTPUT_DIR); } if (!fs.existsSync(CONFIG.LOG_DIR)) { fs.mkdirSync(CONFIG.LOG_DIR); } } function getCsvWriter() { const timestamp = moment().format("YYYY-MM-DD-HH-mm-ss"); return createObjectCsvWriter({ path: `${CONFIG.OUTPUT_DIR}/products_${timestamp}.csv`, header: [ { id: "sku", title: "Product SKU" }, { id: "product_name", title: "Name" }, { id: "category", title: "Category" }, { id: "product_price", title: "Wholesale price" }, { id: "ean", title: "EAN" }, { id: "variation_name", title: "Variation" }, { id: "variation_sku", title: "Variation SKU" }, { id: "width", title: "Width" }, { id: "height", title: "Height" }, { id: "stock", title: "Quantity" }, { id: "description", title: "Description" }, { id: "image", title: "Main image" }, ], fieldDelimiter: ";", recordDelimiter: "\n", }); } function transformData(data) { return data.map((item) => ({ sku: item.sku || "", product_name: item.product_name || "", category: item.category || "", product_price: item.product_price || "", ean: item.ean || "", variation_name: item.variation_name || "", variation_sku: item.variation_sku || item.sku || "", width: item.width || "", height: item.height || "", stock: item.stock || "0", description: (item.description || "").replace(/\n/g, " ").trim(), image: item.image || "", })); } const axiosInstance = axios.create({ timeout: 30000, // 30 seconds timeout httpsAgent: new https.Agent({ rejectUnauthorized: false, // Only use this in development keepAlive: true, keepAliveMsecs: 1000, maxSockets: 10, }), maxContentLength: Infinity, maxBodyLength: Infinity, }); async function saveToCSV(data) { try { const csvWriter = getCsvWriter(); await csvWriter.writeRecords(data); logger.log("Data successfully written to CSV"); } catch (error) { logger.error(`Error writing to CSV: ${error.message}`); throw error; } } async function fetchDataFromAPI() { let retries = 0; while (retries < CONFIG.MAX_RETRIES) { try { logger.log(`Attempting API call (${retries + 1}/${CONFIG.MAX_RETRIES})`); const response = await axiosInstance({ method: "get", url: CONFIG.API_URL, headers: { Accept: "application/json", "Content-Type": "application/json", Authorization: `Bearer ${CONFIG.API_KEY}`, }, params: { perpage: 1000, }, }); if (response.data && response.data.data) { logger.log("Data successfully retrieved from API"); return response.data.data; } throw new Error("Invalid data structure received from API"); } catch (error) { logger.error( `API call failed (attempt ${retries + 1}): ${error.message}`, ); if (error.response) { logger.error(`Status: ${error.response.status}`); logger.error(`Response data: ${JSON.stringify(error.response.data)}`); } retries++; if (retries < CONFIG.MAX_RETRIES) { logger.log( `Waiting ${CONFIG.RETRY_DELAY / 1000} seconds before retry...`, ); await delay(CONFIG.RETRY_DELAY); } } } throw new Error("Max retries exceeded"); } const logger = { log: (message) => { const timestamp = moment().format("YYYY-MM-DD HH:mm:ss"); const logMessage = `${timestamp} - ${message}\n`; console.log(message); fs.appendFileSync(`${CONFIG.LOG_DIR}/app.log`, logMessage); }, error: (message) => { const timestamp = moment().format("YYYY-MM-DD HH:mm:ss"); const logMessage = `${timestamp} - ERROR: ${message}\n`; console.error(message); fs.appendFileSync(`${CONFIG.LOG_DIR}/error.log`, logMessage); }, }; function validateData(data) { if (!Array.isArray(data)) { return []; } return data.filter((item) => { return ( item && typeof item.sku === "string" && typeof item.product_name === "string" && typeof item.product_price !== "undefined" && typeof item.stock !== "undefined" ); }); } async function main() { try { ensureDirectories(); logger.log("Starting data extraction process"); const rawData = await fetchDataFromAPI(); if (rawData) { const validatedData = validateData(rawData); logger.log(`Found ${validatedData.length} valid records`); if (validatedData.length > 0) { const transformedData = transformData(validatedData); await saveToCSV(transformedData); logger.log( `Successfully saved ${transformedData.length} records to CSV`, ); logger.log("Process completed successfully"); } else { logger.log("No valid data to save"); } } else { logger.log("No data received from API"); } } catch (error) { logger.error(`Process failed: ${error.message}`); process.exit(1); } } // Fix the delay function name (it was "dalay") const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); // Fix the loggerConfig function function loggerConfig() { const logFile = `${CONFIG.LOG_DIR}/log-${moment().format("YYYY-MM-DD")}.log`; const logStream = fs.createWriteStream(logFile, { flags: "a" }); console.log = (message) => { logStream.write(`[${moment().format("YYYY-MM-DD HH:mm:ss")}] ${message}\n`); }; } main();