import 'dotenv/config' import express from 'express' import cors from 'cors' import multer from 'multer' import { existsSync, mkdirSync } from 'node:fs' import { dirname, extname, join } from 'node:path' import { fileURLToPath } from 'node:url' import { randomUUID } from 'node:crypto' import { authMiddleware, loginHandler, meHandler } from './auth.js' import { readDb, updateDb } from './db.js' const __dirname = dirname(fileURLToPath(import.meta.url)) const UPLOADS_DIR = join(__dirname, '..', 'uploads') const PORT = Number(process.env.PORT) || 4000 if (!existsSync(UPLOADS_DIR)) mkdirSync(UPLOADS_DIR, { recursive: true }) const storage = multer.diskStorage({ destination: (_req, _file, cb) => cb(null, UPLOADS_DIR), filename: (_req, file, cb) => { const ext = extname(file.originalname) cb(null, `${randomUUID()}${ext}`) }, }) const upload = multer({ storage }) const app = express() const corsOrigin = process.env.CORS_ORIGIN?.split(',') || ['http://localhost:5173'] app.use(cors({ origin: corsOrigin, credentials: true })) app.use(express.json({ limit: '10mb' })) app.use('/uploads', express.static(UPLOADS_DIR)) app.post('/api/auth/login', loginHandler) app.get('/api/auth/me', authMiddleware, meHandler) app.get('/api/site', (_req, res) => { res.json(readDb().site) }) app.put('/api/site', authMiddleware, (req, res) => { const site = updateDb((db) => { db.site = req.body }).site res.json(site) }) app.get('/api/navigation', (_req, res) => { res.json(readDb().navigation) }) app.put('/api/navigation', authMiddleware, (req, res) => { const navigation = updateDb((db) => { db.navigation = req.body }).navigation res.json(navigation) }) app.get('/api/portfolio/categories', (_req, res) => { res.json(readDb().portfolioCategories) }) app.get('/api/portfolio/projects', (_req, res) => { res.json(readDb().projects) }) app.get('/api/portfolio/projects/:id', (req, res) => { const project = readDb().projects.find((p) => p.id === req.params.id) if (!project) return res.status(404).json({ error: 'پروژه یافت نشد' }) res.json(project) }) app.post('/api/portfolio/projects', authMiddleware, (req, res) => { const project = { id: randomUUID(), ...req.body } updateDb((db) => { db.projects.push(project) }) res.status(201).json(project) }) app.put('/api/portfolio/projects/:id', authMiddleware, (req, res) => { let updated = null updateDb((db) => { const i = db.projects.findIndex((p) => p.id === req.params.id) if (i === -1) return db.projects[i] = { ...db.projects[i], ...req.body, id: req.params.id } updated = db.projects[i] }) if (!updated) return res.status(404).json({ error: 'پروژه یافت نشد' }) res.json(updated) }) app.delete('/api/portfolio/projects/:id', authMiddleware, (req, res) => { let found = false updateDb((db) => { const i = db.projects.findIndex((p) => p.id === req.params.id) if (i !== -1) { db.projects.splice(i, 1) found = true } }) if (!found) return res.status(404).json({ error: 'پروژه یافت نشد' }) res.status(204).end() }) app.get('/api/services', (_req, res) => { res.json(readDb().services) }) app.put('/api/services', authMiddleware, (req, res) => { const services = updateDb((db) => { db.services = req.body }).services res.json(services) }) app.get('/api/services/:id', (req, res) => { const service = readDb().services.find((s) => s.id === req.params.id) if (!service) return res.status(404).json({ error: 'خدمت یافت نشد' }) res.json(service) }) app.put('/api/services/:id', authMiddleware, (req, res) => { let updated = null updateDb((db) => { const i = db.services.findIndex((s) => s.id === req.params.id) if (i === -1) return db.services[i] = { ...db.services[i], ...req.body, id: req.params.id } updated = db.services[i] }) if (!updated) return res.status(404).json({ error: 'خدمت یافت نشد' }) res.json(updated) }) app.get('/api/clients', (_req, res) => { res.json(readDb().clients) }) app.put('/api/clients', authMiddleware, (req, res) => { const clients = updateDb((db) => { db.clients = req.body }).clients res.json(clients) }) app.get('/api/stats', (_req, res) => { res.json(readDb().stats || []) }) app.get('/api/blog/posts', (_req, res) => { res.json(readDb().blogPosts.filter((p) => p.published)) }) app.get('/api/blog/posts/all', authMiddleware, (_req, res) => { res.json(readDb().blogPosts) }) app.get('/api/blog/posts/slug/:slug', (req, res) => { const post = readDb().blogPosts.find( (p) => p.slug === req.params.slug && p.published ) if (!post) return res.status(404).json({ error: 'مطلب یافت نشد' }) res.json(post) }) app.get('/api/blog/posts/:id', (req, res) => { const post = readDb().blogPosts.find((p) => p.id === req.params.id) if (!post) return res.status(404).json({ error: 'مطلب یافت نشد' }) res.json(post) }) app.post('/api/blog/posts', authMiddleware, (req, res) => { const post = { id: randomUUID(), published: false, publishedAt: new Date().toISOString(), ...req.body, } updateDb((db) => { db.blogPosts.push(post) }) res.status(201).json(post) }) app.put('/api/blog/posts/:id', authMiddleware, (req, res) => { let updated = null updateDb((db) => { const i = db.blogPosts.findIndex((p) => p.id === req.params.id) if (i === -1) return db.blogPosts[i] = { ...db.blogPosts[i], ...req.body, id: req.params.id } updated = db.blogPosts[i] }) if (!updated) return res.status(404).json({ error: 'مطلب یافت نشد' }) res.json(updated) }) app.delete('/api/blog/posts/:id', authMiddleware, (req, res) => { let found = false updateDb((db) => { const i = db.blogPosts.findIndex((p) => p.id === req.params.id) if (i !== -1) { db.blogPosts.splice(i, 1) found = true } }) if (!found) return res.status(404).json({ error: 'مطلب یافت نشد' }) res.status(204).end() }) app.get('/api/media', authMiddleware, (_req, res) => { res.json(readDb().media) }) app.post('/api/media/upload', authMiddleware, upload.single('file'), (req, res) => { if (!req.file) return res.status(400).json({ error: 'فایلی ارسال نشده' }) const item = { id: randomUUID(), filename: req.file.originalname, url: `/uploads/${req.file.filename}`, mimeType: req.file.mimetype, size: req.file.size, createdAt: new Date().toISOString(), } updateDb((db) => { db.media.unshift(item) }) res.status(201).json(item) }) app.listen(PORT, () => { console.log(`Noro CMS API running at http://localhost:${PORT}`) })