import type { Express } from "express"; import { createServer, type Server } from "http"; import { storage } from "./storage"; import { insertArticleSchema } from "@shared/schema"; import { seedDatabase } from "./seed"; import multer from "multer"; import path from "path"; import fs from "fs"; const uploadDir = path.join(process.cwd(), "client/public/uploads"); if (!fs.existsSync(uploadDir)) { fs.mkdirSync(uploadDir, { recursive: true }); } const upload = multer({ storage: multer.diskStorage({ destination: (_req, _file, cb) => cb(null, uploadDir), filename: (_req, file, cb) => { const uniqueSuffix = Date.now() + "-" + Math.round(Math.random() * 1e9); const ext = path.extname(file.originalname); cb(null, uniqueSuffix + ext); }, }), limits: { fileSize: 10 * 1024 * 1024 }, fileFilter: (_req, file, cb) => { const allowed = /jpeg|jpg|png|gif|webp/; const ext = allowed.test(path.extname(file.originalname).toLowerCase()); const mime = allowed.test(file.mimetype); cb(null, ext && mime); }, }); export async function registerRoutes( httpServer: Server, app: Express ): Promise { await seedDatabase(); app.get("/api/articles", async (_req, res) => { const articles = await storage.getArticles(); res.json(articles); }); app.get("/api/articles/featured", async (_req, res) => { const articles = await storage.getFeaturedArticles(); res.json(articles); }); app.get("/api/articles/popular", async (req, res) => { const limit = parseInt(req.query.limit as string) || 5; const articles = await storage.getPopularArticles(limit); res.json(articles); }); app.get("/api/articles/category/:category", async (req, res) => { const articles = await storage.getArticlesByCategory(req.params.category); res.json(articles); }); app.get("/api/articles/:slug", async (req, res) => { const article = await storage.getArticleBySlug(req.params.slug); if (!article) { return res.status(404).json({ message: "Article not found" }); } await storage.incrementViews(article.id); res.json({ ...article, views: article.views + 1 }); }); app.post("/api/articles", async (req, res) => { const parsed = insertArticleSchema.safeParse(req.body); if (!parsed.success) { return res.status(400).json({ message: "Invalid article data", errors: parsed.error.flatten() }); } const existing = await storage.getArticleBySlug(parsed.data.slug); if (existing) { return res.status(409).json({ message: `Artikel "${existing.title}" existiert bereits (ID: ${existing.id})` }); } const article = await storage.createArticle(parsed.data); res.status(201).json(article); }); app.patch("/api/articles/:id", async (req, res) => { const id = parseInt(req.params.id); const partial = insertArticleSchema.partial().safeParse(req.body); if (!partial.success) { return res.status(400).json({ message: "Invalid article data", errors: partial.error.flatten() }); } const article = await storage.updateArticle(id, partial.data); if (!article) { return res.status(404).json({ message: "Article not found" }); } res.json(article); }); app.delete("/api/articles/:id", async (req, res) => { const id = parseInt(req.params.id); await storage.deleteArticle(id); res.status(204).send(); }); app.post("/api/upload", upload.single("image"), (req, res) => { if (!req.file) { return res.status(400).json({ message: "No file uploaded" }); } const url = `/uploads/${req.file.filename}`; res.json({ url }); }); return httpServer; }