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-08 15:36:52 +00:00
|
|
|
import { swagger } from '@elysiajs/swagger'
|
|
|
|
import { rateLimit } from 'elysia-rate-limit'
|
|
|
|
import { RateLimitError } from "./error/rate-limit-error";
|
|
|
|
import { helmet } from 'elysia-helmet';
|
|
|
|
import { etag } from '@bogeychan/elysia-etag'
|
|
|
|
import AppController from "./controller/app.controller";
|
2024-10-08 14:32:02 +00:00
|
|
|
|
|
|
|
const app = new Elysia();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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)
|
|
|
|
*/
|
|
|
|
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"),
|
|
|
|
}))
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Security settings
|
|
|
|
*/
|
|
|
|
app.use(helmet({
|
|
|
|
hsts: false, // Disable HSTS
|
|
|
|
contentSecurityPolicy: false, // Disable CSP
|
|
|
|
dnsPrefetchControl: true, // Enable DNS prefetch
|
|
|
|
}))
|
|
|
|
|
2024-10-08 14:32:02 +00:00
|
|
|
/**
|
|
|
|
* Controllers
|
|
|
|
*/
|
|
|
|
app.use(
|
|
|
|
decorators({
|
|
|
|
controllers: [AppController],
|
|
|
|
})
|
|
|
|
);
|
|
|
|
|
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);
|