158 lines
4.2 KiB
TypeScript
Executable File
158 lines
4.2 KiB
TypeScript
Executable File
import Fastify from "fastify";
|
|
import config from "@/lib/config";
|
|
import { accessSync, constants as fsConst } from "node:fs";
|
|
import staticStream from "@fastify/static";
|
|
import { styleText } from "node:util";
|
|
import Routes from "@/routes";
|
|
import Database from "@/lib/db";
|
|
import Logger from "@/lib/logger";
|
|
import AccessLog from "@/lib/access";
|
|
import Authorization from "@/lib/auth";
|
|
import { RequestContext } from "@mikro-orm/core";
|
|
import { DatabaseError, ErrorBase } from "@/errors";
|
|
import { ConfigEntity } from "@/modules/entities/Config";
|
|
|
|
process.title = "LynqChat";
|
|
|
|
const logger = new Logger("Core");
|
|
logger.info("Process started...");
|
|
|
|
if (process.env.NODE_ENV !== "production") {
|
|
process.title = "LynqChat backend";
|
|
logger.warn(styleText(["red", "bold", "bgYellow"], "Development environment avaiable!!"));
|
|
}
|
|
|
|
const fastify = Fastify({
|
|
logger: false,
|
|
trustProxy: config.server.trustProxy,
|
|
bodyLimit: 1024 * 100,
|
|
});
|
|
|
|
try {
|
|
fastify.setErrorHandler((err, req, res) => {
|
|
res.header("Content-Type", "application/json");
|
|
|
|
const customLogger = new Logger("Unknown(Error handler)");
|
|
customLogger.error("Unknown error:", err);
|
|
|
|
return res.status(500).send(ErrorBase({
|
|
bad: "server",
|
|
code: "unknown_error",
|
|
message: "不明なエラーが発生しました。",
|
|
}));
|
|
});
|
|
|
|
if (process.env.NODE_ENV === "production") {
|
|
try {
|
|
accessSync(`${import.meta.dirname}/../../frontend/dist/index.html`, fsConst.R_OK);
|
|
|
|
await fastify.register(staticStream, {
|
|
root: `${import.meta.dirname}/../../frontend/dist`,
|
|
index: "/",
|
|
});
|
|
} catch (err) {
|
|
logger.error("It's in production but the frontend dist is not found.");
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
fastify.setNotFoundHandler((req, res) => {
|
|
if (req.url.startsWith("/api")) {
|
|
res.header("Content-Type", "application/json");
|
|
|
|
return res.code(404).send(ErrorBase({
|
|
bad: "client",
|
|
code: "endpoint_not_found",
|
|
message: "エンドポイントが見つかりませんでした。",
|
|
}));
|
|
}
|
|
|
|
if (process.env.NODE_ENV === "production") {
|
|
return res.sendFile("index.html");
|
|
}
|
|
|
|
return res.code(500).send();
|
|
});
|
|
|
|
await fastify.register(Database);
|
|
|
|
fastify.addHook("onRequest", (req, res, done) => {
|
|
RequestContext.create(fastify.orm.em, done);
|
|
});
|
|
|
|
fastify.addHook("onRequest", async (req, res) => {
|
|
if (
|
|
req.url.startsWith("/api") &&
|
|
!req.url.startsWith("/api/setup")
|
|
) {
|
|
try {
|
|
const configCount = await fastify.orm.em.count(ConfigEntity);
|
|
|
|
if (configCount === 0) {
|
|
return res.code(409).send(ErrorBase({
|
|
bad: "client",
|
|
code: "yet_initialization",
|
|
message: "初期設定が行われていません。",
|
|
}));
|
|
}
|
|
} catch (err) {
|
|
const customLogger = new Logger("Check already initialized hook");
|
|
customLogger.error("Database error: Could not check if already initialization:", err);
|
|
|
|
return res.code(500).send(DatabaseError());
|
|
}
|
|
}
|
|
});
|
|
|
|
await fastify.register(AccessLog);
|
|
await fastify.register(Authorization);
|
|
|
|
fastify.removeAllContentTypeParsers();
|
|
|
|
fastify.addContentTypeParser("application/json", { parseAs: "string" }, (req, body, done) => {
|
|
try {
|
|
const json = JSON.parse(
|
|
typeof body === "string"
|
|
? body
|
|
: body.toString("utf-8")
|
|
);
|
|
|
|
done(null, json);
|
|
} catch (err) {
|
|
done(null, {});
|
|
}
|
|
});
|
|
|
|
await fastify.register(Routes, {
|
|
prefix: "/api",
|
|
});
|
|
|
|
const addr = await fastify.listen({
|
|
port: config.server.port,
|
|
host: config.server.host,
|
|
});
|
|
|
|
if (process.env.NODE_ENV === "production") {
|
|
logger.info(`Listening at ${addr}`);
|
|
} else {
|
|
logger.info(`Backend listening at ${addr}`);
|
|
}
|
|
} catch (err) {
|
|
logger.error(err);
|
|
process.exit(1);
|
|
}
|
|
|
|
const shutdown = async () => {
|
|
try {
|
|
await fastify.close();
|
|
logger.log("Server downed.");
|
|
process.exit(0);
|
|
} catch (err) {
|
|
logger.error("Server down failed", err);
|
|
process.exit(1);
|
|
}
|
|
};
|
|
|
|
process.once("SIGINT", shutdown);
|
|
process.once("SIGTERM", shutdown);
|