{-# LANGUAGE OverloadedStrings #-} {- | Entry point for the Sis server. Starts a Warp HTTP server, serves the JSON API and the SPA frontend. -} module Main (main) where import Network.Wai.Handler.Warp qualified as Warp import Options.Applicative qualified as Opt import System.Posix.Signals qualified as Signals import Sis.Database qualified as Database import Sis.Server qualified as Sis data Options = Options { optPort :: Int , optStaticDir :: FilePath , optDbPath :: FilePath } optionsParser :: Opt.Parser Options optionsParser = Options <$> Opt.option Opt.auto ( Opt.long "port" <> Opt.short 'p' <> Opt.metavar "PORT" <> Opt.help "Listen port" <> Opt.value 8080 <> Opt.showDefault ) <*> Opt.strOption ( Opt.long "static-dir" <> Opt.metavar "DIR" <> Opt.help "Directory containing the SPA frontend static files" <> Opt.value "frontend/dist" <> Opt.showDefault ) <*> Opt.strOption ( Opt.long "db-path" <> Opt.metavar "PATH" <> Opt.help "Path to the SQLite database file" <> Opt.value "data/sis.db" <> Opt.showDefault ) main :: IO () main = do opts <- Opt.execParser $ Opt.info (optionsParser Opt.<**> Opt.helper) $ Opt.fullDesc <> Opt.progDesc "Sis — shared household chore tracker" <> Opt.header "sis-server" db <- Database.openDatabase (optDbPath opts) _ <- Signals.installHandler Signals.sigTERM (Signals.Catch (putStrLn "[sis] shutting down")) Nothing let waiApp = Sis.app (optStaticDir opts) db let settings = Warp.setPort (optPort opts) $ Warp.setBeforeMainLoop (putStrLn $ "[sis] listening on 0.0.0.0:" ++ show (optPort opts)) Warp.defaultSettings Warp.runSettings settings waiApp