{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE UndecidableInstances #-}

module Hasura.RQL.Types.Webhook.Transform
  ( MetadataResponseTransform (..),
    RequestTransform (..),
    RequestTransformFns,
    RequestContext,
    RequestData,
    RequestFields (..),
  )
where

import Autodocodec (HasCodec, dimapCodec, disjointEitherCodec, optionalField', optionalFieldWithDefault')
import Autodocodec qualified as AC
import Autodocodec.Extended (optionalVersionField, versionField)
import Data.Aeson (FromJSON, ToJSON)
import Data.Aeson qualified as J
import Data.Aeson.Extended ((.!=), (.:?), (.=), (.=?))
import Data.Functor.Barbie (AllBF, ApplicativeB, ConstraintsB, FunctorB, TraversableB)
import Data.Functor.Barbie qualified as B
import Hasura.Prelude
import Hasura.RQL.Types.Webhook.Transform.Body (Body, BodyTransformFn, TransformCtx (..), TransformFn (..))
import Hasura.RQL.Types.Webhook.Transform.Body qualified as Body
import Hasura.RQL.Types.Webhook.Transform.Class (Template, TemplatingEngine (..))
import Hasura.RQL.Types.Webhook.Transform.Headers (Headers, HeadersTransformFn, TransformCtx (..), TransformFn (..))
import Hasura.RQL.Types.Webhook.Transform.Method (Method, MethodTransformFn, TransformCtx (..), TransformFn (..))
import Hasura.RQL.Types.Webhook.Transform.QueryParams (QueryParams, QueryParamsTransformFn, TransformCtx (..), TransformFn (..))
import Hasura.RQL.Types.Webhook.Transform.Request (RequestTransformCtx, Version (..))
import Hasura.RQL.Types.Webhook.Transform.Url (TransformCtx (..), TransformFn (..), Url, UrlTransformFn (..))
import Hasura.RQL.Types.Webhook.Transform.WithOptional (WithOptional (..), withOptional, withOptionalField')

-------------------------------------------------------------------------------
-- TODO(SOLOMON): Rewrite with HKD

data MetadataResponseTransform = MetadataResponseTransform
  { MetadataResponseTransform -> Version
mrtVersion :: Version,
    MetadataResponseTransform -> Maybe BodyTransformFn
mrtBodyTransform :: Maybe BodyTransformFn,
    MetadataResponseTransform -> TemplatingEngine
mrtTemplatingEngine :: TemplatingEngine
  }
  deriving stock (Int -> MetadataResponseTransform -> ShowS
[MetadataResponseTransform] -> ShowS
MetadataResponseTransform -> String
(Int -> MetadataResponseTransform -> ShowS)
-> (MetadataResponseTransform -> String)
-> ([MetadataResponseTransform] -> ShowS)
-> Show MetadataResponseTransform
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> MetadataResponseTransform -> ShowS
showsPrec :: Int -> MetadataResponseTransform -> ShowS
$cshow :: MetadataResponseTransform -> String
show :: MetadataResponseTransform -> String
$cshowList :: [MetadataResponseTransform] -> ShowS
showList :: [MetadataResponseTransform] -> ShowS
Show, MetadataResponseTransform -> MetadataResponseTransform -> Bool
(MetadataResponseTransform -> MetadataResponseTransform -> Bool)
-> (MetadataResponseTransform -> MetadataResponseTransform -> Bool)
-> Eq MetadataResponseTransform
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: MetadataResponseTransform -> MetadataResponseTransform -> Bool
== :: MetadataResponseTransform -> MetadataResponseTransform -> Bool
$c/= :: MetadataResponseTransform -> MetadataResponseTransform -> Bool
/= :: MetadataResponseTransform -> MetadataResponseTransform -> Bool
Eq, (forall x.
 MetadataResponseTransform -> Rep MetadataResponseTransform x)
-> (forall x.
    Rep MetadataResponseTransform x -> MetadataResponseTransform)
-> Generic MetadataResponseTransform
forall x.
Rep MetadataResponseTransform x -> MetadataResponseTransform
forall x.
MetadataResponseTransform -> Rep MetadataResponseTransform x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x.
MetadataResponseTransform -> Rep MetadataResponseTransform x
from :: forall x.
MetadataResponseTransform -> Rep MetadataResponseTransform x
$cto :: forall x.
Rep MetadataResponseTransform x -> MetadataResponseTransform
to :: forall x.
Rep MetadataResponseTransform x -> MetadataResponseTransform
Generic)
  deriving anyclass (MetadataResponseTransform -> ()
(MetadataResponseTransform -> ())
-> NFData MetadataResponseTransform
forall a. (a -> ()) -> NFData a
$crnf :: MetadataResponseTransform -> ()
rnf :: MetadataResponseTransform -> ()
NFData)

instance HasCodec MetadataResponseTransform where
  codec :: JSONCodec MetadataResponseTransform
codec =
    (Either MetadataResponseTransform MetadataResponseTransform
 -> MetadataResponseTransform)
-> (MetadataResponseTransform
    -> Either MetadataResponseTransform MetadataResponseTransform)
-> Codec
     Value
     (Either MetadataResponseTransform MetadataResponseTransform)
     (Either MetadataResponseTransform MetadataResponseTransform)
-> JSONCodec MetadataResponseTransform
forall oldOutput newOutput newInput oldInput context.
(oldOutput -> newOutput)
-> (newInput -> oldInput)
-> Codec context oldInput oldOutput
-> Codec context newInput newOutput
dimapCodec
      ((MetadataResponseTransform -> MetadataResponseTransform)
-> (MetadataResponseTransform -> MetadataResponseTransform)
-> Either MetadataResponseTransform MetadataResponseTransform
-> MetadataResponseTransform
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either MetadataResponseTransform -> MetadataResponseTransform
forall a. a -> a
id MetadataResponseTransform -> MetadataResponseTransform
forall a. a -> a
id)
      (\MetadataResponseTransform
rt -> case MetadataResponseTransform -> Version
mrtVersion MetadataResponseTransform
rt of Version
V1 -> MetadataResponseTransform
-> Either MetadataResponseTransform MetadataResponseTransform
forall a b. a -> Either a b
Left MetadataResponseTransform
rt; Version
V2 -> MetadataResponseTransform
-> Either MetadataResponseTransform MetadataResponseTransform
forall a b. b -> Either a b
Right MetadataResponseTransform
rt)
      (Codec
   Value
   (Either MetadataResponseTransform MetadataResponseTransform)
   (Either MetadataResponseTransform MetadataResponseTransform)
 -> JSONCodec MetadataResponseTransform)
-> Codec
     Value
     (Either MetadataResponseTransform MetadataResponseTransform)
     (Either MetadataResponseTransform MetadataResponseTransform)
-> JSONCodec MetadataResponseTransform
forall a b. (a -> b) -> a -> b
$ JSONCodec MetadataResponseTransform
-> JSONCodec MetadataResponseTransform
-> Codec
     Value
     (Either MetadataResponseTransform MetadataResponseTransform)
     (Either MetadataResponseTransform MetadataResponseTransform)
forall context input1 output1 input2 output2.
Codec context input1 output1
-> Codec context input2 output2
-> Codec context (Either input1 input2) (Either output1 output2)
disjointEitherCodec JSONCodec MetadataResponseTransform
transformV1 JSONCodec MetadataResponseTransform
transformV2
    where
      transformV1 :: JSONCodec MetadataResponseTransform
transformV1 =
        Text
-> ObjectCodec MetadataResponseTransform MetadataResponseTransform
-> JSONCodec MetadataResponseTransform
forall input output.
Text -> ObjectCodec input output -> ValueCodec input output
AC.object Text
"ResponseTransformV1"
          (ObjectCodec MetadataResponseTransform MetadataResponseTransform
 -> JSONCodec MetadataResponseTransform)
-> ObjectCodec MetadataResponseTransform MetadataResponseTransform
-> JSONCodec MetadataResponseTransform
forall a b. (a -> b) -> a -> b
$ Version
-> Maybe BodyTransformFn
-> TemplatingEngine
-> MetadataResponseTransform
MetadataResponseTransform
          (Version
 -> Maybe BodyTransformFn
 -> TemplatingEngine
 -> MetadataResponseTransform)
-> Codec Object MetadataResponseTransform Version
-> Codec
     Object
     MetadataResponseTransform
     (Maybe BodyTransformFn
      -> TemplatingEngine -> MetadataResponseTransform)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Version
V1 Version
-> Codec Object MetadataResponseTransform (Maybe Scientific)
-> Codec Object MetadataResponseTransform Version
forall a b.
a
-> Codec Object MetadataResponseTransform b
-> Codec Object MetadataResponseTransform a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Integer
-> Codec Object MetadataResponseTransform (Maybe Scientific)
forall a. Integer -> ObjectCodec a (Maybe Scientific)
optionalVersionField Integer
1)
          Codec
  Object
  MetadataResponseTransform
  (Maybe BodyTransformFn
   -> TemplatingEngine -> MetadataResponseTransform)
-> Codec Object MetadataResponseTransform (Maybe BodyTransformFn)
-> Codec
     Object
     MetadataResponseTransform
     (TemplatingEngine -> MetadataResponseTransform)
forall a b.
Codec Object MetadataResponseTransform (a -> b)
-> Codec Object MetadataResponseTransform a
-> Codec Object MetadataResponseTransform b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Codec Object (Maybe BodyTransformFn) (Maybe BodyTransformFn)
bodyV1
          Codec Object (Maybe BodyTransformFn) (Maybe BodyTransformFn)
-> (MetadataResponseTransform -> Maybe BodyTransformFn)
-> Codec Object MetadataResponseTransform (Maybe BodyTransformFn)
forall oldInput output newInput.
ObjectCodec oldInput output
-> (newInput -> oldInput) -> ObjectCodec newInput output
AC..= MetadataResponseTransform -> Maybe BodyTransformFn
mrtBodyTransform
            Codec
  Object
  MetadataResponseTransform
  (TemplatingEngine -> MetadataResponseTransform)
-> Codec Object MetadataResponseTransform TemplatingEngine
-> ObjectCodec MetadataResponseTransform MetadataResponseTransform
forall a b.
Codec Object MetadataResponseTransform (a -> b)
-> Codec Object MetadataResponseTransform a
-> Codec Object MetadataResponseTransform b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Codec Object MetadataResponseTransform TemplatingEngine
transformCommon

      transformV2 :: JSONCodec MetadataResponseTransform
transformV2 =
        Text
-> ObjectCodec MetadataResponseTransform MetadataResponseTransform
-> JSONCodec MetadataResponseTransform
forall input output.
Text -> ObjectCodec input output -> ValueCodec input output
AC.object Text
"ResponseTransformV2"
          (ObjectCodec MetadataResponseTransform MetadataResponseTransform
 -> JSONCodec MetadataResponseTransform)
-> ObjectCodec MetadataResponseTransform MetadataResponseTransform
-> JSONCodec MetadataResponseTransform
forall a b. (a -> b) -> a -> b
$ Version
-> Maybe BodyTransformFn
-> TemplatingEngine
-> MetadataResponseTransform
MetadataResponseTransform
          (Version
 -> Maybe BodyTransformFn
 -> TemplatingEngine
 -> MetadataResponseTransform)
-> Codec Object MetadataResponseTransform Version
-> Codec
     Object
     MetadataResponseTransform
     (Maybe BodyTransformFn
      -> TemplatingEngine -> MetadataResponseTransform)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Version
V2 Version
-> Codec Object MetadataResponseTransform Scientific
-> Codec Object MetadataResponseTransform Version
forall a b.
a
-> Codec Object MetadataResponseTransform b
-> Codec Object MetadataResponseTransform a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Integer -> Codec Object MetadataResponseTransform Scientific
forall a. Integer -> ObjectCodec a Scientific
versionField Integer
2)
          Codec
  Object
  MetadataResponseTransform
  (Maybe BodyTransformFn
   -> TemplatingEngine -> MetadataResponseTransform)
