module Hasura.Backends.DataConnector.Adapter.ConfigTransform
  ( transformSourceConfig,
    transformConnSourceConfig,
  )
where

--------------------------------------------------------------------------------

import Data.Aeson qualified as J
import Data.Aeson.Kriti.Functions qualified as KFunc
import Data.Environment qualified as Env
import Data.HashMap.Strict qualified as M
import Data.Text qualified as T
import Hasura.Backends.DataConnector.API qualified as API
import Hasura.Backends.DataConnector.Adapter.Types (ConnSourceConfig (ConnSourceConfig, template, value), SourceConfig (..))
import Hasura.Base.Error (Code (NotSupported), QErr, throw400)
import Hasura.Prelude
import Kriti.Error qualified as Kriti

transformConfig :: (MonadError QErr m) => API.Config -> Maybe Text -> [(T.Text, J.Value)] -> Env.Environment -> m API.Config
transformConfig :: Config -> Maybe Text -> [(Text, Value)] -> Environment -> m Config
transformConfig Config
config Maybe Text
maybeTemplate [(Text, Value)]
scope Environment
env = do
  case Maybe Text
maybeTemplate of
    Maybe Text
Nothing -> Config -> m Config
forall (f :: * -> *) a. Applicative f => a -> f a
pure Config
config
    (Just Text
t) ->
      case Text
-> [(Text, Value)]
-> HashMap Text KritiFunc
-> Either SerializedError Value
KFunc.runKritiWith Text
t ((Text
"$config", Config -> Value
forall a. ToJSON a => a -> Value
J.toJSON Config
config) (Text, Value) -> [(Text, Value)] -> [(Text, Value)]
forall a. a -> [a] -> [a]
: [(Text, Value)]
scope) (Environment -> HashMap Text KritiFunc
additionalFunctions Environment
env) of
        Left SerializedError
e -> Code -> Text -> m Config
forall (m :: * -> *) a. QErrM m => Code -> Text -> m a
throw400 Code
NotSupported (Text -> m Config) -> Text -> m Config
forall a b. (a -> b) -> a -> b
$ Text
"transformConfig: Kriti template transform failed - " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> SerializedError -> Text
forall a. Show a => a -> Text
tshow SerializedError
e
        Right (J.Object Object
r) -> Config -> m Config
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Config -> m Config) -> Config -> m Config
forall a b. (a -> b) -> a -> b
$ Object -> Config
API.Config Object
r
        Right Value
o -> Code -> Text -> m Config
forall (m :: * -> *) a. QErrM m => Code -> Text -> m a
throw400 Code
NotSupported (Text -> m Config) -> Text -> m Config
forall a b. (a -> b) -> a -> b
$ Text
"transformConfig: Kriti did not decode into Object - " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Value -> Text
forall a. Show a => a -> Text
tshow Value
o

transformSourceConfig :: (MonadError QErr m) => SourceConfig -> [(T.Text, J.Value)] -> Env.Environment -> m SourceConfig
transformSourceConfig :: SourceConfig -> [(Text, Value)] -> Environment -> m SourceConfig
transformSourceConfig sc :: SourceConfig
sc@SourceConfig {Config
_scConfig :: SourceConfig -> Config
_scConfig :: Config
_scConfig, Maybe Text
_scTemplate :: SourceConfig -> Maybe Text
_scTemplate :: Maybe Text
_scTemplate} [(Text, Value)]
scope Environment
env = do
  Config
transformedConfig <- Config -> Maybe Text -> [(Text, Value)] -> Environment -> m Config
forall (m :: * -> *).
MonadError QErr m =>
Config -> Maybe Text -> [(Text, Value)] -> Environment -> m Config
transformConfig Config
_scConfig Maybe Text
_scTemplate [(Text, Value)]
scope Environment
env
  SourceConfig -> m SourceConfig
forall (f :: * -> *) a. Applicative f => a -> f a
pure SourceConfig
sc {_scConfig :: Config
_scConfig = Config
transformedConfig}

transformConnSourceConfig :: (MonadError QErr m) => ConnSourceConfig -> [(T.Text, J.Value)] -> Env.Environment -> m API.Config
transformConnSourceConfig :: ConnSourceConfig -> [(Text, Value)] -> Environment -> m Config
transformConnSourceConfig ConnSourceConfig {Config
value :: Config
value :: ConnSourceConfig -> Config
value, Maybe Text
template :: Maybe Text
template :: ConnSourceConfig -> Maybe Text
template} [(Text, Value)]
scope Environment
env = Config -> Maybe Text -> [(Text, Value)] -> Environment -> m Config
forall (m :: * -> *).
MonadError QErr m =>
Config -> Maybe Text -> [(Text, Value)] -> Environment -> m Config
transformConfig Config
value Maybe Text
template [(Text, Value)]
scope Environment
env

additionalFunctions :: Env.Environment -> M.HashMap T.Text (J.Value -> Either Kriti.CustomFunctionError J.Value)
additionalFunctions :: Environment -> HashMap Text KritiFunc
additionalFunctions Environment
env = Environment -> HashMap Text KritiFunc
KFunc.environmentFunctions Environment
env