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 { items: [], log: [] }; } } function writeData(d) { fs.writeFileSync(DATA, JSON.stringify(d, 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) => { const url = req.url.split("?")[0]; if (req.method === "GET" && url === "/api/items") { const d = readData(); res.writeHead(200, { "Content-Type": "application/json" }); return res.end(JSON.stringify(d.items)); } if (req.method === "POST" && url === "/api/items") { const item = await body(req); const d = readData(); item.id = Date.now(); item.date = item.date || new Date().toISOString().slice(0, 10); d.items.push(item); d.log.push({ when: new Date().toISOString(), what: "добавлена запись: " + (item.fio || "") }); writeData(d); res.writeHead(200, { "Content-Type": "application/json" }); return res.end(JSON.stringify({ ok: true })); } if (req.method === "DELETE" && url.startsWith("/api/items/")) { const id = parseInt(url.split("/").pop()); const d = readData(); const idx = d.items.findIndex((i) => i.id === id); if (idx !== -1) { const removed = d.items.splice(idx, 1)[0]; d.log.push({ when: new Date().toISOString(), what: "удалена запись: " + (removed.fio || "") }); writeData(d); } res.writeHead(200, { "Content-Type": "application/json" }); return res.end(JSON.stringify({ ok: true })); } if (req.method === "PUT" && url.startsWith("/api/items/")) { const id = parseInt(url.split("/").pop()); const upd = await body(req); const d = readData(); const idx = d.items.findIndex((i) => i.id === id); if (idx !== -1) { d.items[idx] = { ...d.items[idx], ...upd, id }; d.log.push({ when: new Date().toISOString(), what: "изменена запись: " + (upd.fio || "") }); writeData(d); } res.writeHead(200, { "Content-Type": "application/json" }); return res.end(JSON.stringify({ ok: true })); } if (req.method === "POST" && url === "/api/upload") { const form = formidable({ uploadDir: UPLOADS, keepExtensions: true, maxFileSize: 10 * 1024 * 1024 }); form.parse(req, function(err, fields, files) { var result = { ok: false }; if (!err) { var uploaded = []; if (files.file) { var arr = Array.isArray(files.file) ? files.file : [files.file]; arr.forEach(function(f) { if (f && f.filepath) { var name = f.originalFilename || "file"; var newPath = path.join(UPLOADS, Date.now() + "_" + name); fs.renameSync(f.filepath, newPath); uploaded.push({ name: name, path: "/uploads/" + path.basename(newPath) }); } }); } result.ok = true; result.files = uploaded; } res.writeHead(200, { "Content-Type": "application/json" }); return res.end(JSON.stringify(result)); }); return; } if (req.method === "GET" && url.startsWith("/uploads/")) { var fName = path.basename(url); var fPath = path.join(UPLOADS, fName); if (fs.existsSync(fPath) && fs.statSync(fPath).isFile()) { var ext = path.extname(fPath); var mime = { ".pdf": "application/pdf", ".doc": "application/msword", ".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document", ".xls": "application/vnd.ms-excel", ".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", ".jpg": "image/jpeg", ".jpeg": "image/jpeg", ".png": "image/png", ".gif": "image/gif" }; res.writeHead(200, { "Content-Type": mime[ext] || "application/octet-stream", "Content-Disposition": 'inline; filename="' + fName + '"' }); return res.end(fs.readFileSync(fPath)); } } let file = url === "/" ? "/index.html" : url; 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));