on master help sign in
Remove old "get" config function and move getFrontendConfigs out of Internal
commit6cca93f04c7f0c04562bd7f4265c946bcadab1a6 authorKen Micklas <ken.micklas@obsidian.systems> dateMon 29 Apr 2019, 17:06 (7 years ago) parentaefb66a
13 files changed+97−156
lib/executable-config/inject/src/Obelisk/ExecutableConfig/Inject.hs+1−1 lib/executable-config/lookup/obelisk-executable-config.cabal−1 lib/executable-config/lookup/src-android/Obelisk/ExecutableConfig.hs+48−5 lib/executable-config/lookup/src-android/Obelisk/ExecutableConfig/Internal.hs−56 lib/executable-config/lookup/src-ghcjs/Obelisk/ExecutableConfig.hs+26−8 lib/executable-config/lookup/src-ghcjs/Obelisk/ExecutableConfig/Internal.hs−33 lib/executable-config/lookup/src-ios/Obelisk/ExecutableConfig.hs+8−13 lib/executable-config/lookup/src-ios/Obelisk/ExecutableConfig/Internal.hs−15 lib/executable-config/lookup/src/Obelisk/ExecutableConfig.hs+9−9 lib/executable-config/lookup/src/Obelisk/ExecutableConfig/Internal.hs−12 lib/frontend/src/Obelisk/Frontend.hs+1−1 lib/run/obelisk-run.cabal+1 lib/run/src/Obelisk/Run.hs+3−2
lib/executable-config/inject/src/Obelisk/ExecutableConfig/Inject.hs+1−1
@@ -9,7 +9,7 @@ import Data.ByteString (ByteString)
99import Data.Text (Text)
1010import qualified Data.Text as T
1111import qualified Data.Text.IO as T
12−import Obelisk.ExecutableConfig.Internal (getFrontendConfigs)
12+import Obelisk.ExecutableConfig (getFrontendConfigs)
1313import Reflex.Dom.Core hiding (value)
1414
1515-- | Produces a @<script>@ tag containing the contents of the config item,
lib/executable-config/lookup/obelisk-executable-config.cabal−1
@@ -5,7 +5,6 @@ build-type: Simple
55
66library
77 exposed-modules: Obelisk.ExecutableConfig
8− exposed-modules: Obelisk.ExecutableConfig.Internal
98 if os(ios)
109 hs-source-dirs: src-ios, src-directory
1110 other-modules: Obelisk.ExecutableConfig.Internal.ConfigDirectory
lib/executable-config/lookup/src-android/Obelisk/ExecutableConfig.hs+48−5
@@ -1,13 +1,56 @@
1−module Obelisk.ExecutableConfig (get) where
1+{-# LANGUAGE LambdaCase #-}
2+module Obelisk.ExecutableConfig where
23
34import Control.Exception (bracket)
5+import Control.Monad (forM)
6+import qualified Data.ByteString as BS
7+import Data.Map (Map)
8+import qualified Data.Map as Map
49import Data.Text (Text)
510import qualified Data.Text.Encoding as T
11+import Foreign.C.String (withCString)
12+import Foreign.Ptr (nullPtr)
613
7−import Obelisk.ExecutableConfig.Internal
814import Obelisk.ExecutableConfig.Internal.AssetManager
915
10−get :: Text -> IO (Maybe Text)
11−get name = bracket getAssets freeAssetManager $ \mgrObj -> do
16+getFromMgr :: AAssetManager -> BS.ByteString -> IO (Maybe Text)
17+getFromMgr mgr name = do
18+ let open = do
19+ a <- BS.useAsCString name $ \fn ->
20+ assetManager_open mgr fn 3
21+ return $ if unAAsset a == nullPtr
22+ then Nothing
23+ else Just a
24+ close = mapM_ asset_close
25+ bracket open close $ mapM $ \asset -> do
26+ b <- asset_getBuffer asset
27+ l <- asset_getLength asset
28+ fmap T.decodeUtf8 $ BS.packCStringLen (b, fromIntegral l)
29+
30+getFrontendConfigs :: IO (Map Text Text)
31+getFrontendConfigs = bracket getAssets freeAssetManager $ \mgrObj -> do
1232 mgr <- assetManagerFromJava mgrObj
13− getFromMgr mgr $ T.encodeUtf8 name
33+ let openDir = do
34+ d <- withCString "config.files" $ \fn ->
35+ assetManager_open mgr fn 3
36+ return $ if unAAsset d == nullPtr
37+ then Nothing
38+ else Just d
39+ closeDir = mapM_ asset_close
40+ configPaths <- bracket openDir closeDir $ \case
41+ Just asset -> do
42+ b <- asset_getBuffer asset
43+ l <- asset_getLength asset
44+ lines0 <$> BS.packCStringLen (b, fromIntegral l)
45+ Nothing -> error "could not open configuration manifest 'config.files'"
46+ fmap Map.fromList $ forM configPaths $ \fp ->
47+ getFromMgr mgr fp >>= \case
48+ Just v -> return (T.decodeUtf8 fp, v)
49+ Nothing -> error $ "Config present in config.files but not in assets: " <> show fp
50+
51+lines0 :: BS.ByteString -> [BS.ByteString]
52+lines0 ps
53+ | BS.null ps = []
54+ | otherwise = case BS.elemIndex 0 ps of
55+ Nothing -> [ps]
56+ Just n -> BS.take n ps : lines0 (BS.drop (n+1) ps)
lib/executable-config/lookup/src-android/Obelisk/ExecutableConfig/Internal.hsdeleted−56
@@ -1,56 +0,0 @@
1−{-# LANGUAGE LambdaCase #-}
2−module Obelisk.ExecutableConfig.Internal where
3−
4−import Control.Exception (bracket)
5−import Control.Monad (forM)
6−import qualified Data.ByteString as BS
7−import Data.Map (Map)
8−import qualified Data.Map as Map
9−import Data.Text (Text)
10−import qualified Data.Text.Encoding as T
11−import Foreign.C.String (withCString)
12−import Foreign.Ptr (nullPtr)
13−
14−import Obelisk.ExecutableConfig.Internal.AssetManager
15−
16−getFromMgr :: AAssetManager -> BS.ByteString -> IO (Maybe Text)
17−getFromMgr mgr name = do
18− let open = do
19− a <- BS.useAsCString name $ \fn ->
20− assetManager_open mgr fn 3
21− return $ if unAAsset a == nullPtr
22− then Nothing
23− else Just a
24− close = mapM_ asset_close
25− bracket open close $ mapM $ \asset -> do
26− b <- asset_getBuffer asset
27− l <- asset_getLength asset
28− fmap T.decodeUtf8 $ BS.packCStringLen (b, fromIntegral l)
29−
30−getFrontendConfigs :: IO (Map Text Text)
31−getFrontendConfigs = bracket getAssets freeAssetManager $ \mgrObj -> do
32− mgr <- assetManagerFromJava mgrObj
33− let openDir = do
34− d <- withCString "config.files" $ \fn ->
35− assetManager_open mgr fn 3
36− return $ if unAAsset d == nullPtr
37− then Nothing
38− else Just d
39− closeDir = mapM_ asset_close
40− configPaths <- bracket openDir closeDir $ \case
41− Just asset -> do
42− b <- asset_getBuffer asset
43− l <- asset_getLength asset
44− lines0 <$> BS.packCStringLen (b, fromIntegral l)
45− Nothing -> error "could not open configuration manifest 'config.files'"
46− fmap Map.fromList $ forM configPaths $ \fp ->
47− getFromMgr mgr fp >>= \case
48− Just v -> return (T.decodeUtf8 fp, v)
49− Nothing -> error $ "Config present in config.files but not in assets: " <> show fp
50−
51−lines0 :: BS.ByteString -> [BS.ByteString]
52−lines0 ps
53− | BS.null ps = []
54− | otherwise = case BS.elemIndex 0 ps of
55− Nothing -> [ps]
56− Just n -> BS.take n ps : lines0 (BS.drop (n+1) ps)
lib/executable-config/lookup/src-ghcjs/Obelisk/ExecutableConfig.hs+26−8
@@ -1,15 +1,33 @@
11{-# LANGUAGE OverloadedStrings #-}
22module Obelisk.ExecutableConfig where
33
4−import Control.Monad.Trans.Maybe
4+import Data.Map (Map)
5+import qualified Data.Map as Map
6+import Data.Maybe (catMaybes)
57import Data.Semigroup ((<>))
68import Data.Text (Text)
9+import qualified Data.Text as T
10+import Data.Traversable (for)
711import GHCJS.DOM
8−import GHCJS.DOM.Element (getInnerHTML)
9−import GHCJS.DOM.NonElementParentNode
12+import GHCJS.DOM.Document (getHead)
13+import GHCJS.DOM.Element (getElementsByClassName, getId, getInnerHTML)
14+import GHCJS.DOM.HTMLCollection (item, getLength)
1015
11−get :: Text -> IO (Maybe Text)
12−get key = runMaybeT $ do
13− doc <- MaybeT currentDocument
14− e <- MaybeT $ getElementById doc $ "config-" <> key
15− getInnerHTML e
16+getFrontendConfigs :: IO (Map Text Text)
17+getFrontendConfigs = do
18+ Just doc <- currentDocument
19+ Just hd <- getHead doc
20+ es <- collToList =<< getElementsByClassName hd ("obelisk-executable-config-inject" :: Text)
21+ cfg <- for es $ \e -> do
22+ ident <- getId e
23+ v <- getInnerHTML e
24+ return $ case T.stripPrefix "config-" ident of
25+ Just k -> (k, v)
26+ Nothing -> error $
27+ "Element '" <> show ident <> "' has class 'obelisk-executable-config-inject' but does not start with 'config-'."
28+ return $ Map.fromList cfg
29+ where
30+ collToList es = do
31+ len <- getLength es
32+ list <- traverse (item es) [0..len-1]
33+ pure $ catMaybes list
lib/executable-config/lookup/src-ghcjs/Obelisk/ExecutableConfig/Internal.hsdeleted−33
@@ -1,33 +0,0 @@
1−{-# LANGUAGE OverloadedStrings #-}
2−module Obelisk.ExecutableConfig.Internal where
3−
4−import Data.Map (Map)
5−import qualified Data.Map as Map
6−import Data.Maybe (catMaybes)
7−import Data.Semigroup ((<>))
8−import Data.Text (Text)
9−import qualified Data.Text as T
10−import Data.Traversable (for)
11−import GHCJS.DOM
12−import GHCJS.DOM.Document (getHead)
13−import GHCJS.DOM.Element (getElementsByClassName, getId, getInnerHTML)
14−import GHCJS.DOM.HTMLCollection (item, getLength)
15−
16−getFrontendConfigs :: IO (Map Text Text)
17−getFrontendConfigs = do
18− Just doc <- currentDocument
19− Just hd <- getHead doc
20− es <- collToList =<< getElementsByClassName hd ("obelisk-executable-config-inject" :: Text)
21− cfg <- for es $ \e -> do
22− ident <- getId e
23− v <- getInnerHTML e
24− return $ case T.stripPrefix "config-" ident of
25− Just k -> (k, v)
26− Nothing -> error $
27− "Element '" <> show ident <> "' has class 'obelisk-executable-config-inject' but does not start with 'config-'."
28− return $ Map.fromList cfg
29− where
30− collToList es = do
31− len <- getLength es
32− list <- traverse (item es) [0..len-1]
33− pure $ catMaybes list
lib/executable-config/lookup/src-ios/Obelisk/ExecutableConfig.hs+8−13
@@ -1,20 +1,15 @@
1−module Obelisk.ExecutableConfig (get) where
1+{-# LANGUAGE LambdaCase #-}
2+module Obelisk.ExecutableConfig where
23
3−import Control.Exception
4−import Control.Monad
4+import Data.Map (Map)
55import Data.Text (Text)
66import qualified Data.Text as T
7−import qualified Data.Text.IO as T
87import qualified Data.Text.Encoding as T
98import Language.Javascript.JSaddle.WKWebView
10−import System.FilePath.Posix ((</>))
11−import System.IO.Error
129
13−get :: Text -> IO (Maybe Text)
14−get name = fmap join $ mainBundleResourcePath >>= \mp -> forM mp $ \p ->
15− catchDoesNotExist $ T.readFile $ T.unpack (T.decodeUtf8 p) </> T.unpack name
10+import Obelisk.ExecutableConfig.Internal.ConfigDirectory
1611
17−catchDoesNotExist :: IO a -> IO (Maybe a)
18−catchDoesNotExist f = catchJust doesNotExist (Just <$> f) $ const $ return Nothing
19− where
20− doesNotExist e = if isDoesNotExistError e then Just () else Nothing
12+getFrontendConfigs :: IO (Map Text Text)
13+getFrontendConfigs = mainBundleResourcePath >>= \case
14+ Nothing -> error "Could not get bundle resource path."
15+ Just p -> getConfigs (T.unpack (T.decodeUtf8 p)) "config"
lib/executable-config/lookup/src-ios/Obelisk/ExecutableConfig/Internal.hsdeleted−15
@@ -1,15 +0,0 @@
1−{-# LANGUAGE LambdaCase #-}
2−module Obelisk.ExecutableConfig.Internal where
3−
4−import Data.Map (Map)
5−import Data.Text (Text)
6−import qualified Data.Text as T
7−import qualified Data.Text.Encoding as T
8−import Language.Javascript.JSaddle.WKWebView
9−
10−import Obelisk.ExecutableConfig.Internal.ConfigDirectory
11−
12−getFrontendConfigs :: IO (Map Text Text)
13−getFrontendConfigs = mainBundleResourcePath >>= \case
14− Nothing -> error "Could not get bundle resource path."
15− Just p -> getConfigs (T.unpack (T.decodeUtf8 p)) "config"
lib/executable-config/lookup/src/Obelisk/ExecutableConfig.hs+9−9
@@ -1,12 +1,12 @@
1−module Obelisk.ExecutableConfig (get) where
1+module Obelisk.ExecutableConfig where
22
3−import Control.Exception
3+import Data.Map (Map)
44import Data.Text (Text)
5−import Data.Text as T
6−import Data.Text.IO as T
7−import System.IO.Error
85
9−get :: Text -> IO (Maybe Text)
10−get path = do
11− let doesNotExist = \e -> if isDoesNotExistError e then Just () else Nothing
12− catchJust doesNotExist (fmap Just $ T.readFile $ T.unpack path) (\_ -> pure Nothing)
6+import Obelisk.ExecutableConfig.Internal.ConfigDirectory
7+
8+getFrontendConfigs :: IO (Map Text Text)
9+getFrontendConfigs = do
10+ cfgC <- getConfigs "." "config/common"
11+ cfgF <- getConfigs "." "config/frontend"
12+ return $ cfgC <> cfgF
lib/executable-config/lookup/src/Obelisk/ExecutableConfig/Internal.hsdeleted−12
@@ -1,12 +0,0 @@
1−module Obelisk.ExecutableConfig.Internal where
2−
3−import Data.Map (Map)
4−import Data.Text (Text)
5−
6−import Obelisk.ExecutableConfig.Internal.ConfigDirectory
7−
8−getFrontendConfigs :: IO (Map Text Text)
9−getFrontendConfigs = do
10− cfgC <- getConfigs "." "config/common"
11− cfgF <- getConfigs "." "config/frontend"
12− return $ cfgC <> cfgF
lib/frontend/src/Obelisk/Frontend.hs+1−1
@@ -46,7 +46,7 @@ import Obelisk.Route.Frontend
4646import Reflex.Dom.Core
4747import Reflex.Host.Class
4848import Obelisk.ExecutableConfig.Inject (injectExecutableConfigs)
49−import Obelisk.ExecutableConfig.Internal (getFrontendConfigs)
49+import Obelisk.ExecutableConfig (getFrontendConfigs)
5050import Web.Cookie
5151
5252makePrisms ''Sum
lib/run/obelisk-run.cabal+1
@@ -10,6 +10,7 @@ library
1010 attoparsec
1111 , base
1212 , bytestring
13+ , containers
1314 , cookie
1415 , dependent-sum
1516 , dependent-sum-template
lib/run/src/Obelisk/Run.hs+3−2
@@ -26,6 +26,7 @@ import Data.Dependent.Sum (DSum (..))
2626import Data.Functor.Identity
2727import Data.Functor.Sum
2828import Data.List (uncons)
29+import qualified Data.Map as Map
2930import Data.Maybe
3031import Data.Semigroup ((<>))
3132import Data.Streaming.Network (bindPortTCP)
@@ -46,7 +47,7 @@ import Network.WebSockets (ConnectionOptions)
4647import Network.WebSockets.Connection (defaultConnectionOptions)
4748import qualified Obelisk.Asset.Serve.Snap as Snap
4849import Obelisk.Backend
49−import Obelisk.ExecutableConfig (get)
50+import Obelisk.ExecutableConfig (getFrontendConfigs)
5051import Obelisk.Frontend
5152import Obelisk.Route.Frontend
5253import Reflex.Dom.Core
@@ -89,7 +90,7 @@ runServeAsset :: FilePath -> [Text] -> Snap ()
8990runServeAsset rootPath = Snap.serveAsset "" rootPath . T.unpack . T.intercalate "/"
9091
9192getConfigRoute :: IO (Maybe URI)
92−getConfigRoute = get "config/common/route" >>= \case
93+getConfigRoute = (Map.lookup "config/common/route" <$> getFrontendConfigs) >>= \case
9394 Just r -> case URI.mkURI $ T.strip r of
9495 Just route -> pure $ Just route
9596 Nothing -> do