daml/daml-assistant/daml-project-config/DA/Daml/Project/Config.hs

129 lines
5.4 KiB
Haskell
Raw Normal View History

-- Copyright (c) 2021 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
2019-04-04 11:33:38 +03:00
-- SPDX-License-Identifier: Apache-2.0
2019-04-05 20:34:23 +03:00
module DA.Daml.Project.Config
2019-04-05 20:34:23 +03:00
( DamlConfig
, ProjectConfig
, SdkConfig
, readSdkConfig
, readProjectConfig
, readDamlConfig
, sdkVersionFromProjectConfig
, sdkVersionFromSdkConfig
, listSdkCommands
, queryDamlConfig
, queryProjectConfig
, querySdkConfig
, queryDamlConfigRequired
, queryProjectConfigRequired
, querySdkConfigRequired
2019-04-04 11:33:38 +03:00
) where
import DA.Daml.Project.Consts
import DA.Daml.Project.Types
import DA.Daml.Project.Util
2019-04-05 20:34:23 +03:00
import qualified Data.Text as T
import Data.Text (Text)
2019-04-05 20:34:23 +03:00
import qualified Data.Yaml as Y
import Data.Yaml ((.:?))
import Data.Either.Extra
import Data.Foldable
2019-04-04 11:33:38 +03:00
import System.FilePath
import Control.Exception.Safe
2019-04-04 11:33:38 +03:00
2019-04-05 20:34:23 +03:00
-- | Read daml config file.
-- Throws a ConfigError if reading or parsing fails.
2019-04-05 20:34:23 +03:00
readDamlConfig :: DamlPath -> IO DamlConfig
readDamlConfig (DamlPath path) = readConfig "daml" (path </> damlConfigName)
2019-04-04 11:33:38 +03:00
2019-04-05 20:34:23 +03:00
-- | Read project config file.
-- Throws a ConfigError if reading or parsing fails.
2019-04-05 20:34:23 +03:00
readProjectConfig :: ProjectPath -> IO ProjectConfig
readProjectConfig (ProjectPath path) = readConfig "project" (path </> projectConfigName)
2019-04-04 11:33:38 +03:00
2019-04-05 20:34:23 +03:00
-- | Read sdk config file.
-- Throws a ConfigError if reading or parsing fails.
2019-04-05 20:34:23 +03:00
readSdkConfig :: SdkPath -> IO SdkConfig
readSdkConfig (SdkPath path) = readConfig "SDK" (path </> sdkConfigName)
-- | (internal) Helper function for defining 'readXConfig' functions.
-- Throws a ConfigError if reading or parsing fails.
2019-04-05 20:34:23 +03:00
readConfig :: Y.FromJSON b => Text -> FilePath -> IO b
readConfig name path = do
configE <- Y.decodeFileEither path
fromRightM (throwIO . ConfigFileInvalid name) configE
2019-04-05 20:34:23 +03:00
-- | Determine pinned sdk version from project config, if it exists.
sdkVersionFromProjectConfig :: ProjectConfig -> Either ConfigError (Maybe SdkVersion)
sdkVersionFromProjectConfig = queryProjectConfig ["sdk-version"]
2019-04-05 20:34:23 +03:00
-- | Determine sdk version from sdk config, if it exists.
sdkVersionFromSdkConfig :: SdkConfig -> Either ConfigError SdkVersion
2019-04-05 20:34:23 +03:00
sdkVersionFromSdkConfig = querySdkConfigRequired ["version"]
-- | Read sdk config to get list of sdk commands.
listSdkCommands :: SdkPath -> EnrichedCompletion -> SdkConfig -> Either ConfigError [SdkCommandInfo]
listSdkCommands sdkPath enriched sdkConf = map (\f -> f sdkPath enriched) <$> querySdkConfigRequired ["commands"] sdkConf
2019-04-04 11:33:38 +03:00
2019-04-05 20:34:23 +03:00
-- | Query the daml config by passing a path to the desired property.
-- See 'queryConfig' for more details.
queryDamlConfig :: Y.FromJSON t => [Text] -> DamlConfig -> Either ConfigError (Maybe t)
2019-04-05 20:34:23 +03:00
queryDamlConfig path = queryConfig "daml" "DamlConfig" path . unwrapDamlConfig
-- | Query the project config by passing a path to the desired property.
-- See 'queryConfig' for more details.
queryProjectConfig :: Y.FromJSON t => [Text] -> ProjectConfig -> Either ConfigError (Maybe t)
2019-04-05 20:34:23 +03:00
queryProjectConfig path = queryConfig "project" "ProjectConfig" path . unwrapProjectConfig
-- | Query the sdk config by passing a list of members to the desired property.
-- See 'queryConfig' for more details.
querySdkConfig :: Y.FromJSON t => [Text] -> SdkConfig -> Either ConfigError (Maybe t)
2019-04-05 20:34:23 +03:00
querySdkConfig path = queryConfig "SDK" "SdkConfig" path . unwrapSdkConfig
-- | Like 'queryDamlConfig' but returns an error if the property is missing.
queryDamlConfigRequired :: Y.FromJSON t => [Text] -> DamlConfig -> Either ConfigError t
2019-04-05 20:34:23 +03:00
queryDamlConfigRequired path = queryConfigRequired "daml" "DamlConfig" path . unwrapDamlConfig
-- | Like 'queryProjectConfig' but returns an error if the property is missing.
queryProjectConfigRequired :: Y.FromJSON t => [Text] -> ProjectConfig -> Either ConfigError t
2019-04-05 20:34:23 +03:00
queryProjectConfigRequired path = queryConfigRequired "project" "ProjectConfig" path . unwrapProjectConfig
-- | Like 'querySdkConfig' but returns an error if the property is missing.
querySdkConfigRequired :: Y.FromJSON t => [Text] -> SdkConfig -> Either ConfigError t
2019-04-05 20:34:23 +03:00
querySdkConfigRequired path = queryConfigRequired "SDK" "SdkConfig" path . unwrapSdkConfig
-- | (internal) Helper function for querying config data. The 'path' argument
-- represents the location of the desired property within the config file.
-- For example, if you had a YAML file like so:
--
-- a:
-- b:
-- c:
-- <desired property>
2019-04-04 11:33:38 +03:00
--
2019-04-05 20:34:23 +03:00
-- Then you would pass ["a", "b", "c"] as path to get the desired property.
2019-04-04 11:33:38 +03:00
--
2019-04-05 20:34:23 +03:00
-- This distinguishes between a missing property and a poorly formed property:
-- * If the property is missing, this returns (Right Nothing).
-- * If the property is poorly formed, this returns (Left ...).
queryConfig :: Y.FromJSON t => Text -> Text -> [Text] -> Y.Value -> Either ConfigError (Maybe t)
2019-04-05 20:34:23 +03:00
queryConfig name root path cfg
= mapLeft (ConfigFieldInvalid name path)
2019-04-05 20:34:23 +03:00
. flip Y.parseEither cfg
$ \v0 -> do
let initial = (root, Just v0)
step (p, Nothing) _ = pure (p, Nothing)
step (p, Just v) n = do
v' <- Y.withObject (T.unpack p) (.:? n) v
2019-04-05 20:34:23 +03:00
pure (p <> "." <> n, v')
(_,v1) <- foldlM step initial path
mapM Y.parseJSON v1
-- | (internal) Like 'queryConfig' but returns an error if property is missing.
queryConfigRequired :: Y.FromJSON t => Text -> Text -> [Text] -> Y.Value -> Either ConfigError t
2019-04-05 20:34:23 +03:00
queryConfigRequired name root path cfg = do
resultM <- queryConfig name root path cfg
fromMaybeM (Left $ ConfigFieldMissing name path) resultM