mirror of
https://github.com/versia-pub/server.git
synced 2025-12-06 16:38:19 +01:00
165 lines
4.4 KiB
TypeScript
165 lines
4.4 KiB
TypeScript
import { dualLogger } from "@loggers";
|
|
import { connectMeili } from "@meilisearch";
|
|
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";
|
|
|
|
const timeAtStart = performance.now();
|
|
|
|
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);
|
|
}
|
|
|
|
// Check if database is reachable
|
|
let postCount = 0;
|
|
try {
|
|
postCount = (
|
|
await db
|
|
.select({
|
|
count: count(),
|
|
})
|
|
.from(Notes)
|
|
)[0].count;
|
|
} catch (e) {
|
|
const error = e as Error;
|
|
await dualServerLogger.logError(LogLevel.CRITICAL, "Database", error);
|
|
process.exit(1);
|
|
}
|
|
|
|
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_private_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(
|
|
LogLevel.INFO,
|
|
"Server",
|
|
`Lysand started at ${config.http.bind}:${config.http.bind_port} in ${(
|
|
performance.now() - timeAtStart
|
|
).toFixed(0)}ms`,
|
|
);
|
|
|
|
await dualServerLogger.log(
|
|
LogLevel.INFO,
|
|
"Database",
|
|
`Database is online, now serving ${postCount} posts`,
|
|
);
|
|
|
|
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 };
|