server/index.ts

165 lines
4.4 KiB
TypeScript
Raw Normal View History

import { dualLogger } from "@loggers";
2024-04-07 07:30:49 +02:00
import { connectMeili } from "@meilisearch";
2024-04-07 06:16:54 +02:00
import { config } from "config-manager";
import { count } from "drizzle-orm";
import { LogLevel, LogManager, type MultiLogManager } from "log-manager";
import { db, setupDatabase } from "~drizzle/db";
import { Notes } from "~drizzle/schema";
import { createServer } from "~server";
2023-11-30 05:16:58 +01:00
const timeAtStart = performance.now();
2023-09-11 05:54:14 +02:00
const isEntry = import.meta.path === Bun.main;
let dualServerLogger: LogManager | MultiLogManager = new LogManager(
Bun.file("/dev/null"),
);
if (isEntry) {
dualServerLogger = dualLogger;
}
await dualServerLogger.log(LogLevel.INFO, "Lysand", "Starting Lysand...");
await setupDatabase(dualServerLogger);
if (config.meilisearch.enabled) {
await connectMeili(dualServerLogger);
}
2023-11-21 00:58:39 +01:00
// Check if database is reachable
2023-11-29 04:57:35 +01:00
let postCount = 0;
2023-11-21 00:58:39 +01:00
try {
postCount = (
await db
.select({
count: count(),
})
.from(Notes)
)[0].count;
2023-11-21 00:58:39 +01:00
} catch (e) {
const error = e as Error;
await dualServerLogger.logError(LogLevel.CRITICAL, "Database", error);
2024-04-07 07:30:49 +02:00
process.exit(1);
2023-11-21 00:58:39 +01:00
}
if (isEntry) {
// Check if JWT private key is set in config
if (!config.oidc.jwt_key) {
await dualServerLogger.log(
LogLevel.CRITICAL,
"Server",
"The JWT private key is not set in the config",
);
await dualServerLogger.log(
LogLevel.CRITICAL,
"Server",
"Below is a generated key for you to copy in the config at oidc.jwt_key",
);
// Generate a key for them
const keys = await crypto.subtle.generateKey("Ed25519", true, [
"sign",
"verify",
]);
const privateKey = Buffer.from(
await crypto.subtle.exportKey("pkcs8", keys.privateKey),
).toString("base64");
const publicKey = Buffer.from(
await crypto.subtle.exportKey("spki", keys.publicKey),
).toString("base64");
await dualServerLogger.log(
LogLevel.CRITICAL,
"Server",
`${privateKey};${publicKey}`,
);
process.exit(1);
}
// Try and import the key
const privateKey = await crypto.subtle
.importKey(
"pkcs8",
Buffer.from(config.oidc.jwt_key.split(";")[0], "base64"),
"Ed25519",
false,
["sign"],
)
.catch((e) => e as Error);
// Try and import the key
const publicKey = await crypto.subtle
.importKey(
"spki",
Buffer.from(config.oidc.jwt_key.split(";")[1], "base64"),
"Ed25519",
false,
["verify"],
)
.catch((e) => e as Error);
if (privateKey instanceof Error || publicKey instanceof Error) {
await dualServerLogger.log(
LogLevel.CRITICAL,
"Server",
"The JWT key could not be imported! You may generate a new one by removing the old one from the config and restarting the server (this will invalidate all current JWTs).",
);
process.exit(1);
}
}
const server = createServer(config, dualServerLogger, true);
await dualServerLogger.log(
2024-04-07 07:30:49 +02:00
LogLevel.INFO,
"Server",
`Lysand started at ${config.http.bind}:${config.http.bind_port} in ${(
performance.now() - timeAtStart
).toFixed(0)}ms`,
2023-10-23 02:32:17 +02:00
);
2023-11-21 00:58:39 +01:00
await dualServerLogger.log(
2024-04-07 07:30:49 +02:00
LogLevel.INFO,
"Database",
`Database is online, now serving ${postCount} posts`,
2023-11-21 00:58:39 +01:00
);
if (config.frontend.enabled) {
if (!URL.canParse(config.frontend.url)) {
await dualServerLogger.log(
LogLevel.ERROR,
"Server",
`Frontend URL is not a valid URL: ${config.frontend.url}`,
);
process.exit(1);
}
// Check if frontend is reachable
const response = await fetch(new URL("/", config.frontend.url))
.then((res) => res.ok)
.catch(() => false);
if (!response) {
await dualServerLogger.log(
LogLevel.ERROR,
"Server",
`Frontend is unreachable at ${config.frontend.url}`,
);
await dualServerLogger.log(
LogLevel.ERROR,
"Server",
"Please ensure the frontend is online and reachable",
);
}
} else {
await dualServerLogger.log(
LogLevel.WARNING,
"Server",
"Frontend is disabled, skipping check",
);
}
export { config, server };