{-# LANGUAGE TemplateHaskell #-}

-- | Types related to metadata management API
module Hasura.RQL.DDL.Metadata.Types
  ( -- * Export Metadata
    ExportMetadata (..),

    -- * Replace Metadata
    ReplaceMetadata (..),
    ReplaceMetadataV1 (..),
    ReplaceMetadataV2 (..),
    AllowInconsistentMetadata (..),

    -- * Reload Metadata
    ReloadMetadata (..),
    ReloadSpec (..),

    -- * Clear Metadata
    ClearMetadata (..),

    -- * Get Inconsistent Metadata
    GetInconsistentMetadata (..),

    -- * Drop Inconsistent Metadata
    DropInconsistentMetadata (..),

    -- * Test Webhook Transform
    TestWebhookTransform (..),
    twtTransformer,
    WebHookUrl (..),

    -- * Dump Internal State
    DumpInternalState (..),
  )
where

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

import Control.Lens (Lens')
import Control.Lens qualified as Lens
import Data.Aeson (FromJSON, ToJSON, (.!=), (.:), (.:?), (.=))
import Data.Aeson qualified as Aeson
import Data.Aeson.KeyMap qualified as KeyMap
import Data.Aeson.TH qualified as Aeson.TH
import Data.CaseInsensitive qualified as CI
import Data.Environment qualified as Env
import Hasura.Prelude
import Hasura.RQL.DDL.Webhook.Transform (MetadataResponseTransform, RequestTransform)
import Hasura.RQL.Types.Common qualified as Common
import Hasura.RQL.Types.Metadata (Metadata, MetadataNoSources)
import Hasura.RQL.Types.Metadata qualified as Metadata
import Hasura.RQL.Types.RemoteSchema (RemoteSchemaName)
import Hasura.Session (SessionVariables)
import Network.HTTP.Client.Transformable qualified as HTTP

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

-- | 'ClearMetadata' can be used to reset the state of Hasura -- clean
-- the current state by forgetting the tables tracked, relationships,
-- permissions, event triggers etc.
--
-- https://hasura.io/docs/latest/api-reference/metadata-api/manage-metadata/#metadata-clear-metadata
data ClearMetadata
  = ClearMetadata
  deriving (Int -> ClearMetadata -> ShowS
[ClearMetadata] -> ShowS
ClearMetadata -> String
(Int -> ClearMetadata -> ShowS)
-> (ClearMetadata -> String)
-> ([ClearMetadata] -> ShowS)
-> Show ClearMetadata
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ClearMetadata] -> ShowS
$cshowList :: [ClearMetadata] -> ShowS
show :: ClearMetadata -> String
$cshow :: ClearMetadata -> String
showsPrec :: Int -> ClearMetadata -> ShowS
$cshowsPrec :: Int -> ClearMetadata -> ShowS
Show, ClearMetadata -> ClearMetadata -> Bool
(ClearMetadata -> ClearMetadata -> Bool)
-> (ClearMetadata -> ClearMetadata -> Bool) -> Eq ClearMetadata
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ClearMetadata -> ClearMetadata -> Bool
$c/= :: ClearMetadata -> ClearMetadata -> Bool
== :: ClearMetadata -> ClearMetadata -> Bool
$c== :: ClearMetadata -> ClearMetadata -> Bool
Eq)

$(Aeson.TH.deriveToJSON Aeson.TH.defaultOptions ''ClearMetadata)

instance FromJSON ClearMetadata where
  parseJSON :: Value -> Parser ClearMetadata
parseJSON Value
_ = ClearMetadata -> Parser ClearMetadata
forall (m :: * -> *) a. Monad m => a -> m a
return ClearMetadata
ClearMetadata

-- | 'ExportMetadata' is used to export the current metadata from the
-- server as a JSON file.
--
-- https://hasura.io/docs/latest/api-reference/metadata-api/manage-metadata/#metadata-export-metadata
data ExportMetadata = ExportMetadata deriving (Int -> ExportMetadata -> ShowS
[ExportMetadata] -> ShowS
ExportMetadata -> String
(Int -> ExportMetadata -> ShowS)
-> (ExportMetadata -> String)
-> ([ExportMetadata] -> ShowS)
-> Show ExportMetadata
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ExportMetadata] -> ShowS
$cshowList :: [ExportMetadata] -> ShowS
show :: ExportMetadata -> String
$cshow :: ExportMetadata -> String
showsPrec :: Int -> ExportMetadata -> ShowS
$cshowsPrec :: Int -> ExportMetadata -> ShowS
Show, ExportMetadata -> ExportMetadata -> Bool
(ExportMetadata -> ExportMetadata -> Bool)
-> (ExportMetadata -> ExportMetadata -> Bool) -> Eq ExportMetadata
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ExportMetadata -> ExportMetadata -> Bool
$c/= :: ExportMetadata -> ExportMetadata -> Bool
== :: ExportMetadata -> ExportMetadata -> Bool
$c== :: ExportMetadata -> ExportMetadata -> Bool
Eq)

instance ToJSON ExportMetadata where
  toJSON :: ExportMetadata -> Value
toJSON ExportMetadata
ExportMetadata = [Pair] -> Value
Aeson.object []

instance FromJSON ExportMetadata where
  parseJSON :: Value -> Parser ExportMetadata
