This repository has been archived on 2024-10-29. You can view files and clone it, but cannot push or open issues or pull requests.
scoresaber-reloadedv3/projects/backend/src/index.ts

117 lines
2.5 KiB
TypeScript
Raw Normal View History

2024-10-08 14:32:02 +00:00
import { Elysia } from "elysia";
import cors from "@elysiajs/cors";
import { decorators } from "elysia-decorators";
import { logger } from "@tqman/nice-logger";
2024-10-09 00:17:00 +00:00
import { swagger } from "@elysiajs/swagger";
import { rateLimit } from "elysia-rate-limit";
2024-10-08 15:36:52 +00:00
import { RateLimitError } from "./error/rate-limit-error";
2024-10-09 00:17:00 +00:00
import { helmet } from "elysia-helmet";
import { etag } from "@bogeychan/elysia-etag";
2024-10-08 15:36:52 +00:00
import AppController from "./controller/app.controller";
2024-10-09 00:17:00 +00:00
import * as dotenv from "@dotenvx/dotenvx";
import mongoose from "mongoose";
import { Config } from "./common/config";
import { setLogLevel } from "@typegoose/typegoose";
import PlayerController from "./controller/player.controller";
import { PlayerService } from "./service/player.service";
2024-10-08 14:32:02 +00:00
2024-10-09 00:17:00 +00:00
// Load .env file
dotenv.config({
logLevel: "success",
path: ".env",
override: true,
});
await mongoose.connect(Config.mongoUri!); // Connect to MongoDB
setLogLevel("DEBUG");
export const app = new Elysia();
2024-10-08 14:32:02 +00:00
/**
* Custom error handler
*/
app.onError({ as: "global" }, ({ code, error }) => {
// Return default error for type validation
if (code === "VALIDATION") {
return error.all;
}
let status = "status" in error ? error.status : undefined;
return {
...((status && { statusCode: status }) || { status: code }),
...(error.message != code && { message: error.message }),
timestamp: new Date().toISOString(),
};
});
2024-10-08 15:36:52 +00:00
/**
* Enable E-Tags
*/
app.use(etag());
2024-10-08 14:32:02 +00:00
/**
* Enable CORS
*/
app.use(cors());
/**
* Request logger
*/
app.use(
logger({
mode: "combined",
})
);
2024-10-08 15:36:52 +00:00
/**
* Rate limit (100 requests per minute)
*/
2024-10-09 00:17:00 +00:00
app.use(
rateLimit({
scoping: "global",
duration: 60 * 1000,
max: 100,
skip: request => {
let [_, path] = request.url.split("/"); // Get the url parts
path === "" || (path === undefined && (path = "/")); // If we're on /, the path is undefined, so we set it to /
return path === "/"; // ignore all requests to /
},
errorResponse: new RateLimitError("Too many requests, please try again later"),
})
);
2024-10-08 15:36:52 +00:00
/**
* Security settings
*/
2024-10-09 00:17:00 +00:00
app.use(
helmet({
hsts: false, // Disable HSTS
contentSecurityPolicy: false, // Disable CSP
dnsPrefetchControl: true, // Enable DNS prefetch
})
);
2024-10-08 15:36:52 +00:00
2024-10-08 14:32:02 +00:00
/**
* Controllers
*/
app.use(
decorators({
2024-10-09 00:17:00 +00:00
controllers: [AppController, PlayerController],
2024-10-08 14:32:02 +00:00
})
);
2024-10-10 00:15:16 +00:00
/**
* Start cronjobs
*/
PlayerService.initCronjobs();
2024-10-08 15:36:52 +00:00
/**
* Swagger Documentation
*/
app.use(swagger());
2024-10-08 14:32:02 +00:00
app.onStart(() => {
console.log("Listening on port http://localhost:8080");
});
app.listen(8080);