209 lines
5.8 KiB
JavaScript
209 lines
5.8 KiB
JavaScript
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();
|