parseJSON Value
_ = ExportMetadata -> Parser ExportMetadata
forall (f :: * -> *) a. Applicative f => a -> f a
pure ExportMetadata
ExportMetadata

data ReloadSpec a
  = RSReloadAll
  | RSReloadList (HashSet a)
  deriving (Int -> ReloadSpec a -> ShowS
[ReloadSpec a] -> ShowS
ReloadSpec a -> String
(Int -> ReloadSpec a -> ShowS)
-> (ReloadSpec a -> String)
-> ([ReloadSpec a] -> ShowS)
-> Show (ReloadSpec a)
forall a. Show a => Int -> ReloadSpec a -> ShowS
forall a. Show a => [ReloadSpec a] -> ShowS
forall a. Show a => ReloadSpec a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ReloadSpec a] -> ShowS
$cshowList :: forall a. Show a => [ReloadSpec a] -> ShowS
show :: ReloadSpec a -> String
$cshow :: forall a. Show a => ReloadSpec a -> String
showsPrec :: Int -> ReloadSpec a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> ReloadSpec a -> ShowS
Show, ReloadSpec a -> ReloadSpec a -> Bool
(ReloadSpec a -> ReloadSpec a -> Bool)
-> (ReloadSpec a -> ReloadSpec a -> Bool) -> Eq (ReloadSpec a)
forall a. Eq a => ReloadSpec a -> ReloadSpec a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ReloadSpec a -> ReloadSpec a -> Bool
$c/= :: forall a. Eq a => ReloadSpec a -> ReloadSpec a -> Bool
== :: ReloadSpec a -> ReloadSpec a -> Bool
$c== :: forall a. Eq a => ReloadSpec a -> ReloadSpec a -> Bool
Eq)

instance (ToJSON a) => ToJSON (ReloadSpec a) where
  toJSON :: ReloadSpec a -> Value
toJSON = \case
    ReloadSpec a
RSReloadAll -> Bool -> Value
Aeson.Bool Bool
True
    RSReloadList HashSet a
l -> HashSet a -> Value
forall a. ToJSON a => a -> Value
Aeson.toJSON HashSet a
l

instance (FromJSON a, Eq a, Hashable a) => FromJSON (ReloadSpec a) where
  parseJSON :: Value -> Parser (ReloadSpec a)
parseJSON (Aeson.Bool Bool
b) = ReloadSpec a -> Parser (ReloadSpec a)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ReloadSpec a -> Parser (ReloadSpec a))
-> ReloadSpec a -> Parser (ReloadSpec a)
forall a b. (a -> b) -> a -> b
$ if Bool
b then ReloadSpec a
forall a. ReloadSpec a
RSReloadAll else HashSet a -> ReloadSpec a
forall a. HashSet a -> ReloadSpec a
RSReloadList HashSet a
forall a. Monoid a => a
mempty
  parseJSON Value
v = HashSet a -> ReloadSpec a
forall a. HashSet a -> ReloadSpec a
RSReloadList (HashSet a -> ReloadSpec a)
-> Parser (HashSet a) -> Parser (ReloadSpec a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser (HashSet a)
forall a. FromJSON a => Value -> Parser a
Aeson.parseJSON Value
v

type ReloadRemoteSchemas = ReloadSpec RemoteSchemaName

type ReloadSources = ReloadSpec Common.SourceName

reloadAllRemoteSchemas :: ReloadRemoteSchemas
reloadAllRemoteSchemas :: ReloadRemoteSchemas
reloadAllRemoteSchemas = ReloadRemoteSchemas
forall a. ReloadSpec a
RSReloadAll

reloadAllSources :: ReloadSources
reloadAllSources :: ReloadSources
reloadAllSources = ReloadSources
forall a. ReloadSpec a
RSReloadAll

-- | 'ReloadMetadata' should be used when there is a change in
-- underlying Postgres database that Hasura should be aware
-- of. Example: a new column is added to a table using psql and this
-- column should now be added to the GraphQL schema.
--
-- https://hasura.io/docs/latest/api-reference/metadata-api/manage-metadata/#metadata-reload-metadata
data ReloadMetadata = ReloadMetadata
  { ReloadMetadata -> ReloadRemoteSchemas
_rmReloadRemoteSchemas :: ReloadRemoteSchemas,
    ReloadMetadata -> ReloadSources
_rmReloadSources :: ReloadSources,
    -- | Provides a way for the user to allow to explicitly recreate event triggers
    --   for some or all the sources. This is useful when a user may have fiddled with
    --   the SQL trigger in the source and they'd simply want the event trigger to be
    --   recreated without deleting and creating the event trigger. By default, no
    --   source's event triggers will be recreated.
    ReloadMetadata -> ReloadSources
_rmRecreateEventTriggers :: ReloadSources
  }
  deriving (Int -> ReloadMetadata -> ShowS
[ReloadMetadata] -> ShowS
ReloadMetadata -> String
(Int -> ReloadMetadata -> ShowS)
-> (ReloadMetadata -> String)
-> ([ReloadMetadata] -> ShowS)
-> Show ReloadMetadata
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ReloadMetadata] -> ShowS
$cshowList :: [ReloadMetadata] -> ShowS
show :: ReloadMetadata -> String
$cshow :: ReloadMetadata -> String
showsPrec :: Int -> ReloadMetadata -> ShowS
$cshowsPrec :: Int -> ReloadMetadata -> ShowS
Show, ReloadMetadata -> ReloadMetadata -> Bool
(ReloadMetadata -> ReloadMetadata -> Bool)
-> (ReloadMetadata -> ReloadMetadata -> Bool) -> Eq ReloadMetadata
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ReloadMetadata -> ReloadMetadata -> Bool
$c/= :: ReloadMetadata -> ReloadMetadata -> Bool
== :: ReloadMetadata -> ReloadMetadata -> Bool
$c== :: ReloadMetadata -> ReloadMetadata -> Bool
Eq)