-> Codec Object MetadataResponseTransform (Maybe BodyTransformFn)
-> Codec
     Object
     MetadataResponseTransform
     (TemplatingEngine -> MetadataResponseTransform)
forall a b.
Codec Object MetadataResponseTransform (a -> b)
-> Codec Object MetadataResponseTransform a
-> Codec Object MetadataResponseTransform b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Codec Object (Maybe BodyTransformFn) (Maybe BodyTransformFn)
bodyV2
          Codec Object (Maybe BodyTransformFn) (Maybe BodyTransformFn)
-> (MetadataResponseTransform -> Maybe BodyTransformFn)
-> Codec Object MetadataResponseTransform (Maybe BodyTransformFn)
forall oldInput output newInput.
ObjectCodec oldInput output
-> (newInput -> oldInput) -> ObjectCodec newInput output
AC..= MetadataResponseTransform -> Maybe BodyTransformFn
mrtBodyTransform
            Codec
  Object
  MetadataResponseTransform
  (TemplatingEngine -> MetadataResponseTransform)
-> Codec Object MetadataResponseTransform TemplatingEngine
-> ObjectCodec MetadataResponseTransform MetadataResponseTransform
forall a b.
Codec Object MetadataResponseTransform (a -> b)
-> Codec Object MetadataResponseTransform a
-> Codec Object MetadataResponseTransform b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Codec Object MetadataResponseTransform TemplatingEngine
transformCommon

      transformCommon :: Codec Object MetadataResponseTransform TemplatingEngine
transformCommon = Text
-> TemplatingEngine
-> ObjectCodec TemplatingEngine TemplatingEngine
forall output.
HasCodec output =>
Text -> output -> ObjectCodec output output
optionalFieldWithDefault' Text
"template_engine" TemplatingEngine
Kriti ObjectCodec TemplatingEngine TemplatingEngine
-> (MetadataResponseTransform -> TemplatingEngine)
-> Codec Object MetadataResponseTransform TemplatingEngine
forall oldInput output newInput.
ObjectCodec oldInput output
-> (newInput -> oldInput) -> ObjectCodec newInput output
AC..= MetadataResponseTransform -> TemplatingEngine
mrtTemplatingEngine

      bodyV1 :: Codec Object (Maybe BodyTransformFn) (Maybe BodyTransformFn)
bodyV1 =
        (Maybe Template -> Maybe BodyTransformFn)
-> (Maybe BodyTransformFn -> Maybe Template)
-> Codec Object (Maybe Template) (Maybe Template)
-> Codec Object (Maybe BodyTransformFn) (Maybe BodyTransformFn)
forall oldOutput newOutput newInput oldInput context.
(oldOutput -> newOutput)
-> (newInput -> oldInput)
-> Codec context oldInput oldOutput
-> Codec context newInput newOutput
dimapCodec
          ((Template -> BodyTransformFn)
-> Maybe Template -> Maybe BodyTransformFn
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Template -> BodyTransformFn
Body.ModifyAsJSON)
          (\case Just (Body.ModifyAsJSON Template
template) -> Template -> Maybe Template
forall a. a -> Maybe a
Just Template
template; Maybe BodyTransformFn
_ -> Maybe Template
forall a. Maybe a
Nothing)
          (Codec Object (Maybe Template) (Maybe Template)
 -> Codec Object (Maybe BodyTransformFn) (Maybe BodyTransformFn))
-> Codec Object (Maybe Template) (Maybe Template)
-> Codec Object (Maybe BodyTransformFn) (Maybe BodyTransformFn)
forall a b. (a -> b) -> a -> b
$ forall output.
HasCodec output =>
Text -> ObjectCodec (Maybe output) (Maybe output)
optionalField' @Template Text
"body"

      bodyV2 :: Codec Object (Maybe BodyTransformFn) (Maybe BodyTransformFn)
bodyV2 = forall output.
HasCodec output =>
Text -> ObjectCodec (Maybe output) (Maybe output)
optionalField' @BodyTransformFn Text
"body"

instance FromJSON MetadataResponseTransform where
  parseJSON :: Value -> Parser MetadataResponseTransform
parseJSON = String
-> (Object -> Parser MetadataResponseTransform)
-> Value
-> Parser MetadataResponseTransform
forall a. String -> (Object -> Parser a) -> Value -> Parser a
J.withObject String
"MetadataResponseTransform" ((Object -> Parser MetadataResponseTransform)
 -> Value -> Parser MetadataResponseTransform)
-> (Object -> Parser MetadataResponseTransform)
-> Value
-> Parser MetadataResponseTransform
forall a b. (a -> b) -> a -> b
$ \Object
o -> do
    Version
mrtVersion <- Object
o Object -> Key -> Parser (Maybe Version)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"version" Parser (Maybe Version) -> Version -> Parser Version
forall a. Parser (Maybe a) -> a -> Parser a
.!= Version
V1
    Maybe BodyTransformFn
