nado-sozdat-po-marketingovom/server.js

163 lines
6.2 KiB
JavaScript

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