presta/app.js
2025-01-24 16:14:18 +01:00

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();