2024-04-15 20:03:10 +02:00
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" ;
2024-04-14 10:12:41 +02:00
import { count } from "drizzle-orm" ;
2024-04-15 07:08:16 +02:00
import { LogLevel , LogManager , type MultiLogManager } from "log-manager" ;
2024-04-14 10:12:41 +02:00
import { db , setupDatabase } from "~drizzle/db" ;
2024-04-17 08:36:01 +02:00
import { Notes } from "~drizzle/schema" ;
2024-04-13 14:20:12 +02:00
import { createServer } from "~server" ;
2023-11-23 00:04:31 +01:00
2023-11-30 05:16:58 +01:00
const timeAtStart = performance . now ( ) ;
2023-09-11 05:54:14 +02:00
2024-04-15 07:08:16 +02:00
const isEntry = import . meta . path === Bun . main ;
2024-04-15 07:13:11 +02:00
let dualServerLogger : LogManager | MultiLogManager = new LogManager (
2024-04-15 07:08:16 +02:00
Bun . file ( "/dev/null" ) ,
) ;
if ( isEntry ) {
2024-04-15 07:13:11 +02:00
dualServerLogger = dualLogger ;
2024-04-15 07:08:16 +02:00
}
2024-04-15 07:13:11 +02:00
await dualServerLogger . log ( LogLevel . INFO , "Lysand" , "Starting Lysand..." ) ;
2023-12-09 04:32:45 +01:00
2024-04-15 07:13:11 +02:00
await setupDatabase ( dualServerLogger ) ;
2023-12-09 02:51:48 +01:00
2023-12-03 05:11:30 +01:00
if ( config . meilisearch . enabled ) {
2024-04-15 07:13:11 +02:00
await connectMeili ( dualServerLogger ) ;
2023-12-03 05:11:30 +01:00
}
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 {
2024-04-11 13:39:07 +02:00
postCount = (
await db
. select ( {
count : count ( ) ,
} )
2024-04-17 08:36:01 +02:00
. from ( Notes )
2024-04-11 13:39:07 +02:00
) [ 0 ] . count ;
2023-11-21 00:58:39 +01:00
} catch ( e ) {
2024-04-11 13:39:07 +02:00
const error = e as Error ;
2024-04-15 07:13:11 +02:00
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
}
2024-04-15 03:35:56 +02:00
2024-04-18 10:42:12 +02: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_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 ) ;
}
}
2024-04-15 07:13:11 +02:00
const server = createServer ( config , dualServerLogger , true ) ;
2023-11-11 03:36:06 +01:00
2024-04-15 07:13:11 +02:00
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
2024-04-15 07:13:11 +02: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
) ;
2024-04-15 20:50:06 +02: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 ) ;
}
2024-04-15 03:35:56 +02:00
2024-04-15 20:50:06 +02:00
// 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 {
2024-04-15 07:13:11 +02:00
await dualServerLogger . log (
2024-04-15 20:50:06 +02:00
LogLevel . WARNING ,
2024-04-15 03:35:56 +02:00
"Server" ,
2024-04-15 20:50:06 +02:00
"Frontend is disabled, skipping check" ,
2024-04-15 03:35:56 +02:00
) ;
}
2024-03-11 03:04:14 +01:00
export { config , server } ;