module IHP.GraphQL.JSON where

import IHP.Prelude
import qualified IHP.GraphQL.Types as GraphQL
import qualified IHP.GraphQL.Parser as GraphQL
import qualified Data.Aeson as Aeson
import Data.Aeson ((.:))
import qualified Data.HashMap.Strict as HashMap
import qualified Data.Attoparsec.Text as Attoparsec

instance Aeson.FromJSON GraphQL.GraphQLRequest where
    parseJSON :: Value -> Parser GraphQLRequest
parseJSON = String
-> (Object -> Parser GraphQLRequest)
-> Value
-> Parser GraphQLRequest
forall a. String -> (Object -> Parser a) -> Value -> Parser a
Aeson.withObject String
"GraphQLRequest" \Object
v -> do
        Document
query <- Object
v Object -> Text -> Parser Document
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"query"
        Variables
variables <- (Object
v Object -> Text -> Parser Variables
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"variables") Parser Variables -> Parser Variables -> Parser Variables
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Variables -> Parser Variables
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([Argument] -> Variables
GraphQL.Variables []))
        GraphQLRequest -> Parser GraphQLRequest
forall (f :: * -> *) a. Applicative f => a -> f a
pure GraphQLRequest :: Document -> Variables -> GraphQLRequest
GraphQL.GraphQLRequest { Document
$sel:query:GraphQLRequest :: Document
query :: Document
query, Variables
$sel:variables:GraphQLRequest :: Variables
variables :: Variables
variables }

instance Aeson.FromJSON GraphQL.Document where
    parseJSON :: Value -> Parser Document
parseJSON = String -> (Text -> Parser Document) -> Value -> Parser Document
forall a. String -> (Text -> Parser a) -> Value -> Parser a
Aeson.withText String
"Document" \Text
gql -> do
        case Parser Document -> Text -> Either String Document
forall a. Parser a -> Text -> Either String a
Attoparsec.parseOnly Parser Document
GraphQL.parseDocument Text
gql of
            Left String
parserError -> String -> Parser Document
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (Text -> String
forall a b. ConvertibleStrings a b => a -> b
cs (Text -> String) -> Text -> String
forall a b. (a -> b) -> a -> b
$ (String -> Text
forall a. Show a => a -> Text
tshow String
parserError) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" while parsing: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
gql)
            Right Document
statements -> Document -> Parser Document
forall (f :: * -> *) a. Applicative f => a -> f a
pure Document
statements

instance Aeson.FromJSON GraphQL.Variables where
    parseJSON :: Value -> Parser Variables
parseJSON = String -> (Object -> Parser Variables) -> Value -> Parser Variables
forall a. String -> (Object -> Parser a) -> Value -> Parser a
Aeson.withObject String
"Variables" \Object
hashMap -> do
        [Argument] -> Variables
GraphQL.Variables ([Argument] -> Variables) -> Parser [Argument] -> Parser Variables
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
            Object
hashMap
                Object -> (Object -> [(Text, Value)]) -> [(Text, Value)]
forall t1 t2. t1 -> (t1 -> t2) -> t2
|> Object -> [(Text, Value)]
forall k v. HashMap k v -> [(k, v)]
HashMap.toList
                [(Text, Value)] -> ([(Text, Value)] -> [Argument]) -> [Argument]
forall t1 t2. t1 -> (t1 -> t2) -> t2
|> ((Text, Value) -> Argument) -> [(Text, Value)] -> [Argument]
forall a b. (a -> b) -> [a] -> [b]
map (\(Text
argumentName, Value
argumentValue) -> Argument :: Text -> Value -> Argument
GraphQL.Argument { Text
$sel:argumentName:Argument :: Text
argumentName :: Text
argumentName, $sel:argumentValue:Argument :: Value
argumentValue = Value -> Value
aesonValueToGraphQLValue Value
argumentValue })
                [Argument]
-> ([Argument] -> Parser [Argument]) -> Parser [Argument]
forall t1 t2. t1 -> (t1 -> t2) -> t2
|> [Argument] -> Parser [Argument]
forall (f :: * -> *) a. Applicative f => a -> f a
pure

aesonValueToGraphQLValue :: Aeson.Value -> GraphQL.Value
aesonValueToGraphQLValue :: Value -> Value
aesonValueToGraphQLValue (Aeson.String Text
text) = Text -> Value
GraphQL.StringValue Text
text
aesonValueToGraphQLValue (Aeson.Bool Bool
bool) = Bool -> Value
GraphQL.BooleanValue Bool
bool
aesonValueToGraphQLValue (Aeson.Object Object
hashMap) = HashMap Text Value -> Value
GraphQL.ObjectValue ((Value -> Value) -> Object -> HashMap Text Value
forall v1 v2 k. (v1 -> v2) -> HashMap k v1 -> HashMap k v2
HashMap.map Value -> Value
aesonValueToGraphQLValue Object
hashMap)
aesonValueToGraphQLValue Value
Aeson.Null = Value
GraphQL.NullValue