mrtBodyTransform <- case Version
mrtVersion of
      Version
V1 -> do
        Maybe Template
template :: (Maybe Template) <- Object
o Object -> Key -> Parser (Maybe Template)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"body"
        Maybe BodyTransformFn -> Parser (Maybe BodyTransformFn)
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe BodyTransformFn -> Parser (Maybe BodyTransformFn))
-> Maybe BodyTransformFn -> Parser (Maybe BodyTransformFn)
forall a b. (a -> b) -> a -> b
$ (Template -> BodyTransformFn)
-> Maybe Template -> Maybe BodyTransformFn
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Template -> BodyTransformFn
Body.ModifyAsJSON Maybe Template
template
      Version
V2 -> Object
o Object -> Key -> Parser (Maybe BodyTransformFn)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"body"
    Maybe TemplatingEngine
templateEngine <- Object
o Object -> Key -> Parser (Maybe TemplatingEngine)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"template_engine"
    let mrtTemplatingEngine :: TemplatingEngine
mrtTemplatingEngine = TemplatingEngine -> Maybe TemplatingEngine -> TemplatingEngine
forall a. a -> Maybe a -> a
fromMaybe TemplatingEngine
Kriti Maybe TemplatingEngine
templateEngine
    MetadataResponseTransform -> Parser MetadataResponseTransform
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (MetadataResponseTransform -> Parser MetadataResponseTransform)
-> MetadataResponseTransform -> Parser MetadataResponseTransform
forall a b. (a -> b) -> a -> b
$ MetadataResponseTransform {Maybe BodyTransformFn
TemplatingEngine
Version
mrtVersion :: Version
mrtBodyTransform :: Maybe BodyTransformFn
mrtTemplatingEngine :: TemplatingEngine
mrtVersion :: Version
mrtBodyTransform :: Maybe BodyTransformFn
mrtTemplatingEngine :: TemplatingEngine
..}

instance ToJSON MetadataResponseTransform where
  toJSON :: MetadataResponseTransform -> Value
toJSON MetadataResponseTransform {Maybe BodyTransformFn
TemplatingEngine
Version
mrtVersion :: MetadataResponseTransform -> Version
mrtBodyTransform :: MetadataResponseTransform -> Maybe BodyTransformFn
mrtTemplatingEngine :: MetadataResponseTransform -> TemplatingEngine
mrtVersion :: Version
mrtBodyTransform :: Maybe BodyTransformFn
mrtTemplatingEngine :: TemplatingEngine
..} =
    let body :: Maybe (Key, Value)
body = case Version
mrtVersion of
          Version
V1 -> case Maybe BodyTransformFn
mrtBodyTransform of
            Just (Body.ModifyAsJSON Template
template) -> (Key, Value) -> Maybe (Key, Value)
forall a. a -> Maybe a
Just (Key
"body", Template -> Value
forall a. ToJSON a => a -> Value
J.toJSON Template
template)
            Maybe BodyTransformFn
_ -> Maybe (Key, Value)
forall a. Maybe a
Nothing
          Version
V2 -> Key
"body" Key -> Maybe BodyTransformFn -> Maybe (Key, Value)
forall v kv. (ToJSON v, KeyValue kv) => Key -> Maybe v -> Maybe kv
.=? Maybe BodyTransformFn
mrtBodyTransform
     in [(Key, Value)] -> Value
J.object
          ([(Key, Value)] -> Value) -> [(Key, Value)] -> Value
forall a b. (a -> b) -> a -> b
$ [ Key
"template_engine" Key -> TemplatingEngine -> (Key, Value)
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> (Key, Value)
.= TemplatingEngine
mrtTemplatingEngine,
              Key
"version" Key -> Version -> (Key, Value)
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> (Key, Value)
.= Version
mrtVersion
            ]
          [(Key, Value)] -> [(Key, Value)] -> [(Key, Value)]
forall a. Semigroup a => a -> a -> a
<> Maybe (Key, Value) -> [(Key, Value)]
forall a. Maybe a -> [a]
maybeToList Maybe (Key, Value)
body

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

-- | 'RequestTransform' is the metadata representation of a request
-- transformation. It consists of a record of higher kinded data (HKD)
-- along with some regular data. We seperate the HKD data into its own
-- record field called 'requestFields' which we nest inside our
-- non-HKD record. The actual transformation operations are contained
-- in the HKD.
data RequestTransform = RequestTransform
  { RequestTransform -> Version
version :: Version,
    RequestTransform -> RequestFields (WithOptional TransformFn)
requestFields :: RequestFields (WithOptional TransformFn),
    RequestTransform -> TemplatingEngine
templateEngine :: TemplatingEngine
  }
  deriving stock (Int -> RequestTransform -> ShowS
[RequestTransform] -> ShowS
RequestTransform -> String
(Int -> RequestTransform -> ShowS)
-> (RequestTransform -> String)
-> ([RequestTransform] -> ShowS)
-> Show RequestTransform
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> RequestTransform -> ShowS
showsPrec :: Int -> RequestTransform -> ShowS
$cshow :: RequestTransform -> String
show :: RequestTransform -> String
$cshowList :: [RequestTransform] -> ShowS
showList :: [RequestTransform] -> ShowS
Show, RequestTransform -> RequestTransform -> Bool
(RequestTransform -> RequestTransform -> Bool)
-> (RequestTransform -> RequestTransform -> Bool)
-> Eq RequestTransform
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: RequestTransform -> RequestTransform -> Bool
== :: RequestTransform -> RequestTransform -> Bool
$c/= :: RequestTransform -> RequestTransform -> Bool
/= :: RequestTransform -> RequestTransform -> Bool
Eq, (forall x. RequestTransform -> Rep RequestTransform x)
-> (forall x. Rep RequestTransform x -> RequestTransform)
-> Generic RequestTransform
forall x. Rep RequestTransform x -> RequestTransform
forall x. RequestTransform -> Rep RequestTransform x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. RequestTransform -> Rep RequestTransform x
from :: forall x. RequestTransform -> Rep RequestTransform x
$cto :: forall x. Rep RequestTransform x -> RequestTransform
to :: forall x. Rep RequestTransform x -> RequestTransform
Generic)
  deriving anyclass (RequestTransform -> ()
(RequestTransform -> ()) -> NFData RequestTransform
forall a. (a -> ()) -> NFData a
$crnf :: RequestTransform -> ()
rnf :: RequestTransform -> ()
NFData)

instance HasCodec RequestTransform where
  codec :: JSONCodec RequestTransform
codec =
    (Either RequestTransform RequestTransform -> RequestTransform)
-> (RequestTransform -> Either RequestTransform RequestTransform)
-> Codec
     Value
     (Either RequestTransform RequestTransform)
     (Either RequestTransform RequestTransform)
-> JSONCodec RequestTransform
forall oldOutput newOutput newInput oldInput context.
(oldOutput -> newOutput)
-> (newInput -> oldInput)
-> Codec context oldInput oldOutput
-> Codec context newInput newOutput
dimapCodec
      ((RequestTransform -> RequestTransform)
-> (RequestTransform -> RequestTransform)
-> Either RequestTransform RequestTransform
-> RequestTransform
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either RequestTransform -> RequestTransform
forall a. a -> a
id RequestTransform -> RequestTransform
forall a. a -> a
id)
      (\RequestTransform
rt -> case RequestTransform -> Version
version RequestTransform
rt of Version
V1 -> RequestTransform -> Either RequestTransform RequestTransform
forall a b. a -> Either a b
Left RequestTransform
rt; Version
V2 -> RequestTransform -> Either RequestTransform RequestTransform
forall a b. b -> Either a b
Right RequestTransform
rt)
      (Codec
   Value
   (Either RequestTransform RequestTransform)
   (Either RequestTransform RequestTransform)
 -> JSONCodec RequestTransform)
-> Codec
     Value
     (Either RequestTransform RequestTransform)
     (Either RequestTransform RequestTransform)
-> JSONCodec RequestTransform
forall a b. (a -> b) -> a -> b
$ JSONCodec RequestTransform
-> JSONCodec RequestTransform
-> Codec
     Value
     (Either RequestTransform RequestTransform)
     (Either RequestTransform RequestTransform)
