const http = require("http"); const fs = require("fs"); const path = require("path"); const formidable = require("formidable"); const PORT = process.env.PORT || 3000; const DATA = path.join(__dirname, "data.json"); const UPLOADS = path.join(__dirname, "uploads"); if (!fs.existsSync(UPLOADS)) fs.mkdirSync(UPLOADS); function readData() { try { return JSON.parse(fs.readFileSync(DATA, "utf8")); } catch (_) { return { inputData: null, suppliers: [], offers: [], checks: { c1: false, c2: false, c3: false }, files: [] }; } } function writeData(data) { fs.writeFileSync(DATA, JSON.stringify(data, null, 2)); } function body(req) { return new Promise((resolve) => { let s = ""; req.on("data", (c) => (s += c)); req.on("end", () => { try { resolve(JSON.parse(s || "{}")); } catch (_) { resolve({}); } }); }); } http.createServer(async (req, res) => { if (req.method === "GET" && req.url === "/api/data") { res.writeHead(200, { "Content-Type": "application/json" }); return res.end(JSON.stringify(readData())); } if (req.method === "GET" && req.url === "/api/files") { const data = readData(); res.writeHead(200, { "Content-Type": "application/json" }); return res.end(JSON.stringify(data.files || [])); } if (req.method === "POST" && req.url === "/api/upload") { const form = formidable({ uploadDir: UPLOADS, keepExtensions: true }); form.parse(req, async (err, fields, files) => { if (err) { res.writeHead(500, { "Content-Type": "application/json" }); return res.end(JSON.stringify({ error: err.message })); } const data = readData(); const uploaded = []; if (files.file && Array.isArray(files.file)) { for (const f of files.file) { const fileName = Date.now() + "_" + path.basename(f.filepath); const newPath = path.join(UPLOADS, fileName); fs.renameSync(f.filepath, newPath); const fileRec = { id: Date.now() + Math.random(), name: f.originalFilename || fileName, path: "/api/files/" + fileName, section: fields.section ? fields.section[0] : "other", size: f.size, date: new Date().toISOString() }; data.files.push(fileRec); uploaded.push(fileRec); } } writeData(data); res.writeHead(200, { "Content-Type": "application/json" }); return res.end(JSON.stringify({ ok: true, files: uploaded })); }); return; } if (req.method === "GET" && req.url.startsWith("/api/files/")) { const fileName = req.url.split("/")[3]; const filePath = path.join(UPLOADS, fileName); if (fs.existsSync(filePath)) { const ext = path.extname(fileName).toLowerCase(); const mime = ext === ".pdf" ? "application/pdf" : ext === ".docx" ? "application/vnd.openxmlformats-officedocument.wordprocessingml.document" : ext === ".xlsx" ? "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" : "application/octet-stream"; res.writeHead(200, { "Content-Type": mime, "Content-Disposition": "attachment; filename=\"" + fileName + "\"" }); return res.end(fs.readFileSync(filePath)); } res.writeHead(404); res.end("File not found"); return; } if (req.method === "DELETE" && req.url.startsWith("/api/files/")) { const fileName = req.url.split("/")[3]; const data = readData(); const fileRec = data.files.find(f => f.path.endsWith(fileName)); if (fileRec) { const filePath = path.join(UPLOADS, fileName); if (fs.existsSync(filePath)) fs.unlinkSync(filePath); data.files = data.files.filter(f => f.path !== fileRec.path); writeData(data); } res.writeHead(200, { "Content-Type": "application/json" }); return res.end(JSON.stringify({ ok: true })); } if (req.method === "POST" && req.url === "/api/inputData") { const d = await body(req); const data = readData(); data.inputData = d; writeData(data); res.writeHead(200, { "Content-Type": "application/json" }); return res.end(JSON.stringify({ ok: true })); } if (req.method === "POST" && req.url === "/api/suppliers") { const s = await body(req); const data = readData(); data.suppliers.push({ id: Date.now(), ...s }); writeData(data); res.writeHead(200, { "Content-Type": "application/json" }); return res.end(JSON.stringify({ ok: true })); } if (req.method === "POST" && req.url === "/api/offers") { const o = await body(req); const data = readData(); data.offers.push({ id: Date.now(), ...o }); writeData(data); res.writeHead(200, { "Content-Type": "application/json" }); return res.end(JSON.stringify({ ok: true })); } if (req.method === "POST" && req.url === "/api/checks") { const c = await body(req); const data = readData(); data.checks = c; writeData(data); res.writeHead(200, { "Content-Type": "application/json" }); return res.end(JSON.stringify({ ok: true })); } if (req.method === "DELETE" && req.url.startsWith("/api/suppliers/")) { const id = parseInt(req.url.split("/")[3]); const data = readData(); data.suppliers = data.suppliers.filter(s => s.id !== id); data.offers = data.offers.filter(o => o.supplierId !== id); writeData(data); res.writeHead(200, { "Content-Type": "application/json" }); return res.end(JSON.stringify({ ok: true })); } if (req.method === "DELETE" && req.url.startsWith("/api/offers/")) { const id = parseInt(req.url.split("/")[3]); const data = readData(); data.offers = data.offers.filter(o => o.id !== id); writeData(data); res.writeHead(200, { "Content-Type": "application/json" }); return res.end(JSON.stringify({ ok: true })); } let file = req.url === "/" ? "/index.html" : req.url.split("?")[0]; const full = path.join(__dirname, file); if (full.startsWith(__dirname) && fs.existsSync(full) && fs.statSync(full).isFile()) { const ext = path.extname(full); const type = ext === ".css" ? "text/css" : ext === ".js" ? "application/javascript" : "text/html"; res.writeHead(200, { "Content-Type": type + "; charset=utf-8" }); return res.end(fs.readFileSync(full)); } res.writeHead(404); res.end("Not found"); }).listen(PORT, () => console.log("Сервер запущен на порту " + PORT));