{-# LANGUAGE OverloadedStrings #-} {- | Entry point for the Roux recipe server. Starts a Warp HTTP server and serves recipe content. -} module Main (main) where import Data.String (fromString) import qualified Network.Wai.Handler.Warp as Warp import qualified Options.Applicative as Opts import System.IO (BufferMode (NoBuffering), hSetBuffering, stderr, stdout) import qualified Roux -- --------------------------------------------------------------------------- -- CLI options -- --------------------------------------------------------------------------- data Options = Options { optHost :: String , optPort :: Int , optRecipeDir :: FilePath } optionsParser :: Opts.Parser Options optionsParser = Options <$> Opts.strOption ( Opts.long "host" <> Opts.metavar "HOST" <> Opts.help "Listen host" <> Opts.value "0.0.0.0" <> Opts.showDefault ) <*> Opts.option Opts.auto ( Opts.long "port" <> Opts.short 'p' <> Opts.metavar "PORT" <> Opts.help "Listen port" <> Opts.value 8080 <> Opts.showDefault ) <*> Opts.strOption ( Opts.long "recipe-dir" <> Opts.short 'r' <> Opts.metavar "DIR" <> Opts.help "Path to directory containing Cooklang recipe files" <> Opts.value "recipes" <> Opts.showDefault ) main :: IO () main = do -- Disable buffering so Docker sees log output immediately. hSetBuffering stdout NoBuffering hSetBuffering stderr NoBuffering opts <- Opts.execParser $ Opts.info (optionsParser Opts.<**> Opts.helper) ( Opts.fullDesc <> Opts.progDesc "Roux recipe management server" <> Opts.header "roux-server — personal/family recipe manager" ) let settings = Warp.setPort (optPort opts) $ Warp.setHost (fromString (optHost opts)) Warp.defaultSettings putStrLn $ "[roux] scanning recipes from " <> optRecipeDir opts putStrLn $ "[roux] listening on " <> optHost opts <> ":" <> show (optPort opts) waiApp <- Roux.app (optRecipeDir opts) Warp.runSettings settings waiApp