$(Aeson.TH.deriveToJSON hasuraJSON ''ReloadMetadata)

instance FromJSON ReloadMetadata where
  parseJSON :: Value -> Parser ReloadMetadata
parseJSON = String
-> (Object -> Parser ReloadMetadata)
-> Value
-> Parser ReloadMetadata
forall a. String -> (Object -> Parser a) -> Value -> Parser a
Aeson.withObject String
"ReloadMetadata" ((Object -> Parser ReloadMetadata)
 -> Value -> Parser ReloadMetadata)
-> (Object -> Parser ReloadMetadata)
-> Value
-> Parser ReloadMetadata
forall a b. (a -> b) -> a -> b
$ \Object
o ->
    ReloadRemoteSchemas
-> ReloadSources -> ReloadSources -> ReloadMetadata
ReloadMetadata
      (ReloadRemoteSchemas
 -> ReloadSources -> ReloadSources -> ReloadMetadata)
-> Parser ReloadRemoteSchemas
-> Parser (ReloadSources -> ReloadSources -> ReloadMetadata)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> Key -> Parser (Maybe ReloadRemoteSchemas)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"reload_remote_schemas" Parser (Maybe ReloadRemoteSchemas)
-> ReloadRemoteSchemas -> Parser ReloadRemoteSchemas
forall a. Parser (Maybe a) -> a -> Parser a
.!= ReloadRemoteSchemas
reloadAllRemoteSchemas
      Parser (ReloadSources -> ReloadSources -> ReloadMetadata)
-> Parser ReloadSources -> Parser (ReloadSources -> ReloadMetadata)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser (Maybe ReloadSources)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"reload_sources" Parser (Maybe ReloadSources)
-> ReloadSources -> Parser ReloadSources
forall a. Parser (Maybe a) -> a -> Parser a
.!= ReloadSources
reloadAllSources
      Parser (ReloadSources -> ReloadMetadata)
-> Parser ReloadSources -> Parser ReloadMetadata
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser (Maybe ReloadSources)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"recreate_event_triggers" Parser (Maybe ReloadSources)
-> ReloadSources -> Parser ReloadSources
forall a. Parser (Maybe a) -> a -> Parser a
.!= HashSet SourceName -> ReloadSources
forall a. HashSet a -> ReloadSpec a
RSReloadList HashSet SourceName
forall a. Monoid a => a
mempty

-- | Undocumented Metadata API action which serializes the entire
-- 'SchemaCache'.
data DumpInternalState
  = DumpInternalState
  deriving (Int -> DumpInternalState -> ShowS
[DumpInternalState] -> ShowS
DumpInternalState -> String
(Int -> DumpInternalState -> ShowS)
-> (DumpInternalState -> String)
-> ([DumpInternalState] -> ShowS)
-> Show DumpInternalState
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [DumpInternalState] -> ShowS
$cshowList :: [DumpInternalState] -> ShowS
show :: DumpInternalState -> String
$cshow :: DumpInternalState -> String
showsPrec :: Int -> DumpInternalState -> ShowS
$cshowsPrec :: Int -> DumpInternalState -> ShowS
Show, DumpInternalState -> DumpInternalState -> Bool
(DumpInternalState -> DumpInternalState -> Bool)
-> (DumpInternalState -> DumpInternalState -> Bool)
-> Eq DumpInternalState
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: DumpInternalState -> DumpInternalState -> Bool
$c/= :: DumpInternalState -> DumpInternalState -> Bool
== :: DumpInternalState -> DumpInternalState -> Bool
$c== :: DumpInternalState -> DumpInternalState -> Bool
Eq)

$(Aeson.TH.deriveToJSON Aeson.TH.defaultOptions ''DumpInternalState)

instance FromJSON DumpInternalState where
  parseJSON :: Value -> Parser DumpInternalState
parseJSON Value
_ = DumpInternalState -> Parser DumpInternalState
forall (m :: * -> *) a. Monad m => a -> m a
return DumpInternalState
DumpInternalState

