/**
* REST API Boilerplate
* Production-ready Express.js API structure
*/
import express, { Request, Response, NextFunction } from "express";
import cors from "cors";
import helmet from "helmet";
import { z } from "zod";
const app = express();
// Middleware
app.use(helmet());
app.use(cors());
app.use(express.json());
// Request validation middleware
function validate<T extends z.ZodSchema>(schema: T) {
return (req: Request, res: Response, next: NextFunction) => {
const result = schema.safeParse(req.body);
if (!result.success) {
return res.status(400).json({
error: "Validation failed",
details: result.error.flatten(),
});
}
req.body = result.data;
next();
};
}
// Error handler
app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
console.error(err.stack);
res.status(500).json({ error: "Internal server error" });
});
// Health check
app.get("/health", (req, res) => {
res.json({ status: "healthy", timestamp: new Date().toISOString() });
});
// Example CRUD routes
const ItemSchema = z.object({
name: z.string().min(1),
value: z.number(),
});
app.get("/api/items", async (req, res) => {
// TODO: Fetch from database
res.json({ items: [] });
});
app.post("/api/items", validate(ItemSchema), async (req, res) => {
const item = req.body;
// TODO: Save to database
res.status(201).json({ item });
});
app.get("/api/items/:id", async (req, res) => {
const { id } = req.params;
// TODO: Fetch from database
res.json({ id });
});
app.put("/api/items/:id", validate(ItemSchema), async (req, res) => {
const { id } = req.params;
const item = req.body;
// TODO: Update in database
res.json({ id, ...item });
});
app.delete("/api/items/:id", async (req, res) => {
const { id } = req.params;
// TODO: Delete from database
res.status(204).send();
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));