morpheus-graphql-client-0.27.0: src/Data/Morpheus/Client/CodeGen/Interpreting/Global.hs
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE NoImplicitPrelude #-}
module Data.Morpheus.Client.CodeGen.Interpreting.Global
( toGlobalDefinitions,
)
where
import Data.Morpheus.Client.CodeGen.AST
( ClientDeclaration,
ClientPreDeclaration (..),
ClientTypeDefinition (..),
DERIVING_MODE (..),
)
import Data.Morpheus.Client.CodeGen.Interpreting.Core (printClientType)
import Data.Morpheus.Client.CodeGen.Interpreting.PreDeclarations
( mapPreDeclarations,
)
import Data.Morpheus.CodeGen.Internal.AST
( CodeGenConstructor (..),
CodeGenField (..),
CodeGenTypeName (..),
FIELD_TYPE_WRAPPER (..),
fromTypeName,
)
import Data.Morpheus.CodeGen.Utils (Flag (FlagLanguageExtension), Flags)
import Data.Morpheus.Internal.Ext (GQLResult)
import Data.Morpheus.Types.Internal.AST
( ANY,
DataEnumValue (DataEnumValue, enumName),
FieldDefinition (..),
Schema (Schema, types),
TRUE,
TypeContent (..),
TypeDefinition (..),
TypeKind (..),
TypeName,
TypeRef (..),
VALID,
isNotSystemTypeName,
isNullable,
isResolverType,
)
import Relude hiding (empty)
toClientDeclarations :: ClientTypeDefinition -> [ClientPreDeclaration]
toClientDeclarations def@ClientTypeDefinition {clientKind}
| KIND_SCALAR == clientKind = [FromJSONClass SCALAR_MODE cgType, ToJSONClass SCALAR_MODE cgType]
| KIND_ENUM == clientKind = [ClientType cgType, FromJSONClass ENUM_MODE cgType, ToJSONClass ENUM_MODE cgType]
| otherwise = [ClientType cgType, ToJSONClass TYPE_MODE cgType]
where
cgType = printClientType def
toGlobalDefinitions :: (TypeName -> Bool) -> Schema VALID -> GQLResult ([ClientDeclaration], Flags)
toGlobalDefinitions f Schema {types} = do
let tyDefs = mapMaybe generateGlobalType $ filter shouldInclude (sortWith typeName $ toList types)
decs <- traverse mapPreDeclarations $ concatMap toClientDeclarations tyDefs
let hasEnums = not $ null [x | x@ClientTypeDefinition {clientKind = KIND_ENUM} <- tyDefs]
pure (decs, [FlagLanguageExtension "LambdaCase" | hasEnums])
where
shouldInclude t =
not (isResolverType t)
&& isNotSystemTypeName (typeName t)
&& f (typeName t)
generateGlobalType :: TypeDefinition ANY VALID -> Maybe ClientTypeDefinition
generateGlobalType TypeDefinition {typeName, typeContent} = do
(clientKind, clientCons) <- genContent typeContent
pure
ClientTypeDefinition
{ clientTypeName = fromTypeName typeName,
clientKind,
clientCons
}
where
genContent :: TypeContent TRUE ANY VALID -> Maybe (TypeKind, [CodeGenConstructor])
genContent (DataInputObject inputFields) =
pure
( KIND_INPUT_OBJECT,
[ CodeGenConstructor
{ constructorName = fromTypeName typeName,
constructorFields = toCodeGenField <$> toList inputFields
}
]
)
genContent (DataEnum enumTags) = pure (KIND_ENUM, mkConsEnum typeName <$> enumTags)
genContent DataScalar {} = pure (KIND_SCALAR, [])
genContent _ = Nothing
toCodeGenField :: FieldDefinition a b -> CodeGenField
toCodeGenField FieldDefinition {fieldType = field@TypeRef {..}, ..} =
CodeGenField
{ fieldName,
fieldType = typeConName,
wrappers = [GQL_WRAPPER typeWrappers],
fieldIsNullable = isNullable field
}
mkConsEnum :: TypeName -> DataEnumValue s -> CodeGenConstructor
mkConsEnum typename DataEnumValue {enumName} =
CodeGenConstructor (CodeGenTypeName [coerce typename] [] enumName) []