forall context input1 output1 input2 output2.
Codec context input1 output1
-> Codec context input2 output2
-> Codec context (Either input1 input2) (Either output1 output2)
disjointEitherCodec JSONCodec RequestTransform
transformV1 JSONCodec RequestTransform
transformV2
    where
      transformV1 :: JSONCodec RequestTransform
transformV1 =
        Text
-> ObjectCodec RequestTransform RequestTransform
-> JSONCodec RequestTransform
forall input output.
Text -> ObjectCodec input output -> ValueCodec input output
AC.object Text
"RequestTransformV1"
          (ObjectCodec RequestTransform RequestTransform
 -> JSONCodec RequestTransform)
-> ObjectCodec RequestTransform RequestTransform
-> JSONCodec RequestTransform
forall a b. (a -> b) -> a -> b
$ Version
-> RequestFields (WithOptional TransformFn)
-> TemplatingEngine
-> RequestTransform
RequestTransform
          (Version
 -> RequestFields (WithOptional TransformFn)
 -> TemplatingEngine
 -> RequestTransform)
-> Codec Object RequestTransform Version
-> Codec
     Object
     RequestTransform
     (RequestFields (WithOptional TransformFn)
      -> TemplatingEngine -> RequestTransform)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Version
V1 Version
-> Codec Object RequestTransform (Maybe Scientific)
-> Codec Object RequestTransform Version
forall a b.
a
-> Codec Object RequestTransform b
-> Codec Object RequestTransform a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Integer -> Codec Object RequestTransform (Maybe Scientific)
forall a. Integer -> ObjectCodec a (Maybe Scientific)
optionalVersionField Integer
1)
          Codec
  Object
  RequestTransform
  (RequestFields (WithOptional TransformFn)
   -> TemplatingEngine -> RequestTransform)
-> Codec
     Object RequestTransform (RequestFields (WithOptional TransformFn))
-> Codec
     Object RequestTransform (TemplatingEngine -> RequestTransform)
forall a b.
Codec Object RequestTransform (a -> b)
-> Codec Object RequestTransform a
-> Codec Object RequestTransform b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ObjectCodec
  (WithOptional TransformFn Body) (WithOptional TransformFn Body)
-> Codec
     Object
     (RequestFields (WithOptional TransformFn))
     (RequestFields (WithOptional TransformFn))
forall {f :: * -> *}.
(Coercible MethodTransformFn (f Method),
 Coercible UnescapedTemplate (f Url),
 Coercible QueryParamsTransformFn (f QueryParams),
 Coercible HeadersTransformFn (f Headers)) =>
ObjectCodec (WithOptional f Body) (WithOptional f Body)
-> Codec
     Object
     (RequestFields (WithOptional f))
     (RequestFields (WithOptional f))
requestFieldsCodec ObjectCodec
  (WithOptional TransformFn Body) (WithOptional TransformFn Body)
bodyV1
          Codec
  Object
  (RequestFields (WithOptional TransformFn))
  (RequestFields (WithOptional TransformFn))
-> (RequestTransform -> RequestFields (WithOptional TransformFn))
-> Codec
     Object RequestTransform (RequestFields (WithOptional TransformFn))
forall oldInput output newInput.
ObjectCodec oldInput output
-> (newInput -> oldInput) -> ObjectCodec newInput output
AC..= RequestTransform -> RequestFields (WithOptional TransformFn)
requestFields
            Codec
  Object RequestTransform (TemplatingEngine -> RequestTransform)
-> Codec Object RequestTransform TemplatingEngine
-> ObjectCodec RequestTransform RequestTransform
forall a b.
Codec Object RequestTransform (a -> b)
-> Codec Object RequestTransform a
-> Codec Object RequestTransform b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Codec Object RequestTransform TemplatingEngine
transformCommon

      transformV2 :: JSONCodec RequestTransform
transformV2 =
        Text
-> ObjectCodec RequestTransform RequestTransform
-> JSONCodec RequestTransform
forall input output.
Text -> ObjectCodec input output -> ValueCodec input output
AC.object Text
"RequestTransformV2"
          (ObjectCodec RequestTransform RequestTransform
 -> JSONCodec RequestTransform)
-> ObjectCodec RequestTransform RequestTransform
-> JSONCodec RequestTransform
forall a b. (a -> b) -> a -> b
$ Version
-> RequestFields (WithOptional TransformFn)
-> TemplatingEngine
-> RequestTransform
RequestTransform
          (Version
 -> RequestFields (WithOptional TransformFn)
 -> TemplatingEngine
 -> RequestTransform)
-> Codec Object RequestTransform Version
-> Codec
     Object
     RequestTransform
     (RequestFields (WithOptional TransformFn)
      -> TemplatingEngine -> RequestTransform)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Version
V2 Version
-> Codec Object RequestTransform Scientific
-> Codec Object RequestTransform Version
forall a b.
a
-> Codec Object RequestTransform b
-> Codec Object RequestTransform a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Integer -> Codec Object RequestTransform Scientific
forall a. Integer -> ObjectCodec a Scientific
versionField Integer
2)
          Codec
  Object
  RequestTransform
  (RequestFields (WithOptional TransformFn)
   -> TemplatingEngine -> RequestTransform)
-> Codec
     Object RequestTransform (RequestFields (WithOptional TransformFn))
-> Codec
     Object RequestTransform (TemplatingEngine -> RequestTransform)
forall a b.
Codec Object RequestTransform (a -> b)
-> Codec Object RequestTransform a
-> Codec Object RequestTransform b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ObjectCodec
  (WithOptional TransformFn Body) (WithOptional TransformFn Body)
-> Codec
     Object
     (RequestFields (WithOptional TransformFn))
     (RequestFields (WithOptional TransformFn))
forall {f :: * -> *}.
(Coercible MethodTransformFn (f Method),
 Coercible UnescapedTemplate (f Url),
 Coercible QueryParamsTransformFn (f QueryParams),
 Coercible HeadersTransformFn (f Headers)) =>
ObjectCodec (WithOptional f Body) (WithOptional f Body)
-> Codec
     Object
     (RequestFields (WithOptional f))
     (RequestFields (WithOptional f))
requestFieldsCodec ObjectCodec
  (WithOptional TransformFn Body) (WithOptional TransformFn Body)
bodyV2
          Codec
  Object
  (RequestFields (WithOptional TransformFn))
  (RequestFields (WithOptional TransformFn))
-> (RequestTransform -> RequestFields (WithOptional TransformFn))
-> Codec
     Object RequestTransform (RequestFields (WithOptional TransformFn))
forall oldInput output newInput.
ObjectCodec oldInput output
-> (newInput -> oldInput) -> ObjectCodec newInput output
AC..= RequestTransform -> RequestFields (WithOptional TransformFn)
requestFields
            Codec
  Object RequestTransform (TemplatingEngine -> RequestTransform)
-> Codec Object RequestTransform TemplatingEngine
-> ObjectCodec RequestTransform RequestTransform
forall a b.
Codec Object RequestTransform (a -> b)
-> Codec Object RequestTransform a
-> Codec Object RequestTransform b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Codec Object RequestTransform TemplatingEngine
transformCommon

      transformCommon :: Codec Object RequestTransform TemplatingEngine
transformCommon = Text
-> TemplatingEngine
-> ObjectCodec TemplatingEngine TemplatingEngine
forall output.
HasCodec output =>
Text -> output -> ObjectCodec output output
optionalFieldWithDefault' Text
"template_engine" TemplatingEngine
Kriti ObjectCodec TemplatingEngine TemplatingEngine
-> (RequestTransform -> TemplatingEngine)
-> Codec Object RequestTransform TemplatingEngine
forall oldInput output newInput.
ObjectCodec oldInput output
-> (newInput -> oldInput) -> ObjectCodec newInput output
AC..= RequestTransform -> TemplatingEngine
templateEngine

      requestFieldsCodec :: ObjectCodec (WithOptional f Body) (WithOptional f Body)
-> Codec
     Object
     (RequestFields (WithOptional f))
     (RequestFields (WithOptional f))
requestFieldsCodec ObjectCodec (WithOptional f Body) (WithOptional f Body)
bodyCodec =
        WithOptional f Method
-> WithOptional f Url
-> WithOptional f Body
-> WithOptional f QueryParams
-> WithOptional f Headers
-> RequestFields (WithOptional f)
forall (f :: * -> *).
f Method
-> f Url -> f Body -> f QueryParams -> f Headers -> RequestFields f
RequestFields
          (WithOptional f Method
 -> WithOptional f Url
 -> WithOptional f Body
 -> WithOptional f QueryParams
 -> WithOptional f Headers
 -> RequestFields (WithOptional f))
