hledger/hledger-web/Hledger/Web/Main.hs
Stephen Morgan b0aa70b27a lib!: Rename the fields of ReportSpec.
This is done to be more consistent with future field naming conventions,
and to make automatic generation of lenses simpler. See discussion in
\#1545.

rsOpts -> _rsReportOpts
rsToday -> _rsDay
rsQuery -> _rsQuery
rsQueryOpts -> _rsQueryOpts
2021-07-23 10:37:08 -10:00

118 lines
4.6 KiB
Haskell

{-|
hledger-web - a hledger add-on providing a web interface.
Copyright (c) 2007-2020 Simon Michael <simon@joyful.com>
Released under GPL version 3 or later.
-}
{-# LANGUAGE MultiWayIf #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
module Hledger.Web.Main where
import Control.Exception (bracket)
import Control.Monad (when)
import Data.String (fromString)
import qualified Data.Text as T
import Network.Socket
import Network.Wai (Application)
import Network.Wai.Handler.Warp (runSettings, runSettingsSocket, defaultSettings, setHost, setPort)
import Network.Wai.Handler.Launch (runHostPortFullUrl)
import Prelude hiding (putStrLn)
import System.Directory (removeFile)
import System.Environment ( getArgs, withArgs )
import System.Exit (exitSuccess, exitFailure)
import System.IO (hFlush, stdout)
import System.PosixCompat.Files (getFileStatus, isSocket)
import Text.Printf (printf)
import Yesod.Default.Config
import Yesod.Default.Main (defaultDevelApp)
import Hledger
import Hledger.Cli hiding (progname,prognameandversion)
import Hledger.Utils.UTF8IOCompat (putStrLn)
import Hledger.Web.Application (makeApplication)
import Hledger.Web.Settings (Extra(..), parseExtra)
import Hledger.Web.Test (hledgerWebTest)
import Hledger.Web.WebOptions
-- Run in fast reloading mode for yesod devel.
hledgerWebDev :: IO (Int, Application)
hledgerWebDev =
withJournalDo (cliopts_ defwebopts) (defaultDevelApp loader . makeApplication defwebopts)
where
loader =
Yesod.Default.Config.loadConfig
(configSettings Development) {csParseExtra = parseExtra}
-- Run normally.
hledgerWebMain :: IO ()
hledgerWebMain = do
wopts@WebOpts{cliopts_=copts@CliOpts{debug_, rawopts_}} <- getHledgerWebOpts
when (debug_ > 0) $ printf "%s\n" prognameandversion >> printf "opts: %s\n" (show wopts)
if
| "help" `inRawOpts` rawopts_ -> putStr (showModeUsage webmode) >> exitSuccess
| "info" `inRawOpts` rawopts_ -> runInfoForTopic "hledger-web" Nothing
| "man" `inRawOpts` rawopts_ -> runManForTopic "hledger-web" Nothing
| "version" `inRawOpts` rawopts_ -> putStrLn prognameandversion >> exitSuccess
| "binary-filename" `inRawOpts` rawopts_ -> putStrLn (binaryfilename progname)
| "test" `inRawOpts` rawopts_ -> do
-- remove --test and --, leaving other args for hspec
filter (not . (`elem` ["--test","--"])) <$> getArgs >>= flip withArgs hledgerWebTest
| otherwise -> withJournalDo copts (web wopts)
-- | The hledger web command.
web :: WebOpts -> Journal -> IO ()
web opts j = do
let initq = _rsQuery . reportspec_ $ cliopts_ opts
j' = filterJournalTransactions initq j
h = host_ opts
p = port_ opts
u = base_url_ opts
staticRoot = T.pack <$> file_url_ opts
appconfig = AppConfig{appEnv = Development
,appHost = fromString h
,appPort = p
,appRoot = T.pack u
,appExtra = Extra "" Nothing staticRoot
}
app <- makeApplication opts j' appconfig
-- XXX would like to allow a host name not just an IP address here
_ <- printf "Serving web %s on %s:%d with base url %s\n"
(if serve_api_ opts then "API" else "UI and API" :: String) h p u
if serve_ opts || serve_api_ opts
then do
putStrLn "Press ctrl-c to quit"
hFlush stdout
let warpsettings = setHost (fromString h) (setPort p defaultSettings)
case socket_ opts of
Just s -> do
if isUnixDomainSocketAvailable then
bracket
(do
sock <- socket AF_UNIX Stream 0
setSocketOption sock ReuseAddr 1
bind sock $ SockAddrUnix s
listen sock maxListenQueue
return sock
)
(\_ -> do
sockstat <- getFileStatus s
when (isSocket sockstat) $ removeFile s
)
(\sock -> Network.Wai.Handler.Warp.runSettingsSocket warpsettings sock app)
else do
putStrLn "Unix domain sockets are not available on your operating system"
putStrLn "Please try again without --socket"
exitFailure
Nothing -> Network.Wai.Handler.Warp.runSettings warpsettings app
else do
putStrLn "This server will exit after 2m with no browser windows open (or press ctrl-c)"
putStrLn "Opening web browser..."
hFlush stdout
-- exits after 2m of inactivity (hardcoded)
Network.Wai.Handler.Launch.runHostPortFullUrl h p u app