-- | 'GetInconsistentMetadata' can be used to fetch all inconsistent metadata objects.
--
-- https://hasura.io/docs/latest/api-reference/schema-metadata-api/manage-metadata/#schema-metadata-get-inconsistent-metadata
data GetInconsistentMetadata
  = GetInconsistentMetadata
  deriving (Int -> GetInconsistentMetadata -> ShowS
[GetInconsistentMetadata] -> ShowS
GetInconsistentMetadata -> String
(Int -> GetInconsistentMetadata -> ShowS)
-> (GetInconsistentMetadata -> String)
-> ([GetInconsistentMetadata] -> ShowS)
-> Show GetInconsistentMetadata
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [GetInconsistentMetadata] -> ShowS
$cshowList :: [GetInconsistentMetadata] -> ShowS
show :: GetInconsistentMetadata -> String
$cshow :: GetInconsistentMetadata -> String
showsPrec :: Int -> GetInconsistentMetadata -> ShowS
$cshowsPrec :: Int -> GetInconsistentMetadata -> ShowS
Show, GetInconsistentMetadata -> GetInconsistentMetadata -> Bool
(GetInconsistentMetadata -> GetInconsistentMetadata -> Bool)
-> (GetInconsistentMetadata -> GetInconsistentMetadata -> Bool)
-> Eq GetInconsistentMetadata
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: GetInconsistentMetadata -> GetInconsistentMetadata -> Bool
$c/= :: GetInconsistentMetadata -> GetInconsistentMetadata -> Bool
== :: GetInconsistentMetadata -> GetInconsistentMetadata -> Bool
$c== :: GetInconsistentMetadata -> GetInconsistentMetadata -> Bool
Eq)

$(Aeson.TH.deriveToJSON Aeson.TH.defaultOptions ''GetInconsistentMetadata)

instance FromJSON GetInconsistentMetadata where
  parseJSON :: Value -> Parser GetInconsistentMetadata
parseJSON Value
_ = GetInconsistentMetadata -> Parser GetInconsistentMetadata
forall (m :: * -> *) a. Monad m => a -> m a
return GetInconsistentMetadata
GetInconsistentMetadata

-- | 'DropInconsistentMetadata' can be used to purge all inconsistent
-- objects from the metadata.
--
-- https://hasura.io/docs/latest/api-reference/metadata-api/manage-metadata/#metadata-drop-inconsistent-metadata
data DropInconsistentMetadata
  = DropInconsistentMetadata
  deriving (Int -> DropInconsistentMetadata -> ShowS
[DropInconsistentMetadata] -> ShowS
DropInconsistentMetadata -> String
(Int -> DropInconsistentMetadata -> ShowS)
-> (DropInconsistentMetadata -> String)
-> ([DropInconsistentMetadata] -> ShowS)
-> Show DropInconsistentMetadata
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [DropInconsistentMetadata] -> ShowS
$cshowList :: [DropInconsistentMetadata] -> ShowS
show :: DropInconsistentMetadata -> String
$cshow :: DropInconsistentMetadata -> String
showsPrec :: Int -> DropInconsistentMetadata -> ShowS
$cshowsPrec :: Int -> DropInconsistentMetadata -> ShowS
Show, DropInconsistentMetadata -> DropInconsistentMetadata -> Bool
(DropInconsistentMetadata -> DropInconsistentMetadata -> Bool)
-> (DropInconsistentMetadata -> DropInconsistentMetadata -> Bool)
-> Eq DropInconsistentMetadata
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: DropInconsistentMetadata -> DropInconsistentMetadata -> Bool
$c/= :: DropInconsistentMetadata -> DropInconsistentMetadata -> Bool
== :: DropInconsistentMetadata -> DropInconsistentMetadata -> Bool
$c== :: DropInconsistentMetadata -> DropInconsistentMetadata -> Bool
Eq)

$(Aeson.TH.deriveToJSON Aeson.TH.defaultOptions ''DropInconsistentMetadata)

instance FromJSON DropInconsistentMetadata where
  parseJSON :: Value -> Parser DropInconsistentMetadata
parseJSON Value
_ = DropInconsistentMetadata -> Parser DropInconsistentMetadata
forall (m :: * -> *) a. Monad m => a -> m a
return DropInconsistentMetadata
DropInconsistentMetadata

data AllowInconsistentMetadata
  = AllowInconsistentMetadata
  | NoAllowInconsistentMetadata
  deriving (Int -> AllowInconsistentMetadata -> ShowS
[AllowInconsistentMetadata] -> ShowS
AllowInconsistentMetadata -> String
(Int -> AllowInconsistentMetadata -> ShowS)
-> (AllowInconsistentMetadata -> String)
-> ([AllowInconsistentMetadata] -> ShowS)
-> Show AllowInconsistentMetadata
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [AllowInconsistentMetadata] -> ShowS
$cshowList :: [AllowInconsistentMetadata] -> ShowS
show :: AllowInconsistentMetadata -> String
$cshow :: AllowInconsistentMetadata -> String
showsPrec :: Int -> AllowInconsistentMetadata -> ShowS
$cshowsPrec :: Int -> AllowInconsistentMetadata -> ShowS
Show, AllowInconsistentMetadata -> AllowInconsistentMetadata -> Bool
(AllowInconsistentMetadata -> AllowInconsistentMetadata -> Bool)
-> (AllowInconsistentMetadata -> AllowInconsistentMetadata -> Bool)
-> Eq AllowInconsistentMetadata
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: AllowInconsistentMetadata -> AllowInconsistentMetadata -> Bool
$c/= :: AllowInconsistentMetadata -> AllowInconsistentMetadata -> Bool
== :: AllowInconsistentMetadata -> AllowInconsistentMetadata -> Bool
$c== :: AllowInconsistentMetadata -> AllowInconsistentMetadata -> Bool
Eq)