-> Codec
     Object (RequestFields (WithOptional f)) (WithOptional f Method)
-> Codec
     Object
     (RequestFields (WithOptional f))
     (WithOptional f Url
      -> WithOptional f Body
      -> WithOptional f QueryParams
      -> WithOptional f Headers
      -> RequestFields (WithOptional f))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a b (f :: * -> *).
(Coercible a (f b), HasCodec a) =>
Text -> ObjectCodec (WithOptional f b) (WithOptional f b)
withOptionalField' @MethodTransformFn Text
"method"
          ObjectCodec (WithOptional f Method) (WithOptional f Method)
-> (RequestFields (WithOptional f) -> WithOptional f Method)
-> Codec
     Object (RequestFields (WithOptional f)) (WithOptional f Method)
forall oldInput output newInput.
ObjectCodec oldInput output
-> (newInput -> oldInput) -> ObjectCodec newInput output
AC..= RequestFields (WithOptional f) -> WithOptional f Method
forall (f :: * -> *). RequestFields f -> f Method
method
            Codec
  Object
  (RequestFields (WithOptional f))
  (WithOptional f Url
   -> WithOptional f Body
   -> WithOptional f QueryParams
   -> WithOptional f Headers
   -> RequestFields (WithOptional f))
-> Codec
     Object (RequestFields (WithOptional f)) (WithOptional f Url)
-> Codec
     Object
     (RequestFields (WithOptional f))
     (WithOptional f Body
      -> WithOptional f QueryParams
      -> WithOptional f Headers
      -> RequestFields (WithOptional f))
forall a b.
Codec Object (RequestFields (WithOptional f)) (a -> b)
-> Codec Object (RequestFields (WithOptional f)) a
-> Codec Object (RequestFields (WithOptional f)) b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a b (f :: * -> *).
(Coercible a (f b), HasCodec a) =>
Text -> ObjectCodec (WithOptional f b) (WithOptional f b)
withOptionalField' @UrlTransformFn Text
"url"
          ObjectCodec (WithOptional f Url) (WithOptional f Url)
-> (RequestFields (WithOptional f) -> WithOptional f Url)
-> Codec
     Object (RequestFields (WithOptional f)) (WithOptional f Url)
forall oldInput output newInput.
ObjectCodec oldInput output
-> (newInput -> oldInput) -> ObjectCodec newInput output
AC..= RequestFields (WithOptional f) -> WithOptional f Url
forall (f :: * -> *). RequestFields f -> f Url
url
            Codec
  Object
  (RequestFields (WithOptional f))
  (WithOptional f Body
   -> WithOptional f QueryParams
   -> WithOptional f Headers
   -> RequestFields (WithOptional f))
-> Codec
     Object (RequestFields (WithOptional f)) (WithOptional f Body)
-> Codec
     Object
     (RequestFields (WithOptional f))
     (WithOptional f QueryParams
      -> WithOptional f Headers -> RequestFields (WithOptional f))
forall a b.
Codec Object (RequestFields (WithOptional f)) (a -> b)
-> Codec Object (RequestFields (WithOptional f)) a
-> Codec Object (RequestFields (WithOptional f)) b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ObjectCodec (WithOptional f Body) (WithOptional f Body)
bodyCodec
          ObjectCodec (WithOptional f Body) (WithOptional f Body)
-> (RequestFields (WithOptional f) -> WithOptional f Body)
-> Codec
     Object (RequestFields (WithOptional f)) (WithOptional f Body)
forall oldInput output newInput.
ObjectCodec oldInput output
-> (newInput -> oldInput) -> ObjectCodec newInput output
AC..= RequestFields (WithOptional f) -> WithOptional f Body
forall (f :: * -> *). RequestFields f -> f Body
body
            Codec
  Object
  (RequestFields (WithOptional f))
  (WithOptional f QueryParams
   -> WithOptional f Headers -> RequestFields (WithOptional f))
-> Codec
     Object
     (RequestFields (WithOptional f))
     (WithOptional f QueryParams)
-> Codec
     Object
     (RequestFields (WithOptional f))
     (WithOptional f Headers -> RequestFields (WithOptional f))
forall a b.
Codec Object (RequestFields (WithOptional f)) (a -> b)
-> Codec Object (RequestFields (WithOptional f)) a
-> Codec Object (RequestFields (WithOptional f)) b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a b (f :: * -> *).
(Coercible a (f b), HasCodec a) =>
Text -> ObjectCodec (WithOptional f b) (WithOptional f b)
withOptionalField' @QueryParamsTransformFn Text
"query_params"
          ObjectCodec
  (WithOptional f QueryParams) (WithOptional f QueryParams)
-> (RequestFields (WithOptional f) -> WithOptional f QueryParams)
-> Codec
     Object
     (RequestFields (WithOptional f))
     (WithOptional f QueryParams)
forall oldInput output newInput.
ObjectCodec oldInput output
-> (newInput -> oldInput) -> ObjectCodec newInput output
AC..= RequestFields (WithOptional f) -> WithOptional f QueryParams
forall (f :: * -> *). RequestFields f -> f QueryParams
queryParams
            Codec
  Object
  (RequestFields (WithOptional f))
  (WithOptional f Headers -> RequestFields (WithOptional f))
-> Codec
     Object (RequestFields (WithOptional f)) (WithOptional f Headers)
-> Codec
     Object
     (RequestFields (WithOptional f))
     (RequestFields (WithOptional f))
forall a b.
Codec Object (RequestFields (WithOptional f)) (a -> b)
-> Codec Object (RequestFields (WithOptional f)) a
-> Codec Object (RequestFields (WithOptional f)) b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a b (f :: * -> *).
(Coercible a (f b), HasCodec a) =>
Text -> ObjectCodec (WithOptional f b) (WithOptional f b)
withOptionalField' @HeadersTransformFn Text
"request_headers"
          ObjectCodec (WithOptional f Headers) (WithOptional f Headers)
-> (RequestFields (WithOptional f) -> WithOptional f Headers)
-> Codec
     Object (RequestFields (WithOptional f)) (WithOptional f Headers)
forall oldInput output newInput.
ObjectCodec oldInput output
-> (newInput -> oldInput) -> ObjectCodec newInput output
AC..= RequestFields (WithOptional f) -> WithOptional f Headers
forall (f :: * -> *). RequestFields f -> f Headers
requestHeaders

      bodyV1 :: ObjectCodec
  (WithOptional TransformFn Body) (WithOptional TransformFn Body)
bodyV1 = (Maybe Template -> WithOptional TransformFn Body)
-> (WithOptional TransformFn Body -> Maybe Template)
-> Codec Object (Maybe Template) (Maybe Template)
-> ObjectCodec
     (WithOptional TransformFn Body) (WithOptional TransformFn Body)
forall oldOutput newOutput newInput oldInput context.
(oldOutput -> newOutput)
-> (newInput -> oldInput)
-> Codec context oldInput oldOutput
-> Codec context newInput newOutput
dimapCodec Maybe Template -> WithOptional TransformFn Body
forall {f :: * -> *} {b}.
Coercible BodyTransformFn (f b) =>
Maybe Template -> WithOptional f b
dec WithOptional TransformFn Body -> Maybe Template
enc (Codec Object (Maybe Template) (Maybe Template)
 -> ObjectCodec
      (WithOptional TransformFn Body) (WithOptional TransformFn Body))
-> Codec Object (Maybe Template) (Maybe Template)
-> ObjectCodec
     (WithOptional TransformFn Body) (WithOptional TransformFn Body)
forall a b. (a -> b) -> a -> b
$ forall output.
HasCodec output =>
Text -> ObjectCodec (Maybe output) (Maybe output)
optionalField' @Template Text
"body"
        where
          dec :: Maybe Template -> WithOptional f b
dec Maybe Template
template = Maybe BodyTransformFn -> WithOptional f b
forall a b (f :: * -> *).
Coercible a (f b) =>
Maybe a -> WithOptional f b
withOptional (Maybe BodyTransformFn -> WithOptional f b)
-> Maybe BodyTransformFn -> WithOptional f b
forall a b. (a -> b) -> a -> b
$ (Template -> BodyTransformFn)
-> Maybe Template -> Maybe BodyTransformFn
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Template -> BodyTransformFn
Body.ModifyAsJSON Maybe Template
template
          enc :: WithOptional TransformFn Body -> Maybe Template
