Files
AniKotoAPI/server.js
T
Sʜɪɴᴇɪ Nᴏᴜᴢᴇɴ 0034617c3b v1.5.0: Complete documentation rewrite - 50+ files with AlisaReactionBot style
- Box-style header comments (Project, Author, License) on every file
- Section headers using double-line box decorators
- Feature markers (// ---- FEATURE: XYZ ----) before every major function
- JSDoc comments for EVERY function with @param, @returns, @example
- Inline notes (NOTE, WARNING, TIP) for non-obvious logic
- Footer END markers on every module
- Matched code style to AlisaReactionBot repository
- All files now searchable by feature name via grep

Author: Shinei Nouzen <157171073+Shineii86@users.noreply.github.com>
2026-06-08 16:14:01 +05:30

131 lines
6.1 KiB
JavaScript

/*
* ======= • ======= • ======= • ======= • =======• =======
* AniKatoAPI — server.js
* Repository: https://github.com/Shineii86/AniKatoAPI
*
* @description
* Main entry point for the AniKatoAPI Express server.
* Configures CORS, middleware, static files, API routes,
* and 404 handling. Starts the server on the configured port.
*
* @exports
* None (side-effect: starts Express server)
*
* @author Shinei Nouzen
* @license MIT
* ======= • ======= • ======= • ======= • =======• =======
*/
import dotenv from "dotenv";
import express from "express";
import cors from "cors";
import path from "path";
import fs from "fs";
import { fileURLToPath } from "url";
import { dirname } from "path";
import { createApiRoutes } from "./src/routes/apiRoutes.js";
dotenv.config();
// ══════════════════════════════════════════════════════════════
// SERVER CONFIGURATION
// ══════════════════════════════════════════════════════════════
const app = express();
const PORT = process.env.PORT || 4444;
const __filename = fileURLToPath(import.meta.url);
const publicDir = path.join(dirname(__filename), "public");
const allowedOrigins = process.env.ALLOWED_ORIGINS?.split(",");
// ══════════════════════════════════════════════════════════════
// CORS MIDDLEWARE
// ══════════════════════════════════════════════════════════════
// NOTE: CORS is configured to only allow GET requests from specified origins
app.use(
cors({
origin: allowedOrigins?.includes("*") ? "*" : allowedOrigins || [],
methods: ["GET"],
})
);
// ---- FEATURE: Custom origin validation middleware ----
app.use((req, res, next) => {
const origin = req.headers.origin;
if (
!allowedOrigins ||
allowedOrigins.includes("*") ||
(origin && allowedOrigins.includes(origin))
) {
res.setHeader("Access-Control-Allow-Origin", origin || "*");
res.setHeader("Access-Control-Allow-Methods", "GET");
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
return next();
}
res
.status(403)
.json({ success: false, message: "Forbidden: Origin not allowed" });
});
// ══════════════════════════════════════════════════════════════
// STATIC FILES
// ══════════════════════════════════════════════════════════════
// NOTE: redirect: false prevents automatic redirects to index.html
app.use(express.static(publicDir, { redirect: false }));
// ══════════════════════════════════════════════════════════════
// RESPONSE HELPERS
// ══════════════════════════════════════════════════════════════
// ---- FEATURE: Standardized JSON response wrapper ----
/**
* Wraps data in a standardized success JSON response.
*
* @param {object} res - Express response object
* @param {*} data - The data to return in the response
* @param {number} status - HTTP status code (default: 200)
*/
const jsonResponse = (res, data, status = 200) =>
res.status(status).json({ success: true, results: data });
// ---- FEATURE: Standardized error response wrapper ----
/**
* Returns a standardized error JSON response.
*
* @param {object} res - Express response object
* @param {string} message - Error message to return (default: "Internal server error")
* @param {number} status - HTTP status code (default: 500)
*/
const jsonError = (res, message = "Internal server error", status = 500) =>
res.status(status).json({ success: false, message });
// ══════════════════════════════════════════════════════════════
// API ROUTES
// ══════════════════════════════════════════════════════════════
createApiRoutes(app, jsonResponse, jsonError);
// ══════════════════════════════════════════════════════════════
// 404 HANDLER
// ══════════════════════════════════════════════════════════════
// ---- FEATURE: Catch-all 404 handler for undefined routes ----
app.use((req, res) => {
const filePath = path.join(publicDir, "404.html");
if (fs.existsSync(filePath)) {
res.status(404).sendFile(filePath);
} else {
res.status(404).json({ success: false, message: "Endpoint not found" });
}
});
// ══════════════════════════════════════════════════════════════
// SERVER START
// ══════════════════════════════════════════════════════════════
app.listen(PORT, () => {
console.info(`AniKatoAPI listening at ${PORT}`);
});
// ══════════════════════════════════════════════════════════════ END: server.js