instance FromJSON AllowInconsistentMetadata where
  parseJSON :: Value -> Parser AllowInconsistentMetadata
parseJSON =
    String
-> (Bool -> Parser AllowInconsistentMetadata)
-> Value
-> Parser AllowInconsistentMetadata
forall a. String -> (Bool -> Parser a) -> Value -> Parser a
Aeson.withBool String
"AllowInconsistentMetadata" ((Bool -> Parser AllowInconsistentMetadata)
 -> Value -> Parser AllowInconsistentMetadata)
-> (Bool -> Parser AllowInconsistentMetadata)
-> Value
-> Parser AllowInconsistentMetadata
forall a b. (a -> b) -> a -> b
$
      AllowInconsistentMetadata -> Parser AllowInconsistentMetadata
forall (f :: * -> *) a. Applicative f => a -> f a
pure (AllowInconsistentMetadata -> Parser AllowInconsistentMetadata)
-> (Bool -> AllowInconsistentMetadata)
-> Bool
-> Parser AllowInconsistentMetadata
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AllowInconsistentMetadata
-> AllowInconsistentMetadata -> Bool -> AllowInconsistentMetadata
forall a. a -> a -> Bool -> a
bool AllowInconsistentMetadata
NoAllowInconsistentMetadata AllowInconsistentMetadata
AllowInconsistentMetadata

instance ToJSON AllowInconsistentMetadata where
  toJSON :: AllowInconsistentMetadata -> Value
toJSON = Bool -> Value
forall a. ToJSON a => a -> Value
Aeson.toJSON (Bool -> Value)
-> (AllowInconsistentMetadata -> Bool)
-> AllowInconsistentMetadata
-> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AllowInconsistentMetadata -> Bool
toBool
    where
      toBool :: AllowInconsistentMetadata -> Bool
toBool AllowInconsistentMetadata
AllowInconsistentMetadata = Bool
True
      toBool AllowInconsistentMetadata
NoAllowInconsistentMetadata = Bool
False

-- | Replace metadata either with or without metadata sources.
data ReplaceMetadataV1
  = RMWithSources Metadata
  | RMWithoutSources MetadataNoSources
  deriving (ReplaceMetadataV1 -> ReplaceMetadataV1 -> Bool
(ReplaceMetadataV1 -> ReplaceMetadataV1 -> Bool)
-> (ReplaceMetadataV1 -> ReplaceMetadataV1 -> Bool)
-> Eq ReplaceMetadataV1
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ReplaceMetadataV1 -> ReplaceMetadataV1 -> Bool
$c/= :: ReplaceMetadataV1 -> ReplaceMetadataV1 -> Bool
== :: ReplaceMetadataV1 -> ReplaceMetadataV1 -> Bool
$c== :: ReplaceMetadataV1 -> ReplaceMetadataV1 -> Bool
Eq)

instance FromJSON ReplaceMetadataV1 where
  parseJSON :: Value -> Parser ReplaceMetadataV1
parseJSON = String
-> (Object -> Parser ReplaceMetadataV1)
-> Value
-> Parser ReplaceMetadataV1
forall a. String -> (Object -> Parser a) -> Value -> Parser a
Aeson.withObject String
"ReplaceMetadataV1" ((Object -> Parser ReplaceMetadataV1)
 -> Value -> Parser ReplaceMetadataV1)
-> (Object -> Parser ReplaceMetadataV1)
-> Value
-> Parser ReplaceMetadataV1
forall a b. (a -> b) -> a -> b
$ \Object
o -> do
    MetadataVersion
version <- Object
o Object -> Key -> Parser (Maybe MetadataVersion)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"version" Parser (Maybe MetadataVersion)
-> MetadataVersion -> Parser MetadataVersion
forall a. Parser (Maybe a) -> a -> Parser a
.!= MetadataVersion
Metadata.MVVersion1
    case MetadataVersion
version of
      MetadataVersion
Metadata.MVVersion3 -> Metadata -> ReplaceMetadataV1
RMWithSources (Metadata -> ReplaceMetadataV1)
-> Parser Metadata -> Parser ReplaceMetadataV1
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser Metadata
forall a. FromJSON a => Value -> Parser a
Aeson.parseJSON (Object -> Value
Aeson.Object Object
o)
      MetadataVersion
_ -> MetadataNoSources -> ReplaceMetadataV1
RMWithoutSources (MetadataNoSources -> ReplaceMetadataV1)
-> Parser MetadataNoSources -> Parser ReplaceMetadataV1
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser MetadataNoSources
forall a. FromJSON a => Value -> Parser a
Aeson.parseJSON (Object -> Value
Aeson.Object Object
o)

instance ToJSON ReplaceMetadataV1 where
  toJSON :: ReplaceMetadataV1 -> Value
toJSON = \case
    RMWithSources Metadata
v -> Metadata -> Value
forall a. ToJSON a => a -> Value
Aeson.toJSON Metadata
v
    RMWithoutSources MetadataNoSources
v -> MetadataNoSources -> Value
forall a. ToJSON a => a -> Value
Aeson.toJSON MetadataNoSources
v