enc WithOptional TransformFn Body
body = case WithOptional TransformFn Body -> Maybe (TransformFn Body)
forall (f :: * -> *) result.
WithOptional f result -> Maybe (f result)
getOptional WithOptional TransformFn Body
body of
            Just (BodyTransformFn_ (Body.ModifyAsJSON Template
template)) -> Template -> Maybe Template
forall a. a -> Maybe a
Just Template
template
            Maybe (TransformFn Body)
_ -> Maybe Template
forall a. Maybe a
Nothing

      bodyV2 :: ObjectCodec
  (WithOptional TransformFn Body) (WithOptional TransformFn Body)
bodyV2 = forall a b (f :: * -> *).
(Coercible a (f b), HasCodec a) =>
Text -> ObjectCodec (WithOptional f b) (WithOptional f b)
withOptionalField' @BodyTransformFn Text
"body"

instance FromJSON RequestTransform where
  parseJSON :: Value -> Parser RequestTransform
parseJSON = String
-> (Object -> Parser RequestTransform)
-> Value
-> Parser RequestTransform
forall a. String -> (Object -> Parser a) -> Value -> Parser a
J.withObject String
"RequestTransform" \Object
o -> do
    Version
version <- Object
o Object -> Key -> Parser (Maybe Version)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"version" Parser (Maybe Version) -> Version -> Parser Version
forall a. Parser (Maybe a) -> a -> Parser a
.!= Version
V1
    Maybe MethodTransformFn
method <- Object
o Object -> Key -> Parser (Maybe MethodTransformFn)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"method"
    Maybe UrlTransformFn
url <- Object
o Object -> Key -> Parser (Maybe UrlTransformFn)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"url"
    Maybe BodyTransformFn
body <- case Version
version of
      Version
V1 -> do
        Maybe Template
template :: Maybe Template <- Object
o Object -> Key -> Parser (Maybe Template)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"body"
        Maybe BodyTransformFn -> Parser (Maybe BodyTransformFn)
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe BodyTransformFn -> Parser (Maybe BodyTransformFn))
-> Maybe BodyTransformFn -> Parser (Maybe BodyTransformFn)
forall a b. (a -> b) -> a -> b
$ (Template -> BodyTransformFn)
-> Maybe Template -> Maybe BodyTransformFn
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Template -> BodyTransformFn
Body.ModifyAsJSON Maybe Template
template
      Version
V2 -> Object
o Object -> Key -> Parser (Maybe BodyTransformFn)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"body"
    Maybe QueryParamsTransformFn
queryParams <- Object
o Object -> Key -> Parser (Maybe QueryParamsTransformFn)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"query_params"
    Maybe HeadersTransformFn
headers <- Object
o Object -> Key -> Parser (Maybe HeadersTransformFn)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"request_headers"
    let requestFields :: RequestFields (WithOptional TransformFn)
requestFields =
          RequestFields
            { method :: WithOptional TransformFn Method
method = forall a b (f :: * -> *).
Coercible a (f b) =>
Maybe a -> WithOptional f b
withOptional @MethodTransformFn Maybe MethodTransformFn
method,
              url :: WithOptional TransformFn Url
url = forall a b (f :: * -> *).
Coercible a (f b) =>
Maybe a -> WithOptional f b
withOptional @UrlTransformFn Maybe UrlTransformFn
url,
              body :: WithOptional TransformFn Body
body = forall a b (f :: * -> *).
Coercible a (f b) =>
Maybe a -> WithOptional f b
withOptional @BodyTransformFn Maybe BodyTransformFn
body,
              queryParams :: WithOptional TransformFn QueryParams
queryParams = forall a b (f :: * -> *).
Coercible a (f b) =>
Maybe a -> WithOptional f b
withOptional @QueryParamsTransformFn Maybe QueryParamsTransformFn
queryParams,
              requestHeaders :: WithOptional TransformFn Headers
requestHeaders = forall a b (f :: * -> *).
Coercible a (f b) =>
Maybe a -> WithOptional f b
withOptional @HeadersTransformFn Maybe HeadersTransformFn
headers
            }
    TemplatingEngine
templateEngine <- Object
o Object -> Key -> Parser (Maybe TemplatingEngine)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"template_engine" Parser (Maybe TemplatingEngine)
-> TemplatingEngine -> Parser TemplatingEngine
forall a. Parser (Maybe a) -> a -> Parser a
.!= TemplatingEngine
Kriti
    RequestTransform -> Parser RequestTransform
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (RequestTransform -> Parser RequestTransform)
-> RequestTransform -> Parser RequestTransform
forall a b. (a -> b) -> a -> b
$ RequestTransform {TemplatingEngine
Version
RequestFields (WithOptional TransformFn)
requestFields :: RequestFields (WithOptional TransformFn)
version :: Version
templateEngine :: TemplatingEngine
version :: Version
requestFields :: RequestFields (WithOptional TransformFn)
templateEngine :: TemplatingEngine
..}

instance ToJSON RequestTransform where
  toJSON :: RequestTransform -> Value
toJSON RequestTransform {TemplatingEngine
Version
RequestFields (WithOptional TransformFn)
requestFields :: RequestTransform -> RequestFields (WithOptional TransformFn)
version :: RequestTransform -> Version
templateEngine :: RequestTransform -> TemplatingEngine
version :: Version
requestFields :: RequestFields (WithOptional TransformFn)
templateEngine :: TemplatingEngine
..} =
    let RequestFields {WithOptional TransformFn Url
WithOptional TransformFn QueryParams
WithOptional TransformFn Method
WithOptional TransformFn Headers
WithOptional TransformFn Body
method :: forall (f :: * -> *). RequestFields f -> f Method
url :: forall (f :: * -> *). RequestFields f -> f Url
body :: forall (f :: * -> *). RequestFields f -> f Body
queryParams :: forall (f :: * -> *). RequestFields f -> f QueryParams
requestHeaders :: forall (f :: * -> *). RequestFields f -> f Headers
method :: WithOptional TransformFn Method
url :: WithOptional TransformFn Url
body :: WithOptional TransformFn Body
queryParams :: WithOptional TransformFn QueryParams
requestHeaders :: WithOptional TransformFn Headers
..} = RequestFields (WithOptional TransformFn)
requestFields
        body' :: Maybe (Key, Value)
body' = case Version
version of
          Version
V1 -> case (WithOptional TransformFn Body -> Maybe (TransformFn Body)
forall (f :: * -> *) result.
WithOptional f result -> Maybe (f result)
getOptional WithOptional TransformFn Body
body) of
            Just (BodyTransformFn_ (Body.ModifyAsJSON Template
template)) ->
              (Key, Value) -> Maybe (Key, Value)
forall a. a -> Maybe a
Just (Key
"body", Template -> Value
forall a. ToJSON a => a -> Value
J.toJSON Template
template)
            Maybe (TransformFn Body)
_ -> Maybe (Key, Value)
forall a. Maybe a
Nothing
          Version
V2 -> Key
"body" Key -> Maybe (TransformFn Body) -> Maybe (Key, Value)
forall v kv. (ToJSON v, KeyValue kv) => Key -> Maybe v -> Maybe kv
.=? WithOptional TransformFn Body -> Maybe (TransformFn Body)
forall (f :: * -> *) result.
WithOptional f result -> Maybe (f result)
getOptional WithOptional TransformFn Body
body
     in [(Key, Value)] -> Value
J.object
          ([(Key, Value)] -> Value) -> [(Key, Value)] -> Value
forall a b. (a -> b) -> a -> b
$ [ Key
"version" Key -> Version -> (Key, Value)
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> (Key, Value)
.= Version
version,
              Key
"template_engine" Key -> TemplatingEngine -> (Key, Value)
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> (Key, Value)
.= TemplatingEngine
templateEngine
            ]
          [(Key, Value)] -> [(Key, Value)] -> [(Key, Value)]
