packages feed

morpheus-graphql 0.7.1 → 0.8.0

raw patch · 120 files changed

+4408/−1538 lines, 120 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Data.Morpheus.Kind: type INPUT_UNION = 'INPUT_UNION
- Data.Morpheus.Types.Internal.AST: DataTyCon :: Key -> DataFingerprint -> Maybe Meta -> a -> DataTyCon a
- Data.Morpheus.Types.Internal.AST: Enum :: Text -> Value
- Data.Morpheus.Types.Internal.AST: INLINE :: ValueOrigin
- Data.Morpheus.Types.Internal.AST: InlineFragment :: Fragment -> RawSelection
- Data.Morpheus.Types.Internal.AST: List :: [Value] -> Value
- Data.Morpheus.Types.Internal.AST: Null :: Value
- Data.Morpheus.Types.Internal.AST: Object :: Object -> Value
- Data.Morpheus.Types.Internal.AST: RawArgument :: Argument -> RawArgument
- Data.Morpheus.Types.Internal.AST: RawSelectionField :: RawSelection' () -> RawSelection
- Data.Morpheus.Types.Internal.AST: RawSelectionSet :: RawSelection' RawSelectionSet -> RawSelection
- Data.Morpheus.Types.Internal.AST: Scalar :: ScalarValue -> Value
- Data.Morpheus.Types.Internal.AST: Selection :: args -> Position -> Maybe Key -> rec -> Selection args rec
- Data.Morpheus.Types.Internal.AST: SelectionField :: SelectionRec
- Data.Morpheus.Types.Internal.AST: SelectionSet :: SelectionSet -> SelectionRec
- Data.Morpheus.Types.Internal.AST: Spread :: Ref -> RawSelection
- Data.Morpheus.Types.Internal.AST: SystemFingerprint :: Key -> DataFingerprint
- Data.Morpheus.Types.Internal.AST: TypeAlias :: Key -> Maybe Key -> [TypeWrapper] -> TypeAlias
- Data.Morpheus.Types.Internal.AST: TypeableFingerprint :: [String] -> DataFingerprint
- Data.Morpheus.Types.Internal.AST: UnionSelection :: UnionSelection -> SelectionRec
- Data.Morpheus.Types.Internal.AST: VARIABLE :: ValueOrigin
- Data.Morpheus.Types.Internal.AST: VariableRef :: Ref -> RawArgument
- Data.Morpheus.Types.Internal.AST: [aliasArgs] :: TypeAlias -> Maybe Key
- Data.Morpheus.Types.Internal.AST: [aliasTyCon] :: TypeAlias -> Key
- Data.Morpheus.Types.Internal.AST: [aliasWrappers] :: TypeAlias -> [TypeWrapper]
- Data.Morpheus.Types.Internal.AST: [argumentOrigin] :: Argument -> ValueOrigin
- Data.Morpheus.Types.Internal.AST: [isVariableRequired] :: Variable a -> Bool
- Data.Morpheus.Types.Internal.AST: [operationArgs] :: Operation args sel -> args
- Data.Morpheus.Types.Internal.AST: [selectionAlias] :: Selection args rec -> Maybe Key
- Data.Morpheus.Types.Internal.AST: [selectionArguments] :: Selection args rec -> args
- Data.Morpheus.Types.Internal.AST: [selectionPosition] :: Selection args rec -> Position
- Data.Morpheus.Types.Internal.AST: [selectionRec] :: Selection args rec -> rec
- Data.Morpheus.Types.Internal.AST: [typeData] :: DataTyCon a -> a
- Data.Morpheus.Types.Internal.AST: [unImplements] :: RawDataType -> DataObject
- Data.Morpheus.Types.Internal.AST: [variableTypeWrappers] :: Variable a -> [TypeWrapper]
- Data.Morpheus.Types.Internal.AST: data DataTyCon a
- Data.Morpheus.Types.Internal.AST: data RawArgument
- Data.Morpheus.Types.Internal.AST: data RawSelection
- Data.Morpheus.Types.Internal.AST: data SelectionRec
- Data.Morpheus.Types.Internal.AST: data TypeAlias
- Data.Morpheus.Types.Internal.AST: data ValueOrigin
- Data.Morpheus.Types.Internal.AST: fromDataType :: (DataTyCon () -> v) -> DataType -> v
- Data.Morpheus.Types.Internal.AST: type RawSelection' a = Selection RawArguments a
+ Data.Morpheus.Kind: type INPUT = 'INPUT
+ Data.Morpheus.Kind: type OUTPUT = 'OUTPUT
+ Data.Morpheus.Server: gqlSocketMonadIOApp :: (RootResCon m e que mut sub, MonadIO m) => GQLRootResolver m e que mut sub -> GQLState m e -> (m () -> IO ()) -> ServerApp
+ Data.Morpheus.Types: failRes :: (LiftEither o Resolver, Monad m) => String -> Resolver o e m a
+ Data.Morpheus.Types.Internal.AST: DataFingerprint :: Name -> [String] -> DataFingerprint
+ Data.Morpheus.Types.Internal.AST: DataType :: Key -> DataFingerprint -> Maybe Meta -> DataTypeContent -> DataType
+ Data.Morpheus.Types.Internal.AST: TypeRef :: Name -> Maybe Name -> [TypeWrapper] -> TypeRef
+ Data.Morpheus.Types.Internal.AST: [DefaultValue] :: Maybe ResolvedValue -> VariableContent RESOLVED
+ Data.Morpheus.Types.Internal.AST: [Enum] :: Name -> Value a
+ Data.Morpheus.Types.Internal.AST: [InlineFragment] :: Fragment -> Selection RAW
+ Data.Morpheus.Types.Internal.AST: [List] :: [Value a] -> Value a
+ Data.Morpheus.Types.Internal.AST: [Null] :: Value a
+ Data.Morpheus.Types.Internal.AST: [Object] :: Object a -> Value a
+ Data.Morpheus.Types.Internal.AST: [ResolvedVariable] :: Ref -> Variable VALID -> Value RESOLVED
+ Data.Morpheus.Types.Internal.AST: [Scalar] :: ScalarValue -> Value a
+ Data.Morpheus.Types.Internal.AST: [SelectionField] :: SelectionContent valid
+ Data.Morpheus.Types.Internal.AST: [SelectionSet] :: SelectionSet valid -> SelectionContent valid
+ Data.Morpheus.Types.Internal.AST: [Selection] :: {selectionArguments :: Arguments valid, selectionPosition :: Position, selectionAlias :: Maybe Key, selectionContent :: SelectionContent valid} -> Selection valid
+ Data.Morpheus.Types.Internal.AST: [Spread] :: Ref -> Selection RAW
+ Data.Morpheus.Types.Internal.AST: [UnionSelection] :: UnionSelection -> SelectionContent VALID
+ Data.Morpheus.Types.Internal.AST: [ValidVariableValue] :: {validVarContent :: ValidValue} -> VariableContent VALID
+ Data.Morpheus.Types.Internal.AST: [VariableValue] :: Ref -> Value RAW
+ Data.Morpheus.Types.Internal.AST: [implementsContent] :: RawDataType -> DataObject
+ Data.Morpheus.Types.Internal.AST: [implementsMeta] :: RawDataType -> Maybe Meta
+ Data.Morpheus.Types.Internal.AST: [implementsName] :: RawDataType -> Key
+ Data.Morpheus.Types.Internal.AST: [interfaceContent] :: RawDataType -> DataObject
+ Data.Morpheus.Types.Internal.AST: [interfaceMeta] :: RawDataType -> Maybe Meta
+ Data.Morpheus.Types.Internal.AST: [interfaceName] :: RawDataType -> Key
+ Data.Morpheus.Types.Internal.AST: [operationArguments] :: Operation -> Collection (Variable stage)
+ Data.Morpheus.Types.Internal.AST: [typeArgs] :: TypeRef -> Maybe Name
+ Data.Morpheus.Types.Internal.AST: [typeConName] :: TypeRef -> Name
+ Data.Morpheus.Types.Internal.AST: [typeContent] :: DataType -> DataTypeContent
+ Data.Morpheus.Types.Internal.AST: [typeWrappers] :: TypeRef -> [TypeWrapper]
+ Data.Morpheus.Types.Internal.AST: data DataTypeContent
+ Data.Morpheus.Types.Internal.AST: data SelectionContent (valid :: Stage)
+ Data.Morpheus.Types.Internal.AST: data Stage
+ Data.Morpheus.Types.Internal.AST: data TypeRef
+ Data.Morpheus.Types.Internal.AST: data VariableContent (stage :: Stage)
+ Data.Morpheus.Types.Internal.AST: getOperationObject :: Operation a -> DataTypeLib -> Validation (Name, DataObject)
+ Data.Morpheus.Types.Internal.AST: isNullableWrapper :: [TypeWrapper] -> Bool
+ Data.Morpheus.Types.Internal.AST: type DataInputUnion = [(Key, Bool)]
+ Data.Morpheus.Types.Internal.AST: type RAW = 'VALID
+ Data.Morpheus.Types.Internal.AST: type RESOLVED = 'RESOLVED
+ Data.Morpheus.Types.Internal.AST: type RawArgument = Argument RAW
+ Data.Morpheus.Types.Internal.AST: type RawObject = Object RAW
+ Data.Morpheus.Types.Internal.AST: type RawSelection = Selection RAW
+ Data.Morpheus.Types.Internal.AST: type RawSelectionRec = SelectionContent RAW
+ Data.Morpheus.Types.Internal.AST: type RawValue = Value RAW
+ Data.Morpheus.Types.Internal.AST: type ResolvedObject = Object RESOLVED
+ Data.Morpheus.Types.Internal.AST: type ResolvedValue = Value RESOLVED
+ Data.Morpheus.Types.Internal.AST: type VALID = 'RAW
+ Data.Morpheus.Types.Internal.AST: type ValidArgument = Argument VALID
+ Data.Morpheus.Types.Internal.AST: type ValidArguments = Collection ValidArgument
+ Data.Morpheus.Types.Internal.AST: type ValidObject = Object VALID
+ Data.Morpheus.Types.Internal.AST: type ValidSelectionRec = SelectionContent VALID
+ Data.Morpheus.Types.Internal.AST: type ValidSelectionSet = Collection ValidSelection
+ Data.Morpheus.Types.Internal.AST: type ValidValue = Value VALID
+ Data.Morpheus.Types.Internal.AST: unpackInputUnion :: [(Name, Bool)] -> Object stage -> Either Message (Name, Maybe (Value stage))
- Data.Morpheus.Kind: type INPUT_OBJECT = 'INPUT_OBJECT
+ Data.Morpheus.Kind: type INPUT_OBJECT = 'INPUT
- Data.Morpheus.Kind: type OBJECT = 'OBJECT
+ Data.Morpheus.Kind: type OBJECT = 'OUTPUT
- Data.Morpheus.Kind: type UNION = 'UNION
+ Data.Morpheus.Kind: type UNION = 'OUTPUT
- Data.Morpheus.Types: Data :: Value -> GQLResponse
+ Data.Morpheus.Types: Data :: ValidValue -> GQLResponse
- Data.Morpheus.Types: class GQLType a where {
+ Data.Morpheus.Types: class IsObject (KIND a) => GQLType a where {
- Data.Morpheus.Types: type KIND a = OBJECT;
+ Data.Morpheus.Types: type KIND a = OUTPUT;
- Data.Morpheus.Types.Internal.AST: Argument :: Value -> ValueOrigin -> Position -> Argument
+ Data.Morpheus.Types.Internal.AST: Argument :: Value valid -> Position -> Argument
- Data.Morpheus.Types.Internal.AST: DataEnum :: DataEnum -> DataType
+ Data.Morpheus.Types.Internal.AST: DataEnum :: DataEnum -> DataTypeContent
- Data.Morpheus.Types.Internal.AST: DataField :: Key -> [(Key, DataArgument)] -> Maybe ArgsType -> TypeAlias -> Maybe Meta -> DataField
+ Data.Morpheus.Types.Internal.AST: DataField :: Key -> [(Key, DataArgument)] -> Maybe ArgsType -> TypeRef -> Maybe Meta -> DataField
- Data.Morpheus.Types.Internal.AST: DataInputObject :: DataObject -> DataType
+ Data.Morpheus.Types.Internal.AST: DataInputObject :: DataObject -> DataTypeContent
- Data.Morpheus.Types.Internal.AST: DataInputUnion :: DataUnion -> DataType
+ Data.Morpheus.Types.Internal.AST: DataInputUnion :: [(Key, Bool)] -> DataTypeContent
- Data.Morpheus.Types.Internal.AST: DataObject :: DataObject -> DataType
+ Data.Morpheus.Types.Internal.AST: DataObject :: DataObject -> DataTypeContent
- Data.Morpheus.Types.Internal.AST: DataScalar :: DataScalar -> DataType
+ Data.Morpheus.Types.Internal.AST: DataScalar :: DataScalar -> DataTypeContent
- Data.Morpheus.Types.Internal.AST: DataTypeLib :: HashMap Key DataType -> (Key, DataObject) -> Maybe (Key, DataObject) -> Maybe (Key, DataObject) -> DataTypeLib
+ Data.Morpheus.Types.Internal.AST: DataTypeLib :: HashMap Key DataType -> (Name, DataType) -> Maybe (Name, DataType) -> Maybe (Name, DataType) -> DataTypeLib
- Data.Morpheus.Types.Internal.AST: DataUnion :: DataUnion -> DataType
+ Data.Morpheus.Types.Internal.AST: DataUnion :: DataUnion -> DataTypeContent
- Data.Morpheus.Types.Internal.AST: DataValidator :: (Value -> Either Key Value) -> DataValidator
+ Data.Morpheus.Types.Internal.AST: DataValidator :: (ValidValue -> Either Key ValidValue) -> DataValidator
- Data.Morpheus.Types.Internal.AST: Directive :: Name -> [(Name, Value)] -> Directive
+ Data.Morpheus.Types.Internal.AST: Directive :: Name -> [(Name, ValidValue)] -> Directive
- Data.Morpheus.Types.Internal.AST: GQLQuery :: FragmentLib -> RawOperation -> [(Key, Value)] -> GQLQuery
+ Data.Morpheus.Types.Internal.AST: GQLQuery :: FragmentLib -> RawOperation -> [(Key, ResolvedValue)] -> GQLQuery
- Data.Morpheus.Types.Internal.AST: Implements :: [Key] -> DataObject -> RawDataType
+ Data.Morpheus.Types.Internal.AST: Implements :: Key -> [Key] -> Maybe Meta -> DataObject -> RawDataType
- Data.Morpheus.Types.Internal.AST: Interface :: DataObject -> RawDataType
+ Data.Morpheus.Types.Internal.AST: Interface :: Key -> Maybe Meta -> DataObject -> RawDataType
- Data.Morpheus.Types.Internal.AST: Operation :: Maybe Key -> OperationType -> args -> sel -> Position -> Operation args sel
+ Data.Morpheus.Types.Internal.AST: Operation :: Maybe Key -> OperationType -> Collection (Variable stage) -> SelectionSet stage -> Position -> Operation
- Data.Morpheus.Types.Internal.AST: Variable :: Key -> Bool -> [TypeWrapper] -> Position -> a -> Variable a
+ Data.Morpheus.Types.Internal.AST: Variable :: TypeRef -> Position -> VariableContent (VAR stage) -> Variable
- Data.Morpheus.Types.Internal.AST: [argumentValue] :: Argument -> Value
+ Data.Morpheus.Types.Internal.AST: [argumentValue] :: Argument -> Value valid
- Data.Morpheus.Types.Internal.AST: [directiveArgs] :: Directive -> [(Name, Value)]
+ Data.Morpheus.Types.Internal.AST: [directiveArgs] :: Directive -> [(Name, ValidValue)]
- Data.Morpheus.Types.Internal.AST: [fieldType] :: DataField -> TypeAlias
+ Data.Morpheus.Types.Internal.AST: [fieldType] :: DataField -> TypeRef
- Data.Morpheus.Types.Internal.AST: [inputVariables] :: GQLQuery -> [(Key, Value)]
+ Data.Morpheus.Types.Internal.AST: [inputVariables] :: GQLQuery -> [(Key, ResolvedValue)]
- Data.Morpheus.Types.Internal.AST: [mutation] :: DataTypeLib -> Maybe (Key, DataObject)
+ Data.Morpheus.Types.Internal.AST: [mutation] :: DataTypeLib -> Maybe (Name, DataType)
- Data.Morpheus.Types.Internal.AST: [operationName] :: Operation args sel -> Maybe Key
+ Data.Morpheus.Types.Internal.AST: [operationName] :: Operation -> Maybe Key
- Data.Morpheus.Types.Internal.AST: [operationPosition] :: Operation args sel -> Position
+ Data.Morpheus.Types.Internal.AST: [operationPosition] :: Operation -> Position
- Data.Morpheus.Types.Internal.AST: [operationSelection] :: Operation args sel -> sel
+ Data.Morpheus.Types.Internal.AST: [operationSelection] :: Operation -> SelectionSet stage
- Data.Morpheus.Types.Internal.AST: [operationType] :: Operation args sel -> OperationType
+ Data.Morpheus.Types.Internal.AST: [operationType] :: Operation -> OperationType
- Data.Morpheus.Types.Internal.AST: [query] :: DataTypeLib -> (Key, DataObject)
+ Data.Morpheus.Types.Internal.AST: [query] :: DataTypeLib -> (Name, DataType)
- Data.Morpheus.Types.Internal.AST: [subscription] :: DataTypeLib -> Maybe (Key, DataObject)
+ Data.Morpheus.Types.Internal.AST: [subscription] :: DataTypeLib -> Maybe (Name, DataType)
- Data.Morpheus.Types.Internal.AST: [typeFingerprint] :: DataTyCon a -> DataFingerprint
+ Data.Morpheus.Types.Internal.AST: [typeFingerprint] :: DataType -> DataFingerprint
- Data.Morpheus.Types.Internal.AST: [typeMeta] :: DataTyCon a -> Maybe Meta
+ Data.Morpheus.Types.Internal.AST: [typeMeta] :: DataType -> Maybe Meta
- Data.Morpheus.Types.Internal.AST: [typeName] :: DataTyCon a -> Key
+ Data.Morpheus.Types.Internal.AST: [typeName] :: DataType -> Key
- Data.Morpheus.Types.Internal.AST: [validateValue] :: DataValidator -> Value -> Either Key Value
+ Data.Morpheus.Types.Internal.AST: [validateValue] :: DataValidator -> ValidValue -> Either Key ValidValue
- Data.Morpheus.Types.Internal.AST: [variablePosition] :: Variable a -> Position
+ Data.Morpheus.Types.Internal.AST: [variablePosition] :: Variable -> Position
- Data.Morpheus.Types.Internal.AST: [variableType] :: Variable a -> Key
+ Data.Morpheus.Types.Internal.AST: [variableType] :: Variable -> TypeRef
- Data.Morpheus.Types.Internal.AST: [variableValue] :: Variable a -> a
+ Data.Morpheus.Types.Internal.AST: [variableValue] :: Variable -> VariableContent (VAR stage)
- Data.Morpheus.Types.Internal.AST: coerceDataObject :: Failure error m => error -> DataType -> m DataObject
+ Data.Morpheus.Types.Internal.AST: coerceDataObject :: Failure error m => error -> DataType -> m (Name, DataObject)
- Data.Morpheus.Types.Internal.AST: createAlias :: Key -> TypeAlias
+ Data.Morpheus.Types.Internal.AST: createAlias :: Key -> TypeRef
- Data.Morpheus.Types.Internal.AST: createType :: Key -> a -> DataTyCon a
+ Data.Morpheus.Types.Internal.AST: createType :: Key -> DataTypeContent -> DataType
- Data.Morpheus.Types.Internal.AST: data Argument
+ Data.Morpheus.Types.Internal.AST: data Argument (valid :: Stage)
- Data.Morpheus.Types.Internal.AST: data Operation args sel
+ Data.Morpheus.Types.Internal.AST: data Operation (stage :: Stage)
- Data.Morpheus.Types.Internal.AST: data Selection args rec
+ Data.Morpheus.Types.Internal.AST: data Selection (valid :: Stage)
- Data.Morpheus.Types.Internal.AST: data Value
+ Data.Morpheus.Types.Internal.AST: data Value (valid :: Stage)
- Data.Morpheus.Types.Internal.AST: data Variable a
+ Data.Morpheus.Types.Internal.AST: data Variable (stage :: Stage)
- Data.Morpheus.Types.Internal.AST: getOperationDataType :: Operation a b -> DataTypeLib -> Validation DataObject
+ Data.Morpheus.Types.Internal.AST: getOperationDataType :: Operation a -> DataTypeLib -> Validation DataType
- Data.Morpheus.Types.Internal.AST: gqlObject :: GQLValue a => [(Text, a)] -> a
+ Data.Morpheus.Types.Internal.AST: gqlObject :: GQLValue a => [(Name, a)] -> a
- Data.Morpheus.Types.Internal.AST: initTypeLib :: (Key, DataObject) -> DataTypeLib
+ Data.Morpheus.Types.Internal.AST: initTypeLib :: (Key, DataType) -> DataTypeLib
- Data.Morpheus.Types.Internal.AST: isEntNode :: DataType -> Bool
+ Data.Morpheus.Types.Internal.AST: isEntNode :: DataTypeContent -> Bool
- Data.Morpheus.Types.Internal.AST: isNullable :: [TypeWrapper] -> Bool
+ Data.Morpheus.Types.Internal.AST: isNullable :: TypeRef -> Bool
- Data.Morpheus.Types.Internal.AST: lookupDataObject :: (Monad m, Failure e m) => e -> Key -> DataTypeLib -> m DataObject
+ Data.Morpheus.Types.Internal.AST: lookupDataObject :: (Monad m, Failure e m) => e -> Key -> DataTypeLib -> m (Name, DataObject)
- Data.Morpheus.Types.Internal.AST: lookupFieldAsSelectionSet :: (Monad m, Failure GQLErrors m) => Position -> Key -> DataTypeLib -> DataField -> m DataObject
+ Data.Morpheus.Types.Internal.AST: lookupFieldAsSelectionSet :: (Monad m, Failure GQLErrors m) => Position -> Key -> DataTypeLib -> DataField -> m (Name, DataObject)
- Data.Morpheus.Types.Internal.AST: lookupSelectionField :: Failure GQLErrors Validation => Position -> Key -> DataObject -> Validation DataField
+ Data.Morpheus.Types.Internal.AST: lookupSelectionField :: Failure GQLErrors Validation => Position -> Name -> Name -> DataObject -> Validation DataField
- Data.Morpheus.Types.Internal.AST: lookupUnionTypes :: (Monad m, Failure GQLErrors m) => Position -> Key -> DataTypeLib -> DataField -> m [DataObject]
+ Data.Morpheus.Types.Internal.AST: lookupUnionTypes :: (Monad m, Failure GQLErrors m) => Position -> Key -> DataTypeLib -> DataField -> m [(Name, DataObject)]
- Data.Morpheus.Types.Internal.AST: replaceValue :: Value -> Value
+ Data.Morpheus.Types.Internal.AST: replaceValue :: Value -> Value a
- Data.Morpheus.Types.Internal.AST: type Arguments = Collection Argument
+ Data.Morpheus.Types.Internal.AST: type Arguments a = Collection (Argument a)
- Data.Morpheus.Types.Internal.AST: type DataEnum = DataTyCon [DataEnumValue]
+ Data.Morpheus.Types.Internal.AST: type DataEnum = [DataEnumValue]
- Data.Morpheus.Types.Internal.AST: type DataObject = DataTyCon [(Key, DataField)]
+ Data.Morpheus.Types.Internal.AST: type DataObject = [(Key, DataField)]
- Data.Morpheus.Types.Internal.AST: type DataScalar = DataTyCon DataValidator
+ Data.Morpheus.Types.Internal.AST: type DataScalar = DataValidator
- Data.Morpheus.Types.Internal.AST: type DataUnion = DataTyCon [Key]
+ Data.Morpheus.Types.Internal.AST: type DataUnion = [Key]
- Data.Morpheus.Types.Internal.AST: type DefaultValue = Maybe Value
+ Data.Morpheus.Types.Internal.AST: type DefaultValue = Maybe ResolvedValue
- Data.Morpheus.Types.Internal.AST: type Object = [(Text, Value)]
+ Data.Morpheus.Types.Internal.AST: type Object a = Collection (Value a)
- Data.Morpheus.Types.Internal.AST: type RawArguments = Collection RawArgument
+ Data.Morpheus.Types.Internal.AST: type RawArguments = Arguments RAW
- Data.Morpheus.Types.Internal.AST: type RawOperation = Operation VariableDefinitions RawSelectionSet
+ Data.Morpheus.Types.Internal.AST: type RawOperation = Operation RAW
- Data.Morpheus.Types.Internal.AST: type SelectionSet = Collection ValidSelection
+ Data.Morpheus.Types.Internal.AST: type SelectionSet a = Collection (Selection a)
- Data.Morpheus.Types.Internal.AST: type ValidOperation = Operation Arguments SelectionSet
+ Data.Morpheus.Types.Internal.AST: type ValidOperation = Operation VALID
- Data.Morpheus.Types.Internal.AST: type ValidSelection = Selection Arguments SelectionRec
+ Data.Morpheus.Types.Internal.AST: type ValidSelection = Selection VALID
- Data.Morpheus.Types.Internal.AST: type ValidVariables = Collection (Variable Value)
+ Data.Morpheus.Types.Internal.AST: type ValidVariables = Collection (Variable VALID)
- Data.Morpheus.Types.Internal.AST: type VariableDefinitions = Collection (Variable DefaultValue)
+ Data.Morpheus.Types.Internal.AST: type VariableDefinitions = Collection (Variable RAW)
- Data.Morpheus.Types.Internal.AST: type Variables = Map Key Value
+ Data.Morpheus.Types.Internal.AST: type Variables = Map Key ResolvedValue

Files

README.md view
@@ -29,7 +29,7 @@ resolver: lts-14.8  extra-deps:-  - morpheus-graphql-0.7.1+  - morpheus-graphql-0.8.0 ```  As Morpheus is quite new, make sure stack can find morpheus-graphql by running `stack upgrade` and `stack update`@@ -118,10 +118,7 @@ data Deity = Deity   { fullName :: Text         -- Non-Nullable Field   , power    :: Maybe Text   -- Nullable Field-  } deriving (Generic)--instance GQLType Deity where-  type  KIND Deity = OBJECT+  } deriving (Generic,GQLType)  data DeityArgs = DeityArgs   { name      :: Text        -- Required Argument@@ -152,8 +149,6 @@ askDB = ... ``` -Note that the type `a -> IORes b` is just Synonym for `a -> ExceptT String IO b`- To make this `Query` type available as an API, we define a `GQLRootResolver` and feed it to the Morpheus `interpreter`. A `GQLRootResolver` consists of `query`, `mutation` and `subscription` definitions, while we omit the latter for this example:  ```haskell@@ -236,14 +231,70 @@  ```haskell data Character-  = DEITY Deity-  | HUMAN Human-  deriving (Generic)+  = data Character  =+    CharacterDeity Deity -- Only <tyconName><conName> should generate direct link+  -- RECORDS+  | Creature { creatureName :: Text, creatureAge :: Int }+  --- Types+  | SomeDeity Deity+  | CharacterInt Int+  | SomeMutli Int Text+  --- ENUMS+  | Zeus+  | Cronus+  deriving (Generic, GQLType)+``` -instance GQLType Character where-  type KIND Character = UNION+where deity is and object++as you see there ar different kinds of unions. `morpheus` handles them all.++this type will be represented as++```gql+union Character =+    Deity # unwrapped union: becouse Character + Deity = CharacterDeity+  | Creature+  | SomeDeity # wrapped union: becouse Character + Deity != SomeDeity+  | CharacterInt+  | SomeMutli+  | CharacterEnumObject # object wrapped for enums++type Creature {+  creatureName: String!+  creatureAge: Int!+}++type SomeDeity {+  _0: Deity!+}++type CharacterInt {+  _0: Int!+}++type SomeMutli {+  _0: Int!+  _1: String!+}++# enum+type CharacterEnumObject {+  enum: CharacterEnum!+}++enum CharacterEnum {+  Zeus+  Cronus+} ``` +- namespaced Unions: `CharacterDeity` where `Character` is TypeConstructor and `Deity` referenced object (not scalar) type: will be generate regular graphql Union+  +- for for all other unions will be generated new object type. for types without record syntaxt, fields will be automatally indexed.++- all empty constructors in union will be summed in type `<tyConName>Enum` (e.g `CharacterEnum`), this enum will be wrapped in `CharacterEnumObject` and added to union members.+ ### Scalar types  To use custom scalar types, you need to provide implementations for `parseValue` and `serialize` respectively.@@ -285,6 +336,28 @@ ![alt text](https://morpheusgraphql.com/assets/img/introspection/spelling.png "spelling") ![alt text](https://morpheusgraphql.com/assets/img/introspection/autocomplete.png "autocomplete") ![alt text](https://morpheusgraphql.com/assets/img/introspection/type.png "type")++## Handling Errors++for errors you can use use either `liftEither` or `failRes`:+at the and they have same result.++with `liftEither`++```haskell+resolveDeity :: DeityArgs -> IORes e Deity+resolveDeity DeityArgs {} = liftEither $ dbDeity++dbDeity ::  IO Either Deity+dbDeity = pure $ Left "db error"+```++with `failRes`++```haskell+resolveDeity :: DeityArgs -> IORes e Deity+resolveDeity DeityArgs { } = failRes "db error"+```  ### Mutations 
changelog.md view
@@ -1,14 +1,187 @@+## [0.8.0] - 15.12.2009++### Changed++- deprecated: `INPUT_OBJECT`, `OBJECT`, `UNION`,++  - use `INPUT` instead of `INPUT_OBJECT`+  - use `deriving(GQLType)` insead of `OBJECT` or `UNION`++- only namespaced Unions  generate regular graphql Union, other attempts will be wrapped inside an object with constructor name :++  e.g:+  +  ```hs+  data Character = +    CharacterDeity Deity+    SomeDeity Deity+    deriving (GQLType)+  ```++  where `Deity` is Object.+  will generate++  ```gql+    union CHaracter = Deity | SomeDeity++    type SomeDeity {+      _0: Deity+    }+  ```++### Added++- `failRes` for resolver failures+- added kind: INPUT , OUTPUT+- Automatic Type Inference (only for Object, Union and Enum)+- More general stateful resolvers which accept instances of MonadIO (Authored by Sebastian Pulido [sebashack])+- Utility to create web-socket applications with custom MonadIO instances (Authored by Sebastian Pulido [sebashack])++```hs++data Realm  =+    Sky+  | Sea+  | Underworld+    deriving (Generic, GQLType)++data Deity  = Deity{+    fullName:: Text,+    realm:: Realm+  } deriving (Generic, GQLType)++data Character  =+    CharacterDeity Deity -- Only <tyconName><conName> should generate direct link+  -- RECORDS+  | Creature { creatureName :: Text, creatureAge :: Int }+  --- Types+  | SomeDeity Deity+  | CharacterInt Int+  | SomeMutli Int Text+  --- ENUMS+  | Zeus+  | Cronus deriving (Generic, GQLType)+++```++will generate schema:++```gql+enum Realm {+  Sky+  Sea+  Underworld+}++type Deity {+  fullName: String!+  realm: Realm!+}++union Character =+    Deity+  | Creature+  | SomeDeity+  | CharacterInt+  | SomeMutli+  | CharacterEnumObject++type Creature {+  creatureName: String!+  creatureAge: Int!+}++type SomeDeity {+  _0: Deity!+}++type CharacterInt {+  _0: Int!+}++type SomeMutli {+  _0: Int!+  _1: String!+}++# enum+type CharacterEnumObject {+  enum: CharacterEnum!+}++enum CharacterEnum {+  Zeus+  Cronus+}+```++rules:++- haskell union type with only empty constructors (e.g `Realm`), will generate graphql `enum`+- haskell record without union (e.g `Deity`), will generate graphql `object`+- namespaced Unions: `CharacterDeity` where `Character` is TypeConstructor and `Deity` referenced object (not scalar) type: will be generate regular graphql Union++  ```gql+  union Character =+        Deity+      | ...+  ```++- for union recrods (`Creature { creatureName :: Text, creatureAge :: Int }`) will be referenced in union type, plus type `Creature`will be added in schema.++  e.g++  ```gql+    union Character =+      ...+      | Creature+      | ...++    type Creature {+      creatureName : String!+      creatureAge: Int!+    }++  ```++  - all empty constructors in union will be summed in type `<tyConName>Enum` (e.g `CharacterEnum`), this enum will be wrapped in `CharacterEnumObject` and this type will be added to union `Character`. as in example above++  - there is only types left with form `TypeName Type1 2Type ..`(e.g `SomeDeity Deity` ,`CharacterInt Int`, `SomeMutli Int Text`),++    morpheus will generate objet type from it:++    ```gql+    type TypeName {+      _0: Type1!+      _1: Type2!+      ...+    }+    ```++### Removed++- removed kind: INPUT_UNION++### Fixed++- on filed resolver was displayed. unexhausted case exception of graphql error+- support of signed numbers (e.g `-4`)+- support of round floats (e.g `1.000`) +- validation checks undefined fields on inputObject+- variables are supported inside input values+ ## [0.7.1] - 26.11.2019  - max bound icludes: support-megaparsec-8.0  ## [0.7.0] - 24.11.2019 -## Removed+### Removed  - `toMorpheusHaskellAPi` from `Data.Morpheus.Document` functionality will be migrated in `morpheus-graphql-cli` -## Changed+### Changed  - `liftM` to `MonadTrans` instance method `lift` 
morpheus-graphql.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: efbb028b66786193717210bd506961ab228d3150ecf66b7d6645e5f972aa3c95+-- hash: edc0f21d61026ad6d50de9239e2f190424c4f7c8968b0908c467f9c487bf4e5b  name:           morpheus-graphql-version:        0.7.1+version:        0.8.0 synopsis:       Morpheus GraphQL description:    Build GraphQL APIs with your favourite functional language! category:       web, graphql@@ -26,6 +26,7 @@     test/Feature/Holistic/arguments/nameConflict/query.gql     test/Feature/Holistic/arguments/undefinedArgument/query.gql     test/Feature/Holistic/arguments/unknownArguments/query.gql+    test/Feature/Holistic/failure/resolveFailure/query.gql     test/Feature/Holistic/fragment/cannotBeSpreadOnType/query.gql     test/Feature/Holistic/fragment/inlineFragment/query.gql     test/Feature/Holistic/fragment/inlineFragmentTypeMismatch/query.gql@@ -72,6 +73,7 @@     test/Feature/Holistic/parsing/invalidNotNullOperator/query.gql     test/Feature/Holistic/parsing/missingCloseBrace/query.gql     test/Feature/Holistic/parsing/notNullSpacing/query.gql+    test/Feature/Holistic/parsing/numbers/query.gql     test/Feature/Holistic/parsing/singleLineComments/query.gql     test/Feature/Holistic/schema.gql     test/Feature/Holistic/selection/AliasNameConflict/query.gql@@ -91,6 +93,15 @@     test/Feature/Input/Enum/decodeMany/con4/query.gql     test/Feature/Input/Enum/decodeMany/con5/query.gql     test/Feature/Input/Enum/decodeMany/con6/query.gql+    test/Feature/Input/Object/nullableUndefinedField/query.gql+    test/Feature/Input/Object/resolveObject/query.gql+    test/Feature/Input/Object/resolveVariable/query.gql+    test/Feature/Input/Object/undefinedField/query.gql+    test/Feature/Input/Object/unexpectedValue/query.gql+    test/Feature/Input/Object/unexpectedVariable/query.gql+    test/Feature/Input/Object/unknownField/query.gql+    test/Feature/Input/Scalar/decodeFloat/query.gql+    test/Feature/Input/Scalar/decodeInt/query.gql     test/Feature/InputType/variables/incompatibleType/equalType/query.gql     test/Feature/InputType/variables/incompatibleType/stricterType/query.gql     test/Feature/InputType/variables/incompatibleType/weakerType1/query.gql@@ -112,6 +123,18 @@     test/Feature/InputType/variables/valueNotProvided/nonNullVariableWithDefaultValue/query.gql     test/Feature/InputType/variables/valueNotProvided/nullableVariable/query.gql     test/Feature/Schema/nameCollision/query.gql+    test/Feature/TypeInference/introspection/complexInput/query.gql+    test/Feature/TypeInference/introspection/complexUnion/query.gql+    test/Feature/TypeInference/introspection/complexUnionEnum/query.gql+    test/Feature/TypeInference/introspection/complexUnionIndexedTypes/query.gql+    test/Feature/TypeInference/introspection/complexUnionRecord/query.gql+    test/Feature/TypeInference/introspection/complexUnionScalar/query.gql+    test/Feature/TypeInference/introspection/enum/query.gql+    test/Feature/TypeInference/introspection/inputObject/query.gql+    test/Feature/TypeInference/introspection/object/query.gql+    test/Feature/TypeInference/resolving/complexUnion/query.gql+    test/Feature/TypeInference/resolving/input/query.gql+    test/Feature/TypeInference/resolving/object/query.gql     test/Feature/UnionType/cannotBeSpreadOnType/query.gql     test/Feature/UnionType/fragmentOnAAndB/query.gql     test/Feature/UnionType/fragmentOnlyOnA/query.gql@@ -127,6 +150,7 @@     test/Feature/Holistic/arguments/undefinedArgument/response.json     test/Feature/Holistic/arguments/unknownArguments/response.json     test/Feature/Holistic/cases.json+    test/Feature/Holistic/failure/resolveFailure/response.json     test/Feature/Holistic/fragment/cannotBeSpreadOnType/response.json     test/Feature/Holistic/fragment/inlineFragment/response.json     test/Feature/Holistic/fragment/inlineFragmentTypeMismatch/response.json@@ -174,6 +198,7 @@     test/Feature/Holistic/parsing/missingCloseBrace/response.json     test/Feature/Holistic/parsing/notNullSpacing/response.json     test/Feature/Holistic/parsing/notNullSpacing/variables.json+    test/Feature/Holistic/parsing/numbers/response.json     test/Feature/Holistic/parsing/singleLineComments/response.json     test/Feature/Holistic/selection/AliasNameConflict/response.json     test/Feature/Holistic/selection/AliasResolve/response.json@@ -193,6 +218,18 @@     test/Feature/Input/Enum/decodeMany/con4/response.json     test/Feature/Input/Enum/decodeMany/con5/response.json     test/Feature/Input/Enum/decodeMany/con6/response.json+    test/Feature/Input/Object/cases.json+    test/Feature/Input/Object/nullableUndefinedField/response.json+    test/Feature/Input/Object/resolveObject/response.json+    test/Feature/Input/Object/resolveVariable/response.json+    test/Feature/Input/Object/resolveVariable/variables.json+    test/Feature/Input/Object/undefinedField/response.json+    test/Feature/Input/Object/unexpectedValue/response.json+    test/Feature/Input/Object/unexpectedVariable/response.json+    test/Feature/Input/Object/unknownField/response.json+    test/Feature/Input/Scalar/cases.json+    test/Feature/Input/Scalar/decodeFloat/response.json+    test/Feature/Input/Scalar/decodeInt/response.json     test/Feature/InputType/cases.json     test/Feature/InputType/variables/incompatibleType/equalType/response.json     test/Feature/InputType/variables/incompatibleType/equalType/variables.json@@ -229,6 +266,19 @@     test/Feature/InputType/variables/valueNotProvided/nullableVariable/response.json     test/Feature/Schema/cases.json     test/Feature/Schema/nameCollision/response.json+    test/Feature/TypeInference/cases.json+    test/Feature/TypeInference/introspection/complexInput/response.json+    test/Feature/TypeInference/introspection/complexUnion/response.json+    test/Feature/TypeInference/introspection/complexUnionEnum/response.json+    test/Feature/TypeInference/introspection/complexUnionIndexedTypes/response.json+    test/Feature/TypeInference/introspection/complexUnionRecord/response.json+    test/Feature/TypeInference/introspection/complexUnionScalar/response.json+    test/Feature/TypeInference/introspection/enum/response.json+    test/Feature/TypeInference/introspection/inputObject/response.json+    test/Feature/TypeInference/introspection/object/response.json+    test/Feature/TypeInference/resolving/complexUnion/response.json+    test/Feature/TypeInference/resolving/input/response.json+    test/Feature/TypeInference/resolving/object/response.json     test/Feature/UnionType/cannotBeSpreadOnType/response.json     test/Feature/UnionType/cases.json     test/Feature/UnionType/fragmentOnAAndB/response.json@@ -313,7 +363,6 @@       Data.Morpheus.Types.ID       Data.Morpheus.Types.Internal.AST.Base       Data.Morpheus.Types.Internal.AST.Data-      Data.Morpheus.Types.Internal.AST.Operation       Data.Morpheus.Types.Internal.AST.Selection       Data.Morpheus.Types.Internal.AST.Value       Data.Morpheus.Types.Internal.Resolving@@ -359,9 +408,12 @@   other-modules:       Feature.Holistic.API       Feature.Input.Enum.API+      Feature.Input.Object.API+      Feature.Input.Scalar.API       Feature.InputType.API       Feature.Schema.A2       Feature.Schema.API+      Feature.TypeInference.API       Feature.UnionType.API       Feature.WrappedTypeName.API       Lib
src/Data/Morpheus/Error/Fragment.hs view
@@ -11,7 +11,9 @@ where  import           Data.Semigroup                 ( (<>) )-import           Data.Text                      ( Text )+import           Data.Text                      ( Text+                                                , intercalate+                                                ) import qualified Data.Text                     as T  -- MORPHEUS@@ -40,7 +42,7 @@ fragmentNameCollision = map toError  where   toError Ref { refName, refPosition } = GQLError-    { message      = "There can be only one fragment named \"" <> refName <> "\"."+    { message   = "There can be only one fragment named \"" <> refName <> "\"."     , locations = [refPosition]     } @@ -48,7 +50,7 @@ unusedFragment = map toError  where   toError Ref { refName, refPosition } = GQLError-    { message      = "Fragment \"" <> refName <> "\" is never used."+    { message   = "Fragment \"" <> refName <> "\" is never used."     , locations = [refPosition]     } @@ -60,7 +62,7 @@     [ "Cannot spread fragment \""     , refName $ head fragments     , "\" within itself via "-    , T.intercalate "," (map refName fragments)+    , T.intercalate ", " (map refName fragments)     , "."     ] @@ -70,19 +72,18 @@   where text = T.concat ["Unknown Fragment \"", key', "\"."]  -- Fragment type mismatch -> "Fragment \"H\" cannot be spread here as objects of type \"Hobby\" can never be of type \"Experience\"."-cannotBeSpreadOnType :: Maybe Text -> Text -> Position -> Text -> GQLErrors-cannotBeSpreadOnType key' type' position' selectionType' = errorMessage-  position'-  text+cannotBeSpreadOnType :: Maybe Text -> Text -> Position -> [Text] -> GQLErrors+cannotBeSpreadOnType key fragmentType position typeMembers = errorMessage+  position+  message  where-  text = T.concat-    [ "Fragment"-    , getName key'-    , " cannot be spread here as objects of type \""-    , selectionType'-    , "\" can never be of type \""-    , type'-    , "\"."-    ]-  getName (Just x') = T.concat [" \"", x', "\""]-  getName Nothing   = ""+  message =+    "Fragment "+      <> getName key+      <> "cannot be spread here as objects of type \""+      <> intercalate ", " typeMembers+      <> "\" can never be of type \""+      <> fragmentType+      <> "\"."+  getName (Just x) = "\"" <> x <> "\" "+  getName Nothing  = ""
src/Data/Morpheus/Error/Input.hs view
@@ -13,19 +13,25 @@ import           Data.Aeson                     ( encode ) import           Data.ByteString.Lazy.Char8     ( unpack ) import           Data.Morpheus.Types.Internal.AST.Value-                                                ( Value )+                                                ( ResolvedValue ) import           Data.Text                      ( Text ) import qualified Data.Text                     as T                                                 ( concat                                                 , intercalate                                                 , pack                                                 )+++import           Data.Morpheus.Types.Internal.Resolving.Core+                                                ( GQLErrors )+ type InputValidation a = Either InputError a  data InputError-  = UnexpectedType [Prop] Text Value (Maybe Text)+  = UnexpectedType [Prop] Text ResolvedValue (Maybe Text)   | UndefinedField [Prop] Text   | UnknownField [Prop] Text+  | GlobalInputError GQLErrors  data Prop =   Prop@@ -33,17 +39,20 @@     , propType :: Text     } -inputErrorMessage :: InputError -> Text+inputErrorMessage :: InputError -> Either GQLErrors Text inputErrorMessage (UnexpectedType path type' value errorMessage) =-  expectedTypeAFoundB path type' value errorMessage-inputErrorMessage (UndefinedField path' field') = undefinedField path' field'-inputErrorMessage (UnknownField   path' field') = unknownField path' field'+  Right $ expectedTypeAFoundB path type' value errorMessage+inputErrorMessage (UndefinedField path' field') =+  Right $ undefinedField path' field'+inputErrorMessage (UnknownField path' field') =+  Right $ unknownField path' field'+inputErrorMessage (GlobalInputError err) = Left err  pathToText :: [Prop] -> Text pathToText []    = "" pathToText path' = T.concat ["on ", T.intercalate "." $ fmap propKey path'] -expectedTypeAFoundB :: [Prop] -> Text -> Value -> Maybe Text -> Text+expectedTypeAFoundB :: [Prop] -> Text -> ResolvedValue -> Maybe Text -> Text expectedTypeAFoundB path' expected found Nothing = T.concat   [ pathToText path'   , " Expected type \""
src/Data/Morpheus/Error/Internal.hs view
@@ -5,6 +5,7 @@   , internalArgumentError   , internalUnknownTypeMessage   , internalError+  , internalResolvingError   ) where @@ -23,7 +24,7 @@                                                 , Failure(..)                                                 ) import           Data.Morpheus.Types.Internal.AST.Value-                                                ( Value(..) )+                                                ( ValidValue )   -- GQL:: if no mutation defined -> "Schema is not configured for mutations."@@ -32,6 +33,11 @@ internalError x = failure $ globalErrorMessage $ "INTERNAL ERROR: " <> x  -- if type did not not found, but was defined by Schema+internalResolvingError :: Text -> GQLErrors+internalResolvingError = globalErrorMessage . ("INTERNAL RESOLVING ERROR:" <>)+++-- if type did not not found, but was defined by Schema internalUnknownTypeMessage :: Text -> GQLErrors internalUnknownTypeMessage x = globalErrorMessage   $ T.concat ["type did not not found, but was defined by Schema", x]@@ -41,6 +47,6 @@ internalArgumentError x = internalError $ "Argument " <> x  -- if value is already validated but value has different type-internalTypeMismatch :: Text -> Value -> Validation b+internalTypeMismatch :: Text -> ValidValue -> Validation b internalTypeMismatch text jsType =   internalError $ "Type mismatch " <> text <> T.pack (show jsType)
src/Data/Morpheus/Execution/Client/Compile.hs view
@@ -58,7 +58,8 @@ validateWith :: DataTypeLib -> (GQLQuery, String) -> Validation ClientQuery validateWith schema (rawRequest@GQLQuery { operation }, queryText) = do   validOperation <- validateRequest schema WITHOUT_VARIABLES rawRequest-  (queryArgsType, queryTypes) <- operationTypes schema-                                                (O.operationArgs operation)-                                                validOperation+  (queryArgsType, queryTypes) <- operationTypes+    schema+    (O.operationArguments operation)+    validOperation   return ClientQuery { queryText, queryTypes, queryArgsType }
src/Data/Morpheus/Execution/Client/Selection.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE GADTs               #-} {-# LANGUAGE FlexibleInstances   #-} {-# LANGUAGE NamedFieldPuns      #-} {-# LANGUAGE OverloadedStrings   #-}@@ -23,25 +24,24 @@ import           Data.Morpheus.Execution.Internal.Utils                                                 ( nameSpaceType ) import           Data.Morpheus.Types.Internal.AST-                                                ( DefaultValue-                                                , Operation(..)+                                                ( Operation(..)                                                 , ValidOperation                                                 , Variable(..)                                                 , VariableDefinitions                                                 , getOperationName                                                 , getOperationDataType                                                 , Selection(..)-                                                , SelectionRec(..)-                                                , SelectionSet+                                                , SelectionContent(..)+                                                , ValidSelectionSet                                                 , ValidSelection-                                                , Ref(..) +                                                , Ref(..)                                                 , DataField(..)-                                                , DataTyCon(..)+                                                , DataTypeContent(..)                                                 , DataType(..)                                                 , DataTypeKind(..)                                                 , DataTypeLib(..)                                                 , Key-                                                , TypeAlias(..)+                                                , TypeRef(..)                                                 , DataEnumValue(..)                                                 , allDataTypes                                                 , lookupType@@ -50,6 +50,7 @@                                                 , TypeD(..)                                                 , lookupDeprecated                                                 , lookupDeprecatedReason+                                                , RAW                                                 ) import           Data.Morpheus.Types.Internal.Resolving                                                 ( GQLErrors@@ -79,13 +80,13 @@ operationTypes lib variables = genOperation  where   genOperation operation@Operation { operationName, operationSelection } = do-    datatype            <- DataObject <$> getOperationDataType operation lib+    datatype            <- getOperationDataType operation lib     (queryTypes, enums) <- genRecordType []                                          (getOperationName operationName)                                          datatype                                          operationSelection     inputTypeRequests <- resolveUpdates []-      $ map (scanInputTypes lib . variableType . snd) variables+      $ map (scanInputTypes lib . typeConName . variableType . snd) variables     inputTypesAndEnums <- buildListedTypes (inputTypeRequests <> enums)     pure       ( rootArguments (getOperationName operationName <> "Args")@@ -112,15 +113,12 @@       , tMeta      = Nothing       }      where-      fieldD :: (Text, Variable DefaultValue) -> DataField-      fieldD (key, Variable { variableType, variableTypeWrappers }) = DataField+      fieldD :: (Text, Variable RAW) -> DataField+      fieldD (key, Variable { variableType }) = DataField         { fieldName     = key         , fieldArgs     = []         , fieldArgsType = Nothing-        , fieldType     = TypeAlias { aliasWrappers = variableTypeWrappers-                                    , aliasTyCon    = variableType-                                    , aliasArgs     = Nothing-                                    }+        , fieldType     = variableType         , fieldMeta     = Nothing         }   ---------------------------------------------------------@@ -129,7 +127,7 @@     :: [Key]     -> Key     -> DataType-    -> SelectionSet+    -> ValidSelectionSet     -> Validation ([ClientType], [Text])   genRecordType path name dataType recordSelSet = do     (con, subTypes, requests) <- genConsD (unpack name) dataType recordSelSet@@ -150,7 +148,7 @@     genConsD       :: String       -> DataType-      -> SelectionSet+      -> ValidSelectionSet       -> Validation (ConsD, [ClientType], [Text])     genConsD cName datatype selSet = do       (cFields, subTypes, requests) <- unzip3 <$> traverse genField selSet@@ -184,13 +182,13 @@         ------------------------------------------         subTypesBySelection           :: DataType -> ValidSelection -> Validation ([ClientType], [Text])-        subTypesBySelection dType Selection { selectionRec = SelectionField } =-          leafType dType+        subTypesBySelection dType Selection { selectionContent = SelectionField }+          = leafType dType           --withLeaf buildLeaf dType-        subTypesBySelection dType Selection { selectionRec = SelectionSet selectionSet }+        subTypesBySelection dType Selection { selectionContent = SelectionSet selectionSet }           = genRecordType fieldPath (typeFrom [] dType) dType selectionSet           ---- UNION-        subTypesBySelection dType Selection { selectionRec = UnionSelection unionSelections }+        subTypesBySelection dType Selection { selectionContent = UnionSelection unionSelections }           = do             (tCons, subTypes, requests) <-               unzip3 <$> mapM getUnionType unionSelections@@ -213,55 +211,58 @@  scanInputTypes :: DataTypeLib -> Key -> LibUpdater [Key] scanInputTypes lib name collected | name `elem` collected = pure collected-                                  | otherwise = getType lib name >>= scanType+                                  | otherwise = getType lib name >>= scanInpType  where-  scanType (DataInputObject DataTyCon { typeData }) = resolveUpdates-    (name : collected)-    (map toInputTypeD typeData)+  scanInpType DataType { typeContent, typeName } = scanType typeContent    where-    toInputTypeD :: (Text, DataField) -> LibUpdater [Key]-    toInputTypeD (_, DataField { fieldType = TypeAlias { aliasTyCon } }) =-      scanInputTypes lib aliasTyCon-  scanType (DataEnum DataTyCon { typeName }) = pure (collected <> [typeName])-  scanType _ = pure collected+    scanType (DataInputObject fields) = resolveUpdates+      (name : collected)+      (map toInputTypeD fields)+     where+      toInputTypeD :: (Text, DataField) -> LibUpdater [Key]+      toInputTypeD (_, DataField { fieldType = TypeRef { typeConName } }) =+        scanInputTypes lib typeConName+    scanType (DataEnum _) = pure (collected <> [typeName])+    scanType _            = pure collected  buildInputType :: DataTypeLib -> Text -> Validation [ClientType]-buildInputType lib name = getType lib name >>= subTypes+buildInputType lib name = getType lib name >>= generateTypes  where-  subTypes (DataInputObject DataTyCon { typeName, typeData }) = do-    fields <- traverse toFieldD typeData-    pure+  generateTypes DataType { typeName, typeContent } = subTypes typeContent+   where+    subTypes (DataInputObject inputFields) = do+      fields <- traverse toFieldD inputFields+      pure+        [ ClientType+            { clientType =+              TypeD+                { tName      = unpack typeName+                , tNamespace = []+                , tCons = [ConsD { cName = unpack typeName, cFields = fields }]+                , tMeta      = Nothing+                }+            , clientKind = KindInputObject+            }+        ]+     where+      toFieldD :: (Text, DataField) -> Validation DataField+      toFieldD (_, field@DataField { fieldType }) = do+        typeConName <- typeFrom [] <$> getType lib (typeConName fieldType)+        pure $ field { fieldType = fieldType { typeConName } }+    subTypes (DataEnum enumTags) = pure       [ ClientType-          { clientType =-            TypeD-              { tName      = unpack typeName-              , tNamespace = []-              , tCons = [ConsD { cName = unpack typeName, cFields = fields }]-              , tMeta      = Nothing-              }-          , clientKind = KindInputObject+          { clientType = TypeD { tName      = unpack typeName+                               , tNamespace = []+                               , tCons      = map enumOption enumTags+                               , tMeta      = Nothing+                               }+          , clientKind = KindEnum           }       ]--   where-    toFieldD :: (Text, DataField) -> Validation DataField-    toFieldD (_, field@DataField { fieldType }) = do-      aliasTyCon <- typeFrom [] <$> getType lib (aliasTyCon fieldType)-      pure $ field { fieldType = fieldType { aliasTyCon } }-  subTypes (DataEnum DataTyCon { typeName, typeData }) = pure-    [ ClientType-        { clientType = TypeD { tName      = unpack typeName-                             , tNamespace = []-                             , tCons      = map enumOption typeData-                             , tMeta      = Nothing-                             }-        , clientKind = KindEnum-        }-    ]-   where-    enumOption DataEnumValue { enumName } =-      ConsD { cName = unpack enumName, cFields = [] }-  subTypes _ = pure []+     where+      enumOption DataEnumValue { enumName } =+        ConsD { cName = unpack enumName, cFields = [] }+    subTypes _ = pure []   lookupFieldType@@ -270,14 +271,14 @@   -> DataType   -> Position   -> Text-  -> Validation (DataType, TypeAlias)-lookupFieldType lib path (DataObject DataTyCon { typeData, typeName }) refPosition key-  = case lookup key typeData of-    Just DataField { fieldType = alias@TypeAlias { aliasTyCon }, fieldMeta } ->-      checkDeprecated >> (trans <$> getType lib aliasTyCon)+  -> Validation (DataType, TypeRef)+lookupFieldType lib path DataType { typeContent = DataObject typeContent, typeName } refPosition key+  = case lookup key typeContent of+    Just DataField { fieldType = alias@TypeRef { typeConName }, fieldMeta } ->+      checkDeprecated >> (trans <$> getType lib typeConName)      where       trans x =-        (x, alias { aliasTyCon = typeFrom path x, aliasArgs = Nothing })+        (x, alias { typeConName = typeFrom path x, typeArgs = Nothing })       ------------------------------------------------------------------       checkDeprecated :: Validation ()       checkDeprecated = case fieldMeta >>= lookupDeprecated of@@ -288,16 +289,20 @@                                      (lookupDeprecatedReason deprecation)         Nothing -> pure ()     -------------------    Nothing -> failure-      (compileError $ "cant find field \"" <> pack (show typeData) <> "\"")+    Nothing ->+      failure+        (compileError $ "cant find field \"" <> pack (show typeContent) <> "\"") lookupFieldType _ _ dt _ _ =   failure (compileError $ "Type should be output Object \"" <> pack (show dt))   leafType :: DataType -> Validation ([ClientType], [Text])-leafType (DataEnum DataTyCon { typeName }) = pure ([], [typeName])-leafType DataScalar{} = pure ([], [])-leafType _ = failure $ compileError "Invalid schema Expected scalar"+leafType DataType { typeName, typeContent } = fromKind typeContent+ where+  fromKind :: DataTypeContent -> Validation ([ClientType], [Text])+  fromKind DataEnum{} = pure ([], [typeName])+  fromKind DataScalar{} = pure ([], [])+  fromKind _ = failure $ compileError "Invalid schema Expected scalar"  getType :: DataTypeLib -> Text -> Validation DataType getType lib typename =@@ -312,9 +317,9 @@ typeFromScalar _         = "ScalarValue"  typeFrom :: [Key] -> DataType -> Text-typeFrom _ (DataScalar DataTyCon { typeName }) = typeFromScalar typeName-typeFrom _ (DataEnum x) = typeName x-typeFrom _ (DataInputObject x) = typeName x-typeFrom path (DataObject x) = pack $ nameSpaceType path $ typeName x-typeFrom path (DataUnion x) = pack $ nameSpaceType path $ typeName x-typeFrom _ (DataInputUnion x) = typeName x+typeFrom path DataType { typeName, typeContent } = __typeFrom typeContent+ where+  __typeFrom DataScalar{} = typeFromScalar typeName+  __typeFrom DataObject{} = pack $ nameSpaceType path typeName+  __typeFrom DataUnion{}  = pack $ nameSpaceType path typeName+  __typeFrom _            = typeName
src/Data/Morpheus/Execution/Document/Convert.hs view
@@ -23,12 +23,12 @@ import           Data.Morpheus.Types.Internal.AST                                                 ( ArgsType(..)                                                 , DataField(..)-                                                , DataTyCon(..)+                                                , DataTypeContent(..)                                                 , DataType(..)                                                 , DataTypeKind(..)                                                 , OperationType(..)                                                 , ResolverKind(..)-                                                , TypeAlias(..)+                                                , TypeRef(..)                                                 , DataEnumValue(..)                                                 , sysTypes                                                 , ConsD(..)@@ -42,7 +42,7 @@ renderTHTypes namespace lib = traverse renderTHType lib  where   renderTHType :: (Text, DataType) -> Validation GQLTypeD-  renderTHType (tyConName, x) = genType x+  renderTHType (tyConName, x) = generateType x    where     genArgsTypeName fieldName | namespace = sysName tyConName <> argTName                               | otherwise = argTName@@ -73,19 +73,19 @@     sysName = unpack . genTypeName     ---------------------------------------------------------------------------------------------     genField :: (Text, DataField) -> DataField-    genField (_, field@DataField { fieldType = alias@TypeAlias { aliasTyCon } })-      = field { fieldType = alias { aliasTyCon = genFieldTypeName aliasTyCon }+    genField (_, field@DataField { fieldType = alias@TypeRef { typeConName } })+      = field { fieldType = alias { typeConName = genFieldTypeName typeConName }               }     ---------------------------------------------------------------------------------------------     genResField :: (Text, DataField) -> DataField-    genResField (_, field@DataField { fieldName, fieldArgs, fieldType = alias@TypeAlias { aliasTyCon } })-      = field { fieldType     = alias { aliasTyCon = ftName, aliasArgs }+    genResField (_, field@DataField { fieldName, fieldArgs, fieldType = alias@TypeRef { typeConName } })+      = field { fieldType     = alias { typeConName = ftName, typeArgs }               , fieldArgsType               }      where-      ftName    = genFieldTypeName aliasTyCon+      ftName   = genFieldTypeName typeConName       ----------------------------------------      aliasArgs = case lookup aliasTyCon lib of+      typeArgs = case typeContent <$> lookup typeConName lib of         Just DataObject{} -> Just "m"         Just DataUnion{}  -> Just "m"         _                 -> Nothing@@ -96,37 +96,38 @@         argsTypeName | null fieldArgs = "()"                      | otherwise = pack $ genArgsTypeName $ unpack fieldName         ---------------------------------------        getFieldType key = case lookup key lib of+        getFieldType key = case typeContent <$> lookup key lib of           Nothing           -> ExternalResolver           Just DataObject{} -> TypeVarResolver           Just DataUnion{}  -> TypeVarResolver           Just _            -> PlainResolver     ---------------------------------------------    genType dt@(DataEnum DataTyCon { typeName, typeData, typeMeta }) = pure-      GQLTypeD+    generateType dt@DataType { typeName, typeContent, typeMeta } = genType+      typeContent+     where+      genType (DataEnum tags) = pure GQLTypeD         { typeD        = TypeD { tName      = sysName typeName                                , tNamespace = []-                               , tCons      = map enumOption typeData+                               , tCons      = map enumOption tags                                , tMeta      = typeMeta                                }         , typeKindD    = KindEnum         , typeArgD     = []         , typeOriginal = (typeName, dt)         }-     where-      enumOption DataEnumValue { enumName } =-        ConsD { cName = sysName enumName, cFields = [] }-    genType (DataScalar _) =-      internalError "Scalar Types should defined By Native Haskell Types"-    genType (DataInputUnion _) = internalError "Input Unions not Supported"-    genType dt@(DataInputObject DataTyCon { typeName, typeData, typeMeta }) =-      pure GQLTypeD+       where+        enumOption DataEnumValue { enumName } =+          ConsD { cName = sysName enumName, cFields = [] }+      genType (DataScalar _) =+        internalError "Scalar Types should defined By Native Haskell Types"+      genType (DataInputUnion _) = internalError "Input Unions not Supported"+      genType (DataInputObject fields) = pure GQLTypeD         { typeD        =           TypeD             { tName      = sysName typeName             , tNamespace = []             , tCons      = [ ConsD { cName   = sysName typeName-                                   , cFields = map genField typeData+                                   , cFields = map genField fields                                    }                            ]             , tMeta      = typeMeta@@ -135,51 +136,52 @@         , typeArgD     = []         , typeOriginal = (typeName, dt)         }-    genType dt@(DataObject DataTyCon { typeName, typeData, typeMeta }) = do-      typeArgD <- concat <$> traverse genArgumentType typeData-      pure GQLTypeD-        { typeD        = TypeD-                           { tName      = sysName typeName-                           , tNamespace = []-                           , tCons = [ ConsD { cName = sysName typeName-                                             , cFields = map genResField typeData-                                             }-                                     ]-                           , tMeta      = typeMeta-                           }-        , typeKindD    = if typeName == "Subscription"-                           then KindObject (Just Subscription)-                           else KindObject Nothing-        , typeArgD-        , typeOriginal = (typeName, dt)-        }-    genType dt@(DataUnion DataTyCon { typeName, typeData, typeMeta }) = do-      let tCons = map unionCon typeData-      pure GQLTypeD-        { typeD        = TypeD { tName      = unpack typeName-                               , tNamespace = []-                               , tCons-                               , tMeta      = typeMeta-                               }-        , typeKindD    = KindUnion-        , typeArgD     = []-        , typeOriginal = (typeName, dt)-        }-     where-      unionCon memberName = ConsD-        { cName-        , cFields = [ DataField-                        { fieldName     = pack $ "un" <> cName-                        , fieldType     = TypeAlias { aliasTyCon = pack utName-                                                    , aliasArgs = Just "m"-                                                    , aliasWrappers = []-                                                    }-                        , fieldMeta     = Nothing-                        , fieldArgs     = []-                        , fieldArgsType = Nothing-                        }-                    ]-        }+      genType (DataObject fields) = do+        typeArgD <- concat <$> traverse genArgumentType fields+        pure GQLTypeD+          { typeD        =+            TypeD+              { tName      = sysName typeName+              , tNamespace = []+              , tCons      = [ ConsD { cName   = sysName typeName+                                     , cFields = map genResField fields+                                     }+                             ]+              , tMeta      = typeMeta+              }+          , typeKindD    = if typeName == "Subscription"+                             then KindObject (Just Subscription)+                             else KindObject Nothing+          , typeArgD+          , typeOriginal = (typeName, dt)+          }+      genType (DataUnion members) = do+        let tCons = map unionCon members+        pure GQLTypeD+          { typeD        = TypeD { tName      = unpack typeName+                                 , tNamespace = []+                                 , tCons+                                 , tMeta      = typeMeta+                                 }+          , typeKindD    = KindUnion+          , typeArgD     = []+          , typeOriginal = (typeName, dt)+          }        where-        cName  = sysName typeName <> utName-        utName = sysName memberName+        unionCon memberName = ConsD+          { cName+          , cFields = [ DataField+                          { fieldName     = pack $ "un" <> cName+                          , fieldType     = TypeRef { typeConName = pack utName+                                                    , typeArgs = Just "m"+                                                    , typeWrappers = []+                                                    }+                          , fieldMeta     = Nothing+                          , fieldArgs     = []+                          , fieldArgsType = Nothing+                          }+                      ]+          }+         where+          cName  = sysName typeName <> utName+          utName = sysName memberName
src/Data/Morpheus/Execution/Document/Declare.hs view
@@ -47,7 +47,7 @@    where     gqlInstances       | isObject typeKindD && isInput typeKindD-      = [deriveObjectRep (typeD, Just typeKindD), deriveDecode typeD]+      = [deriveObjectRep (typeD, Nothing), deriveDecode typeD]       | isObject typeKindD       = [deriveObjectRep (typeD, Just typeKindD), deriveEncode gqlType]       | otherwise
src/Data/Morpheus/Execution/Document/Decode.hs view
@@ -18,30 +18,30 @@ import           Data.Morpheus.Execution.Internal.Decode                                                 ( decodeFieldWith                                                 , decodeObjectExpQ+                                                , withObject                                                 ) import           Data.Morpheus.Execution.Server.Decode                                                 ( Decode(..)-                                                , DecodeObject(..)+                                                , DecodeType(..)                                                 ) import           Data.Morpheus.Types.Internal.AST                                                 ( TypeD(..)-                                                , Object+                                                , ValidValue                                                 ) import           Data.Morpheus.Types.Internal.TH                                                 ( instanceHeadT ) import           Data.Morpheus.Types.Internal.Resolving                                                 ( Validation ) --(.:) :: Decode a => Object -> Text -> Validation a-object .: selectorName = decodeFieldWith decode selectorName object+(.:) :: Decode a => ValidValue -> Text -> Validation a+value .: selectorName = withObject (decodeFieldWith decode selectorName) value  deriveDecode :: TypeD -> Q [Dec] deriveDecode TypeD { tName, tCons = [cons] } =   pure <$> instanceD (cxt []) appHead methods  where-  appHead = instanceHeadT ''DecodeObject tName []-  methods = [funD 'decodeObject [clause argsE (normalB body) []]]+  appHead = instanceHeadT ''DecodeType tName []+  methods = [funD 'decodeType [clause argsE (normalB body) []]]    where     argsE = map (varP . mkName) ["o"]     body  = decodeObjectExpQ [|(.:)|] cons
src/Data/Morpheus/Execution/Document/Encode.hs view
@@ -17,7 +17,7 @@ -- MORPHEUS import           Data.Morpheus.Execution.Server.Encode                                                 ( Encode(..)-                                                , ObjectResolvers(..)+                                                , ExploreResolvers(..)                                                 ) import           Data.Morpheus.Types.GQLType    ( TRUE ) import           Data.Morpheus.Types.Internal.AST@@ -34,6 +34,7 @@                                                 , MapStrategy(..)                                                 , LiftEither                                                 , ResolvingStrategy+                                                , DataResolver(..)                                                 ) import           Data.Morpheus.Types.Internal.TH                                                 ( applyT@@ -88,15 +89,16 @@          ]   -------------------------------------------------------------------   -- defines: instance <constraint> =>  ObjectResolvers ('TRUE) (<Type> (ResolveT m)) (ResolveT m value) where-  appHead =-    instanceHeadMultiT ''ObjectResolvers (conT ''TRUE) (mainType : instanceArgs)+  appHead = instanceHeadMultiT ''ExploreResolvers+                               (conT ''TRUE)+                               (mainType : instanceArgs)   ------------------------------------------------------------------   -- defines: objectResolvers <Type field1 field2 ...> = [("field1",encode field1),("field2",encode field2), ...]-  methods = [funD 'objectResolvers [clause argsE (normalB body) []]]+  methods = [funD 'exploreResolvers [clause argsE (normalB body) []]]    where     argsE = [varP (mkName "_"), destructRecord tName varNames]-    body  = listE $ map decodeVar varNames-    decodeVar name = [|(name, encode $(varName))|]+    body  = appE (conE 'ObjectRes) (listE $ map decodeVar varNames)+    decodeVar name = [| (name, encode $(varName))|]       where varName = varE $ mkName name     varNames = map (unpack . fieldName) cFields deriveEncode _ = pure []
src/Data/Morpheus/Execution/Document/GQLType.hs view
@@ -19,12 +19,10 @@ import           Data.Morpheus.Execution.Internal.Declare                                                 ( tyConArgs ) import           Data.Morpheus.Kind             ( ENUM-                                                , INPUT_OBJECT-                                                , INPUT_UNION-                                                , OBJECT                                                 , SCALAR-                                                , UNION                                                 , WRAPPER+                                                , INPUT+                                                , OUTPUT                                                 ) import           Data.Morpheus.Types.GQLType    ( GQLType(..)                                                 , TRUE@@ -84,9 +82,9 @@     ---------------------------------     toKIND KindScalar      = ''SCALAR     toKIND KindEnum        = ''ENUM-    toKIND (KindObject _)  = ''OBJECT-    toKIND KindUnion       = ''UNION-    toKIND KindInputObject = ''INPUT_OBJECT+    toKIND (KindObject _)  = ''OUTPUT+    toKIND KindUnion       = ''OUTPUT+    toKIND KindInputObject = ''INPUT     toKIND KindList        = ''WRAPPER     toKIND KindNonNull     = ''WRAPPER-    toKIND KindInputUnion  = ''INPUT_UNION+    toKIND KindInputUnion  = ''INPUT
src/Data/Morpheus/Execution/Document/Introspect.hs view
@@ -9,15 +9,15 @@  import Data.Maybe(maybeToList) import           Data.Proxy                                (Proxy (..))-import           Data.Text                                 (unpack)+import           Data.Text                                 (unpack,Text) import           Data.Typeable                             (Typeable) import           Language.Haskell.TH    -- MORPHEUS import           Data.Morpheus.Execution.Internal.Declare  (tyConArgs)-import           Data.Morpheus.Execution.Server.Introspect (Introspect (..), ObjectFields (..))+import           Data.Morpheus.Execution.Server.Introspect (Introspect (..), objectFields, IntrospectRep (..),TypeScope(..)) import           Data.Morpheus.Types.GQLType               (GQLType (__typeName), TRUE)-import           Data.Morpheus.Types.Internal.AST          (ConsD (..), TypeD (..), ArgsType (..),Key, DataType(..), DataField (..),insertType,DataTypeKind(..), TypeAlias (..))+import           Data.Morpheus.Types.Internal.AST          (ConsD (..), TypeD (..), ArgsType (..),Key, DataType(..), DataTypeContent(..), DataField (..),insertType,DataTypeKind(..), TypeRef (..)) import           Data.Morpheus.Types.Internal.TH           (instanceFunD, instanceProxyFunD,instanceHeadT, instanceHeadMultiT, typeT)  @@ -25,14 +25,23 @@ -- FIXME: dirty fix for introspection instanceIntrospect ("__DirectiveLocation",_) = pure [] instanceIntrospect ("__TypeKind",_) = pure []-instanceIntrospect (name, DataEnum enumType) =-  pure <$> instanceD (cxt []) iHead [defineIntrospect]+instanceIntrospect (name, DataType {+      typeContent = DataEnum enumType,+      typeName+      , typeMeta+      , typeFingerprint+    }) = pure <$> instanceD (cxt []) iHead [defineIntrospect]   where     -----------------------------------------------     iHead = instanceHeadT ''Introspect  (unpack name) []     defineIntrospect = instanceProxyFunD ('introspect,body)       where-        body =[| insertType (name, DataEnum enumType) |]+        body =[| insertType (name,DataType {+          typeName+          ,typeMeta+          , typeFingerprint+          ,typeContent = DataEnum enumType+        }) |] instanceIntrospect _ = pure []  -- [((Text, DataField), TypeUpdater)]@@ -40,16 +49,20 @@ deriveObjectRep (TypeD {tName, tCons = [ConsD {cFields}]}, tKind) =   pure <$> instanceD (cxt constrains) iHead methods   where+    mainTypeName = typeT (mkName tName) typeArgs     typeArgs = concatMap tyConArgs (maybeToList tKind)     constrains = map conTypeable typeArgs       where         conTypeable name = typeT ''Typeable [name]     ------------------------------------------------    iHead = instanceHeadMultiT ''ObjectFields (conT ''TRUE) [typeT (mkName tName) typeArgs]-    methods = [instanceFunD 'objectFields ["_proxy1", "_proxy2"] body]+    iHead = instanceHeadMultiT ''IntrospectRep (conT ''TRUE) [mainTypeName]+    methods = [instanceFunD 'introspectRep ["_proxy1", "_proxy2"] body]       where-        body = [|($(buildFields cFields), concat $(buildTypes cFields))|]+        body +          | tKind == Just KindInputObject || null tKind  = [| (DataInputObject  $(buildFields cFields), concat $(buildTypes cFields))|]+          | otherwise  =  [| (DataObject $(buildFields cFields), concat $(buildTypes cFields))|] deriveObjectRep _ = pure []+      buildTypes :: [DataField] -> ExpQ buildTypes = listE . concatMap introspectField@@ -58,30 +71,35 @@       [|[introspect $(proxyT fieldType)]|] : inputTypes fieldArgsType       where         inputTypes (Just ArgsType {argsTypeName})-          | argsTypeName /= "()" = [[|snd $ objectFields (Proxy :: Proxy TRUE) $(proxyT tAlias)|]]+          | argsTypeName /= "()" = [[|snd $ objectFields (Proxy :: Proxy TRUE) (argsTypeName, InputType,$(proxyT tAlias))|]]           where-            tAlias = TypeAlias {aliasTyCon = argsTypeName, aliasWrappers = [], aliasArgs = Nothing}+            tAlias = TypeRef {typeConName = argsTypeName, typeWrappers = [], typeArgs = Nothing}         inputTypes _ = [] -proxyT :: TypeAlias -> Q Exp-proxyT TypeAlias {aliasTyCon, aliasArgs} = [|(Proxy :: Proxy $(genSig aliasArgs))|]+conTX :: Text -> Q Type    +conTX =  conT . mkName . unpack++varTX :: Text -> Q Type    +varTX =  varT . mkName . unpack++proxyT :: TypeRef -> Q Exp+proxyT TypeRef {typeConName, typeArgs} = [|(Proxy :: Proxy $(genSig typeArgs))|]   where-    genSig (Just m) = appT (conT $ mkName $ unpack aliasTyCon) (varT $ mkName $ unpack m)-    genSig _        = conT $ mkName $ unpack aliasTyCon+    genSig (Just m) = appT (conTX typeConName) (varTX m)+    genSig _        = conTX typeConName  buildFields :: [DataField] -> ExpQ buildFields = listE . map buildField   where-    buildField DataField {fieldName, fieldArgs, fieldType = alias@TypeAlias {aliasArgs, aliasWrappers}, fieldMeta} =-      [|( fName+    buildField DataField {fieldName, fieldArgs, fieldType = alias@TypeRef {typeArgs, typeWrappers}, fieldMeta} =+      [|( fieldName         , DataField-            { fieldName = fName+            { fieldName             , fieldArgs = fArgs             , fieldArgsType = Nothing-            , fieldType = TypeAlias {aliasTyCon = __typeName $(proxyT alias), aliasArgs = aArgs, aliasWrappers}+            , fieldType = TypeRef {typeConName = __typeName $(proxyT alias), typeArgs = aArgs, typeWrappers}             , fieldMeta             })|]       where-        fName = unpack fieldName         fArgs = map (\(k, v) -> (unpack k, v)) fieldArgs-        aArgs = unpack <$> aliasArgs+        aArgs = unpack <$> typeArgs
src/Data/Morpheus/Execution/Internal/Declare.hs view
@@ -30,7 +30,7 @@                                                 , DataField(..)                                                 , DataTypeKind(..)                                                 , DataTypeKind(..)-                                                , TypeAlias(..)+                                                , TypeRef(..)                                                 , TypeWrapper(..)                                                 , isOutputObject                                                 , isSubscription@@ -42,16 +42,16 @@  type Arrow = (->) -declareTypeAlias :: Bool -> TypeAlias -> Type-declareTypeAlias isSub TypeAlias { aliasTyCon, aliasWrappers, aliasArgs } =-  wrappedT aliasWrappers+declareTypeRef :: Bool -> TypeRef -> Type+declareTypeRef isSub TypeRef { typeConName, typeWrappers, typeArgs } =+  wrappedT typeWrappers  where   wrappedT :: [TypeWrapper] -> Type   wrappedT (TypeList  : xs) = AppT (ConT ''[]) $ wrappedT xs   wrappedT (TypeMaybe : xs) = AppT (ConT ''Maybe) $ wrappedT xs-  wrappedT []               = decType aliasArgs+  wrappedT []               = decType typeArgs   -------------------------------------------------------  typeName = ConT (mkName $ unpack aliasTyCon)+  typeName = ConT (mkName $ unpack typeConName)   --------------------------------------------   decType _ | isSub =     AppT typeName (AppT (ConT ''UnSubResolver) (VarT $ mkName "m"))@@ -98,4 +98,4 @@           | isResolver                       = AppT monadVar result           | otherwise                        = result         -------------------------------------------------        result = declareTypeAlias (maybe False isSubscription kindD) fieldType+        result = declareTypeRef (maybe False isSubscription kindD) fieldType
src/Data/Morpheus/Execution/Internal/Decode.hs view
@@ -13,7 +13,6 @@   ) where -import           Data.Semigroup                 ( (<>) ) import           Data.Text                      ( unpack ) import           Language.Haskell.TH            ( ExpQ                                                 , conE@@ -23,17 +22,20 @@                                                 )  -- MORPHEUS-import           Data.Morpheus.Error.Internal   ( internalArgumentError-                                                , internalTypeMismatch+import           Data.Morpheus.Error.Internal   ( +                                                internalTypeMismatch                                                 ) import           Data.Morpheus.Types.Internal.AST                                                 ( DataField(..)                                                 , Key                                                 , ConsD(..) -                                                , Object-                                                , Value(..))+                                                , ValidObject+                                                , Value(..)+                                                , ValidValue+                                                , Message+                                                ) import           Data.Morpheus.Types.Internal.Resolving-                                                ( Validation )+                                                ( Validation, Failure(..) )   decodeObjectExpQ :: ExpQ -> ConsD -> ExpQ@@ -52,32 +54,31 @@                                                [|fName|]       where fName = unpack fieldName -withObject :: (Object -> Validation a) -> Value -> Validation a+withObject :: (ValidObject -> Validation a) -> ValidValue -> Validation a withObject f (Object object) = f object withObject _ isType          = internalTypeMismatch "Object" isType -withMaybe :: Monad m => (Value -> m a) -> Value -> m (Maybe a)+withMaybe :: Monad m => (ValidValue -> m a) -> ValidValue -> m (Maybe a) withMaybe _      Null = pure Nothing withMaybe decode x    = Just <$> decode x -withList :: (Value -> Validation a) -> Value -> Validation [a]+withList :: (ValidValue -> Validation a) -> ValidValue -> Validation [a] withList decode (List li) = mapM decode li withList _      isType    = internalTypeMismatch "List" isType -withEnum :: (Key -> Validation a) -> Value -> Validation a+withEnum :: (Key -> Validation a) -> ValidValue -> Validation a withEnum decode (Enum value) = decode value withEnum _      isType       = internalTypeMismatch "Enum" isType -withUnion :: (Key -> Object -> Object -> Validation a) -> Object -> Validation a-withUnion decoder unions = case lookup "tag" unions of+withUnion :: (Key -> ValidObject -> ValidObject -> Validation a) -> ValidObject -> Validation a+withUnion decoder unions = case lookup "__typename" unions of   Just (Enum key) -> case lookup key unions of-    Nothing -> internalArgumentError-      ("type \"" <> key <> "\" was not provided on object")+    Nothing -> withObject (decoder key unions) (Object [])     Just value -> withObject (decoder key unions) value-  Just _  -> internalArgumentError "tag must be Enum"-  Nothing -> internalArgumentError "tag not found on Input Union"+  Just _  -> failure ("__typename must be Enum" :: Message)+  Nothing -> failure ("__typename not found on Input Union" :: Message) -decodeFieldWith :: (Value -> Validation a) -> Key -> Object -> Validation a+decodeFieldWith :: (ValidValue -> Validation a) -> Key -> ValidObject -> Validation a decodeFieldWith decoder name object = case lookup name object of-  Nothing    -> internalArgumentError ("Missing Field: \"" <> name <> "\"")+  Nothing    -> decoder Null   Just value -> decoder value
src/Data/Morpheus/Execution/Server/Decode.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE NamedFieldPuns        #-} {-# LANGUAGE ConstraintKinds       #-} {-# LANGUAGE DataKinds             #-} {-# LANGUAGE FlexibleContexts      #-}@@ -9,57 +10,67 @@ {-# LANGUAGE TypeFamilies          #-} {-# LANGUAGE TypeOperators         #-} {-# LANGUAGE UndecidableInstances  #-}+{-# LANGUAGE TupleSections         #-}  module Data.Morpheus.Execution.Server.Decode   ( decodeArguments   , Decode(..)-  , DecodeObject(..)+  , DecodeType(..)   ) where  import           Data.Proxy                     ( Proxy(..) )-import           Data.Semigroup                 ( (<>) )+import           Data.Semigroup                 ( Semigroup(..) ) import           Data.Text                      ( pack ) import           GHC.Generics  -- MORPHEUS-import           Data.Morpheus.Error.Internal   ( internalArgumentError-                                                , internalTypeMismatch+import           Data.Morpheus.Error.Internal   ( internalTypeMismatch+                                                , internalError                                                 ) import           Data.Morpheus.Execution.Internal.Decode                                                 ( decodeFieldWith-                                                , withEnum                                                 , withList                                                 , withMaybe                                                 , withObject                                                 , withUnion                                                 )-import           Data.Morpheus.Execution.Server.Generics.EnumRep-                                                ( EnumRep(..) ) import           Data.Morpheus.Kind             ( ENUM                                                 , GQL_KIND-                                                , INPUT_OBJECT-                                                , INPUT_UNION                                                 , SCALAR+                                                , OUTPUT+                                                , INPUT                                                 ) import           Data.Morpheus.Types.GQLScalar  ( GQLScalar(..)                                                 , toScalar                                                 ) import           Data.Morpheus.Types.GQLType    ( GQLType(KIND, __typeName) ) import           Data.Morpheus.Types.Internal.AST-                                                ( Key+                                                ( Name                                                 , Argument(..)-                                                , Arguments-                                                , Object+                                                , ValidArguments+                                                , ValidArgument+                                                , ValidObject                                                 , Value(..)+                                                , ValidValue                                                 ) import           Data.Morpheus.Types.Internal.Resolving-                                                ( Validation )+                                                ( Validation+                                                , Failure(..)+                                                )  +-- GENERIC+decodeArguments :: DecodeType a => ValidArguments -> Validation a+decodeArguments = decodeType . Object . map toObject+ where+  toObject :: (Name, ValidArgument) -> (Name, ValidValue)+  toObject (x, Argument { argumentValue }) = (x, argumentValue)++ -- | Decode GraphQL query arguments and input values class Decode a where-  decode :: Value -> Validation a+  decode :: ValidValue -> Validation a  instance {-# OVERLAPPABLE #-} DecodeKind (KIND a) a => Decode a where   decode = decodeKind (Proxy @(KIND a))@@ -72,7 +83,7 @@  -- | Decode GraphQL type with Specific Kind class DecodeKind (kind :: GQL_KIND) a where-  decodeKind :: Proxy kind -> Value -> Validation a+  decodeKind :: Proxy kind -> ValidValue -> Validation a  -- SCALAR instance (GQLScalar a) => DecodeKind SCALAR a where@@ -81,74 +92,140 @@     Left  errorMessage -> internalTypeMismatch errorMessage value  -- ENUM-instance (Generic a, EnumRep (Rep a)) => DecodeKind ENUM a where-  decodeKind _ = withEnum (fmap to . decodeEnum)+instance DecodeType a => DecodeKind ENUM a where+  decodeKind _ = decodeType --- INPUT_OBJECT-instance DecodeObject a => DecodeKind INPUT_OBJECT a where-  decodeKind _ = withObject decodeObject+-- TODO: remove  +instance DecodeType a => DecodeKind OUTPUT a where+  decodeKind _ = decodeType --- INPUT_UNION-instance (Generic a, GDecode (Rep a)) => DecodeKind INPUT_UNION a where-  decodeKind _ = withObject (fmap to . decodeUnion)+-- INPUT_OBJECT and  INPUT_UNION+instance DecodeType a => DecodeKind INPUT a where+  decodeKind _ = decodeType --- GENERIC-decodeArguments :: DecodeObject p => Arguments -> Validation p-decodeArguments = decodeObject . fmap toObject-  where toObject (x, y) = (x, argumentValue y) -class DecodeObject a where-  decodeObject :: Object -> Validation a+class DecodeType a where+  decodeType :: ValidValue -> Validation a -instance {-# OVERLAPPABLE #-} (Generic a, GDecode (Rep a)) => DecodeObject a where-  decodeObject = fmap to . __decodeObject . Object+instance {-# OVERLAPPABLE #-} (Generic a, DecodeRep (Rep a))=> DecodeType a where+  decodeType = fmap to . decodeRep . (, Cont D_CONS "") +-- data Inpuz  =+--    InputHuman Human  -- direct link: { __typename: Human, Human: {field: ""} }+--   | InputRecord { name :: Text, age :: Int } -- { __typename: InputRecord, InputRecord: {field: ""} }+--   | IndexedType Int Text  -- { __typename: InputRecord, _0:2 , _1:""  }+--   | Zeus                 -- { __typename: Zeus }+--     deriving (Generic, GQLType)++decideUnion+  :: ([Name], value -> Validation (f1 a))+  -> ([Name], value -> Validation (f2 a))+  -> Name+  -> value+  -> Validation ((:+:) f1 f2 a)+decideUnion (left, f1) (right, f2) name value+  | name `elem` left+  = L1 <$> f1 value+  | name `elem` right+  = R1 <$> f2 value+  | otherwise+  = failure $ "Constructor \"" <> name <> "\" could not find in Union"++data Tag = D_CONS | D_UNION deriving (Eq ,Ord)++data Cont = Cont {+  contKind:: Tag,+  typeName :: Name+}++data Info = Info {+  kind :: Tag,+  tagName :: [Name]+}++instance Semigroup Info where+  Info D_UNION t1 <> Info _       t2 = Info D_UNION (t1 <> t2)+  Info _       t1 <> Info D_UNION t2 = Info D_UNION (t1 <> t2)+  Info D_CONS  t1 <> Info D_CONS  t2 = Info D_CONS (t1 <> t2)+ -- -- GENERICS ---class GDecode f where-  unionTags :: Proxy f -> [Key]-  decodeUnion :: Object -> Validation (f a)-  __decodeObject :: Value -> Validation (f a)+class DecodeRep f where+  tags :: Proxy f -> Name -> Info+  decodeRep :: (ValidValue,Cont) -> Validation (f a) -instance GDecode U1 where-  unionTags _ = []-  __decodeObject _ = pure U1-  decodeUnion _ = pure U1+instance (Datatype d, DecodeRep f) => DecodeRep (M1 D d f) where+  tags _ = tags (Proxy @f)+  decodeRep (x, y) = M1 <$> decodeRep+    (x, y { typeName = pack $ datatypeName (undefined :: (M1 D d f a)) }) --- Recursive Decoding: (Selector (Rec1 ))-instance (Selector s, GQLType a, Decode a) => GDecode (M1 S s (K1 i a)) where-  unionTags _ = [__typeName (Proxy @a)]-  decodeUnion    = fmap (M1 . K1) . decode . Object-  __decodeObject = fmap (M1 . K1) . decodeRec+getEnumTag :: ValidObject -> Validation Name+getEnumTag [("enum", Enum value)] = pure value+getEnumTag _                      = internalError "bad union enum object"++instance (DecodeRep a, DecodeRep b) => DecodeRep (a :+: b) where+  tags _ = tags (Proxy @a) <> tags (Proxy @b)+  decodeRep = __decode    where-    fieldName = pack $ selName (undefined :: M1 S s f a)-    decodeRec = withObject (decodeFieldWith decode fieldName) -instance (Datatype c, GDecode f) => GDecode (M1 D c f) where-  decodeUnion = fmap M1 . decodeUnion-  unionTags _ = unionTags (Proxy @f)-  __decodeObject = fmap M1 . __decodeObject+    __decode (Object obj, cont) = withUnion handleUnion obj+     where+      handleUnion name unions object+        | name == typeName cont <> "EnumObject"+        = getEnumTag object >>= __decode . (, ctx) . Enum+        | [name] == l1+        = L1 <$> decodeRep (Object object, ctx)+        | [name] == r1+        = R1 <$> decodeRep (Object object, ctx)+        | otherwise+        = decideUnion (l1, decodeRep) (r1, decodeRep) name (Object unions, ctx)+      l1  = tagName l1t+      r1  = tagName r1t+      l1t = tags (Proxy @a) (typeName cont)+      r1t = tags (Proxy @b) (typeName cont)+      ctx = cont { contKind = kind (l1t <> r1t) }+    __decode (Enum name, cxt) = decideUnion+      (tagName $ tags (Proxy @a) (typeName cxt), decodeRep)+      (tagName $ tags (Proxy @b) (typeName cxt), decodeRep)+      name+      (Enum name, cxt)+    __decode _ = internalError "lists and scalars are not allowed in Union" -instance (Constructor c, GDecode f) => GDecode (M1 C c f) where-  decodeUnion = fmap M1 . decodeUnion-  unionTags _ = unionTags (Proxy @f)-  __decodeObject = fmap M1 . __decodeObject+instance (Constructor c, DecodeFields a) => DecodeRep (M1 C c a) where+  decodeRep = fmap M1 . decodeFields+  tags _ baseName = getTag (refType (Proxy @a))+   where+    getTag (Just memberRef)+      | isUnionRef memberRef = Info { kind = D_UNION, tagName = [memberRef] }+      | otherwise            = Info { kind = D_CONS, tagName = [consName] }+    getTag Nothing = Info { kind = D_CONS, tagName = [consName] }+    --------+    consName = pack $ conName unsafeType+    ----------+    isUnionRef x = baseName <> x == consName+    --------------------------+    unsafeType :: (M1 C c U1 x)+    unsafeType = undefined -instance (GDecode f, GDecode g) => GDecode (f :*: g) where-  __decodeObject gql = (:*:) <$> __decodeObject gql <*> __decodeObject gql+class DecodeFields f where+  refType :: Proxy f -> Maybe Name+  decodeFields :: (ValidValue,Cont) -> Validation (f a) -instance (GDecode a, GDecode b) => GDecode (a :+: b) where-  decodeUnion = withUnion handleUnion+instance (DecodeFields f, DecodeFields g) => DecodeFields (f :*: g) where+  refType _ = Nothing+  decodeFields gql = (:*:) <$> decodeFields gql <*> decodeFields gql++instance (Selector s, GQLType a, Decode a) => DecodeFields (M1 S s (K1 i a)) where+  refType _ = Just $ __typeName (Proxy @a)+  decodeFields (value, Cont { contKind })+    | contKind == D_UNION = M1 . K1 <$> decode value+    | otherwise           = __decode value    where-    handleUnion name unions object-      | [name] == l1Tags = L1 <$> decodeUnion object-      | [name] == r1Tags = R1 <$> decodeUnion object-      | name `elem` l1Tags = L1 <$> decodeUnion unions-      | name `elem` r1Tags = R1 <$> decodeUnion unions-      | otherwise = internalArgumentError-        ("type \"" <> name <> "\" could not find in union")-     where-      l1Tags = unionTags $ Proxy @a-      r1Tags = unionTags $ Proxy @b-  unionTags _ = unionTags (Proxy @a) ++ unionTags (Proxy @b)+    __decode  = fmap (M1 . K1) . decodeRec+    fieldName = pack $ selName (undefined :: M1 S s f a)+    decodeRec = withObject (decodeFieldWith decode fieldName)++instance DecodeFields U1 where+  refType _ = Nothing+  decodeFields _ = pure U1
src/Data/Morpheus/Execution/Server/Encode.hs view
@@ -13,12 +13,11 @@  module Data.Morpheus.Execution.Server.Encode   ( EncodeCon-  , GResolver(..)   , Encode(..)   , encodeQuery   , encodeSubscription   , encodeMutation-  , ObjectResolvers(..)+  , ExploreResolvers(..)   ) where @@ -35,45 +34,41 @@ import           GHC.Generics  -- MORPHEUS-import           Data.Morpheus.Error.Internal   ( internalUnknownTypeMessage )+import           Data.Morpheus.Error.Internal   ( internalResolvingError ) import           Data.Morpheus.Execution.Server.Decode-                                                ( DecodeObject+                                                ( DecodeType                                                 , decodeArguments                                                 ) import           Data.Morpheus.Execution.Server.Generics.EnumRep                                                 ( EnumRep(..) ) import           Data.Morpheus.Kind             ( ENUM                                                 , GQL_KIND-                                                , OBJECT                                                 , ResContext(..)                                                 , SCALAR-                                                , UNION+                                                , OUTPUT                                                 , VContext(..)                                                 )-import           Data.Morpheus.Types.Types     ( MapKind+import           Data.Morpheus.Types.Types      ( MapKind                                                 , Pair(..)                                                 , mapKindFromList                                                 ) import           Data.Morpheus.Types.GQLScalar  ( GQLScalar(..) )-import           Data.Morpheus.Types.GQLType    ( GQLType-                                                  ( CUSTOM-                                                  , KIND-                                                  , __typeName-                                                  )-                                                )+import           Data.Morpheus.Types.GQLType    ( GQLType(..) ) import           Data.Morpheus.Types.Internal.AST-                                                ( Operation(..)+                                                ( Name+                                                , Operation(..)                                                 , ValidOperation-                                                , Key,-                                                  MUTATION+                                                , Key+                                                , MUTATION                                                 , OperationType                                                 , QUERY                                                 , SUBSCRIPTION                                                 , Selection(..)-                                                , SelectionRec(..)+                                                , SelectionContent(..)                                                 , ValidSelection                                                 , GQLValue(..)-                                                , Value(..)+                                                , ValidValue+                                                , ValidSelectionSet                                                 ) import           Data.Morpheus.Types.Internal.Resolving                                                 ( MapStrategy(..)@@ -82,14 +77,18 @@                                                 , resolving                                                 , toResolver                                                 , ResolvingStrategy(..)-                                                , resolveObject                                                 , withObject                                                 , Validation                                                 , failure+                                                , DataResolver(..)+                                                , resolveObject+                                                , resolve__typename+                                                , resolveEnum+                                                , FieldRes                                                 )  class Encode resolver o e (m :: * -> *) where-  encode :: resolver -> (Key, ValidSelection) -> ResolvingStrategy o e m Value+  encode :: resolver -> (Key, ValidSelection) -> ResolvingStrategy o e m ValidValue  instance {-# OVERLAPPABLE #-} (EncodeKind (KIND a) a o e m , LiftEither o ResolvingStrategy) => Encode a o e m where   encode resolver = encodeKind (VContext resolver :: VContext (KIND a) a)@@ -116,16 +115,19 @@   encode list query = gqlList <$> traverse (`encode` query) list  --  GQL a -> Resolver b, MUTATION, SUBSCRIPTION, QUERY-instance (DecodeObject a, Monad m,LiftEither fo Resolver, MapStrategy fo o, Encode b fo e m) => Encode (a -> Resolver fo e m b) o e m where+instance (DecodeType a,Generic a, Monad m,LiftEither fo Resolver, MapStrategy fo o, Encode b fo e m) => Encode (a -> Resolver fo e m b) o e m where   encode resolver selection@(_, Selection { selectionArguments }) =     mapStrategy $ resolving encode (toResolver args resolver) selection    where     args :: Validation a     args = decodeArguments selectionArguments +++ -- ENCODE GQL KIND class EncodeKind (kind :: GQL_KIND) a o e (m :: * -> *) where-  encodeKind :: LiftEither o ResolvingStrategy =>  VContext kind a -> (Key, ValidSelection) -> ResolvingStrategy o e m Value+  encodeKind :: LiftEither o ResolvingStrategy =>  VContext kind a -> (Key, ValidSelection) -> ResolvingStrategy o e m ValidValue  -- SCALAR instance (GQLScalar a, Monad m) => EncodeKind SCALAR a o e m where@@ -135,87 +137,83 @@ instance (Generic a, EnumRep (Rep a), Monad m) => EncodeKind ENUM a o e m where   encodeKind = pure . pure . gqlString . encodeRep . from . unVContext ---  OBJECT-instance (Monad m, EncodeCon o e m a, Monad m, GResolver OBJECT (Rep a) o e m) => EncodeKind OBJECT a o e m where-  encodeKind (VContext value) = withObject encodeK+instance (Monad m,Generic a, GQLType a,ExploreResolvers (CUSTOM a) a o e m) => EncodeKind OUTPUT a o e m where+  encodeKind (VContext value) (key, sel@Selection { selectionContent }) =+    encodeNode (exploreResolvers (Proxy @(CUSTOM a)) value) selectionContent    where-    encodeK selection = resolveObject-      selection-      (__typenameResolver : objectResolvers (Proxy :: Proxy (CUSTOM a)) value)-    __typenameResolver =-      ("__typename", const $ pure $ gqlString $ __typeName (Proxy @a))+    encodeNode (ObjectRes fields) _ = withObject encodeObject (key, sel)+     where+      encodeObject selection =+        resolveObject selection+          $ ObjectRes+          $ resolve__typename (__typeName (Proxy @a))+          : fields+    encodeNode (EnumRes enum) _ =+      resolveEnum (__typeName (Proxy @a)) enum selectionContent+    -- Type References --------------------------------------------------------------+    encodeNode (UnionRef (fieldTypeName, fieldResolver)) (UnionSelection selections)+      = fieldResolver+        (key, sel { selectionContent = SelectionSet currentSelection })+      where currentSelection = pickSelection fieldTypeName selections+    -- RECORDS ----------------------------------------------------------------------------+    encodeNode (UnionRes (name, fields)) (UnionSelection selections) =+      resolveObject selection resolvers+     where+      selection = pickSelection name selections+      resolvers = ObjectRes (resolve__typename name : fields)+    encodeNode _ _ = failure $ internalResolvingError+      "union Resolver should only recieve UnionSelection" --- exploreKindChannels--- UNION-instance (Monad m, GQL_RES a, GResolver UNION (Rep a) o e m) => EncodeKind UNION a o e m where-  encodeKind (VContext value) (key, sel@Selection { selectionRec = UnionSelection selections })-    = resolver (key, sel { selectionRec = SelectionSet lookupSelection })++convertNode+  :: (Monad m, LiftEither o ResolvingStrategy)+  => ResNode o e m+  -> DataResolver o e m+convertNode ResNode { resKind = REP_OBJECT, resFields } =+  ObjectRes $ map toFieldRes resFields+convertNode ResNode { resDatatypeName, resKind = REP_UNION, resFields, resTypeName, isResRecord }+  = encodeUnion resFields+ where+  -- ENUM+  encodeUnion [] = EnumRes resTypeName+  -- Type References --------------------------------------------------------------+  encodeUnion [FieldNode { fieldTypeName, fieldResolver, isFieldObject }]+    | isFieldObject && resTypeName == resDatatypeName <> fieldTypeName+    = UnionRef (fieldTypeName, fieldResolver)+  -- RECORDS ----------------------------------------------------------------------------+  encodeUnion fields = UnionRes+    (resTypeName, resolve__typename resTypeName : map toFieldRes resolvers)    where-    lookupSelection      = fromMaybe [] $ lookup typeName selections-    (typeName, resolver) = unionResolver value-  encodeKind _ _ = failure $ internalUnknownTypeMessage-    "union Resolver only should recieve UnionSelection"+    resolvers | isResRecord = fields+              | otherwise   = setFieldNames fields  -- Types & Constrains ------------------------------------------------------- type GQL_RES a = (Generic a, GQLType a)  type EncodeOperator o e m a-  = a -> ValidOperation -> ResolvingStrategy o e m Value+  = a -> ValidOperation -> ResolvingStrategy o e m ValidValue -type EncodeCon o e m a = (GQL_RES a, ObjectResolvers (CUSTOM a) a o e m)+type EncodeCon o e m a = (GQL_RES a, ExploreResolvers (CUSTOM a) a o e m) -type FieldRes o e m-  = (Key, (Key, ValidSelection) -> ResolvingStrategy o e m Value) -type family GRes (kind :: GQL_KIND) value :: *+objectResolvers+  :: forall custom a o e m+   . ExploreResolvers custom a o e m+  => Proxy custom+  -> a+  -> DataResolver o e m+objectResolvers isCustom value = case exploreResolvers isCustom value of+  ObjectRes resFields -> ObjectRes resFields+  _                   -> InvalidRes "resolver must be an object" -type instance GRes OBJECT v = [(Key, (Key, ValidSelection) -> v)] -type instance GRes UNION v = (Key, (Key, ValidSelection) -> v)- --- GENERICS -------------------------------------------------class ObjectResolvers (custom :: Bool) a (o :: OperationType) e (m :: * -> *) where-  objectResolvers :: Proxy custom -> a -> [(Key, (Key, ValidSelection) -> ResolvingStrategy o e m Value)]--instance (Generic a, GResolver OBJECT (Rep a) o e m ) => ObjectResolvers 'False a o e m where-  objectResolvers _ =-    getResolvers (ResContext :: ResContext OBJECT o e m value) . from--unionResolver-  :: (Generic a, GResolver UNION (Rep a) o e m)-  => a-  -> (Key, (Key, ValidSelection) -> ResolvingStrategy o e m Value)-unionResolver =-  getResolvers (ResContext :: ResContext UNION o e m value) . from---- | Derives resolvers for OBJECT and UNION-class GResolver (kind :: GQL_KIND) f o e (m :: * -> *) where-  getResolvers :: ResContext kind o e m value -> f a -> GRes kind (ResolvingStrategy o e m Value)--instance GResolver kind f o e m => GResolver kind (M1 D c f) o e m where-  getResolvers context (M1 src) = getResolvers context src--instance GResolver kind f o e m => GResolver kind (M1 C c f) o e m where-  getResolvers context (M1 src) = getResolvers context src---- OBJECT-instance GResolver OBJECT U1 o e m where-  getResolvers _ _ = []--instance (Selector s, GQLType a, Encode a o e m) => GResolver OBJECT (M1 S s (K1 s2 a)) o e m where-  getResolvers _ m@(M1 (K1 src)) = [(pack (selName m), encode src)]--instance (GResolver OBJECT f o e m, GResolver OBJECT g o e m) => GResolver OBJECT (f :*: g) o e m where-  getResolvers context (a :*: b) =-    getResolvers context a ++ getResolvers context b---- UNION-instance (Selector s, GQLType a, Encode a o e m ) => GResolver UNION (M1 S s (K1 s2 a)) o e m where-  getResolvers _ (M1 (K1 src)) = (__typeName (Proxy @a), encode src)+class ExploreResolvers (custom :: Bool) a (o :: OperationType) e (m :: * -> *) where+  exploreResolvers :: Proxy custom -> a -> DataResolver o e m -instance (GResolver UNION a o e m, GResolver UNION b o e m) => GResolver UNION (a :+: b) o e m where-  getResolvers context (L1 x) = getResolvers context x-  getResolvers context (R1 x) = getResolvers context x+instance (Generic a,Monad m,LiftEither o ResolvingStrategy,TypeRep (Rep a) o e m ) => ExploreResolvers 'False a o e m where+  exploreResolvers _ value = convertNode+    $ typeResolvers (ResContext :: ResContext OUTPUT o e m value) (from value)  ----- HELPERS ---------------------------- encodeQuery@@ -227,29 +225,107 @@   => schema (Resolver QUERY event m)   -> EncodeOperator QUERY event m query encodeQuery schema = encodeOperationWith-  (objectResolvers (Proxy :: Proxy (CUSTOM (schema (Resolver QUERY event m))))-                   schema+  (Just $ objectResolvers+    (Proxy :: Proxy (CUSTOM (schema (Resolver QUERY event m))))+    schema   )  encodeMutation   :: forall event m mut    . (Monad m, EncodeCon MUTATION event m mut)   => EncodeOperator MUTATION event m mut-encodeMutation = encodeOperationWith []+encodeMutation = encodeOperationWith Nothing  encodeSubscription   :: forall m event mut    . (Monad m, EncodeCon SUBSCRIPTION event m mut)   => EncodeOperator SUBSCRIPTION event m mut-encodeSubscription = encodeOperationWith []+encodeSubscription = encodeOperationWith Nothing  encodeOperationWith   :: forall o e m a    . (Monad m, EncodeCon o e m a, LiftEither o ResolvingStrategy)-  => [FieldRes o e m]+  => Maybe (DataResolver o e m)   -> EncodeOperator o e m a encodeOperationWith externalRes rootResolver Operation { operationSelection } =-  resolveObject operationSelection resolvers+  resolveObject operationSelection (rootDataRes <> extDataRes)  where-  resolvers =-    externalRes <> objectResolvers (Proxy :: Proxy (CUSTOM a)) rootResolver+  rootDataRes = objectResolvers (Proxy :: Proxy (CUSTOM a)) rootResolver+  extDataRes  = fromMaybe (ObjectRes []) externalRes++toFieldRes :: FieldNode o e m -> FieldRes o e m+toFieldRes FieldNode { fieldSelName, fieldResolver } =+  (fieldSelName, fieldResolver)+++-- NEW AUTOMATIC DERIVATION SYSTEM++pickSelection :: Name -> [(Name, ValidSelectionSet)] -> ValidSelectionSet+pickSelection name = fromMaybe [] . lookup name++data REP_KIND = REP_UNION | REP_OBJECT++data ResNode o e m = ResNode {+    resDatatypeName :: Name,+    resTypeName :: Name,+    resKind :: REP_KIND,+    resFields :: [FieldNode o e m],+    isResRecord :: Bool+  }++data FieldNode o e m = FieldNode {+    fieldTypeName :: Name,+    fieldSelName :: Name,+    fieldResolver  :: (Key, ValidSelection) -> ResolvingStrategy o e m ValidValue,+    isFieldObject  :: Bool+  }++-- setFieldNames ::  Power Int Text -> Power { _1 :: Int, _2 :: Text }+setFieldNames :: [FieldNode o e m] -> [FieldNode o e m]+setFieldNames = zipWith setFieldName ([0 ..] :: [Int])+  where setFieldName i field = field { fieldSelName = "_" <> pack (show i) }++class TypeRep f o e (m :: * -> *) where+  typeResolvers :: ResContext OUTPUT o e m value -> f a -> ResNode o e m++instance (Datatype d,TypeRep  f o e m) => TypeRep (M1 D d f) o e m where+  typeResolvers context (M1 src) = (typeResolvers context src)+    { resDatatypeName = pack $ datatypeName (undefined :: M1 D d f a)+    }+++      --- UNION OR OBJECT +instance (TypeRep a o e m,TypeRep b o e m) => TypeRep (a :+: b) o e m where+  typeResolvers context (L1 x) =+    (typeResolvers context x) { resKind = REP_UNION }+  typeResolvers context (R1 x) =+    (typeResolvers context x) { resKind = REP_UNION }++instance (FieldRep f o e m,Constructor c) => TypeRep (M1 C c f) o e m where+  typeResolvers context (M1 src) = ResNode { resDatatypeName = ""+                                           , resTypeName = pack (conName proxy)+                                           , resKind = REP_OBJECT+                                           , resFields = fieldRep context src+                                           , isResRecord = conIsRecord proxy+                                           }+    where proxy = undefined :: (M1 C c U1 x)++      --- FIELDS      +class FieldRep f o e (m :: * -> *) where+        fieldRep :: ResContext OUTPUT o e m value -> f a -> [FieldNode o e m]++instance (FieldRep f o e m, FieldRep g o e m) => FieldRep  (f :*: g) o e m where+  fieldRep context (a :*: b) = fieldRep context a <> fieldRep context b++instance (Selector s, GQLType a, Encode a o e m) => FieldRep (M1 S s (K1 s2 a)) o e m where+  fieldRep _ m@(M1 (K1 src)) =+    [ FieldNode { fieldSelName  = pack (selName m)+                , fieldTypeName = __typeName (Proxy @a)+                , fieldResolver = encode src+                , isFieldObject = isObjectKind (Proxy @a)+                }+    ]++instance FieldRep U1 o e m where+  fieldRep _ _ = []+
src/Data/Morpheus/Execution/Server/Interpreter.hs view
@@ -24,6 +24,7 @@ import           Data.Text.Lazy.Encoding        ( decodeUtf8                                                 , encodeUtf8                                                 )+import           Control.Monad.IO.Class         ( MonadIO() )  -- MORPHEUS import           Data.Morpheus.Execution.Server.Resolve@@ -96,18 +97,18 @@ -} type WSPub m e a = GQLState m e -> a -> m a -instance Interpreter (WSPub IO e LB.ByteString) IO e where+instance MonadIO m => Interpreter (WSPub m e LB.ByteString) m e where   interpreter root state = statefulResolver state (coreResolver root) -instance Interpreter (WSPub IO e  LT.Text) IO e where+instance MonadIO m => Interpreter (WSPub m e  LT.Text) m e where   interpreter root state request =     decodeUtf8 <$> interpreter root state (encodeUtf8 request) -instance Interpreter (WSPub IO e  ByteString) IO e where+instance MonadIO m => Interpreter (WSPub m e  ByteString) m e where   interpreter root state request =     LB.toStrict <$> interpreter root state (LB.fromStrict request) -instance Interpreter (WSPub IO e  Text) IO e  where+instance MonadIO m => Interpreter (WSPub m e  Text) m e  where   interpreter root state request =     LT.toStrict <$> interpreter root state (LT.fromStrict request) 
src/Data/Morpheus/Execution/Server/Introspect.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE TupleSections #-} {-# LANGUAGE ConstraintKinds       #-} {-# LANGUAGE DataKinds             #-} {-# LANGUAGE DefaultSignatures     #-}@@ -17,10 +18,12 @@ module Data.Morpheus.Execution.Server.Introspect   ( TypeUpdater   , Introspect(..)-  , ObjectFields(..)+  , IntrospectRep(..)   , IntroCon   , updateLib   , buildType+  , objectFields+  , TypeScope(..)   ) where @@ -31,21 +34,22 @@                                                 , pack                                                 ) import           GHC.Generics+import           Data.Semigroup                 ( (<>) )+import           Data.List                      ( partition )  -- MORPHEUS+import           Data.Morpheus.Error.Utils      ( globalErrorMessage ) import           Data.Morpheus.Error.Schema     ( nameCollisionError ) import           Data.Morpheus.Execution.Server.Generics.EnumRep                                                 ( EnumRep(..) ) import           Data.Morpheus.Kind             ( Context(..)                                                 , ENUM                                                 , GQL_KIND-                                                , INPUT_OBJECT-                                                , INPUT_UNION-                                                , OBJECT                                                 , SCALAR-                                                , UNION+                                                , OUTPUT+                                                , INPUT                                                 )-import           Data.Morpheus.Types.Types     ( MapKind+import           Data.Morpheus.Types.Types      ( MapKind                                                 , Pair                                                 ) import           Data.Morpheus.Types.GQLScalar  ( GQLScalar(..) )@@ -55,10 +59,11 @@                                                 , resolveUpdates                                                 ) import           Data.Morpheus.Types.Internal.AST-                                                ( DataArguments+                                                ( Name+                                                , DataArguments                                                 , Meta(..)                                                 , DataField(..)-                                                , DataTyCon(..)+                                                , DataTypeContent(..)                                                 , DataType(..)                                                 , Key                                                 , createAlias@@ -68,13 +73,21 @@                                                 , toNullableField                                                 , createEnumValue                                                 , TypeUpdater+                                                , DataFingerprint(..)+                                                , DataUnion+                                                , DataObject+                                                , TypeRef(..)                                                 )  -type IntroCon a = (GQLType a, ObjectFields (CUSTOM a) a)+type IntroCon a = (GQLType a, IntrospectRep (CUSTOM a) a) + -- |  Generates internal GraphQL Schema for query validation and introspection rendering class Introspect a where+  isObject :: proxy a -> Bool+  default isObject :: GQLType a => proxy a -> Bool+  isObject _ = isObjectKind (Proxy @a)   field :: proxy a -> Text -> DataField   introspect :: proxy a -> TypeUpdater   -----------------------------------------------@@ -87,39 +100,50 @@  -- Maybe instance Introspect a => Introspect (Maybe a) where+  isObject _ = False   field _ = toNullableField . field (Proxy @a)   introspect _ = introspect (Proxy @a)  -- List instance Introspect a => Introspect [a] where+  isObject _ = False   field _ = toListField . field (Proxy @a)   introspect _ = introspect (Proxy @a)  -- Tuple instance Introspect (Pair k v) => Introspect (k, v) where+  isObject _ = True   field _ = field (Proxy @(Pair k v))   introspect _ = introspect (Proxy @(Pair k v))  -- Set instance Introspect [a] => Introspect (Set a) where+  isObject _ = False   field _ = field (Proxy @[a])   introspect _ = introspect (Proxy @[a])  -- Map instance Introspect (MapKind k v Maybe) => Introspect (Map k v) where+  isObject _ = True   field _ = field (Proxy @(MapKind k v Maybe))   introspect _ = introspect (Proxy @(MapKind k v Maybe))  -- Resolver : a -> Resolver b-instance (ObjectFields 'False a, Introspect b) => Introspect (a -> m b) where-  field _ name = (field (Proxy @b) name)-    { fieldArgs = fst $ objectFields (Proxy :: Proxy 'False) (Proxy @a)-    }+instance (GQLType b, IntrospectRep 'False a, Introspect b) => Introspect (a -> m b) where+  isObject _ = False+  field _ name = fieldObj { fieldArgs }+   where+    fieldObj  = field (Proxy @b) name+    fieldArgs = fst $ objectFields+      (Proxy :: Proxy 'False)+      (__typeName (Proxy @b), OutputType, Proxy @a)   introspect _ typeLib = resolveUpdates typeLib-                                        (introspect (Proxy @b) : argTypes)+                                        (introspect (Proxy @b) : inputs)    where-    argTypes :: [TypeUpdater]-    argTypes = snd $ objectFields (Proxy :: Proxy 'False) (Proxy @a)+    name = "Arguments for " <> __typeName (Proxy @b)+    inputs :: [TypeUpdater]+    inputs =+      snd $ objectFields (Proxy :: Proxy 'False) (name, InputType, Proxy @a)  -- | Introspect With specific Kind: 'kind': object, scalar, enum ... class IntrospectKind (kind :: GQL_KIND) a where@@ -128,102 +152,66 @@ -- SCALAR instance (GQLType a, GQLScalar a) => IntrospectKind SCALAR a where   introspectKind _ = updateLib scalarType [] (Proxy @a)-    where scalarType = DataScalar . buildType (scalarValidator (Proxy @a))+    where scalarType = buildType $ DataScalar $ scalarValidator (Proxy @a)  -- ENUM instance (GQL_TYPE a, EnumRep (Rep a)) => IntrospectKind ENUM a where   introspectKind _ = updateLib enumType [] (Proxy @a)    where     enumType =-      DataEnum . buildType (map createEnumValue $ enumTags (Proxy @(Rep a)))---- INPUT_OBJECT-instance (GQL_TYPE a, ObjectFields (CUSTOM a) a) => IntrospectKind INPUT_OBJECT a where-  introspectKind _ = updateLib (DataInputObject . buildType fields)-                               types-                               (Proxy @a)-    where (fields, types) = objectFields (Proxy @(CUSTOM a)) (Proxy @a)---- OBJECTS-instance (GQL_TYPE a, ObjectFields (CUSTOM a) a) => IntrospectKind OBJECT a where-  introspectKind _ = updateLib (DataObject . buildType (__typename : fields))-                               types-                               (Proxy @a)-   where-    __typename =-      ( "__typename"-      , DataField { fieldName     = "__typename"-                  , fieldArgs     = []-                  , fieldArgsType = Nothing-                  , fieldType     = createAlias "String"-                  , fieldMeta     = Nothing-                  }-      )-    (fields, types) = objectFields (Proxy @(CUSTOM a)) (Proxy @a)+      buildType $ DataEnum $ map createEnumValue $ enumTags (Proxy @(Rep a)) --- UNION-instance (GQL_TYPE a, GQLRep UNION (Rep a)) => IntrospectKind UNION a where-  introspectKind _ = updateLib (DataUnion . buildType memberTypes)-                               stack-                               (Proxy @a)-   where-    (memberTypes, stack) = unzip $ gqlRep (Context :: Context UNION (Rep a))+instance (GQL_TYPE a, IntrospectRep (CUSTOM a) a) => IntrospectKind INPUT a where+  introspectKind _ = derivingData (Proxy @a) InputType --- INPUT_UNION-instance (GQL_TYPE a, GQLRep UNION (Rep a)) => IntrospectKind INPUT_UNION a where-  introspectKind _ = updateLib (DataInputUnion . buildType memberTypes)-                               stack-                               (Proxy @a)-   where-    (memberTypes, stack) = unzip $ gqlRep (Context :: Context UNION (Rep a))+instance (GQL_TYPE a, IntrospectRep (CUSTOM a) a) => IntrospectKind OUTPUT a where+  introspectKind _ = derivingData (Proxy @a) OutputType --- Types+derivingData+  :: forall a+   . (GQLType a, IntrospectRep (CUSTOM a) a)+  => Proxy a+  -> TypeScope+  -> TypeUpdater+derivingData _ scope = updateLib (buildType datatypeContent) updates (Proxy @a)+ where+  (datatypeContent, updates) = introspectRep+    (Proxy @(CUSTOM a))+    (Proxy @a, scope, baseName, baseFingerprint)+  baseName        = __typeName (Proxy @a)+  baseFingerprint = __typeFingerprint (Proxy @a)  type GQL_TYPE a = (Generic a, GQLType a) --- Object Fields-class ObjectFields (custom :: Bool) a where-  objectFields :: proxy1 custom -> proxy2 a -> ([(Text, DataField)], [TypeUpdater]) -instance GQLRep OBJECT (Rep a) => ObjectFields 'False a where-  objectFields _ _ = unzip $ gqlRep (Context :: Context OBJECT (Rep a))--type family GQLRepResult (a :: GQL_KIND) :: *--type instance GQLRepResult OBJECT = (Text, DataField)--type instance GQLRepResult UNION = Key----  GENERIC UNION-class GQLRep (kind :: GQL_KIND) f where-  gqlRep :: Context kind f -> [(GQLRepResult kind, TypeUpdater)]--instance GQLRep kind f => GQLRep kind (M1 D d f) where-  gqlRep _ = gqlRep (Context :: Context kind f)--instance GQLRep kind f => GQLRep kind (M1 C c f) where-  gqlRep _ = gqlRep (Context :: Context kind f)---- | recursion for Object types, both of them : 'UNION' and 'INPUT_UNION'-instance (GQLRep UNION a, GQLRep UNION b) => GQLRep UNION (a :+: b) where-  gqlRep _ =-    gqlRep (Context :: Context UNION a) ++ gqlRep (Context :: Context UNION b)--instance (GQL_TYPE a, Introspect a) => GQLRep UNION (M1 S s (Rec0 a)) where-  gqlRep _ = [(__typeName (Proxy @a), introspect (Proxy @a))]---- | recursion for Object types, both of them : 'INPUT_OBJECT' and 'OBJECT'-instance (GQLRep OBJECT a, GQLRep OBJECT b) => GQLRep OBJECT (a :*: b) where-  gqlRep _ =-    gqlRep (Context :: Context OBJECT a) ++ gqlRep (Context :: Context OBJECT b)--instance (Selector s, Introspect a) => GQLRep OBJECT (M1 S s (Rec0 a)) where-  gqlRep _ = [((name, field (Proxy @a) name), introspect (Proxy @a))]-    where name = pack $ selName (undefined :: M1 S s (Rec0 ()) ())+objectFields+  :: IntrospectRep custom a+  => proxy1 (custom :: Bool)+  -> (Name, TypeScope, proxy2 a)+  -> ([(Name, DataField)], [TypeUpdater])+objectFields p1 (name, scope, proxy) = withObject+  (introspectRep p1 (proxy, scope, "", DataFingerprint "" []))+ where+  withObject (DataObject      x, ts) = (x, ts)+  withObject (DataInputObject x, ts) = (x, ts)+  withObject _ =+    ( []+    , [ const+          $  failure+          $  globalErrorMessage+          $  "invalid schema: "+          <> name+          <> " should have only one nonempty constructor"+      ]+    ) -instance GQLRep OBJECT U1 where-  gqlRep _ = []+-- Object Fields+class IntrospectRep (custom :: Bool) a where+  introspectRep :: proxy1 custom -> ( proxy2 a,TypeScope,Name,DataFingerprint) -> (DataTypeContent, [TypeUpdater]) +instance (TypeRep (Rep a) , Generic a) => IntrospectRep 'False a where+  introspectRep _ (_, scope, name, fing) =+    derivingDataContent (Proxy @a) (name, fing) scope  buildField :: GQLType a => Proxy a -> DataArguments -> Text -> DataField buildField proxy fieldArgs fieldName = DataField@@ -234,14 +222,14 @@   , fieldMeta     = Nothing   } -buildType :: GQLType a => t -> Proxy a -> DataTyCon t-buildType typeData proxy = DataTyCon+buildType :: GQLType a => DataTypeContent -> Proxy a -> DataType+buildType typeContent proxy = DataType   { typeName        = __typeName proxy   , typeFingerprint = __typeFingerprint proxy   , typeMeta        = Just Meta { metaDescription = description proxy                                 , metaDirectives  = []                                 }-  , typeData+  , typeContent   }  updateLib@@ -258,3 +246,258 @@     Just fingerprint' | fingerprint' == __typeFingerprint proxy -> return lib'     -- throw error if 2 different types has same name     Just _ -> failure $ nameCollisionError (__typeName proxy)+++-- NEW AUTOMATIC DERIVATION SYSTEM++data ConsRep =  ConsRep {+  consName :: Key,+  consIsRecord :: Bool,+  consFields :: [FieldRep]+}++data FieldRep = FieldRep {+  fieldTypeName :: Name,+  fieldData :: (Name, DataField),+  fieldTypeUpdater :: TypeUpdater,+  fieldIsObject :: Bool+}++data ResRep = ResRep {+  enumCons :: [Name],+  unionRef :: [Name],+  unionRecordRep :: [ConsRep]+}++isEmpty :: ConsRep -> Bool+isEmpty ConsRep { consFields = [] } = True+isEmpty _                           = False++isUnionRecord :: ConsRep -> Bool+isUnionRecord ConsRep { consIsRecord } = consIsRecord++isUnionRef :: Name -> ConsRep -> Bool+isUnionRef baseName ConsRep { consName, consFields = [FieldRep { fieldIsObject = True, fieldTypeName }] }+  = consName == baseName <> fieldTypeName+isUnionRef _ _ = False++setFieldNames :: ConsRep -> ConsRep+setFieldNames cons@ConsRep { consFields } = cons+  { consFields = zipWith setFieldName ([0 ..] :: [Int]) consFields+  }+ where+  setFieldName i fieldR@FieldRep { fieldData = (_, fieldD) } = fieldR+    { fieldData = (fieldName, fieldD { fieldName })+    }+    where fieldName = "_" <> pack (show i)++analyseRep :: Name -> [ConsRep] -> ResRep+analyseRep baseName cons = ResRep+  { enumCons       = map consName enumRep+  , unionRef       = map fieldTypeName $ concatMap consFields unionRefRep+  , unionRecordRep = unionRecordRep <> map setFieldNames anyonimousUnionRep+  }+ where+  (enumRep       , left1             ) = partition isEmpty cons+  (unionRefRep   , left2             ) = partition (isUnionRef baseName) left1+  (unionRecordRep, anyonimousUnionRep) = partition isUnionRecord left2++derivingDataContent+  :: forall a+   . (Generic a, TypeRep (Rep a))+  => Proxy a+  -> (Name, DataFingerprint)+  -> TypeScope+  -> (DataTypeContent, [TypeUpdater])+derivingDataContent _ (baseName, baseFingerprint) scope =+  builder $ typeRep $ Proxy @(Rep a)+ where+  builder [ConsRep { consFields }] = buildObject scope consFields+  builder cons                     = genericUnion scope cons+   where+    genericUnion InputType = buildInputUnion (baseName, baseFingerprint)+    genericUnion OutputType =+      buildUnionType (baseName, baseFingerprint) DataUnion DataObject+++buildInputUnion+  :: (Name, DataFingerprint) -> [ConsRep] -> (DataTypeContent, [TypeUpdater])+buildInputUnion (baseName, baseFingerprint) cons = datatype+  (analyseRep baseName cons)+ where+  datatype ResRep { unionRef = [], unionRecordRep = [], enumCons } =+    (DataEnum (map createEnumValue enumCons), types)+  datatype ResRep { unionRef, unionRecordRep, enumCons } =+    (DataInputUnion typeMembers, types <> unionTypes)+   where+    typeMembers =+      map (, True) (unionRef <> unionMembers) <> map (, False) enumCons+    (unionMembers, unionTypes) =+      buildUnions DataInputObject baseFingerprint unionRecordRep+  types = map fieldTypeUpdater $ concatMap consFields cons++buildUnionType+  :: (Name, DataFingerprint)+  -> (DataUnion -> DataTypeContent)+  -> (DataObject -> DataTypeContent)+  -> [ConsRep]+  -> (DataTypeContent, [TypeUpdater])+buildUnionType (baseName, baseFingerprint) wrapUnion wrapObject cons = datatype+  (analyseRep baseName cons)+ where+  datatype ResRep { unionRef = [], unionRecordRep = [], enumCons } =+    (DataEnum (map createEnumValue enumCons), types)+  datatype ResRep { unionRef, unionRecordRep, enumCons } =+    (wrapUnion typeMembers, types <> enumTypes <> unionTypes)+   where+    typeMembers = unionRef <> enumMembers <> unionMembers+    (enumMembers, enumTypes) =+      buildUnionEnum wrapObject baseName baseFingerprint enumCons+    (unionMembers, unionTypes) =+      buildUnions wrapObject baseFingerprint unionRecordRep+  types = map fieldTypeUpdater $ concatMap consFields cons+++buildObject :: TypeScope -> [FieldRep] -> (DataTypeContent, [TypeUpdater])+buildObject isOutput consFields = (wrap fields, types)+ where+  (fields, types) = buildDataObject consFields+  wrap | isOutput == OutputType = DataObject+       | otherwise              = DataInputObject++buildDataObject :: [FieldRep] -> (DataObject, [TypeUpdater])+buildDataObject consFields = (fields, types)+ where+  fields = map fieldData consFields+  types  = map fieldTypeUpdater consFields++buildUnions+  :: (DataObject -> DataTypeContent)+  -> DataFingerprint+  -> [ConsRep]+  -> ([Name], [TypeUpdater])+buildUnions wrapObject baseFingerprint cons = (members, map buildURecType cons)+ where+  buildURecType consRep = pure . defineType+    (consName consRep, buildUnionRecord wrapObject baseFingerprint consRep)+  members = map consName cons++buildUnionRecord+  :: (DataObject -> DataTypeContent) -> DataFingerprint -> ConsRep -> DataType+buildUnionRecord wrapObject typeFingerprint ConsRep { consName, consFields } =+  DataType { typeName        = consName+           , typeFingerprint+           , typeMeta        = Nothing+           , typeContent     = wrapObject $ genFields consFields+           }++ where+  genFields [FieldRep { fieldData = ("", fData) }] =+    [("value", fData { fieldName = "value" })]+  genFields fields = map uRecField fields+  uRecField FieldRep { fieldData = (fName, fData) } = (fName, fData)+++buildUnionEnum+  :: (DataObject -> DataTypeContent)+  -> Name+  -> DataFingerprint+  -> [Name]+  -> ([Name], [TypeUpdater])+buildUnionEnum wrapObject baseName baseFingerprint enums = (members, updates)+ where+  members | null enums = []+          | otherwise  = [enumTypeWrapperName]+  enumTypeName        = baseName <> "Enum"+  enumTypeWrapperName = enumTypeName <> "Object"+  -------------------------+  updates :: [TypeUpdater]+  updates+    | null enums+    = []+    | otherwise+    = [ buildEnumObject wrapObject+                        enumTypeWrapperName+                        baseFingerprint+                        enumTypeName+      , buildEnum enumTypeName baseFingerprint enums+      ]++buildEnum :: Name -> DataFingerprint -> [Name] -> TypeUpdater+buildEnum typeName typeFingerprint tags = pure . defineType+  ( typeName+  , DataType { typeName+             , typeFingerprint+             , typeMeta        = Nothing+             , typeContent     = DataEnum $ map createEnumValue tags+             }+  )++buildEnumObject+  :: (DataObject -> DataTypeContent)+  -> Name+  -> DataFingerprint+  -> Name+  -> TypeUpdater+buildEnumObject wrapObject typeName typeFingerprint enumTypeName =+  pure . defineType+    ( typeName+    , DataType+      { typeName+      , typeFingerprint+      , typeMeta        = Nothing+      , typeContent     = wrapObject+                            [ ( "enum"+                              , DataField { fieldName     = "enum"+                                          , fieldArgs     = []+                                          , fieldArgsType = Nothing+                                          , fieldType = createAlias enumTypeName+                                          , fieldMeta     = Nothing+                                          }+                              )+                            ]+      }+    )++data TypeScope = InputType | OutputType deriving (Show,Eq,Ord)++--  GENERIC UNION+class TypeRep f where+  typeRep :: Proxy f -> [ConsRep]++instance TypeRep f => TypeRep (M1 D d f) where+  typeRep _ = typeRep (Proxy @f)++-- | recursion for Object types, both of them : 'INPUT_OBJECT' and 'OBJECT'+instance (TypeRep a, TypeRep b) => TypeRep (a :+: b) where+  typeRep _ = typeRep (Proxy @a) <> typeRep (Proxy @b)++instance (ConRep f, Constructor c) => TypeRep (M1 C c f) where+  typeRep _ =+    [ ConsRep { consName     = pack $ conName (undefined :: (M1 C c f a))+              , consFields   = conRep (Proxy @f)+              , consIsRecord = conIsRecord (undefined :: (M1 C c f a))+              }+    ]++class ConRep f where+    conRep :: Proxy f -> [FieldRep]++-- | recursion for Object types, both of them : 'UNION' and 'INPUT_UNION'+instance (ConRep  a, ConRep  b) => ConRep  (a :*: b) where+  conRep _ = conRep (Proxy @a) <> conRep (Proxy @b)++instance (Selector s, Introspect a) => ConRep (M1 S s (Rec0 a)) where+  conRep _ =+    [ FieldRep { fieldTypeName    = typeConName $ fieldType fieldData+               , fieldData        = (name, fieldData)+               , fieldTypeUpdater = introspect (Proxy @a)+               , fieldIsObject    = isObject (Proxy @a)+               }+    ]+   where+    name      = pack $ selName (undefined :: M1 S s (Rec0 ()) ())+    fieldData = field (Proxy @a) name++instance ConRep U1 where+  conRep _ = []
src/Data/Morpheus/Execution/Server/Resolve.hs view
@@ -39,7 +39,8 @@                                                 ) import           Data.Morpheus.Execution.Server.Introspect                                                 ( IntroCon-                                                , ObjectFields(..)+                                                , objectFields+                                                , TypeScope(..)                                                 ) import           Data.Morpheus.Execution.Subscription.ClientRegister                                                 ( GQLState@@ -57,14 +58,17 @@                                                 ( Operation(..)                                                 , ValidOperation                                                 , DataFingerprint(..)-                                                , DataTyCon(..)+                                                , DataTypeContent(..)                                                 , DataTypeLib(..)+                                                , DataType(..)                                                 , MUTATION                                                 , OperationType(..)                                                 , QUERY                                                 , SUBSCRIPTION                                                 , initTypeLib-                                                , Value+                                                , ValidValue+                                                , Name+                                                , DataField                                                 ) import           Data.Morpheus.Types.Internal.Resolving                                                 ( GQLRootResolver(..)@@ -89,7 +93,7 @@ import           Data.Morpheus.Validation.Query.Validation                                                 ( validateRequest ) import           Data.Typeable                  ( Typeable )-+import           Control.Monad.IO.Class         ( MonadIO() )  type EventCon event   = (Eq (StreamChannel event), Typeable event, GQLChannel event)@@ -147,7 +151,7 @@    . (Monad m, RootResCon m event query mut sub)   => GQLRootResolver m event query mut sub   -> GQLRequest-  -> ResponseStream event m Value+  -> ResponseStream event m ValidValue coreResolver root@GQLRootResolver { queryResolver, mutationResolver, subscriptionResolver } request   = validRequest >>= execOperator  where@@ -169,11 +173,11 @@       toResponseRes (encodeSubscription subscriptionResolver operation)  statefulResolver-  :: EventCon event-  => GQLState IO event-  -> (GQLRequest -> ResponseStream event IO Value)+  :: (EventCon event, MonadIO m)+  => GQLState m event+  -> (GQLRequest -> ResponseStream event m ValidValue)   -> L.ByteString-  -> IO L.ByteString+  -> m L.ByteString statefulResolver state streamApi requestText = do   res <- runResultT (decodeNoDup requestText >>= streamApi)   mapM_ execute (unpackEvents res)@@ -182,7 +186,6 @@   execute (Publish updates) = publishUpdates state updates   execute Subscribe{}       = pure () - fullSchema   :: forall proxy m event query mutation subscription    . (IntrospectConstraint m event query mutation subscription)@@ -196,7 +199,7 @@    where     (fields, types) = objectFields       (Proxy @(CUSTOM (query (Resolver QUERY event m))))-      (Proxy @(query (Resolver QUERY event m)))+      ("type for query", OutputType, Proxy @(query (Resolver QUERY event m)))   ------------------------------   mutationSchema lib = resolveUpdates     (lib { mutation = maybeOperator fields "Mutation" })@@ -204,7 +207,10 @@    where     (fields, types) = objectFields       (Proxy @(CUSTOM (mutation (Resolver MUTATION event m))))-      (Proxy @(mutation (Resolver MUTATION event m)))+      ( "type for mutation"+      , OutputType+      , Proxy @(mutation (Resolver MUTATION event m))+      )   ------------------------------   subscriptionSchema lib = resolveUpdates     (lib { subscription = maybeOperator fields "Subscription" })@@ -212,16 +218,20 @@    where     (fields, types) = objectFields       (Proxy @(CUSTOM (subscription (Resolver SUBSCRIPTION event m))))-      (Proxy @(subscription (Resolver SUBSCRIPTION event m)))-   -- maybeOperator :: [a] -> Text -> Maybe (Text, DataTyCon[a])+      ( "type for subscription"+      , OutputType+      , Proxy @(subscription (Resolver SUBSCRIPTION event m))+      )+  maybeOperator :: [(Name, DataField)] -> Name -> Maybe (Name, DataType)   maybeOperator []     = const Nothing   maybeOperator fields = Just . operatorType fields-  -- operatorType :: [a] -> Text -> (Text, DataTyCon[a])-  operatorType typeData typeName =+  -------------------------------------------------+  operatorType :: [(Name, DataField)] -> Name -> (Name, DataType)+  operatorType fields typeName =     ( typeName-    , DataTyCon { typeData-                , typeName-                , typeFingerprint = SystemFingerprint typeName-                , typeMeta        = Nothing-                }+    , DataType { typeContent     = DataObject fields+               , typeName+               , typeFingerprint = DataFingerprint typeName []+               , typeMeta        = Nothing+               }     )
src/Data/Morpheus/Execution/Subscription/ClientRegister.hs view
@@ -13,6 +13,7 @@   ) where +import           Control.Monad.IO.Class         ( MonadIO(liftIO) ) import           Control.Concurrent             ( MVar                                                 , modifyMVar                                                 , modifyMVar_@@ -50,7 +51,7 @@ initGQLState :: IO (GQLState m e) initGQLState = newMVar [] -connectClient :: Connection -> GQLState m e -> IO (GQLClient m e)+connectClient :: MonadIO m => Connection -> GQLState m e -> IO (GQLClient m e) connectClient clientConnection varState' = do   client' <- newClient   modifyMVar_ varState' (addClient client')@@ -70,11 +71,12 @@   removeClient = filter ((/= clientID client) . fst)  updateClientByID-  :: ClientID+  :: MonadIO m =>+     ClientID   -> (GQLClient m e -> GQLClient m e)   -> MVar (ClientRegister m e)-  -> IO ()-updateClientByID id' updateFunc state = modifyMVar_+  -> m ()+updateClientByID id' updateFunc state = liftIO $ modifyMVar_   state   (return . map updateClient)  where@@ -82,9 +84,9 @@   updateClient state'                      = state'  publishUpdates-  :: (Eq (StreamChannel e), GQLChannel e) => GQLState IO e -> e -> IO ()+  :: (Eq (StreamChannel e), GQLChannel e, MonadIO m) => GQLState m e -> e -> m () publishUpdates state event = do-  state' <- readMVar state+  state' <- liftIO $ readMVar state   traverse_ sendMessage state'  where   sendMessage (_, GQLClient { clientSessions = [] }             ) = return ()@@ -92,10 +94,10 @@     __send     (filterByChannels clientSessions)    where-    __send ClientSession { sessionId, sessionSubscription = Event { content = subscriptionRes } }-      = subscriptionRes event-        >>= sendTextData clientConnection-        .   toApolloResponse sessionId+    __send ClientSession { sessionId, sessionSubscription = Event { content = subscriptionRes } } = do+      res <- subscriptionRes event+      let apolloRes = toApolloResponse sessionId res+      liftIO $ sendTextData clientConnection apolloRes     ---------------------------     filterByChannels = filter       ( not@@ -105,7 +107,7 @@       . sessionSubscription       ) -removeClientSubscription :: ClientID -> Text -> GQLState m e -> IO ()+removeClientSubscription :: MonadIO m => ClientID -> Text -> GQLState m e -> m () removeClientSubscription id' sid' = updateClientByID id' stopSubscription  where   stopSubscription client' = client'@@ -113,7 +115,7 @@     }  addClientSubscription-  :: ClientID -> SubEvent m e -> Text -> GQLState m e -> IO ()+  :: MonadIO m => ClientID -> SubEvent m e -> Text -> GQLState m e -> m () addClientSubscription id' sessionSubscription sessionId = updateClientByID   id'   startSubscription
src/Data/Morpheus/Kind.hs view
@@ -11,11 +11,12 @@   , WRAPPER   , UNION   , INPUT_OBJECT-  , INPUT_UNION   , GQL_KIND   , Context(..)   , VContext(..)   , ResContext(..)+  , OUTPUT+  , INPUT   ) where @@ -24,14 +25,11 @@  data GQL_KIND   = SCALAR-  | OBJECT   | ENUM-  | INPUT_OBJECT-  | UNION-  | INPUT_UNION+  | INPUT+  | OUTPUT   | WRAPPER - data ResContext (kind :: GQL_KIND) (operation:: OperationType) event (m :: * -> * )  value = ResContext  --type ObjectConstraint a =@@ -48,20 +46,26 @@ -- | GraphQL Scalar: Int, Float, String, Boolean or any user defined custom Scalar type type SCALAR = 'SCALAR --- | GraphQL Object-type OBJECT = 'OBJECT- -- | GraphQL Enum type ENUM = 'ENUM +-- | GraphQL Arrays , Resolvers and NonNull fields+type WRAPPER = 'WRAPPER++-- | GraphQL Object and union+type OUTPUT = 'OUTPUT++-- | GraphQL input Object and input union+type INPUT = 'INPUT++{-# DEPRECATED INPUT_OBJECT "use more generalised kind: INPUT" #-} -- | GraphQL input Object-type INPUT_OBJECT = 'INPUT_OBJECT+type INPUT_OBJECT = 'INPUT +{-# DEPRECATED UNION "use: deriving(GQLType), INPORTANT: only types with <type constructor name><constructor name> will sustain their form, other union constructors will be wrapped inside an new object" #-} -- | GraphQL Union-type UNION = 'UNION---- | extension for graphQL-type INPUT_UNION = 'INPUT_UNION+type UNION = 'OUTPUT --- | GraphQL Arrays , Resolvers and NonNull fields-type WRAPPER = 'WRAPPER+{-# DEPRECATED OBJECT "use: deriving(GQLType), will be automatically inferred" #-}+-- | GraphQL Object+type OBJECT = 'OUTPUT
src/Data/Morpheus/Parsing/Document/TypeSystem.hs view
@@ -34,7 +34,7 @@ import           Data.Morpheus.Types.Internal.AST                                                 ( DataField                                                 , DataFingerprint(..)-                                                , DataTyCon(..)+                                                , DataTypeContent(..)                                                 , DataType(..)                                                 , DataValidator(..)                                                 , Key@@ -54,12 +54,11 @@   metaDirectives <- optionalDirectives   pure     ( typeName-    , DataScalar DataTyCon-      { typeName-      , typeMeta        = Just Meta { metaDescription, metaDirectives }-      , typeFingerprint = SystemFingerprint typeName-      , typeData        = DataValidator pure-      }+    , DataType { typeName+               , typeMeta        = Just Meta { metaDescription, metaDirectives }+               , typeFingerprint = DataFingerprint typeName []+               , typeContent     = DataScalar $ DataValidator pure+               }     )  -- Objects : https://graphql.github.io/graphql-spec/June2018/#sec-Objects@@ -79,18 +78,18 @@ -- objectTypeDefinition :: Maybe Text -> Parser (Text, RawDataType) objectTypeDefinition metaDescription = label "ObjectTypeDefinition" $ do-  name           <- typDeclaration "type"-  interfaces     <- optionalImplementsInterfaces-  metaDirectives <- optionalDirectives-  fields         <- fieldsDefinition+  implementsName       <- typDeclaration "type"+  implementsInterfaces <- optionalImplementsInterfaces+  metaDirectives       <- optionalDirectives+  fields               <- fieldsDefinition   --------------------------   pure-    ( name-    , Implements interfaces $ DataTyCon-      { typeName        = name-      , typeMeta        = Just Meta { metaDescription, metaDirectives }-      , typeFingerprint = SystemFingerprint name-      , typeData        = fields+    ( implementsName+    , Implements+      { implementsName+      , implementsInterfaces+      , implementsMeta       = Just Meta { metaDescription, metaDirectives }+      , implementsContent    = fields       }     ) @@ -107,20 +106,17 @@ -- interfaceTypeDefinition :: Maybe Text -> Parser (Text, RawDataType) interfaceTypeDefinition metaDescription = label "InterfaceTypeDefinition" $ do-  typeName       <- typDeclaration "interface"+  interfaceName  <- typDeclaration "interface"   metaDirectives <- optionalDirectives   fields         <- fieldsDefinition   pure-    ( typeName-    , Interface DataTyCon-      { typeName-      , typeMeta        = Just Meta { metaDescription, metaDirectives }-      , typeFingerprint = SystemFingerprint typeName-      , typeData        = fields-      }+    ( interfaceName+    , Interface { interfaceName+                , interfaceMeta = Just Meta { metaDescription, metaDirectives }+                , interfaceContent = fields+                }     ) - -- Unions : https://graphql.github.io/graphql-spec/June2018/#sec-Unions -- --  UnionTypeDefinition:@@ -137,12 +133,11 @@   memberTypes    <- unionMemberTypes   pure     ( typeName-    , DataUnion DataTyCon-      { typeName-      , typeMeta        = Just Meta { metaDescription, metaDirectives }-      , typeFingerprint = SystemFingerprint typeName-      , typeData        = memberTypes-      }+    , DataType { typeName+               , typeMeta        = Just Meta { metaDescription, metaDirectives }+               , typeFingerprint = DataFingerprint typeName []+               , typeContent     = DataUnion memberTypes+               }     )   where unionMemberTypes = operator '=' *> parseName `sepBy1` pipeLiteral @@ -164,12 +159,11 @@   enumValuesDefinitions <- setOf enumValueDefinition   pure     ( typeName-    , DataEnum DataTyCon-      { typeName-      , typeMeta        = Just Meta { metaDescription, metaDirectives }-      , typeFingerprint = SystemFingerprint typeName-      , typeData        = enumValuesDefinitions-      }+    , DataType { typeName+               , typeMeta        = Just Meta { metaDescription, metaDirectives }+               , typeFingerprint = DataFingerprint typeName []+               , typeContent     = DataEnum enumValuesDefinitions+               }     )  @@ -189,12 +183,11 @@     fields         <- inputFieldsDefinition     pure       ( typeName-      , DataInputObject DataTyCon-        { typeName-        , typeMeta        = Just Meta { metaDescription, metaDirectives }-        , typeFingerprint = SystemFingerprint typeName-        , typeData        = fields-        }+      , DataType { typeName+                 , typeMeta = Just Meta { metaDescription, metaDirectives }+                 , typeFingerprint = DataFingerprint typeName []+                 , typeContent     = DataInputObject fields+                 }       )  where   inputFieldsDefinition :: Parser [(Key, DataField)]
src/Data/Morpheus/Parsing/Internal/Pattern.hs view
@@ -39,7 +39,6 @@                                                 , Meta(..)                                                 , DataEnumValue(..)                                                 , Name-                                                , TypeAlias(..)                                                 )  @@ -68,21 +67,17 @@     metaDescription <- optDescription     fieldName       <- parseName     litAssignment -- ':'-    (aliasWrappers, aliasTyCon) <- parseType-    _                           <- parseDefaultValue-    metaDirectives              <- optionalDirectives+    fieldType      <- parseType+    _              <- parseDefaultValue+    metaDirectives <- optionalDirectives     pure         ( fieldName-        , DataField-            { fieldArgs     = []-            , fieldArgsType = Nothing-            , fieldName-            , fieldType     = TypeAlias { aliasTyCon-                                        , aliasWrappers-                                        , aliasArgs     = Nothing-                                        }-            , fieldMeta     = Just Meta { metaDescription, metaDirectives }-            }+        , DataField { fieldArgs     = []+                    , fieldArgsType = Nothing+                    , fieldName+                    , fieldType+                    , fieldMeta = Just Meta { metaDescription, metaDirectives }+                    }         )  -- Field Arguments: https://graphql.github.io/graphql-spec/June2018/#sec-Field-Arguments@@ -113,20 +108,16 @@     fieldName       <- parseName     fieldArgs       <- argumentsDefinition     litAssignment -- ':'-    (aliasWrappers, aliasTyCon) <- parseType-    metaDirectives              <- optionalDirectives+    fieldType      <- parseType+    metaDirectives <- optionalDirectives     pure         ( fieldName-        , DataField-            { fieldName-            , fieldArgs-            , fieldArgsType = Nothing-            , fieldType     = TypeAlias { aliasTyCon-                                        , aliasWrappers-                                        , aliasArgs     = Nothing-                                        }-            , fieldMeta     = Just Meta { metaDescription, metaDirectives }-            }+        , DataField { fieldName+                    , fieldArgs+                    , fieldArgsType = Nothing+                    , fieldType+                    , fieldMeta = Just Meta { metaDescription, metaDirectives }+                    }         )  -- Directives : https://graphql.github.io/graphql-spec/June2018/#sec-Language.Directives
src/Data/Morpheus/Parsing/Internal/Terms.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TupleSections     #-} @@ -26,6 +27,7 @@   , keyword   , operator   , optDescription+  , parseNegativeSign   ) where @@ -69,15 +71,21 @@                                                 , Key                                                 , Description                                                 , Name-                                                , TypeWrapper(..)                                                 , toHSWrappers-                                                , convertToHaskellName )+                                                , convertToHaskellName+                                                , Ref(..)+                                                , TypeRef(..)+                                                )   -- Name : https://graphql.github.io/graphql-spec/June2018/#sec-Names -- -- Name :: /[_A-Za-z][_0-9A-Za-z]*/ --++parseNegativeSign :: Parser Bool+parseNegativeSign = (char '-' $> True <* spaceAndComments) <|> pure False+ parseName :: Parser Name parseName = token @@ -121,12 +129,13 @@ -- -- Variable :  $Name ---variable :: Parser (Text, Position)+variable :: Parser Ref variable = label "variable" $ do-  position' <- getLocation-  _         <- char '$'-  varName'  <- token-  return (varName', position')+  refPosition <- getLocation+  _           <- char '$'+  refName     <- token+  spaceAndComments+  pure $ Ref { refName, refPosition }  spaceAndComments1 :: Parser () spaceAndComments1 = space1 *> spaceAndComments@@ -244,8 +253,11 @@   where alias = label "alias" $ token <* char ':' <* spaceAndComments  -parseType :: Parser ([TypeWrapper], Key)+parseType :: Parser TypeRef parseType = do-  (wrappers, fieldType) <- parseWrappedType-  nonNull               <- parseNonNull-  pure (toHSWrappers $ nonNull ++ wrappers, fieldType)+  (wrappers, typeConName) <- parseWrappedType+  nonNull                 <- parseNonNull+  pure TypeRef { typeConName+               , typeArgs     = Nothing+               , typeWrappers = toHSWrappers $ nonNull ++ wrappers+               }
src/Data/Morpheus/Parsing/Internal/Value.hs view
@@ -5,6 +5,7 @@   ( parseValue   , enumValue   , parseDefaultValue+  , parseRawValue   ) where @@ -34,44 +35,38 @@                                                 , setOf                                                 , spaceAndComments                                                 , token+                                                , parseNegativeSign+                                                , variable                                                 ) import           Data.Morpheus.Types.Internal.AST                                                 ( ScalarValue(..)                                                 , Value(..)+                                                , RawValue+                                                , ValidValue                                                 , decodeScientific+                                                , Name+                                                , Value(..)+                                                , ResolvedValue                                                 ) -parseDefaultValue :: Parser (Maybe Value)-parseDefaultValue = optional $ do-  litEquals-  parseValue--parseValue :: Parser Value-parseValue = label "value" $ do-  value <--    valueNull-    <|> booleanValue-    <|> valueNumber-    <|> enumValue-    <|> stringValue-    <|> objectValue-    <|> listValue-  spaceAndComments-  return value--valueNull :: Parser Value+valueNull :: Parser (Value a) valueNull = string "null" $> Null -booleanValue :: Parser Value+booleanValue :: Parser (Value a) booleanValue = boolTrue <|> boolFalse  where   boolTrue  = string "true" $> Scalar (Boolean True)   boolFalse = string "false" $> Scalar (Boolean False) -valueNumber :: Parser Value-valueNumber = Scalar . decodeScientific <$> scientific+valueNumber :: Parser (Value a)+valueNumber = do+  isNegative <- parseNegativeSign+  Scalar . decodeScientific . signedNumber isNegative <$> scientific+ where+  signedNumber isNegative number | isNegative = -number+                                 | otherwise  = number -enumValue :: Parser Value+enumValue :: Parser (Value a) enumValue = do   enum <- Enum <$> token   spaceAndComments@@ -86,18 +81,47 @@   codes        = ['b', 'n', 'f', 'r', 't', '\\', '\"', '/']   escapeChar code replacement = char code >> return replacement -stringValue :: Parser Value+stringValue :: Parser (Value a) stringValue = label "stringValue" $ Scalar . String . pack <$> between   (char '"')   (char '"')   (many escaped) -listValue :: Parser Value-listValue = label "listValue" $ List <$> between++listValue :: Parser a -> Parser [a]+listValue parser = label "listValue" $ between   (char '[' *> spaceAndComments)   (char ']' *> spaceAndComments)-  (parseValue `sepBy` (char ',' *> spaceAndComments))+  (parser `sepBy` (char ',' *> spaceAndComments)) -objectValue :: Parser Value-objectValue = label "objectValue" $ Object <$> setOf entry-  where entry = parseAssignment token parseValue+objectValue :: Show a => Parser a -> Parser [(Name, a)]+objectValue parser = label "objectValue" $ setOf entry+  where entry = parseAssignment token parser++structValue :: Parser (Value a) -> Parser (Value a)+structValue parser =+  label "Value"+    $  (   parsePrimitives+       <|> (Object <$> objectValue parser)+       <|> (List <$> listValue parser)+       )+    <* spaceAndComments++parsePrimitives :: Parser (Value a)+parsePrimitives =+  valueNull <|> booleanValue <|> valueNumber <|> enumValue <|> stringValue++parseDefaultValue :: Parser (Maybe ResolvedValue)+parseDefaultValue = optional $ do+  litEquals+  parseV+ where+  parseV :: Parser ResolvedValue+  parseV = structValue parseV+++parseValue :: Parser ValidValue+parseValue = structValue parseValue++parseRawValue :: Parser RawValue+parseRawValue = (VariableValue <$> variable) <|> structValue parseRawValue
src/Data/Morpheus/Parsing/JSONSchema/Parse.hs view
@@ -24,6 +24,7 @@ import           Data.Morpheus.Types.Internal.AST                                                 ( DataField                                                 , DataType(..)+                                                , DataTypeContent(..)                                                 , DataTypeLib                                                 , DataTypeWrapper(..)                                                 , Key@@ -70,11 +71,11 @@   parse Type { name = Just typeName, kind = INPUT_OBJECT, inputFields = Just iFields }     = do       fields <- traverse parse iFields-      pure [(typeName, DataInputObject $ createType typeName fields)]+      pure [(typeName, createType typeName $ DataInputObject fields)]   parse Type { name = Just typeName, kind = OBJECT, fields = Just oFields } =     do       fields <- traverse parse oFields-      pure [(typeName, DataObject $ createType typeName fields)]+      pure [(typeName, createType typeName $ DataObject  fields)]   parse _ = pure []  instance ParseJSONSchema Field (Key,DataField) where
src/Data/Morpheus/Parsing/Request/Arguments.hs view
@@ -5,9 +5,7 @@   ) where -import           Text.Megaparsec                ( label-                                                , (<|>)-                                                )+import           Text.Megaparsec                ( label)  -- MORPHEUS import           Data.Morpheus.Parsing.Internal.Internal@@ -18,18 +16,13 @@                                                 ( parseAssignment                                                 , parseMaybeTuple                                                 , token-                                                , variable                                                 ) import           Data.Morpheus.Parsing.Internal.Value-                                                ( enumValue-                                                , parseValue-                                                )+                                                ( parseRawValue ) import           Data.Morpheus.Types.Internal.AST-                                                ( ValueOrigin(..)-                                                , Argument(..)-                                                , RawArgument(..)+                                                ( Argument(..)+                                                , RawArgument                                                 , RawArguments-                                                , Ref(..)                                                 )  @@ -42,19 +35,11 @@ --  Name : Value[Const] -- TODO: move variable to Value valueArgument :: Parser RawArgument-valueArgument = label "valueArgument" $ do+valueArgument = label "Argument" $ do   argumentPosition <- getLocation-  argumentValue    <- parseValue <|> enumValue-  pure $ RawArgument $ Argument { argumentValue-                                , argumentOrigin   = INLINE-                                , argumentPosition-                                }--variableArgument :: Parser RawArgument-variableArgument = label "variableArgument" $ do-  (refName, refPosition) <- variable-  pure $ VariableRef $ Ref { refName, refPosition }+  argumentValue    <- parseRawValue+  pure $ Argument { argumentValue, argumentPosition }  maybeArguments :: Parser RawArguments-maybeArguments = label "maybeArguments" $ parseMaybeTuple argument-  where argument = parseAssignment token (valueArgument <|> variableArgument)+maybeArguments =+  label "Arguments" $ parseMaybeTuple (parseAssignment token valueArgument)
src/Data/Morpheus/Parsing/Request/Operation.hs view
@@ -36,12 +36,13 @@ import           Data.Morpheus.Parsing.Request.Selection                                                 ( parseSelectionSet ) import           Data.Morpheus.Types.Internal.AST-                                                ( DefaultValue-                                                , Operation(..)+                                                ( Operation(..)                                                 , RawOperation                                                 , Variable(..)                                                 , OperationType(..)-                                                , isNullable+                                                , Ref(..)+                                                , VariableContent(..)+                                                , RAW                                                 )  @@ -50,19 +51,17 @@ --  VariableDefinition --    Variable : Type DefaultValue(opt) ---variableDefinition :: Parser (Text, Variable DefaultValue)+variableDefinition :: Parser (Text, Variable RAW) variableDefinition = label "VariableDefinition" $ do-  (name, variablePosition) <- variable+  (Ref name variablePosition) <- variable   operator ':'-  (variableTypeWrappers, variableType) <- parseType-  defaultValue                         <- parseDefaultValue+  variableType <- parseType+  defaultValue <- parseDefaultValue   pure     ( name     , Variable { variableType-               , isVariableRequired   = not (isNullable variableTypeWrappers)-               , variableTypeWrappers                , variablePosition-               , variableValue        = defaultValue+               , variableValue    = DefaultValue defaultValue                }     ) @@ -78,14 +77,14 @@   operationPosition  <- getLocation   operationType      <- parseOperationType   operationName      <- optional parseName-  operationArgs      <- parseMaybeTuple variableDefinition+  operationArguments <- parseMaybeTuple variableDefinition   -- TODO: handle directives   _directives        <- optionalDirectives   operationSelection <- parseSelectionSet   pure     (Operation { operationName                , operationType-               , operationArgs+               , operationArguments                , operationSelection                , operationPosition                }@@ -107,7 +106,7 @@   pure       (Operation { operationName      = Nothing                  , operationType      = Query-                 , operationArgs      = []+                 , operationArguments = []                  , operationSelection                  , operationPosition                  }
src/Data/Morpheus/Parsing/Request/Parser.hs view
@@ -35,9 +35,9 @@                                                 , Failure(..)                                                 ) import           Data.Morpheus.Types.Internal.AST-                                                ( Value(..)-                                                , replaceValue+                                                ( replaceValue                                                 , GQLQuery(..)+                                                , ResolvedValue                                                 ) import           Data.Morpheus.Types.IO         ( GQLRequest(..) ) @@ -57,7 +57,7 @@   Right root       -> pure $ root { inputVariables = toVariableMap variables }   Left  parseError -> failure $ processErrorBundle parseError  where-  toVariableMap :: Maybe Aeson.Value -> [(Text, Value)]+  toVariableMap :: Maybe Aeson.Value -> [(Text, ResolvedValue)]   toVariableMap (Just (Aeson.Object x)) = map toMorpheusValue (toList x)     where toMorpheusValue (key, value) = (key, replaceValue value)   toVariableMap _ = []
src/Data/Morpheus/Parsing/Request/Selection.hs view
@@ -34,11 +34,12 @@                                                 ( maybeArguments ) import           Data.Morpheus.Types.Internal.AST                                                 ( Selection(..)+                                                , SelectionContent(..)+                                                , Ref(..)                                                 , Fragment(..)                                                 , RawArguments-                                                , RawSelection(..)+                                                , RawSelection                                                 , RawSelectionSet-                                                , Ref(..)                                                 )  @@ -80,23 +81,23 @@  where     ----------------------------------------   buildField selectionAlias selectionArguments selectionPosition = pure-    (RawSelectionField $ Selection { selectionAlias-                                   , selectionArguments-                                   , selectionRec       = ()-                                   , selectionPosition-                                   }+    (Selection { selectionAlias+               , selectionArguments+               , selectionContent   = SelectionField+               , selectionPosition+               }     )   -----------------------------------------   selSet :: Maybe Text -> RawArguments -> Parser RawSelection   selSet selectionAlias selectionArguments = label "body" $ do     selectionPosition <- getLocation-    selectionRec      <- parseSelectionSet+    selectionSet      <- parseSelectionSet     return-      (RawSelectionSet $ Selection { selectionAlias-                                   , selectionArguments-                                   , selectionRec-                                   , selectionPosition-                                   }+      (Selection { selectionAlias+                 , selectionArguments+                 , selectionContent   = SelectionSet selectionSet+                 , selectionPosition+                 }       )  
src/Data/Morpheus/Rendering/RenderGQL.hs view
@@ -21,12 +21,12 @@ -- MORPHEUS import           Data.Morpheus.Types.Internal.AST                                                 ( DataField(..)-                                                , DataTyCon(..)+                                                , DataTypeContent(..)                                                 , DataType(..)                                                 , DataTypeLib                                                 , DataTypeWrapper(..)                                                 , Key-                                                , TypeAlias(..)+                                                , TypeRef(..)                                                 , TypeWrapper(..)                                                 , allDataTypes                                                 , createInputUnionFields@@ -34,7 +34,8 @@                                                 , isDefaultTypeName                                                 , toGQLWrapper                                                 , DataEnumValue(..)-                                                , convertToJSONName )+                                                , convertToJSONName+                                                )   renderGraphQLDocument :: DataTypeLib -> ByteString@@ -53,42 +54,34 @@       showGQLWrapper (ListType:xs)    = "[" <> showGQLWrapper xs <> "]"       showGQLWrapper (NonNullType:xs) = showGQLWrapper xs <> "!" + instance RenderGQL Key where   render = id -instance RenderGQL TypeAlias where-  render TypeAlias { aliasTyCon, aliasWrappers } =-    renderWrapped aliasTyCon aliasWrappers+instance RenderGQL TypeRef where+  render TypeRef { typeConName, typeWrappers } =+    renderWrapped typeConName typeWrappers  instance RenderGQL DataType where-  render (DataScalar      x) = typeName x-  render (DataEnum        x) = typeName x-  render (DataUnion       x) = typeName x-  render (DataInputObject x) = typeName x-  render (DataInputUnion  x) = typeName x-  render (DataObject      x) = typeName x+  render = typeName  instance RenderGQL DataEnumValue where   render DataEnumValue { enumName } = enumName  instance RenderGQL (Key, DataType) where-  render (name, DataScalar{}) = "scalar " <> name-  render (name, DataEnum DataTyCon { typeData }) =-    "enum " <> name <> renderObject render typeData-  render (name, DataUnion DataTyCon { typeData }) =-    "union "-      <> name-      <> " =\n    "-      <> intercalate ("\n" <> renderIndent <> "| ") typeData-  render (name, DataInputObject DataTyCon { typeData }) =-    "input " <> name <> render typeData-  render (name, DataInputUnion DataTyCon { typeData }) =-    "input " <> name <> render fields-    where fields = createInputUnionFields name typeData-  render (name, DataObject DataTyCon { typeData }) =-    "type " <> name <> render typeData--+  render (name, DataType { typeContent }) = __render typeContent+   where+    __render DataScalar{}    = "scalar " <> name+    __render (DataEnum tags) = "enum " <> name <> renderObject render tags+    __render (DataUnion members) =+      "union "+        <> name+        <> " =\n    "+        <> intercalate ("\n" <> renderIndent <> "| ") members+    __render (DataInputObject fields ) = "input " <> name <> render fields+    __render (DataInputUnion  members) = "input " <> name <> render fields+      where fields = createInputUnionFields name (map fst members)+    __render (DataObject fields) = "type " <> name <> render fields  -- OBJECT instance RenderGQL [(Text, DataField)] where
src/Data/Morpheus/Rendering/RenderIntrospection.hs view
@@ -19,15 +19,16 @@ import           Data.Morpheus.Schema.Schema import           Data.Morpheus.Schema.TypeKind  ( TypeKind(..) ) import           Data.Morpheus.Types.Internal.AST-                                                ( DataField(..)-                                                , DataTyCon(..)+                                                ( DataInputUnion+                                                , DataField(..)+                                                , DataTypeContent(..)                                                 , DataType(..)                                                 , DataTypeKind(..)                                                 , DataTypeLib                                                 , DataTypeWrapper(..)                                                 , DataUnion                                                 , Meta(..)-                                                , TypeAlias(..)+                                                , TypeRef(..)                                                 , createInputUnionFields                                                 , fieldVisibility                                                 , kindOf@@ -35,8 +36,10 @@                                                 , toGQLWrapper                                                 , DataEnumValue(..)                                                 , lookupDeprecated+                                                , DataInputUnion                                                 , lookupDeprecatedReason-                                                , convertToJSONName )+                                                , convertToJSONName+                                                ) import           Data.Morpheus.Types.Internal.Resolving                                                 ( Failure(..) ) @@ -49,24 +52,22 @@   render :: (Monad m, Failure Text m) => (Text, a) -> DataTypeLib -> m (b m)  instance RenderSchema DataType S__Type where-  render (key, DataScalar DataTyCon { typeMeta }) =-    constRes $ createLeafType SCALAR key typeMeta Nothing-  render (key, DataEnum DataTyCon { typeMeta, typeData }) =-    constRes-      $ createLeafType ENUM key typeMeta (Just $ map createEnumValue typeData)-  render (name, DataInputObject DataTyCon { typeData, typeMeta }) =-    renderInputObject-   where-    renderInputObject lib = do-      fields <- traverse (`renderinputValue` lib) typeData-      pure $ createInputObject name typeMeta fields-  render (name, DataObject object') = typeFromObject (name, object')+  render (name, DataType { typeMeta, typeContent }) = __render typeContent    where-    typeFromObject (key, DataTyCon { typeData, typeMeta }) lib =-      createObjectType key (typeMeta >>= metaDescription)-        <$> (Just <$> traverse (`render` lib) (filter fieldVisibility typeData))-  render (name, DataUnion union) = constRes $ typeFromUnion (name, union)-  render (name, DataInputUnion inpUnion') = renderInputUnion (name, inpUnion')+    __render DataScalar{} =+      constRes $ createLeafType SCALAR name typeMeta Nothing+    __render (DataEnum enums) = constRes+      $ createLeafType ENUM name typeMeta (Just $ map createEnumValue enums)+    __render (DataInputObject fields) = \lib ->+      createInputObject name typeMeta+        <$> traverse (`renderinputValue` lib) fields+    __render (DataObject fields) = \lib ->+      createObjectType name (typeMeta >>= metaDescription)+        <$> (Just <$> traverse (`render` lib) (filter fieldVisibility fields))+    __render (DataUnion union) =+      constRes $ typeFromUnion (name, typeMeta, union)+    __render (DataInputUnion members) =+      renderInputUnion (name, typeMeta, members)  createEnumValue :: Monad m => DataEnumValue -> S__EnumValue m createEnumValue DataEnumValue { enumName, enumMeta } = S__EnumValue@@ -79,16 +80,16 @@   where deprecated = enumMeta >>= lookupDeprecated  instance RenderSchema DataField S__Field where-  render (name, field@DataField { fieldType = TypeAlias { aliasTyCon }, fieldArgs, fieldMeta }) lib+  render (name, field@DataField { fieldType = TypeRef { typeConName }, fieldArgs, fieldMeta }) lib     = do-      kind <- renderTypeKind <$> lookupKind aliasTyCon lib+      kind <- renderTypeKind <$> lookupKind typeConName lib       args <- traverse (`renderinputValue` lib) fieldArgs       pure S__Field         { s__FieldName              = constRes (convertToJSONName name)         , s__FieldDescription       = constRes (fieldMeta >>= metaDescription)         , s__FieldArgs              = constRes args         , s__FieldType'             =-          constRes (wrap field $ createType kind aliasTyCon Nothing $ Just [])+          constRes (wrap field $ createType kind typeConName Nothing $ Just [])         , s__FieldIsDeprecated      = constRes (isJust deprecated)         , s__FieldDeprecationReason = constRes                                         (deprecated >>= lookupDeprecatedReason)@@ -106,8 +107,8 @@ renderTypeKind KindNonNull     = NON_NULL  wrap :: Monad m => DataField -> S__Type m -> S__Type m-wrap DataField { fieldType = TypeAlias { aliasWrappers } } typ =-  foldr wrapByTypeWrapper typ (toGQLWrapper aliasWrappers)+wrap DataField { fieldType = TypeRef { typeWrappers } } typ =+  foldr wrapByTypeWrapper typ (toGQLWrapper typeWrappers)  wrapByTypeWrapper :: Monad m => DataTypeWrapper -> S__Type m -> S__Type m wrapByTypeWrapper ListType    = wrapAs LIST@@ -128,17 +129,20 @@  createInputObjectType   :: (Monad m, Failure Text m) => DataField -> Result m (S__Type m)-createInputObjectType field@DataField { fieldType = TypeAlias { aliasTyCon } } lib+createInputObjectType field@DataField { fieldType = TypeRef { typeConName } } lib   = do-    kind <- renderTypeKind <$> lookupKind aliasTyCon lib-    pure $ wrap field $ createType kind aliasTyCon Nothing $ Just []+    kind <- renderTypeKind <$> lookupKind typeConName lib+    pure $ wrap field $ createType kind typeConName Nothing $ Just []   renderInputUnion-  :: (Monad m, Failure Text m) => (Text, DataUnion) -> Result m (S__Type m)-renderInputUnion (key, DataTyCon { typeData, typeMeta }) lib =-  createInputObject key typeMeta-    <$> traverse createField (createInputUnionFields key typeData)+  :: (Monad m, Failure Text m)+  => (Text, Maybe Meta, DataInputUnion)+  -> Result m (S__Type m)+renderInputUnion (key, meta, fields) lib =+  createInputObject key meta <$> traverse+    createField+    (createInputUnionFields key $ map fst $ filter snd fields)  where   createField (name, field) =     createInputValueWith name Nothing <$> createInputObjectType field lib@@ -162,8 +166,8 @@   , s__TypeInputFields   = constRes Nothing   } -typeFromUnion :: Monad m => (Text, DataUnion) -> S__Type m-typeFromUnion (name, DataTyCon { typeData, typeMeta }) = S__Type+typeFromUnion :: Monad m => (Text, Maybe Meta, DataUnion) -> S__Type m+typeFromUnion (name, typeMeta, typeContent) = S__Type   { s__TypeKind          = constRes UNION   , s__TypeName          = constRes $ Just name   , s__TypeDescription   = constRes (typeMeta >>= metaDescription)@@ -171,7 +175,8 @@   , s__TypeOfType        = constRes Nothing   , s__TypeInterfaces    = constRes Nothing   , s__TypePossibleTypes =-    constRes $ Just (map (\x -> createObjectType x Nothing $ Just []) typeData)+    constRes+      $ Just (map (\x -> createObjectType x Nothing $ Just []) typeContent)   , s__TypeEnumValues    = constRes Nothing   , s__TypeInputFields   = constRes Nothing   }
src/Data/Morpheus/Schema/SchemaAPI.hs view
@@ -1,7 +1,8 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE NamedFieldPuns   #-}-{-# LANGUAGE TypeApplications #-}-{-# LANGUAGE TypeOperators    #-}+{-# LANGUAGE FlexibleContexts  #-}+{-# LANGUAGE NamedFieldPuns    #-}+{-# LANGUAGE TypeApplications  #-}+{-# LANGUAGE TypeOperators     #-}+{-# LANGUAGE OverloadedStrings #-}  module Data.Morpheus.Schema.SchemaAPI   ( hiddenRootFields@@ -15,9 +16,10 @@  -- MORPHEUS import           Data.Morpheus.Execution.Server.Introspect-                                                ( ObjectFields(..)+                                                ( objectFields                                                 , TypeUpdater                                                 , introspect+                                                , TypeScope(..)                                                 ) import           Data.Morpheus.Rendering.RenderIntrospection                                                 ( createObjectType@@ -33,9 +35,9 @@ import           Data.Morpheus.Types.ID         ( ID ) import           Data.Morpheus.Types.Internal.AST                                                 ( DataField(..)-                                                , DataObject                                                 , DataTypeLib(..)                                                 , QUERY+                                                , DataType                                                 , allDataTypes                                                 , lookupDataType                                                 )@@ -50,7 +52,7 @@ convertTypes lib = traverse (`render` lib) (allDataTypes lib)  buildSchemaLinkType-  :: Monad m => (Text, DataObject) -> S__Type (Resolver QUERY e m)+  :: Monad m => (Text, DataType) -> S__Type (Resolver QUERY e m) buildSchemaLinkType (key', _) = createObjectType key' Nothing $ Just []  findType@@ -78,8 +80,9 @@   }  hiddenRootFields :: [(Text, DataField)]-hiddenRootFields = fst-  $ objectFields (Proxy :: Proxy (CUSTOM (Root Maybe))) (Proxy @(Root Maybe))+hiddenRootFields = fst $ objectFields+  (Proxy :: Proxy (CUSTOM (Root Maybe)))+  ("Root", OutputType, Proxy @(Root Maybe))  defaultTypes :: TypeUpdater defaultTypes = flip
src/Data/Morpheus/Server.hs view
@@ -7,6 +7,7 @@ -- |  GraphQL Wai Server Applications module Data.Morpheus.Server   ( gqlSocketApp+  , gqlSocketMonadIOApp   , initGQLState   , GQLState   )@@ -14,6 +15,7 @@  import           Control.Exception              ( finally ) import           Control.Monad                  ( forever )+import           Control.Monad.IO.Class         ( MonadIO(liftIO) ) import           Data.Text                      ( Text ) import           Network.WebSockets             ( ServerApp                                                 , acceptRequestWith@@ -55,21 +57,21 @@                                                 ( GQLClient(..) ) import           Data.Morpheus.Types.IO         ( GQLResponse(..) ) import           Data.Morpheus.Types.Internal.AST-                                                ( Value )+                                                ( ValidValue )  handleSubscription-  :: (Eq (StreamChannel e), GQLChannel e)-  => GQLClient IO e-  -> GQLState IO e+  :: (Eq (StreamChannel e), GQLChannel e, MonadIO m)+  => GQLClient m e+  -> GQLState m e   -> Text-  -> ResponseStream e IO Value-  -> IO ()+  -> ResponseStream e m ValidValue+  -> m () handleSubscription GQLClient { clientConnection, clientID } state sessionId stream   = do     response <- runResultT stream     case response of       Success { events } -> mapM_ execute events-      Failure errors     -> sendTextData+      Failure errors     -> liftIO $ sendTextData         clientConnection         (toApolloResponse sessionId $ Errors errors)  where@@ -77,25 +79,35 @@   execute (Subscribe sub) = addClientSubscription clientID sub sessionId state  -- | Wai WebSocket Server App for GraphQL subscriptions-gqlSocketApp-  :: RootResCon IO e que mut sub-  => GQLRootResolver IO e que mut sub-  -> GQLState IO e+gqlSocketMonadIOApp+  :: (RootResCon m e que mut sub, MonadIO m)+  => GQLRootResolver m e que mut sub+  -> GQLState m e+  -> (m () -> IO ())   -> ServerApp-gqlSocketApp gqlRoot state pending = do+gqlSocketMonadIOApp gqlRoot state f pending = do   connection <- acceptRequestWith pending     $ acceptApolloSubProtocol (pendingRequest pending)   forkPingThread connection 30   client <- connectClient connection state-  finally (queryHandler client) (disconnectClient client state)+  finally (f $ queryHandler client) (disconnectClient client state)  where   queryHandler client = forever handleRequest    where-    handleRequest =-      receiveData (clientConnection client) >>= resolveMessage . apolloFormat+    handleRequest = do+      d <- liftIO $ receiveData (clientConnection client)+      resolveMessage (apolloFormat d)      where-      resolveMessage (SubError x) = print x+      resolveMessage (SubError x) = liftIO $ print x       resolveMessage (AddSub sessionId request) =         handleSubscription client state sessionId (coreResolver gqlRoot request)       resolveMessage (RemoveSub sessionId) =         removeClientSubscription (clientID client) sessionId state++-- | Same as above but specific to IO+gqlSocketApp+  :: (RootResCon IO e que mut sub)+  => GQLRootResolver IO e que mut sub+  -> GQLState IO e+  -> ServerApp+gqlSocketApp gqlRoot state = gqlSocketMonadIOApp gqlRoot state id
src/Data/Morpheus/Types.hs view
@@ -29,9 +29,11 @@   , ResolveQ   , ResolveM   , ResolveS+  , failRes   ) where +import           Data.Text                      ( pack ) import           Data.Morpheus.Types.GQLScalar  ( GQLScalar                                                   ( parseValue                                                   , serialize@@ -51,6 +53,7 @@                                                 , Resolver(..)                                                 , LiftEither(..)                                                 , lift+                                                , failure                                                 ) import           Data.Morpheus.Types.IO         ( GQLRequest(..)                                                 , GQLResponse(..)@@ -76,3 +79,6 @@  constMutRes :: Monad m => [e] -> a -> args -> MutRes e m a constMutRes events value = const $ MutResolver $ pure (events, value)++failRes :: (LiftEither o Resolver, Monad m) => String -> Resolver o e m a+failRes = failure . pack
src/Data/Morpheus/Types/GQLScalar.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE GADTs                   #-} {-# LANGUAGE ConstrainedClassMethods #-} {-# LANGUAGE OverloadedStrings       #-} {-# LANGUAGE ScopedTypeVariables     #-}@@ -10,14 +11,15 @@  import           Data.Morpheus.Types.Internal.AST.Data                                                 ( DataValidator(..) )-import           Data.Morpheus.Types.Internal.AST.Value+import           Data.Morpheus.Types.Internal.AST                                                 ( ScalarValue(..)+                                                , ValidValue                                                 , Value(..)                                                 ) import           Data.Proxy                     ( Proxy(..) ) import           Data.Text                      ( Text ) -toScalar :: Value -> Either Text ScalarValue+toScalar :: ValidValue -> Either Text ScalarValue toScalar (Scalar x) = pure x toScalar _          = Left "" @@ -65,5 +67,6 @@  instance GQLScalar Float where   parseValue (Float x) = pure x+  parseValue (Int   x) = pure $ fromInteger $ toInteger x   parseValue _         = Left ""   serialize = Float
src/Data/Morpheus/Types/GQLType.hs view
@@ -80,13 +80,34 @@ --     instance GQLType ... where --       description = const "your description ..." --  @-class GQLType a where++class IsObject (a :: GQL_KIND) where+  isObject :: Proxy a -> Bool++instance IsObject SCALAR where+  isObject _ = False++instance IsObject ENUM where+  isObject _ = False++instance IsObject WRAPPER where+  isObject _ = False++instance IsObject INPUT where+  isObject _ = True++instance IsObject OUTPUT where+  isObject _ = True++class IsObject (KIND a) => GQLType a where   type KIND a :: GQL_KIND-  type KIND a = OBJECT+  type KIND a = OUTPUT   type CUSTOM a :: Bool   type CUSTOM a = FALSE   description :: Proxy a -> Maybe Text   description _ = Nothing+  isObjectKind :: Proxy a -> Bool+  isObjectKind _ = isObject (Proxy @(KIND a))   __typeName :: Proxy a -> Text   default __typeName :: (Typeable a) =>     Proxy a -> Text@@ -96,7 +117,7 @@   __typeFingerprint :: Proxy a -> DataFingerprint   default __typeFingerprint :: (Typeable a) =>     Proxy a -> DataFingerprint-  __typeFingerprint _ = TypeableFingerprint $ map show $ conFingerprints (Proxy @a)+  __typeFingerprint _ = DataFingerprint "Typeable" $ map show $ conFingerprints (Proxy @a)     where       conFingerprints = fmap (map tyConFingerprint) (ignoreResolver . splitTyConApp . typeRep) @@ -143,10 +164,10 @@   __typeFingerprint _ = __typeFingerprint (Proxy @a)  instance (Typeable a, Typeable b, GQLType a, GQLType b) => GQLType (Pair a b) where-  type KIND (Pair a b) = OBJECT+  type KIND (Pair a b) = OUTPUT  instance (Typeable a, Typeable b, GQLType a, GQLType b) => GQLType (MapKind a b m) where-  type KIND (MapKind a b m) = OBJECT+  type KIND (MapKind a b m) = OUTPUT   __typeName _ = __typeName (Proxy @(Map a b))   __typeFingerprint _ = __typeFingerprint (Proxy @(Map a b)) 
src/Data/Morpheus/Types/ID.hs view
@@ -10,7 +10,7 @@ import           Data.Morpheus.Kind             ( SCALAR ) import           Data.Morpheus.Types.GQLScalar  ( GQLScalar(..) ) import           Data.Morpheus.Types.GQLType    ( GQLType(KIND) )-import           Data.Morpheus.Types.Internal.AST.Value+import           Data.Morpheus.Types.Internal.AST                                                 ( ScalarValue(..) ) import           Data.Text                      ( Text                                                 , pack
src/Data/Morpheus/Types/IO.hs view
@@ -32,10 +32,10 @@                                                 , Result(..)                                                 ) import           Data.Morpheus.Types.Internal.AST.Value-                                                ( Value )+                                                ( ValidValue )  -renderResponse :: Result e GQLError con Value -> GQLResponse+renderResponse :: Result e GQLError con ValidValue -> GQLResponse renderResponse (Failure errors)   = Errors errors renderResponse Success { result } = Data result @@ -57,7 +57,7 @@  -- | GraphQL Response data GQLResponse-  = Data Value+  = Data ValidValue   | Errors [GQLError]   deriving (Show, Generic) 
src/Data/Morpheus/Types/Internal/AST.hs view
@@ -1,4 +1,6 @@-{-# LANGUAGE DeriveLift       #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE DeriveLift           #-}+{-# LANGUAGE OverloadedStrings    #-}  module Data.Morpheus.Types.Internal.AST   (@@ -11,6 +13,10 @@   , anonymousRef   , Name   , Description+  , Stage+  , RESOLVED+  , VALID+  , RAW    -- VALUE   , Value(..)@@ -21,22 +27,32 @@   , decodeScientific   , convertToJSONName   , convertToHaskellName+  , RawValue+  , ValidValue+  , RawObject+  , ValidObject+  , ResolvedObject+  , ResolvedValue+  , unpackInputUnion    -- Selection   , Argument(..)   , Arguments   , SelectionSet-  , SelectionRec(..)-  , ValueOrigin(..)+  , SelectionContent(..)   , ValidSelection   , Selection(..)-  , RawSelection'+  , RawSelection   , FragmentLib   , RawArguments   , RawSelectionSet   , Fragment(..)-  , RawArgument(..)-  , RawSelection(..)+  , RawArgument+  , ValidSelectionSet+  , ValidArgument+  , ValidArguments+  , RawSelectionRec+  , ValidSelectionRec    -- OPERATION   , Operation(..)@@ -48,6 +64,7 @@   , DefaultValue   , getOperationName   , getOperationDataType+  , getOperationObject     -- DSL@@ -58,7 +75,7 @@   , DataUnion   , DataArguments   , DataField(..)-  , DataTyCon(..)+  , DataTypeContent(..)   , DataType(..)   , DataTypeLib(..)   , DataTypeWrapper(..)@@ -68,7 +85,7 @@   , RawDataType(..)   , ResolverKind(..)   , TypeWrapper(..)-  , TypeAlias(..)+  , TypeRef(..)   , ArgsType(..)   , DataEnumValue(..)   , isTypeDefined@@ -120,7 +137,6 @@   , Meta(..)   , Directive(..)   , createEnumValue-  , fromDataType   , insertType   , TypeUpdater   , lookupDeprecated@@ -130,33 +146,64 @@   , ClientQuery(..)   , GQLTypeD(..)   , ClientType(..)+  , DataInputUnion+  , VariableContent(..)   -- LOCAL   , GQLQuery(..)   , Variables+  , isNullableWrapper   ) where  import           Data.Map                       ( Map ) import           Language.Haskell.TH.Syntax     ( Lift )-import           Instances.TH.Lift              ( )+import           Data.Semigroup                 ( (<>) )  -- Morpheus import           Data.Morpheus.Types.Internal.AST.Data --import           Data.Morpheus.Types.Internal.AST.Operation- import           Data.Morpheus.Types.Internal.AST.Selection  import           Data.Morpheus.Types.Internal.AST.Base  import           Data.Morpheus.Types.Internal.AST.Value +import           Data.Morpheus.Types.Internal.Resolving.Core+                                                ( Failure(..) ) -type Variables = Map Key Value+type Variables = Map Key ResolvedValue  data GQLQuery = GQLQuery   { fragments      :: FragmentLib   , operation      :: RawOperation-  , inputVariables :: [(Key, Value)]+  , inputVariables :: [(Key, ResolvedValue)]   } deriving (Show,Lift)++unpackInputUnion+  :: [(Name, Bool)]+  -> Object stage+  -> Either Message (Name, Maybe (Value stage))+unpackInputUnion tags [("__typename", enum)] = do+  tyName <- isPosibeUnion tags enum+  pure (tyName, Nothing)+unpackInputUnion tags [("__typename", enum), (name, value)] = do+  tyName <- isPosibeUnion tags enum+  inputtypeName tyName name value+unpackInputUnion tags [(name, value), ("__typename", enum)] = do+  tyName <- isPosibeUnion tags enum+  inputtypeName tyName name value+unpackInputUnion _ _ = failure+  ("valid input union should contain __typename and actual value" :: Message)++isPosibeUnion :: [(Name, Bool)] -> Value stage -> Either Message Name+isPosibeUnion tags (Enum name) = case lookup name tags of+  Nothing -> failure (name <> " is not posible union type" :: Message)+  _       -> pure name+isPosibeUnion _ _ = failure ("__typename must be Enum" :: Message)+++inputtypeName+  :: Name -> Name -> Value stage -> Either Message (Name, Maybe (Value stage))+inputtypeName name fName fieldValue+  | fName == name = pure (name, Just fieldValue)+  | otherwise = failure ("field \"" <> name <> "\" was not provided" :: Message)
src/Data/Morpheus/Types/Internal/AST/Base.hs view
@@ -2,6 +2,7 @@ {-# LANGUAGE DeriveGeneric   #-} {-# LANGUAGE DeriveLift      #-} {-# LANGUAGE NamedFieldPuns  #-}+{-# LANGUAGE DataKinds       #-}  module Data.Morpheus.Types.Internal.AST.Base   ( Key@@ -12,6 +13,12 @@   , anonymousRef   , Name   , Description+  , VALID+  , RAW+  , TypeWrapper(..)+  , Stage(..)+  , RESOLVED+  , TypeRef(..)   ) where @@ -31,6 +38,15 @@  type Collection a = [(Key, a)] ++data Stage = RAW | RESOLVED | VALID++type VALID = 'RAW++type RESOLVED = 'RESOLVED++type RAW = 'VALID+ data Position = Position   { line   :: Int   , column :: Int@@ -53,3 +69,14 @@  anonymousRef :: Key -> Ref anonymousRef refName = Ref { refName, refPosition = Position 0 0 }++data TypeWrapper+  = TypeList+  | TypeMaybe+  deriving (Show, Lift)++data TypeRef = TypeRef+  { typeConName    :: Name+  , typeArgs     :: Maybe Name+  , typeWrappers :: [TypeWrapper]+  } deriving (Show,Lift)
src/Data/Morpheus/Types/Internal/AST/Data.hs view
@@ -10,15 +10,14 @@ {-# LANGUAGE RankNTypes            #-}  module Data.Morpheus.Types.Internal.AST.Data-  ( -    DataScalar+  ( DataScalar   , DataEnum   , DataObject   , DataArgument   , DataUnion   , DataArguments   , DataField(..)-  , DataTyCon(..)+  , DataTypeContent(..)   , DataType(..)   , DataTypeLib(..)   , DataTypeWrapper(..)@@ -28,7 +27,7 @@   , RawDataType(..)   , ResolverKind(..)   , TypeWrapper(..)-  , TypeAlias(..)+  , TypeRef(..)   , ArgsType(..)   , DataEnumValue(..)   , isTypeDefined@@ -80,7 +79,6 @@   , Meta(..)   , Directive(..)   , createEnumValue-  , fromDataType   , insertType   , TypeUpdater   , lookupDeprecated@@ -90,6 +88,8 @@   , ClientQuery(..)   , GQLTypeD(..)   , ClientType(..)+  , DataInputUnion+  , isNullableWrapper   ) where @@ -117,6 +117,8 @@                                                 , Position                                                 , Name                                                 , Description+                                                , TypeWrapper(..)+                                                , TypeRef(..)                                                 ) import           Data.Morpheus.Types.Internal.Resolving.Core                                                 ( Validation@@ -126,7 +128,8 @@                                                 , resolveUpdates                                                 ) import           Data.Morpheus.Types.Internal.AST.Value-                                                ( Value(..)+                                                ( Value(..) +                                                , ValidValue                                                 , ScalarValue(..)                                                 ) import           Data.Morpheus.Error.Schema     ( nameCollisionError )@@ -196,18 +199,19 @@   | ExternalResolver   deriving (Show, Eq, Lift) -data TypeWrapper-  = TypeList-  | TypeMaybe-  deriving (Show, Lift) + isFieldNullable :: DataField -> Bool-isFieldNullable = isNullable . aliasWrappers . fieldType+isFieldNullable = isNullable . fieldType -isNullable :: [TypeWrapper] -> Bool-isNullable (TypeMaybe : _) = True-isNullable _               = False+isNullable :: TypeRef -> Bool+isNullable TypeRef { typeWrappers = typeWrappers } = isNullableWrapper typeWrappers +isNullableWrapper :: [TypeWrapper] -> Bool+isNullableWrapper (TypeMaybe : _ ) = True+isNullableWrapper _               = False++ isWeaker :: [TypeWrapper] -> [TypeWrapper] -> Bool isWeaker (TypeMaybe : xs1) (TypeMaybe : xs2) = isWeaker xs1 xs2 isWeaker (TypeMaybe : _  ) _                 = True@@ -229,27 +233,21 @@ toHSWrappers []                              = [TypeMaybe] toHSWrappers [NonNullType]                   = [] -data DataFingerprint = SystemFingerprint Key | TypeableFingerprint [String]-  deriving (Show, Eq, Ord, Lift)-+data DataFingerprint = DataFingerprint Name [String] deriving (Show, Eq, Ord, Lift)  newtype DataValidator = DataValidator-  { validateValue :: Value -> Either Key Value+  { validateValue :: ValidValue -> Either Key ValidValue   }  instance Show DataValidator where   show _ = "DataValidator" -type DataScalar = DataTyCon DataValidator--type DataEnum = DataTyCon [DataEnumValue]--type DataObject = DataTyCon [(Key, DataField)]-+type DataScalar = DataValidator+type DataEnum = [DataEnumValue]+type DataObject = [(Key, DataField)] type DataArgument = DataField--type DataUnion = DataTyCon [Key]-+type DataUnion = [Key]+type DataInputUnion = [(Key, Bool)] type DataArguments = [(Key, DataArgument)]  data DataTypeWrapper@@ -257,12 +255,6 @@   | NonNullType   deriving (Show, Lift) -data TypeAlias = TypeAlias-  { aliasTyCon    :: Key-  , aliasArgs     :: Maybe Key-  , aliasWrappers :: [TypeWrapper]-  } deriving (Show,Lift)- data ArgsType = ArgsType   { argsTypeName :: Key   , resKind      :: ResolverKind@@ -270,7 +262,7 @@  data Directive = Directive {   directiveName :: Name,-  directiveArgs :: [(Name,Value)]+  directiveArgs :: [(Name, ValidValue)] } deriving (Show,Lift)  -- META@@ -289,6 +281,7 @@ lookupDeprecatedReason Directive { directiveArgs } =   maybeString . snd <$> find isReason directiveArgs  where+  maybeString :: ValidValue -> Name   maybeString (Scalar (String x)) = x   maybeString _                   = "can't read deprecated Reason Value"   isReason ("reason", _) = True@@ -305,7 +298,7 @@   { fieldName     :: Key   , fieldArgs     :: [(Key, DataArgument)]   , fieldArgsType :: Maybe ArgsType-  , fieldType     :: TypeAlias+  , fieldType     :: TypeRef   , fieldMeta     :: Maybe Meta   } deriving (Show,Lift) @@ -316,11 +309,11 @@ fieldVisibility _                 = True  createField :: DataArguments -> Key -> ([TypeWrapper], Key) -> DataField-createField fieldArgs fieldName (aliasWrappers, aliasTyCon) = DataField+createField fieldArgs fieldName (typeWrappers, typeConName) = DataField   { fieldArgs   , fieldArgsType = Nothing   , fieldName-  , fieldType     = TypeAlias { aliasTyCon, aliasWrappers, aliasArgs = Nothing }+  , fieldType     = TypeRef { typeConName, typeWrappers, typeArgs = Nothing }   , fieldMeta     = Nothing   } @@ -330,17 +323,17 @@  toNullableField :: DataField -> DataField toNullableField dataField-  | isNullable (aliasWrappers $ fieldType dataField) = dataField+  | isNullable (fieldType dataField) = dataField   | otherwise = dataField { fieldType = nullable (fieldType dataField) }  where-  nullable alias@TypeAlias { aliasWrappers } =-    alias { aliasWrappers = TypeMaybe : aliasWrappers }+  nullable alias@TypeRef { typeWrappers } =+    alias { typeWrappers = TypeMaybe : typeWrappers }  toListField :: DataField -> DataField toListField dataField = dataField { fieldType = listW (fieldType dataField) }  where-  listW alias@TypeAlias { aliasWrappers } =-    alias { aliasWrappers = TypeList : aliasWrappers }+  listW alias@TypeRef { typeWrappers } =+    alias { typeWrappers = TypeList : typeWrappers }  lookupField :: Failure error m => Key -> [(Key, field)] -> error -> m field lookupField key fields gqlError = case lookup key fields of@@ -350,58 +343,69 @@ lookupSelectionField   :: Failure GQLErrors Validation   => Position-  -> Key+  -> Name+  -> Name   -> DataObject   -> Validation DataField-lookupSelectionField position fieldName DataTyCon { typeData, typeName } =-  lookupField fieldName typeData gqlError+lookupSelectionField position fieldName typeName fields = lookupField+  fieldName+  fields+  gqlError   where gqlError = cannotQueryField fieldName typeName position  -- -- TYPE CONSTRUCTOR ---------------------------------------------------------------------------------------------------data DataTyCon a = DataTyCon-  { typeName        :: Key-  , typeFingerprint :: DataFingerprint-  , typeMeta :: Maybe Meta-  , typeData        :: a-  } deriving (Show, Lift) - data RawDataType   = FinalDataType DataType-  | Interface DataObject-  | Implements { implementsInterfaces :: [Key]-               , unImplements         :: DataObject }+  | Interface {+      interfaceName    :: Key+      , interfaceMeta    :: Maybe Meta+      , interfaceContent :: DataObject+    }+  | Implements {+        implementsName    :: Key+      , implementsInterfaces :: [Key]+      , implementsMeta    :: Maybe Meta+      , implementsContent         :: DataObject+    }   deriving (Show)  -- -- DATA TYPE ---------------------------------------------------------------------------------------------------data DataType+data DataTypeContent   = DataScalar DataScalar   | DataEnum DataEnum   | DataInputObject DataObject   | DataObject DataObject   | DataUnion DataUnion-  | DataInputUnion DataUnion+  | DataInputUnion [(Key,Bool)]   deriving (Show) -createType :: Key -> a -> DataTyCon a-createType typeName typeData = DataTyCon+data DataType = DataType+  { typeName        :: Key+  , typeFingerprint :: DataFingerprint+  , typeMeta :: Maybe Meta+  , typeContent       :: DataTypeContent+  } deriving (Show)++createType :: Key -> DataTypeContent -> DataType+createType typeName typeContent = DataType   { typeName   , typeMeta        = Nothing-  , typeFingerprint = SystemFingerprint ""-  , typeData+  , typeFingerprint = DataFingerprint typeName []+  , typeContent   }  createScalarType :: Key -> (Key, DataType) createScalarType typeName =-  (typeName, DataScalar $ createType typeName (DataValidator pure))+  (typeName, createType typeName $ DataScalar (DataValidator pure))  createEnumType :: Key -> [Key] -> (Key, DataType) createEnumType typeName typeData =-  (typeName, DataEnum $ createType typeName enumValues)+  (typeName, createType typeName $ DataEnum enumValues)   where enumValues = map createEnumValue typeData  createEnumValue :: Key -> DataEnumValue@@ -409,58 +413,54 @@  createUnionType :: Key -> [Key] -> (Key, DataType) createUnionType typeName typeData =-  (typeName, DataUnion $ createType typeName typeData)-+  (typeName, createType typeName $ DataUnion typeData) -isEntNode :: DataType -> Bool-isEntNode DataScalar{} = True-isEntNode DataEnum{}   = True-isEntNode _            = False+isEntNode :: DataTypeContent -> Bool+isEntNode DataScalar{}  = True+isEntNode DataEnum{} = True+isEntNode _ = False  isInputDataType :: DataType -> Bool-isInputDataType DataScalar{}      = True-isInputDataType DataEnum{}        = True-isInputDataType DataInputObject{} = True-isInputDataType DataInputUnion{}  = True-isInputDataType _                 = False+isInputDataType DataType { typeContent } = __isInput typeContent+ where+  __isInput DataScalar{}      = True+  __isInput DataEnum{}        = True+  __isInput DataInputObject{} = True+  __isInput DataInputUnion{}  = True+  __isInput _                 = False -coerceDataObject :: Failure error m => error -> DataType -> m DataObject-coerceDataObject _        (DataObject object) = pure object-coerceDataObject gqlError _                   = failure gqlError+coerceDataObject :: Failure error m => error -> DataType -> m (Name,DataObject)+coerceDataObject _ DataType { typeContent = DataObject object , typeName } = pure (typeName,object)+coerceDataObject gqlError _ = failure gqlError  coerceDataUnion :: Failure error m => error -> DataType -> m DataUnion-coerceDataUnion _        (DataUnion object) = pure object-coerceDataUnion gqlError _                  = failure gqlError+coerceDataUnion _ DataType { typeContent = DataUnion members } = pure members+coerceDataUnion gqlError _ = failure gqlError  kindOf :: DataType -> DataTypeKind-kindOf (DataScalar      _) = KindScalar-kindOf (DataEnum        _) = KindEnum-kindOf (DataInputObject _) = KindInputObject-kindOf (DataObject      _) = KindObject Nothing-kindOf (DataUnion       _) = KindUnion-kindOf (DataInputUnion  _) = KindInputUnion+kindOf DataType { typeContent } = __kind typeContent+ where+  __kind (DataScalar      _) = KindScalar+  __kind (DataEnum        _) = KindEnum+  __kind (DataInputObject _) = KindInputObject+  __kind (DataObject      _) = KindObject Nothing+  __kind (DataUnion       _) = KindUnion+  __kind (DataInputUnion  _) = KindInputUnion -fromDataType :: (DataTyCon () -> v) -> DataType -> v-fromDataType f (DataScalar      dt) = f dt { typeData = () }-fromDataType f (DataEnum        dt) = f dt { typeData = () }-fromDataType f (DataUnion       dt) = f dt { typeData = () }-fromDataType f (DataInputObject dt) = f dt { typeData = () }-fromDataType f (DataInputUnion  dt) = f dt { typeData = () }-fromDataType f (DataObject      dt) = f dt { typeData = () }  -- -- Type Register -------------------------------------------------------------------------------------------------- data DataTypeLib = DataTypeLib   { types        :: HashMap Key DataType-  , query        :: (Key,  DataObject)-  , mutation     :: Maybe (Key, DataObject)-  , subscription :: Maybe (Key, DataObject)+  , query        :: (Name,DataType)+  , mutation     :: Maybe (Name, DataType)+  , subscription :: Maybe (Name, DataType)   } deriving (Show)  type TypeRegister = HashMap Key DataType -initTypeLib :: (Key, DataObject) -> DataTypeLib+initTypeLib :: (Key, DataType) -> DataTypeLib initTypeLib query = DataTypeLib { types        = empty                                 , query        = query                                 , mutation     = Nothing@@ -476,9 +476,9 @@   types `union` fromList     (concatMap fromOperation [Just query, mutation, subscription]) -fromOperation :: Maybe (Key, DataObject) -> [(Key, DataType)]-fromOperation (Just (key', dataType')) = [(key', DataObject dataType')]-fromOperation Nothing                  = []+fromOperation :: Maybe (Key, DataType) -> [(Key, DataType)]+fromOperation (Just (key, datatype)) = [(key, datatype)]+fromOperation Nothing = []  lookupDataType :: Key -> DataTypeLib -> Maybe DataType lookupDataType name lib = name `HM.lookup` typeRegister lib@@ -489,7 +489,7 @@   _      -> failure gqlError  lookupDataObject-  :: (Monad m, Failure e m) => e -> Key -> DataTypeLib -> m DataObject+  :: (Monad m, Failure e m) => e -> Key -> DataTypeLib -> m (Name,DataObject) lookupDataObject validationError name lib =   getDataType name lib validationError >>= coerceDataObject validationError @@ -504,11 +504,10 @@   -> Key   -> DataTypeLib   -> DataField-  -> m [DataObject]-lookupUnionTypes position key lib DataField { fieldType = TypeAlias { aliasTyCon = typeName } }+  -> m [(Name,DataObject)]+lookupUnionTypes position key lib DataField { fieldType = TypeRef { typeConName = typeName } }   = lookupDataUnion gqlError typeName lib     >>= mapM (flip (lookupDataObject gqlError) lib)-    .   typeData   where gqlError = hasNoSubfields key typeName position  lookupFieldAsSelectionSet@@ -517,10 +516,10 @@   -> Key   -> DataTypeLib   -> DataField-  -> m DataObject-lookupFieldAsSelectionSet position key lib DataField { fieldType = TypeAlias { aliasTyCon } }-  = lookupDataObject gqlError aliasTyCon lib-  where gqlError = hasNoSubfields key aliasTyCon position+  -> m (Name,DataObject)+lookupFieldAsSelectionSet position key lib DataField { fieldType = TypeRef { typeConName } }+  = lookupDataObject gqlError typeConName lib+  where gqlError = hasNoSubfields key typeConName position  lookupInputType :: Failure e m => Key -> DataTypeLib -> e -> m DataType lookupInputType name lib errors = case lookupDataType name lib of@@ -528,19 +527,19 @@   _                          -> failure errors  isTypeDefined :: Key -> DataTypeLib -> Maybe DataFingerprint-isTypeDefined name lib =-  fromDataType typeFingerprint <$> lookupDataType name lib+isTypeDefined name lib = typeFingerprint <$> lookupDataType name lib  defineType :: (Key, DataType) -> DataTypeLib -> DataTypeLib-defineType (key, datatype@(DataInputUnion DataTyCon { typeName, typeData = enumKeys, typeFingerprint })) lib+defineType (key, datatype@DataType { typeName, typeContent = DataInputUnion enumKeys, typeFingerprint }) lib   = lib { types = insert name unionTags (insert key datatype (types lib)) }  where   name      = typeName <> "Tags"-  unionTags = DataEnum DataTyCon { typeName        = name-                                 , typeFingerprint-                                 , typeMeta        = Nothing-                                 , typeData = map createEnumValue enumKeys-                                 }+  unionTags = DataType+    { typeName        = name+    , typeFingerprint+    , typeMeta        = Nothing+    , typeContent     = DataEnum $ map (createEnumValue . fst) enumKeys+    } defineType (key, datatype) lib =   lib { types = insert key datatype (types lib) } @@ -560,33 +559,19 @@                                                        }           )   _ -> internalError "Query Not Defined"-  ------------------------------------------------------------------------------------------  where   takeByKey key lib = case lookup key lib of-    Just (DataObject value) -> (Just (key, value), filter ((/= key) . fst) lib)-    _                       -> (Nothing, lib)+    Just dt@DataType { typeContent = DataObject {} } ->+      (Just (key, dt), filter ((/= key) . fst) lib)+    _ -> (Nothing, lib)   createInputUnionFields :: Key -> [Key] -> [(Key, DataField)] createInputUnionFields name members = fieldTag : map unionField members  where   fieldTag =-    ( "tag"-    , DataField { fieldName     = "tag"+    ( "__typename"+    , DataField { fieldName     = "__typename"                 , fieldArgs     = []                 , fieldArgsType = Nothing                 , fieldType     = createAlias (name <> "Tags")@@ -599,17 +584,17 @@       { fieldArgs     = []       , fieldArgsType = Nothing       , fieldName     = memberName-      , fieldType     = TypeAlias { aliasTyCon    = memberName-                                  , aliasWrappers = [TypeMaybe]-                                  , aliasArgs     = Nothing+      , fieldType     = TypeRef { typeConName    = memberName+                                  , typeWrappers = [TypeMaybe]+                                  , typeArgs     = Nothing                                   }       , fieldMeta     = Nothing       }     ) -createAlias :: Key -> TypeAlias-createAlias aliasTyCon =-  TypeAlias { aliasTyCon, aliasWrappers = [], aliasArgs = Nothing }+createAlias :: Key -> TypeRef+createAlias typeConName =+  TypeRef { typeConName, typeWrappers = [], typeArgs = Nothing }   type TypeUpdater = LibUpdater DataTypeLib@@ -617,11 +602,10 @@ insertType :: (Key, DataType) -> TypeUpdater insertType nextType@(name, datatype) lib = case isTypeDefined name lib of   Nothing -> resolveUpdates (defineType nextType lib) []-  Just fingerprint-    | fingerprint == fromDataType typeFingerprint datatype -> return lib-    |+  Just fingerprint | fingerprint == typeFingerprint datatype -> return lib+                   |       -- throw error if 2 different types has same name-      otherwise -> failure $ nameCollisionError name+                     otherwise -> failure $ nameCollisionError name   -- TEMPLATE HASKELL DATA TYPES
− src/Data/Morpheus/Types/Internal/AST/Operation.hs
@@ -1,88 +0,0 @@-{-# LANGUAGE DeriveLift         #-}-{-# LANGUAGE NamedFieldPuns     #-}-{-# LANGUAGE FlexibleInstances  #-}-{-# LANGUAGE OverloadedStrings  #-}--module Data.Morpheus.Types.Internal.AST.Operation-  ( Operation(..)-  , Variable(..)-  , ValidOperation-  , RawOperation-  , VariableDefinitions-  , ValidVariables-  , DefaultValue-  , getOperationName-  , getOperationDataType-  )-where--import           Data.Maybe                     ( fromMaybe )-import           Language.Haskell.TH.Syntax     ( Lift(..) )---- MORPHEUS-import           Data.Morpheus.Error.Mutation   ( mutationIsNotDefined )-import           Data.Morpheus.Error.Subscription-                                                ( subscriptionIsNotDefined )-import           Data.Morpheus.Types.Internal.AST.Selection-                                                ( Arguments-                                                , SelectionSet-                                                , RawSelectionSet-                                                )--import           Data.Morpheus.Types.Internal.Resolving.Core-                                                ( Validation ,Failure(..) )-import           Data.Morpheus.Types.Internal.AST.Base-                                                ( Collection-                                                , Key-                                                , Position-                                                )-import           Data.Morpheus.Types.Internal.AST.Data-                                                ( OperationType(..)-                                                , TypeWrapper-                                                , DataTypeLib(..)-                                                , DataObject-                                                )-import           Data.Morpheus.Types.Internal.AST.Value-                                                ( Value )--type DefaultValue = Maybe Value--type VariableDefinitions = Collection (Variable DefaultValue)--type ValidVariables = Collection (Variable Value)--type ValidOperation = Operation Arguments SelectionSet--type RawOperation = Operation VariableDefinitions RawSelectionSet--getOperationName :: Maybe Key -> Key-getOperationName = fromMaybe "AnonymousOperation"--data Operation args sel = Operation-  { operationName      :: Maybe Key-  , operationType      :: OperationType-  , operationArgs      :: args-  , operationSelection :: sel-  , operationPosition  :: Position-  } deriving (Show,Lift)--data Variable a = Variable-  { variableType         :: Key-  , isVariableRequired   :: Bool-  , variableTypeWrappers :: [TypeWrapper]-  , variablePosition     :: Position-  , variableValue        :: a-  } deriving (Show,Lift)--getOperationDataType :: Operation a b -> DataTypeLib -> Validation DataObject-getOperationDataType Operation { operationType = Query } lib =-  pure $ snd $ query lib-getOperationDataType Operation { operationType = Mutation, operationPosition } lib-  = case mutation lib of-    Just (_, mutation') -> pure mutation'-    Nothing             -> failure $ mutationIsNotDefined operationPosition-getOperationDataType Operation { operationType = Subscription, operationPosition } lib-  = case subscription lib of-    Just (_, subscription') -> pure subscription'-    Nothing                 -> failure $ subscriptionIsNotDefined operationPosition-
src/Data/Morpheus/Types/Internal/AST/Selection.hs view
@@ -1,95 +1,179 @@-{-# LANGUAGE DeriveLift #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE NamedFieldPuns     #-}+{-# LANGUAGE DeriveLift         #-}+{-# LANGUAGE KindSignatures     #-}+{-# LANGUAGE DataKinds          #-}+{-# LANGUAGE GADTs              #-}+{-# LANGUAGE OverloadedStrings  #-}+{-# LANGUAGE FlexibleInstances  #-} + module Data.Morpheus.Types.Internal.AST.Selection   ( Argument(..)   , Arguments   , SelectionSet-  , SelectionRec(..)-  , ValueOrigin(..)+  , SelectionContent(..)   , ValidSelection   , Selection(..)-  , RawSelection'+  , RawSelection   , FragmentLib   , RawArguments   , RawSelectionSet   , Fragment(..)-  , RawArgument(..)-  , RawSelection(..)+  , RawArgument+  , ValidSelectionSet+  , ValidArgument+  , ValidArguments+  , RawSelectionRec+  , ValidSelectionRec+  , Operation(..)+  , Variable(..)+  , ValidOperation+  , RawOperation+  , VariableDefinitions+  , ValidVariables+  , DefaultValue+  , getOperationName+  , getOperationDataType+  , getOperationObject   ) where -import           Language.Haskell.TH.Syntax     ( Lift ) +import           Data.Maybe                     ( fromMaybe )+import           Data.Semigroup                 ( (<>) )+import           Language.Haskell.TH.Syntax     ( Lift(..) )  -- MORPHEUS+import           Data.Morpheus.Error.Mutation   ( mutationIsNotDefined )+import           Data.Morpheus.Error.Subscription+                                                ( subscriptionIsNotDefined ) import           Data.Morpheus.Types.Internal.AST.Base                                                 ( Collection                                                 , Key                                                 , Position                                                 , Ref(..)+                                                , Name+                                                , VALID+                                                , RAW+                                                , Stage                                                 )-+import           Data.Morpheus.Types.Internal.Resolving.Core+                                                ( Validation+                                                , Failure(..)+                                                )+import           Data.Morpheus.Types.Internal.AST.Data+                                                ( OperationType(..)+                                                , DataTypeLib(..)+                                                , DataType(..)+                                                , DataTypeContent(..)+                                                , DataObject+                                                ) import           Data.Morpheus.Types.Internal.AST.Value-                                                ( Value )+                                                ( Value+                                                , Variable(..)+                                                , ResolvedValue+                                                )  --- RAW SELECTION--type RawSelection' a = Selection RawArguments a+data Fragment = Fragment+  { fragmentType      :: Key+  , fragmentPosition  :: Position+  , fragmentSelection :: RawSelectionSet+  } deriving (Show,Lift)  type FragmentLib = [(Key, Fragment)] -type RawArguments = Collection RawArgument+data Argument (valid :: Stage) = Argument {+    argumentValue    :: Value valid+  , argumentPosition :: Position+  } deriving (Show,Lift) -type RawSelectionSet = Collection RawSelection+type RawArgument = Argument RAW -data Fragment = Fragment-  { fragmentType      :: Key-  , fragmentPosition  :: Position-  , fragmentSelection :: RawSelectionSet-  } deriving (Show, Lift)+type ValidArgument = Argument VALID -data RawArgument-  = VariableRef Ref-  | RawArgument Argument-  deriving (Show, Lift)+type Arguments a = Collection (Argument a) -data RawSelection-  = RawSelectionSet (RawSelection' RawSelectionSet)-  | RawSelectionField (RawSelection' ())-  | InlineFragment Fragment-  | Spread Ref-  deriving (Show,Lift)+type RawArguments = Arguments RAW --- VALID SELECTION -type Arguments = Collection Argument+type ValidArguments = Collection ValidArgument -type SelectionSet = Collection ValidSelection+data SelectionContent (valid :: Stage) where+  SelectionField ::SelectionContent valid+  SelectionSet   ::SelectionSet valid -> SelectionContent valid+  UnionSelection ::UnionSelection -> SelectionContent VALID -type ValidSelection = Selection Arguments SelectionRec+deriving instance Show (SelectionContent a)+deriving instance Lift (SelectionContent a) -type UnionSelection = Collection SelectionSet+type RawSelectionRec = SelectionContent RAW+type ValidSelectionRec = SelectionContent VALID+type UnionSelection = Collection (SelectionSet VALID)+type SelectionSet a = Collection (Selection a)+type RawSelectionSet = Collection RawSelection+type ValidSelectionSet = Collection ValidSelection -data ValueOrigin-  = VARIABLE-  | INLINE-  deriving (Show, Lift) -data Argument = Argument-  { argumentValue    :: Value-  , argumentOrigin   :: ValueOrigin-  , argumentPosition :: Position-  } deriving (Show, Lift)+data Selection (valid:: Stage) where+    Selection ::{+      selectionArguments :: Arguments valid+    , selectionPosition  :: Position+    , selectionAlias     :: Maybe Key+    , selectionContent   :: SelectionContent valid+    } -> Selection valid+    InlineFragment ::Fragment -> Selection RAW+    Spread ::Ref -> Selection RAW -data Selection args rec = Selection-  { selectionArguments :: args-  , selectionPosition  :: Position-  , selectionAlias     :: Maybe Key-  , selectionRec       :: rec+deriving instance Show (Selection a)+deriving instance Lift (Selection a)++type RawSelection = Selection RAW+type ValidSelection = Selection VALID++type DefaultValue = Maybe ResolvedValue++type VariableDefinitions = Collection (Variable RAW)++type ValidVariables = Collection (Variable VALID)++data Operation (stage:: Stage) = Operation+  { operationName      :: Maybe Key+  , operationType      :: OperationType+  , operationArguments :: Collection (Variable stage)+  , operationSelection :: SelectionSet stage+  , operationPosition  :: Position   } deriving (Show,Lift) -data SelectionRec-  = SelectionSet SelectionSet-  | UnionSelection UnionSelection-  | SelectionField-  deriving (Show)+type RawOperation = Operation RAW++type ValidOperation = Operation VALID+++getOperationName :: Maybe Key -> Key+getOperationName = fromMaybe "AnonymousOperation"++getOperationObject+  :: Operation a -> DataTypeLib -> Validation (Name, DataObject)+getOperationObject op lib = do+  dt <- getOperationDataType op lib+  case dt of+    DataType { typeContent = DataObject x, typeName } -> pure (typeName, x)+    DataType { typeName } ->+      failure+        $  "Type Mismatch: operation \""+        <> typeName+        <> "\" must be an Object"++getOperationDataType :: Operation a -> DataTypeLib -> Validation DataType+getOperationDataType Operation { operationType = Query } lib =+  pure $ snd $ query lib+getOperationDataType Operation { operationType = Mutation, operationPosition } lib+  = case mutation lib of+    Just (_, mutation') -> pure mutation'+    Nothing             -> failure $ mutationIsNotDefined operationPosition+getOperationDataType Operation { operationType = Subscription, operationPosition } lib+  = case subscription lib of+    Just (_, subscription') -> pure subscription'+    Nothing -> failure $ subscriptionIsNotDefined operationPosition+
src/Data/Morpheus/Types/Internal/AST/Value.hs view
@@ -1,8 +1,14 @@+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE DeriveGeneric       #-} {-# LANGUAGE DeriveLift          #-} {-# LANGUAGE FlexibleInstances   #-} {-# LANGUAGE OverloadedStrings   #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE DataKinds           #-}+{-# LANGUAGE GADTs               #-}+{-# LANGUAGE TemplateHaskell     #-}  module Data.Morpheus.Types.Internal.AST.Value   ( Value(..)@@ -13,6 +19,14 @@   , decodeScientific   , convertToJSONName   , convertToHaskellName+  , RawValue+  , ValidValue+  , RawObject+  , ValidObject+  , Variable(..)+  , ResolvedValue+  , ResolvedObject+  , VariableContent(..)   ) where @@ -30,16 +44,31 @@                                                 , floatingOrInteger                                                 ) import           Data.Semigroup                 ( (<>) )-import           Data.Text                      ( Text )+import           Data.Text                      ( Text+                                                , unpack+                                                ) import qualified Data.Text                     as T import qualified Data.Vector                   as V                                                 ( toList ) import           GHC.Generics                   ( Generic ) import           Instances.TH.Lift              ( )-import           Language.Haskell.TH.Syntax     ( Lift )+import           Language.Haskell.TH.Syntax     ( Lift(..) ) +-- MORPHEUS+import           Data.Morpheus.Types.Internal.AST.Base+                                                ( Collection+                                                , Ref(..)+                                                , Name+                                                , RAW+                                                , VALID+                                                , Position+                                                , Stage+                                                , RESOLVED+                                                , TypeRef+                                                ) -isReserved :: Text -> Bool++isReserved :: Name -> Bool isReserved "case"     = True isReserved "class"    = True isReserved "data"     = True@@ -85,7 +114,6 @@   | Boolean Bool   deriving (Show, Generic,Lift) - instance A.ToJSON ScalarValue where   toJSON (Float   x) = A.toJSON x   toJSON (Int     x) = A.toJSON x@@ -98,22 +126,85 @@   parseJSON (A.String v) = pure $ String v   parseJSON notScalar    = fail $ "Expected Scalar got :" <> show notScalar +type family VAR (a:: Stage) :: Stage+type instance VAR RAW = RESOLVED+type instance VAR RESOLVED = RESOLVED+type instance VAR VALID = VALID -type Object = [(Text, Value)]+data VariableContent (stage:: Stage) where+  DefaultValue ::Maybe ResolvedValue -> VariableContent RESOLVED+  ValidVariableValue ::{ validVarContent::ValidValue }-> VariableContent VALID -data Value-  = Object Object-  | List [Value]-  | Enum Text-  | Scalar ScalarValue-  | Null-  deriving (Show, Generic,Lift)+instance Lift (VariableContent a) where+  lift (DefaultValue       x) = [| DefaultValue x |]+  lift (ValidVariableValue x) = [| ValidVariableValue x |] -instance A.ToJSON Value where+deriving instance Show (VariableContent a)++data Variable (stage :: Stage) = Variable+  { variableType         :: TypeRef+  , variablePosition     :: Position+  , variableValue        :: VariableContent (VAR stage)+  } deriving (Show,Lift)++data Value (valid :: Stage) where+  ResolvedVariable::Ref -> Variable VALID -> Value RESOLVED+  VariableValue ::Ref -> Value RAW+  Object  ::Object a -> Value a+  List ::[Value a] -> Value a+  Enum ::Name -> Value a+  Scalar ::ScalarValue -> Value a+  Null ::Value a+++type Object a = Collection (Value a)+type ValidObject = Object VALID+type RawObject = Object RAW+type ResolvedObject = Object RESOLVED+type RawValue = Value RAW+type ValidValue = Value VALID+type ResolvedValue = Value RESOLVED++deriving instance Lift (Value a)++instance Show (Value a) where+  show Null       = "null"+  show (Enum   x) = "" <> unpack x+  show (Scalar x) = show x+  show (ResolvedVariable Ref { refName } Variable { variableValue }) =+    "($" <> unpack refName <> ": " <> show variableValue <> ") "+  show (VariableValue Ref { refName }) = "$" <> unpack refName <> " "+  show (Object        keys           ) = "{" <> foldl toEntry "" keys <> "}"+   where+    toEntry :: String -> (Name, Value a) -> String+    toEntry ""  (key, value) = unpack key <> ":" <> show value+    toEntry txt (key, value) = txt <> ", " <> unpack key <> ":" <> show value+  show (List list) = "[" <> foldl toEntry "" list <> "]"+   where+    toEntry :: String -> Value a -> String+    toEntry ""  value = show value+    toEntry txt value = txt <> ", " <> show value++instance A.ToJSON (Value a) where+  toJSON (ResolvedVariable _ Variable { variableValue = ValidVariableValue x })+    = A.toJSON x+  toJSON (VariableValue Ref { refName }) =+    A.String $ "($ref:" <> refName <> ")"+  toJSON Null            = A.Null+  toJSON (Enum   x     ) = A.String x+  toJSON (Scalar x     ) = A.toJSON x+  toJSON (List   x     ) = A.toJSON x+  toJSON (Object fields) = A.object $ map toEntry fields+    where toEntry (name, value) = name A..= A.toJSON value+  -------------------------------------------+  toEncoding (ResolvedVariable _ Variable { variableValue = ValidVariableValue x })+    = A.toEncoding x+  toEncoding (VariableValue Ref { refName }) =+    A.toEncoding $ "($ref:" <> refName <> ")"   toEncoding Null        = A.toEncoding A.Null   toEncoding (Enum   x ) = A.toEncoding x-  toEncoding (List   x ) = A.toEncoding x   toEncoding (Scalar x ) = A.toEncoding x+  toEncoding (List   x ) = A.toEncoding x   toEncoding (Object []) = A.toEncoding $ A.object []   toEncoding (Object x ) = A.pairs $ foldl1 (<>) $ map encodeField x     where encodeField (key, value) = convertToJSONName key A..= value@@ -123,18 +214,18 @@   Left  float -> Float float   Right int   -> Int int -replaceValue :: A.Value -> Value+replaceValue :: A.Value -> Value a replaceValue (A.Bool   v) = gqlBoolean v replaceValue (A.Number v) = Scalar $ decodeScientific v replaceValue (A.String v) = gqlString v replaceValue (A.Object v) = gqlObject $ map replace (M.toList v)- where-  replace :: (a, A.Value) -> (a, Value)-  replace (key, val) = (key, replaceValue val)+  where+  --replace :: (a, A.Value) -> (a, Value a)+        replace (key, val) = (key, replaceValue val) replaceValue (A.Array li) = gqlList (map replaceValue (V.toList li)) replaceValue A.Null       = gqlNull -instance A.FromJSON Value where+instance A.FromJSON (Value a) where   parseJSON = pure . replaceValue  -- DEFAULT VALUES@@ -144,10 +235,10 @@   gqlBoolean :: Bool -> a   gqlString :: Text -> a   gqlList :: [a] -> a-  gqlObject :: [(Text, a)] -> a+  gqlObject :: [(Name, a)] -> a  -- build GQL Values for Subscription Resolver-instance GQLValue Value where+instance GQLValue (Value a) where   gqlNull    = Null   gqlScalar  = Scalar   gqlBoolean = Scalar . Boolean
src/Data/Morpheus/Types/Internal/Resolving.hs view
@@ -27,6 +27,10 @@     , GQLErrors     , GQLError(..)     , Position+    , resolveEnum+    , resolve__typename+    , DataResolver(..)+    , FieldRes     ) where 
src/Data/Morpheus/Types/Internal/Resolving/Core.hs view
@@ -1,11 +1,12 @@-{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FlexibleInstances     #-} {-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE DeriveFunctor      #-}-{-# LANGUAGE DeriveAnyClass     #-}-{-# LANGUAGE DeriveGeneric      #-}-{-# LANGUAGE DataKinds          #-}-{-# LANGUAGE PolyKinds          #-}-{-# LANGUAGE NamedFieldPuns     #-}+{-# LANGUAGE DeriveFunctor         #-}+{-# LANGUAGE DeriveAnyClass        #-}+{-# LANGUAGE DeriveGeneric         #-}+{-# LANGUAGE DataKinds             #-}+{-# LANGUAGE PolyKinds             #-}+{-# LANGUAGE NamedFieldPuns        #-}+{-# LANGUAGE OverloadedStrings     #-}  module Data.Morpheus.Types.Internal.Resolving.Core   ( GQLError(..)@@ -84,6 +85,10 @@ instance Failure [error] (Result ev error con) where   failure = Failure +instance Failure Text Validation where+  failure text =+    Failure [GQLError { message = "INTERNAL ERROR: " <> text, locations = [] }]+ unpackEvents :: Result event c e a -> [event] unpackEvents Success { events } = events unpackEvents _                  = []@@ -137,20 +142,21 @@   => (ea -> eb)   -> ResultT ea er con m value   -> ResultT eb er con m value-mapEvent func (ResultT ma) = ResultT $ do-  state <- ma-  return $ state { events = map func (events state) }+mapEvent func (ResultT ma) = ResultT $ mapEv <$> ma+ where+  mapEv Success { result, warnings, events } =+    Success { result, warnings, events = map func events }+  mapEv (Failure err) = Failure err  mapFailure   :: Monad m   => (er1 -> er2)   -> ResultT ev er1 con m value   -> ResultT ev er2 con m value-mapFailure f (ResultT ma) = ResultT $ do-  state <- ma-  case state of-    Failure x     -> pure $ Failure (map f x)-    Success x w e -> pure $ Success x (map f w) e+mapFailure f (ResultT ma) = ResultT $ mapF <$> ma+ where+  mapF (Failure x    ) = Failure (map f x)+  mapF (Success x w e) = Success x (map f w) e   -- Helper Functions
src/Data/Morpheus/Types/Internal/Resolving/Resolver.hs view
@@ -14,8 +14,7 @@ {-# LANGUAGE UndecidableInstances  #-}  module Data.Morpheus.Types.Internal.Resolving.Resolver-  ( -    Event(..)+  ( Event(..)   , GQLRootResolver(..)   , UnSubResolver   , Resolver(..)@@ -23,6 +22,7 @@   , MapStrategy(..)   , LiftEither(..)   , resolveObject+  , resolveEnum   , toResponseRes   , withObject   , resolving@@ -32,31 +32,41 @@   , GQLChannel(..)   , ResponseEvent(..)   , ResponseStream+  , resolve__typename+  , DataResolver(..)+  , FieldRes   ) where  import           Control.Monad.Trans.Class      ( MonadTrans(..) ) import           Data.Maybe                     ( fromMaybe )-import           Data.Semigroup                 ( (<>) )+import           Data.Semigroup                 ( (<>)+                                                , Semigroup(..)+                                                ) import           Data.Text                      ( unpack                                                 , pack                                                 )  -- MORPHEUS+import           Data.Morpheus.Error.Internal   ( internalResolvingError ) import           Data.Morpheus.Error.Selection  ( resolvingFailedError                                                 , subfieldsNotSelected                                                 ) import           Data.Morpheus.Types.Internal.AST.Selection                                                 ( Selection(..)-                                                , SelectionRec(..)-                                                , SelectionSet+                                                , SelectionContent(..)                                                 , ValidSelection+                                                , ValidSelectionRec+                                                , ValidSelectionSet+                                                , ValidSelection                                                 ) import           Data.Morpheus.Types.Internal.AST.Base-                                                ( Message , Key )+                                                ( Message+                                                , Key+                                                , Name+                                                ) import           Data.Morpheus.Types.Internal.AST.Data-                                                ( -                                                  MUTATION+                                                ( MUTATION                                                 , OperationType                                                 , QUERY                                                 , SUBSCRIPTION@@ -77,9 +87,11 @@                                                 ) import           Data.Morpheus.Types.Internal.AST.Value                                                 ( GQLValue(..)-                                                , Value+                                                , ValidValue                                                 )-import           Data.Morpheus.Types.IO         (renderResponse, GQLResponse)+import           Data.Morpheus.Types.IO         ( renderResponse+                                                , GQLResponse+                                                ) -- MORPHEUS  class LiftEither (o::OperationType) res where@@ -152,35 +164,75 @@ instance (LiftEither o ResolvingStrategy, Monad m) => Failure GQLErrors (ResolvingStrategy o e m) where   failure = liftEither . pure . Left --- helper functins+-- DataResolver+data DataResolver o e m =+    EnumRes  Name+  | UnionRes  (Name,[FieldRes o e m])+  | ObjectRes  [FieldRes o e m ]+  | UnionRef (FieldRes o e m)+  | InvalidRes Name++instance Semigroup (DataResolver o e m) where+  ObjectRes x <> ObjectRes y = ObjectRes (x <> y)+  _           <> _           = InvalidRes "can't merge: incompatible resolvers"+ withObject   :: (LiftEither o ResolvingStrategy, Monad m)-  => (SelectionSet -> ResolvingStrategy o e m value)+  => (ValidSelectionSet -> ResolvingStrategy o e m value)   -> (Key, ValidSelection)   -> ResolvingStrategy o e m value-withObject f (_, Selection { selectionRec = SelectionSet selection }) =+withObject f (_, Selection { selectionContent = SelectionSet selection }) =   f selection withObject _ (key, Selection { selectionPosition }) =   failure (subfieldsNotSelected key "" selectionPosition)  resolveObject   :: (Monad m, LiftEither o ResolvingStrategy)-  => SelectionSet-  -> [FieldRes o e m]-  -> ResolvingStrategy o e m Value-resolveObject selectionSet fieldResolvers =+  => ValidSelectionSet+  -> DataResolver o e m+  -> ResolvingStrategy o e m ValidValue+resolveObject selectionSet (ObjectRes resolvers) =   gqlObject <$> traverse selectResolver selectionSet  where   selectResolver (key, selection@Selection { selectionAlias }) =     (fromMaybe key selectionAlias, ) <$> lookupRes selection    where     lookupRes sel =-      (fromMaybe (const $ pure gqlNull) $ lookup key fieldResolvers) (key, sel)+      (fromMaybe (const $ pure gqlNull) $ lookup key resolvers) (key, sel)+resolveObject _ _ =+  failure $ internalResolvingError "expected object as resolver" +resolveEnum+  :: (Monad m, LiftEither o ResolvingStrategy)+  => Name+  -> Name+  -> ValidSelectionRec+  -> ResolvingStrategy o e m ValidValue+resolveEnum _        enum SelectionField              = pure $ gqlString enum+resolveEnum typeName enum (UnionSelection selections) = resolveObject+  currentSelection+  resolvers+ where+  enumObjectTypeName = typeName <> "EnumObject"+  currentSelection   = fromMaybe [] $ lookup enumObjectTypeName selections+  resolvers          = ObjectRes+    [ ("enum", const $ pure $ gqlString enum)+    , resolve__typename enumObjectTypeName+    ]+resolveEnum _ _ _ =+  failure $ internalResolvingError "wrong selection on enum value"+++resolve__typename+  :: (Monad m, LiftEither o ResolvingStrategy)+  => Name+  -> (Key, (Key, ValidSelection) -> ResolvingStrategy o e m ValidValue)+resolve__typename name = ("__typename", const $ pure $ gqlString name)+ toResponseRes   :: Monad m-  => ResolvingStrategy o event m Value-  -> ResponseStream event m Value+  => ResolvingStrategy o event m ValidValue+  -> ResponseStream event m ValidValue toResponseRes (ResolveQ resT) = cleanEvents resT toResponseRes (ResolveM resT) = mapEvent Publish resT toResponseRes (ResolveS resT) = ResultT $ handleActions <$> runResultT resT@@ -192,7 +244,8 @@     , events   = [Subscribe $ Event channels eventResolver]     }    where-    eventResolver event = renderResponse <$> runResultT  (unRecResolver subRes event) +    eventResolver event =+      renderResponse <$> runResultT (unRecResolver subRes event)  -- --     @@ -276,7 +329,7 @@  -- RESOLVING type FieldRes o e m-  = (Key, (Key, ValidSelection) -> ResolvingStrategy o e m Value)+  = (Key, (Key, ValidSelection) -> ResolvingStrategy o e m ValidValue)  toResolver   :: (LiftEither o Resolver, Monad m)@@ -290,10 +343,10 @@ resolving   :: forall o e m value    . Monad m-  => (value -> (Key, ValidSelection) -> ResolvingStrategy o e m Value)+  => (value -> (Key, ValidSelection) -> ResolvingStrategy o e m ValidValue)   -> Resolver o e m value   -> (Key, ValidSelection)-  -> ResolvingStrategy o e m Value+  -> ResolvingStrategy o e m ValidValue resolving encode gResolver selection@(fieldName, Selection { selectionPosition })   = _resolve gResolver  where@@ -322,17 +375,16 @@     , warnings = []     }    where-    eventResolver :: e -> StatelessResT m Value+    eventResolver :: e -> StatelessResT m ValidValue     eventResolver event =       convert (unQueryResolver $ res event) >>= unPureSub . _encode      where       unPureSub         :: Monad m-        => ResolvingStrategy SUBSCRIPTION e m Value-        -> StatelessResT m Value+        => ResolvingStrategy SUBSCRIPTION e m ValidValue+        -> StatelessResT m ValidValue       unPureSub (ResolveS x) = cleanEvents x >>= passEvent-       where-          passEvent (RecResolver f) = f event+        where passEvent (RecResolver f) = f event  -- map Resolving strategies  class MapStrategy (from :: OperationType) (to :: OperationType) where@@ -360,7 +412,7 @@ -- Channel  newtype Channel event = Channel {-  unChannel :: StreamChannel event+  _unChannel :: StreamChannel event }  instance (Eq (StreamChannel event)) => Eq (Channel event) where
src/Data/Morpheus/Validation/Document/Validation.hs view
@@ -20,10 +20,13 @@                                                 ( DataField(..)                                                 , DataType(..)                                                 , DataObject-                                                , DataTyCon(..)+                                                , DataTypeContent(..)+                                                , Name                                                 , Key                                                 , RawDataType(..)-                                                , TypeAlias(..)+                                                , TypeRef(..)+                                                , DataFingerprint(..)+                                                , Meta                                                 , isWeaker                                                 , isWeaker                                                 )@@ -37,29 +40,37 @@  where   validateType :: (Key, RawDataType) -> Validation (Maybe (Key, DataType))   validateType (name, FinalDataType x) = pure $ Just (name, x)-  validateType (name, Implements interfaces object) =-    asTuple name <$> object `mustImplement` interfaces+  validateType (name, Implements { implementsName, implementsInterfaces, implementsMeta, implementsContent })+    = asTuple name+      <$>             (implementsName, implementsMeta, implementsContent)+      `mustImplement` implementsInterfaces   validateType _ = pure Nothing   -----------------------------------   asTuple name x = Just (name, x)   ------------------------------------  mustImplement :: DataObject -> [Key] -> Validation DataType-  mustImplement object interfaceKey = do+  mustImplement :: (Name, Maybe Meta, DataObject) -> [Key] -> Validation DataType+  mustImplement (typeName, typeMeta, object) interfaceKey = do     interface <- traverse getInterfaceByKey interfaceKey     case concatMap (mustBeSubset object) interface of-      []     -> pure $ DataObject object-      errors -> failure $ partialImplements (typeName object) errors+      [] -> pure $ DataType { typeName+                            , typeFingerprint = DataFingerprint typeName []+                            , typeMeta+                            , typeContent     = DataObject object+                            }+      errors -> failure $ partialImplements typeName errors   --------------------------------  mustBeSubset :: DataObject -> DataObject -> [(Key, Key, ImplementsError)]-  mustBeSubset DataTyCon { typeData = objFields } DataTyCon { typeName, typeData = interfaceFields }-    = concatMap checkField interfaceFields+  mustBeSubset+    :: DataObject -> (Name, DataObject) -> [(Key, Key, ImplementsError)]+  mustBeSubset objFields (typeName, interfaceFields) = concatMap+    checkField+    interfaceFields    where     checkField :: (Key, DataField) -> [(Key, Key, ImplementsError)]-    checkField (key, DataField { fieldType = interfaceT@TypeAlias { aliasTyCon = interfaceTypeName, aliasWrappers = interfaceWrappers } })+    checkField (key, DataField { fieldType = interfaceT@TypeRef { typeConName = interfaceTypeName, typeWrappers = interfaceWrappers } })       = case lookup key objFields of-        Just DataField { fieldType = objT@TypeAlias { aliasTyCon, aliasWrappers } }-          | aliasTyCon == interfaceTypeName && not-            (isWeaker aliasWrappers interfaceWrappers)+        Just DataField { fieldType = objT@TypeRef { typeConName, typeWrappers } }+          | typeConName == interfaceTypeName && not+            (isWeaker typeWrappers interfaceWrappers)           -> []           | otherwise           -> [ ( typeName@@ -71,7 +82,7 @@              ]         Nothing -> [(typeName, key, UndefinedField)]   --------------------------------  getInterfaceByKey :: Key -> Validation DataObject+  getInterfaceByKey :: Key -> Validation (Name,DataObject)   getInterfaceByKey key = case lookup key lib of-    Just (Interface x) -> pure x-    _                  -> failure $ unknownInterface key+    Just Interface { interfaceContent } -> pure (key,interfaceContent)+    _ -> failure $ unknownInterface key
src/Data/Morpheus/Validation/Internal/Value.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE GADTs #-} {-# LANGUAGE NamedFieldPuns    #-} {-# LANGUAGE OverloadedStrings #-} @@ -10,104 +11,190 @@ import           Data.List                      ( elem )  -- MORPHEUS+import           Data.Morpheus.Error.Variable   ( incompatibleVariableType ) import           Data.Morpheus.Error.Input      ( InputError(..)                                                 , InputValidation                                                 , Prop(..)                                                 )-import           Data.Morpheus.Rendering.RenderGQL-                                                ( renderWrapped ) import           Data.Morpheus.Types.Internal.AST                                                 ( DataField(..)-                                                , DataTyCon(..)+                                                , DataTypeContent(..)                                                 , DataType(..)                                                 , DataTypeLib(..)                                                 , DataValidator(..)                                                 , Key-                                                , TypeAlias(..)+                                                , TypeRef(..)                                                 , TypeWrapper(..)                                                 , DataEnumValue(..)-                                                , isNullable                                                 , lookupField                                                 , lookupInputType                                                 , Value(..)+                                                , ValidValue+                                                , Variable(..)+                                                , Ref(..)+                                                , isWeaker+                                                , DataScalar+                                                , Message+                                                , Name+                                                , ResolvedValue+                                                , VALID+                                                , VariableContent(..)+                                                , unpackInputUnion+                                                , isFieldNullable+                                                , TypeRef(..)+                                                , isNullableWrapper                                                 )  import           Data.Morpheus.Types.Internal.Resolving                                                 ( Failure(..) )+import           Data.Morpheus.Rendering.RenderGQL+                                                ( RenderGQL(..) ) +checkTypeEquality+  :: (Name, [TypeWrapper])+  -> Ref+  -> Variable VALID+  -> InputValidation ValidValue+checkTypeEquality (tyConName, tyWrappers) Ref { refName, refPosition } Variable { variableValue = ValidVariableValue value, variableType }+  | typeConName variableType == tyConName && not+    (isWeaker (typeWrappers variableType) tyWrappers)+  = pure value+  | otherwise+  = failure $ GlobalInputError $ incompatibleVariableType refName+                                                          varSignature+                                                          fieldSignature+                                                          refPosition+ where+  varSignature   = render variableType+  fieldSignature = render TypeRef { typeConName  = tyConName+                                  , typeWrappers = tyWrappers+                                  , typeArgs     = Nothing+                                  }+++ -- Validate Variable Argument or all Possible input Values validateInputValue   :: DataTypeLib   -> [Prop]   -> [TypeWrapper]   -> DataType-  -> (Key, Value)-  -> InputValidation Value-validateInputValue lib prop' = validate+  -> (Key, ResolvedValue)+  -> InputValidation ValidValue+validateInputValue lib props rw datatype@DataType { typeContent, typeName } =+  validateWrapped rw typeContent  where-  throwError :: [TypeWrapper] -> DataType -> Value -> InputValidation Value-  throwError wrappers datatype value =-    Left $ UnexpectedType prop' (renderWrapped datatype wrappers) value Nothing+  throwError :: [TypeWrapper] -> ResolvedValue -> InputValidation ValidValue+  throwError wrappers value =+    Left $ UnexpectedType props (renderWrapped datatype wrappers) value Nothing   -- VALIDATION-  validate :: [TypeWrapper] -> DataType -> (Key, Value) -> InputValidation Value+  validateWrapped+    :: [TypeWrapper]+    -> DataTypeContent+    -> (Key, ResolvedValue)+    -> InputValidation ValidValue   -- Validate Null. value = null ?-  validate wrappers tName (_, Null) | isNullable wrappers = return Null-                                    | otherwise = throwError wrappers tName Null+  validateWrapped wrappers _ (_, ResolvedVariable ref variable) =+    checkTypeEquality (typeName, wrappers) ref variable+  validateWrapped wrappers _ (_, Null)+    | isNullableWrapper wrappers = return Null+    | otherwise                  = throwError wrappers Null   -- Validate LIST-  validate (TypeMaybe : wrappers) type' value' =-    validateInputValue lib prop' wrappers type' value'-  validate (TypeList : wrappers) type' (key', List list') =-    List <$> mapM validateElement list'+  validateWrapped (TypeMaybe : wrappers) _ value =+    validateInputValue lib props wrappers datatype value+  validateWrapped (TypeList : wrappers) _ (key, List list) =+    List <$> mapM validateElement list    where-    validateElement element' =-      validateInputValue lib prop' wrappers type' (key', element')+    validateElement element =+      validateInputValue lib props wrappers datatype (key, element)   {-- 2. VALIDATE TYPES, all wrappers are already Processed --}   {-- VALIDATE OBJECT--}-  validate [] (DataInputObject DataTyCon { typeData = parentFields' }) (_, Object fields)-    = Object <$> mapM validateField fields+  validateWrapped [] dt v = validate dt v    where-    validateField (_name, value) = do-      (type', currentProp') <- validationData value-      wrappers'             <- aliasWrappers . fieldType <$> getField-      value''               <- validateInputValue lib-                                                  currentProp'-                                                  wrappers'-                                                  type'-                                                  (_name, value)-      return (_name, value'')+    validate+      :: DataTypeContent -> (Key, ResolvedValue) -> InputValidation ValidValue+    validate (DataInputObject parentFields) (_, Object fields) =+      traverse requiredFieldsDefined parentFields+        >>  Object+        <$> traverse validateField fields      where-      validationData x = do-        fieldTypeName' <- aliasTyCon . fieldType <$> getField-        let currentProp = prop' ++ [Prop _name fieldTypeName']-        type' <- lookupInputType fieldTypeName'-                                 lib-                                 (typeMismatch x fieldTypeName' currentProp)-        return (type', currentProp)-      getField = lookupField _name parentFields' (UnknownField prop' _name)-  -- VALIDATE INPUT UNION-  -- TODO: Validate Union-  validate [] (DataInputUnion DataTyCon { typeData }) (_, Object fields) =-    return (Object fields)-  {-- VALIDATE SCALAR --}-  validate [] (DataEnum DataTyCon { typeData = tags, typeName = name' }) (_, value')-    = validateEnum (UnexpectedType prop' name' value' Nothing) tags value'-  {-- VALIDATE ENUM --}-  validate [] (DataScalar DataTyCon { typeName = name', typeData = DataValidator { validateValue = validator' } }) (_, value')-    = case validator' value' of-      Right _  -> return value'-      Left  "" -> failure (UnexpectedType prop' name' value' Nothing)-      Left errorMessage ->-        Left $ UnexpectedType prop' name' value' (Just errorMessage)-  {-- 3. THROW ERROR: on invalid values --}-  validate wrappers datatype (_, value) = throwError wrappers datatype value+      requiredFieldsDefined (fName, datafield)+        | fName `elem` map fst fields || isFieldNullable datafield = pure ()+        | otherwise = failure (UndefinedField props fName)+      validateField+        :: (Name, ResolvedValue) -> InputValidation (Name, ValidValue)+      validateField (_name, value) = do+        (type', currentProp') <- validationData value+        wrappers'             <- typeWrappers . fieldType <$> getField+        value''               <- validateInputValue lib+                                                    currentProp'+                                                    wrappers'+                                                    type'+                                                    (_name, value)+        return (_name, value'')+       where+        validationData :: ResolvedValue -> InputValidation (DataType, [Prop])+        validationData x = do+          fieldTypeName' <- typeConName . fieldType <$> getField+          let currentProp = props ++ [Prop _name fieldTypeName']+          type' <- lookupInputType fieldTypeName'+                                   lib+                                   (typeMismatch x fieldTypeName' currentProp)+          return (type', currentProp)+        getField = lookupField _name parentFields (UnknownField props _name)+    -- VALIDATE INPUT UNION+    validate (DataInputUnion inputUnion) (_, Object rawFields) =+      case unpackInputUnion inputUnion rawFields of+        Left message -> failure+          $ UnexpectedType props typeName (Object rawFields) (Just message)+        Right (name, Nothing   ) -> return (Object [("__typename", Enum name)])+        Right (name, Just value) -> do+          currentUnionDatatype <- lookupInputType+            name+            lib+            (typeMismatch value name props)+          validValue <- validateInputValue lib+                                           props+                                           [TypeMaybe]+                                           currentUnionDatatype+                                           (name, value)+          return (Object [("__typename", Enum name), (name, validValue)]) -validateEnum :: error -> [DataEnumValue] -> Value -> Either error Value+    {-- VALIDATE ENUM --}+    validate (DataEnum tags) (_, value) =+      validateEnum (UnexpectedType props typeName value Nothing) tags value+    {-- VALIDATE SCALAR --}+    validate (DataScalar dataScalar) (_, value) =+      validateScalar dataScalar value (UnexpectedType props typeName)+    validate _ (_, value) = throwError [] value+    {-- 3. THROW ERROR: on invalid values --}+  validateWrapped wrappers _ (_, value) = throwError wrappers value+++validateScalar+  :: DataScalar+  -> ResolvedValue+  -> (ResolvedValue -> Maybe Message -> InputError)+  -> InputValidation ValidValue+validateScalar DataValidator { validateValue } value err = do+  scalarValue <- toScalar value+  case validateValue scalarValue of+    Right _            -> return scalarValue+    Left  ""           -> failure (err value Nothing)+    Left  errorMessage -> failure $ err value (Just errorMessage)+ where+  toScalar :: ResolvedValue -> InputValidation ValidValue+  toScalar (Scalar x) = pure (Scalar x)+  toScalar scValue    = Left (err scValue Nothing)++validateEnum+  :: error -> [DataEnumValue] -> ResolvedValue -> Either error ValidValue validateEnum gqlError enumValues (Enum enumValue)   | enumValue `elem` tags = pure (Enum enumValue)   | otherwise             = Left gqlError   where tags = map enumName enumValues validateEnum gqlError _ _ = Left gqlError -typeMismatch :: Value -> Key -> [Prop] -> InputError+typeMismatch :: ResolvedValue -> Key -> [Prop] -> InputError typeMismatch jsType expected' path' =   UnexpectedType path' expected' jsType Nothing
src/Data/Morpheus/Validation/Query/Arguments.hs view
@@ -1,11 +1,13 @@+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE GADTs #-} {-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE TupleSections  #-}  module Data.Morpheus.Validation.Query.Arguments   ( validateArguments   ) where +import           Data.Maybe                     ( maybe ) import           Data.Morpheus.Error.Arguments  ( argumentGotInvalidValue                                                 , argumentNameCollision                                                 , undefinedArgument@@ -15,29 +17,30 @@                                                 , inputErrorMessage                                                 ) import           Data.Morpheus.Error.Internal   ( internalUnknownTypeMessage )-import           Data.Morpheus.Error.Variable   ( incompatibleVariableType-                                                , undefinedVariable-                                                )-import           Data.Morpheus.Rendering.RenderGQL-                                                ( RenderGQL(..) )+import           Data.Morpheus.Error.Variable   ( undefinedVariable ) import           Data.Morpheus.Types.Internal.AST                                                 ( ValidVariables                                                 , Variable(..)                                                 , Argument(..)-                                                , ValueOrigin(..)-                                                , Arguments-                                                , RawArgument(..)+                                                , RawArgument                                                 , RawArguments+                                                , ValidArgument+                                                , ValidArguments+                                                , Arguments                                                 , Ref(..)                                                 , Position                                                 , DataArgument                                                 , DataField(..)                                                 , DataTypeLib-                                                , TypeAlias(..)+                                                , TypeRef(..)                                                 , isFieldNullable-                                                , isWeaker                                                 , lookupInputType-                                                , Value(Null)+                                                , Value(..)+                                                , Name+                                                , RawValue+                                                , ResolvedValue+                                                , RESOLVED+                                                , VALID                                                 ) import           Data.Morpheus.Types.Internal.Resolving                                                 ( Validation@@ -51,74 +54,86 @@                                                 ( validateInputValue ) import           Data.Text                      ( Text ) +-- only Resolves , doesnot checks the types+resolveObject :: Name -> ValidVariables -> RawValue -> Validation ResolvedValue+resolveObject operationName variables = resolve+ where+  resolve :: RawValue -> Validation ResolvedValue+  resolve Null         = pure Null+  resolve (Scalar x  ) = pure $ Scalar x+  resolve (Enum   x  ) = pure $ Enum x+  resolve (List   x  ) = List <$> traverse resolve x+  resolve (Object obj) = Object <$> traverse mapSecond obj+    where mapSecond (fName, y) = (fName, ) <$> resolve y+  resolve (VariableValue ref) =+    ResolvedVariable ref <$> variableByRef operationName variables ref+    --  >>= checkTypeEquality ref fieldType+  -- RAW | RESOLVED | Valid ++variableByRef :: Name -> ValidVariables -> Ref -> Validation (Variable VALID)+variableByRef operationName variables Ref { refName, refPosition } = maybe+  variableError+  pure+  (lookup refName variables)+ where+  variableError = failure $ undefinedVariable operationName refPosition refName+++ resolveArgumentVariables-  :: Text -> ValidVariables -> DataField -> RawArguments -> Validation Arguments-resolveArgumentVariables operatorName variables DataField { fieldName, fieldArgs }+  :: Name+  -> ValidVariables+  -> DataField+  -> RawArguments+  -> Validation (Arguments RESOLVED)+resolveArgumentVariables operationName variables DataField { fieldName, fieldArgs }   = mapM resolveVariable  where-  resolveVariable :: (Text, RawArgument) -> Validation (Text, Argument)-  resolveVariable (key, RawArgument argument) = pure (key, argument)-  resolveVariable (key, VariableRef Ref { refName, refPosition }) =-    (key, ) . toArgument <$> lookupVar-   where-    toArgument argumentValue = Argument { argumentValue-                                        , argumentOrigin   = VARIABLE-                                        , argumentPosition = refPosition-                                        }-    lookupVar = case lookup refName variables of-      Nothing -> failure $ undefinedVariable operatorName refPosition refName-      Just Variable { variableValue, variableType, variableTypeWrappers } ->-        case lookup key fieldArgs of-          Nothing -> failure $ unknownArguments fieldName [Ref key refPosition]-          Just DataField { fieldType = fieldT@TypeAlias { aliasTyCon, aliasWrappers } }-            -> if variableType == aliasTyCon && not-                 (isWeaker variableTypeWrappers aliasWrappers)-              then return variableValue-              else failure $ incompatibleVariableType refName-                                                      varSignature-                                                      fieldSignature-                                                      refPosition-           where-            varSignature   = renderWrapped variableType variableTypeWrappers-            fieldSignature = render fieldT+  resolveVariable :: (Text, RawArgument) -> Validation (Text, Argument RESOLVED)+  resolveVariable (key, Argument val position) = case lookup key fieldArgs of+    Nothing -> failure $ unknownArguments fieldName [Ref key position]+    Just _  -> do+      constValue <- resolveObject operationName variables val+      pure (key, Argument constValue position)  validateArgument   :: DataTypeLib   -> Position-  -> Arguments+  -> Arguments RESOLVED   -> (Text, DataArgument)-  -> Validation (Text, Argument)-validateArgument lib fieldPosition requestArgs (key, argType@DataField { fieldType = TypeAlias { aliasTyCon, aliasWrappers } })+  -> Validation (Text, ValidArgument)+validateArgument lib fieldPosition requestArgs (key, argType@DataField { fieldType = TypeRef { typeConName, typeWrappers } })   = case lookup key requestArgs of     Nothing -> handleNullable-    Just argument@Argument { argumentOrigin = VARIABLE } ->-      pure (key, argument) -- Variables are already checked in Variable Validation+    -- TODO: move it in value validation+   -- Just argument@Argument { argumentOrigin = VARIABLE } ->+   --   pure (key, argument) -- Variables are already checked in Variable Validation     Just Argument { argumentValue = Null } -> handleNullable-    Just argument                          -> validateArgumentValue argument+    Just argument -> validateArgumentValue argument  where   handleNullable-    | isFieldNullable argType = pure-      ( key-      , Argument { argumentValue    = Null-                 , argumentOrigin   = INLINE-                 , argumentPosition = fieldPosition-                 }-      )-    | otherwise = failure $ undefinedArgument (Ref key fieldPosition)+    | isFieldNullable argType+    = pure+      (key, Argument { argumentValue = Null, argumentPosition = fieldPosition })+    | otherwise+    = failure $ undefinedArgument (Ref key fieldPosition)   --------------------------------------------------------------------------  validateArgumentValue :: Argument -> Validation (Text, Argument)-  validateArgumentValue arg@Argument { argumentValue, argumentPosition } =-    lookupInputType aliasTyCon lib (internalUnknownTypeMessage aliasTyCon)-      >>= checkType-      >>  pure (key, arg)+  validateArgumentValue :: Argument RESOLVED -> Validation (Text, ValidArgument)+  validateArgumentValue Argument { argumentValue = value, argumentPosition } =+    do+      datatype <- lookupInputType typeConName+                                  lib+                                  (internalUnknownTypeMessage typeConName)+      argumentValue <- handleInputError+        $ validateInputValue lib [] typeWrappers datatype (key, value)+      pure (key, Argument { argumentValue, argumentPosition })    where-    checkType type' = handleInputError-      (validateInputValue lib [] aliasWrappers type' (key, argumentValue))     ----------    handleInputError :: InputValidation a -> Validation ()-    handleInputError (Left err) = failure-      $ argumentGotInvalidValue key (inputErrorMessage err) argumentPosition-    handleInputError _ = pure ()+    handleInputError :: InputValidation a -> Validation a+    handleInputError (Left err) = failure $ case inputErrorMessage err of+      Left  errors  -> errors+      Right message -> argumentGotInvalidValue key message argumentPosition+    handleInputError (Right x) = pure x  validateArguments   :: DataTypeLib@@ -127,14 +142,15 @@   -> (Text, DataField)   -> Position   -> RawArguments-  -> Validation Arguments+  -> Validation ValidArguments validateArguments typeLib operatorName variables (key, field@DataField { fieldArgs }) pos rawArgs   = do     args     <- resolveArgumentVariables operatorName variables field rawArgs     dataArgs <- checkForUnknownArguments args     mapM (validateArgument typeLib pos args) dataArgs  where-  checkForUnknownArguments :: Arguments -> Validation [(Text, DataField)]+  checkForUnknownArguments+    :: Arguments RESOLVED -> Validation [(Text, DataField)]   checkForUnknownArguments args =     checkForUnknownKeys enhancedKeys fieldKeys argError       >> checkNameCollision enhancedKeys argumentNameCollision@@ -142,5 +158,6 @@    where     argError     = unknownArguments key     enhancedKeys = map argToKey args+    argToKey :: (Name, Argument RESOLVED) -> Ref     argToKey (key', Argument { argumentPosition }) = Ref key' argumentPosition     fieldKeys = map fst fieldArgs
src/Data/Morpheus/Validation/Query/Fragment.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE GADTs #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE NamedFieldPuns #-} @@ -12,8 +13,6 @@ import           Data.List                      ( (\\) ) import           Data.Semigroup                 ( (<>) ) import           Data.Text                      ( Text )-import qualified Data.Text                     as T-                                                ( concat )  -- MORPHEUS import           Data.Morpheus.Error.Fragment   ( cannotBeSpreadOnType@@ -26,7 +25,8 @@ import           Data.Morpheus.Types.Internal.AST                                                 ( Fragment(..)                                                 , FragmentLib-                                                , RawSelection(..)+                                                , RawSelection+                                                , SelectionContent(..)                                                 , Selection(..)                                                 , Ref(..)                                                 , Position@@ -69,11 +69,10 @@  castFragmentType   :: Maybe Text -> Position -> [Text] -> Fragment -> Validation Fragment-castFragmentType key' position' targets' fragment@Fragment { fragmentType } =-  if fragmentType `elem` targets'+castFragmentType key' position' typeMembers fragment@Fragment { fragmentType }+  = if fragmentType `elem` typeMembers     then pure fragment-    else failure-      $ cannotBeSpreadOnType key' fragmentType position' (T.concat targets')+    else failure $ cannotBeSpreadOnType key' fragmentType position' typeMembers  resolveSpread :: FragmentLib -> [Text] -> Ref -> Validation Fragment resolveSpread fragments allowedTargets reference@Ref { refName, refPosition } =@@ -81,27 +80,28 @@     >>= castFragmentType (Just refName) refPosition allowedTargets  usedFragments :: FragmentLib -> [(Text, RawSelection)] -> [Node]-usedFragments fragments = concatMap findAllUses+usedFragments fragments = concatMap (findAllUses . snd)  where-  findAllUses :: (Text, RawSelection) -> [Node]-  findAllUses (_, RawSelectionSet Selection { selectionRec }) =-    concatMap findAllUses selectionRec-  findAllUses (_, InlineFragment Fragment { fragmentSelection }) =-    concatMap findAllUses fragmentSelection-  findAllUses (_, RawSelectionField{}) = []-  findAllUses (_, Spread Ref { refName, refPosition }) =+  findAllUses :: RawSelection -> [Node]+  findAllUses Selection { selectionContent = SelectionField } = []+  findAllUses Selection { selectionContent = SelectionSet selectionSet } =+    concatMap (findAllUses . snd) selectionSet+  findAllUses (InlineFragment Fragment { fragmentSelection }) =+    concatMap (findAllUses . snd) fragmentSelection+  findAllUses (Spread Ref { refName, refPosition }) =     [Ref refName refPosition] <> searchInFragment    where-    searchInFragment = maybe []-                             (concatMap findAllUses . fragmentSelection)-                             (lookup refName fragments)+    searchInFragment = maybe+      []+      (concatMap (findAllUses . snd) . fragmentSelection)+      (lookup refName fragments)  scanForSpread :: (Text, RawSelection) -> [Node]-scanForSpread (_, RawSelectionSet Selection { selectionRec }) =-  concatMap scanForSpread selectionRec+scanForSpread (_, Selection { selectionContent = SelectionField }) = []+scanForSpread (_, Selection { selectionContent = SelectionSet selectionSet }) =+  concatMap scanForSpread selectionSet scanForSpread (_, InlineFragment Fragment { fragmentSelection = selection' }) =   concatMap scanForSpread selection'-scanForSpread (_, RawSelectionField{}) = [] scanForSpread (_, Spread Ref { refName = name', refPosition = position' }) =   [Ref name' position'] 
src/Data/Morpheus/Validation/Query/Selection.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE GADTs #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances   #-} {-# LANGUAGE NamedFieldPuns      #-}@@ -22,21 +23,23 @@                                                 ) import           Data.Morpheus.Error.Variable   ( unknownType ) import           Data.Morpheus.Types.Internal.AST-                                                ( ValidVariables +                                                ( ValidVariables                                                 , Selection(..)-                                                , SelectionRec(..)-                                                , SelectionSet+                                                , SelectionContent(..)+                                                , ValidSelection+                                                , ValidSelectionSet                                                 , Fragment(..)                                                 , FragmentLib-                                                , RawSelection(..)+                                                , RawSelection                                                 , RawSelectionSet                                                 , DataField(..)                                                 , Ref(..)                                                 , DataObject-                                                , DataTyCon(..)+                                                , DataTypeContent(..)                                                 , DataType(..)                                                 , DataTypeLib(..)-                                                , TypeAlias(..)+                                                , TypeRef(..)+                                                , Name                                                 , allDataTypes                                                 , isEntNode                                                 , lookupFieldAsSelectionSet@@ -57,51 +60,52 @@                                                 , resolveSpread                                                 ) -checkDuplicatesOn :: DataObject -> SelectionSet -> Validation SelectionSet-checkDuplicatesOn DataTyCon { typeName = name' } keys =-  checkNameCollision enhancedKeys selError >> pure keys+checkDuplicatesOn :: Name -> ValidSelectionSet -> Validation ValidSelectionSet+checkDuplicatesOn typeName keys = checkNameCollision enhancedKeys selError+  >> pure keys  where-  selError     = duplicateQuerySelections name'+  selError     = duplicateQuerySelections typeName   enhancedKeys = map selToKey keys+  selToKey :: (Name, ValidSelection) -> Ref   selToKey (key, Selection { selectionPosition = position', selectionAlias }) =     Ref (fromMaybe key selectionAlias) position'  clusterUnionSelection   :: FragmentLib   -> Text-  -> [DataObject]+  -> [Name]   -> (Text, RawSelection)-  -> Validation ([Fragment], SelectionSet)-clusterUnionSelection fragments type' possibleTypes' = splitFrag+  -> Validation ([Fragment], ValidSelectionSet)+clusterUnionSelection fragments type' typeNames = splitFrag  where   packFragment fragment = return ([fragment], [])-  typeNames = map typeName possibleTypes'-  splitFrag :: (Text, RawSelection) -> Validation ([Fragment], SelectionSet)+  splitFrag+    :: (Text, RawSelection) -> Validation ([Fragment], ValidSelectionSet)   splitFrag (_, Spread ref) =     resolveSpread fragments typeNames ref >>= packFragment-  splitFrag ("__typename", RawSelectionField selection) = pure-    ( []-    , [ ( "__typename"-        , selection { selectionArguments = [], selectionRec = SelectionField }-        )-      ]-    )-  splitFrag (key, RawSelectionSet Selection { selectionPosition }) =-    failure $ cannotQueryField key type' selectionPosition-  splitFrag (key, RawSelectionField Selection { selectionPosition }) =+  splitFrag ("__typename", selection@Selection { selectionContent = SelectionField })+    = pure+      ( []+      , [ ( "__typename"+          , selection { selectionArguments = [], selectionContent = SelectionField }+          )+        ]+      )+  splitFrag (key, Selection { selectionPosition }) =     failure $ cannotQueryField key type' selectionPosition --  splitFrag (key', RawAlias {rawAliasPosition = position'}) = failure $ cannotQueryField key' type' position'   splitFrag (_, InlineFragment fragment') =     castFragmentType Nothing (fragmentPosition fragment') typeNames fragment'       >>= packFragment -categorizeTypes :: [DataObject] -> [Fragment] -> [(DataObject, [Fragment])]+categorizeTypes+  :: [(Name, DataObject)] -> [Fragment] -> [((Name, DataObject), [Fragment])] categorizeTypes types fragments = filter notEmpty $ map categorizeType types  where   notEmpty = (0 /=) . length . snd-  categorizeType :: DataObject -> (DataObject, [Fragment])+  categorizeType :: (Name, DataObject) -> ((Name, DataObject), [Fragment])   categorizeType datatype = (datatype, filter matches fragments)-    where matches fragment = fragmentType fragment == typeName datatype+    where matches fragment = fragmentType fragment == fst datatype  flatTuple :: [([a], [b])] -> ([a], [b]) flatTuple list' = (concatMap fst list', concatMap snd list')@@ -122,45 +126,51 @@   -> FragmentLib   -> Text   -> ValidVariables-  -> DataObject+  -> (Name, DataObject)   -> RawSelectionSet-  -> Validation SelectionSet+  -> Validation ValidSelectionSet validateSelectionSet lib fragments' operatorName variables = __validate  where-  __validate dataType'@DataTyCon { typeName = typeName' } selectionSet' =+  __validate+    :: (Name, DataObject) -> RawSelectionSet -> Validation ValidSelectionSet+  __validate dataType@(typeName, objectFields) selectionSet =     concat-      <$> mapM validateSelection selectionSet'-      >>= checkDuplicatesOn dataType'+    <$> mapM validateSelection selectionSet+    >>= checkDuplicatesOn typeName    where     validateFragment Fragment { fragmentSelection = selection' } =-      __validate dataType' selection'+      __validate dataType selection'     {-             get dataField and validated arguments for RawSelection         -}-    getValidationData key Selection { selectionArguments, selectionPosition } =-      do-        selectionField <- lookupSelectionField selectionPosition key dataType'-        -- validate field Argument ------        arguments      <- validateArguments lib-                                            operatorName-                                            variables-                                            (key, selectionField)-                                            selectionPosition-                                            selectionArguments-        -- check field Type existence  ------        fieldDataType <- lookupType-          (unknownType (aliasTyCon $fieldType selectionField) selectionPosition)-          (allDataTypes lib)-          (aliasTyCon $ fieldType selectionField)-        return (selectionField, fieldDataType, arguments)+    -- getValidationData :: Name -> ValidSelection -> (DataField, DataTypeContent, ValidArguments)+    getValidationData key (selectionArguments, selectionPosition) = do+      selectionField <- lookupSelectionField selectionPosition+                                             key+                                             typeName+                                             objectFields+      -- validate field Argument -----+      arguments <- validateArguments lib+                                     operatorName+                                     variables+                                     (key, selectionField)+                                     selectionPosition+                                     selectionArguments+      -- check field Type existence  -----+      fieldDataType <- lookupType+        (unknownType (typeConName $fieldType selectionField) selectionPosition)+        (allDataTypes lib)+        (typeConName $ fieldType selectionField)+      return (selectionField, fieldDataType, arguments)     -- validate single selection: InlineFragments and Spreads will Be resolved and included in SelectionSet     ---    validateSelection :: (Text, RawSelection) -> Validation SelectionSet-    validateSelection (key', RawSelectionSet fullRawSelection@Selection { selectionRec = rawSelection, selectionPosition })+    validateSelection :: (Text, RawSelection) -> Validation ValidSelectionSet+    validateSelection (key', fullRawSelection@Selection { selectionArguments = selArgs, selectionContent = SelectionSet rawSelection, selectionPosition })       = do-        (dataField, dataType, arguments) <- getValidationData key'-                                                              fullRawSelection-        case dataType of+        (dataField, datatype, arguments) <- getValidationData+          key'+          (selArgs, selectionPosition)+        case typeContent datatype of           DataUnion _ -> do             (categories, __typename) <- clusterTypes             mapM (validateCluster __typename) categories@@ -175,19 +185,22 @@               (spreads, __typename) <-                 flatTuple                   <$> mapM-                        (clusterUnionSelection fragments' typeName' unionTypes)+                        (   clusterUnionSelection fragments' typeName+                        $   fst+                        <$> unionTypes+                        )                         rawSelection               return (categorizeTypes unionTypes spreads, __typename)             --             --    second arguments will be added to every selection cluster             validateCluster-              :: SelectionSet-              -> (DataObject, [Fragment])-              -> Validation (Text, SelectionSet)+              :: ValidSelectionSet+              -> ((Name, DataObject), [Fragment])+              -> Validation (Text, ValidSelectionSet)             validateCluster sysSelection' (type', frags') = do               selection' <- __validate type'                                        (concatMap fragmentSelection frags')-              return (typeName type', sysSelection' ++ selection')+              return (fst type', sysSelection' ++ selection')           DataObject _ -> do             fieldType' <- lookupFieldAsSelectionSet selectionPosition                                                     key'@@ -197,32 +210,29 @@               >>= returnSelection arguments               .   SelectionSet           _ -> failure $ hasNoSubfields key'-                                        (aliasTyCon $fieldType dataField)+                                        (typeConName $fieldType dataField)                                         selectionPosition      where-      returnSelection selectionArguments selectionRec =-        pure [(key', fullRawSelection { selectionArguments, selectionRec })]-    validateSelection (key, RawSelectionField rawSelection@Selection { selectionPosition })+      returnSelection selectionArguments selectionContent =+        pure [(key', fullRawSelection { selectionArguments, selectionContent })]+    validateSelection (key, rawSelection@Selection { selectionArguments = selArgs, selectionPosition, selectionContent = SelectionField })       = do         (dataField, datatype, selectionArguments) <- getValidationData           key-          rawSelection-        isLeaf datatype dataField+          (selArgs, selectionPosition)+        isLeaf (typeContent datatype) dataField         pure           [ ( key-            , rawSelection { selectionArguments, selectionRec = SelectionField }+            , rawSelection { selectionArguments, selectionContent = SelectionField }             )           ]      where-      isLeaf dataType DataField { fieldType = TypeAlias { aliasTyCon } }-        | isEntNode dataType = pure ()+      isLeaf datatype DataField { fieldType = TypeRef { typeConName } }+        | isEntNode datatype = pure ()         | otherwise = failure-        $ subfieldsNotSelected key aliasTyCon selectionPosition+        $ subfieldsNotSelected key typeConName selectionPosition     validateSelection (_, Spread reference') =-      resolveSpread fragments' [typeName'] reference' >>= validateFragment+      resolveSpread fragments' [typeName] reference' >>= validateFragment     validateSelection (_, InlineFragment fragment') =-      castFragmentType Nothing-                       (fragmentPosition fragment')-                       [typeName']-                       fragment'+      castFragmentType Nothing (fragmentPosition fragment') [typeName] fragment'         >>= validateFragment
src/Data/Morpheus/Validation/Query/Validation.hs view
@@ -13,7 +13,7 @@                                                 ( Operation(..)                                                 , ValidOperation                                                 , getOperationName-                                                , getOperationDataType+                                                , getOperationObject                                                 , DataTypeLib(..)                                                 , GQLQuery(..)                                                 )@@ -34,7 +34,7 @@   :: DataTypeLib -> VALIDATION_MODE -> GQLQuery -> Validation ValidOperation validateRequest lib validationMode GQLQuery { fragments, inputVariables, operation = rawOperation@Operation { operationName, operationType, operationSelection, operationPosition } }   = do-    operationDataType <- getOperationDataType rawOperation lib+    operationDataType <-  getOperationObject rawOperation lib     variables         <- resolveOperationVariables lib                                                    fragments                                                    (fromList inputVariables)@@ -49,7 +49,7 @@                                       operationSelection     pure $ Operation { operationName                      , operationType-                     , operationArgs      = []+                     , operationArguments      = []                      , operationSelection = selection                      , operationPosition                      }
src/Data/Morpheus/Validation/Query/Variable.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE NamedFieldPuns #-} @@ -29,10 +31,12 @@                                                 , getOperationName                                                 , Fragment(..)                                                 , FragmentLib-                                                , RawArgument(..)-                                                , RawSelection(..)-                                                , RawSelectionSet+                                                , Argument(..)+                                                , RawArgument                                                 , Selection(..)+                                                , SelectionContent(..)+                                                , RawSelection+                                                , RawSelectionSet                                                 , Ref(..)                                                 , Position                                                 , DataType@@ -40,6 +44,15 @@                                                 , lookupInputType                                                 , Variables                                                 , Value(..)+                                                , ValidValue+                                                , RawValue+                                                , ResolvedValue+                                                , Name+                                                , VALID+                                                , RAW+                                                , VariableContent(..)+                                                , isNullable+                                                , TypeRef(..)                                                 ) import           Data.Morpheus.Types.Internal.Resolving                                                 ( Validation@@ -59,24 +72,34 @@ concatMapM :: Monad m => (a -> m [b]) -> [a] -> m [b] concatMapM f = fmap concat . mapM f ++class ExploreRefs a where+  exploreRefs :: a -> [Ref]++instance ExploreRefs RawValue where+  exploreRefs (VariableValue ref   ) = [ref]+  exploreRefs (Object        fields) = concatMap (exploreRefs . snd) fields+  exploreRefs (List          ls    ) = concatMap exploreRefs ls+  exploreRefs _                      = []++instance ExploreRefs (Text, RawArgument) where+  exploreRefs (_, Argument { argumentValue }) = exploreRefs argumentValue+ allVariableRefs :: FragmentLib -> [RawSelectionSet] -> Validation [Ref] allVariableRefs fragmentLib = concatMapM (concatMapM searchRefs)  where-  referencesFromArgument :: (Text, RawArgument) -> [Ref]-  referencesFromArgument (_, RawArgument{}) = []-  referencesFromArgument (_, VariableRef Ref { refName, refPosition }) =-    [Ref refName refPosition]+   -- | search used variables in every arguments   searchRefs :: (Text, RawSelection) -> Validation [Ref]-  searchRefs (_, RawSelectionSet Selection { selectionArguments, selectionRec })-    = getArgs <$> concatMapM searchRefs selectionRec+  searchRefs (_, Selection { selectionArguments, selectionContent = SelectionField })+    = return $ concatMap exploreRefs selectionArguments+  searchRefs (_, Selection { selectionArguments, selectionContent = SelectionSet selSet })+    = getArgs <$> concatMapM searchRefs selSet    where     getArgs :: [Ref] -> [Ref]-    getArgs x = concatMap referencesFromArgument selectionArguments <> x+    getArgs x = concatMap exploreRefs selectionArguments <> x   searchRefs (_, InlineFragment Fragment { fragmentSelection }) =     concatMapM searchRefs fragmentSelection-  searchRefs (_, RawSelectionField Selection { selectionArguments }) =-    return $ concatMap referencesFromArgument selectionArguments   searchRefs (_, Spread reference) =     getFragment reference fragmentLib       >>= concatMapM searchRefs@@ -89,17 +112,17 @@   -> VALIDATION_MODE   -> RawOperation   -> Validation ValidVariables-resolveOperationVariables typeLib lib root validationMode Operation { operationName, operationSelection, operationArgs }+resolveOperationVariables typeLib lib root validationMode Operation { operationName, operationSelection, operationArguments }   = do     allVariableRefs lib [operationSelection] >>= checkUnusedVariables     mapM (lookupAndValidateValueOnBody typeLib root validationMode)-         operationArgs+         operationArguments  where   varToKey :: (Text, Variable a) -> Ref   varToKey (key', Variable { variablePosition }) = Ref key' variablePosition   --   checkUnusedVariables :: [Ref] -> Validation ()-  checkUnusedVariables refs = case map varToKey operationArgs \\ refs of+  checkUnusedVariables refs = case map varToKey operationArguments \\ refs of     [] -> pure ()     unused' ->       failure $ unusedVariables (getOperationName operationName) unused'@@ -108,40 +131,50 @@   :: DataTypeLib   -> Variables   -> VALIDATION_MODE-  -> (Text, Variable DefaultValue)-  -> Validation (Text, Variable Value)-lookupAndValidateValueOnBody typeLib bodyVariables validationMode (key, var@Variable { variableType, variablePosition, isVariableRequired, variableTypeWrappers, variableValue = defaultValue })+  -> (Text, Variable RAW)+  -> Validation (Text, Variable VALID)+lookupAndValidateValueOnBody typeLib bodyVariables validationMode (key, var@Variable { variableType, variablePosition, variableValue = DefaultValue defaultValue })   = toVariable-    <$> (   getVariableType variableType variablePosition typeLib+    <$> (   getVariableType (typeConName variableType) variablePosition typeLib         >>= checkType getVariable defaultValue         )  where-  toVariable (varKey, variableValue) = (varKey, var { variableValue })+  toVariable (varKey, x) =+    (varKey, var { variableValue = ValidVariableValue x })+  getVariable :: Maybe ResolvedValue   getVariable = M.lookup key bodyVariables   ------------------------------------------------------------------+  -- checkType :: +  checkType+    :: Maybe ResolvedValue+    -> DefaultValue+    -> DataType+    -> Validation (Name, ValidValue)   checkType (Just variable) Nothing varType = validator varType variable   checkType (Just variable) (Just defValue) varType =     validator varType defValue >> validator varType variable   checkType Nothing (Just defValue) varType = validator varType defValue   checkType Nothing Nothing varType-    | validationMode /= WITHOUT_VARIABLES && isVariableRequired-    = failure $ uninitializedVariable variablePosition variableType key+    | validationMode /= WITHOUT_VARIABLES && not (isNullable variableType)+    = failure+      $ uninitializedVariable variablePosition (typeConName variableType) key     | otherwise     = returnNull    where     returnNull =       maybe (pure (key, Null)) (validator varType) (M.lookup key bodyVariables)   -----------------------------------------------------------------------------------------------+  validator :: DataType -> ResolvedValue -> Validation (Name, ValidValue)   validator varType varValue =     case         validateInputValue typeLib                            []-                           variableTypeWrappers+                           (typeWrappers variableType)                            varType                            (key, varValue)       of-        Left message -> failure $ variableGotInvalidValue-          key-          (inputErrorMessage message)-          variablePosition+        Left message -> failure $ case inputErrorMessage message of+          Left errors -> errors+          Right errMessage ->+            variableGotInvalidValue key errMessage variablePosition         Right value -> pure (key, value)
test/Feature/Holistic/API.hs view
@@ -28,6 +28,8 @@                                                 , ScalarValue(..)                                                 , Resolver(..)                                                 , constRes+                                                , failRes+                                                , liftEither                                                 ) import           Data.Text                      ( Text ) import           GHC.Generics                   ( Generic )@@ -53,9 +55,19 @@  importGQLDocument "test/Feature/Holistic/schema.gql" +++alwaysFail :: IO (Either String a)+alwaysFail = pure $ Left "fail with Either"++ rootResolver :: GQLRootResolver IO EVENT Query Mutation Subscription rootResolver = GQLRootResolver-  { queryResolver        = Query { user, testUnion = constRes Nothing }+  { queryResolver        = Query { user+                                 , testUnion = constRes Nothing+                                 , fail1     = const $ liftEither alwaysFail+                                 , fail2 = const $ failRes "fail with failRes"+                                 }   , mutationResolver     = Mutation { createUser = user }   , subscriptionResolver = Subscription                              { newUser = const SubResolver
test/Feature/Holistic/cases.json view
@@ -200,6 +200,10 @@     "description": "fail when: directive is used in Variable Definition"   },   {+    "path": "parsing/numbers",+    "description": "parse signed numbers and numbers with expotential"+  },+  {     "path": "introspection/description/object",     "description": "check object descriptions, type, field, args"   },@@ -222,5 +226,9 @@   {     "path": "introspection/deprecated/field",     "description": "check if deprecated works with object fields"+  },+  {+    "path": "failure/resolveFailure",+    "description": "test failed resolvers"   } ]
+ test/Feature/Holistic/failure/resolveFailure/query.gql view
@@ -0,0 +1,4 @@+{+  fail1+  fail2+}
+ test/Feature/Holistic/failure/resolveFailure/response.json view
@@ -0,0 +1,12 @@+{+  "errors": [+    {+      "message": "Failure on Resolving Field \"fail1\": fail with Either",+      "locations": [{ "line": 2, "column": 3 }]+    },+    {+      "message": "Failure on Resolving Field \"fail2\": fail with failRes",+      "locations": [{ "line": 3, "column": 3 }]+    }+  ]+}
test/Feature/Holistic/fragment/loopingFragment/response.json view
@@ -1,7 +1,7 @@ {   "errors": [     {-      "message": "Cannot spread fragment \"A\" within itself via A,A,C.",+      "message": "Cannot spread fragment \"A\" within itself via A, A, C.",       "locations": [         { "line": 17, "column": 3 },         { "line": 7, "column": 10 },
test/Feature/Holistic/parsing/complex/response.json view
@@ -13,6 +13,10 @@       "locations": [{ "line": 15, "column": 21 }]     },     {+      "message": "Argument cityID got invalid value ; Expected type \"TestEnum\" found \"HH\".",+      "locations": [{ "line": 15, "column": 33 }]+    },+    {       "message": "Cannot query field \"home\" on type \"User\".",       "locations": [{ "line": 25, "column": 5 }]     },
test/Feature/Holistic/parsing/invalidFields/response.json view
@@ -1,13 +1,8 @@ {   "errors": [     {-      "message": "offset=26:\nunexpected '<'\nexpecting '#', ',', '_', '}', Directives, IgnoredTokens, Selection, body, digit, letter, maybeArguments, or white space\n",-      "locations": [-        {-          "line": 1,-          "column": 27-        }-      ]+      "message": "offset=26:\nunexpected '<'\nexpecting '#', ',', '_', '}', Arguments, Directives, IgnoredTokens, Selection, body, digit, letter, or white space\n",+      "locations": [{ "line": 1, "column": 27 }]     }   ] }
+ test/Feature/Holistic/parsing/numbers/query.gql view
@@ -0,0 +1,7 @@+{+  negative1(num: -1)+  negative2(num: -20232)+  negative3(num: -5.0)+  exp1(num: 1.01e4)+  exp2(num: 6.0221413e23)+}
+ test/Feature/Holistic/parsing/numbers/response.json view
@@ -0,0 +1,24 @@+{+  "errors": [+    {+      "message": "Cannot query field \"negative1\" on type \"Query\".",+      "locations": [{ "line": 2, "column": 3 }]+    },+    {+      "message": "Cannot query field \"negative2\" on type \"Query\".",+      "locations": [{ "line": 3, "column": 3 }]+    },+    {+      "message": "Cannot query field \"negative3\" on type \"Query\".",+      "locations": [{ "line": 4, "column": 3 }]+    },+    {+      "message": "Cannot query field \"exp1\" on type \"Query\".",+      "locations": [{ "line": 5, "column": 3 }]+    },+    {+      "message": "Cannot query field \"exp2\" on type \"Query\".",+      "locations": [{ "line": 6, "column": 3 }]+    }+  ]+}
test/Feature/Holistic/schema.gql view
@@ -92,6 +92,8 @@ type Query {   user: User!   testUnion: TestUnion+  fail1: String!+  fail2: Int! }  type Mutation {
+ test/Feature/Input/Object/API.hs view
@@ -0,0 +1,55 @@+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric  #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE TypeFamilies   #-}+{-# LANGUAGE TypeOperators  #-}++module Feature.Input.Object.API+  ( api+  )+where++import           Data.Morpheus                  ( interpreter )+import           Data.Morpheus.Types            ( GQLRequest+                                                , GQLResponse+                                                , GQLRootResolver(..)+                                                , GQLType(..)+                                                , Undefined(..)+                                                )+import           GHC.Generics                   ( Generic )+import           Data.Morpheus.Kind             ( INPUT )+import           Data.Text                      ( Text+                                                , pack+                                                )+++data InputObject = InputObject {+  field :: Text,+  nullableField :: Maybe Int+} deriving (Generic, Show)++instance GQLType InputObject where+  type KIND InputObject = INPUT++-- types & args+newtype Arg a = Arg+  { value :: a+  } deriving (Generic, Show)++-- query+testRes :: Show a => Applicative m => Arg a -> m Text+testRes Arg { value } = pure $ pack $ show value++-- resolver+newtype Query m = Query+  { input  :: Arg InputObject -> m Text+  } deriving (Generic, GQLType)++rootResolver :: GQLRootResolver IO () Query Undefined Undefined+rootResolver = GQLRootResolver { queryResolver = Query { input = testRes }+                               , mutationResolver = Undefined+                               , subscriptionResolver = Undefined+                               }++api :: GQLRequest -> IO GQLResponse+api = interpreter rootResolver
+ test/Feature/Input/Object/cases.json view
@@ -0,0 +1,30 @@+[+  {+    "path": "undefinedField",+    "description": "fail when field was not provided"+  },+  {+    "path": "nullableUndefinedField",+    "description": "dont fail when nullable field was not provided"+  },+  {+    "path": "unknownField",+    "description": "fail on unknown field"+  },+  {+    "path": "unexpectedValue",+    "description": "fail on value with unexpected type"+  },+  {+    "path": "unexpectedVariable",+    "description": "fail on use of variable with unexpected type"+  },+  {+    "path": "resolveVariable",+    "description": "resolve by variable"+  },+  {+    "path": "resolveObject",+    "description": "resolve object"+  }+]
+ test/Feature/Input/Object/nullableUndefinedField/query.gql view
@@ -0,0 +1,3 @@+query NullableUndefinedField {+  input(value: { field: "value" })+}
+ test/Feature/Input/Object/nullableUndefinedField/response.json view
@@ -0,0 +1,5 @@+{+  "data": {+    "input": "InputObject {field = \"value\", nullableField = Nothing}"+  }+}
+ test/Feature/Input/Object/resolveObject/query.gql view
@@ -0,0 +1,4 @@+query ResolveObject {+  i1: input(value: { field: "v1", nullableField: 123 })+  i2: input(value: { field: "v2" })+}
+ test/Feature/Input/Object/resolveObject/response.json view
@@ -0,0 +1,6 @@+{+  "data": {+    "i1": "InputObject {field = \"v1\", nullableField = Just 123}",+    "i2": "InputObject {field = \"v2\", nullableField = Nothing}"+  }+}
+ test/Feature/Input/Object/resolveVariable/query.gql view
@@ -0,0 +1,4 @@+query ResolveVariable($v1: String!, $v2: Int!, $v3: Int) {+  i1: input(value: { field: $v1, nullableField: $v2 })+  i2: input(value: { field: "", nullableField: $v3 })+}
+ test/Feature/Input/Object/resolveVariable/response.json view
@@ -0,0 +1,6 @@+{+  "data": {+    "i1": "InputObject {field = \"string from variable\", nullableField = Just 123011}",+    "i2": "InputObject {field = \"\", nullableField = Nothing}"+  }+}
+ test/Feature/Input/Object/resolveVariable/variables.json view
@@ -0,0 +1,4 @@+{+  "v1": "string from variable",+  "v2": 123011+}
+ test/Feature/Input/Object/undefinedField/query.gql view
@@ -0,0 +1,4 @@+query UndefinedField {+  i1: input(value: { nullableField: 1 })+  i2: input(value: {})+}
+ test/Feature/Input/Object/undefinedField/response.json view
@@ -0,0 +1,12 @@+{+  "errors": [+    {+      "message": "Argument value got invalid value ; Undefined Field \"field\".",+      "locations": [{ "line": 2, "column": 20 }]+    },+    {+      "message": "Argument value got invalid value ; Undefined Field \"field\".",+      "locations": [{ "line": 3, "column": 20 }]+    }+  ]+}
+ test/Feature/Input/Object/unexpectedValue/query.gql view
@@ -0,0 +1,6 @@+query UnexpectedValue {+  i1: input(value: "some text")+  i2: input(value: 1)+  i3: input(value: { field: {} })+  i4: input(value: { field: 3 })+}
+ test/Feature/Input/Object/unexpectedValue/response.json view
@@ -0,0 +1,20 @@+{+  "errors": [+    {+      "message": "Argument value got invalid value ; Expected type \"InputObject!\" found \"some text\".",+      "locations": [{ "line": 2, "column": 20 }]+    },+    {+      "message": "Argument value got invalid value ; Expected type \"InputObject!\" found 1.",+      "locations": [{ "line": 3, "column": 20 }]+    },+    {+      "message": "Argument value got invalid value ;on field Expected type \"String\" found {}.",+      "locations": [{ "line": 4, "column": 20 }]+    },+    {+      "message": "Argument value got invalid value ;on field Expected type \"String\" found 3.",+      "locations": [{ "line": 5, "column": 20 }]+    }+  ]+}
+ test/Feature/Input/Object/unexpectedVariable/query.gql view
@@ -0,0 +1,4 @@+query Unexpectedvariable($v1: String, $v2: String) {+  i1: input(value: { field: $v1, nullableField: 1 })+  i2: input(value: { field: "", nullableField: $v2 })+}
+ test/Feature/Input/Object/unexpectedVariable/response.json view
@@ -0,0 +1,12 @@+{+  "errors": [+    {+      "message": "Variable \"$v1\" of type \"String\" used in position expecting type \"String!\".",+      "locations": [{ "line": 2, "column": 29 }]+    },+    {+      "message": "Variable \"$v2\" of type \"String\" used in position expecting type \"Int\".",+      "locations": [{ "line": 3, "column": 48 }]+    }+  ]+}
+ test/Feature/Input/Object/unknownField/query.gql view
@@ -0,0 +1,3 @@+query UndefinedField {+  input(value: { moo: 1, field: "some field" })+}
+ test/Feature/Input/Object/unknownField/response.json view
@@ -0,0 +1,8 @@+{+  "errors": [+    {+      "message": "Argument value got invalid value ; Unknown Field \"moo\".",+      "locations": [{ "line": 2, "column": 16 }]+    }+  ]+}
+ test/Feature/Input/Scalar/API.hs view
@@ -0,0 +1,44 @@+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric  #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE TypeFamilies   #-}+{-# LANGUAGE TypeOperators  #-}++module Feature.Input.Scalar.API+  ( api+  )+where++import           Data.Morpheus                  ( interpreter )+import           Data.Morpheus.Types            ( GQLRequest+                                                , GQLResponse+                                                , GQLRootResolver(..)+                                                , GQLType(..)+                                                , Undefined(..)+                                                )+import           GHC.Generics                   ( Generic )++-- types & args+newtype Arg a = Arg+  { value :: a+  } deriving (Generic, Show)++-- query+testRes :: Applicative m => Arg a -> m a+testRes Arg { value } = pure value++-- resolver+data Query m = Query+  { testFloat  :: Arg Float -> m Float+  , testInt :: Arg Int -> m Int+  } deriving (Generic, GQLType)++rootResolver :: GQLRootResolver IO () Query Undefined Undefined+rootResolver = GQLRootResolver+  { queryResolver        = Query { testFloat = testRes, testInt = testRes }+  , mutationResolver     = Undefined+  , subscriptionResolver = Undefined+  }++api :: GQLRequest -> IO GQLResponse+api = interpreter rootResolver
+ test/Feature/Input/Scalar/cases.json view
@@ -0,0 +1,10 @@+[+  {+    "path": "decodeFloat",+    "description": "test signed float and float with expotential"+  },+  {+    "path": "decodeInt",+    "description": "test signed int and int with expotential"+  }+]
+ test/Feature/Input/Scalar/decodeFloat/query.gql view
@@ -0,0 +1,7 @@+query ValidDecoding {+  one: testFloat(value: 1.00)+  negOne: testFloat(value: -1)+  negNummber: testFloat(value: -1.235)+  expNumber: testFloat(value: 0.3e5)+  negExpNumber: testFloat(value: - 0.12e-35)+}
+ test/Feature/Input/Scalar/decodeFloat/response.json view
@@ -0,0 +1,9 @@+{+  "data": {+    "one": 1,+    "negOne": -1,+    "negNummber": -1.235,+    "expNumber": 30000,+    "negExpNumber": -1.2e-36+  }+}
+ test/Feature/Input/Scalar/decodeInt/query.gql view
@@ -0,0 +1,7 @@+query ValidDecoding {+  one: testInt(value: 1)+  negOne: testInt(value: -1)+  negNummber: testInt(value: -1235)+  expNumber: testInt(value: 123e5)+  negExpNumber: testInt(value: - 123e5)+}
+ test/Feature/Input/Scalar/decodeInt/response.json view
@@ -0,0 +1,9 @@+{+  "data": {+    "one": 1,+    "negOne": -1,+    "negNummber": -1235,+    "expNumber": 12300000,+    "negExpNumber": -12300000+  }+}
+ test/Feature/TypeInference/API.hs view
@@ -0,0 +1,106 @@+{-# LANGUAGE DeriveAnyClass         #-}+{-# LANGUAGE DeriveGeneric          #-}+{-# LANGUAGE OverloadedStrings      #-}+{-# LANGUAGE TypeFamilies           #-}+{-# LANGUAGE TypeOperators          #-}+{-# LANGUAGE NamedFieldPuns         #-}+{-# LANGUAGE DuplicateRecordFields  #-}++module Feature.TypeInference.API+  ( api+  )+where++import           Data.Morpheus                  ( interpreter )+import           Data.Morpheus.Kind             ( INPUT )+import           Data.Morpheus.Types            ( GQLRequest+                                                , GQLResponse+                                                , GQLRootResolver(..)+                                                , GQLType(..)+                                                , Undefined(..)+                                                )+import           Data.Text                      ( Text+                                                , pack+                                                )+import           GHC.Generics                   ( Generic )++data Power = Thunderbolts | Shapeshift | Hurricanes+  deriving (Generic,GQLType)++data Deity = Deity {+  name :: Text ,+  power :: Power+} deriving(Generic,GQLType)++deityRes :: Deity+deityRes = Deity { name = "Morpheus", power = Shapeshift }++data Hydra = Hydra {+  name :: Text,+  age :: Int+} deriving (Show,Generic)++instance GQLType Hydra where+  type KIND Hydra = INPUT++data Monster =+    MonsterHydra Hydra+  | Cerberus { name :: Text }+  | UnidentifiedMonster+  deriving (Show, Generic)++instance GQLType Monster where+  type KIND Monster = INPUT++data Character  =+  CharacterDeity Deity -- Only <tycon name><type ref name> should generate direct link+  -- RECORDS+  | Creature { creatureName :: Text, creatureAge :: Int }+  | BoxedDeity { boxedDeity :: Deity}+  | ScalarRecord { scalarText :: Text }+  --- Types +  | CharacterInt Int -- all scalars mus be boxed+  -- Types+  | SomeDeity Deity+  | SomeMutli Int Text+  --- ENUMS+  | Zeus+  | Cronus deriving (Generic, GQLType)++++newtype MonsterArgs = MonsterArgs {+  monster :: Monster+} deriving (Generic)++data Query (m :: * -> *) = Query+  { deity :: Deity,+    character :: [Character],+    showMonster :: MonsterArgs -> m Text+  } deriving (Generic, GQLType)++rootResolver :: GQLRootResolver IO () Query Undefined Undefined+rootResolver = GQLRootResolver+  { queryResolver        = Query { deity = deityRes, character, showMonster }+  , mutationResolver     = Undefined+  , subscriptionResolver = Undefined+  }+ where+  showMonster MonsterArgs { monster } = pure (pack $ show monster)+  character :: [Character]+  character =+    [ CharacterDeity deityRes+    , Creature { creatureName = "Lamia", creatureAge = 205 }+    , BoxedDeity { boxedDeity = deityRes }+    , ScalarRecord { scalarText = "Some Text" }+      ---+    , SomeDeity deityRes+    , CharacterInt 12+    , SomeMutli 21 "some text"+    , Zeus+    , Cronus+    ]+++api :: GQLRequest -> IO GQLResponse+api = interpreter rootResolver
+ test/Feature/TypeInference/cases.json view
@@ -0,0 +1,50 @@+[+  {+    "path": "introspection/object",+    "description": "derives simple gql object type"+  },+  {+    "path": "introspection/enum",+    "description": "derive as gql enum, if type has only empty constructors"+  },+  {+    "path": "introspection/complexUnion",+    "description": "derive complex union"+  },+  {+    "path": "introspection/complexUnionEnum",+    "description": "complex union enum contains, actual enums with empty constructors and enum object wrapper"+  },+  {+    "path": "introspection/complexUnionRecord",+    "description": "creates object type for every union records"+  },+  {+    "path": "introspection/complexUnionScalar",+    "description": "all scalar unions must be boxed"+  },+  {+    "path": "introspection/complexUnionIndexedTypes",+    "description": "all types without record syntax(indexed types), will be converted to gql object with fields _0,_1...."+  },+  {+    "path": "introspection/inputObject",+    "description": "introspect input object"+  },+  {+    "path": "introspection/complexInput",+    "description": "introspect complex input"+  },+  {+    "path": "resolving/object",+    "description": "resolve regular object"+  },+  {+    "path": "resolving/complexUnion",+    "description": "resolve regular object"+  },+  {+    "path": "resolving/input",+    "description": "resolve input"+  }+]
+ test/Feature/TypeInference/introspection/complexInput/query.gql view
@@ -0,0 +1,79 @@+query Get__Type {+  __type(name: "Monster") {+    ...FullType+  }+  tags: __type(name: "MonsterTags") {+    ...FullType+  }+}++fragment FullType on __Type {+  kind+  name+  fields(includeDeprecated: true) {+    name+    args {+      ...InputValue+    }+    type {+      ...TypeRef+    }+    isDeprecated+    deprecationReason+  }+  inputFields {+    ...InputValue+  }+  interfaces {+    ...TypeRef+  }+  enumValues(includeDeprecated: true) {+    name+    isDeprecated+    deprecationReason+  }+  possibleTypes {+    ...TypeRef+  }+}++fragment InputValue on __InputValue {+  name+  type {+    ...TypeRef+  }+  defaultValue+}++fragment TypeRef on __Type {+  kind+  name+  ofType {+    kind+    name+    ofType {+      kind+      name+      ofType {+        kind+        name+        ofType {+          kind+          name+          ofType {+            kind+            name+            ofType {+              kind+              name+              ofType {+                kind+                name+              }+            }+          }+        }+      }+    }+  }+}
+ test/Feature/TypeInference/introspection/complexInput/response.json view
@@ -0,0 +1,58 @@+{+  "data": {+    "__type": {+      "kind": "INPUT_OBJECT",+      "name": "Monster",+      "fields": null,+      "inputFields": [+        {+          "name": "__typename",+          "type": {+            "kind": "NON_NULL",+            "name": null,+            "ofType": { "kind": "ENUM", "name": "MonsterTags", "ofType": null }+          },+          "defaultValue": null+        },+        {+          "name": "Hydra",+          "type": { "kind": "INPUT_OBJECT", "name": "Hydra", "ofType": null },+          "defaultValue": null+        },+        {+          "name": "Cerberus",+          "type": {+            "kind": "INPUT_OBJECT",+            "name": "Cerberus",+            "ofType": null+          },+          "defaultValue": null+        }+      ],+      "interfaces": null,+      "enumValues": null,+      "possibleTypes": null+    },+    "tags": {+      "kind": "ENUM",+      "name": "MonsterTags",+      "fields": null,+      "inputFields": null,+      "interfaces": null,+      "enumValues": [+        { "name": "Hydra", "isDeprecated": false, "deprecationReason": null },+        {+          "name": "Cerberus",+          "isDeprecated": false,+          "deprecationReason": null+        },+        {+          "name": "UnidentifiedMonster",+          "isDeprecated": false,+          "deprecationReason": null+        }+      ],+      "possibleTypes": null+    }+  }+}
+ test/Feature/TypeInference/introspection/complexUnion/query.gql view
@@ -0,0 +1,76 @@+query Get__Type {+  __type(name: "Character") {+    ...FullType+  }+}++fragment FullType on __Type {+  kind+  name+  fields(includeDeprecated: true) {+    name+    args {+      ...InputValue+    }+    type {+      ...TypeRef+    }+    isDeprecated+    deprecationReason+  }+  inputFields {+    ...InputValue+  }+  interfaces {+    ...TypeRef+  }+  enumValues(includeDeprecated: true) {+    name+    isDeprecated+    deprecationReason+  }+  possibleTypes {+    ...TypeRef+  }+}++fragment InputValue on __InputValue {+  name+  type {+    ...TypeRef+  }+  defaultValue+}++fragment TypeRef on __Type {+  kind+  name+  ofType {+    kind+    name+    ofType {+      kind+      name+      ofType {+        kind+        name+        ofType {+          kind+          name+          ofType {+            kind+            name+            ofType {+              kind+              name+              ofType {+                kind+                name+              }+            }+          }+        }+      }+    }+  }+}
+ test/Feature/TypeInference/introspection/complexUnion/response.json view
@@ -0,0 +1,22 @@+{+  "data": {+    "__type": {+      "kind": "UNION",+      "name": "Character",+      "fields": null,+      "inputFields": null,+      "interfaces": null,+      "enumValues": null,+      "possibleTypes": [+        { "kind": "OBJECT", "name": "Deity", "ofType": null },+        { "kind": "OBJECT", "name": "CharacterEnumObject", "ofType": null },+        { "kind": "OBJECT", "name": "Creature", "ofType": null },+        { "kind": "OBJECT", "name": "BoxedDeity", "ofType": null },+        { "kind": "OBJECT", "name": "ScalarRecord", "ofType": null },+        { "kind": "OBJECT", "name": "CharacterInt", "ofType": null },+        { "kind": "OBJECT", "name": "SomeDeity", "ofType": null },+        { "kind": "OBJECT", "name": "SomeMutli", "ofType": null }+      ]+    }+  }+}
+ test/Feature/TypeInference/introspection/complexUnionEnum/query.gql view
@@ -0,0 +1,79 @@+query Get__Type {+  enumObject: __type(name: "CharacterEnumObject") {+    ...FullType+  }+  enum: __type(name: "CharacterEnum") {+    ...FullType+  }+}++fragment FullType on __Type {+  kind+  name+  fields(includeDeprecated: true) {+    name+    args {+      ...InputValue+    }+    type {+      ...TypeRef+    }+    isDeprecated+    deprecationReason+  }+  inputFields {+    ...InputValue+  }+  interfaces {+    ...TypeRef+  }+  enumValues(includeDeprecated: true) {+    name+    isDeprecated+    deprecationReason+  }+  possibleTypes {+    ...TypeRef+  }+}++fragment InputValue on __InputValue {+  name+  type {+    ...TypeRef+  }+  defaultValue+}++fragment TypeRef on __Type {+  kind+  name+  ofType {+    kind+    name+    ofType {+      kind+      name+      ofType {+        kind+        name+        ofType {+          kind+          name+          ofType {+            kind+            name+            ofType {+              kind+              name+              ofType {+                kind+                name+              }+            }+          }+        }+      }+    }+  }+}
+ test/Feature/TypeInference/introspection/complexUnionEnum/response.json view
@@ -0,0 +1,41 @@+{+  "data": {+    "enumObject": {+      "kind": "OBJECT",+      "name": "CharacterEnumObject",+      "fields": [+        {+          "name": "enum",+          "args": [],+          "type": {+            "kind": "NON_NULL",+            "name": null,+            "ofType": {+              "kind": "ENUM",+              "name": "CharacterEnum",+              "ofType": null+            }+          },+          "isDeprecated": false,+          "deprecationReason": null+        }+      ],+      "inputFields": null,+      "interfaces": [],+      "enumValues": null,+      "possibleTypes": null+    },+    "enum": {+      "kind": "ENUM",+      "name": "CharacterEnum",+      "fields": null,+      "inputFields": null,+      "interfaces": null,+      "enumValues": [+        { "name": "Zeus", "isDeprecated": false, "deprecationReason": null },+        { "name": "Cronus", "isDeprecated": false, "deprecationReason": null }+      ],+      "possibleTypes": null+    }+  }+}
+ test/Feature/TypeInference/introspection/complexUnionIndexedTypes/query.gql view
@@ -0,0 +1,79 @@+query Get__Type {+  someDeity: __type(name: "SomeDeity") {+    ...FullType+  }+  someMutli: __type(name: "SomeMutli") {+    ...FullType+  }+}++fragment FullType on __Type {+  kind+  name+  fields(includeDeprecated: true) {+    name+    args {+      ...InputValue+    }+    type {+      ...TypeRef+    }+    isDeprecated+    deprecationReason+  }+  inputFields {+    ...InputValue+  }+  interfaces {+    ...TypeRef+  }+  enumValues(includeDeprecated: true) {+    name+    isDeprecated+    deprecationReason+  }+  possibleTypes {+    ...TypeRef+  }+}++fragment InputValue on __InputValue {+  name+  type {+    ...TypeRef+  }+  defaultValue+}++fragment TypeRef on __Type {+  kind+  name+  ofType {+    kind+    name+    ofType {+      kind+      name+      ofType {+        kind+        name+        ofType {+          kind+          name+          ofType {+            kind+            name+            ofType {+              kind+              name+              ofType {+                kind+                name+              }+            }+          }+        }+      }+    }+  }+}
+ test/Feature/TypeInference/introspection/complexUnionIndexedTypes/response.json view
@@ -0,0 +1,57 @@+{+  "data": {+    "someDeity": {+      "kind": "OBJECT",+      "name": "SomeDeity",+      "fields": [+        {+          "name": "_0",+          "args": [],+          "type": {+            "kind": "NON_NULL",+            "name": null,+            "ofType": { "kind": "OBJECT", "name": "Deity", "ofType": null }+          },+          "isDeprecated": false,+          "deprecationReason": null+        }+      ],+      "inputFields": null,+      "interfaces": [],+      "enumValues": null,+      "possibleTypes": null+    },+    "someMutli": {+      "kind": "OBJECT",+      "name": "SomeMutli",+      "fields": [+        {+          "name": "_0",+          "args": [],+          "type": {+            "kind": "NON_NULL",+            "name": null,+            "ofType": { "kind": "SCALAR", "name": "Int", "ofType": null }+          },+          "isDeprecated": false,+          "deprecationReason": null+        },+        {+          "name": "_1",+          "args": [],+          "type": {+            "kind": "NON_NULL",+            "name": null,+            "ofType": { "kind": "SCALAR", "name": "String", "ofType": null }+          },+          "isDeprecated": false,+          "deprecationReason": null+        }+      ],+      "inputFields": null,+      "interfaces": [],+      "enumValues": null,+      "possibleTypes": null+    }+  }+}
+ test/Feature/TypeInference/introspection/complexUnionRecord/query.gql view
@@ -0,0 +1,82 @@+query Get__Type {+  creature: __type(name: "Creature") {+    ...FullType+  }+  boxedDeity: __type(name: "BoxedDeity") {+    ...FullType+  }+  scalarRecord: __type(name: "ScalarRecord") {+    ...FullType+  }+}++fragment FullType on __Type {+  kind+  name+  fields(includeDeprecated: true) {+    name+    args {+      ...InputValue+    }+    type {+      ...TypeRef+    }+    isDeprecated+    deprecationReason+  }+  inputFields {+    ...InputValue+  }+  interfaces {+    ...TypeRef+  }+  enumValues(includeDeprecated: true) {+    name+    isDeprecated+    deprecationReason+  }+  possibleTypes {+    ...TypeRef+  }+}++fragment InputValue on __InputValue {+  name+  type {+    ...TypeRef+  }+  defaultValue+}++fragment TypeRef on __Type {+  kind+  name+  ofType {+    kind+    name+    ofType {+      kind+      name+      ofType {+        kind+        name+        ofType {+          kind+          name+          ofType {+            kind+            name+            ofType {+              kind+              name+              ofType {+                kind+                name+              }+            }+          }+        }+      }+    }+  }+}
+ test/Feature/TypeInference/introspection/complexUnionRecord/response.json view
@@ -0,0 +1,78 @@+{+  "data": {+    "creature": {+      "kind": "OBJECT",+      "name": "Creature",+      "fields": [+        {+          "name": "creatureName",+          "args": [],+          "type": {+            "kind": "NON_NULL",+            "name": null,+            "ofType": { "kind": "SCALAR", "name": "String", "ofType": null }+          },+          "isDeprecated": false,+          "deprecationReason": null+        },+        {+          "name": "creatureAge",+          "args": [],+          "type": {+            "kind": "NON_NULL",+            "name": null,+            "ofType": { "kind": "SCALAR", "name": "Int", "ofType": null }+          },+          "isDeprecated": false,+          "deprecationReason": null+        }+      ],+      "inputFields": null,+      "interfaces": [],+      "enumValues": null,+      "possibleTypes": null+    },+    "boxedDeity": {+      "kind": "OBJECT",+      "name": "BoxedDeity",+      "fields": [+        {+          "name": "boxedDeity",+          "args": [],+          "type": {+            "kind": "NON_NULL",+            "name": null,+            "ofType": { "kind": "OBJECT", "name": "Deity", "ofType": null }+          },+          "isDeprecated": false,+          "deprecationReason": null+        }+      ],+      "inputFields": null,+      "interfaces": [],+      "enumValues": null,+      "possibleTypes": null+    },+    "scalarRecord": {+      "kind": "OBJECT",+      "name": "ScalarRecord",+      "fields": [+        {+          "name": "scalarText",+          "args": [],+          "type": {+            "kind": "NON_NULL",+            "name": null,+            "ofType": { "kind": "SCALAR", "name": "String", "ofType": null }+          },+          "isDeprecated": false,+          "deprecationReason": null+        }+      ],+      "inputFields": null,+      "interfaces": [],+      "enumValues": null,+      "possibleTypes": null+    }+  }+}
+ test/Feature/TypeInference/introspection/complexUnionScalar/query.gql view
@@ -0,0 +1,76 @@+query Get__Type {+  __type(name: "CharacterInt") {+    ...FullType+  }+}++fragment FullType on __Type {+  kind+  name+  fields(includeDeprecated: true) {+    name+    args {+      ...InputValue+    }+    type {+      ...TypeRef+    }+    isDeprecated+    deprecationReason+  }+  inputFields {+    ...InputValue+  }+  interfaces {+    ...TypeRef+  }+  enumValues(includeDeprecated: true) {+    name+    isDeprecated+    deprecationReason+  }+  possibleTypes {+    ...TypeRef+  }+}++fragment InputValue on __InputValue {+  name+  type {+    ...TypeRef+  }+  defaultValue+}++fragment TypeRef on __Type {+  kind+  name+  ofType {+    kind+    name+    ofType {+      kind+      name+      ofType {+        kind+        name+        ofType {+          kind+          name+          ofType {+            kind+            name+            ofType {+              kind+              name+              ofType {+                kind+                name+              }+            }+          }+        }+      }+    }+  }+}
+ test/Feature/TypeInference/introspection/complexUnionScalar/response.json view
@@ -0,0 +1,25 @@+{+  "data": {+    "__type": {+      "kind": "OBJECT",+      "name": "CharacterInt",+      "fields": [+        {+          "name": "_0",+          "args": [],+          "type": {+            "kind": "NON_NULL",+            "name": null,+            "ofType": { "kind": "SCALAR", "name": "Int", "ofType": null }+          },+          "isDeprecated": false,+          "deprecationReason": null+        }+      ],+      "inputFields": null,+      "interfaces": [],+      "enumValues": null,+      "possibleTypes": null+    }+  }+}
+ test/Feature/TypeInference/introspection/enum/query.gql view
@@ -0,0 +1,76 @@+query Get__Type {+  __type(name: "Power") {+    ...FullType+  }+}++fragment FullType on __Type {+  kind+  name+  fields(includeDeprecated: true) {+    name+    args {+      ...InputValue+    }+    type {+      ...TypeRef+    }+    isDeprecated+    deprecationReason+  }+  inputFields {+    ...InputValue+  }+  interfaces {+    ...TypeRef+  }+  enumValues(includeDeprecated: true) {+    name+    isDeprecated+    deprecationReason+  }+  possibleTypes {+    ...TypeRef+  }+}++fragment InputValue on __InputValue {+  name+  type {+    ...TypeRef+  }+  defaultValue+}++fragment TypeRef on __Type {+  kind+  name+  ofType {+    kind+    name+    ofType {+      kind+      name+      ofType {+        kind+        name+        ofType {+          kind+          name+          ofType {+            kind+            name+            ofType {+              kind+              name+              ofType {+                kind+                name+              }+            }+          }+        }+      }+    }+  }+}
+ test/Feature/TypeInference/introspection/enum/response.json view
@@ -0,0 +1,29 @@+{+  "data": {+    "__type": {+      "kind": "ENUM",+      "name": "Power",+      "fields": null,+      "inputFields": null,+      "interfaces": null,+      "enumValues": [+        {+          "name": "Thunderbolts",+          "isDeprecated": false,+          "deprecationReason": null+        },+        {+          "name": "Shapeshift",+          "isDeprecated": false,+          "deprecationReason": null+        },+        {+          "name": "Hurricanes",+          "isDeprecated": false,+          "deprecationReason": null+        }+      ],+      "possibleTypes": null+    }+  }+}
+ test/Feature/TypeInference/introspection/inputObject/query.gql view
@@ -0,0 +1,76 @@+query Get__Type {+  __type(name: "Hydra") {+    ...FullType+  }+}++fragment FullType on __Type {+  kind+  name+  fields(includeDeprecated: true) {+    name+    args {+      ...InputValue+    }+    type {+      ...TypeRef+    }+    isDeprecated+    deprecationReason+  }+  inputFields {+    ...InputValue+  }+  interfaces {+    ...TypeRef+  }+  enumValues(includeDeprecated: true) {+    name+    isDeprecated+    deprecationReason+  }+  possibleTypes {+    ...TypeRef+  }+}++fragment InputValue on __InputValue {+  name+  type {+    ...TypeRef+  }+  defaultValue+}++fragment TypeRef on __Type {+  kind+  name+  ofType {+    kind+    name+    ofType {+      kind+      name+      ofType {+        kind+        name+        ofType {+          kind+          name+          ofType {+            kind+            name+            ofType {+              kind+              name+              ofType {+                kind+                name+              }+            }+          }+        }+      }+    }+  }+}
+ test/Feature/TypeInference/introspection/inputObject/response.json view
@@ -0,0 +1,32 @@+{+  "data": {+    "__type": {+      "kind": "INPUT_OBJECT",+      "name": "Hydra",+      "fields": null,+      "inputFields": [+        {+          "name": "name",+          "type": {+            "kind": "NON_NULL",+            "name": null,+            "ofType": { "kind": "SCALAR", "name": "String", "ofType": null }+          },+          "defaultValue": null+        },+        {+          "name": "age",+          "type": {+            "kind": "NON_NULL",+            "name": null,+            "ofType": { "kind": "SCALAR", "name": "Int", "ofType": null }+          },+          "defaultValue": null+        }+      ],+      "interfaces": null,+      "enumValues": null,+      "possibleTypes": null+    }+  }+}
+ test/Feature/TypeInference/introspection/object/query.gql view
@@ -0,0 +1,76 @@+query Get__Type {+  __type(name: "Deity") {+    ...FullType+  }+}++fragment FullType on __Type {+  kind+  name+  fields(includeDeprecated: true) {+    name+    args {+      ...InputValue+    }+    type {+      ...TypeRef+    }+    isDeprecated+    deprecationReason+  }+  inputFields {+    ...InputValue+  }+  interfaces {+    ...TypeRef+  }+  enumValues(includeDeprecated: true) {+    name+    isDeprecated+    deprecationReason+  }+  possibleTypes {+    ...TypeRef+  }+}++fragment InputValue on __InputValue {+  name+  type {+    ...TypeRef+  }+  defaultValue+}++fragment TypeRef on __Type {+  kind+  name+  ofType {+    kind+    name+    ofType {+      kind+      name+      ofType {+        kind+        name+        ofType {+          kind+          name+          ofType {+            kind+            name+            ofType {+              kind+              name+              ofType {+                kind+                name+              }+            }+          }+        }+      }+    }+  }+}
+ test/Feature/TypeInference/introspection/object/response.json view
@@ -0,0 +1,36 @@+{+  "data": {+    "__type": {+      "kind": "OBJECT",+      "name": "Deity",+      "fields": [+        {+          "name": "name",+          "args": [],+          "type": {+            "kind": "NON_NULL",+            "name": null,+            "ofType": { "kind": "SCALAR", "name": "String", "ofType": null }+          },+          "isDeprecated": false,+          "deprecationReason": null+        },+        {+          "name": "power",+          "args": [],+          "type": {+            "kind": "NON_NULL",+            "name": null,+            "ofType": { "kind": "ENUM", "name": "Power", "ofType": null }+          },+          "isDeprecated": false,+          "deprecationReason": null+        }+      ],+      "inputFields": null,+      "interfaces": [],+      "enumValues": null,+      "possibleTypes": null+    }+  }+}
+ test/Feature/TypeInference/resolving/complexUnion/query.gql view
@@ -0,0 +1,45 @@+{+  character {+    ## regular union+    __typename+    ... on Deity {+      name+    }++    ## union Enums+    ... on CharacterEnumObject {+      enum+    }++    ... on Creature {+      creatureName+      creatureAge+    }++    ... on BoxedDeity {+      boxedDeity {+        power+      }+    }++    ... on ScalarRecord {+      scalarText+    }++    ... on CharacterInt {+      _0+    }++    ... on SomeDeity {+      _0 {+        name+        power+      }+    }++    ... on SomeMutli {+      _0+      _1+    }+  }+}
+ test/Feature/TypeInference/resolving/complexUnion/response.json view
@@ -0,0 +1,18 @@+{+  "data": {+    "character": [+      { "__typename": "Deity", "name": "Morpheus" },+      { "__typename": "Creature", "creatureName": "Lamia", "creatureAge": 205 },+      { "__typename": "BoxedDeity", "boxedDeity": { "power": "Shapeshift" } },+      { "__typename": "ScalarRecord", "scalarText": "Some Text" },+      {+        "__typename": "SomeDeity",+        "_0": { "name": "Morpheus", "power": "Shapeshift" }+      },+      { "__typename": "CharacterInt", "_0": 12 },+      { "__typename": "SomeMutli", "_0": 21, "_1": "some text" },+      { "__typename": "CharacterEnumObject", "enum": "Zeus" },+      { "__typename": "CharacterEnumObject", "enum": "Cronus" }+    ]+  }+}
+ test/Feature/TypeInference/resolving/input/query.gql view
@@ -0,0 +1,9 @@+{+  object: showMonster(+    monster: { __typename: Hydra, Hydra: { name: "someName", age: 12 } }+  )+  record: showMonster(+    monster: { __typename: Cerberus, Cerberus: { name: "someName" } }+  )+  enum: showMonster(monster: { __typename: UnidentifiedMonster })+}
+ test/Feature/TypeInference/resolving/input/response.json view
@@ -0,0 +1,7 @@+{+  "data": {+    "object": "MonsterHydra (Hydra {name = \"someName\", age = 12})",+    "record": "Cerberus {name = \"someName\"}",+    "enum": "UnidentifiedMonster"+  }+}
+ test/Feature/TypeInference/resolving/object/query.gql view
@@ -0,0 +1,6 @@+{+  deity {+    name+    power+  }+}
+ test/Feature/TypeInference/resolving/object/response.json view
@@ -0,0 +1,1 @@+{ "data": { "deity": { "name": "Morpheus", "power": "Shapeshift" } } }
test/Feature/UnionType/API.hs view
@@ -6,14 +6,22 @@  module Feature.UnionType.API   ( api-  ) where+  )+where -import           Data.Morpheus       (interpreter)-import           Data.Morpheus.Kind  (OBJECT, UNION)-import           Data.Morpheus.Types (GQLRequest, GQLResponse, GQLRootResolver (..), GQLType (..), IORes,-                                      Undefined (..))-import           Data.Text           (Text)-import           GHC.Generics        (Generic)+import           Data.Morpheus                  ( interpreter )+import           Data.Morpheus.Kind             ( OBJECT+                                                , UNION+                                                )+import           Data.Morpheus.Types            ( GQLRequest+                                                , GQLResponse+                                                , GQLRootResolver(..)+                                                , GQLType(..)+                                                , IORes+                                                , Undefined(..)+                                                )+import           Data.Text                      ( Text )+import           GHC.Generics                   ( Generic )  instance GQLType A where   type KIND A = OBJECT@@ -24,8 +32,8 @@ instance GQLType C where   type KIND C = OBJECT -instance GQLType AOrB where-  type KIND AOrB = UNION+instance GQLType Sum where+  type KIND Sum = UNION  data A = A   { aText :: Text@@ -42,26 +50,28 @@   , cInt  :: Int   } deriving (Generic) -data AOrB-  = A' A-  | B' B+data Sum+  = SumA A+  | SumB B   deriving (Generic)  data Query m = Query-  { union :: () -> m [AOrB]+  { union :: () -> m [Sum]   , fc    :: C   } deriving (Generic, GQLType) -resolveUnion :: () -> IORes () [AOrB]-resolveUnion _ = return [A' A {aText = "at", aInt = 1}, B' B {bText = "bt", bInt = 2}]+resolveUnion :: () -> IORes () [Sum]+resolveUnion _ =+  return [SumA A { aText = "at", aInt = 1 }, SumB B { bText = "bt", bInt = 2 }]  rootResolver :: GQLRootResolver IO () Query Undefined Undefined-rootResolver =-  GQLRootResolver-    { queryResolver = Query {union = resolveUnion, fc = C {cText = "", cInt = 3}}-    , mutationResolver = Undefined-    , subscriptionResolver = Undefined-    }+rootResolver = GQLRootResolver+  { queryResolver        = Query { union = resolveUnion+                                 , fc    = C { cText = "", cInt = 3 }+                                 }+  , mutationResolver     = Undefined+  , subscriptionResolver = Undefined+  }  api :: GQLRequest -> IO GQLResponse api = interpreter rootResolver
test/Feature/UnionType/cannotBeSpreadOnType/response.json view
@@ -1,9 +1,13 @@ {-  "errors": [{-    "message": "Fragment \"FC\" cannot be spread here as objects of type \"AB\" can never be of type \"C\".",-    "locations": [{-      "line": 3,-      "column": 5-    }]-  }]+  "errors": [+    {+      "message": "Fragment \"FC\" cannot be spread here as objects of type \"A, B\" can never be of type \"C\".",+      "locations": [+        {+          "line": 3,+          "column": 5+        }+      ]+    }+  ] }
test/Feature/UnionType/inlineFragment/cannotBeSpreadOnType/response.json view
@@ -1,7 +1,7 @@ {   "errors": [     {-      "message": "Fragment cannot be spread here as objects of type \"AB\" can never be of type \"C\".",+      "message": "Fragment cannot be spread here as objects of type \"A, B\" can never be of type \"C\".",       "locations": [         {           "line": 3,
test/Spec.hs view
@@ -2,27 +2,56 @@  module Main   ( main-  ) where+  )+where -import qualified Feature.Holistic.API          as Holistic (api)-import qualified Feature.Input.Enum.API        as InputEnum (api)-import qualified Feature.InputType.API         as InputType (api)-import qualified Feature.Schema.API            as Schema (api)-import qualified Feature.UnionType.API         as UnionType (api)-import qualified Feature.WrappedTypeName.API   as TypeName (api)-import           Rendering.TestSchemaRendering (testSchemaRendering)-import           Test.Tasty                    (defaultMain, testGroup)-import           TestFeature                   (testFeature)+import qualified Feature.Holistic.API          as Holistic+                                                ( api )+import qualified Feature.Input.Enum.API        as InputEnum+                                                ( api )+import qualified Feature.Input.Scalar.API      as InputScalar+                                                ( api )+import qualified Feature.Input.Object.API      as InputObject+                                                ( api )+import qualified Feature.InputType.API         as InputType+                                                ( api )+import qualified Feature.Schema.API            as Schema+                                                ( api )+import qualified Feature.UnionType.API         as UnionType+                                                ( api )+import qualified Feature.WrappedTypeName.API   as TypeName+                                                ( api )+import qualified Feature.TypeInference.API     as Inference+                                                ( api )+import           Rendering.TestSchemaRendering  ( testSchemaRendering )+import           Test.Tasty                     ( defaultMain+                                                , testGroup+                                                )+import           TestFeature                    ( testFeature )  main :: IO () main = do-  ioTests <- testFeature Holistic.api "Feature/Holistic"-  unionTest <- testFeature UnionType.api "Feature/UnionType"-  inputTest <- testFeature InputType.api "Feature/InputType"-  schemaTest <- testFeature Schema.api "Feature/Schema"-  typeName <- testFeature TypeName.api "Feature/WrappedTypeName"-  inputEnum <- testFeature InputEnum.api "Feature/Input/Enum"+  ioTests     <- testFeature Holistic.api "Feature/Holistic"+  unionTest   <- testFeature UnionType.api "Feature/UnionType"+  inputTest   <- testFeature InputType.api "Feature/InputType"+  schemaTest  <- testFeature Schema.api "Feature/Schema"+  typeName    <- testFeature TypeName.api "Feature/WrappedTypeName"+  inputEnum   <- testFeature InputEnum.api "Feature/Input/Enum"+  inputScalar <- testFeature InputScalar.api "Feature/Input/Scalar"+  inputObject <- testFeature InputObject.api "Feature/Input/Object"+  inference   <- testFeature Inference.api "Feature/TypeInference"   defaultMain     (testGroup-       "Morpheus Graphql Tests"-       [ioTests, unionTest, inputTest, schemaTest, typeName, inputEnum, testSchemaRendering])+      "Morpheus Graphql Tests"+      [ ioTests+      , unionTest+      , inputTest+      , schemaTest+      , typeName+      , inputEnum+      , inputScalar+      , inputObject+      , testSchemaRendering+      , inference+      ]+    )