-- | Replace metadata while allowing for inconsitency in the metadata object.
--
-- https://hasura.io/docs/latest/api-reference/metadata-api/manage-metadata/#metadata-replace-metadata-syntax
data ReplaceMetadataV2 = ReplaceMetadataV2
  { ReplaceMetadataV2 -> AllowInconsistentMetadata
_rmv2AllowInconsistentMetadata :: AllowInconsistentMetadata,
    ReplaceMetadataV2 -> ReplaceMetadataV1
_rmv2Metadata :: ReplaceMetadataV1
  }
  deriving (ReplaceMetadataV2 -> ReplaceMetadataV2 -> Bool
(ReplaceMetadataV2 -> ReplaceMetadataV2 -> Bool)
-> (ReplaceMetadataV2 -> ReplaceMetadataV2 -> Bool)
-> Eq ReplaceMetadataV2
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ReplaceMetadataV2 -> ReplaceMetadataV2 -> Bool
$c/= :: ReplaceMetadataV2 -> ReplaceMetadataV2 -> Bool
== :: ReplaceMetadataV2 -> ReplaceMetadataV2 -> Bool
$c== :: ReplaceMetadataV2 -> ReplaceMetadataV2 -> Bool
Eq)

instance FromJSON ReplaceMetadataV2 where
  parseJSON :: Value -> Parser ReplaceMetadataV2
parseJSON = String
-> (Object -> Parser ReplaceMetadataV2)
-> Value
-> Parser ReplaceMetadataV2
forall a. String -> (Object -> Parser a) -> Value -> Parser a
Aeson.withObject String
"ReplaceMetadataV2" ((Object -> Parser ReplaceMetadataV2)
 -> Value -> Parser ReplaceMetadataV2)
-> (Object -> Parser ReplaceMetadataV2)
-> Value
-> Parser ReplaceMetadataV2
forall a b. (a -> b) -> a -> b
$ \Object
o ->
    AllowInconsistentMetadata -> ReplaceMetadataV1 -> ReplaceMetadataV2
ReplaceMetadataV2
      (AllowInconsistentMetadata
 -> ReplaceMetadataV1 -> ReplaceMetadataV2)
-> Parser AllowInconsistentMetadata
-> Parser (ReplaceMetadataV1 -> ReplaceMetadataV2)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> Key -> Parser (Maybe AllowInconsistentMetadata)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"allow_inconsistent_metadata" Parser (Maybe AllowInconsistentMetadata)
-> AllowInconsistentMetadata -> Parser AllowInconsistentMetadata
forall a. Parser (Maybe a) -> a -> Parser a
.!= AllowInconsistentMetadata
NoAllowInconsistentMetadata
      Parser (ReplaceMetadataV1 -> ReplaceMetadataV2)
-> Parser ReplaceMetadataV1 -> Parser ReplaceMetadataV2
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Key -> Parser ReplaceMetadataV1
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"metadata"

instance ToJSON ReplaceMetadataV2 where
  toJSON :: ReplaceMetadataV2 -> Value
toJSON ReplaceMetadataV2 {ReplaceMetadataV1
AllowInconsistentMetadata
_rmv2Metadata :: ReplaceMetadataV1
_rmv2AllowInconsistentMetadata :: AllowInconsistentMetadata
_rmv2Metadata :: ReplaceMetadataV2 -> ReplaceMetadataV1
_rmv2AllowInconsistentMetadata :: ReplaceMetadataV2 -> AllowInconsistentMetadata
..} =
    [Pair] -> Value
Aeson.object
      [ Key
"allow_inconsistent_metadata" Key -> AllowInconsistentMetadata -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= AllowInconsistentMetadata
_rmv2AllowInconsistentMetadata,
        Key
"metadata" Key -> ReplaceMetadataV1 -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= ReplaceMetadataV1
_rmv2Metadata
      ]

-- | 'ReplaceMetadata' is used to replace/import metadata into
-- Hasura. Existing metadata will be replaced with the new one.
--
-- https://hasura.io/docs/latest/api-reference/metadata-api/manage-metadata/#metadata-replace-metadata
-- TODO: If additional API versions are supported in future it would
-- be ideal to include a version field Rather than differentiating on
-- the "metadata" field.
data ReplaceMetadata
  = RMReplaceMetadataV1 ReplaceMetadataV1
  | RMReplaceMetadataV2 ReplaceMetadataV2
  deriving (ReplaceMetadata -> ReplaceMetadata -> Bool
(ReplaceMetadata -> ReplaceMetadata -> Bool)
-> (ReplaceMetadata -> ReplaceMetadata -> Bool)
-> Eq ReplaceMetadata
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ReplaceMetadata -> ReplaceMetadata -> Bool
$c/= :: ReplaceMetadata -> ReplaceMetadata -> Bool
== :: ReplaceMetadata -> ReplaceMetadata -> Bool
$c== :: ReplaceMetadata -> ReplaceMetadata -> Bool
Eq)

instance FromJSON ReplaceMetadata where
  parseJSON :: Value -> Parser ReplaceMetadata
parseJSON = String
-> (Object -> Parser ReplaceMetadata)
-> Value
-> Parser ReplaceMetadata
forall a. String -> (Object -> Parser a) -> Value -> Parser a
Aeson.withObject String
"ReplaceMetadata" ((Object -> Parser ReplaceMetadata)
 -> Value -> Parser ReplaceMetadata)
