{-# LANGUAGE DeriveAnyClass #-}

module Hasura.RQL.Types.Webhook.Transform.Request
  ( RequestTransformCtx (..),
    Version (..),
  )
where

import Data.Aeson (FromJSON, ToJSON, (.=))
import Data.Aeson qualified as J
import Hasura.Prelude
import Hasura.RQL.Types.Webhook.Transform.Class (TemplatingEngine (..))
import Hasura.Session (SessionVariables)

-- | Common context that is made available to all request transformations.
data RequestTransformCtx = RequestTransformCtx
  { RequestTransformCtx -> Maybe Value
rtcBaseUrl :: Maybe J.Value,
    RequestTransformCtx -> Value
rtcBody :: J.Value,
    RequestTransformCtx -> Maybe SessionVariables
rtcSessionVariables :: Maybe SessionVariables,
    RequestTransformCtx -> Maybe Value
rtcQueryParams :: Maybe J.Value,
    RequestTransformCtx -> TemplatingEngine
rtcEngine :: TemplatingEngine
  }

instance ToJSON RequestTransformCtx where
  toJSON :: RequestTransformCtx -> Value
toJSON RequestTransformCtx {Maybe Value
Maybe SessionVariables
Value
TemplatingEngine
rtcBaseUrl :: RequestTransformCtx -> Maybe Value
rtcBody :: RequestTransformCtx -> Value
rtcSessionVariables :: RequestTransformCtx -> Maybe SessionVariables
rtcQueryParams :: RequestTransformCtx -> Maybe Value
rtcEngine :: RequestTransformCtx -> TemplatingEngine
rtcBaseUrl :: Maybe Value
rtcBody :: Value
rtcSessionVariables :: Maybe SessionVariables
rtcQueryParams :: Maybe Value
rtcEngine :: TemplatingEngine
..} =
    let required :: [Pair]
required =
          [ Key
"body" Key -> Value -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= Value
rtcBody,
            Key
"session_variables" Key -> Maybe SessionVariables -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= Maybe SessionVariables
rtcSessionVariables
          ]
        optional :: [Maybe Pair]
optional =
          [ (Key
"base_url" Key -> Value -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.=) (Value -> Pair) -> Maybe Value -> Maybe Pair
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe Value
rtcBaseUrl,
            (Key
"query_params" Key -> Value -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.=) (Value -> Pair) -> Maybe Value -> Maybe Pair
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe Value
rtcQueryParams
          ]
     in [Pair] -> Value
J.object ([Pair]
required [Pair] -> [Pair] -> [Pair]
forall a. Semigroup a => a -> a -> a
<> [Maybe Pair] -> [Pair]
forall a. [Maybe a] -> [a]
forall (f :: * -> *) a. Filterable f => f (Maybe a) -> f a
catMaybes [Maybe Pair]
optional)

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

-- | 'RequestTransform' Versioning
data Version
  = V1
  | V2
  deriving stock (Version -> Version -> Bool
(Version -> Version -> Bool)
-> (Version -> Version -> Bool) -> Eq Version
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Version -> Version -> Bool
== :: Version -> Version -> Bool
$c/= :: Version -> Version -> Bool
/= :: Version -> Version -> Bool
Eq, (forall x. Version -> Rep Version x)
-> (forall x. Rep Version x -> Version) -> Generic Version
forall x. Rep Version x -> Version
forall x. Version -> Rep Version x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Version -> Rep Version x
from :: forall x. Version -> Rep Version x
$cto :: forall x. Rep Version x -> Version
to :: forall x. Rep Version x -> Version
Generic, Int -> Version -> ShowS
[Version] -> ShowS
Version -> String
(Int -> Version -> ShowS)
-> (Version -> String) -> ([Version] -> ShowS) -> Show Version
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Version -> ShowS
showsPrec :: Int -> Version -> ShowS
$cshow :: Version -> String
show :: Version -> String
$cshowList :: [Version] -> ShowS
showList :: [Version] -> ShowS
Show)
  deriving anyclass (Eq Version
Eq Version
-> (Int -> Version -> Int) -> (Version -> Int) -> Hashable Version
Int -> Version -> Int
Version -> Int
forall a. Eq a -> (Int -> a -> Int) -> (a -> Int) -> Hashable a
$chashWithSalt :: Int -> Version -> Int
hashWithSalt :: Int -> Version -> Int
$chash :: Version -> Int
hash :: Version -> Int
Hashable, Version -> ()
(Version -> ()) -> NFData Version
forall a. (a -> ()) -> NFData a
$crnf :: Version -> ()
rnf :: Version -> ()
NFData)

instance FromJSON Version where
  parseJSON :: Value -> Parser Version
parseJSON Value
v = do
    Int
version :: Int <- Value -> Parser Int
forall a. FromJSON a => Value -> Parser a
J.parseJSON Value
v
    case Int
version of
      Int
1 -> Version -> Parser Version
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Version
V1
      Int
2 -> Version -> Parser Version
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Version
V2
      Int
i -> String -> Parser Version
forall a. String -> Parser a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> Parser Version) -> String -> Parser Version
forall a b. (a -> b) -> a -> b
$ String
"expected 1 or 2, encountered " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
i

instance ToJSON Version where
  toJSON :: Version -> Value
toJSON = \case
    Version
V1 -> forall a. ToJSON a => a -> Value
J.toJSON @Int Int
1
    Version
V2 -> forall a. ToJSON a => a -> Value
J.toJSON @Int Int
2