{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-} {-# HLINT ignore "Use maybe" #-} module AirGQL.ExternalAppContext ( SandboxingConfig (..), ExternalAppContext (..), getExternalAppContext, ) where import Protolude ( FilePath, IO, Maybe (Just, Nothing), Show, Text, not, pure, ($), (&&), (/=), (<|>), (==), ) import Protolude qualified as P import Data.ByteString qualified as BS import Data.Text qualified as T import System.Environment (lookupEnv) import System.Info (os) import System.Process.Typed (ExitCode (ExitSuccess), proc, readProcessStdout) lookupBinaryPath :: Text -> IO (Maybe FilePath) lookupBinaryPath :: Text -> IO (Maybe String) lookupBinaryPath Text name = do (ExitCode code, ByteString resultBS) <- ProcessConfig () () () -> IO (ExitCode, ByteString) forall (m :: * -> *) stdin stdoutIgnored stderr. MonadIO m => ProcessConfig stdin stdoutIgnored stderr -> m (ExitCode, ByteString) readProcessStdout (ProcessConfig () () () -> IO (ExitCode, ByteString)) -> ProcessConfig () () () -> IO (ExitCode, ByteString) forall a b. (a -> b) -> a -> b $ String -> [String] -> ProcessConfig () () () proc String "which" [Text -> String T.unpack Text name] let result :: Text result = Text -> Text T.strip (Text -> Text) -> Text -> Text forall a b. (a -> b) -> a -> b $ ByteString -> Text P.decodeUtf8 (ByteString -> Text) -> ByteString -> Text forall a b. (a -> b) -> a -> b $ ByteString -> ByteString BS.toStrict ByteString resultBS Maybe String -> IO (Maybe String) forall a. a -> IO a forall (f :: * -> *) a. Applicative f => a -> f a pure (Maybe String -> IO (Maybe String)) -> Maybe String -> IO (Maybe String) forall a b. (a -> b) -> a -> b $ if ExitCode code ExitCode -> ExitCode -> Bool forall a. Eq a => a -> a -> Bool == ExitCode ExitSuccess Bool -> Bool -> Bool && Text result Text -> Text -> Bool forall a. Eq a => a -> a -> Bool /= Text "" Bool -> Bool -> Bool && Bool -> Bool not (Text "which: no" Text -> Text -> Bool `T.isInfixOf` Text result) then String -> Maybe String forall a. a -> Maybe a Just (String -> Maybe String) -> String -> Maybe String forall a b. (a -> b) -> a -> b $ Text -> String T.unpack Text result else Maybe String forall a. Maybe a Nothing data SandboxingConfig = SandboxingConfig { SandboxingConfig -> String firejail :: FilePath , SandboxingConfig -> [String] extraBinds :: [FilePath] } deriving (Int -> SandboxingConfig -> ShowS [SandboxingConfig] -> ShowS SandboxingConfig -> String (Int -> SandboxingConfig -> ShowS) -> (SandboxingConfig -> String) -> ([SandboxingConfig] -> ShowS) -> Show SandboxingConfig forall a. (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a $cshowsPrec :: Int -> SandboxingConfig -> ShowS showsPrec :: Int -> SandboxingConfig -> ShowS $cshow :: SandboxingConfig -> String show :: SandboxingConfig -> String $cshowList :: [SandboxingConfig] -> ShowS showList :: [SandboxingConfig] -> ShowS Show) data ExternalAppContext = ExternalAppContext { ExternalAppContext -> String sqlite :: FilePath , ExternalAppContext -> Maybe String sqliteLib :: Maybe FilePath , ExternalAppContext -> Text baseUrl :: Text } deriving (Int -> ExternalAppContext -> ShowS [ExternalAppContext] -> ShowS ExternalAppContext -> String (Int -> ExternalAppContext -> ShowS) -> (ExternalAppContext -> String) -> ([ExternalAppContext] -> ShowS) -> Show ExternalAppContext forall a. (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a $cshowsPrec :: Int -> ExternalAppContext -> ShowS showsPrec :: Int -> ExternalAppContext -> ShowS $cshow :: ExternalAppContext -> String show :: ExternalAppContext -> String $cshowList :: [ExternalAppContext] -> ShowS showList :: [ExternalAppContext] -> ShowS Show) getExternalAppContext :: Text -> IO ExternalAppContext getExternalAppContext :: Text -> IO ExternalAppContext getExternalAppContext Text baseUrl = do Maybe String sqlite <- Text -> IO (Maybe String) lookupBinaryPath Text "sqlite3" Maybe String sqliteEnv <- String -> IO (Maybe String) lookupEnv String "AIRGQL_SQLITE_BIN" Maybe String sqliteLib <- String -> IO (Maybe String) lookupEnv String "AIRGQL_SQLITE_LIB" ExternalAppContext -> IO ExternalAppContext forall a. a -> IO a forall (f :: * -> *) a. Applicative f => a -> f a pure (ExternalAppContext -> IO ExternalAppContext) -> ExternalAppContext -> IO ExternalAppContext forall a b. (a -> b) -> a -> b $ ExternalAppContext { $sel:baseUrl:ExternalAppContext :: Text baseUrl = Text baseUrl , $sel:sqlite:ExternalAppContext :: String sqlite = String -> Maybe String -> String forall a. a -> Maybe a -> a P.fromMaybe String "/usr/bin/sqlite3" (Maybe String -> String) -> Maybe String -> String forall a b. (a -> b) -> a -> b $ Maybe String sqliteEnv Maybe String -> Maybe String -> Maybe String forall a. Maybe a -> Maybe a -> Maybe a forall (f :: * -> *) a. Alternative f => f a -> f a -> f a <|> Maybe String sqlite , $sel:sqliteLib:ExternalAppContext :: Maybe String sqliteLib = Maybe String sqliteLib Maybe String -> Maybe String -> Maybe String forall a. Maybe a -> Maybe a -> Maybe a forall (f :: * -> *) a. Alternative f => f a -> f a -> f a <|> if String os String -> String -> Bool forall a. Eq a => a -> a -> Bool == String "darwin" then String -> Maybe String forall a. a -> Maybe a Just String "/usr/local/opt/sqlite/lib/libsqlite3.dylib" else Maybe String forall a. Maybe a Nothing }