-> (Object -> Parser ReplaceMetadata)
-> Value
-> Parser ReplaceMetadata
forall a b. (a -> b) -> a -> b
$ \Object
o -> do
    if Key -> Object -> Bool
forall a. Key -> KeyMap a -> Bool
KeyMap.member Key
"metadata" Object
o
      then ReplaceMetadataV2 -> ReplaceMetadata
RMReplaceMetadataV2 (ReplaceMetadataV2 -> ReplaceMetadata)
-> Parser ReplaceMetadataV2 -> Parser ReplaceMetadata
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser ReplaceMetadataV2
forall a. FromJSON a => Value -> Parser a
Aeson.parseJSON (Object -> Value
Aeson.Object Object
o)
      else ReplaceMetadataV1 -> ReplaceMetadata
RMReplaceMetadataV1 (ReplaceMetadataV1 -> ReplaceMetadata)
-> Parser ReplaceMetadataV1 -> Parser ReplaceMetadata
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser ReplaceMetadataV1
forall a. FromJSON a => Value -> Parser a
Aeson.parseJSON (Object -> Value
Aeson.Object Object
o)

instance ToJSON ReplaceMetadata where
  toJSON :: ReplaceMetadata -> Value
toJSON = \case
    RMReplaceMetadataV1 ReplaceMetadataV1
v1 -> ReplaceMetadataV1 -> Value
forall a. ToJSON a => a -> Value
Aeson.toJSON ReplaceMetadataV1
v1
    RMReplaceMetadataV2 ReplaceMetadataV2
v2 -> ReplaceMetadataV2 -> Value
forall a. ToJSON a => a -> Value
Aeson.toJSON ReplaceMetadataV2
v2

data WebHookUrl = EnvVar String | URL Text
  deriving (WebHookUrl -> WebHookUrl -> Bool
(WebHookUrl -> WebHookUrl -> Bool)
-> (WebHookUrl -> WebHookUrl -> Bool) -> Eq WebHookUrl
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: WebHookUrl -> WebHookUrl -> Bool
$c/= :: WebHookUrl -> WebHookUrl -> Bool
== :: WebHookUrl -> WebHookUrl -> Bool
$c== :: WebHookUrl -> WebHookUrl -> Bool
Eq)

instance FromJSON WebHookUrl where
  parseJSON :: Value -> Parser WebHookUrl
parseJSON (Aeson.Object Object
o) = do
    String
var <- Object
o Object -> Key -> Parser String
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"from_env"
    WebHookUrl -> Parser WebHookUrl
forall (f :: * -> *) a. Applicative f => a -> f a
pure (WebHookUrl -> Parser WebHookUrl)
-> WebHookUrl -> Parser WebHookUrl
forall a b. (a -> b) -> a -> b
$ String -> WebHookUrl
EnvVar String
var
  parseJSON (Aeson.String Text
str) = WebHookUrl -> Parser WebHookUrl
forall (f :: * -> *) a. Applicative f => a -> f a
pure (WebHookUrl -> Parser WebHookUrl)
-> WebHookUrl -> Parser WebHookUrl
forall a b. (a -> b) -> a -> b
$ Text -> WebHookUrl
URL Text
str
  parseJSON Value
_ = Parser WebHookUrl
forall (f :: * -> *) a. Alternative f => f a
empty

instance ToJSON WebHookUrl where
  toJSON :: WebHookUrl -> Value
toJSON (EnvVar String
var) = [Pair] -> Value
Aeson.object [Key
"from_env" Key -> String -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= String
var]
  toJSON (URL Text
url) = Text -> Value
forall a. ToJSON a => a -> Value
Aeson.toJSON Text
url

-- | 'TestWebhookTransform' can be used to test out request
-- transformations using mock data.
--
-- https://hasura.io/docs/latest/api-reference/metadata-api/manage-metadata/#test-webhook-transform
data TestWebhookTransform = TestWebhookTransform
  { TestWebhookTransform -> Environment
_twtEnv :: Env.Environment,
    TestWebhookTransform -> [Header]
_twtHeaders :: [HTTP.Header],
    TestWebhookTransform -> WebHookUrl
_twtWebhookUrl :: WebHookUrl,
    TestWebhookTransform -> Value
_twtPayload :: Aeson.Value,
    TestWebhookTransform -> RequestTransform
_twtTransformer :: RequestTransform,
    TestWebhookTransform -> Maybe MetadataResponseTransform
_twtResponseTransformer :: Maybe MetadataResponseTransform,
    TestWebhookTransform -> Maybe SessionVariables
_twtSessionVariables :: Maybe SessionVariables
  }
  deriving (TestWebhookTransform -> TestWebhookTransform -> Bool
(TestWebhookTransform -> TestWebhookTransform -> Bool)
-> (TestWebhookTransform -> TestWebhookTransform -> Bool)
-> Eq TestWebhookTransform
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TestWebhookTransform -> TestWebhookTransform -> Bool
$c/= :: TestWebhookTransform -> TestWebhookTransform -> Bool
== :: TestWebhookTransform -> TestWebhookTransform -> Bool
$c== :: TestWebhookTransform -> TestWebhookTransform -> Bool
Eq)

