108 lines
3.7 KiB
TypeScript
108 lines
3.7 KiB
TypeScript
import { Application, Router } from "@oak/oak";
|
|
import { config } from "./config/env.ts";
|
|
import { db } from "./config/database.ts";
|
|
import { cors, securityHeaders, requestLogger, rateLimit } from "./middleware/security.ts";
|
|
|
|
// Import routes
|
|
import authRoutes from "./routes/auth.ts";
|
|
import userRoutes from "./routes/users.ts";
|
|
import departmentRoutes from "./routes/departments.ts";
|
|
import workAllocationRoutes from "./routes/work-allocations.ts";
|
|
import attendanceRoutes from "./routes/attendance.ts";
|
|
import contractorRateRoutes from "./routes/contractor-rates.ts";
|
|
|
|
// Initialize database connection
|
|
await db.connect();
|
|
|
|
// Create Oak application
|
|
const app = new Application();
|
|
|
|
// Global error handler
|
|
app.use(async (ctx, next) => {
|
|
try {
|
|
await next();
|
|
} catch (err) {
|
|
const error = err as Error & { status?: number };
|
|
console.error("Error:", error.message);
|
|
ctx.response.status = error.status || 500;
|
|
ctx.response.body = {
|
|
error: config.isDevelopment() ? error.message : "Internal server error",
|
|
};
|
|
}
|
|
});
|
|
|
|
// Apply security middleware
|
|
app.use(cors);
|
|
app.use(securityHeaders);
|
|
app.use(requestLogger);
|
|
|
|
// Rate limiting (only in production or if enabled)
|
|
if (config.isProduction()) {
|
|
app.use(rateLimit);
|
|
}
|
|
|
|
// Create main router
|
|
const router = new Router();
|
|
|
|
// Health check endpoint
|
|
router.get("/health", (ctx) => {
|
|
ctx.response.body = {
|
|
status: "ok",
|
|
timestamp: new Date().toISOString(),
|
|
version: "2.0.0-deno",
|
|
runtime: "Deno",
|
|
};
|
|
});
|
|
|
|
// Mount API routes
|
|
router.use("/api/auth", authRoutes.routes(), authRoutes.allowedMethods());
|
|
router.use("/api/users", userRoutes.routes(), userRoutes.allowedMethods());
|
|
router.use("/api/departments", departmentRoutes.routes(), departmentRoutes.allowedMethods());
|
|
router.use("/api/work-allocations", workAllocationRoutes.routes(), workAllocationRoutes.allowedMethods());
|
|
router.use("/api/attendance", attendanceRoutes.routes(), attendanceRoutes.allowedMethods());
|
|
router.use("/api/contractor-rates", contractorRateRoutes.routes(), contractorRateRoutes.allowedMethods());
|
|
|
|
// Apply routes
|
|
app.use(router.routes());
|
|
app.use(router.allowedMethods());
|
|
|
|
// 404 handler
|
|
app.use((ctx) => {
|
|
ctx.response.status = 404;
|
|
ctx.response.body = { error: "Route not found" };
|
|
});
|
|
|
|
// Graceful shutdown
|
|
const controller = new AbortController();
|
|
|
|
Deno.addSignalListener("SIGINT", () => {
|
|
console.log("\n🛑 Shutting down gracefully...");
|
|
controller.abort();
|
|
db.close();
|
|
Deno.exit(0);
|
|
});
|
|
|
|
Deno.addSignalListener("SIGTERM", () => {
|
|
console.log("\n🛑 Shutting down gracefully...");
|
|
controller.abort();
|
|
db.close();
|
|
Deno.exit(0);
|
|
});
|
|
|
|
// Start server
|
|
console.log(`
|
|
╔════════════════════════════════════════════════════════════╗
|
|
║ Work Allocation System - Deno Backend v2.0.0 ║
|
|
╠════════════════════════════════════════════════════════════╣
|
|
║ 🦕 Runtime: Deno ${Deno.version.deno} ║
|
|
║ 🔒 TypeScript with strict type checking ║
|
|
║ 🛡️ Security: Rate limiting, CORS, XSS protection ║
|
|
╚════════════════════════════════════════════════════════════╝
|
|
`);
|
|
|
|
console.log(`🚀 Server running on http://localhost:${config.PORT}`);
|
|
console.log(`📊 Health check: http://localhost:${config.PORT}/health`);
|
|
console.log(`🔧 Environment: ${config.NODE_ENV}`);
|
|
|
|
await app.listen({ port: config.PORT, signal: controller.signal });
|