forall a. Semigroup a => a -> a -> a
<> [Maybe (Key, Value)] -> [(Key, Value)]
forall a. [Maybe a] -> [a]
forall (f :: * -> *) a. Filterable f => f (Maybe a) -> f a
catMaybes
            [ Key
"method" Key -> Maybe (TransformFn Method) -> Maybe (Key, Value)
forall v kv. (ToJSON v, KeyValue kv) => Key -> Maybe v -> Maybe kv
.=? WithOptional TransformFn Method -> Maybe (TransformFn Method)
forall (f :: * -> *) result.
WithOptional f result -> Maybe (f result)
getOptional WithOptional TransformFn Method
method,
              Key
"url" Key -> Maybe (TransformFn Url) -> Maybe (Key, Value)
forall v kv. (ToJSON v, KeyValue kv) => Key -> Maybe v -> Maybe kv
.=? WithOptional TransformFn Url -> Maybe (TransformFn Url)
forall (f :: * -> *) result.
WithOptional f result -> Maybe (f result)
getOptional WithOptional TransformFn Url
url,
              Key
"query_params" Key -> Maybe (TransformFn QueryParams) -> Maybe (Key, Value)
forall v kv. (ToJSON v, KeyValue kv) => Key -> Maybe v -> Maybe kv
.=? WithOptional TransformFn QueryParams
-> Maybe (TransformFn QueryParams)
forall (f :: * -> *) result.
WithOptional f result -> Maybe (f result)
getOptional WithOptional TransformFn QueryParams
queryParams,
              Key
"request_headers" Key -> Maybe (TransformFn Headers) -> Maybe (Key, Value)
forall v kv. (ToJSON v, KeyValue kv) => Key -> Maybe v -> Maybe kv
.=? WithOptional TransformFn Headers -> Maybe (TransformFn Headers)
forall (f :: * -> *) result.
WithOptional f result -> Maybe (f result)
getOptional WithOptional TransformFn Headers
requestHeaders,
              Maybe (Key, Value)
body'
            ]

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

-- | Defunctionalized Webhook Request Transformation
--
-- We represent a defunctionalized request transformation by parameterizing
-- our HKD with 'WithOptional'@ @'TransformFn', which marks each of the fields
-- as optional and supplies the appropriate transformation function to them if
-- if they are provided.
type RequestTransformFns = RequestFields (WithOptional TransformFn)

-- | Actual Request Data
--
-- We represent the actual request data by parameterizing our HKD with
-- 'Identity', which allows us to trivially unwrap the fields (which should
-- exist after any transformations have been applied).
type RequestData = RequestFields Identity

-- | This is our HKD type. It is a record with fields for each
-- component of an 'HTTP.Request' we wish to transform.
data RequestFields f = RequestFields
  { forall (f :: * -> *). RequestFields f -> f Method
method :: f Method,
    forall (f :: * -> *). RequestFields f -> f Url
url :: f Url,
    forall (f :: * -> *). RequestFields f -> f Body
body :: f Body,
    forall (f :: * -> *). RequestFields f -> f QueryParams
queryParams :: f QueryParams,
    forall (f :: * -> *). RequestFields f -> f Headers
requestHeaders :: f Headers
  }
  deriving stock ((forall x. RequestFields f -> Rep (RequestFields f) x)
-> (forall x. Rep (RequestFields f) x -> RequestFields f)
-> Generic (RequestFields f)
forall x. Rep (RequestFields f) x -> RequestFields f
forall x. RequestFields f -> Rep (RequestFields f) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall (f :: * -> *) x. Rep (RequestFields f) x -> RequestFields f
forall (f :: * -> *) x. RequestFields f -> Rep (RequestFields f) x
$cfrom :: forall (f :: * -> *) x. RequestFields f -> Rep (RequestFields f) x
from :: forall x. RequestFields f -> Rep (RequestFields f) x
$cto :: forall (f :: * -> *) x. Rep (RequestFields f) x -> RequestFields f
to :: forall x. Rep (RequestFields f) x -> RequestFields f
Generic)
  deriving anyclass ((forall (f :: * -> *) (g :: * -> *).
 (forall a. f a -> g a) -> RequestFields f -> RequestFields g)
-> FunctorB RequestFields
forall k (b :: (k -> *) -> *).
(forall (f :: k -> *) (g :: k -> *).
 (forall (a :: k). f a -> g a) -> b f -> b g)
-> FunctorB b
forall (f :: * -> *) (g :: * -> *).
(forall a. f a -> g a) -> RequestFields f -> RequestFields g
$cbmap :: forall (f :: * -> *) (g :: * -> *).
(forall a. f a -> g a) -> RequestFields f -> RequestFields g
bmap :: forall (f :: * -> *) (g :: * -> *).
(forall a. f a -> g a) -> RequestFields f -> RequestFields g
FunctorB, FunctorB RequestFields
FunctorB RequestFields
-> (forall (f :: * -> *). (forall a. f a) -> RequestFields f)
-> (forall (f :: * -> *) (g :: * -> *).
    RequestFields f -> RequestFields g -> RequestFields (Product f g))
-> ApplicativeB RequestFields
forall k (b :: (k -> *) -> *).
FunctorB b
-> (forall (f :: k -> *). (forall (a :: k). f a) -> b f)
-> (forall (f :: k -> *) (g :: k -> *).
    b f -> b g -> b (Product f g))
-> ApplicativeB b
forall (f :: * -> *). (forall a. f a) -> RequestFields f
forall (f :: * -> *) (g :: * -> *).
RequestFields f -> RequestFields g -> RequestFields (Product f g)
$cbpure :: forall (f :: * -> *). (forall a. f a) -> RequestFields f
bpure :: forall (f :: * -> *). (forall a. f a) -> RequestFields f
$cbprod :: forall (f :: * -> *) (g :: * -> *).
RequestFields f -> RequestFields g -> RequestFields (Product f g)
bprod :: forall (f :: * -> *) (g :: * -> *).
RequestFields f -> RequestFields g -> RequestFields (Product f g)
ApplicativeB, FunctorB RequestFields
FunctorB RequestFields
-> (forall (e :: * -> *) (f :: * -> *) (g :: * -> *).
    Applicative e =>
    (forall a. f a -> e (g a))
    -> RequestFields f -> e (RequestFields g))
-> TraversableB RequestFields
forall k (b :: (k -> *) -> *).
FunctorB b
-> (forall (e :: * -> *) (f :: k -> *) (g :: k -> *).
    Applicative e =>
    (forall (a :: k). f a -> e (g a)) -> b f -> e (b g))
-> TraversableB b
forall (e :: * -> *) (f :: * -> *) (g :: * -> *).
Applicative e =>
(forall a. f a -> e (g a))
-> RequestFields f -> e (RequestFields g)
$cbtraverse :: forall (e :: * -> *) (f :: * -> *) (g :: * -> *).
Applicative e =>
(forall a. f a -> e (g a))
-> RequestFields f -> e (RequestFields g)
btraverse :: forall (e :: * -> *) (f :: * -> *) (g :: * -> *).
Applicative e =>
(forall a. f a -> e (g a))
-> RequestFields f -> e (RequestFields g)
TraversableB, FunctorB RequestFields
FunctorB RequestFields
-> (forall (c :: * -> Constraint) (f :: * -> *).
    AllB c RequestFields =>
    RequestFields f -> RequestFields (Product (Dict c) f))
-> ConstraintsB RequestFields
forall k (b :: (k -> *) -> *).
FunctorB b
-> (forall (c :: k -> Constraint) (f :: k -> *).
    AllB c b =>
    b f -> b (Product (Dict c) f))
-> ConstraintsB b
forall (c :: * -> Constraint) (f :: * -> *).
AllB c RequestFields =>
RequestFields f -> RequestFields (Product (Dict c) f)
$cbaddDicts :: forall (c :: * -> Constraint) (f :: * -> *).
AllB c RequestFields =>
RequestFields f -> RequestFields (Product (Dict c) f)
baddDicts :: forall (c :: * -> Constraint) (f :: * -> *).
AllB c RequestFields =>
RequestFields f -> RequestFields (Product (Dict c) f)
ConstraintsB)

deriving stock instance
  (AllBF Show f RequestFields) =>
  Show (RequestFields f)

deriving stock instance
  (AllBF Eq f RequestFields) =>
  Eq (RequestFields f)

deriving anyclass instance
  (AllBF NFData f RequestFields) =>
  NFData (RequestFields f)

-- NOTE: It is likely that we can derive these instances. Possibly if
-- we move the aeson instances onto the *Transform types.
instance FromJSON RequestTransformFns where
  parseJSON :: Value -> Parser (RequestFields (WithOptional TransformFn))
parseJSON = String
-> (Object -> Parser (RequestFields (WithOptional TransformFn)))
-> Value
-> Parser (RequestFields (WithOptional TransformFn))
forall a. String -> (Object -> Parser a) -> Value -> Parser a
J.withObject String
"RequestTransformFns" ((Object -> Parser (RequestFields (WithOptional TransformFn)))
 -> Value -> Parser (RequestFields (WithOptional TransformFn)))
