morpheus-graphql-0.11.0: src/Data/Morpheus/Parsing/JSONSchema/Parse.hs
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Data.Morpheus.Parsing.JSONSchema.Parse
( decodeIntrospection
)
where
import Data.Aeson
import Data.ByteString.Lazy ( ByteString )
import Data.Morpheus.Error.Internal ( internalError )
import Data.Morpheus.Parsing.JSONSchema.Types
( EnumValue(..)
, Field(..)
, InputValue(..)
, Introspection(..)
, Schema(..)
, Type(..)
)
import Data.Morpheus.Schema.TypeKind ( TypeKind(..) )
import qualified Data.Morpheus.Types.Internal.AST as AST
( Schema)
import Data.Morpheus.Types.Internal.AST
( FieldDefinition
, TypeDefinition(..)
, TypeContent(..)
, DataTypeWrapper(..)
, TypeWrapper
, createArgument
, createDataTypeLib
, createEnumType
, createField
, createScalarType
, createType
, createUnionType
, toHSWrappers
, ArgumentsDefinition(..)
)
import Data.Morpheus.Types.Internal.Operation
( Listable(..))
import Data.Morpheus.Types.Internal.Resolving
( Eventless )
import Data.Morpheus.Types.IO ( JSONResponse(..) )
import Data.Semigroup ( (<>) )
import Data.Text ( Text
, pack
)
decodeIntrospection :: ByteString -> Eventless AST.Schema
decodeIntrospection jsonDoc = case jsonSchema of
Left errors -> internalError $ pack errors
Right JSONResponse { responseData = Just Introspection { __schema = Schema { types } } }
-> traverse parse types >>= createDataTypeLib . concat
Right res -> internalError (pack $ show res)
where
jsonSchema :: Either String (JSONResponse Introspection)
jsonSchema = eitherDecode jsonDoc
class ParseJSONSchema a b where
parse :: a -> Eventless b
instance ParseJSONSchema Type [TypeDefinition] where
parse Type { name = Just typeName, kind = SCALAR } =
pure [createScalarType typeName]
parse Type { name = Just typeName, kind = ENUM, enumValues = Just enums } =
pure [createEnumType typeName (map enumName enums)]
parse Type { name = Just typeName, kind = UNION, possibleTypes = Just unions }
= case traverse name unions of
Nothing -> internalError "ERROR: GQL ERROR"
Just uni -> pure [createUnionType typeName uni]
parse Type { name = Just typeName, kind = INPUT_OBJECT, inputFields = Just iFields }
= do
(fields :: [FieldDefinition]) <- traverse parse iFields
fs <- fromList fields
pure [createType typeName $ DataInputObject fs]
parse Type { name = Just typeName, kind = OBJECT, fields = Just oFields } =
do
(fields :: [FieldDefinition]) <- traverse parse oFields
fs <- fromList fields
pure [createType typeName $ DataObject [] fs]
parse _ = pure []
instance ParseJSONSchema Field FieldDefinition where
parse Field { fieldName, fieldArgs, fieldType } = do
fType <- fieldTypeFromJSON fieldType
args <- traverse genArg fieldArgs >>= fromList
pure $ createField (ArgumentsDefinition Nothing args) fieldName fType
where
genArg InputValue { inputName = argName, inputType = argType } =
createArgument argName <$> fieldTypeFromJSON argType
instance ParseJSONSchema InputValue FieldDefinition where
parse InputValue { inputName, inputType } = createField NoArguments inputName <$> fieldTypeFromJSON inputType
fieldTypeFromJSON :: Type -> Eventless ([TypeWrapper], Text)
fieldTypeFromJSON = fmap toHs . fieldTypeRec []
where
toHs (w, t) = (toHSWrappers w, t)
fieldTypeRec
:: [DataTypeWrapper] -> Type -> Eventless ([DataTypeWrapper], Text)
fieldTypeRec acc Type { kind = LIST, ofType = Just ofType } =
fieldTypeRec (ListType : acc) ofType
fieldTypeRec acc Type { kind = NON_NULL, ofType = Just ofType } =
fieldTypeRec (NonNullType : acc) ofType
fieldTypeRec acc Type { name = Just name } = pure (acc, name)
fieldTypeRec _ x = internalError $ "Unsuported Field" <> pack (show x)