twtTransformer :: Lens' TestWebhookTransform RequestTransform
twtTransformer :: (RequestTransform -> f RequestTransform)
-> TestWebhookTransform -> f TestWebhookTransform
twtTransformer = (TestWebhookTransform -> RequestTransform)
-> (TestWebhookTransform
    -> RequestTransform -> TestWebhookTransform)
-> Lens
     TestWebhookTransform
     TestWebhookTransform
     RequestTransform
     RequestTransform
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
Lens.lens TestWebhookTransform -> RequestTransform
_twtTransformer \TestWebhookTransform
twt RequestTransform
a -> TestWebhookTransform
twt {_twtTransformer :: RequestTransform
_twtTransformer = RequestTransform
a}

instance FromJSON TestWebhookTransform where
  parseJSON :: Value -> Parser TestWebhookTransform
parseJSON = String
-> (Object -> Parser TestWebhookTransform)
-> Value
-> Parser TestWebhookTransform
forall a. String -> (Object -> Parser a) -> Value -> Parser a
Aeson.withObject String
"TestWebhookTransform" ((Object -> Parser TestWebhookTransform)
 -> Value -> Parser TestWebhookTransform)
-> (Object -> Parser TestWebhookTransform)
-> Value
-> Parser TestWebhookTransform
forall a b. (a -> b) -> a -> b
$ \Object
o -> do
    Environment
env <- (Maybe Environment -> Environment)
-> Parser (Maybe Environment) -> Parser Environment
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Environment -> Maybe Environment -> Environment
forall a. a -> Maybe a -> a
fromMaybe Environment
forall a. Monoid a => a
mempty) (Parser (Maybe Environment) -> Parser Environment)
-> Parser (Maybe Environment) -> Parser Environment
forall a b. (a -> b) -> a -> b
$ Object
o Object -> Key -> Parser (Maybe Environment)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"env"
    [Header]
headers <- ([(ByteString, ByteString)] -> [Header])
-> Parser [(ByteString, ByteString)] -> Parser [Header]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (((ByteString, ByteString) -> Header)
-> [(ByteString, ByteString)] -> [Header]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((ByteString -> CI ByteString) -> (ByteString, ByteString) -> Header
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (b, d) (c, d)
first (ByteString -> CI ByteString
forall s. FoldCase s => s -> CI s
CI.mk))) (Parser [(ByteString, ByteString)] -> Parser [Header])
-> Parser [(ByteString, ByteString)] -> Parser [Header]
forall a b. (a -> b) -> a -> b
$ Object
o Object -> Key -> Parser (Maybe [(ByteString, ByteString)])
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"request_headers" Parser (Maybe [(ByteString, ByteString)])
-> [(ByteString, ByteString)] -> Parser [(ByteString, ByteString)]
forall a. Parser (Maybe a) -> a -> Parser a
.!= []
    WebHookUrl
url <- Object
o Object -> Key -> Parser WebHookUrl
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"webhook_url"
    Value
payload <- Object
o Object -> Key -> Parser Value
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"body"
    RequestTransform
reqTransform <- Object
o Object -> Key -> Parser RequestTransform
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"request_transform"
    Maybe MetadataResponseTransform
respTransform <- Object
o Object -> Key -> Parser (Maybe MetadataResponseTransform)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"response_transform"
    Maybe SessionVariables
sessionVars <- Object
o Object -> Key -> Parser (Maybe SessionVariables)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"session_variables"
    TestWebhookTransform -> Parser TestWebhookTransform
forall (f :: * -> *) a. Applicative f => a -> f a
pure (TestWebhookTransform -> Parser TestWebhookTransform)
-> TestWebhookTransform -> Parser TestWebhookTransform
forall a b. (a -> b) -> a -> b
$ Environment
-> [Header]
-> WebHookUrl
-> Value
-> RequestTransform
-> Maybe MetadataResponseTransform
-> Maybe SessionVariables
-> TestWebhookTransform
TestWebhookTransform Environment
env [Header]
headers WebHookUrl
url Value
payload RequestTransform
reqTransform Maybe MetadataResponseTransform
respTransform Maybe SessionVariables
sessionVars

instance ToJSON TestWebhookTransform where
  toJSON :: TestWebhookTransform -> Value
toJSON (TestWebhookTransform Environment
env [Header]
headers WebHookUrl
url Value
payload RequestTransform
mt Maybe MetadataResponseTransform
mrt Maybe SessionVariables
sv) =
    [Pair] -> Value
Aeson.object
      [ Key
"env" Key -> Environment -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Environment
env,
        Key
"request_headers" Key -> [(ByteString, ByteString)] -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= (Header -> (ByteString, ByteString))
-> [Header] -> [(ByteString, ByteString)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((CI ByteString -> ByteString) -> Header -> (ByteString, ByteString)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (b, d) (c, d)
first CI ByteString -> ByteString
forall s. CI s -> s
CI.original) [Header]
headers,
        Key
"webhook_url" Key -> WebHookUrl -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= WebHookUrl
url,
        Key
"body" Key -> Value -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Value
payload,
        Key
"request_transform" Key -> RequestTransform -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= RequestTransform
mt,
        Key
"response_transform" Key -> Maybe MetadataResponseTransform -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Maybe MetadataResponseTransform
mrt,
        Key
"session_variables" Key -> Maybe SessionVariables -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Maybe SessionVariables
sv
      ]