-> (Object -> Parser (RequestFields (WithOptional TransformFn)))
-> Value
-> Parser (RequestFields (WithOptional TransformFn))
forall a b. (a -> b) -> a -> b
$ \Object
o -> do
    Maybe MethodTransformFn
method <- Object
o Object -> Key -> Parser (Maybe MethodTransformFn)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"method"
    Maybe UrlTransformFn
url <- Object
o Object -> Key -> Parser (Maybe UrlTransformFn)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"url"
    Maybe BodyTransformFn
body <- Object
o Object -> Key -> Parser (Maybe BodyTransformFn)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"body"
    Maybe QueryParamsTransformFn
queryParams <- Object
o Object -> Key -> Parser (Maybe QueryParamsTransformFn)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"query_params"
    Maybe HeadersTransformFn
headers <- Object
o Object -> Key -> Parser (Maybe HeadersTransformFn)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"request_headers"
    RequestFields (WithOptional TransformFn)
-> Parser (RequestFields (WithOptional TransformFn))
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
      (RequestFields (WithOptional TransformFn)
 -> Parser (RequestFields (WithOptional TransformFn)))
-> RequestFields (WithOptional TransformFn)
-> Parser (RequestFields (WithOptional TransformFn))
forall a b. (a -> b) -> a -> b
$ RequestFields
        { method :: WithOptional TransformFn Method
method = forall a b (f :: * -> *).
Coercible a (f b) =>
Maybe a -> WithOptional f b
withOptional @MethodTransformFn Maybe MethodTransformFn
method,
          url :: WithOptional TransformFn Url
url = forall a b (f :: * -> *).
Coercible a (f b) =>
Maybe a -> WithOptional f b
withOptional @UrlTransformFn Maybe UrlTransformFn
url,
          body :: WithOptional TransformFn Body
body = forall a b (f :: * -> *).
Coercible a (f b) =>
Maybe a -> WithOptional f b
withOptional @BodyTransformFn Maybe BodyTransformFn
body,
          queryParams :: WithOptional TransformFn QueryParams
queryParams = forall a b (f :: * -> *).
Coercible a (f b) =>
Maybe a -> WithOptional f b
withOptional @QueryParamsTransformFn Maybe QueryParamsTransformFn
queryParams,
          requestHeaders :: WithOptional TransformFn Headers
requestHeaders = forall a b (f :: * -> *).
Coercible a (f b) =>
Maybe a -> WithOptional f b
withOptional @HeadersTransformFn Maybe HeadersTransformFn
headers
        }

instance ToJSON RequestTransformFns where
  toJSON :: RequestFields (WithOptional TransformFn) -> Value
toJSON RequestFields {WithOptional TransformFn Url
WithOptional TransformFn QueryParams
WithOptional TransformFn Method
WithOptional TransformFn Headers
WithOptional TransformFn Body
method :: forall (f :: * -> *). RequestFields f -> f Method
url :: forall (f :: * -> *). RequestFields f -> f Url
body :: forall (f :: * -> *). RequestFields f -> f Body
queryParams :: forall (f :: * -> *). RequestFields f -> f QueryParams
requestHeaders :: forall (f :: * -> *). RequestFields f -> f Headers
method :: WithOptional TransformFn Method
url :: WithOptional TransformFn Url
body :: WithOptional TransformFn Body
queryParams :: WithOptional TransformFn QueryParams
requestHeaders :: WithOptional TransformFn Headers
..} =
    [(Key, Value)] -> Value
J.object
      ([(Key, Value)] -> Value)
-> ([Maybe (Key, Value)] -> [(Key, Value)])
-> [Maybe (Key, Value)]
-> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Maybe (Key, Value)] -> [(Key, Value)]
forall a. [Maybe a] -> [a]
forall (f :: * -> *) a. Filterable f => f (Maybe a) -> f a
catMaybes
      ([Maybe (Key, Value)] -> Value) -> [Maybe (Key, Value)] -> Value
forall a b. (a -> b) -> a -> b
$ [ Key
"method" Key -> Maybe (TransformFn Method) -> Maybe (Key, Value)
forall v kv. (ToJSON v, KeyValue kv) => Key -> Maybe v -> Maybe kv
.=? WithOptional TransformFn Method -> Maybe (TransformFn Method)
forall (f :: * -> *) result.
WithOptional f result -> Maybe (f result)
getOptional WithOptional TransformFn Method
method,
          Key
"url" Key -> Maybe (TransformFn Url) -> Maybe (Key, Value)
forall v kv. (ToJSON v, KeyValue kv) => Key -> Maybe v -> Maybe kv
.=? WithOptional TransformFn Url -> Maybe (TransformFn Url)
forall (f :: * -> *) result.
WithOptional f result -> Maybe (f result)
getOptional WithOptional TransformFn Url
url,
          Key
"body" Key -> Maybe (TransformFn Body) -> Maybe (Key, Value)
forall v kv. (ToJSON v, KeyValue kv) => Key -> Maybe v -> Maybe kv
.=? WithOptional TransformFn Body -> Maybe (TransformFn Body)
forall (f :: * -> *) result.
WithOptional f result -> Maybe (f result)
getOptional WithOptional TransformFn Body
body,
          Key
"query_params" Key -> Maybe (TransformFn QueryParams) -> Maybe (Key, Value)
forall v kv. (ToJSON v, KeyValue kv) => Key -> Maybe v -> Maybe kv
.=? WithOptional TransformFn QueryParams
-> Maybe (TransformFn QueryParams)
forall (f :: * -> *) result.
WithOptional f result -> Maybe (f result)
getOptional WithOptional TransformFn QueryParams
queryParams,
          Key
"request_headers" Key -> Maybe (TransformFn Headers) -> Maybe (Key, Value)
forall v kv. (ToJSON v, KeyValue kv) => Key -> Maybe v -> Maybe kv
.=? WithOptional TransformFn Headers -> Maybe (TransformFn Headers)
forall (f :: * -> *) result.
WithOptional f result -> Maybe (f result)
getOptional WithOptional TransformFn Headers
requestHeaders
        ]

type RequestContext = RequestFields TransformCtx

instance ToJSON RequestContext where
  toJSON :: RequestContext -> Value
toJSON RequestFields {TransformCtx Url
TransformCtx QueryParams
TransformCtx Method
TransformCtx Headers
TransformCtx Body
method :: forall (f :: * -> *). RequestFields f -> f Method
url :: forall (f :: * -> *). RequestFields f -> f Url
body :: forall (f :: * -> *). RequestFields f -> f Body
queryParams :: forall (f :: * -> *). RequestFields f -> f QueryParams
requestHeaders :: forall (f :: * -> *). RequestFields f -> f Headers
method :: TransformCtx Method
url :: TransformCtx Url
body :: TransformCtx Body
queryParams :: TransformCtx QueryParams
requestHeaders :: TransformCtx Headers
..} =
    [(Key, Value)] -> Value
J.object
      [ Key
"method" Key -> RequestTransformCtx -> (Key, Value)
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> (Key, Value)
.= forall a b. Coercible a b => a -> b
forall a b. Coercible a b => a -> b
coerce @_ @RequestTransformCtx TransformCtx Method
method,
        Key
"url" Key -> RequestTransformCtx -> (Key, Value)
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> (Key, Value)
.= forall a b. Coercible a b => a -> b
forall a b. Coercible a b => a -> b
coerce @_ @RequestTransformCtx TransformCtx Url
url,
        Key
"body" Key -> RequestTransformCtx -> (Key, Value)
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> (Key, Value)
.= forall a b. Coercible a b => a -> b
forall a b. Coercible a b => a -> b
coerce @_ @RequestTransformCtx TransformCtx Body
body,
        Key
"query_params" Key -> RequestTransformCtx -> (Key, Value)
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> (Key, Value)
.= forall a b. Coercible a b => a -> b
forall a b. Coercible a b => a -> b
coerce @_ @RequestTransformCtx TransformCtx QueryParams
queryParams,
        Key
"request_headers" Key -> RequestTransformCtx -> (Key, Value)
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> (Key, Value)
.= forall a b. Coercible a b => a -> b
forall a b. Coercible a b => a -> b
coerce @_ @RequestTransformCtx TransformCtx Headers
requestHeaders
      ]