packages feed

morpheus-graphql-core 0.17.0 → 0.18.0

raw patch · 132 files changed

+3975/−4514 lines, 132 filesdep +morpheus-graphql-testsPVP ok

version bump matches the API change (PVP)

Dependencies added: morpheus-graphql-tests

API changes (from Hackage documentation)

- Data.Morpheus.Internal.Ext: [events] :: Result events a -> [events]
- Data.Morpheus.Internal.Ext: class Applicative f => Failure error (f :: * -> *)
- Data.Morpheus.Internal.Ext: class SemigroupM (m :: * -> *) a
- Data.Morpheus.Internal.Ext: instance Data.Morpheus.Internal.Ext.UnsafeFromList Data.Morpheus.Ext.OrdMap.OrdMap
- Data.Morpheus.Internal.Ext: instance Data.Morpheus.Internal.Ext.UnsafeFromList Data.Morpheus.Ext.SafeHashMap.SafeHashMap
- Data.Morpheus.Internal.Ext: mergeM :: SemigroupM m a => [Ref FieldName] -> a -> a -> m a
- Data.Morpheus.Internal.Ext: type Eventless = Result ()
- Data.Morpheus.Internal.Ext: unpackEvents :: Result event a -> [event]
- Data.Morpheus.Internal.TH: _' :: PatQ
- Data.Morpheus.Internal.TH: apply :: (Apply a, ToCon i a) => i -> [a] -> a
- Data.Morpheus.Internal.TH: applyCons :: (ToName con, ToName cons) => con -> [cons] -> Q Type
- Data.Morpheus.Internal.TH: applyVars :: (ToName con, ToName var, Apply res, ToCon con res, ToVar var res) => con -> [var] -> res
- Data.Morpheus.Internal.TH: class ToName a
- Data.Morpheus.Internal.TH: declareTypeRef :: (TypeName -> Type) -> TypeRef -> Type
- Data.Morpheus.Internal.TH: funDSimple :: Name -> [PatQ] -> ExpQ -> DecQ
- Data.Morpheus.Internal.TH: instance Data.Morpheus.Internal.TH.Apply Language.Haskell.TH.Lib.Internal.ExpQ
- Data.Morpheus.Internal.TH: instance Data.Morpheus.Internal.TH.Apply Language.Haskell.TH.Lib.Internal.TypeQ
- Data.Morpheus.Internal.TH: instance Data.Morpheus.Internal.TH.Apply Language.Haskell.TH.Syntax.Exp
- Data.Morpheus.Internal.TH: instance Data.Morpheus.Internal.TH.Apply Language.Haskell.TH.Syntax.Type
- Data.Morpheus.Internal.TH: instance Data.Morpheus.Internal.TH.ToCon a b => Data.Morpheus.Internal.TH.ToCon a (Language.Haskell.TH.Syntax.Q b)
- Data.Morpheus.Internal.TH: instance Data.Morpheus.Internal.TH.ToName Data.Morpheus.Types.Internal.AST.Base.FieldName
- Data.Morpheus.Internal.TH: instance Data.Morpheus.Internal.TH.ToName Data.Morpheus.Types.Internal.AST.Base.TypeName
- Data.Morpheus.Internal.TH: instance Data.Morpheus.Internal.TH.ToName GHC.Base.String
- Data.Morpheus.Internal.TH: instance Data.Morpheus.Internal.TH.ToName Language.Haskell.TH.Syntax.Name
- Data.Morpheus.Internal.TH: instance Data.Morpheus.Internal.TH.ToName a => Data.Morpheus.Internal.TH.ToCon a Language.Haskell.TH.Syntax.Exp
- Data.Morpheus.Internal.TH: instance Data.Morpheus.Internal.TH.ToName a => Data.Morpheus.Internal.TH.ToCon a Language.Haskell.TH.Syntax.Type
- Data.Morpheus.Internal.TH: instance Data.Morpheus.Internal.TH.ToName a => Data.Morpheus.Internal.TH.ToVar a Language.Haskell.TH.Syntax.Exp
- Data.Morpheus.Internal.TH: instance Data.Morpheus.Internal.TH.ToName a => Data.Morpheus.Internal.TH.ToVar a Language.Haskell.TH.Syntax.Pat
- Data.Morpheus.Internal.TH: instance Data.Morpheus.Internal.TH.ToName a => Data.Morpheus.Internal.TH.ToVar a Language.Haskell.TH.Syntax.Type
- Data.Morpheus.Internal.TH: instance Data.Morpheus.Internal.TH.ToString Data.Morpheus.Types.Internal.AST.Base.FieldName Language.Haskell.TH.Syntax.Exp
- Data.Morpheus.Internal.TH: instance Data.Morpheus.Internal.TH.ToString Data.Morpheus.Types.Internal.AST.Base.FieldName Language.Haskell.TH.Syntax.Lit
- Data.Morpheus.Internal.TH: instance Data.Morpheus.Internal.TH.ToString Data.Morpheus.Types.Internal.AST.Base.TypeName Language.Haskell.TH.Syntax.Exp
- Data.Morpheus.Internal.TH: instance Data.Morpheus.Internal.TH.ToString Data.Morpheus.Types.Internal.AST.Base.TypeName Language.Haskell.TH.Syntax.Lit
- Data.Morpheus.Internal.TH: instance Data.Morpheus.Internal.TH.ToString Data.Morpheus.Types.Internal.AST.Base.TypeName Language.Haskell.TH.Syntax.Pat
- Data.Morpheus.Internal.TH: instance Data.Morpheus.Internal.TH.ToString a b => Data.Morpheus.Internal.TH.ToString a (Language.Haskell.TH.Syntax.Q b)
- Data.Morpheus.Internal.TH: instance Data.Morpheus.Internal.TH.ToVar a b => Data.Morpheus.Internal.TH.ToVar a (Language.Haskell.TH.Syntax.Q b)
- Data.Morpheus.Internal.TH: nameSpaceField :: TypeName -> FieldName -> FieldName
- Data.Morpheus.Internal.TH: nameSpaceType :: [FieldName] -> TypeName -> TypeName
- Data.Morpheus.Internal.TH: toCon :: ToCon a b => a -> b
- Data.Morpheus.Internal.TH: toName :: ToName a => a -> Name
- Data.Morpheus.Internal.TH: toString :: ToString a b => a -> b
- Data.Morpheus.Internal.TH: toVar :: ToVar a b => a -> b
- Data.Morpheus.Internal.TH: typeInstanceDec :: Name -> Type -> Type -> Dec
- Data.Morpheus.Internal.TH: v' :: ToVar Name a => a
- Data.Morpheus.Internal.TH: vars :: ToVar a b => [a] -> [b]
- Data.Morpheus.Internal.Utils: capitalTypeName :: FieldName -> TypeName
- Data.Morpheus.Internal.Utils: capitalize :: Text -> Text
- Data.Morpheus.Internal.Utils: class Collection a coll | coll -> a
- Data.Morpheus.Internal.Utils: class Elems a coll | coll -> a
- Data.Morpheus.Internal.Utils: class Applicative f => Failure error (f :: * -> *)
- Data.Morpheus.Internal.Utils: class FromElems m a coll | coll -> a
- Data.Morpheus.Internal.Utils: class Selectable k a c | c -> a
- Data.Morpheus.Internal.Utils: failOnDuplicates :: (Failure ValidationErrors m, NameCollision a) => NonEmpty a -> m a
- Data.Morpheus.Internal.Utils: instance (Data.Morpheus.Error.NameCollision.NameCollision a, Data.Morpheus.Ext.Failure.Failure Data.Morpheus.Types.Internal.AST.Base.ValidationErrors m, Data.Morpheus.Ext.KeyOf.KeyOf k a, GHC.Base.Monad m) => Data.Morpheus.Internal.Utils.FromElems m a (Data.HashMap.Internal.HashMap k a)
- Data.Morpheus.Internal.Utils: instance Data.Morpheus.Ext.KeyOf.KeyOf k v => Data.Morpheus.Internal.Utils.Collection v (Data.HashMap.Internal.HashMap k v)
- Data.Morpheus.Internal.Utils: instance Data.Morpheus.Internal.Utils.Collection a [a]
- Data.Morpheus.Internal.Utils: mapFst :: (a -> a') -> (a, b) -> (a', b)
- Data.Morpheus.Internal.Utils: mapSnd :: (b -> b') -> (a, b) -> (a, b')
- Data.Morpheus.Internal.Utils: mapTuple :: (a -> a') -> (b -> b') -> (a, b) -> (a', b')
- Data.Morpheus.Internal.Utils: nameSpaceField :: TypeName -> FieldName -> FieldName
- Data.Morpheus.Internal.Utils: nameSpaceType :: [FieldName] -> TypeName -> TypeName
- Data.Morpheus.Internal.Utils: size :: Elems a coll => coll -> Int
- Data.Morpheus.Internal.Utils: stripConstructorNamespace :: TypeName -> String -> String
- Data.Morpheus.Internal.Utils: stripFieldNamespace :: TypeName -> String -> String
- Data.Morpheus.Types.Internal.AST: ConsD :: TypeName -> [f] -> ConsD f
- Data.Morpheus.Types.Internal.AST: FieldName :: Text -> FieldName
- Data.Morpheus.Types.Internal.AST: GQLError :: Message -> [Position] -> GQLError
- Data.Morpheus.Types.Internal.AST: InternalError :: Text -> InternalError
- Data.Morpheus.Types.Internal.AST: ListType :: DataTypeWrapper
- Data.Morpheus.Types.Internal.AST: NonNullType :: DataTypeWrapper
- Data.Morpheus.Types.Internal.AST: TypeMaybe :: TypeWrapper
- Data.Morpheus.Types.Internal.AST: TypeName :: Text -> TypeName
- Data.Morpheus.Types.Internal.AST: ValidationError :: Message -> [Position] -> ValidationError
- Data.Morpheus.Types.Internal.AST: [cFields] :: ConsD f -> [f]
- Data.Morpheus.Types.Internal.AST: [cName] :: ConsD f -> TypeName
- Data.Morpheus.Types.Internal.AST: [locations] :: GQLError -> [Position]
- Data.Morpheus.Types.Internal.AST: [message] :: GQLError -> Message
- Data.Morpheus.Types.Internal.AST: [readInternalError] :: InternalError -> Text
- Data.Morpheus.Types.Internal.AST: [readName] :: FieldName -> Text
- Data.Morpheus.Types.Internal.AST: [readTypeName] :: TypeName -> Text
- Data.Morpheus.Types.Internal.AST: [validationLocations] :: ValidationError -> [Position]
- Data.Morpheus.Types.Internal.AST: [validationMessage] :: ValidationError -> Message
- Data.Morpheus.Types.Internal.AST: anonymousRef :: name -> Ref name
- Data.Morpheus.Types.Internal.AST: convertToHaskellName :: FieldName -> FieldName
- Data.Morpheus.Types.Internal.AST: convertToJSONName :: FieldName -> FieldName
- Data.Morpheus.Types.Internal.AST: data ConsD f
- Data.Morpheus.Types.Internal.AST: data DataTypeWrapper
- Data.Morpheus.Types.Internal.AST: data Message
- Data.Morpheus.Types.Internal.AST: data ValidationError
- Data.Morpheus.Types.Internal.AST: fieldContentArgs :: FieldContent b cat s -> ArgumentsDefinition s
- Data.Morpheus.Types.Internal.AST: hsTypeName :: TypeName -> TypeName
- Data.Morpheus.Types.Internal.AST: intercalateName :: FieldName -> [FieldName] -> FieldName
- Data.Morpheus.Types.Internal.AST: isWeaker :: [TypeWrapper] -> [TypeWrapper] -> Bool
- Data.Morpheus.Types.Internal.AST: mkConsEnum :: DataEnumValue s -> ConsD f
- Data.Morpheus.Types.Internal.AST: mkInputValue :: FieldName -> [TypeWrapper] -> TypeName -> FieldDefinition cat s
- Data.Morpheus.Types.Internal.AST: msgInternal :: Msg a => a -> InternalError
- Data.Morpheus.Types.Internal.AST: msgSepBy :: Msg a => Text -> [a] -> Message
- Data.Morpheus.Types.Internal.AST: msgValidation :: Msg a => a -> ValidationError
- Data.Morpheus.Types.Internal.AST: newtype FieldName
- Data.Morpheus.Types.Internal.AST: newtype InternalError
- Data.Morpheus.Types.Internal.AST: newtype TypeName
- Data.Morpheus.Types.Internal.AST: toFieldName :: TypeName -> FieldName
- Data.Morpheus.Types.Internal.AST: toGQLError :: ValidationError -> GQLError
- Data.Morpheus.Types.Internal.AST: toGQLWrapper :: [TypeWrapper] -> [DataTypeWrapper]
- Data.Morpheus.Types.Internal.AST: toHSWrappers :: [DataTypeWrapper] -> [TypeWrapper]
- Data.Morpheus.Types.Internal.AST: type DataInputUnion s = [UnionMember IN s]
- Data.Morpheus.Types.Internal.AST: type DataUnion s = [UnionMember OUT s]
- Data.Morpheus.Types.Internal.AST: type DirectiveDefinitions s = [DirectiveDefinition s]
- Data.Morpheus.Types.Internal.AST: type TypeLib s = SafeHashMap TypeName (TypeDefinition ANY s)
- Data.Morpheus.Types.Internal.AST: type ValidationErrors = [ValidationError]
- Data.Morpheus.Types.Internal.AST: withPosition :: Maybe Position -> ValidationError -> ValidationError
+ Data.Morpheus.Internal.Ext: class Merge m a
+ Data.Morpheus.Internal.Ext: merge :: (Merge m a, Monad m) => a -> a -> m a
+ Data.Morpheus.Internal.Ext: toEither :: Result err b -> Either (NonEmpty err) b
+ Data.Morpheus.Internal.Ext: type Failure = MonadError
+ Data.Morpheus.Internal.Ext: type GQLResult = Result GQLError
+ Data.Morpheus.Internal.Utils: (<:>) :: (Merge (HistoryT m) a, Monad m) => a -> a -> m a
+ Data.Morpheus.Internal.Utils: addPath :: MonadReader [a1] m => a1 -> m a2 -> m a2
+ Data.Morpheus.Internal.Utils: class IsMap k m | m -> k
+ Data.Morpheus.Internal.Utils: insert :: (NameCollision e a, KeyOf k a, Failure e m) => a -> SafeHashMap k a -> m (SafeHashMap k a)
+ Data.Morpheus.Internal.Utils: mergeConcat :: (Monad m, Merge m a, MonadError e m) => NonEmpty a -> m a
+ Data.Morpheus.Internal.Utils: startHistory :: HistoryT m a -> m a
+ Data.Morpheus.Internal.Utils: throwErrors :: MonadError e m => NonEmpty e -> m b
+ Data.Morpheus.Internal.Utils: type Failure = MonadError
+ Data.Morpheus.Internal.Utils: type HistoryT = ReaderT [Ref FieldName]
+ Data.Morpheus.Internal.Utils: unsafeFromList :: IsMap k m => [(k, a)] -> m a
+ Data.Morpheus.Types.ID: instance GHC.Base.Semigroup Data.Morpheus.Types.ID.ID
+ Data.Morpheus.Types.Internal.AST: BaseType :: !Bool -> TypeWrapper
+ Data.Morpheus.Types.Internal.AST: at :: GQLError -> Position -> GQLError
+ Data.Morpheus.Types.Internal.AST: atPositions :: Foldable t => GQLError -> t Position -> GQLError
+ Data.Morpheus.Types.Internal.AST: class Subtyping t
+ Data.Morpheus.Types.Internal.AST: data Name (t :: NAME)
+ Data.Morpheus.Types.Internal.AST: fieldArguments :: FieldDefinition c s -> ArgumentsDefinition s
+ Data.Morpheus.Types.Internal.AST: intercalate :: Name t1 -> [Name t2] -> Name t3
+ Data.Morpheus.Types.Internal.AST: internal :: GQLError -> GQLError
+ Data.Morpheus.Types.Internal.AST: isInternal :: GQLError -> Bool
+ Data.Morpheus.Types.Internal.AST: isPossibleInterfaceType :: TypeName -> TypeDefinition c s -> Maybe (TypeDefinition c s)
+ Data.Morpheus.Types.Internal.AST: isSubtype :: Subtyping t => t -> t -> Bool
+ Data.Morpheus.Types.Internal.AST: lookupDataType :: TypeName -> Schema s -> Maybe (TypeDefinition ANY s)
+ Data.Morpheus.Types.Internal.AST: mkBaseType :: TypeWrapper
+ Data.Morpheus.Types.Internal.AST: mkMaybeType :: TypeWrapper
+ Data.Morpheus.Types.Internal.AST: packName :: Text -> Name t
+ Data.Morpheus.Types.Internal.AST: splitSystemSelection :: SelectionSet s -> (Maybe (SelectionSet s), Maybe (SelectionSet s))
+ Data.Morpheus.Types.Internal.AST: type DirectivesDefinition s = OrdMap FieldName (DirectiveDefinition s)
+ Data.Morpheus.Types.Internal.AST: type FieldName = Name 'FIELD
+ Data.Morpheus.Types.Internal.AST: type FragmentName = Name 'FRAGMENT
+ Data.Morpheus.Types.Internal.AST: type Message = Text
+ Data.Morpheus.Types.Internal.AST: type TypeDefinitions s = SafeHashMap TypeName (TypeDefinition ANY s)
+ Data.Morpheus.Types.Internal.AST: type TypeName = Name 'TYPE
+ Data.Morpheus.Types.Internal.AST: type UnionTypeDefinition k s = OrdMap TypeName (UnionMember k s)
+ Data.Morpheus.Types.Internal.AST: typeDefinitions :: Schema s -> HashMap TypeName (TypeDefinition ANY s)
+ Data.Morpheus.Types.Internal.AST: unpackName :: Name t -> Text
+ Data.Morpheus.Types.Internal.AST: withPath :: GQLError -> [Text] -> GQLError
- Data.Morpheus.Core: parseFullSchema :: ByteString -> Eventless (Schema VALID)
+ Data.Morpheus.Core: parseFullSchema :: ByteString -> GQLResult (Schema VALID)
- Data.Morpheus.Core: parseRequest :: GQLRequest -> Eventless ExecutableDocument
+ Data.Morpheus.Core: parseRequest :: GQLRequest -> GQLResult ExecutableDocument
- Data.Morpheus.Core: parseRequestWith :: Config -> Schema VALID -> GQLRequest -> Eventless (Operation VALID)
+ Data.Morpheus.Core: parseRequestWith :: Config -> Schema VALID -> GQLRequest -> GQLResult (Operation VALID)
- Data.Morpheus.Core: parseSchema :: ByteString -> Eventless (Schema VALID)
+ Data.Morpheus.Core: parseSchema :: ByteString -> GQLResult (Schema VALID)
- Data.Morpheus.Core: parseTypeDefinitions :: ByteString -> Eventless [TypeDefinition ANY CONST]
+ Data.Morpheus.Core: parseTypeDefinitions :: ByteString -> GQLResult [TypeDefinition ANY CONST]
- Data.Morpheus.Core: validateRequest :: Config -> Schema VALID -> ExecutableDocument -> Eventless (Operation VALID)
+ Data.Morpheus.Core: validateRequest :: Config -> Schema VALID -> ExecutableDocument -> GQLResult (Operation VALID)
- Data.Morpheus.Core: validateSchema :: ValidateSchema s => Bool -> Config -> Schema s -> Eventless (Schema VALID)
+ Data.Morpheus.Core: validateSchema :: ValidateSchema s => Bool -> Config -> Schema s -> GQLResult (Schema VALID)
- Data.Morpheus.Error: class NameCollision a
+ Data.Morpheus.Error: class NameCollision e a
- Data.Morpheus.Error: deprecatedField :: FieldName -> Ref FieldName -> Maybe Description -> GQLErrors
+ Data.Morpheus.Error: deprecatedField :: FieldName -> Ref FieldName -> Maybe Description -> GQLError
- Data.Morpheus.Error: errorMessage :: Position -> Message -> GQLErrors
+ Data.Morpheus.Error: errorMessage :: Position -> Message -> [GQLError]
- Data.Morpheus.Error: globalErrorMessage :: Message -> GQLErrors
+ Data.Morpheus.Error: globalErrorMessage :: Message -> [GQLError]
- Data.Morpheus.Error: gqlWarnings :: GQLErrors -> Q ()
+ Data.Morpheus.Error: gqlWarnings :: [GQLError] -> Q ()
- Data.Morpheus.Error: nameCollision :: NameCollision a => a -> ValidationError
+ Data.Morpheus.Error: nameCollision :: NameCollision e a => a -> e
- Data.Morpheus.Error: subfieldsNotSelected :: FieldName -> TypeName -> Position -> ValidationError
+ Data.Morpheus.Error: subfieldsNotSelected :: FieldName -> TypeName -> Position -> GQLError
- Data.Morpheus.Internal.Ext: (<:>) :: SemigroupM m a => a -> a -> m a
+ Data.Morpheus.Internal.Ext: (<:>) :: (Merge (HistoryT m) a, Monad m) => a -> a -> m a
- Data.Morpheus.Internal.Ext: Failure :: GQLErrors -> Result events a
+ Data.Morpheus.Internal.Ext: Failure :: NonEmpty err -> Result err a
- Data.Morpheus.Internal.Ext: ResultT :: m (Result event a) -> ResultT event (m :: * -> *) a
+ Data.Morpheus.Internal.Ext: ResultT :: m (Result GQLError ([event], a)) -> ResultT event (m :: Type -> Type) a
- Data.Morpheus.Internal.Ext: Success :: a -> GQLErrors -> [events] -> Result events a
+ Data.Morpheus.Internal.Ext: Success :: a -> [err] -> Result err a
- Data.Morpheus.Internal.Ext: [errors] :: Result events a -> GQLErrors
+ Data.Morpheus.Internal.Ext: [errors] :: Result err a -> NonEmpty err
- Data.Morpheus.Internal.Ext: [result] :: Result events a -> a
+ Data.Morpheus.Internal.Ext: [result] :: Result err a -> a
- Data.Morpheus.Internal.Ext: [runResultT] :: ResultT event (m :: * -> *) a -> m (Result event a)
+ Data.Morpheus.Internal.Ext: [runResultT] :: ResultT event (m :: Type -> Type) a -> m (Result GQLError ([event], a))
- Data.Morpheus.Internal.Ext: [warnings] :: Result events a -> GQLErrors
+ Data.Morpheus.Internal.Ext: [warnings] :: Result err a -> [err]
- Data.Morpheus.Internal.Ext: data Result events a
+ Data.Morpheus.Internal.Ext: data Result err a
- Data.Morpheus.Internal.Ext: failure :: Failure error f => error -> f v
+ Data.Morpheus.Internal.Ext: failure :: MonadError e m => e -> m a
- Data.Morpheus.Internal.Ext: newtype ResultT event (m :: * -> *) a
+ Data.Morpheus.Internal.Ext: newtype ResultT event (m :: Type -> Type) a
- Data.Morpheus.Internal.Ext: resultOr :: (GQLErrors -> a') -> (a -> a') -> Result e a -> a'
+ Data.Morpheus.Internal.Ext: resultOr :: (NonEmpty err -> a') -> (a -> a') -> Result err a -> a'
- Data.Morpheus.Internal.Ext: sortErrors :: Result e a -> Result e a
+ Data.Morpheus.Internal.Ext: sortErrors :: Result GQLError a -> Result GQLError a
- Data.Morpheus.Internal.Ext: unsafeFromList :: (UnsafeFromList f, Hashable k, KeyOf k a, Eq k) => [(k, a)] -> f k a
+ Data.Morpheus.Internal.Ext: unsafeFromList :: IsMap k m => [(k, a)] -> m a
- Data.Morpheus.Internal.Utils: elems :: Elems a coll => coll -> [a]
+ Data.Morpheus.Internal.Utils: elems :: Foldable t => t a -> [a]
- Data.Morpheus.Internal.Utils: failure :: Failure error f => error -> f v
+ Data.Morpheus.Internal.Utils: failure :: MonadError e m => e -> m a
- Data.Morpheus.Internal.Utils: fromElems :: FromElems m a coll => [a] -> m coll
+ Data.Morpheus.Internal.Utils: fromElems :: (Monad m, KeyOf k a, FromList m map k a) => [a] -> m (map k a)
- Data.Morpheus.Internal.Utils: member :: Selectable k a c => k -> c -> Bool
+ Data.Morpheus.Internal.Utils: member :: IsMap k m => k -> m a -> Bool
- Data.Morpheus.Internal.Utils: mergeT :: (KeyOf k a, Monad m, Elems a c) => c -> c -> ResolutionT k a c m c
+ Data.Morpheus.Internal.Utils: mergeT :: (KeyOf k a, Foldable t, Monad m) => t a -> t a -> ResolutionT k a c m c
- Data.Morpheus.Internal.Utils: selectBy :: (Failure e m, Selectable k a c, Monad m) => e -> k -> c -> m a
+ Data.Morpheus.Internal.Utils: selectBy :: (MonadError e m, IsMap k c, Monad m) => e -> k -> c a -> m a
- Data.Morpheus.Internal.Utils: selectOr :: Selectable k a c => d -> (a -> d) -> k -> c -> d
+ Data.Morpheus.Internal.Utils: selectOr :: IsMap k c => d -> (a -> d) -> k -> c a -> d
- Data.Morpheus.Internal.Utils: singleton :: Collection a coll => a -> coll
+ Data.Morpheus.Internal.Utils: singleton :: (IsMap k m, KeyOf k a) => a -> m a
- Data.Morpheus.Internal.Utils: traverseCollection :: (Monad f, KeyOf k b, Elems a (t a), FromElems f b (t' b), Failure ValidationErrors f) => (a -> f b) -> t a -> f (t' b)
+ Data.Morpheus.Internal.Utils: traverseCollection :: (Monad m, Failure GQLError m, KeyOf k b, FromList m map k b, Foldable t) => (a -> m b) -> t a -> m (map k b)
- Data.Morpheus.Types.GQLScalar: class DecodeScalar (a :: *)
+ Data.Morpheus.Types.GQLScalar: class DecodeScalar (a :: Type)
- Data.Morpheus.Types.GQLScalar: class EncodeScalar (a :: *)
+ Data.Morpheus.Types.GQLScalar: class EncodeScalar (a :: Type)
- Data.Morpheus.Types.IO: renderResponse :: Result e ValidValue -> GQLResponse
+ Data.Morpheus.Types.IO: renderResponse :: Result GQLError ValidValue -> GQLResponse
- Data.Morpheus.Types.Internal.AST: DataEnumValue :: Maybe Description -> TypeName -> [Directive s] -> DataEnumValue s
+ Data.Morpheus.Types.Internal.AST: DataEnumValue :: Maybe Description -> TypeName -> Directives s -> DataEnumValue s
- Data.Morpheus.Types.Internal.AST: FieldDefinition :: Maybe Description -> FieldName -> TypeRef -> Maybe (FieldContent TRUE cat s) -> [Directive s] -> FieldDefinition (cat :: TypeCategory) (s :: Stage)
+ Data.Morpheus.Types.Internal.AST: FieldDefinition :: Maybe Description -> FieldName -> TypeRef -> Maybe (FieldContent TRUE cat s) -> Directives s -> FieldDefinition (cat :: TypeCategory) (s :: Stage)
- Data.Morpheus.Types.Internal.AST: Fragment :: FieldName -> TypeName -> Position -> SelectionSet stage -> Directives stage -> Fragment (stage :: Stage)
+ Data.Morpheus.Types.Internal.AST: Fragment :: FragmentName -> TypeName -> Position -> SelectionSet stage -> Directives stage -> Fragment (stage :: Stage)
- Data.Morpheus.Types.Internal.AST: Schema :: TypeLib s -> TypeDefinition OBJECT s -> Maybe (TypeDefinition OBJECT s) -> Maybe (TypeDefinition OBJECT s) -> [DirectiveDefinition s] -> Schema (s :: Stage)
+ Data.Morpheus.Types.Internal.AST: Schema :: TypeDefinitions s -> TypeDefinition OBJECT s -> Maybe (TypeDefinition OBJECT s) -> Maybe (TypeDefinition OBJECT s) -> DirectivesDefinition s -> Schema (s :: Stage)
- Data.Morpheus.Types.Internal.AST: TypeList :: TypeWrapper
+ Data.Morpheus.Types.Internal.AST: TypeList :: !TypeWrapper -> !Bool -> TypeWrapper
- Data.Morpheus.Types.Internal.AST: TypeRef :: TypeName -> [TypeWrapper] -> TypeRef
+ Data.Morpheus.Types.Internal.AST: TypeRef :: TypeName -> TypeWrapper -> TypeRef
- Data.Morpheus.Types.Internal.AST: [DataInputUnion] :: {inputUnionMembers :: DataInputUnion s} -> CondTypeContent IN a s
+ Data.Morpheus.Types.Internal.AST: [DataInputUnion] :: {inputUnionMembers :: UnionTypeDefinition IN s} -> CondTypeContent IN a s
- Data.Morpheus.Types.Internal.AST: [DataUnion] :: {unionMembers :: DataUnion s} -> CondTypeContent OUT a s
+ Data.Morpheus.Types.Internal.AST: [DataUnion] :: {unionMembers :: UnionTypeDefinition OUT s} -> CondTypeContent OUT a s
- Data.Morpheus.Types.Internal.AST: [Spread] :: Directives RAW -> Ref FieldName -> Selection RAW
+ Data.Morpheus.Types.Internal.AST: [Spread] :: Directives RAW -> Ref FragmentName -> Selection RAW
- Data.Morpheus.Types.Internal.AST: [UnionSelection] :: UnionSelection VALID -> SelectionContent VALID
+ Data.Morpheus.Types.Internal.AST: [UnionSelection] :: {defaultSelection :: SelectionSet VALID, conditionalSelections :: UnionSelection VALID} -> SelectionContent VALID
- Data.Morpheus.Types.Internal.AST: [directiveDefinitions] :: Schema (s :: Stage) -> [DirectiveDefinition s]
+ Data.Morpheus.Types.Internal.AST: [directiveDefinitions] :: Schema (s :: Stage) -> DirectivesDefinition s
- Data.Morpheus.Types.Internal.AST: [enumDirectives] :: DataEnumValue s -> [Directive s]
+ Data.Morpheus.Types.Internal.AST: [enumDirectives] :: DataEnumValue s -> Directives s
- Data.Morpheus.Types.Internal.AST: [fieldDirectives] :: FieldDefinition (cat :: TypeCategory) (s :: Stage) -> [Directive s]
+ Data.Morpheus.Types.Internal.AST: [fieldDirectives] :: FieldDefinition (cat :: TypeCategory) (s :: Stage) -> Directives s
- Data.Morpheus.Types.Internal.AST: [fragmentName] :: Fragment (stage :: Stage) -> FieldName
+ Data.Morpheus.Types.Internal.AST: [fragmentName] :: Fragment (stage :: Stage) -> FragmentName
- Data.Morpheus.Types.Internal.AST: [typeWrappers] :: TypeRef -> [TypeWrapper]
+ Data.Morpheus.Types.Internal.AST: [typeWrappers] :: TypeRef -> TypeWrapper
- Data.Morpheus.Types.Internal.AST: [types] :: Schema (s :: Stage) -> TypeLib s
+ Data.Morpheus.Types.Internal.AST: [types] :: Schema (s :: Stage) -> TypeDefinitions s
- Data.Morpheus.Types.Internal.AST: buildSchema :: (Monad m, Failure ValidationErrors m) => (Maybe SchemaDefinition, [TypeDefinition ANY s], [DirectiveDefinition s]) -> m (Schema s)
+ Data.Morpheus.Types.Internal.AST: buildSchema :: (Monad m, MonadError GQLError m) => (Maybe SchemaDefinition, [TypeDefinition ANY s], DirectivesDefinition s) -> m (Schema s)
- Data.Morpheus.Types.Internal.AST: constraintInputUnion :: forall stage schemaStage. [UnionMember IN schemaStage] -> Object stage -> Either Message (UnionMember IN schemaStage, Value stage)
+ Data.Morpheus.Types.Internal.AST: constraintInputUnion :: forall stage schemaStage. UnionTypeDefinition IN schemaStage -> Object stage -> Either GQLError (UnionMember IN schemaStage, Value stage)
- Data.Morpheus.Types.Internal.AST: defineSchemaWith :: (Monad f, Failure ValidationErrors f) => [TypeDefinition cat s] -> (Maybe (TypeDefinition OBJECT s), Maybe (TypeDefinition OBJECT s), Maybe (TypeDefinition OBJECT s)) -> f (Schema s)
+ Data.Morpheus.Types.Internal.AST: defineSchemaWith :: (Monad f, MonadError GQLError f) => [TypeDefinition cat s] -> (Maybe (TypeDefinition OBJECT s), Maybe (TypeDefinition OBJECT s), Maybe (TypeDefinition OBJECT s)) -> f (Schema s)
- Data.Morpheus.Types.Internal.AST: getInputUnionValue :: forall stage. Object stage -> Either Message (TypeName, Value stage)
+ Data.Morpheus.Types.Internal.AST: getInputUnionValue :: forall stage. Object stage -> Either GQLError (TypeName, Value stage)
- Data.Morpheus.Types.Internal.AST: getOperationDataType :: Failure ValidationError m => Operation s -> Schema VALID -> m (TypeDefinition OBJECT VALID)
+ Data.Morpheus.Types.Internal.AST: getOperationDataType :: MonadError GQLError m => Operation s -> Schema VALID -> m (TypeDefinition OBJECT VALID)
- Data.Morpheus.Types.Internal.AST: lookupDeprecated :: [Directive s] -> Maybe (Directive s)
+ Data.Morpheus.Types.Internal.AST: lookupDeprecated :: Directives s -> Maybe (Directive s)
- Data.Morpheus.Types.Internal.AST: mkInputUnionFields :: [UnionMember IN s] -> FieldsDefinition IN s
+ Data.Morpheus.Types.Internal.AST: mkInputUnionFields :: Foldable t => t (UnionMember IN s) -> FieldsDefinition IN s
- Data.Morpheus.Types.Internal.AST: mkObjectField :: ArgumentsDefinition s -> FieldName -> [TypeWrapper] -> TypeName -> FieldDefinition OUT s
+ Data.Morpheus.Types.Internal.AST: mkObjectField :: ArgumentsDefinition s -> FieldName -> TypeWrapper -> TypeName -> FieldDefinition OUT s
- Data.Morpheus.Types.Internal.AST: msg :: Msg a => a -> Message
+ Data.Morpheus.Types.Internal.AST: msg :: Msg a => a -> GQLError
- Data.Morpheus.Types.Internal.AST: type Directives s = [Directive s]
+ Data.Morpheus.Types.Internal.AST: type Directives s = OrdMap FieldName (Directive s)
- Data.Morpheus.Types.Internal.AST: type Fragments (s :: Stage) = OrdMap FieldName (Fragment s)
+ Data.Morpheus.Types.Internal.AST: type Fragments (s :: Stage) = OrdMap FragmentName (Fragment s)
- Data.Morpheus.Types.Internal.AST: type GQLErrors = [GQLError]
+ Data.Morpheus.Types.Internal.AST: type GQLErrors = NonEmpty GQLError
- Data.Morpheus.Types.Internal.AST: type SelectionSet (s :: Stage) = MergeSet s FieldName (Selection s)
+ Data.Morpheus.Types.Internal.AST: type SelectionSet (s :: Stage) = MergeMap (ALLOW_DUPLICATES s) FieldName (Selection s)
- Data.Morpheus.Types.Internal.AST: type UnionSelection (s :: Stage) = MergeSet s TypeName UnionTag
+ Data.Morpheus.Types.Internal.AST: type UnionSelection (s :: Stage) = MergeMap (ALLOW_DUPLICATES s) TypeName UnionTag

Files

changelog.md view
@@ -1,5 +1,12 @@ # Changelog +## 0.18.0 - 08.11.2021++- GraphQL errors support additional field `extensions :: Maybe Value`+- the parser reports invalid empty selection sets+- The parser is compliant with the GQL specification and supports all valid characters #581+- The parser performance improvement: on average 3-4 times faster, in some cases more than 100 times faster.+ ## 0.17.0 - 25.02.2021  ### New features
morpheus-graphql-core.cabal view
@@ -1,13 +1,13 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.33.0.+-- This file has been generated from package.yaml by hpack version 0.34.4. -- -- see: https://github.com/sol/hpack ----- hash: 90068e1d18639f399f1e45aabe9e946400be315246c366b4277f1cae1888f54e+-- hash: b607f4416a8e2ed3786cf203ee2634af203a16673866b658909609815a742be3  name:           morpheus-graphql-core-version:        0.17.0+version:        0.18.0 synopsis:       Morpheus GraphQL Core description:    Build GraphQL APIs with your favorite functional language! category:       web, graphql@@ -23,6 +23,12 @@     changelog.md     README.md data-files:+    test/query/parsing/selection-set/empty-selection/query.gql+    test/query/parsing/selection-set/non-empty-selection/query.gql+    test/query/validation/__typename/arguments/query.gql+    test/query/validation/__typename/schema.gql+    test/query/validation/__typename/selection-set/query.gql+    test/query/validation/__typename/success/query.gql     test/rendering/simple/directive/query.gql     test/rendering/simple/directive/rendering.gql     test/rendering/simple/fragment/query.gql@@ -54,6 +60,8 @@     test/rendering/variable/schema.gql     test/rendering/variable/simple/query.gql     test/rendering/variable/simple/rendering.gql+    test/schema/parsing/descriptions/grave-accent/schema.gql+    test/schema/parsing/descriptions/ok/schema.gql     test/schema/parsing/directive/ok/simple/schema.gql     test/schema/parsing/directive/ok/sophisticated/schema.gql     test/schema/parsing/schema-definition/fail/dupplicate-field/query-mutation-subscription/schema.gql@@ -92,14 +100,18 @@     "test/schema/validation/schema-definition/fail/required query/schema-with-query/schema.gql"     test/schema/validation/schema-definition/fail/unknown-type/unknown/schema.gql     test/schema/validation/schema-definition/ok/full/schema.gql-    test/rendering/simple/fragment/variables.json-    test/rendering/union/interface/variables.json-    test/rendering/union/union/variables.json+    test/query/parsing/selection-set/empty-selection/response.json+    test/query/parsing/selection-set/non-empty-selection/response.json+    test/query/validation/__typename/arguments/response.json+    test/query/validation/__typename/selection-set/response.json+    test/query/validation/__typename/success/response.json     test/rendering/variable/enum/variables.json     test/rendering/variable/include-exclude/variables.json     test/rendering/variable/input/variables.json     test/rendering/variable/list/variables.json     test/rendering/variable/simple/variables.json+    test/schema/parsing/descriptions/grave-accent/response.json+    test/schema/parsing/descriptions/ok/response.json     test/schema/parsing/directive/ok/simple/response.json     test/schema/parsing/directive/ok/sophisticated/response.json     test/schema/parsing/schema-definition/fail/dupplicate-field/query-mutation-subscription/response.json@@ -153,36 +165,35 @@       Data.Morpheus.Types.GQLScalar       Data.Morpheus.Types.ID       Data.Morpheus.Types.SelectionTree-      Data.Morpheus.Internal.TH       Data.Morpheus.Internal.Utils       Data.Morpheus.Internal.Ext   other-modules:+      Data.Mergeable+      Data.Mergeable.Internal.Merge+      Data.Mergeable.Internal.NameCollision+      Data.Mergeable.Internal.Resolution+      Data.Mergeable.IsMap+      Data.Mergeable.MergeMap+      Data.Mergeable.OrdMap+      Data.Mergeable.SafeHashMap       Data.Morpheus.Error.Document.Interface       Data.Morpheus.Error.Fragment       Data.Morpheus.Error.Input-      Data.Morpheus.Error.NameCollision       Data.Morpheus.Error.Operation       Data.Morpheus.Error.Selection       Data.Morpheus.Error.Utils       Data.Morpheus.Error.Variable       Data.Morpheus.Error.Warning-      Data.Morpheus.Ext.Elems       Data.Morpheus.Ext.Empty-      Data.Morpheus.Ext.Failure       Data.Morpheus.Ext.KeyOf-      Data.Morpheus.Ext.Map-      Data.Morpheus.Ext.MergeSet-      Data.Morpheus.Ext.OrdMap       Data.Morpheus.Ext.Result-      Data.Morpheus.Ext.SafeHashMap-      Data.Morpheus.Ext.Selectable-      Data.Morpheus.Ext.SemigroupM       Data.Morpheus.Internal.Graph       Data.Morpheus.Parser       Data.Morpheus.Parsing.Document.TypeSystem       Data.Morpheus.Parsing.Internal.Arguments       Data.Morpheus.Parsing.Internal.Internal       Data.Morpheus.Parsing.Internal.Pattern+      Data.Morpheus.Parsing.Internal.SourceText       Data.Morpheus.Parsing.Internal.Terms       Data.Morpheus.Parsing.Internal.Value       Data.Morpheus.Parsing.Request.Operation@@ -193,10 +204,12 @@       Data.Morpheus.Schema.Schema       Data.Morpheus.Types.Internal.AST.Base       Data.Morpheus.Types.Internal.AST.DirectiveLocation+      Data.Morpheus.Types.Internal.AST.Error       Data.Morpheus.Types.Internal.AST.Fields+      Data.Morpheus.Types.Internal.AST.Name+      Data.Morpheus.Types.Internal.AST.OperationType       Data.Morpheus.Types.Internal.AST.Selection       Data.Morpheus.Types.Internal.AST.Stage-      Data.Morpheus.Types.Internal.AST.TH       Data.Morpheus.Types.Internal.AST.Type       Data.Morpheus.Types.Internal.AST.TypeCategory       Data.Morpheus.Types.Internal.AST.TypeSystem@@ -207,7 +220,9 @@       Data.Morpheus.Types.Internal.Validation.Error       Data.Morpheus.Types.Internal.Validation.Internal       Data.Morpheus.Types.Internal.Validation.SchemaValidator+      Data.Morpheus.Types.Internal.Validation.Scope       Data.Morpheus.Types.Internal.Validation.Validator+      Data.Morpheus.Validation.Document.Interface       Data.Morpheus.Validation.Document.Validation       Data.Morpheus.Validation.Internal.Arguments       Data.Morpheus.Validation.Internal.Directive@@ -240,13 +255,10 @@     , vector >=0.12.0.1 && <0.13   default-language: Haskell2010 -test-suite morpheus-test+test-suite morpheus-graphql-core-test   type: exitcode-stdio-1.0   main-is: Spec.hs   other-modules:-      Utils.Rendering-      Utils.Schema-      Utils.Utils       Paths_morpheus_graphql_core   hs-source-dirs:       test@@ -260,6 +272,7 @@     , hashable >=1.0.0     , megaparsec >=7.0.0 && <10.0.0     , morpheus-graphql-core+    , morpheus-graphql-tests >=0.18.0 && <0.19.0     , mtl >=2.0 && <=3.0     , relude >=0.3.0     , scientific >=0.3.6.2 && <0.4
+ src/Data/Mergeable.hs view
@@ -0,0 +1,27 @@+module Data.Mergeable+  ( Merge (..),+    mergeNoDuplicates,+    recursiveMerge,+    mergeConcat,+    Indexed (..),+    NameCollision (..),+    ResolutionT,+    fromListT,+    indexed,+    resolveWith,+    runResolutionT,+    collect,+    IsMap (..),+    MergeMap,+    toNonEmpty,+    OrdMap,+    throwErrors,+  )+where++import Data.Mergeable.Internal.Merge+import Data.Mergeable.Internal.NameCollision+import Data.Mergeable.Internal.Resolution+import Data.Mergeable.IsMap+import Data.Mergeable.MergeMap+import Data.Mergeable.OrdMap
+ src/Data/Mergeable/Internal/Merge.hs view
@@ -0,0 +1,107 @@+{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE NoImplicitPrelude #-}++module Data.Mergeable.Internal.Merge+  ( mergeConcat,+    Merge (..),+    mergeNoDuplicates,+    recursiveMerge,+    collect,+    throwErrors,+  )+where++import Control.Monad.Except (MonadError (throwError))+import qualified Data.HashMap.Lazy as HM+import Data.Mergeable.Internal.NameCollision (NameCollision (nameCollision))+import Data.Mergeable.Internal.Resolution+  ( fromListT,+    resolveWith,+    runResolutionT,+  )+import Relude hiding (empty, join)++class Merge m a where+  merge :: (Monad m) => a -> a -> m a++instance+  ( Eq k,+    Hashable k,+    MonadError e m,+    NameCollision e a+  ) =>+  Merge m (HashMap k a)+  where+  merge x y = mergeNoDuplicates HM.fromList (HM.toList x <> HM.toList y)++mergeConcat ::+  ( Monad m,+    Merge m a,+    MonadError e m+  ) =>+  NonEmpty a ->+  m a+mergeConcat (value :| []) = pure value+mergeConcat (value :| (x : xs)) = do+  a <- merge value x+  mergeConcat (a :| xs)++throwErrors :: MonadError e m => NonEmpty e -> m b+throwErrors (e :| es) = throwError e <* traverse throwError es++-- Merge Object with of Failure as an Option+failOnDuplicates :: (MonadError e m, NameCollision e a) => NonEmpty a -> m a+failOnDuplicates (x :| xs)+  | null xs = pure x+  | otherwise = throwErrors (nameCollision <$> x :| xs)++mergeOnDuplicates ::+  ( Monad m,+    Eq a,+    Merge m a+  ) =>+  a ->+  a ->+  m a+mergeOnDuplicates oldValue newValue+  | oldValue == newValue = pure oldValue+  | otherwise = merge oldValue newValue++mergeNoDuplicates ::+  ( Eq k,+    Hashable k,+    Monad m,+    MonadError e m,+    NameCollision e a+  ) =>+  ([(k, a)] -> b) ->+  [(k, a)] ->+  m b+mergeNoDuplicates f xs = runResolutionT (fromListT xs) f failOnDuplicates++recursiveMerge ::+  ( Eq k,+    Eq a,+    Hashable k,+    Monad m,+    Merge m a+  ) =>+  ([(k, a)] -> b) ->+  [(k, a)] ->+  m b+recursiveMerge f xs = runResolutionT (fromListT xs) f (resolveWith mergeOnDuplicates)++collect ::+  ( Eq k,+    Hashable k,+    Monad m,+    Semigroup v+  ) =>+  [(k, v)] ->+  m (HashMap k v)+collect xs = runResolutionT (fromListT xs) HM.fromList (resolveWith (\x y -> pure (x <> y)))
+ src/Data/Mergeable/Internal/NameCollision.hs view
@@ -0,0 +1,18 @@+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE NoImplicitPrelude #-}++module Data.Mergeable.Internal.NameCollision+  ( NameCollision (..),+  )+where++import Data.Mergeable.Internal.Resolution (Indexed (..))+import Relude++class NameCollision e a where+  nameCollision :: a -> e++instance NameCollision e a => NameCollision e (Indexed k a) where+  nameCollision = nameCollision . indexedValue
+ src/Data/Mergeable/Internal/Resolution.hs view
@@ -0,0 +1,103 @@+{-# LANGUAGE DeriveLift #-}+{-# LANGUAGE DeriveTraversable #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE NoImplicitPrelude #-}++module Data.Mergeable.Internal.Resolution+  ( Indexed (..),+    indexed,+    fromListT,+    resolveWith,+    runResolutionT,+    ResolutionT,+  )+where++import qualified Data.HashMap.Lazy as HM+import Language.Haskell.TH.Syntax (Lift)+import Relude++sortedEntries :: [Indexed k a] -> [(k, a)]+sortedEntries = fmap f . sortOn index+  where+    f a = (indexedKey a, indexedValue a)++fromListT :: (Monad m, Eq k, Hashable k) => [(k, a)] -> ResolutionT k a coll m coll+fromListT = traverse resolveDuplicatesM . fromListDuplicates >=> fromNoDuplicatesM++resolveWith ::+  Monad m =>+  (a -> a -> m a) ->+  NonEmpty a ->+  m a+resolveWith f (x :| xs) = foldlM f x xs++data Indexed k a = Indexed+  { index :: Int,+    indexedKey :: k,+    indexedValue :: a+  }+  deriving+    ( Show,+      Eq,+      Functor,+      Traversable,+      Foldable,+      Lift+    )++fromListDuplicates :: (Eq k, Hashable k) => [(k, a)] -> [(k, NonEmpty a)]+fromListDuplicates xs =+  sortedEntries+    $ HM.elems+    $ clusterDuplicates (indexed xs) HM.empty++indexed :: [(k, a)] -> [Indexed k a]+indexed = __indexed 0+  where+    __indexed :: Int -> [(k, a)] -> [Indexed k a]+    __indexed _ [] = []+    __indexed i ((k, x) : xs) = Indexed i k x : __indexed (i + 1) xs++resolveDuplicatesM :: Monad m => (k, NonEmpty a) -> ResolutionT k a coll m (k, a)+resolveDuplicatesM (k, xs) = asks resolveDuplicates >>= lift . fmap (k,) . (xs &)++fromNoDuplicatesM :: Monad m => [(k, a)] -> ResolutionT k a coll m coll+fromNoDuplicatesM xs = asks ((xs &) . fromNoDuplicates)++insertWithList :: (Eq k, Hashable k) => Indexed k (NonEmpty a) -> HashMap k (Indexed k (NonEmpty a)) -> HashMap k (Indexed k (NonEmpty a))+insertWithList (Indexed i1 key value) = HM.alter (Just . updater) key+  where+    updater Nothing = Indexed i1 key value+    updater (Just (Indexed i2 _ x)) = Indexed i2 key (x <> value)++clusterDuplicates :: (Eq k, Hashable k) => [Indexed k a] -> HashMap k (Indexed k (NonEmpty a)) -> HashMap k (Indexed k (NonEmpty a))+clusterDuplicates [] = id+clusterDuplicates xs = flip (foldl' (\coll x -> insertWithList (fmap (:| []) x) coll)) xs++data Resolution k a coll m = Resolution+  { resolveDuplicates :: NonEmpty a -> m a,+    fromNoDuplicates :: [(k, a)] -> coll+  }++runResolutionT ::+  ResolutionT k a coll m b ->+  ([(k, a)] -> coll) ->+  (NonEmpty a -> m a) ->+  m b+runResolutionT (ResolutionT x) fromNoDuplicates resolveDuplicates = runReaderT x Resolution {..}++newtype ResolutionT k a coll m x = ResolutionT+  { _runResolutionT :: ReaderT (Resolution k a coll m) m x+  }+  deriving+    ( Functor,+      Monad,+      Applicative,+      MonadReader (Resolution k a coll m)+    )++instance MonadTrans (ResolutionT k a coll) where+  lift = ResolutionT . lift
+ src/Data/Mergeable/IsMap.hs view
@@ -0,0 +1,47 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE NoImplicitPrelude #-}++module Data.Mergeable.IsMap+  ( IsMap (..),+    selectBy,+    selectOr,+    FromList (..),+  )+where++import Control.Monad.Except (MonadError (throwError))+import qualified Data.HashMap.Lazy as HM+import Data.Mergeable.Internal.Merge (mergeNoDuplicates)+import Data.Mergeable.Internal.NameCollision (NameCollision)+import Relude++class IsMap k m | m -> k where+  unsafeFromList :: [(k, a)] -> m a++  singleton :: k -> a -> m a++  lookup :: k -> m a -> Maybe a++  member :: k -> m a -> Bool+  member = selectOr False (const True)++instance (Eq k, Hashable k) => IsMap k (HashMap k) where+  unsafeFromList = HM.fromList+  singleton = HM.singleton+  lookup = HM.lookup+  member = HM.member++selectBy :: (MonadError e m, IsMap k c, Monad m) => e -> k -> c a -> m a+selectBy err = selectOr (throwError err) pure++selectOr :: IsMap k c => d -> (a -> d) -> k -> c a -> d+selectOr fb f key lib = maybe fb f (lookup key lib)++class FromList m map k a where+  fromList :: (Monad m) => [(k, a)] -> m (map k a)++instance (Hashable k, Eq k, MonadError e m, NameCollision e a) => FromList m HashMap k a where+  fromList = mergeNoDuplicates HM.fromList
+ src/Data/Mergeable/MergeMap.hs view
@@ -0,0 +1,117 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveLift #-}+{-# LANGUAGE DeriveTraversable #-}+{-# LANGUAGE DerivingStrategies #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE NoImplicitPrelude #-}++module Data.Mergeable.MergeMap+  ( MergeMap,+    toNonEmpty,+    partition,+  )+where++import Control.Monad.Except (MonadError (..))+import qualified Data.List as L+import qualified Data.List.NonEmpty as NE (partition)+import qualified Data.List.NonEmpty as NM+import Data.Mergeable.Internal.Merge+  ( Merge (..),+    recursiveMerge,+  )+import Data.Mergeable.IsMap (FromList (..), IsMap (..))+import Language.Haskell.TH.Syntax (Lift (..))+import Relude hiding (fromList)++partition :: (a -> Bool) -> MergeMap dups k a -> (Maybe (MergeMap dups k a), Maybe (MergeMap dups k a))+partition f (MergeMap xs) =+  case NE.partition (f . snd) xs of+    ([], _) -> (Nothing, Just (MergeMap xs))+    (_, []) -> (Just (MergeMap xs), Nothing)+    (a : as, b : bs) -> (Just (MergeMap (a :| as)), Just (MergeMap (b :| bs)))++newtype MergeMap (dups :: Bool) k a = MergeMap+  { unpack :: NonEmpty (k, a)+  }+  deriving+    ( Show,+      Eq,+      Functor,+      Foldable,+      Traversable+    )++instance (Lift a, Lift k) => Lift (MergeMap dups k a) where+  lift (MergeMap (x :| xs)) = [|MergeMap (x :| xs)|]++#if MIN_VERSION_template_haskell(2,16,0)+  liftTyped (MergeMap (x :| xs))  = [|| MergeMap (x :| xs) ||]+#endif++instance+  (Hashable k, Eq k) =>+  IsMap k (MergeMap dups k)+  where+  unsafeFromList (x : xs) = MergeMap (x :| xs)+  unsafeFromList [] = error "empty selection sets are not supported."+  singleton k x = MergeMap ((k, x) :| [])+  lookup key (MergeMap (x :| xs)) = L.lookup key (x : xs)++instance+  ( Monad m,+    Eq a,+    Merge m a,+    Hashable k,+    Eq k+  ) =>+  Merge m (MergeMap 'False k a)+  where+  merge (MergeMap x) (MergeMap y) = resolveMergeable (x <> y)++instance Monad m => Merge m (MergeMap 'True k a) where+  merge (MergeMap x) (MergeMap y) = pure $ MergeMap $ x <> y++resolveMergeable ::+  ( Monad m,+    Eq a,+    Merge m a,+    Hashable k,+    Eq k+  ) =>+  NonEmpty (k, a) ->+  m (MergeMap dups k a)+resolveMergeable (x :| xs) = recursiveMerge (MergeMap . NM.fromList) (x : xs)++toNonEmpty :: (IsString e, MonadError e f) => [a] -> f (NonEmpty a)+toNonEmpty [] = throwError $ fromString "empty selection sets are not supported."+toNonEmpty (x : xs) = pure (x :| xs)++instance+  ( Hashable k,+    Eq k,+    Eq a,+    IsString e,+    MonadError e m,+    Merge m a+  ) =>+  FromList m (MergeMap 'False) k a+  where+  fromList = resolveMergeable <=< toNonEmpty++instance+  ( IsString e,+    MonadError e m+  ) =>+  FromList m (MergeMap 'True) k a+  where+  fromList = fmap MergeMap . toNonEmpty
+ src/Data/Mergeable/OrdMap.hs view
@@ -0,0 +1,88 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveTraversable #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE NoImplicitPrelude #-}++module Data.Mergeable.OrdMap+  ( OrdMap (..),+  )+where++import Control.Monad.Except (MonadError)+import qualified Data.HashMap.Lazy as HM+import Data.Mergeable.Internal.Merge (Merge (..))+import Data.Mergeable.Internal.NameCollision (NameCollision (..))+import Data.Mergeable.Internal.Resolution+  ( Indexed (..),+    indexed,+  )+import Data.Mergeable.IsMap+  ( FromList (..),+    IsMap (..),+  )+import Data.Morpheus.Ext.Empty (Empty (..))+import Language.Haskell.TH.Syntax (Lift (..))+import Relude hiding (fromList)++-- OrdMap+newtype OrdMap k a = OrdMap+  { mapEntries :: HashMap k (Indexed k a)+  }+  deriving+    ( Show,+      Eq,+      Functor,+      Traversable,+      Empty+    )++instance (Lift a, Lift k, Eq k, Hashable k) => Lift (OrdMap k a) where+  lift (OrdMap x) = [|OrdMap (HM.fromList ls)|]+    where+      ls = HM.toList x++#if MIN_VERSION_template_haskell(2,16,0)+  liftTyped (OrdMap x) = [||OrdMap (HM.fromList ls)||]+    where+      ls = HM.toList x+#endif++instance (Eq k, Hashable k) => Foldable (OrdMap k) where+  foldMap f = foldMap f . getElements++getElements :: (Eq k, Hashable k) => OrdMap k b -> [b]+getElements = fmap indexedValue . sortOn index . toList . mapEntries++instance (Eq k, Hashable k) => IsMap k (OrdMap k) where+  unsafeFromList = OrdMap . HM.fromList . fmap withKey . indexed+    where+      withKey idx = (indexedKey idx, idx)+  singleton k x = OrdMap $ HM.singleton k (Indexed 0 k x)+  lookup key OrdMap {mapEntries} = indexedValue <$> lookup key mapEntries++instance (NameCollision e a, Eq k, Hashable k, Monad m, MonadError e m) => Merge m (OrdMap k a) where+  merge (OrdMap x) (OrdMap y) = OrdMap <$> merge x (fmap (shiftIndexes (HM.size x)) y)++shiftIndexes :: Int -> Indexed k a -> Indexed k a+shiftIndexes n Indexed {..} = Indexed {index = index + n, ..}++instance+  ( Hashable k,+    Eq k,+    NameCollision e a,+    MonadError e m+  ) =>+  FromList m OrdMap k a+  where+  fromList = fmap OrdMap . fromList . map xyz . indexed+    where+      xyz x = (indexedKey x, x)
+ src/Data/Mergeable/SafeHashMap.hs view
@@ -0,0 +1,59 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveTraversable #-}+{-# LANGUAGE DerivingStrategies #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE NoImplicitPrelude #-}++module Data.Mergeable.SafeHashMap+  ( SafeHashMap,+    toHashMap,+  )+where++import Control.Monad.Except (MonadError)+import qualified Data.HashMap.Lazy as HM+import Data.Mergeable+  ( Merge (..),+    NameCollision (..),+  )+import Data.Mergeable.IsMap (IsMap)+import Data.Morpheus.Ext.Empty (Empty)+import Language.Haskell.TH.Syntax (Lift (..))+import Relude++newtype SafeHashMap k a = SafeHashMap+  { unpackSafeHashMap :: HashMap k a+  }+  deriving+    ( Show,+      Eq,+      Functor,+      Foldable,+      Traversable+    )+  deriving newtype+    ( IsMap k,+      Empty+    )++toHashMap :: SafeHashMap k a -> HashMap k a+toHashMap = unpackSafeHashMap++instance (Lift a, Lift k, Eq k, Hashable k) => Lift (SafeHashMap k a) where+  lift (SafeHashMap x) = let ls = HM.toList x in [|SafeHashMap (HM.fromList ls)|]++#if MIN_VERSION_template_haskell(2,16,0)+  liftTyped (SafeHashMap x) = let ls = HM.toList x in [||SafeHashMap (HM.fromList ls)||]+#endif++instance (NameCollision e a, Monad m, Hashable k, Eq k, MonadError e m) => Merge m (SafeHashMap k a) where+  merge (SafeHashMap x) (SafeHashMap y) = SafeHashMap <$> merge x y
src/Data/Morpheus/Core.hs view
@@ -30,11 +30,9 @@   ( ByteString,   ) import Data.Morpheus.Ext.Result-  ( Eventless,-  )-import Data.Morpheus.Ext.SemigroupM-  ( (<:>),+  ( GQLResult,   )+import Data.Morpheus.Internal.Utils ((<:>)) import Data.Morpheus.Parser   ( parseRequest,     parseRequestWith,@@ -60,5 +58,5 @@   ) import Relude hiding (ByteString) -parseFullSchema :: ByteString -> Eventless (Schema VALID)+parseFullSchema :: ByteString -> GQLResult (Schema VALID) parseFullSchema = parseSchema >=> (internalSchema <:>)
src/Data/Morpheus/Error.hs view
@@ -3,21 +3,15 @@ module Data.Morpheus.Error   ( errorMessage,     globalErrorMessage,-    gqlWarnings,     renderGQLErrors,     deprecatedField,     subfieldsNotSelected,     NameCollision (..),+    gqlWarnings,   ) where -import Data.Morpheus.Error.NameCollision (NameCollision (..))+import Data.Mergeable import Data.Morpheus.Error.Selection-  ( subfieldsNotSelected,-  ) import Data.Morpheus.Error.Utils import Data.Morpheus.Error.Warning-  ( deprecatedField,-    gqlWarnings,-    renderGQLErrors,-  )
src/Data/Morpheus/Error/Document/Interface.hs view
@@ -1,33 +1,36 @@+{-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Error.Document.Interface   ( unknownInterface,-    PartialImplements (..),     ImplementsError (..),-    Place (..),+    partialImplements,   ) where -import Data.Maybe (Maybe (..))-import Data.Morpheus.Types.Internal.AST.Base-  ( FieldName (..),-    TypeName (..),-    ValidationError,-    msgValidation,+import Data.Morpheus.Types.Internal.AST.Error+  ( GQLError,+    msg,   )+import Data.Morpheus.Types.Internal.AST.Name+  ( TypeName,+  ) import Data.Morpheus.Types.Internal.AST.Type (TypeRef) import Data.Morpheus.Types.Internal.Validation.SchemaValidator   ( Field (..),-    Interface (..),+    InterfaceName (..),+    ON_INTERFACE,+    TypeEntity (..),     renderField,   )-import Data.Semigroup ((<>))+import Relude -unknownInterface :: TypeName -> ValidationError-unknownInterface name = "Unknown Interface " <> msgValidation name <> "."+unknownInterface :: TypeName -> GQLError+unknownInterface name = "Unknown Interface " <> msg name <> "."  data ImplementsError   = UnexpectedType@@ -36,55 +39,27 @@       }   | Missing -data Place = Place-  { fieldname :: TypeName,-    typename :: FieldName,-    fieldArg :: Maybe (FieldName, TypeName)-  }--class PartialImplements ctx where-  partialImplements :: ctx -> ImplementsError -> ValidationError--instance PartialImplements (Interface, FieldName) where-  partialImplements (Interface interfaceName typename, fieldname) errorType =-    "Interface field "-      <> renderField interfaceName fieldname Nothing-      <> detailedMessage errorType-    where-      detailedMessage UnexpectedType {expectedType, foundType} =-        " expects type "-          <> msgValidation expectedType-          <> " but "-          <> renderField typename fieldname Nothing-          <> " is type "-          <> msgValidation foundType-          <> "."-      detailedMessage Missing =-        " expected but "-          <> msgValidation typename-          <> " does not provide it."+partialImplements :: Field ON_INTERFACE -> ImplementsError -> GQLError+partialImplements (Field fieldName argName (TypeEntity (OnInterface interfaceName) typename)) errorType =+  "Interface field " <> maybe "" (const "argument ") argName+    <> renderField interfaceName fieldName argName+    <> detailedMessageGen+      (renderField typename fieldName argName)+      (maybe (msg typename) (const $ renderField typename fieldName Nothing) argName)+      errorType  -- Interface field TestInterface.name expected but User does not provide it. -- Interface field TestInterface.name expects type String! but User.name is type Int!.--instance PartialImplements (Interface, Field) where-  partialImplements (Interface interfaceName typename, Field fieldname argName) errorType =-    "Interface field argument "-      <> renderField interfaceName fieldname (Just argName)-      <> detailedMessage errorType-    where-      detailedMessage UnexpectedType {expectedType, foundType} =-        " expects type"-          <> msgValidation expectedType-          <> " but "-          <> renderField typename fieldname (Just argName)-          <> " is type "-          <> msgValidation foundType-          <> "."-      detailedMessage Missing =-        " expected but "-          <> renderField typename fieldname Nothing-          <> " does not provide it."- -- Interface field argument TestInterface.name(id:) expected but User.name does not provide it. -- Interface field argument TestInterface.name(id:) expects type ID but User.name(id:) is type String.++detailedMessageGen :: GQLError -> GQLError -> ImplementsError -> GQLError+detailedMessageGen pl1 _ UnexpectedType {expectedType, foundType} =+  " expects type "+    <> msg expectedType+    <> " but "+    <> pl1+    <> " is type "+    <> msg foundType+    <> "."+detailedMessageGen _ pl2 Missing = " expected but " <> pl2 <> " does not provide it."
src/Data/Morpheus/Error/Fragment.hs view
@@ -8,16 +8,21 @@ where  -- MORPHEUS-import Data.Morpheus.Error.Utils (validationErrorMessage) import Data.Morpheus.Types.Internal.AST.Base-  ( FieldName,-    Position,+  ( Position,     Ref (..),-    TypeName,-    ValidationError (..),+  )+import Data.Morpheus.Types.Internal.AST.Error+  ( GQLError,+    at,+    atPositions,+    manyMsg,     msg,-    msgSepBy,   )+import Data.Morpheus.Types.Internal.AST.Name+  ( FragmentName,+    TypeName,+  ) import Relude  {-@@ -32,30 +37,28 @@     {...H} -> "Unknown fragment \"H\"." -} -cannotSpreadWithinItself :: NonEmpty (Ref FieldName) -> ValidationError-cannotSpreadWithinItself (fr :| frs) = ValidationError text (fmap refPosition (fr : frs))-  where-    text =-      "Cannot spread fragment "-        <> msg (refName fr)-        <> " within itself via "-        <> msgSepBy ", " (fmap refName (fr : frs))-        <> "."+cannotSpreadWithinItself :: NonEmpty (Ref FragmentName) -> GQLError+cannotSpreadWithinItself (fr :| frs) =+  ( "Cannot spread fragment "+      <> msg (refName fr)+      <> " within itself via "+      <> manyMsg (refName <$> (fr : frs))+      <> "."+  )+    `atPositions` map refPosition (fr : frs)  -- Fragment type mismatch -> "Fragment \"H\" cannot be spread here as objects of type \"Hobby\" can never be of type \"Experience\"."-cannotBeSpreadOnType :: Maybe FieldName -> TypeName -> Position -> [TypeName] -> ValidationError+cannotBeSpreadOnType :: Maybe FragmentName -> TypeName -> Position -> [TypeName] -> GQLError cannotBeSpreadOnType key fragmentType position typeMembers =-  validationErrorMessage-    (Just position)-    text+  ( "Fragment "+      <> getName key+      <> "cannot be spread here as objects of type "+      <> manyMsg typeMembers+      <> " can never be of type "+      <> msg fragmentType+      <> "."+  )+    `at` position   where-    text =-      "Fragment "-        <> getName key-        <> "cannot be spread here as objects of type "-        <> msgSepBy ", " typeMembers-        <> " can never be of type "-        <> msg fragmentType-        <> "."     getName (Just x) = msg x <> " "     getName Nothing = ""
src/Data/Morpheus/Error/Input.hs view
@@ -7,19 +7,19 @@ where  import Data.Morpheus.Types.Internal.AST-  ( TypeRef (..),-    ValidationError,+  ( GQLError,+    TypeRef (..),     Value,-    msgValidation,+    msg,   ) import Data.Semigroup ((<>)) -typeViolation :: TypeRef -> Value s -> ValidationError+typeViolation :: TypeRef -> Value s -> GQLError typeViolation expected found =   "Expected type "-    <> msgValidation expected+    <> msg expected     <> " found "-    <> msgValidation found+    <> msg found     <> "."  {-
− src/Data/Morpheus/Error/NameCollision.hs
@@ -1,18 +0,0 @@-{-# LANGUAGE NoImplicitPrelude #-}--module Data.Morpheus.Error.NameCollision-  ( NameCollision (..),-  )-where--import Data.Morpheus.Ext.Map (Indexed (..))-import Data.Morpheus.Types.Internal.AST.Base-  ( ValidationError,-  )-import Relude--class NameCollision a where-  nameCollision :: a -> ValidationError--instance NameCollision a => NameCollision (Indexed k a) where-  nameCollision = nameCollision . indexedValue
src/Data/Morpheus/Error/Operation.hs view
@@ -9,17 +9,16 @@  import Data.Morpheus.Types.Internal.AST.Base   ( Position,-    ValidationError (..),   )+import Data.Morpheus.Types.Internal.AST.Error+  ( GQLError,+    at,+  ) -mutationIsNotDefined :: Position -> ValidationError+mutationIsNotDefined :: Position -> GQLError mutationIsNotDefined position =-  ValidationError-    "Schema is not configured for mutations."-    [position]+  "Schema is not configured for mutations." `at` position -subscriptionIsNotDefined :: Position -> ValidationError+subscriptionIsNotDefined :: Position -> GQLError subscriptionIsNotDefined position =-  ValidationError-    "Schema is not configured for subscriptions."-    [position]+  "Schema is not configured for subscriptions." `at` position
src/Data/Morpheus/Error/Selection.hs view
@@ -11,19 +11,20 @@  import Data.Morpheus.Types.Internal.AST   ( FieldName,+    GQLError,     Position,     Ref (..),     TypeDefinition (..),     TypeName,     VALID,-    ValidationError (..),+    at,     msg,   ) import Data.Semigroup ((<>))  -- GQL: "Field \"default\" must not have a selection since type \"String!\" has no subfields."-hasNoSubfields :: Ref FieldName -> TypeDefinition s VALID -> ValidationError-hasNoSubfields (Ref selectionName position) TypeDefinition {typeName} = ValidationError text [position]+hasNoSubfields :: Ref FieldName -> TypeDefinition s VALID -> GQLError+hasNoSubfields (Ref selectionName position) TypeDefinition {typeName} = text `at` position   where     text =       "Field "@@ -32,8 +33,8 @@         <> msg typeName         <> " has no subfields." -unknownSelectionField :: TypeName -> Ref FieldName -> ValidationError-unknownSelectionField typeName Ref {refName, refPosition} = ValidationError text [refPosition]+unknownSelectionField :: TypeName -> Ref FieldName -> GQLError+unknownSelectionField typeName Ref {refName, refPosition} = text `at` refPosition   where     text =       "Cannot query field " <> msg refName@@ -42,8 +43,8 @@         <> "."  -- GQL:: Field \"hobby\" of type \"Hobby!\" must have a selection of subfields. Did you mean \"hobby { ... }\"?-subfieldsNotSelected :: FieldName -> TypeName -> Position -> ValidationError-subfieldsNotSelected fieldName typeName position = ValidationError text [position]+subfieldsNotSelected :: FieldName -> TypeName -> Position -> GQLError+subfieldsNotSelected fieldName typeName position = text `at` position   where     text =       "Field " <> msg fieldName <> " of type "
src/Data/Morpheus/Error/Utils.hs view
@@ -1,27 +1,25 @@-{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Error.Utils   ( errorMessage,     globalErrorMessage,-    validationErrorMessage,   ) where  import Data.Morpheus.Types.Internal.AST.Base-  ( GQLError (..),-    GQLErrors,+  ( Position (..),+  )+import Data.Morpheus.Types.Internal.AST.Error+  ( GQLError,     Message,-    Position (..),-    ValidationError (..),+    at,+    msg,   )-import Relude hiding (ByteString) -validationErrorMessage :: Maybe Position -> Message -> ValidationError-validationErrorMessage pos message = ValidationError message (maybeToList pos)--errorMessage :: Position -> Message -> GQLErrors-errorMessage position message = [GQLError {message, locations = [position]}]+{-# DEPRECATED errorMessage "\"my error\" `at` position" #-}+errorMessage :: Position -> Message -> [GQLError]+errorMessage position message = [msg message `at` position] -globalErrorMessage :: Message -> GQLErrors-globalErrorMessage message = [GQLError {message, locations = []}]+{-# DEPRECATED globalErrorMessage "use validation errors" #-}+globalErrorMessage :: Message -> [GQLError]+globalErrorMessage message = [msg message]
src/Data/Morpheus/Error/Variable.hs view
@@ -8,40 +8,39 @@   ) where -import Data.Morpheus.Error.Utils (validationErrorMessage) import Data.Morpheus.Types.Internal.AST   ( FieldName,+    GQLError,     Ref (..),     TypeRef,-    ValidationError,     Variable (..),+    at,     msg,   ) import Relude  -- query M ( $v : String ) { a(p:$v) } -> "Variable \"$v\" of type \"String\" used in position expecting type \"LANGUAGE\"."-incompatibleVariableType :: Ref FieldName -> Variable s -> TypeRef -> ValidationError+incompatibleVariableType :: Ref FieldName -> Variable s -> TypeRef -> GQLError incompatibleVariableType   (Ref variableName argPosition)   Variable {variableType}   argumentType =-    validationErrorMessage (Just argPosition) text-    where-      text =-        "Variable "-          <> msg ("$" <> variableName)-          <> " of type "-          <> msg variableType-          <> " used in position expecting type "-          <> msg argumentType-          <> "."+    ( "Variable "+        <> msg ("$" <> variableName)+        <> " of type "+        <> msg variableType+        <> " used in position expecting type "+        <> msg argumentType+        <> "."+    )+      `at` argPosition -uninitializedVariable :: Variable s -> ValidationError+uninitializedVariable :: Variable s -> GQLError uninitializedVariable Variable {variableName, variableType, variablePosition} =-  validationErrorMessage-    (Just variablePosition)-    $ "Variable "+  ( "Variable "       <> msg ("$" <> variableName)       <> " of required type "       <> msg variableType       <> " was not provided."+  )+    `at` variablePosition
src/Data/Morpheus/Error/Warning.hs view
@@ -12,41 +12,46 @@  import Data.Aeson (encode) import Data.ByteString.Lazy.Char8 (unpack)-import Data.Morpheus.Error.Utils (errorMessage) import Data.Morpheus.Types.Internal.AST.Base   ( Description,-    FieldName,-    GQLErrors,     Ref (..),+  )+import Data.Morpheus.Types.Internal.AST.Error+  ( GQLError,+    GQLErrors,+    at,     msg,+    msg,   )-import Language.Haskell.TH (Q, reportWarning)+import Data.Morpheus.Types.Internal.AST.Name+  ( FieldName,+  )+import Language.Haskell.TH import Relude  renderGQLErrors :: GQLErrors -> String-renderGQLErrors = unpack . encode+renderGQLErrors = unpack . encode . toList -deprecatedEnum :: FieldName -> Ref FieldName -> Maybe Description -> GQLErrors+-- TODO: implement warnings, is not used+deprecatedEnum :: FieldName -> Ref FieldName -> Maybe Description -> GQLError deprecatedEnum typeName Ref {refPosition, refName} reason =-  errorMessage refPosition $-    "the enum value "-      <> msg typeName-      <> "."-      <> msg refName-      <> " is deprecated."-      <> msg (maybe "" (" " <>) reason)+  "the enum value "+    <> msg typeName+    <> "."+    <> msg refName+    <> " is deprecated."+    <> msg (maybe "" (" " <>) reason) `at` refPosition -deprecatedField :: FieldName -> Ref FieldName -> Maybe Description -> GQLErrors+deprecatedField :: FieldName -> Ref FieldName -> Maybe Description -> GQLError deprecatedField typeName Ref {refPosition, refName} reason =-  errorMessage refPosition $-    "the field "-      <> msg typeName-      <> "."-      <> msg refName-      <> " is deprecated."-      <> msg (maybe "" (" " <>) reason)+  "the field "+    <> msg typeName+    <> "."+    <> msg refName+    <> " is deprecated."+    <> msg (maybe "" (" " <>) reason) `at` refPosition -gqlWarnings :: GQLErrors -> Q ()+gqlWarnings :: [GQLError] -> Q () gqlWarnings [] = pure () gqlWarnings warnings = traverse_ handleWarning warnings   where
− src/Data/Morpheus/Ext/Elems.hs
@@ -1,25 +0,0 @@-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE NoImplicitPrelude #-}--module Data.Morpheus.Ext.Elems-  ( Elems (..),-    size,-  )-where--import qualified Data.HashMap.Lazy as HM-import Instances.TH.Lift ()-import Relude--class Elems a coll | coll -> a where-  elems :: coll -> [a]--instance Elems a (HashMap k a) where-  elems = HM.elems--instance Elems a [a] where-  elems = id--size :: Elems a coll => coll -> Int-size = length . elems
− src/Data/Morpheus/Ext/Failure.hs
@@ -1,21 +0,0 @@-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE PolyKinds #-}-{-# LANGUAGE NoImplicitPrelude #-}--module Data.Morpheus.Ext.Failure-  ( Failure (..),-  )-where--import Relude---- Failure: for custom Morpheus GrapHQL errors-class Applicative f => Failure error (f :: * -> *) where-  failure :: error -> f v--instance Failure error (Either error) where-  failure = Left--instance (Monad m, Failure errors m) => Failure errors (ReaderT ctx m) where-  failure = lift . failure
src/Data/Morpheus/Ext/KeyOf.hs view
@@ -8,7 +8,7 @@   ) where -import Data.Morpheus.Ext.Map+import Data.Mergeable   ( Indexed (..),   ) import Data.Morpheus.Types.Internal.AST.Base
− src/Data/Morpheus/Ext/Map.hs
@@ -1,103 +0,0 @@-{-# LANGUAGE DeriveLift #-}-{-# LANGUAGE DeriveTraversable #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE TupleSections #-}-{-# LANGUAGE NoImplicitPrelude #-}--module Data.Morpheus.Ext.Map-  ( Indexed (..),-    indexed,-    fromListT,-    resolveWith,-    runResolutionT,-    ResolutionT,-  )-where--import qualified Data.HashMap.Lazy as HM-import Language.Haskell.TH.Syntax (Lift)-import Relude--sortedEntries :: [Indexed k a] -> [(k, a)]-sortedEntries = fmap f . sortOn index-  where-    f a = (indexedKey a, indexedValue a)--fromListT :: (Monad m, Eq k, Hashable k) => [(k, a)] -> ResolutionT k a coll m coll-fromListT = traverse resolveDuplicatesM . fromListDuplicates >=> fromNoDuplicatesM--resolveWith ::-  Monad m =>-  (a -> a -> m a) ->-  NonEmpty a ->-  m a-resolveWith f (x :| xs) = foldlM f x xs--data Indexed k a = Indexed-  { index :: Int,-    indexedKey :: k,-    indexedValue :: a-  }-  deriving-    ( Show,-      Eq,-      Functor,-      Traversable,-      Foldable,-      Lift-    )--fromListDuplicates :: (Eq k, Hashable k) => [(k, a)] -> [(k, NonEmpty a)]-fromListDuplicates xs =-  sortedEntries-    $ HM.elems-    $ clusterDuplicates (indexed xs) HM.empty--indexed :: [(k, a)] -> [Indexed k a]-indexed = __indexed 0-  where-    __indexed :: Int -> [(k, a)] -> [Indexed k a]-    __indexed _ [] = []-    __indexed i ((k, x) : xs) = Indexed i k x : __indexed (i + 1) xs--resolveDuplicatesM :: Monad m => (k, NonEmpty a) -> ResolutionT k a coll m (k, a)-resolveDuplicatesM (k, xs) = asks resolveDuplicates >>= lift . fmap (k,) . (xs &)--fromNoDuplicatesM :: Monad m => [(k, a)] -> ResolutionT k a coll m coll-fromNoDuplicatesM xs = asks ((xs &) . fromNoDuplicates)--insertWithList :: (Eq k, Hashable k) => Indexed k (NonEmpty a) -> HashMap k (Indexed k (NonEmpty a)) -> HashMap k (Indexed k (NonEmpty a))-insertWithList (Indexed i1 key value) = HM.alter (Just . updater) key-  where-    updater Nothing = Indexed i1 key value-    updater (Just (Indexed i2 _ x)) = Indexed i2 key (x <> value)--clusterDuplicates :: (Eq k, Hashable k) => [Indexed k a] -> HashMap k (Indexed k (NonEmpty a)) -> HashMap k (Indexed k (NonEmpty a))-clusterDuplicates [] = id-clusterDuplicates xs = flip (foldl' (\coll x -> insertWithList (fmap (:| []) x) coll)) xs--data Resolution k a coll m = Resolution-  { resolveDuplicates :: NonEmpty a -> m a,-    fromNoDuplicates :: [(k, a)] -> coll-  }--runResolutionT ::-  ResolutionT k a coll m b ->-  ([(k, a)] -> coll) ->-  (NonEmpty a -> m a) ->-  m b-runResolutionT (ResolutionT x) fromNoDuplicates resolveDuplicates = runReaderT x Resolution {..}--newtype ResolutionT k a coll m x = ResolutionT-  { _runResolutionT :: ReaderT (Resolution k a coll m) m x-  }-  deriving-    ( Functor,-      Monad,-      Applicative,-      MonadReader (Resolution k a coll m)-    )--instance MonadTrans (ResolutionT k a coll) where-  lift = ResolutionT . lift
− src/Data/Morpheus/Ext/MergeSet.hs
@@ -1,119 +0,0 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE DeriveLift #-}-{-# LANGUAGE DeriveTraversable #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE NoImplicitPrelude #-}--module Data.Morpheus.Ext.MergeSet-  ( MergeSet,-  )-where--import Data.Morpheus.Ext.Elems (Elems (..))-import Data.Morpheus.Ext.Empty (Empty (..))-import Data.Morpheus.Ext.Map-  ( fromListT,-    resolveWith,-    runResolutionT,-  )-import Data.Morpheus.Ext.SemigroupM-  ( SemigroupM (..),-  )-import Data.Morpheus.Internal.Utils-  ( Collection (..),-    Failure (..),-    FromElems (..),-    KeyOf (..),-    Selectable (..),-    toPair,-  )-import Data.Morpheus.Types.Internal.AST.Base-  ( FieldName,-    Ref,-    ValidationErrors,-  )-import Data.Morpheus.Types.Internal.AST.Stage-  ( RAW,-    Stage,-    VALID,-  )-import Language.Haskell.TH.Syntax (Lift (..))-import Relude---- set with mergeable components-newtype MergeSet (dups :: Stage) k a = MergeSet-  { unpack :: [a]-  }-  deriving-    ( Show,-      Eq,-      Functor,-      Foldable,-      Lift,-      Traversable,-      Collection a,-      Elems a,-      Empty-    )--instance (KeyOf k a) => Selectable k a (MergeSet opt k a) where-  selectOr fb f key (MergeSet ls) = maybe fb f (find ((key ==) . keyOf) ls)--instance-  ( KeyOf k a,-    SemigroupM m a,-    Monad m,-    Failure ValidationErrors m,-    Eq a-  ) =>-  SemigroupM m (MergeSet VALID k a)-  where-  mergeM path (MergeSet x) (MergeSet y) = resolveMergable path (x <> y)--resolveMergable ::-  ( KeyOf k a,-    Monad m,-    Eq a,-    SemigroupM m a,-    Failure ValidationErrors m-  ) =>-  [Ref FieldName] ->-  [a] ->-  m (MergeSet dups k a)-resolveMergable path xs = runResolutionT (fromListT (toPair <$> xs)) (MergeSet . fmap snd) (resolveWith (resolveConflict path))--instance-  ( KeyOf k a,-    SemigroupM m a,-    Monad m,-    Failure ValidationErrors m,-    Eq a-  ) =>-  FromElems m a (MergeSet VALID k a)-  where-  fromElems = resolveMergable []--instance Applicative m => SemigroupM m (MergeSet RAW k a) where-  mergeM _ (MergeSet x) (MergeSet y) = pure $ MergeSet $ x <> y--instance Applicative m => FromElems m a (MergeSet RAW k a) where-  fromElems = pure . MergeSet--resolveConflict ::-  ( Monad m,-    Eq a,-    KeyOf k a,-    SemigroupM m a,-    Failure ValidationErrors m-  ) =>-  [Ref FieldName] ->-  a ->-  a ->-  m a-resolveConflict path oldValue newValue-  | oldValue == newValue = pure oldValue-  | otherwise = mergeM path oldValue newValue
− src/Data/Morpheus/Ext/OrdMap.hs
@@ -1,93 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE DeriveTraversable #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE NoImplicitPrelude #-}--module Data.Morpheus.Ext.OrdMap-  ( OrdMap (..),-    unsafeFromList,-  )-where--import qualified Data.HashMap.Lazy as HM-import Data.Morpheus.Error.NameCollision (NameCollision (..))-import Data.Morpheus.Ext.Elems (Elems (..))-import Data.Morpheus.Ext.Empty (Empty (..))-import Data.Morpheus.Ext.Map-  ( Indexed (..),-    indexed,-  )-import Data.Morpheus.Ext.SemigroupM-  ( SemigroupM (..),-  )-import Data.Morpheus.Internal.Utils-  ( Collection (..),-    Failure,-    FromElems (..),-    KeyOf (..),-    Selectable (..),-    toPair,-  )-import Data.Morpheus.Types.Internal.AST.Base (ValidationErrors)-import Language.Haskell.TH.Syntax (Lift (..))-import Relude---- OrdMap-newtype OrdMap k a = OrdMap-  { mapEntries :: HashMap k (Indexed k a)-  }-  deriving-    ( Show,-      Eq,-      Functor,-      Traversable,-      Empty-    )--instance (Lift a, Lift k, Eq k, Hashable k) => Lift (OrdMap k a) where-  lift (OrdMap x) = [|OrdMap (HM.fromList ls)|]-    where-      ls = HM.toList x--#if MIN_VERSION_template_haskell(2,16,0)-  liftTyped (OrdMap x) = [||OrdMap (HM.fromList ls)||]-    where-      ls = HM.toList x-#endif--instance (Eq k, Hashable k) => Foldable (OrdMap k) where-  foldMap f = foldMap f . getElements--getElements :: (Eq k, Hashable k) => OrdMap k b -> [b]-getElements = fmap indexedValue . sortOn index . toList . mapEntries--instance (KeyOf k a, Hashable k) => Collection a (OrdMap k a) where-  singleton x = OrdMap $ HM.singleton (keyOf x) (Indexed 0 (keyOf x) x)--instance (Eq k, Hashable k) => Selectable k a (OrdMap k a) where-  selectOr fb f key OrdMap {mapEntries} = maybe fb (f . indexedValue) (HM.lookup key mapEntries)--instance (NameCollision a, Monad m, KeyOf k a, Failure ValidationErrors m) => SemigroupM m (OrdMap k a) where-  mergeM ref (OrdMap x) (OrdMap y) = OrdMap <$> mergeM ref x y--instance (NameCollision a, Monad m, Failure ValidationErrors m, KeyOf k a, Hashable k) => FromElems m a (OrdMap k a) where-  fromElems values = OrdMap <$> fromElems (indexed (toPair <$> values))--instance (Eq k, Hashable k) => Elems a (OrdMap k a) where-  elems = getElements--unsafeFromList ::-  (Hashable k, Eq k) =>-  [(k, a)] ->-  OrdMap k a-unsafeFromList = OrdMap . HM.fromList . fmap withKey . indexed-  where-    withKey idx = (indexedKey idx, idx)
src/Data/Morpheus/Ext/Result.hs view
@@ -4,130 +4,133 @@ {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE PolyKinds #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TupleSections #-} {-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Ext.Result-  ( Eventless,-    Result (..),-    Failure (..),+  ( Result (..),     ResultT (..),-    unpackEvents,     mapEvent,     cleanEvents,     PushEvents (..),     resultOr,     sortErrors,+    toEither,+    GQLResult,   ) where -import Data.Morpheus.Internal.Utils-  ( Failure (..),-  )-import Data.Morpheus.Types.Internal.AST.Base+import Control.Monad.Except (MonadError (..))+import qualified Data.List.NonEmpty as NE+import Data.Morpheus.Types.Internal.AST.Error   ( GQLError (..),-    GQLErrors,-    ValidationError (..),-    toGQLError,+    GQLError,   )+import Data.Text.Lazy.Builder () import Relude -type Eventless = Result ()+type GQLResult = Result GQLError  -- EVENTS class PushEvents e m where   pushEvents :: [e] -> m () -unpackEvents :: Result event a -> [event]-unpackEvents Success {events} = events-unpackEvents _ = []- -- -- Result -- ---data Result events a-  = Success {result :: a, warnings :: GQLErrors, events :: [events]}-  | Failure {errors :: GQLErrors}+data Result err a+  = Success {result :: a, warnings :: [err]}+  | Failure {errors :: NonEmpty err}   deriving (Functor) -instance Applicative (Result e) where-  pure x = Success x [] []-  Success f w1 e1 <*> Success x w2 e2 = Success (f x) (w1 <> w2) (e1 <> e2)+instance Applicative (Result er) where+  pure x = Success x []+  Success f w1 <*> Success x w2 = Success (f x) (w1 <> w2)   Failure e1 <*> Failure e2 = Failure (e1 <> e2)-  Failure e <*> Success _ w _ = Failure (e <> w)-  Success _ w _ <*> Failure e = Failure (e <> w)+  Failure (e :| es) <*> Success _ w = Failure (e :| es <> w)+  Success _ w <*> Failure (e :| es) = Failure (e :| es <> w) -instance Monad (Result e) where+instance Monad (Result er) where   return = pure-  Success v w1 e1 >>= fm = case fm v of-    (Success x w2 e2) -> Success x (w1 <> w2) (e1 <> e2)-    (Failure e) -> Failure (e <> w1)+  Success v w1 >>= fm = case fm v of+    (Success x w2) -> Success x (w1 <> w2)+    (Failure (e :| es)) -> Failure (e :| es <> w1)   Failure e >>= _ = Failure e -instance Failure [GQLError] (Result ev) where-  failure = Failure+instance Bifunctor Result where+  bimap f g Success {..} = Success {warnings = f <$> warnings, result = g result, ..}+  bimap f _ Failure {..} = Failure (f <$> errors) -instance PushEvents events (Result events) where-  pushEvents events = Success {result = (), warnings = [], events}+instance MonadError er (Result er) where+  throwError = Failure . pure+  catchError (Failure (x :| _)) f = f x+  catchError x _ = x -instance Failure [ValidationError] (Result ev) where-  failure = failure . fmap toGQLError+instance IsString err => MonadFail (Result err) where+  fail = Failure . pure . fromString -resultOr :: (GQLErrors -> a') -> (a -> a') -> Result e a -> a'-resultOr _ f (Success x _ _) = f x-resultOr f _ (Failure e) = f e+resultOr :: (NonEmpty err -> a') -> (a -> a') -> Result err a -> a'+resultOr _ f Success {result} = f result+resultOr f _ Failure {errors} = f errors -sortErrors :: Result e a -> Result e a-sortErrors (Failure errors) = Failure (sortOn locations errors)+sortErrors :: Result GQLError a -> Result GQLError a+sortErrors (Failure errors) = Failure (NE.sort errors) sortErrors x = x  -- ResultT-newtype ResultT event (m :: * -> *) a = ResultT-  { runResultT :: m (Result event a)+newtype ResultT event (m :: Type -> Type) a = ResultT+  { runResultT :: m (Result GQLError ([event], a))   }   deriving (Functor)  instance Applicative m => Applicative (ResultT event m) where-  pure = ResultT . pure . pure-  ResultT app1 <*> ResultT app2 = ResultT $ liftA2 (<*>) app1 app2+  pure = ResultT . pure . pure . ([],)+  ResultT app1 <*> ResultT app2 = ResultT $ liftA2 (<*>) (fx <$> app1) app2+    where+      fx :: Monad f => f ([event], a -> b) -> f (([event], a) -> ([event], b))+      fx x = do+        (e', f) <- x+        pure $ \(e, a) -> (e <> e', f a)  instance Monad m => Monad (ResultT event m) where   return = pure   (ResultT m1) >>= mFunc = ResultT $ do-    result1 <- m1-    case result1 of+    result <- m1+    case result of       Failure errors -> pure $ Failure errors-      Success value1 w1 e1 -> do-        result2 <- runResultT (mFunc value1)-        case result2 of-          Failure errors -> pure $ Failure (errors <> w1)-          Success v2 w2 e2 -> pure $ Success v2 (w1 <> w2) (e1 <> e2)+      Success (events, value) w1 -> do+        result' <- runResultT (mFunc value)+        case result' of+          Failure (e :| es) -> pure $ Failure (e :| es <> w1)+          Success (events', value') w2 -> pure $ Success (events <> events', value') (w1 <> w2)  instance MonadTrans (ResultT event) where-  lift = ResultT . fmap pure+  lift = ResultT . fmap (pure . ([],)) -instance Monad m => Failure GQLErrors (ResultT event m) where-  failure = ResultT . pure . failure+instance Monad m => MonadError GQLError (ResultT event m) where+  throwError = ResultT . pure . throwError+  catchError (ResultT mx) f = ResultT (mx >>= catchResultError)+    where+      catchResultError (Failure (x :| _)) = runResultT (f x)+      catchResultError x = pure x  instance Applicative m => PushEvents event (ResultT event m) where-  pushEvents = ResultT . pure . pushEvents+  pushEvents x = ResultT $ pure $ pure (x, ())  cleanEvents ::   Functor m =>   ResultT e m a ->   ResultT e' m a-cleanEvents resT = ResultT $ replace <$> runResultT resT-  where-    replace (Success v w _) = Success v w []-    replace (Failure e) = Failure e+cleanEvents resT = ResultT $ fmap (first (const [])) <$> runResultT resT  mapEvent ::   Monad m =>   (e -> e') ->   ResultT e m value ->   ResultT e' m value-mapEvent func (ResultT ma) = ResultT $ mapEv <$> ma-  where-    mapEv Success {result, warnings, events} =-      Success {result, warnings, events = fmap func events}-    mapEv (Failure err) = Failure err+mapEvent func (ResultT ma) = ResultT $ fmap (first (map func)) <$> ma++toEither :: Result err b -> Either (NonEmpty err) b+toEither = resultOr Left Right
− src/Data/Morpheus/Ext/SafeHashMap.hs
@@ -1,83 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE DeriveTraversable #-}-{-# LANGUAGE DerivingStrategies #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE StandaloneDeriving #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE NoImplicitPrelude #-}--module Data.Morpheus.Ext.SafeHashMap-  ( SafeHashMap,-    unsafeFromList,-    insert,-  )-where--import qualified Data.HashMap.Lazy as HM-import Data.Morpheus.Error.NameCollision (NameCollision (..))-import Data.Morpheus.Ext.Elems (Elems)-import Data.Morpheus.Ext.Empty (Empty)-import Data.Morpheus.Ext.SemigroupM-  ( (<:>),-    SemigroupM (..),-  )-import Data.Morpheus.Internal.Utils-  ( Collection (..),-    Failure (..),-    FromElems (..),-    KeyOf (..),-    Selectable (..),-  )-import Data.Morpheus.Types.Internal.AST.Base (ValidationErrors)-import Language.Haskell.TH.Syntax (Lift (..))-import Relude--newtype SafeHashMap k a = SafeHashMap-  { unpackSafeHashMap :: HashMap k a-  }-  deriving-    ( Show,-      Eq,-      Functor,-      Foldable,-      Traversable-    )-  deriving newtype-    ( Collection a,-      Selectable k a,-      Elems a,-      Empty-    )--instance (Lift a, Lift k, Eq k, Hashable k) => Lift (SafeHashMap k a) where-  lift (SafeHashMap x) = let ls = HM.toList x in [|SafeHashMap (HM.fromList ls)|]--#if MIN_VERSION_template_haskell(2,16,0)-  liftTyped (SafeHashMap x) = let ls = HM.toList x in [||SafeHashMap (HM.fromList ls)||]-#endif--instance (NameCollision a, Monad m, KeyOf k a, Failure ValidationErrors m) => SemigroupM m (SafeHashMap k a) where-  mergeM ref (SafeHashMap x) (SafeHashMap y) = SafeHashMap <$> mergeM ref x y--instance (NameCollision a, Failure ValidationErrors m, Monad m, KeyOf k a, Hashable k) => FromElems m a (SafeHashMap k a) where-  fromElems = fmap SafeHashMap . fromElems--unsafeFromList :: (Eq k, Hashable k) => [(k, a)] -> SafeHashMap k a-unsafeFromList = SafeHashMap . HM.fromList--insert ::-  ( NameCollision a,-    KeyOf k a,-    Monad m,-    Failure ValidationErrors m-  ) =>-  a ->-  SafeHashMap k a ->-  m (SafeHashMap k a)-insert x = (<:> singleton x)
− src/Data/Morpheus/Ext/Selectable.hs
@@ -1,29 +0,0 @@-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE NoImplicitPrelude #-}--module Data.Morpheus.Ext.Selectable-  ( Selectable (..),-    selectBy,-  )-where--import qualified Data.HashMap.Lazy as HM-import Data.Morpheus.Ext.Failure (Failure (..))-import Data.Morpheus.Ext.KeyOf (KeyOf (..))-import Relude--class Selectable k a c | c -> a where-  selectOr :: d -> (a -> d) -> k -> c -> d--  member :: k -> c -> Bool-  member = selectOr False (const True)--instance KeyOf k a => Selectable k a [a] where-  selectOr fb f key lib = maybe fb f (find ((key ==) . keyOf) lib)--instance (Eq k, Hashable k) => Selectable k a (HashMap k a) where-  selectOr fb f key lib = maybe fb f (HM.lookup key lib)--selectBy :: (Failure e m, Selectable k a c, Monad m) => e -> k -> c -> m a-selectBy err = selectOr (failure err) pure
− src/Data/Morpheus/Ext/SemigroupM.hs
@@ -1,83 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE NoImplicitPrelude #-}--module Data.Morpheus.Ext.SemigroupM-  ( SemigroupM (..),-    (<:>),-    concatTraverse,-    join,-  )-where--import qualified Data.HashMap.Lazy as HM-import Data.HashMap.Lazy (HashMap)-import Data.Morpheus.Error.NameCollision (NameCollision)-import Data.Morpheus.Ext.Empty (Empty (..))-import Data.Morpheus.Ext.KeyOf (KeyOf (..))-import Data.Morpheus.Ext.Map-  ( fromListT,-    runResolutionT,-  )-import Data.Morpheus.Internal.Utils-  ( Elems (..),-    Failure,-    failOnDuplicates,-  )-import Data.Morpheus.Types.Internal.AST.Base-  ( FieldName,-    Ref,-    ValidationErrors,-  )-import Relude-  ( ($),-    Applicative (..),-    Monad (..),-    Semigroup (..),-    Traversable (..),-  )--class SemigroupM (m :: * -> *) a where-  mergeM :: [Ref FieldName] -> a -> a -> m a--instance-  ( NameCollision a,-    Monad m,-    KeyOf k a,-    Failure ValidationErrors m-  ) =>-  SemigroupM m (HashMap k a)-  where-  mergeM _ x y = runResolutionT (fromListT $ HM.toList x <> HM.toList y) HM.fromList failOnDuplicates--concatTraverse ::-  ( Monad m,-    Failure ValidationErrors m,-    Elems a ca,-    SemigroupM m cb,-    Empty cb-  ) =>-  (a -> m cb) ->-  ca ->-  m cb-concatTraverse f smap =-  traverse f (elems smap)-    >>= join--join ::-  ( Empty a,-    Monad m,-    Failure ValidationErrors m,-    SemigroupM m a-  ) =>-  [a] ->-  m a-join = __join empty-  where-    __join acc [] = pure acc-    __join acc (x : xs) = acc <:> x >>= (`__join` xs)--(<:>) :: SemigroupM m a => a -> a -> m a-(<:>) = mergeM []
src/Data/Morpheus/Internal/Ext.hs view
@@ -1,37 +1,25 @@ {-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Internal.Ext-  ( Eventless,-    Failure (..),+  ( Failure,     PushEvents (..),     Result (..),     ResultT (..),     cleanEvents,     resultOr,-    SemigroupM (..),     mapEvent,-    unpackEvents,     sortErrors,     unsafeFromList,     (<:>),     resolveWith,     runResolutionT,+    toEither,+    Merge (..),+    failure,+    GQLResult,   ) where -import Data.Morpheus.Ext.KeyOf-import Data.Morpheus.Ext.Map-import qualified Data.Morpheus.Ext.OrdMap as OM+import Data.Mergeable import Data.Morpheus.Ext.Result-import qualified Data.Morpheus.Ext.SafeHashMap as SHM-import Data.Morpheus.Ext.SemigroupM-import Relude--class UnsafeFromList f where-  unsafeFromList :: (Hashable k, KeyOf k a, Eq k) => [(k, a)] -> f k a--instance UnsafeFromList OM.OrdMap where-  unsafeFromList = OM.unsafeFromList--instance UnsafeFromList SHM.SafeHashMap where-  unsafeFromList = SHM.unsafeFromList+import Data.Morpheus.Internal.Utils
− src/Data/Morpheus/Internal/TH.hs
@@ -1,179 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE NoImplicitPrelude #-}--module Data.Morpheus.Internal.TH-  ( _',-    apply,-    applyCons,-    applyVars,-    declareTypeRef,-    funDSimple,-    nameSpaceField,-    nameSpaceType,-    toCon,-    toVar,-    ToName (..),-    toString,-    typeInstanceDec,-    v',-    vars,-  )-where--import Data.Morpheus.Internal.Utils-  ( capitalize,-    nameSpaceField,-    nameSpaceType,-  )-import Data.Morpheus.Types.Internal.AST-  ( FieldName (..),-    TypeName (..),-    TypeRef (..),-    TypeWrapper (..),-    convertToHaskellName,-    readName,-  )-import Data.Text (unpack)-import Language.Haskell.TH-import Relude hiding-  ( ToString (..),-    Type,-  )--_' :: PatQ-_' = toVar (mkName "_")--v' :: ToVar Name a => a-v' = toVar (mkName "v")--declareTypeRef :: (TypeName -> Type) -> TypeRef -> Type-declareTypeRef f TypeRef {typeConName, typeWrappers} =-  wrappedT-    typeWrappers-  where-    wrappedT :: [TypeWrapper] -> Type-    wrappedT (TypeList : xs) = AppT (ConT ''[]) $ wrappedT xs-    wrappedT (TypeMaybe : xs) = AppT (ConT ''Maybe) $ wrappedT xs-    wrappedT [] = f typeConName--cons :: ToCon a b => [a] -> [b]-cons = map toCon--vars :: ToVar a b => [a] -> [b]-vars = map toVar--class ToName a where-  toName :: a -> Name--instance ToName String where-  toName = mkName--instance ToName Name where-  toName = id--instance ToName TypeName where-  toName = mkName . unpack . capitalize . readTypeName--instance ToName FieldName where-  toName = mkName . unpack . readName . convertToHaskellName--class ToString a b where-  toString :: a -> b--instance ToString a b => ToString a (Q b) where-  toString = pure . toString--instance ToString TypeName Lit where-  toString = stringL . unpack . readTypeName--instance ToString TypeName Pat where-  toString = LitP . toString--instance ToString FieldName Lit where-  toString (FieldName x) = stringL (unpack x)--instance ToString TypeName Exp where-  toString = LitE . toString--instance ToString FieldName Exp where-  toString = LitE . toString--class ToCon a b where-  toCon :: a -> b--instance ToCon a b => ToCon a (Q b) where-  toCon = pure . toCon--instance (ToName a) => ToCon a Type where-  toCon = ConT . toName--instance (ToName a) => ToCon a Exp where-  toCon = ConE . toName--class ToVar a b where-  toVar :: a -> b--instance ToVar a b => ToVar a (Q b) where-  toVar = pure . toVar--instance (ToName a) => ToVar a Type where-  toVar = VarT . toName--instance (ToName a) => ToVar a Exp where-  toVar = VarE . toName--instance (ToName a) => ToVar a Pat where-  toVar = VarP . toName--class Apply a where-  apply :: ToCon i a => i -> [a] -> a--instance Apply TypeQ where-  apply = foldl' appT . toCon--instance Apply Type where-  apply = foldl' AppT . toCon--instance Apply Exp where-  apply = foldl' AppE . toCon--instance Apply ExpQ where-  apply = foldl' appE . toCon--applyVars ::-  ( ToName con,-    ToName var,-    Apply res,-    ToCon con res,-    ToVar var res-  ) =>-  con ->-  [var] ->-  res-applyVars name li = apply name (vars li)--applyCons :: (ToName con, ToName cons) => con -> [cons] -> Q Type-applyCons name li = apply name (cons li)--funDSimple :: Name -> [PatQ] -> ExpQ -> DecQ-funDSimple name args body = funD name [clause args (normalB body) []]--#if MIN_VERSION_template_haskell(2,15,0)--- fix breaking changes-typeInstanceDec :: Name -> Type -> Type -> Dec-typeInstanceDec typeFamily arg res = TySynInstD (TySynEqn Nothing (AppT (ConT typeFamily) arg) res)-#else----typeInstanceDec :: Name -> Type -> Type -> Dec-typeInstanceDec typeFamily arg res = TySynInstD typeFamily (TySynEqn [arg] res)-#endif
src/Data/Morpheus/Internal/Utils.hs view
@@ -1,65 +1,63 @@ {-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Internal.Utils-  ( capitalize,-    nameSpaceField,-    nameSpaceType,-    capitalTypeName,-    Collection (..),-    Selectable (..),-    FromElems (..),-    Failure (..),+  ( singleton,+    IsMap,+    Failure,+    failure,     KeyOf (..),     toPair,     selectBy,-    mapFst,-    mapSnd,-    mapTuple,     traverseCollection,     prop,-    stripFieldNamespace,-    stripConstructorNamespace,     fromLBS,     toLBS,     mergeT,-    Elems (..),-    size,-    failOnDuplicates,     Empty (..),+    elems,+    HistoryT,+    addPath,+    startHistory,+    mergeConcat,+    (<:>),+    selectOr,+    member,+    unsafeFromList,+    insert,+    fromElems,+    throwErrors,   ) where +import Control.Monad.Except (MonadError (throwError)) import Data.ByteString.Lazy (ByteString)-import Data.Char-  ( toLower,-    toUpper,+import Data.Mergeable+  ( IsMap,+    Merge (merge),+    NameCollision (..),+    ResolutionT,+    fromListT,+    mergeConcat,+    throwErrors,   )-import qualified Data.HashMap.Lazy as HM-import Data.Morpheus.Error.NameCollision (NameCollision (..))-import Data.Morpheus.Ext.Elems (Elems (..), size)+import Data.Mergeable.IsMap (FromList (..), member, selectBy, selectOr, unsafeFromList)+import qualified Data.Mergeable.IsMap as M+import Data.Mergeable.SafeHashMap (SafeHashMap) import Data.Morpheus.Ext.Empty-import Data.Morpheus.Ext.Failure (Failure (..)) import Data.Morpheus.Ext.KeyOf (KeyOf (..), toPair)-import Data.Morpheus.Ext.Map-  ( ResolutionT,-    fromListT,-    runResolutionT,+import Data.Morpheus.Types.Internal.AST.Base (Ref)+import Data.Morpheus.Types.Internal.AST.Error+  ( GQLError,   )-import Data.Morpheus.Ext.Selectable-import Data.Morpheus.Types.Internal.AST.Base+import Data.Morpheus.Types.Internal.AST.Name   ( FieldName,-    FieldName (..),-    Token,-    TypeName (..),-    ValidationErrors,   )-import qualified Data.Text as T import qualified Data.Text.Lazy as LT import Data.Text.Lazy.Encoding (decodeUtf8, encodeUtf8) import Instances.TH.Lift ()@@ -67,100 +65,74 @@   ( ByteString,     decodeUtf8,     encodeUtf8,+    fromList,   ) -toLBS :: Text -> ByteString-toLBS = encodeUtf8 . LT.fromStrict--fromLBS :: ByteString -> Text-fromLBS = LT.toStrict . decodeUtf8--prop :: (b -> b -> m b) -> (a -> b) -> a -> a -> m b-prop f fSel a1 a2 = f (fSel a1) (fSel a2)--nameSpaceType :: [FieldName] -> TypeName -> TypeName-nameSpaceType list (TypeName name) = TypeName . T.concat $ fmap capitalize (fmap readName list <> [name])+{-# DEPRECATED Failure "use MonadError" #-} -nameSpaceField :: TypeName -> FieldName -> FieldName-nameSpaceField (TypeName nSpace) (FieldName name) = FieldName (uncapitalize nSpace <> capitalize name)+type Failure = MonadError -dropPrefix :: TypeName -> String -> String-dropPrefix (TypeName name) = drop (T.length name)+{-# DEPRECATED failure "use throwError" #-}+failure :: MonadError e m => e -> m a+failure = throwError -stripConstructorNamespace :: TypeName -> String -> String-stripConstructorNamespace = dropPrefix+(<:>) :: (Merge (HistoryT m) a, Monad m) => a -> a -> m a+x <:> y = startHistory (merge x y) -stripFieldNamespace :: TypeName -> String -> String-stripFieldNamespace prefix = __uncapitalize . dropPrefix prefix-  where-    __uncapitalize [] = []-    __uncapitalize (x : xs) = toLower x : xs+addPath :: MonadReader [a1] m => a1 -> m a2 -> m a2+addPath p = local (\xs -> xs <> [p]) -capitalize :: Text -> Text-capitalize = mapFstChar toUpper+type HistoryT = ReaderT [Ref FieldName] -uncapitalize :: Text -> Text-uncapitalize = mapFstChar toLower+startHistory :: HistoryT m a -> m a+startHistory x = runReaderT x [] -mapFstChar :: (Char -> Char) -> Token -> Token-mapFstChar f x-  | T.null x = x-  | otherwise = T.singleton (f $ T.head x) <> T.tail x+toLBS :: Text -> ByteString+toLBS = encodeUtf8 . LT.fromStrict -capitalTypeName :: FieldName -> TypeName-capitalTypeName = TypeName . capitalize . readName+fromLBS :: ByteString -> Text+fromLBS = LT.toStrict . decodeUtf8 ---(KEY v ~ k) =>-class Collection a coll | coll -> a where-  singleton :: a -> coll+prop :: (b -> b -> m b) -> (a -> b) -> a -> a -> m b+prop f fSel a1 a2 = f (fSel a1) (fSel a2) -instance Collection a [a] where-  singleton x = [x]+{-# DEPRECATED elems "use Foldable.toList" #-}+elems :: Foldable t => t a -> [a]+elems = toList -instance KeyOf k v => Collection v (HashMap k v) where-  singleton x = HM.singleton (keyOf x) x+singleton :: (IsMap k m, KeyOf k a) => a -> m a+singleton x = M.singleton (keyOf x) x  traverseCollection ::-  ( Monad f,+  ( Monad m,+    Failure GQLError m,     KeyOf k b,-    Elems a (t a),-    FromElems f b (t' b),-    Failure ValidationErrors f+    FromList m map k b,+    Foldable t   ) =>-  (a -> f b) ->+  (a -> m b) ->   t a ->-  f (t' b)-traverseCollection f a = fromElems =<< traverse f (elems a)---- list Like Collections-class FromElems m a coll | coll -> a where-  fromElems :: [a] -> m coll--mergeT :: (KeyOf k a, Monad m, Elems a c) => c -> c -> ResolutionT k a c m c-mergeT x y = fromListT (toPair <$> (elems x <> elems y))+  m (map k b)+traverseCollection f a = fromElems =<< traverse f (toList a) -instance-  ( NameCollision a,-    Failure ValidationErrors m,+fromElems ::+  ( Monad m,     KeyOf k a,-    Monad m+    FromList m map k a   ) =>-  FromElems m a (HashMap k a)-  where-  fromElems xs = runResolutionT (fromListT (toPair <$> xs)) HM.fromList failOnDuplicates---- Merge Object with of Failure as an Option--mapFst :: (a -> a') -> (a, b) -> (a', b)-mapFst f (a, b) = (f a, b)--mapSnd :: (b -> b') -> (a, b) -> (a, b')-mapSnd f (a, b) = (a, f b)+  [a] ->+  m (map k a)+fromElems = fromList . map toPair -mapTuple :: (a -> a') -> (b -> b') -> (a, b) -> (a', b')-mapTuple f1 f2 (a, b) = (f1 a, f2 b)+insert ::+  ( NameCollision e a,+    KeyOf k a,+    Failure e m+  ) =>+  a ->+  SafeHashMap k a ->+  m (SafeHashMap k a)+insert x = merge (singleton x) -failOnDuplicates :: (Failure ValidationErrors m, NameCollision a) => NonEmpty a -> m a-failOnDuplicates (x :| xs)-  | null xs = pure x-  | otherwise = failure $ fmap nameCollision (x : xs)+mergeT :: (KeyOf k a, Foldable t, Monad m) => t a -> t a -> ResolutionT k a c m c+mergeT x y = fromListT (toPair <$> (toList x <> toList y))
src/Data/Morpheus/Parser.hs view
@@ -10,13 +10,15 @@  import Data.ByteString.Lazy (ByteString) import Data.Morpheus.Ext.Result-  ( Eventless,+  ( GQLResult,     sortErrors,   )-import Data.Morpheus.Ext.SemigroupM ((<:>))+import Data.Morpheus.Internal.Utils ((<:>))+import Data.Morpheus.Parsing.Document.TypeSystem+  ( parseTypeDefinitions,+  ) import qualified Data.Morpheus.Parsing.Document.TypeSystem as P   ( parseSchema,-    parseTypeDefinitions,   ) import Data.Morpheus.Parsing.Request.Parser   ( parseRequest,@@ -26,11 +28,8 @@   ( GQLRequest (..),   ) import Data.Morpheus.Types.Internal.AST-  ( ANY,-    CONST,-    Operation,+  ( Operation,     Schema (..),-    TypeDefinition (..),     VALID,   ) import Data.Morpheus.Types.Internal.Config@@ -46,7 +45,7 @@ import Relude hiding (ByteString)  parseSchema ::-  ByteString -> Eventless (Schema VALID)+  ByteString -> GQLResult (Schema VALID) parseSchema =   sortErrors     . ( P.parseSchema@@ -58,11 +57,7 @@               }       ) -parseTypeDefinitions ::-  ByteString -> Eventless [TypeDefinition ANY CONST]-parseTypeDefinitions = P.parseTypeDefinitions--parseRequestWith :: Config -> Schema VALID -> GQLRequest -> Eventless (Operation VALID)+parseRequestWith :: Config -> Schema VALID -> GQLRequest -> GQLResult (Operation VALID) parseRequestWith config schema req = do   qu <- parseRequest req   fillSchema <- internalSchema <:> schema
src/Data/Morpheus/Parsing/Document/TypeSystem.hs view
@@ -3,6 +3,7 @@ {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TupleSections #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE NoImplicitPrelude #-} @@ -14,11 +15,13 @@  import Data.ByteString.Lazy (ByteString) import Data.Foldable (foldr')-import Data.Morpheus.Error.NameCollision (NameCollision (..))+import Data.Mergeable (NameCollision (nameCollision), throwErrors) import Data.Morpheus.Ext.Result-  ( Eventless,-    failure,+  ( GQLResult,   )+import Data.Morpheus.Internal.Utils+  ( fromElems,+  ) import Data.Morpheus.Parsing.Internal.Internal   ( Parser,     processParser,@@ -57,6 +60,7 @@     Description,     DirectiveDefinition (..),     Directives,+    DirectivesDefinition,     FieldsDefinition,     OBJECT,     OUT,@@ -93,6 +97,7 @@     { typeContent = DataObject {objectImplements, objectFields},       ..     }+{-# INLINEABLE mkObject #-}  -- Scalars : https://graphql.github.io/graphql-spec/June2018/#sec-Scalars --@@ -109,6 +114,7 @@       <$> typeDeclaration "scalar"       <*> optionalDirectives       <*> pure (DataScalar (ScalarDefinition pure))+{-# INLINEABLE scalarTypeDefinition #-}  -- Objects : https://graphql.github.io/graphql-spec/June2018/#sec-Objects --@@ -136,14 +142,14 @@       <*> optionalImplementsInterfaces       <*> optionalDirectives       <*> fieldsDefinition---- build object+{-# INLINEABLE objectTypeDefinition #-}  optionalImplementsInterfaces :: Parser [TypeName] optionalImplementsInterfaces = implements <|> pure []   where     implements =       label "ImplementsInterfaces" $ keyword "implements" *> sepByAnd parseTypeName+{-# INLINEABLE optionalImplementsInterfaces #-}  -- Interfaces: https://graphql.github.io/graphql-spec/June2018/#sec-Interfaces --@@ -160,6 +166,7 @@       <$> typeDeclaration "interface"       <*> optionalDirectives       <*> (DataInterface <$> fieldsDefinition)+{-# INLINEABLE interfaceTypeDefinition #-}  -- Unions : https://graphql.github.io/graphql-spec/June2018/#sec-Unions --@@ -182,8 +189,10 @@       <*> (DataUnion <$> unionMemberTypes)   where     unionMemberTypes =-      equal+      lift . fromElems+        =<< equal         *> pipe (mkUnionMember <$> parseTypeName)+{-# INLINEABLE unionTypeDefinition #-}  -- Enums : https://graphql.github.io/graphql-spec/June2018/#sec-Enums --@@ -206,6 +215,7 @@       <$> typeDeclaration "enum"       <*> optionalDirectives       <*> (DataEnum <$> collection enumValueDefinition)+{-# INLINEABLE enumTypeDefinition #-}  -- Input Objects : https://graphql.github.io/graphql-spec/June2018/#sec-Input-Objects --@@ -226,6 +236,7 @@       <$> typeDeclaration "input"       <*> optionalDirectives       <*> (DataInputObject <$> inputFieldsDefinition)+{-# INLINEABLE inputObjectTypeDefinition #-}  -- 3.13 DirectiveDefinition --@@ -249,6 +260,7 @@         <*> pure directiveDefinitionDescription         <*> optionalCollection argumentsDefinition         <*> (optional (keyword "repeatable") *> keyword "on" *> pipe parseDirectiveLocation)+{-# INLINEABLE parseDirectiveDefinition #-}  -- 3.2 Schema -- SchemaDefinition:@@ -271,12 +283,14 @@              <$> optionalDirectives              <*> setOf parseRootOperationTypeDefinition          )+{-# INLINEABLE parseSchemaDefinition #-}  parseRootOperationTypeDefinition :: Parser RootOperationTypeDefinition parseRootOperationTypeDefinition =   RootOperationTypeDefinition     <$> (parseOperationType <* colon)     <*> parseTypeName+{-# INLINEABLE parseRootOperationTypeDefinition #-}  parseTypeSystemUnit ::   Parser RawTypeDefinition@@ -298,6 +312,7 @@                 <|> enumTypeDefinition description                 <|> scalarTypeDefinition description             )+{-# INLINEABLE parseTypeSystemUnit #-}  typePartition ::   [RawTypeDefinition] ->@@ -328,11 +343,10 @@     [TypeDefinition ANY s],     [DirectiveDefinition CONST]   ) ->-  Eventless-    (Maybe SchemaDefinition, [TypeDefinition ANY s], [DirectiveDefinition CONST])-withSchemaDefinition ([], t, dirs) = pure (Nothing, t, dirs)-withSchemaDefinition ([x], t, dirs) = pure (Just x, t, dirs)-withSchemaDefinition (_ : xs, _, _) = failure (fmap nameCollision xs)+  GQLResult (Maybe SchemaDefinition, [TypeDefinition ANY s], DirectivesDefinition CONST)+withSchemaDefinition ([], t, dirs) = (Nothing,t,) <$> fromElems dirs+withSchemaDefinition ([x], t, dirs) = (Just x,t,) <$> fromElems dirs+withSchemaDefinition (x : xs, _, _) = throwErrors (nameCollision <$> (x :| xs))  parseRawTypeDefinitions :: Parser [RawTypeDefinition] parseRawTypeDefinitions =@@ -342,20 +356,19 @@  typeSystemDefinition ::   ByteString ->-  Eventless+  GQLResult     ( Maybe SchemaDefinition,       [TypeDefinition ANY CONST],-      [DirectiveDefinition CONST]+      DirectivesDefinition CONST     ) typeSystemDefinition =   processParser parseRawTypeDefinitions     >=> withSchemaDefinition . typePartition -parseTypeDefinitions :: ByteString -> Eventless [TypeDefinition ANY CONST]-parseTypeDefinitions = fmap snd3 . typeSystemDefinition--snd3 :: (a, b, c) -> b-snd3 (_, x, _) = x+parseTypeDefinitions :: ByteString -> GQLResult [TypeDefinition ANY CONST]+parseTypeDefinitions =+  fmap (\d -> [td | RawTypeDefinition td <- d])+    . processParser parseRawTypeDefinitions -parseSchema :: ByteString -> Eventless (Schema CONST)+parseSchema :: ByteString -> GQLResult (Schema CONST) parseSchema = typeSystemDefinition >=> buildSchema
src/Data/Morpheus/Parsing/Internal/Arguments.hs view
@@ -9,7 +9,8 @@     getLocation,   ) import Data.Morpheus.Parsing.Internal.Terms-  ( fieldNameColon,+  ( colon,+    parseName,     uniqTupleOpt,   ) import Data.Morpheus.Parsing.Internal.Value@@ -35,10 +36,12 @@   label "Argument" $     Argument       <$> getLocation-      <*> fieldNameColon+      <*> (parseName <* colon)       <*> parse+{-# INLINEABLE valueArgument #-}  maybeArguments :: Parse (Value s) => Parser (Arguments s) maybeArguments =   label "Arguments" $     uniqTupleOpt valueArgument+{-# INLINEABLE maybeArguments #-}
src/Data/Morpheus/Parsing/Internal/Internal.hs view
@@ -10,27 +10,17 @@ where  import Data.ByteString.Lazy (ByteString)-import qualified Data.List.NonEmpty as NonEmpty import Data.Morpheus.Ext.Result-  ( Eventless,+  ( GQLResult,     Result (..),-    failure,   ) import Data.Morpheus.Types.Internal.AST-  ( GQLError (..),-    GQLErrors,+  ( GQLError,     Position (..),+    at,     msg,   )-import Relude-  ( ($),-    (.),-    Applicative (..),-    Either (..),-    Functor (..),-    Void,-    fst,-  )+import Relude hiding (ByteString) import Text.Megaparsec   ( ParseError,     ParseErrorBundle@@ -51,39 +41,31 @@  getLocation :: Parser Position getLocation = fmap toLocation getSourcePos+{-# INLINEABLE getLocation #-}  toLocation :: SourcePos -> Position toLocation SourcePos {sourceLine, sourceColumn} =   Position {line = unPos sourceLine, column = unPos sourceColumn}+{-# INLINEABLE toLocation #-}  type MyError = Void -type Parser = ParsecT MyError ByteString Eventless+type Parser = ParsecT MyError ByteString GQLResult  type ErrorBundle = ParseErrorBundle ByteString MyError -processParser :: Parser a -> ByteString -> Eventless a+processParser :: Parser a -> ByteString -> GQLResult a processParser parser txt = case runParserT parser [] txt of-  Success {result} -> case result of-    Right root -> pure root-    Left parseError -> failure (processErrorBundle parseError)-  Failure {errors} -> failure errors--processErrorBundle :: ErrorBundle -> GQLErrors-processErrorBundle = fmap parseErrorToGQLError . bundleToErrors+  Success {result} ->+    either+      (Failure . fmap parseErrorToGQLError . bundleToErrors)+      pure+      result+  Failure {errors} -> Failure errors  parseErrorToGQLError :: (ParseError ByteString MyError, SourcePos) -> GQLError-parseErrorToGQLError (err, position) =-  GQLError-    { message = msg (parseErrorPretty err),-      locations = [toLocation position]-    }+parseErrorToGQLError (err, position) = msg (parseErrorPretty err) `at` toLocation position -bundleToErrors ::-  ErrorBundle -> [(ParseError ByteString MyError, SourcePos)]+bundleToErrors :: ErrorBundle -> NonEmpty (ParseError ByteString MyError, SourcePos) bundleToErrors ParseErrorBundle {bundleErrors, bundlePosState} =-  NonEmpty.toList $ fst $-    attachSourcePos-      errorOffset-      bundleErrors-      bundlePosState+  fst $ attachSourcePos errorOffset bundleErrors bundlePosState
src/Data/Morpheus/Parsing/Internal/Pattern.hs view
@@ -16,6 +16,8 @@   ) where +import Data.ByteString.Lazy.Internal (ByteString)+import Data.Morpheus.Internal.Utils (fromElems) import Data.Morpheus.Parsing.Internal.Arguments   ( maybeArguments,   )@@ -46,6 +48,7 @@     Description,     Directive (..),     DirectiveLocation (..),+    Directives,     FieldContent (..),     FieldDefinition (..),     FieldName,@@ -59,7 +62,7 @@     TypeRef,     Value,   )-import Relude hiding (many)+import Relude hiding (ByteString, many) import Text.Megaparsec   ( choice,     label,@@ -81,6 +84,7 @@       <$> optDescription       <*> parseTypeName       <*> optionalDirectives+{-# INLINEABLE enumValueDefinition #-}  -- InputValue : https://graphql.github.io/graphql-spec/June2018/#InputValueDefinition --@@ -98,6 +102,7 @@       <*> (colon *> parseType)       <*> optional (DefaultInputValue <$> parseDefaultValue)       <*> optionalDirectives+{-# INLINEABLE inputValueDefinition #-}  -- Field Arguments: https://graphql.github.io/graphql-spec/June2018/#sec-Field-Arguments --@@ -110,6 +115,7 @@ argumentsDefinition =   label "ArgumentsDefinition" $     uniqTuple (fmap ArgumentDefinition inputValueDefinition)+{-# INLINEABLE argumentsDefinition #-}  --  FieldsDefinition : https://graphql.github.io/graphql-spec/June2018/#FieldsDefinition --@@ -120,6 +126,7 @@   Parse (Value s) =>   Parser (FieldsDefinition OUT s) fieldsDefinition = label "FieldsDefinition" $ setOf fieldDefinition+{-# INLINEABLE fieldsDefinition #-}  --  FieldDefinition --    Description(opt) Name ArgumentsDefinition(opt) : Type Directives(Const)(opt)@@ -133,16 +140,18 @@       <*> optional (FieldArgs <$> argumentsDefinition)       <*> (colon *> parseType)       <*> optionalDirectives+{-# INLINEABLE fieldDefinition #-}  mkField ::   Maybe Description ->   FieldName ->   Maybe (FieldContent TRUE cat s) ->   TypeRef ->-  [Directive s] ->+  Directives s ->   FieldDefinition cat s mkField fieldDescription fieldName fieldContent fieldType fieldDirectives =   FieldDefinition {..}+{-# INLINEABLE mkField #-}  -- InputFieldsDefinition : https://graphql.github.io/graphql-spec/June2018/#sec-Language.Directives --   InputFieldsDefinition:@@ -152,6 +161,7 @@   Parse (Value s) =>   Parser (InputFieldsDefinition s) inputFieldsDefinition = label "InputFieldsDefinition" $ setOf inputValueDefinition+{-# INLINEABLE inputFieldsDefinition #-}  -- Directives : https://graphql.github.io/graphql-spec/June2018/#sec-Language.Directives --@@ -160,8 +170,9 @@ -- Directives[Const] -- Directive[Const](list) ---optionalDirectives :: Parse (Value s) => Parser [Directive s]-optionalDirectives = label "Directives" $ many directive+optionalDirectives :: Parse (Value s) => Parser (Directives s)+optionalDirectives = label "Directives" $ many directive >>= lift . fromElems+{-# INLINEABLE optionalDirectives #-}  -- Directive[Const] --@@ -173,14 +184,16 @@       <$> getLocation       <*> (at *> parseName)       <*> maybeArguments+{-# INLINEABLE directive #-}  -- typDeclaration : Not in spec ,start part of type definitions -- --  typDeclaration --   Description(opt) scalar Name ---typeDeclaration :: FieldName -> Parser TypeName+typeDeclaration :: ByteString -> Parser TypeName typeDeclaration kind = keyword kind *> parseTypeName+{-# INLINEABLE typeDeclaration #-}  parseOperationType :: Parser OperationType parseOperationType =@@ -190,6 +203,7 @@         <|> (string "subscription" $> Subscription)     )       <* ignoredTokens+{-# INLINEABLE parseOperationType #-}  parseDirectiveLocation :: Parser DirectiveLocation parseDirectiveLocation =@@ -218,6 +232,8 @@               ]     )     <* ignoredTokens+{-# INLINEABLE parseDirectiveLocation #-}  toKeyword :: Show a => a -> Parser a toKeyword x = string (fromString $ show x) $> x+{-# INLINEABLE toKeyword #-}
+ src/Data/Morpheus/Parsing/Internal/SourceText.hs view
@@ -0,0 +1,139 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE NoImplicitPrelude #-}+{-# OPTIONS_GHC -Wno-overflowed-literals #-}++module Data.Morpheus.Parsing.Internal.SourceText+  ( parseStringBS,+    ignoredTokens,+    ignoredTokens1,+  )+where++import Data.ByteString.Lazy.Internal+  ( ByteString,+  )+import Data.Morpheus.Parsing.Internal.Internal+  ( Parser,+  )+import Relude hiding (ByteString, empty, many)+import Text.Megaparsec+  ( choice,+    label,+    many,+    satisfy,+    takeWhile1P,+    takeWhileP,+    unexpected,+  )+import Text.Megaparsec.Byte+  ( char,+    space1,+    string,+  )+import Text.Megaparsec.Error+  ( ErrorItem (..),+  )++-- White Space+#define TABULATION 0x0009+#define NEW_LINE 0x000A+#define SPACE 0x0020+#define CARRIAGE_RETURN 0x000D+#define UNICODE_BOM 0xFEFF+#define NON_CHARACTER 0xFFFF++-- Non-alphabetic characters+#define DOUBLE_QUOTE 34+#define BACKSLASH 92+#define COMMA 44+#define HASH_TAG 35++-- Alphabetic characters+#define CHAR_b 98+#define CHAR_f 102+#define CHAR_n 110+#define CHAR_r 114+#define CHAR_t 116++-- https://spec.graphql.org/June2018/#sec-Source-Text+-- SourceCharacter : [\u0009\u000A\u000D\u0020-\uFFFF]/+isSourceCharacter :: Word8 -> Bool+isSourceCharacter TABULATION = True+isSourceCharacter NEW_LINE = True+isSourceCharacter CARRIAGE_RETURN = True+isSourceCharacter x = SPACE <= x && x <= NON_CHARACTER+{-# INLINE isSourceCharacter #-}++inlineString :: Parser ByteString+inlineString =+  label "String" $+    char DOUBLE_QUOTE+      *> parseContent+      <* ignoredTokens+{-# INLINE inlineString #-}++parseContent :: Parser ByteString+parseContent = do+  xs <- takeWhileP Nothing (\x -> isSourceCharacter x && DOUBLE_QUOTE /= x && x /= BACKSLASH && NEW_LINE /= x)+  z <- satisfy (const True)+  case z of+    DOUBLE_QUOTE -> pure xs+    BACKSLASH -> (xs <>) <$> ((<>) <$> escapeChar <*> parseContent)+    w -> unexpected (Tokens (w :| []))+  where+    escapeChar :: Parser ByteString+    escapeChar =+      choice+        [ char CHAR_b $> "\b",+          char CHAR_f $> "\f",+          char CHAR_n $> "\n",+          char CHAR_r $> "\r",+          char CHAR_t $> "\t",+          char BACKSLASH $> "\\",+          char DOUBLE_QUOTE $> "\"",+          char 47 $> "/"+        ]+    {-# INLINE escapeChar #-}+{-# INLINE parseContent #-}++blockString :: Parser ByteString+blockString = string "\"\"\"" *> content <* ignoredTokens+  where+    content :: Parser ByteString+    content = do+      text <- takeWhileP Nothing (\x -> isSourceCharacter x && x /= DOUBLE_QUOTE)+      doubleQuotes <- takeWhileP Nothing (== DOUBLE_QUOTE)+      case doubleQuotes of+        "\"\"\"" -> pure text+        _ -> ((text <> doubleQuotes) <>) <$> content+    {-# INLINE content #-}+{-# INLINE blockString #-}++parseStringBS :: Parser ByteString+parseStringBS = blockString <|> inlineString+{-# INLINE parseStringBS #-}++-- Ignored Tokens : https://graphql.github.io/graphql-spec/June2018/#sec-Source-Text.Ignored-Tokens+ignoredTokens :: Parser ()+ignoredTokens = label "IgnoredTokens" $ many ignored $> ()+{-# INLINE ignoredTokens #-}++-- isIgnored :: UnicodeBOM, WhiteSpace, LineTerminator, Comment , Comma+ignored :: Parser ()+ignored = (takeWhile1P Nothing isIgnored <|> comment) $> ()+  where+    isIgnored x =+      (x >= TABULATION && x <= CARRIAGE_RETURN)+        || x == SPACE+        || x == COMMA+        || x == UNICODE_BOM+    {-# INLINE isIgnored #-}+    comment = char HASH_TAG *> takeWhileP Nothing (\x -> isSourceCharacter x && x /= NEW_LINE)+    {-# INLINE comment #-}+{-# INLINE ignored #-}++ignoredTokens1 :: Parser ()+ignoredTokens1 = space1 *> ignoredTokens+{-# INLINE ignoredTokens1 #-}
src/Data/Morpheus/Parsing/Internal/Terms.hs view
@@ -1,7 +1,6 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TupleSections #-} {-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Parsing.Internal.Terms@@ -16,173 +15,171 @@     uniqTupleOpt,     parseTypeCondition,     spreadLiteral,-    parseNonNull,-    parseWrappedType,     parseAlias,     sepByAnd,     parseName,     parseType,     keyword,-    symbol,     optDescription,     optionalCollection,-    parseNegativeSign,     parseTypeName,     pipe,-    fieldNameColon,     brackets,     equal,-    comma,     colon,     at,+    symbol,   ) where -import Data.ByteString.Lazy-  ( pack,-  )-import Data.Morpheus.Ext.Result (Eventless)+import Data.ByteString.Lazy.Internal (ByteString)+import Data.Mergeable.IsMap (FromList)+import Data.Morpheus.Ext.Result (GQLResult) import Data.Morpheus.Internal.Utils   ( Empty (..),-    FromElems (..),     KeyOf,     fromElems,+    fromElems,     fromLBS,-    toLBS,   ) import Data.Morpheus.Parsing.Internal.Internal   ( Parser,     Position,     getLocation,   )+import Data.Morpheus.Parsing.Internal.SourceText+  ( ignoredTokens,+    ignoredTokens1,+    parseStringBS,+  )+import qualified Data.Morpheus.Types.Internal.AST as AST import Data.Morpheus.Types.Internal.AST-  ( DataTypeWrapper (..),-    Description,-    FieldName (..),+  ( Description,+    FieldName,     Ref (..),-    Token,-    TypeName (..),+    TypeName,     TypeRef (..),-    toHSWrappers,-  )-import Data.Text-  ( strip,+    TypeWrapper (..),+    packName,   )-import Relude hiding (empty, many)+import Data.Morpheus.Types.Internal.AST.Name (Name)+import Relude hiding (ByteString, empty, many) import Text.Megaparsec   ( (<?>),     between,-    choice,     label,-    many,-    manyTill,     sepBy,     sepBy1,     sepEndBy,-    skipManyTill,+    takeWhile1P,+    takeWhileP,     try,   ) import Text.Megaparsec.Byte   ( char,-    digitChar,-    letterChar,-    newline,-    printChar,-    space,-    space1,     string,   ) -parseNegativeSign :: Parser Bool-parseNegativeSign = (minus $> True <* ignoredTokens) <|> pure False--parseName :: Parser FieldName-parseName = FieldName <$> name+-- ':'+#define COLON 58+-- '@'+#define AT 64+-- '='+#define EQUAL 61+-- '|'+#define PIPE 124+-- '$'+#define DOLLAR 36+-- '&'+#define AMPERSAND 38+-- '_'+#define UNDERSCORE 95+-- '!'+#define BANG 33 -parseTypeName :: Parser TypeName-parseTypeName = label "TypeName" $ TypeName <$> name+#define CHAR_A 65 -keyword :: FieldName -> Parser ()-keyword (FieldName word) = string (toLBS word) *> space1 *> ignoredTokens+#define CHAR_Z 90 -symbol :: Word8 -> Parser ()-symbol x = char x *> ignoredTokens+#define CHAR_a 97 --- braces: {}-braces :: Parser a -> Parser a-braces = between (symbol 123) (symbol 125)+#define CHAR_z 122 --- brackets: []-brackets :: Parser a -> Parser a-brackets = between (symbol 91) (symbol 93)+#define DIGIT_0 48 --- parens : '()'-parens :: Parser a -> Parser a-parens = between (symbol 40) (symbol 41)+#define DIGIT_9 57 --- underscore : '_'-underscore :: Parser Word8-underscore = char 95+symbol :: Word8 -> Parser ()+symbol x = char x *> ignoredTokens+{-# INLINE symbol #-} -comma :: Parser ()-comma = label "," $ char 44 *> space+colon :: Parser ()+colon = symbol COLON+{-# INLINE colon #-} --- dollar :: $-dollar :: Parser ()-dollar = label "$" $ symbol 36+at :: Parser ()+at = symbol AT+{-# INLINE at #-} --- equal :: '=' equal :: Parser ()-equal = label "=" $ symbol 61---- colon :: ':'-colon :: Parser ()-colon = label ":" $ symbol 58---- minus: '-'-minus :: Parser ()-minus = label "-" $ symbol 45+equal = symbol EQUAL+{-# INLINE equal #-} --- verticalPipe: '|'-verticalPipe :: Parser ()-verticalPipe = label "|" $ symbol 124+pipe :: Parser a -> Parser [a]+pipe x = optional (symbol PIPE) *> (x `sepBy1` symbol PIPE)+{-# INLINE pipe #-} -ampersand :: Parser ()-ampersand = label "&" $ symbol 38+-- parens : '()'+parens :: Parser a -> Parser a+parens = between (symbol 40) (symbol 41)+{-# INLINE parens #-} --- at: '@'-at :: Parser ()-at = label "@" $ symbol 64+-- braces: {}+braces :: Parser a -> Parser a+braces = between (symbol 123) (symbol 125)+{-# INLINE braces #-} --- PRIMITIVE-------------------------------------+-- brackets: []+brackets :: Parser a -> Parser a+brackets = between (symbol 91) (symbol 93)+{-# INLINE brackets #-}  -- 2.1.9 Names -- https://spec.graphql.org/draft/#Name--- Name ::---  NameStart NameContinue[list,opt]----name :: Parser Token+-- Name+name :: Parser AST.Token name =   label "Name" $-    fromLBS . pack-      <$> ((:) <$> nameStart <*> nameContinue)+    fromLBS <$> do+      (<>) <$> takeWhile1P Nothing isStartChar <*> takeWhileP Nothing isContinueChar       <* ignoredTokens+  where+    isStartChar x =+      (x >= CHAR_a && x <= CHAR_z)+        || (x >= CHAR_A && x <= CHAR_Z)+        || x == UNDERSCORE+    {-# INLINE isStartChar #-}+    isContinueChar x =+      isStartChar x+        || (x >= DIGIT_0 && x <= DIGIT_9) -- digit+    {-# INLINE isContinueChar #-}+{-# INLINE name #-} --- NameStart::---   Letter---   _-nameStart :: Parser Word8-nameStart = letterChar <|> underscore+parseName :: Parser (Name t)+parseName = packName <$> name+{-# INLINE parseName #-} ---  NameContinue::---   Letter---   Digit-nameContinue :: Parser [Word8]-nameContinue = many (letterChar <|> underscore <|> digitChar)+parseTypeName :: Parser TypeName+parseTypeName = packName <$> name+{-# INLINE parseTypeName #-} +keyword :: ByteString -> Parser ()+keyword x = string x *> ignoredTokens1+{-# INLINE keyword #-}+ varName :: Parser FieldName-varName = dollar *> parseName <* ignoredTokens+varName = symbol DOLLAR *> parseName <* ignoredTokens+{-# INLINE varName #-}  -- Variable : https://graphql.github.io/graphql-spec/June2018/#Variable --@@ -194,124 +191,59 @@     flip Ref       <$> getLocation       <*> varName+{-# INLINE variable #-}  -- Descriptions: https://graphql.github.io/graphql-spec/June2018/#Description -- -- Description: --   StringValue-parseDescription :: Parser Description-parseDescription = strip <$> parseString- optDescription :: Parser (Maybe Description)-optDescription = optional parseDescription--parseString :: Parser Token-parseString = blockString <|> singleLineString--blockString :: Parser Token-blockString = stringWith (string "\"\"\"") (printChar <|> newline)--singleLineString :: Parser Token-singleLineString = stringWith (string "\"") escapedChar--stringWith :: Parser quote -> Parser Word8 -> Parser Token-stringWith quote parser =-  fromLBS . pack-    <$> ( quote-            *> manyTill parser quote-            <* ignoredTokens-        )--escapedChar :: Parser Word8-escapedChar = label "EscapedChar" $ printChar >>= handleEscape--handleEscape :: Word8 -> Parser Word8-handleEscape 92 = choice escape-handleEscape x = pure x--escape :: [Parser Word8]-escape = escapeCh <$> escapeOptions-  where-    escapeCh :: (Word8, Word8) -> Parser Word8-    escapeCh (code, replacement) = char code $> replacement--escapeOptions :: [(Word8, Word8)]-escapeOptions =-  [ (98, 8),-    (110, 10),-    (102, 12),-    (114, 13),-    (116, 9),-    (92, 92),-    (34, 34),-    (47, 47)-  ]---- Ignored Tokens : https://graphql.github.io/graphql-spec/June2018/#sec-Source-Text.Ignored-Tokens---  Ignored:---    UnicodeBOM---    WhiteSpace---    LineTerminator---    Comment---    Comma-ignoredTokens :: Parser ()-ignoredTokens =-  label "IgnoredTokens" $-    space-      *> many ignored-      *> space--ignored :: Parser ()-ignored = label "Ignored" (comment <|> comma)--comment :: Parser ()-comment =-  label "Comment" $-    octothorpe *> skipManyTill printChar newline *> space---- exclamationMark: '!'-exclamationMark :: Parser ()-exclamationMark = label "!" $symbol 33+optDescription = optional parseString+{-# INLINE optDescription #-} --- octothorpe: '#'-octothorpe :: Parser ()-octothorpe = label "#" $ char 35 $> ()+parseString :: Parser AST.Token+parseString = label "String" $ fromLBS <$> parseStringBS+{-# INLINE parseString #-}  ------------------------------------------------------------------------- sepByAnd :: Parser a -> Parser [a]-sepByAnd entry = entry `sepBy` (optional ampersand *> ignoredTokens)--pipe :: Parser a -> Parser [a]-pipe x = optional verticalPipe *> (x `sepBy1` verticalPipe)+sepByAnd entry = entry `sepBy` (optional (symbol AMPERSAND) *> ignoredTokens)+{-# INLINE sepByAnd #-}  ----------------------------- collection :: Parser a -> Parser [a] collection entry = braces (entry `sepEndBy` ignoredTokens)+{-# INLINE collection #-} -setOf :: (FromElems Eventless a coll, KeyOf k a) => Parser a -> Parser coll+setOf :: (FromList GQLResult map k a, KeyOf k a) => Parser a -> Parser (map k a) setOf = collection >=> lift . fromElems+{-# INLINE setOf #-} -optionalCollection :: Empty c => Parser c -> Parser c+optionalCollection :: (Empty c) => Parser c -> Parser c optionalCollection x = x <|> pure empty+{-# INLINE optionalCollection #-} -parseNonNull :: Parser [DataTypeWrapper]-parseNonNull =-  (exclamationMark $> [NonNullType])-    <|> pure []+parseNonNull :: Parser Bool+parseNonNull = (symbol BANG $> True) <|> pure False+{-# INLINE parseNonNull #-} -uniqTuple :: (FromElems Eventless a coll, KeyOf k a) => Parser a -> Parser coll+uniqTuple :: (FromList GQLResult map k a, KeyOf k a) => Parser a -> Parser (map k a) uniqTuple parser =   label "Tuple" $     parens       (parser `sepBy` ignoredTokens <?> "empty Tuple value!")       >>= lift . fromElems+{-# INLINE uniqTuple #-} -uniqTupleOpt :: (FromElems Eventless a coll, Empty coll, KeyOf k a) => Parser a -> Parser coll+uniqTupleOpt ::+  ( FromList GQLResult map k a,+    Empty (map k a),+    KeyOf k a+  ) =>+  Parser a ->+  Parser (map k a) uniqTupleOpt x = uniqTuple x <|> pure empty--fieldNameColon :: Parser FieldName-fieldNameColon = parseName <* colon+{-# INLINE uniqTupleOpt #-}  -- Type Conditions: https://graphql.github.io/graphql-spec/June2018/#sec-Type-Conditions --@@ -320,9 +252,11 @@ -- parseTypeCondition :: Parser TypeName parseTypeCondition = keyword "on" *> parseTypeName+{-# INLINE parseTypeCondition #-}  spreadLiteral :: Parser Position-spreadLiteral = getLocation <* string "..." <* space+spreadLiteral = getLocation <* string "..." <* ignoredTokens+{-# INLINE spreadLiteral #-}  -- Field Alias : https://graphql.github.io/graphql-spec/June2018/#sec-Field-Alias -- Alias@@ -330,26 +264,20 @@ parseAlias :: Parser (Maybe FieldName) parseAlias = try (optional alias) <|> pure Nothing   where-    alias = label "alias" fieldNameColon+    alias = label "alias" (parseName <* colon)+{-# INLINE parseAlias #-}  parseType :: Parser TypeRef-parseType = parseTypeW <$> parseWrappedType <*> parseNonNull--parseTypeW :: ([DataTypeWrapper], TypeName) -> [DataTypeWrapper] -> TypeRef-parseTypeW (wrappers, typeConName) nonNull =-  TypeRef-    { typeConName,-      typeWrappers = toHSWrappers (nonNull <> wrappers)-    }--parseWrappedType :: Parser ([DataTypeWrapper], TypeName)-parseWrappedType = (unwrapped <|> wrapped) <* ignoredTokens+parseType = uncurry TypeRef <$> (unwrapped <|> wrapped)   where-    unwrapped :: Parser ([DataTypeWrapper], TypeName)-    unwrapped = ([],) <$> parseTypeName <* ignoredTokens+    unwrapped :: Parser (TypeName, TypeWrapper)+    unwrapped = (,) <$> parseTypeName <*> (BaseType <$> parseNonNull)+    {-# INLINE unwrapped #-}     -----------------------------------------------    wrapped :: Parser ([DataTypeWrapper], TypeName)-    wrapped = brackets (wrapAsList <$> (unwrapped <|> wrapped) <*> parseNonNull)--wrapAsList :: ([DataTypeWrapper], TypeName) -> [DataTypeWrapper] -> ([DataTypeWrapper], TypeName)-wrapAsList (wrappers, tName) nonNull = (ListType : nonNull <> wrappers, tName)+    wrapped :: Parser (TypeName, TypeWrapper)+    wrapped = do+      (typename, wrapper) <- brackets (unwrapped <|> wrapped)+      isRequired <- parseNonNull+      pure (typename, TypeList wrapper isRequired)+    {-# INLINE wrapped #-}+{-# INLINE parseType #-}
src/Data/Morpheus/Parsing/Internal/Value.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TypeFamilies #-}@@ -15,13 +16,14 @@   ) import Data.Morpheus.Parsing.Internal.Terms   ( brackets,+    colon,     equal,-    fieldNameColon,     ignoredTokens,-    parseNegativeSign,+    parseName,     parseString,     parseTypeName,     setOf,+    symbol,     variable,   ) import Data.Morpheus.Types.Internal.AST@@ -44,44 +46,56 @@   ) import Text.Megaparsec.Byte.Lexer (scientific) +-- '-'+#define MINUS 45+ valueNull :: Parser (Value a) valueNull = string "null" $> Null+{-# INLINE valueNull #-}  booleanValue :: Parser (Value a)-booleanValue = boolTrue <|> boolFalse-  where-    boolTrue = string "true" $> Scalar (Boolean True)-    boolFalse = string "false" $> Scalar (Boolean False)+booleanValue =+  Scalar . Boolean+    <$> ( string "true" $> True+            <|> string "false" $> False+        )+{-# INLINE booleanValue #-}  valueNumber :: Parser (Value a)-valueNumber =-  Scalar . decodeScientific-    <$> (signedNumber <$> parseNegativeSign <*> scientific)+valueNumber = Scalar . decodeScientific <$> ((*) <$> negation <*> scientific)   where-    signedNumber isNegative number-      | isNegative = - number-      | otherwise = number+    negation = (symbol MINUS $> (-1) <* ignoredTokens) <|> pure 1+    {-# INLINE negation #-}+{-# INLINE valueNumber #-}  enumValue :: Parser (Value a) enumValue = Enum <$> parseTypeName <* ignoredTokens+{-# INLINE enumValue #-}  stringValue :: Parser (Value a)-stringValue = label "stringValue" $ Scalar . String <$> parseString+stringValue = Scalar . String <$> parseString+{-# INLINE stringValue #-}  listValue :: Parser a -> Parser [a]-listValue parser = label "list" $ brackets (parser `sepBy` ignoredTokens)+listValue parser = label "List" $ brackets (parser `sepBy` ignoredTokens)+{-# INLINE listValue #-}  objectEntry :: Parser (Value a) -> Parser (ObjectEntry a)-objectEntry parser =-  label "ObjectEntry" $-    ObjectEntry <$> fieldNameColon <*> parser+objectEntry parser = ObjectEntry <$> (parseName <* colon) <*> parser+{-# INLINE objectEntry #-}  objectValue :: Parser (Value a) -> Parser (OrdMap FieldName (ObjectEntry a)) objectValue = label "ObjectValue" . setOf . objectEntry+{-# INLINE objectValue #-}  parsePrimitives :: Parser (Value a) parsePrimitives =-  valueNull <|> booleanValue <|> valueNumber <|> enumValue <|> stringValue+  valueNull+    <|> booleanValue+    <|> valueNumber+    <|> enumValue+    <|> stringValue+{-# INLINE parsePrimitives #-}  parseDefaultValue :: Parser (Value s) parseDefaultValue = equal *> parseV
src/Data/Morpheus/Parsing/Request/Parser.hs view
@@ -14,11 +14,11 @@   ) import Data.HashMap.Lazy (toList) import Data.Morpheus.Ext.Result-  ( Eventless,+  ( GQLResult,   )-import Data.Morpheus.Ext.SafeHashMap (unsafeFromList) import Data.Morpheus.Internal.Utils-  ( empty,+  ( IsMap (unsafeFromList),+    empty,     fromElems,     toLBS,   )@@ -38,8 +38,8 @@ import Data.Morpheus.Types.IO (GQLRequest (..)) import Data.Morpheus.Types.Internal.AST   ( ExecutableDocument (..),-    FieldName (..),     Variables,+    packName,     replaceValue,   ) import Relude hiding@@ -64,7 +64,7 @@       <* ignoredTokens       <* eof -parseRequest :: GQLRequest -> Eventless ExecutableDocument+parseRequest :: GQLRequest -> GQLResult ExecutableDocument parseRequest GQLRequest {query, variables} =   processParser     (parseExecutableDocument $ toVariables variables)@@ -73,5 +73,5 @@     toVariables :: Maybe Aeson.Value -> Variables     toVariables (Just (Aeson.Object x)) = unsafeFromList $ toMorpheusValue <$> toList x       where-        toMorpheusValue (key, value) = (FieldName key, replaceValue value)+        toMorpheusValue (key, value) = (packName key, replaceValue value)     toVariables _ = empty
src/Data/Morpheus/Parsing/Request/Selection.hs view
@@ -31,8 +31,7 @@     spreadLiteral,   ) import Data.Morpheus.Types.Internal.AST-  ( FieldName,-    Fragment (..),+  ( Fragment (..),     Position,     RAW,     Ref (..),@@ -40,6 +39,7 @@     SelectionContent (..),     SelectionSet,   )+import Data.Morpheus.Types.Internal.AST.Name import Relude import Text.Megaparsec   ( label,@@ -125,7 +125,7 @@   fragmentPosition <- spreadLiteral   InlineFragment <$> fragmentBody "INLINE_FRAGMENT" fragmentPosition -fragmentBody :: FieldName -> Position -> Parser (Fragment RAW)+fragmentBody :: FragmentName -> Position -> Parser (Fragment RAW) fragmentBody fragmentName fragmentPosition = label "FragmentBody" $ do   fragmentType <- parseTypeCondition   fragmentDirectives <- optionalDirectives
src/Data/Morpheus/QuasiQuoter.hs view
@@ -38,19 +38,20 @@ import Language.Haskell.TH.Quote import Relude hiding (ByteString) +notSupported :: Text -> a+notSupported things =+  error $+    things+      <> " are not supported by the GraphQL QuasiQuoter"+ gql :: QuasiQuoter gql =   QuasiQuoter     { quoteExp = gqlExpression . pack,-      quotePat = notHandled "Patterns",-      quoteType = notHandled "Types",-      quoteDec = notHandled "Declarations"+      quotePat = notSupported "Patterns",+      quoteType = notSupported "Types",+      quoteDec = notSupported "Declarations"     }-  where-    notHandled things =-      error $-        things-          <> " are not supported by the GraphQL QuasiQuoter"  gqlExpression :: ByteString -> Q Exp gqlExpression queryText = case parseRequest request of@@ -70,14 +71,10 @@ dsl =   QuasiQuoter     { quoteExp = dslExpression . pack,-      quotePat = notHandled "Patterns",-      quoteType = notHandled "Types",-      quoteDec = notHandled "Declarations"+      quotePat = notSupported "Patterns",+      quoteType = notSupported "Types",+      quoteDec = notSupported "Declarations"     }-  where-    notHandled things =-      error $-        things <> " are not supported by the GraphQL QuasiQuoter"  dslExpression :: ByteString -> Q Exp dslExpression doc = case parseSchema doc of
src/Data/Morpheus/Rendering/RenderGQL.hs view
@@ -58,6 +58,10 @@   where   renderGQL = maybe "" renderGQL +instance (RenderGQL l, RenderGQL r) => RenderGQL (Either l r) where+  renderGQL (Left x) = renderGQL x+  renderGQL (Right x) = renderGQL x+ instance RenderGQL ByteString where   renderGQL = Rendering . const @@ -105,8 +109,8 @@ renderObject :: (RenderGQL a) => [a] -> Rendering renderObject fields = space <> "{" <> renderAtNewLine fields <> newline <> "}" -renderMembers :: (RenderGQL a) => [a] -> Rendering-renderMembers members = intercalate (space <> "|" <> space) (fmap renderGQL members)+renderMembers :: (RenderGQL a, Foldable t) => t a -> Rendering+renderMembers members = intercalate (space <> "|" <> space) (fmap renderGQL (toList members))  renderArguments :: (RenderGQL a) => [a] -> Rendering renderArguments arguments
src/Data/Morpheus/Types/GQLScalar.hs view
@@ -40,11 +40,11 @@       pure value  -- | GraphQL Scalar Serializer-class EncodeScalar (a :: *) where+class EncodeScalar (a :: Type) where   encodeScalar :: a -> ScalarValue  -- | GraphQL Scalar parser-class DecodeScalar (a :: *) where+class DecodeScalar (a :: Type) where   -- value parsing and validating   --   -- for exhaustive pattern matching  should be handled all scalar types : 'Int', 'Float', 'String', 'Boolean'
src/Data/Morpheus/Types/ID.hs view
@@ -34,7 +34,8 @@       Generic,       Eq,       Hashable,-      IsString+      IsString,+      Semigroup     )  instance DecodeScalar ID where
src/Data/Morpheus/Types/IO.hs view
@@ -30,6 +30,7 @@ import Data.Morpheus.Types.Internal.AST   ( FieldName,     GQLError (..),+    GQLError,     ValidValue,   ) import Relude hiding@@ -37,8 +38,8 @@     encodeUtf8,   ) -renderResponse :: Result e ValidValue -> GQLResponse-renderResponse (Failure errors) = Errors (sortOn locations errors)+renderResponse :: Result GQLError ValidValue -> GQLResponse+renderResponse (Failure errors) = Errors $ sort $ toList errors renderResponse Success {result} = Data result  -- | GraphQL HTTP Request Body
src/Data/Morpheus/Types/Internal/AST.hs view
@@ -9,8 +9,7 @@   ( Ref (..),     Position (..),     Message,-    anonymousRef,-    FieldName (..),+    FieldName,     Description,     Stage,     CONST,@@ -21,8 +20,6 @@     Object,     replaceValue,     decodeScientific,-    convertToJSONName,-    convertToHaskellName,     RawValue,     ValidValue,     RawObject,@@ -45,14 +42,13 @@     DataEnum,     FieldsDefinition,     ArgumentDefinition (..),-    DataUnion,+    UnionTypeDefinition,     ArgumentsDefinition,     FieldDefinition (..),     InputFieldsDefinition,     TypeContent (..),     TypeDefinition (..),     Schema (..),-    DataTypeWrapper (..),     TypeKind (..),     TypeWrapper (..),     TypeRef (..),@@ -62,18 +58,14 @@     MUTATION,     SUBSCRIPTION,     Directive (..),-    ConsD (..),     TypeCategory (..),-    DataInputUnion,     VariableContent (..),-    TypeLib,+    TypeDefinitions,     initTypeLib,     kindOf,     toNullable,-    toHSWrappers,     isNullable,-    toGQLWrapper,-    isWeaker,+    Subtyping (..),     isNotSystemTypeName,     isLeaf,     isResolverType,@@ -86,7 +78,6 @@     lookupDeprecated,     lookupDeprecatedReason,     lookupWith,-    hsTypeName,     ExecutableDocument (..),     Variables,     unsafeFromFields,@@ -104,20 +95,17 @@     toAny,     TRUE,     FALSE,-    TypeName (..),+    TypeName,     Token,     Msg (..),-    intercalateName,-    toFieldName,+    intercalate,     fieldsToArguments,-    mkConsEnum,     Directives,-    DirectiveDefinitions,+    DirectivesDefinition,     DirectiveDefinition (..),     DirectiveLocation (..),     FieldContent (..),-    fieldContentArgs,-    mkInputValue,+    fieldArguments,     mkType,     mkObjectField,     UnionMember (..),@@ -128,17 +116,10 @@     UnionSelection,     SchemaDefinition (..),     buildSchema,-    InternalError (..),-    ValidationError (..),-    msgInternal,     getOperationDataType,     Typed (Typed),     typed,     untyped,-    msgValidation,-    withPosition,-    ValidationErrors,-    toGQLError,     LEAF,     INPUT_OBJECT,     ToCategory (..),@@ -153,17 +134,34 @@     getInputUnionValue,     unitFieldName,     unitTypeName,+    mkBaseType,+    mkMaybeType,+    isPossibleInterfaceType,+    packName,+    unpackName,+    at,+    atPositions,+    typeDefinitions,+    FragmentName,+    isInternal,+    internal,+    splitSystemSelection,+    lookupDataType,+    Name,+    withPath,   ) where -import Data.Morpheus.Ext.OrdMap (OrdMap (..))-import Data.Morpheus.Ext.SafeHashMap (SafeHashMap)+import Data.Mergeable.OrdMap (OrdMap (..))+import Data.Mergeable.SafeHashMap (SafeHashMap) import Data.Morpheus.Types.Internal.AST.Base import Data.Morpheus.Types.Internal.AST.DirectiveLocation (DirectiveLocation (..))+import Data.Morpheus.Types.Internal.AST.Error import Data.Morpheus.Types.Internal.AST.Fields+import Data.Morpheus.Types.Internal.AST.Name+import Data.Morpheus.Types.Internal.AST.OperationType import Data.Morpheus.Types.Internal.AST.Selection import Data.Morpheus.Types.Internal.AST.Stage-import Data.Morpheus.Types.Internal.AST.TH import Data.Morpheus.Types.Internal.AST.Type import Data.Morpheus.Types.Internal.AST.TypeCategory import Data.Morpheus.Types.Internal.AST.TypeSystem
src/Data/Morpheus/Types/Internal/AST/Base.hs view
@@ -5,76 +5,25 @@ {-# LANGUAGE DeriveLift #-} {-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Types.Internal.AST.Base   ( Ref (..),     Position (..),-    Message (..),-    FieldName (..),     Description,-    OperationType (..),-    QUERY,-    MUTATION,-    SUBSCRIPTION,     Token,-    isNotSystemTypeName,-    sysFields,-    hsTypeName,-    toOperationType,-    GQLError (..),-    GQLErrors,     TRUE,     FALSE,-    TypeName (..),-    Msg (..),-    intercalateName,-    toFieldName,-    convertToJSONName,-    convertToHaskellName,-    InternalError (..),-    msgInternal,-    ValidationError (..),-    msgValidation,-    ValidationErrors,-    withPosition,-    toGQLError,-    unitTypeName,-    unitFieldName,-    anonymousRef,   ) where  import Data.Aeson   ( FromJSON,-    ToJSON,-    Value,-    encode,-  )-import Data.ByteString.Lazy (ByteString)-import Data.Char (toLower)-import Data.Morpheus.Rendering.RenderGQL-  ( RenderGQL (..),-    fromText,-    renderGQL,-  )-import Data.Text (intercalate, pack)-import qualified Data.Text as T-import qualified Data.Text.Lazy as LT-import Data.Text.Lazy.Encoding (decodeUtf8)-import Language.Haskell.TH-  ( ExpQ,-    stringE,+    ToJSON (..),   ) import Language.Haskell.TH.Syntax   ( Lift (..),-    Q,-    TExp,-    unsafeTExpCoerce,   ) import Relude hiding   ( ByteString,@@ -89,145 +38,6 @@ -- Strings type Token = Text --- Error / Warning Messages-newtype Message = Message {readMessage :: Text}-  deriving-    (Generic)-  deriving newtype-    (Show, Eq, Ord, IsString, Semigroup, Hashable, FromJSON, ToJSON)--instance Lift Message where-  lift = liftString . readMessage--#if MIN_VERSION_template_haskell(2,16,0)-  liftTyped = liftTypedString . readMessage-#endif--newtype InternalError = InternalError-  { readInternalError :: Text-  }-  deriving-    (Generic)-  deriving newtype-    (Show, Eq, Ord, IsString, Semigroup, Hashable, FromJSON, ToJSON)--data ValidationError = ValidationError-  { validationMessage :: Message,-    validationLocations :: [Position]-  }-  deriving (Show)--instance IsString ValidationError where-  fromString = (`ValidationError` []) . msg--instance Semigroup ValidationError where-  ValidationError m1 p1 <> ValidationError m2 p2 =-    ValidationError (m1 <> m2) (p1 <> p2)--withPosition :: Maybe Position -> ValidationError -> ValidationError-withPosition pos (ValidationError m ps) = ValidationError m (ps <> maybeToList pos)--type ValidationErrors = [ValidationError]--toGQLError :: ValidationError -> GQLError-toGQLError (ValidationError m p) = GQLError m p---- instance Lift InternalError where---   lift = liftString . readInternalError---- #if MIN_VERSION_template_haskell(2,16,0)---   liftTyped = liftTypedString . readInternalError--- #endif--msgInternal :: (Msg a) => a -> InternalError-msgInternal = InternalError . readMessage . msg--msgValidation :: (Msg a) => a -> ValidationError-msgValidation = (`ValidationError` []) . msg--class Msg a where-  msg :: a -> Message-  msgSepBy :: Text -> [a] -> Message-  msgSepBy t = Message . intercalate t . fmap (readMessage . msg)--instance Msg Message where-  msg = id--instance Msg InternalError where-  msg = Message . ("Internal Error! " <>) . readInternalError--instance Msg String where-  msg = Message . pack--instance Msg ByteString where-  msg = Message . LT.toStrict . decodeUtf8--instance Msg Text where-  msg = Message--instance Msg Value where-  msg = msg . encode---- FieldName : lower case names-newtype FieldName = FieldName {readName :: Text}-  deriving-    (Generic)-  deriving newtype-    (Show, Ord, Eq, IsString, Hashable, Semigroup, FromJSON, ToJSON)--instance Lift FieldName where-  lift = liftString . readName--#if MIN_VERSION_template_haskell(2,16,0)-  liftTyped = liftTypedString . readName-#endif--instance Msg FieldName where-  msg FieldName {readName} = Message $ "\"" <> readName <> "\""--instance RenderGQL FieldName where-  renderGQL = fromText . readName--intercalateName :: FieldName -> [FieldName] -> FieldName-intercalateName (FieldName x) = FieldName . intercalate x . fmap readName--toFieldName :: TypeName -> FieldName-toFieldName = FieldName . readTypeName---- TypeName-newtype TypeName = TypeName {readTypeName :: Text}-  deriving-    (Generic)-  deriving newtype-    ( Show,-      Ord,-      Eq,-      IsString,-      Hashable,-      Semigroup,-      FromJSON,-      ToJSON-    )--instance Lift TypeName where-  lift = liftString . readTypeName--#if MIN_VERSION_template_haskell(2,16,0)-  liftTyped = liftTypedString . readTypeName-#endif--liftTypedString :: IsString a => Token -> Q (TExp a)-liftTypedString = unsafeTExpCoerce . stringE . T.unpack--liftString :: Token -> ExpQ-liftString = stringE . T.unpack--instance Msg TypeName where-  msg TypeName {readTypeName} = Message $ "\"" <> readTypeName <> "\""--instance RenderGQL TypeName where-  renderGQL = fromText . readTypeName- -- Description type Description = Text @@ -235,48 +45,27 @@   { line :: Int,     column :: Int   }-  deriving (Show, Generic, FromJSON, ToJSON, Lift)--instance Ord Position where-  compare x y = compare (line x) (line y)+  deriving+    ( Show,+      Generic,+      FromJSON,+      ToJSON,+      Lift+    )  -- Positions 2 Value with same structure -- but different Positions should be Equal instance Eq Position where   _ == _ = True -data GQLError = GQLError-  { message :: Message,-    locations :: [Position]-  }-  deriving (Show, Eq, Generic, FromJSON, ToJSON)--type GQLErrors = [GQLError]--data OperationType-  = Query-  | Subscription-  | Mutation-  deriving (Show, Eq, Lift, Generic, Hashable)--instance RenderGQL OperationType where-  renderGQL = fromString . fmap toLower . show--instance Msg OperationType where-  msg Query = msg ("query" :: TypeName)-  msg Mutation = msg ("mutation" :: TypeName)-  msg Subscription = msg ("subscription" :: TypeName)--type QUERY = 'Query--type MUTATION = 'Mutation--type SUBSCRIPTION = 'Subscription+instance Ord Position where+  compare (Position l1 c1) (Position l2 c2) = compare l1 l2 <> compare c1 c2 --- Document Reference with its Position--- Position  only for error messages--- includes position for debugging, where Ref "a" 1 === Ref "a" 3+-- | Document Reference with its Position --+-- Position is used only for error messages. that means:+--+-- Ref "a" 1 === Ref "a" 3 data Ref name = Ref   { refName :: name,     refPosition :: Position@@ -285,85 +74,3 @@  instance Ord name => Ord (Ref name) where   compare (Ref x _) (Ref y _) = compare x y--anonymousRef :: name -> Ref name-anonymousRef refName = Ref {refName, refPosition = Position 0 0}--isNotSystemTypeName :: TypeName -> Bool-isNotSystemTypeName =-  ( `notElem`-      [ "__Schema",-        "__Type",-        "__Directive",-        "__TypeKind",-        "__Field",-        "__DirectiveLocation",-        "__InputValue",-        "__EnumValue",-        "String",-        "Float",-        "Int",-        "Boolean",-        "ID"-      ]-  )--sysFields :: [FieldName]-sysFields = ["__typename", "__schema", "__type"]--hsTypeName :: TypeName -> TypeName-hsTypeName "String" = "Text"-hsTypeName "Boolean" = "Bool"-hsTypeName name = name--toOperationType :: TypeName -> Maybe OperationType-toOperationType "Subscription" = Just Subscription-toOperationType "Mutation" = Just Mutation-toOperationType "Query" = Just Query-toOperationType _ = Nothing---- handle reserved Names-isReserved :: FieldName -> Bool-isReserved "case" = True-isReserved "class" = True-isReserved "data" = True-isReserved "default" = True-isReserved "deriving" = True-isReserved "do" = True-isReserved "else" = True-isReserved "foreign" = True-isReserved "if" = True-isReserved "import" = True-isReserved "in" = True-isReserved "infix" = True-isReserved "infixl" = True-isReserved "infixr" = True-isReserved "instance" = True-isReserved "let" = True-isReserved "module" = True-isReserved "newtype" = True-isReserved "of" = True-isReserved "then" = True-isReserved "type" = True-isReserved "where" = True-isReserved "_" = True-isReserved _ = False-{-# INLINE isReserved #-}--convertToJSONName :: FieldName -> FieldName-convertToJSONName (FieldName hsName)-  | not (T.null hsName) && isReserved (FieldName name) && (T.last hsName == '\'') = FieldName name-  | otherwise = FieldName hsName-  where-    name = T.init hsName--convertToHaskellName :: FieldName -> FieldName-convertToHaskellName name-  | isReserved name = name <> "'"-  | otherwise = name--unitTypeName :: TypeName-unitTypeName = "Unit"--unitFieldName :: FieldName-unitFieldName = "_"
src/Data/Morpheus/Types/Internal/AST/DirectiveLocation.hs view
@@ -6,7 +6,7 @@   ) where -import Data.Morpheus.Types.Internal.AST.Base (Msg (..))+import Data.Morpheus.Types.Internal.AST.Error (Msg (..)) import Language.Haskell.TH.Syntax (Lift) import Relude hiding (Show, show) import Prelude (Show (..))
+ src/Data/Morpheus/Types/Internal/AST/Error.hs view
@@ -0,0 +1,138 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE NoImplicitPrelude #-}++module Data.Morpheus.Types.Internal.AST.Error+  ( at,+    atPositions,+    internal,+    isInternal,+    GQLErrors,+    GQLError+      ( message,+        locations+      ),+    manyMsg,+    Msg (..),+    Message,+    withPath,+  )+where++import Data.Aeson+  ( FromJSON,+    Options (..),+    ToJSON (..),+    Value,+    defaultOptions,+    encode,+    genericToJSON,+  )+import Data.ByteString.Lazy (ByteString)+import Data.Morpheus.Types.Internal.AST.Base+  ( Position (..),+  )+import qualified Data.Text as T+import qualified Data.Text.Lazy as LT+import Data.Text.Lazy.Encoding (decodeUtf8)+import Relude hiding (ByteString, decodeUtf8)++type Message = Text++internal :: GQLError -> GQLError+internal x = x {errorType = Just Internal}++isInternal :: GQLError -> Bool+isInternal GQLError {errorType = Just Internal} = True+isInternal _ = False++at :: GQLError -> Position -> GQLError+at err pos = atPositions err [pos]+{-# INLINE at #-}++atPositions :: Foldable t => GQLError -> t Position -> GQLError+atPositions GQLError {..} pos = case toList pos of+  [] -> GQLError {..}+  posList -> GQLError {locations = locations <> Just posList, ..}+{-# INLINE atPositions #-}++withPath :: GQLError -> [Text] -> GQLError+withPath err [] = err+withPath err path = err {path = Just path}++manyMsg :: (Foldable t, Msg a) => t a -> GQLError+manyMsg =+  msg . T.intercalate ", "+    . fmap (message . msg)+    . toList++data ErrorType = Internal+  deriving+    ( Show,+      Eq,+      Generic,+      FromJSON,+      ToJSON+    )++instance Semigroup ErrorType where+  Internal <> Internal = Internal++data GQLError = GQLError+  { message :: Message,+    locations :: Maybe [Position],+    path :: Maybe [Text],+    errorType :: Maybe ErrorType,+    extensions :: Maybe (Map Text Value)+  }+  deriving+    ( Show,+      Eq,+      Generic,+      FromJSON+    )++instance Ord GQLError where+  compare x y = compare (locations x) (locations y) <> compare (message x) (message y)++instance IsString GQLError where+  fromString = msg++instance ToJSON GQLError where+  toJSON = genericToJSON (defaultOptions {omitNothingFields = True})++instance Semigroup GQLError where+  GQLError m1 l1 p1 t1 e1 <> GQLError m2 l2 p2 t2 e2 = GQLError (m1 <> m2) (l1 <> l2) (p1 <> p2) (t1 <> t2) (e1 <> e2)++type GQLErrors = NonEmpty GQLError++class Msg a where+  msg :: a -> GQLError++instance Msg GQLError where+  msg = id++instance Msg String where+  msg = msg . T.pack++instance Msg Text where+  msg message =+    GQLError+      { message,+        locations = Nothing,+        errorType = Nothing,+        extensions = Nothing,+        path = Nothing+      }++instance Msg ByteString where+  msg = msg . LT.toStrict . decodeUtf8++instance Msg Value where+  msg = msg . encode
src/Data/Morpheus/Types/Internal/AST/Fields.hs view
@@ -23,7 +23,7 @@     FieldsDefinition,     FieldContent (..),     InputFieldsDefinition,-    DirectiveDefinitions,+    DirectivesDefinition,     DirectiveDefinition (..),     Directives,     Directive (..),@@ -32,8 +32,7 @@     lookupDeprecatedReason,     unsafeFromFields,     fieldsToArguments,-    fieldContentArgs,-    mkInputValue,+    fieldArguments,     mkObjectField,     mkField,     renderArgumentValues,@@ -41,19 +40,17 @@   ) where -import Data.Morpheus.Error.NameCollision-  ( NameCollision (..),-  )-import Data.Morpheus.Ext.OrdMap-  ( OrdMap,-    unsafeFromList,+import Data.Mergeable+  ( IsMap (lookup),+    NameCollision (..),+    OrdMap,   ) import Data.Morpheus.Internal.Utils-  ( Elems (..),-    Empty (..),+  ( Empty (..),     KeyOf (..),-    Selectable (..),+    selectOr,     toPair,+    unsafeFromList,   ) import Data.Morpheus.Rendering.RenderGQL   ( RenderGQL (..),@@ -66,17 +63,20 @@   ) import Data.Morpheus.Types.Internal.AST.Base   ( Description,-    FieldName,-    FieldName (..),-    Msg (..),     Position,     TRUE,-    TypeName,-    ValidationError (..),-    msgValidation,-    sysFields,   ) import Data.Morpheus.Types.Internal.AST.DirectiveLocation (DirectiveLocation)+import Data.Morpheus.Types.Internal.AST.Error+  ( GQLError,+    at,+    msg,+  )+import Data.Morpheus.Types.Internal.AST.Name+  ( FieldName,+    TypeName,+    isNotSystemFieldName,+  ) import Data.Morpheus.Types.Internal.AST.Stage   ( Stage,   )@@ -118,17 +118,15 @@   renderGQL Argument {argumentName, argumentValue} =     renderEntry argumentName argumentValue -instance NameCollision (Argument s) where+instance NameCollision GQLError (Argument s) where   nameCollision Argument {argumentName, argumentPosition} =-    ValidationError-      { validationMessage = "There can Be only One Argument Named " <> msg argumentName,-        validationLocations = [argumentPosition]-      }+    ("There can Be only One Argument Named " <> msg argumentName)+      `at` argumentPosition  type Arguments (s :: Stage) = OrdMap FieldName (Argument s)  renderArgumentValues :: Arguments s -> Rendering-renderArgumentValues = renderArguments . filter notNull . elems+renderArgumentValues = renderArguments . filter notNull . toList   where     notNull Argument {argumentValue = Null} = False     notNull _ = True@@ -142,6 +140,12 @@   }   deriving (Show, Lift, Eq) +instance NameCollision GQLError (Directive s) where+  nameCollision Directive {directiveName} =+    "The directive "+      <> msg ("@" <> directiveName)+      <> " can only be used once at his location."+ instance KeyOf FieldName (Directive s) where   keyOf = directiveName @@ -150,14 +154,14 @@     "@" <> renderGQL directiveName       <> renderArgumentValues directiveArgs -type Directives s = [Directive s]+type Directives s = OrdMap FieldName (Directive s)  renderDirectives :: Directives s -> Rendering renderDirectives xs   | null dirs = ""   | otherwise = space <> intercalate space (fmap renderGQL dirs)   where-    dirs = filter notSystem xs+    dirs = filter notSystem (toList xs)     notSystem Directive {directiveName = "include"} = False     notSystem Directive {directiveName = "skip"} = False     notSystem _ = True@@ -170,20 +174,22 @@   }   deriving (Show, Lift) -type DirectiveDefinitions s = [DirectiveDefinition s]+instance NameCollision GQLError (DirectiveDefinition s) where+  nameCollision DirectiveDefinition {directiveDefinitionName} =+    "There can Be only One DirectiveDefinition Named "+      <> msg directiveDefinitionName+      <> "." +type DirectivesDefinition s = OrdMap FieldName (DirectiveDefinition s)+ instance KeyOf FieldName (DirectiveDefinition s) where   keyOf = directiveDefinitionName -instance Selectable FieldName (ArgumentDefinition s) (DirectiveDefinition s) where-  selectOr fb f key DirectiveDefinition {directiveDefinitionArgs} =-    selectOr fb f key directiveDefinitionArgs+-- instance IsMap FieldName (ArgumentDefinition s) (DirectiveDefinition s) where+--   lookup key DirectiveDefinition {directiveDefinitionArgs} = lookup key directiveDefinitionArgs -lookupDeprecated :: [Directive s] -> Maybe (Directive s)-lookupDeprecated = find isDeprecation-  where-    isDeprecation Directive {directiveName = "deprecated"} = True-    isDeprecation _ = False+lookupDeprecated :: Directives s -> Maybe (Directive s)+lookupDeprecated = lookup "deprecated"  lookupDeprecatedReason :: Directive s -> Maybe Description lookupDeprecatedReason Directive {directiveArgs} =@@ -236,7 +242,7 @@     fieldName :: FieldName,     fieldType :: TypeRef,     fieldContent :: Maybe (FieldContent TRUE cat s),-    fieldDirectives :: [Directive s]+    fieldDirectives :: Directives s   }   deriving (Show, Lift, Eq) @@ -250,9 +256,9 @@     } ->     FieldContent (OUT <=? cat) cat s -fieldContentArgs :: FieldContent b cat s -> ArgumentsDefinition s-fieldContentArgs (FieldArgs args) = args-fieldContentArgs _ = empty+fieldArguments :: FieldDefinition c s -> ArgumentsDefinition s+fieldArguments FieldDefinition {fieldContent = Just (FieldArgs args)} = args+fieldArguments _ = empty  deriving instance Eq (FieldContent bool cat s) @@ -263,13 +269,9 @@ instance KeyOf FieldName (FieldDefinition cat s) where   keyOf = fieldName -instance Selectable FieldName (ArgumentDefinition s) (FieldDefinition OUT s) where-  selectOr fb f key FieldDefinition {fieldContent = Just (FieldArgs args)} = selectOr fb f key args-  selectOr fb _ _ _ = fb--instance NameCollision (FieldDefinition cat s) where+instance NameCollision GQLError (FieldDefinition cat s) where   nameCollision FieldDefinition {fieldName} =-    "There can Be only One field Named " <> msgValidation fieldName+    "There can Be only One field Named " <> msg fieldName  instance RenderGQL (FieldDefinition cat s) where   renderGQL FieldDefinition {fieldName, fieldType, fieldContent = Just (FieldArgs args)} =@@ -278,14 +280,14 @@     renderEntry fieldName fieldType  instance RenderGQL (FieldsDefinition cat s) where-  renderGQL = renderObject . filter fieldVisibility . elems+  renderGQL = renderObject . filter fieldVisibility . toList  instance Nullable (FieldDefinition cat s) where   isNullable = isNullable . fieldType   toNullable field = field {fieldType = toNullable (fieldType field)}  fieldVisibility :: FieldDefinition cat s -> Bool-fieldVisibility FieldDefinition {fieldName} = fieldName `notElem` sysFields+fieldVisibility = isNotSystemFieldName . fieldName  mkField ::   Maybe (FieldContent TRUE cat s) ->@@ -298,20 +300,13 @@       fieldContent,       fieldDescription = Nothing,       fieldType,-      fieldDirectives = []+      fieldDirectives = empty     } -mkInputValue :: FieldName -> [TypeWrapper] -> TypeName -> FieldDefinition cat s-mkInputValue fieldName typeWrappers typeConName =-  mkField-    Nothing-    fieldName-    TypeRef {typeWrappers, typeConName}- mkObjectField ::   ArgumentsDefinition s ->   FieldName ->-  [TypeWrapper] ->+  TypeWrapper ->   TypeName ->   FieldDefinition OUT s mkObjectField args fieldName typeWrappers typeConName =@@ -337,7 +332,7 @@ type ArgumentsDefinition s = OrdMap FieldName (ArgumentDefinition s)  instance RenderGQL (ArgumentsDefinition s) where-  renderGQL = renderArguments . elems+  renderGQL = renderArguments . toList  instance RenderGQL (ArgumentDefinition s) where   renderGQL = renderGQL . argument@@ -350,6 +345,6 @@ instance KeyOf FieldName (ArgumentDefinition s) where   keyOf = keyOf . argument -instance NameCollision (ArgumentDefinition s) where+instance NameCollision GQLError (ArgumentDefinition s) where   nameCollision ArgumentDefinition {argument} =-    "There can Be only One argument Named " <> msgValidation (fieldName argument)+    "There can Be only One argument Named " <> msg (fieldName argument)
+ src/Data/Morpheus/Types/Internal/AST/Name.hs view
@@ -0,0 +1,160 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DerivingStrategies #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE NoImplicitPrelude #-}++module Data.Morpheus.Types.Internal.AST.Name+  ( Name,+    packName,+    unpackName,+    FieldName,+    TypeName,+    unitTypeName,+    unitFieldName,+    isNotSystemTypeName,+    isNotSystemFieldName,+    intercalate,+    NAME (..),+    FragmentName,+  )+where++import Data.Aeson+  ( FromJSON,+    ToJSON (..),+  )+import Data.Morpheus.Rendering.RenderGQL+  ( RenderGQL (..),+    fromText,+    renderGQL,+  )+import Data.Morpheus.Types.Internal.AST.Error+  ( Msg (..),+  )+import qualified Data.Text as T+#if MIN_VERSION_template_haskell(2,17,0)+import Language.Haskell.TH+  ( Quote,+    Code,+    unsafeCodeCoerce,+    stringE+  )+import Language.Haskell.TH.Syntax(+    Lift(..)+  )+# else+import Language.Haskell.TH+  ( stringE,+  )+import Language.Haskell.TH.Syntax+  ( Lift (..),+    Q,+    TExp,+    unsafeTExpCoerce,+  )+#endif+import Relude hiding+  ( ByteString,+    decodeUtf8,+    intercalate,+  )++data NAME+  = TYPE+  | FIELD+  | FRAGMENT++newtype Name (t :: NAME) = Name {unpackName :: Text}+  deriving+    (Generic)+  deriving newtype+    ( Show,+      Ord,+      Eq,+      IsString,+      ToString,+      Hashable,+      Semigroup,+      FromJSON,+      ToJSON+    )++instance Msg (Name t) where+  msg name = msg $ "\"" <> unpackName name <> "\""++packName :: Text -> Name t+packName = Name++instance Lift (Name t) where+  lift = stringE . T.unpack . unpackName++#if MIN_VERSION_template_haskell(2,17,0)+  liftTyped = liftTypedString . unpackName+    where+      liftTypedString :: (Quote m) => Text -> Code m (Name t)+      liftTypedString = unsafeCodeCoerce . stringE . T.unpack+      {-# INLINE liftTypedString #-}+#elif MIN_VERSION_template_haskell(2,16,0)+  liftTyped = liftTypedString . unpackName+    where+      liftTypedString :: IsString a => Text -> Q (TExp a)+      liftTypedString = unsafeTExpCoerce . stringE . T.unpack+      {-# INLINE liftTypedString #-}+#endif++instance RenderGQL (Name a) where+  renderGQL = fromText . unpackName++type FieldName = Name 'FIELD++type TypeName = Name 'TYPE++type FragmentName = Name 'FRAGMENT++intercalate :: Name t1 -> [Name t2] -> Name t3+intercalate (Name x) = Name . T.intercalate x . fmap unpackName+{-# INLINE intercalate #-}++unitTypeName :: TypeName+unitTypeName = "Unit"+{-# INLINE unitTypeName #-}++unitFieldName :: FieldName+unitFieldName = "_"+{-# INLINE unitFieldName #-}++isNotSystemTypeName :: TypeName -> Bool+isNotSystemTypeName =+  ( `notElem`+      [ "__Schema",+        "__Type",+        "__Directive",+        "__TypeKind",+        "__Field",+        "__DirectiveLocation",+        "__InputValue",+        "__EnumValue",+        "String",+        "Float",+        "Int",+        "Boolean",+        "ID"+      ]+  )+{-# INLINE isNotSystemTypeName #-}++isNotSystemFieldName :: FieldName -> Bool+isNotSystemFieldName =+  ( `notElem`+      [ "__typename",+        "__schema",+        "__type"+      ]+  )+{-# INLINE isNotSystemFieldName #-}
+ src/Data/Morpheus/Types/Internal/AST/OperationType.hs view
@@ -0,0 +1,63 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveLift #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE NoImplicitPrelude #-}++module Data.Morpheus.Types.Internal.AST.OperationType+  ( OperationType (..),+    QUERY,+    MUTATION,+    SUBSCRIPTION,+    toOperationType,+  )+where++import Data.Char (toLower)+import Data.Morpheus.Rendering.RenderGQL+  ( RenderGQL (..),+  )+import Data.Morpheus.Types.Internal.AST.Error (Msg (..))+import Data.Morpheus.Types.Internal.AST.Name (TypeName)+import Language.Haskell.TH.Syntax+  ( Lift,+  )+import Relude hiding+  ( ByteString,+    decodeUtf8,+    intercalate,+  )++type QUERY = 'Query++type MUTATION = 'Mutation++type SUBSCRIPTION = 'Subscription++data OperationType+  = Query+  | Subscription+  | Mutation+  deriving+    ( Show,+      Eq,+      Lift,+      Generic,+      Hashable+    )++instance RenderGQL OperationType where+  renderGQL = fromString . fmap toLower . show++toOperationType :: TypeName -> Maybe OperationType+toOperationType "Subscription" = Just Subscription+toOperationType "Mutation" = Just Mutation+toOperationType "Query" = Just Query+toOperationType _ = Nothing+{-# INLINE toOperationType #-}++instance Msg OperationType where+  msg Query = msg ("query" :: TypeName)+  msg Mutation = msg ("mutation" :: TypeName)+  msg Subscription = msg ("subscription" :: TypeName)
src/Data/Morpheus/Types/Internal/AST/Selection.hs view
@@ -26,28 +26,28 @@     DefaultValue,     getOperationName,     getOperationDataType,+    splitSystemSelection,   ) where +import Control.Monad.Except (MonadError (throwError)) import Data.Foldable (foldr')-import Data.Morpheus.Error.NameCollision-  ( NameCollision (..),+import Data.Mergeable+  ( Merge (..),+    MergeMap,+    NameCollision (..),+    OrdMap,   )+import Data.Mergeable.MergeMap (partition) import Data.Morpheus.Error.Operation   ( mutationIsNotDefined,     subscriptionIsNotDefined,   )-import Data.Morpheus.Ext.MergeSet-  ( MergeSet,-  )-import Data.Morpheus.Ext.OrdMap-  ( OrdMap,-  )-import Data.Morpheus.Ext.SemigroupM (SemigroupM (..)) import Data.Morpheus.Internal.Utils-  ( Failure (..),+  ( (<:>),+    HistoryT,     KeyOf (..),-    elems,+    addPath,   ) import Data.Morpheus.Rendering.RenderGQL   ( RenderGQL (..),@@ -57,19 +57,14 @@     space,   ) import Data.Morpheus.Types.Internal.AST.Base-  ( FieldName,-    Message,-    Msg (..),-    OperationType (..),-    Position,+  ( Position,     Ref (..),-    TypeName (..),-    ValidationError (..),-    ValidationErrors,-    intercalateName,+  )+import Data.Morpheus.Types.Internal.AST.Error+  ( GQLError,+    at,+    atPositions,     msg,-    msgValidation,-    readName,   ) import Data.Morpheus.Types.Internal.AST.Fields   ( Arguments,@@ -77,8 +72,17 @@     renderArgumentValues,     renderDirectives,   )+import Data.Morpheus.Types.Internal.AST.Name+  ( FieldName,+    FragmentName,+    TypeName,+    intercalate,+    isNotSystemFieldName,+  )+import Data.Morpheus.Types.Internal.AST.OperationType (OperationType (..)) import Data.Morpheus.Types.Internal.AST.Stage-  ( RAW,+  ( ALLOW_DUPLICATES,+    RAW,     Stage,     VALID,   )@@ -95,10 +99,11 @@     VariableDefinitions,   ) import Language.Haskell.TH.Syntax (Lift (..))-import Relude+import Relude hiding (intercalate, show)+import Prelude (show)  data Fragment (stage :: Stage) = Fragment-  { fragmentName :: FieldName,+  { fragmentName :: FragmentName,     fragmentType :: TypeName,     fragmentPosition :: Position,     fragmentSelection :: SelectionSet stage,@@ -107,48 +112,56 @@   deriving (Show, Eq, Lift)  -- ERRORs-instance NameCollision (Fragment s) where+instance NameCollision GQLError (Fragment s) where   nameCollision Fragment {fragmentName, fragmentPosition} =-    ValidationError-      ("There can be only one fragment named " <> msg fragmentName <> ".")-      [fragmentPosition]+    ("There can be only one fragment named " <> msg fragmentName <> ".")+      `at` fragmentPosition -instance KeyOf FieldName (Fragment s) where+instance KeyOf FragmentName (Fragment s) where   keyOf = fragmentName -type Fragments (s :: Stage) = OrdMap FieldName (Fragment s)+type Fragments (s :: Stage) = OrdMap FragmentName (Fragment s)  data SelectionContent (s :: Stage) where   SelectionField :: SelectionContent s   SelectionSet :: SelectionSet s -> SelectionContent s-  UnionSelection :: UnionSelection VALID -> SelectionContent VALID+  UnionSelection ::+    { defaultSelection :: SelectionSet VALID,+      conditionalSelections :: UnionSelection VALID+    } ->+    SelectionContent VALID  renderSelectionSet :: SelectionSet VALID -> Rendering-renderSelectionSet = renderObject . elems+renderSelectionSet = renderObject . toList  instance RenderGQL (SelectionContent VALID) where   renderGQL SelectionField = ""   renderGQL (SelectionSet selSet) = renderSelectionSet selSet-  renderGQL (UnionSelection unionSets) = renderObject (elems unionSets)+  renderGQL (UnionSelection interfaceFields unionSets) =+    renderObject unionSelectionElements+    where+      unionSelectionElements :: [Either (Selection VALID) UnionTag]+      unionSelectionElements =+        map Left (toList interfaceFields)+          <> map Right (sortOn unionTagName $ toList unionSets)  instance   ( Monad m,-    Failure ValidationErrors m,-    SemigroupM m (SelectionSet s)+    MonadError GQLError m,+    Merge (HistoryT m) (SelectionSet s)   ) =>-  SemigroupM m (SelectionContent s)+  Merge (HistoryT m) (SelectionContent s)   where-  mergeM path (SelectionSet s1) (SelectionSet s2) = SelectionSet <$> mergeM path s1 s2-  mergeM path (UnionSelection u1) (UnionSelection u2) = UnionSelection <$> mergeM path u1 u2-  mergeM path oldC currentC+  merge (SelectionSet s1) (SelectionSet s2) = SelectionSet <$> merge s1 s2+  merge (UnionSelection m1 u1) (UnionSelection m2 u2) = UnionSelection <$> merge m1 m2 <*> merge u1 u2+  merge oldC currentC     | oldC == currentC = pure oldC-    | otherwise =-      failure-        [ ValidationError-            { validationMessage = msg (intercalateName "." $ fmap refName path),-              validationLocations = fmap refPosition path-            }-        ]+    | otherwise = do+      path <- ask+      throwError+        ( msg (intercalate "." $ fmap refName path)+            `atPositions` fmap refPosition path+        )  deriving instance Show (SelectionContent a) @@ -171,32 +184,42 @@       <> renderGQL unionTagName       <> renderSelectionSet unionTagSelection -mergeConflict :: [Ref FieldName] -> ValidationError -> ValidationErrors-mergeConflict [] err = [err]-mergeConflict refs@(rootField : xs) err =-  [ ValidationError-      { validationMessage = renderSubfields <> validationMessage err,-        validationLocations = fmap refPosition refs <> validationLocations err-      }-  ]+mergeConflict :: (Monad m, MonadError GQLError m) => GQLError -> HistoryT m a+mergeConflict err = do+  path <- ask+  __mergeConflict path   where-    fieldConflicts ref = msg (refName ref) <> " conflict because "-    renderSubfield ref txt = txt <> "subfields " <> fieldConflicts ref-    renderStart = "Fields " <> fieldConflicts rootField-    renderSubfields =-      foldr'-        renderSubfield-        renderStart-        xs+    __mergeConflict :: (Monad m, MonadError GQLError m) => [Ref FieldName] -> HistoryT m a+    __mergeConflict [] = throwError err+    __mergeConflict refs@(rootField : xs) =+      throwError+        (renderSubfields `atPositions` fmap refPosition refs <> err)+      where+        fieldConflicts ref = msg (refName ref) <> " conflict because "+        renderSubfield ref txt = txt <> "subfields " <> fieldConflicts ref+        renderStart = "Fields " <> fieldConflicts rootField+        renderSubfields =+          foldr'+            renderSubfield+            renderStart+            xs -instance (Monad m, Failure ValidationErrors m) => SemigroupM m UnionTag where-  mergeM path (UnionTag oldTag oldSel) (UnionTag _ currentSel) =-    UnionTag oldTag <$> mergeM path oldSel currentSel+instance+  ( Monad m,+    MonadError GQLError m+  ) =>+  Merge (HistoryT m) UnionTag+  where+  merge (UnionTag oldTag oldSel) (UnionTag _ currentSel) =+    UnionTag oldTag <$> merge oldSel currentSel -type UnionSelection (s :: Stage) = MergeSet s TypeName UnionTag+type UnionSelection (s :: Stage) = MergeMap (ALLOW_DUPLICATES s) TypeName UnionTag -type SelectionSet (s :: Stage) = MergeSet s FieldName (Selection s)+type SelectionSet (s :: Stage) = MergeMap (ALLOW_DUPLICATES s) FieldName (Selection s) +splitSystemSelection :: SelectionSet s -> (Maybe (SelectionSet s), Maybe (SelectionSet s))+splitSystemSelection = partition (not . isNotSystemFieldName . selectionName)+ data Selection (s :: Stage) where   Selection ::     { selectionPosition :: Position,@@ -208,7 +231,7 @@     } ->     Selection s   InlineFragment :: Fragment RAW -> Selection RAW-  Spread :: Directives RAW -> Ref FieldName -> Selection RAW+  Spread :: Directives RAW -> Ref FragmentName -> Selection RAW  instance RenderGQL (Selection VALID) where   renderGQL@@ -228,76 +251,81 @@       } = fromMaybe selectionName selectionAlias   keyOf _ = "" -useDifferentAliases :: Message+useDifferentAliases :: GQLError useDifferentAliases =   "Use different aliases on the "     <> "fields to fetch both if this was intentional."  instance   ( Monad m,-    SemigroupM m (SelectionSet a),-    Failure ValidationErrors m+    MonadError GQLError m,+    Merge (HistoryT m) (SelectionSet s)   ) =>-  SemigroupM m (Selection a)+  Merge (HistoryT m) (Selection s)   where-  mergeM-    path-    old@Selection {selectionPosition = pos1}-    current@Selection {selectionPosition = pos2} =-      do-        selectionName <- mergeName-        let currentPath = path <> [Ref selectionName pos1]-        selectionArguments <- mergeArguments currentPath-        selectionContent <- mergeM currentPath (selectionContent old) (selectionContent current)+  merge = mergeSelection++mergeSelection ::+  ( Monad m,+    MonadError GQLError m,+    Merge (HistoryT m) (SelectionSet s)+  ) =>+  Selection s ->+  Selection s ->+  HistoryT m (Selection s)+mergeSelection+  old@Selection {selectionPosition = pos1}+  current@Selection {selectionPosition = pos2} =+    do+      selectionName <- mergeName [pos1, pos2] old current+      addPath (Ref selectionName pos1) $ do+        selectionArguments <- mergeArguments+        selectionContent <- merge (selectionContent old) (selectionContent current)+        dirs <- selectionDirectives old <:> selectionDirectives current         pure $           Selection             { selectionAlias = mergeAlias,               selectionPosition = pos1,-              selectionDirectives = selectionDirectives old <> selectionDirectives current,+              selectionDirectives = dirs,               ..             }-      where-        -- passes if:+    where+      mergeAlias+        | all (isJust . selectionAlias) [old, current] = selectionAlias old+        | otherwise = Nothing+      --- arguments must be equal+      mergeArguments+        | selectionArguments old == selectionArguments current = pure $ selectionArguments current+        | otherwise =+          mergeConflict $+            ("they have differing arguments. " <> useDifferentAliases)+              `atPositions` [pos1, pos2]+mergeSelection x y = mergeConflict ("INTERNAL: can't merge. " <> msgValue x <> msgValue y <> useDifferentAliases) -        --     user1: user-        --   }-        -- fails if:+msgValue :: Show a => a -> GQLError+msgValue = msg . show -        --     user1: product-        --   }-        mergeName-          | selectionName old == selectionName current = pure $ selectionName current-          | otherwise =-            failure $ mergeConflict path $-              ValidationError-                { validationMessage =-                    "" <> msg (selectionName old) <> " and " <> msg (selectionName current)-                      <> " are different fields. "-                      <> useDifferentAliases,-                  validationLocations = [pos1, pos2]-                }-        ----------------------        -- alias name is relevant only if they collide by allies like:-        --   { user1: user-        --     user1: user-        --   }-        mergeAlias-          | all (isJust . selectionAlias) [old, current] = selectionAlias old-          | otherwise = Nothing-        --- arguments must be equal-        mergeArguments currentPath-          | selectionArguments old == selectionArguments current = pure $ selectionArguments current-          | otherwise =-            failure $ mergeConflict currentPath $-              ValidationError-                { validationMessage = "they have differing arguments. " <> useDifferentAliases,-                  validationLocations = [pos1, pos2]-                }-  mergeM path _ _ =-    failure $-      mergeConflict-        path-        ("INTERNAL: can't merge. " <> msgValidation useDifferentAliases :: ValidationError)+-- fails if alias matches but name not:+--   { user1: user+--     user1: product+--   }+mergeName ::+  (Monad m, MonadError GQLError m, Foldable t) =>+  t Position ->+  Selection s1 ->+  Selection s2 ->+  HistoryT m FieldName+mergeName pos old current+  | selectionName old == selectionName current = pure $ selectionName current+  | otherwise =+    mergeConflict $+      ( msg (selectionName old)+          <> " and "+          <> msg (selectionName current)+          <> " are different fields. "+          <> useDifferentAliases+      )+        `atPositions` pos  deriving instance Show (Selection a) @@ -332,11 +360,11 @@         <> newline  getOperationName :: Maybe FieldName -> TypeName-getOperationName = maybe "AnonymousOperation" (TypeName . readName)+getOperationName = maybe "AnonymousOperation" coerce -getOperationDataType :: Failure ValidationError m => Operation s -> Schema VALID -> m (TypeDefinition OBJECT VALID)+getOperationDataType :: MonadError GQLError m => Operation s -> Schema VALID -> m (TypeDefinition OBJECT VALID) getOperationDataType Operation {operationType = Query} lib = pure (query lib) getOperationDataType Operation {operationType = Mutation, operationPosition} lib =-  maybe (failure $ mutationIsNotDefined operationPosition) pure (mutation lib)+  maybe (throwError $ mutationIsNotDefined operationPosition) pure (mutation lib) getOperationDataType Operation {operationType = Subscription, operationPosition} lib =-  maybe (failure $ subscriptionIsNotDefined operationPosition) pure (subscription lib)+  maybe (throwError $ subscriptionIsNotDefined operationPosition) pure (subscription lib)
src/Data/Morpheus/Types/Internal/AST/Stage.hs view
@@ -8,9 +8,12 @@     RAW,     Stage (..),     CONST_OR_VALID,+    ALLOW_DUPLICATES,   ) where +import Data.Bool (Bool (..))+ type CONST = 'CONST  type VALID = 'VALID@@ -25,3 +28,7 @@ type family CONST_OR_VALID (a :: Stage) :: Stage where   CONST_OR_VALID VALID = VALID   CONST_OR_VALID a = CONST++type family ALLOW_DUPLICATES s where+  ALLOW_DUPLICATES RAW = 'True+  ALLOW_DUPLICATES a = 'False
− src/Data/Morpheus/Types/Internal/AST/TH.hs
@@ -1,28 +0,0 @@--- Template Haskell Types-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE NoImplicitPrelude #-}--module Data.Morpheus.Types.Internal.AST.TH-  ( ConsD (..),-    mkConsEnum,-  )-where--import Data.Morpheus.Types.Internal.AST.Base-  ( TypeName,-    hsTypeName,-  )-import Data.Morpheus.Types.Internal.AST.TypeSystem-  ( DataEnumValue (..),-  )-import Relude--data ConsD f = ConsD-  { cName :: TypeName,-    cFields :: [f]-  }-  deriving (Show)--mkConsEnum :: DataEnumValue s -> ConsD f-mkConsEnum DataEnumValue {enumName} = ConsD {cName = hsTypeName enumName, cFields = []}
src/Data/Morpheus/Types/Internal/AST/Type.hs view
@@ -6,16 +6,15 @@ {-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Types.Internal.AST.Type-  ( DataTypeWrapper (..),-    TypeRef (..),+  ( TypeRef (..),     TypeWrapper (..),     Nullable (..),     Strictness (..),     TypeKind (..),-    isWeaker,+    Subtyping (..),     mkTypeRef,-    toGQLWrapper,-    toHSWrappers,+    mkBaseType,+    mkMaybeType,   ) where @@ -25,12 +24,16 @@     render,     renderGQL,   )-import Data.Morpheus.Types.Internal.AST.Base-  ( FieldName (..),-    Msg (..),-    OperationType,-    TypeName (..),+import Data.Morpheus.Types.Internal.AST.Error+  ( Msg (..),   )+import Data.Morpheus.Types.Internal.AST.Name+  ( TypeName,+    packName,+  )+import Data.Morpheus.Types.Internal.AST.OperationType+  ( OperationType (..),+  ) import qualified Data.Text.Lazy as LT import Data.Text.Lazy.Encoding (decodeUtf8) import Language.Haskell.TH.Syntax (Lift (..))@@ -82,71 +85,86 @@  -- TypeWrappers ------------------------------------------------------------------------------------ data TypeWrapper-  = TypeList-  | TypeMaybe+  = TypeList !TypeWrapper !Bool+  | BaseType !Bool   deriving (Show, Eq, Lift) -data DataTypeWrapper-  = ListType-  | NonNullType-  deriving (Show, Lift)--isWeaker :: [TypeWrapper] -> [TypeWrapper] -> Bool-isWeaker (TypeMaybe : xs1) (TypeMaybe : xs2) = isWeaker xs1 xs2-isWeaker (TypeMaybe : _) _ = True-isWeaker (_ : xs1) (_ : xs2) = isWeaker xs1 xs2-isWeaker _ _ = False+mkBaseType :: TypeWrapper+mkBaseType = BaseType True -toGQLWrapper :: [TypeWrapper] -> [DataTypeWrapper]-toGQLWrapper (TypeMaybe : (TypeMaybe : tw)) = toGQLWrapper (TypeMaybe : tw)-toGQLWrapper (TypeMaybe : (TypeList : tw)) = ListType : toGQLWrapper tw-toGQLWrapper (TypeList : tw) = [NonNullType, ListType] <> toGQLWrapper tw-toGQLWrapper [TypeMaybe] = []-toGQLWrapper [] = [NonNullType]+mkMaybeType :: TypeWrapper+mkMaybeType = BaseType False -toHSWrappers :: [DataTypeWrapper] -> [TypeWrapper]-toHSWrappers (NonNullType : (NonNullType : xs)) =-  toHSWrappers (NonNullType : xs)-toHSWrappers (NonNullType : (ListType : xs)) = TypeList : toHSWrappers xs-toHSWrappers (ListType : xs) = [TypeMaybe, TypeList] <> toHSWrappers xs-toHSWrappers [] = [TypeMaybe]-toHSWrappers [NonNullType] = []+-- If S is a subtype of T, "S <: T"+-- A is a subtype of B, then all terms of type A also have type B.+-- type B = Int | Null+-- type A = Int+-- A <: B+--+-- interface A { a: String }+--+-- type B implements A { a: String!}+--+-- type B is subtype of A since :  {String} ⊂ {String, null}+--+-- interface A { a: String! }+--+-- type B implements A { a: String }+--+-- type B is not subtype of A since :  {String, null} ⊂ {String}+--+-- type A = { T, Null}+-- type B = T+-- type B is subtype of A since :  {T} ⊂ {T, Null}+-- type B is Subtype if B since: {T} ⊂ {T}+class Subtyping t where+  isSubtype :: t -> t -> Bool -renderWrapped :: RenderGQL a => a -> [TypeWrapper] -> Rendering-renderWrapped x wrappers = showGQLWrapper (toGQLWrapper wrappers)-  where-    showGQLWrapper [] = renderGQL x-    showGQLWrapper (ListType : xs) = "[" <> showGQLWrapper xs <> "]"-    showGQLWrapper (NonNullType : xs) = showGQLWrapper xs <> "!"+instance Subtyping TypeWrapper where+  isSubtype (TypeList b nonNull1) (TypeList a nonNull2) =+    nonNull1 >= nonNull2 && isSubtype b a+  isSubtype (BaseType b) (BaseType a) = b >= a+  isSubtype b a = b == a  -- TypeRef ------------------------------------------------------------------- data TypeRef = TypeRef   { typeConName :: TypeName,-    typeWrappers :: [TypeWrapper]+    typeWrappers :: TypeWrapper   }   deriving (Show, Eq, Lift)  mkTypeRef :: TypeName -> TypeRef-mkTypeRef typeConName = TypeRef {typeConName, typeWrappers = []}+mkTypeRef typeConName = TypeRef {typeConName, typeWrappers = mkBaseType} +instance Subtyping TypeRef where+  isSubtype t1 t2 =+    typeConName t1 == typeConName t2+      && typeWrappers t1 `isSubtype` typeWrappers t2+ instance RenderGQL TypeRef where-  renderGQL TypeRef {typeConName, typeWrappers} = renderWrapped typeConName typeWrappers+  renderGQL TypeRef {typeConName, typeWrappers} = renderWrapper typeWrappers+    where+      renderWrapper (TypeList xs isNonNull) = "[" <> renderWrapper xs <> "]" <> renderNonNull isNonNull+      renderWrapper (BaseType isNonNull) = renderGQL typeConName <> renderNonNull isNonNull +renderNonNull :: Bool -> Rendering+renderNonNull True = "!"+renderNonNull False = ""+ instance Msg TypeRef where-  msg = msg . FieldName . LT.toStrict . decodeUtf8 . render+  msg = msg . packName . LT.toStrict . decodeUtf8 . render  class Nullable a where   isNullable :: a -> Bool   toNullable :: a -> a -instance Nullable [TypeWrapper] where-  isNullable (TypeMaybe : _) = True-  isNullable _ = False-  toNullable (TypeMaybe : xs) = TypeMaybe : xs-  toNullable xs = TypeMaybe : xs+instance Nullable TypeWrapper where+  isNullable (TypeList _ nonNull) = not nonNull+  isNullable (BaseType nonNull) = not nonNull+  toNullable (TypeList t _) = TypeList t False+  toNullable BaseType {} = BaseType False  instance Nullable TypeRef where   isNullable = isNullable . typeWrappers
src/Data/Morpheus/Types/Internal/AST/TypeSystem.hs view
@@ -23,14 +23,13 @@ module Data.Morpheus.Types.Internal.AST.TypeSystem   ( ScalarDefinition (..),     DataEnum,-    DataUnion,+    UnionTypeDefinition,     TypeContent (..),     TypeDefinition (..),     Schema (..),     DataEnumValue (..),-    TypeLib,+    TypeDefinitions,     TypeCategory,-    DataInputUnion,     mkEnumContent,     mkUnionContent,     mkType,@@ -49,31 +48,40 @@     possibleTypes,     possibleInterfaceTypes,     defineSchemaWith,+    isPossibleInterfaceType,+    typeDefinitions,+    lookupDataType,   ) where  -- MORPHEUS-import Data.Morpheus.Error.NameCollision-  ( NameCollision (..),-  )-import Data.Morpheus.Ext.OrdMap-  ( OrdMap,++-- MORPHEUS++-- MORPHEUS++-- MORPHEUS+import Control.Monad.Except (MonadError (throwError))+import qualified Data.HashMap.Lazy as HM+import Data.Mergeable+  ( IsMap (lookup),+    Merge (..),+    NameCollision (..),+    OrdMap,   )-import Data.Morpheus.Ext.SafeHashMap+import Data.Mergeable.SafeHashMap   ( SafeHashMap,-    insert,-  )-import Data.Morpheus.Ext.SemigroupM-  ( (<:>),-    SemigroupM (..),+    toHashMap,   ) import Data.Morpheus.Internal.Utils-  ( Elems (..),+  ( (<:>),     Empty (..),-    Failure (..),-    FromElems (..),+    IsMap (..),     KeyOf (..),-    Selectable (..),+    insert,+    selectOr,+    toPair,+    unsafeFromList,   ) import Data.Morpheus.Rendering.RenderGQL   ( RenderGQL (..),@@ -86,22 +94,28 @@   ) import Data.Morpheus.Types.Internal.AST.Base   ( Description,-    OperationType (..),     TRUE,     Token,-    TypeName,-    ValidationError,-    ValidationErrors,-    isNotSystemTypeName,-    msgValidation,-    toOperationType,   )+import Data.Morpheus.Types.Internal.AST.Error+  ( GQLError,+    msg,+  ) import Data.Morpheus.Types.Internal.AST.Fields-  ( Directive,-    DirectiveDefinition (..),+  ( DirectiveDefinition (..),     Directives,+    DirectivesDefinition,     FieldsDefinition,   )+import Data.Morpheus.Types.Internal.AST.Name+  ( TypeName,+    isNotSystemTypeName,+    unpackName,+  )+import Data.Morpheus.Types.Internal.AST.OperationType+  ( OperationType (..),+    toOperationType,+  ) import Data.Morpheus.Types.Internal.AST.Stage   ( CONST,     Stage,@@ -128,14 +142,14 @@     type (<=?),   ) import Data.Morpheus.Types.Internal.AST.Union-  ( DataInputUnion,-    DataUnion,+  ( UnionTypeDefinition,     mkInputUnionFields,     mkUnionMember,   ) import Data.Morpheus.Types.Internal.AST.Value   ( Value (..),   )+import qualified Data.Text as T import Instances.TH.Lift () import Language.Haskell.TH.Syntax (Lift (..)) import Relude hiding@@ -185,7 +199,7 @@ data DataEnumValue s = DataEnumValue   { enumDescription :: Maybe Description,     enumName :: TypeName,-    enumDirectives :: [Directive s]+    enumDirectives :: Directives s   }   deriving (Show, Lift, Eq) @@ -201,32 +215,30 @@ --    OperationType: NamedType  data Schema (s :: Stage) = Schema-  { types :: TypeLib s,+  { types :: TypeDefinitions s,     query :: TypeDefinition OBJECT s,     mutation :: Maybe (TypeDefinition OBJECT s),     subscription :: Maybe (TypeDefinition OBJECT s),-    directiveDefinitions :: [DirectiveDefinition s]+    directiveDefinitions :: DirectivesDefinition s   }   deriving (Show, Lift)  instance   ( Monad m,-    Failure ValidationErrors m+    MonadError GQLError m   ) =>-  SemigroupM-    m-    (Schema s)+  Merge m (Schema s)   where-  mergeM _ s1 s2 =+  merge s1 s2 =     Schema-      <$> (types s1 <:> types s2)+      <$> merge (types s1) (types s2)       <*> mergeOperation (query s1) (query s2)       <*> mergeOptional (mutation s1) (mutation s2)       <*> mergeOptional (subscription s1) (subscription s2)-      <*> pure (directiveDefinitions s1 <> directiveDefinitions s2)+      <*> directiveDefinitions s1 <:> directiveDefinitions s2  mergeOptional ::-  (Monad m, Failure ValidationErrors m) =>+  (Monad m, MonadError GQLError m) =>   Maybe (TypeDefinition OBJECT s) ->   Maybe (TypeDefinition OBJECT s) ->   m (Maybe (TypeDefinition OBJECT s))@@ -235,7 +247,7 @@ mergeOptional (Just x) (Just y) = Just <$> mergeOperation x y  mergeOperation ::-  (Monad m, Failure ValidationErrors m) =>+  (Monad m, MonadError GQLError m) =>   TypeDefinition OBJECT s ->   TypeDefinition OBJECT s ->   m (TypeDefinition OBJECT s)@@ -243,7 +255,7 @@   TypeDefinition {typeContent = DataObject i1 fields1}   TypeDefinition {typeContent = DataObject i2 fields2, ..} =     do-      fields <- fields1 <:> fields2+      fields <- merge fields1 fields2       pure $ TypeDefinition {typeContent = DataObject (i1 <> i2) fields, ..}  data SchemaDefinition = SchemaDefinition@@ -253,16 +265,12 @@   deriving (Show)  instance RenderGQL SchemaDefinition where-  renderGQL = renderSchemaDefinition . elems . unSchemaDefinition+  renderGQL = renderSchemaDefinition . toList . unSchemaDefinition -renderSchemaDefinition :: RenderGQL a => [a] -> Rendering+renderSchemaDefinition :: [RootOperationTypeDefinition] -> Rendering renderSchemaDefinition entries = "schema" <> renderObject entries <> newline -instance Selectable OperationType RootOperationTypeDefinition SchemaDefinition where-  selectOr fallback f key SchemaDefinition {unSchemaDefinition} =-    selectOr fallback f key unSchemaDefinition--instance NameCollision SchemaDefinition where+instance NameCollision GQLError SchemaDefinition where   nameCollision _ = "There can Be only One SchemaDefinition."  instance KeyOf TypeName SchemaDefinition where@@ -280,9 +288,9 @@   }   deriving (Show, Eq) -instance NameCollision RootOperationTypeDefinition where+instance NameCollision GQLError RootOperationTypeDefinition where   nameCollision RootOperationTypeDefinition {rootOperationType} =-    "There can Be only One TypeDefinition for schema." <> msgValidation rootOperationType+    "There can Be only One TypeDefinition for schema." <> msg rootOperationType  instance KeyOf OperationType RootOperationTypeDefinition where   keyOf = rootOperationType@@ -294,34 +302,29 @@         rootOperationTypeDefinitionName       } = renderEntry rootOperationType rootOperationTypeDefinitionName -type TypeLib s = SafeHashMap TypeName (TypeDefinition ANY s)+type TypeDefinitions s = SafeHashMap TypeName (TypeDefinition ANY s) -instance Selectable TypeName (TypeDefinition ANY s) (Schema s) where-  selectOr fb f name lib = maybe fb f (lookupDataType name lib)+typeDefinitions :: Schema s -> HashMap TypeName (TypeDefinition ANY s)+typeDefinitions schema@Schema {..} = toHashMap types <> HM.fromList operations+  where+    operations = map toPair $ rootTypeDefinitions schema -instance Elems (TypeDefinition ANY s) (Schema s) where-  elems Schema {..} =-    elems types-      <> concatMap fromOperation [Just query, mutation, subscription]+rootTypeDefinitions :: Schema s -> [TypeDefinition ANY s]+rootTypeDefinitions Schema {..} = map toAny $ catMaybes [Just query, mutation, subscription] -instance-  ( Monad m,-    Failure ValidationErrors m-  ) =>-  FromElems m (TypeDefinition ANY s) (Schema s)-  where-  fromElems types =-    traverse3-      (popByKey types)-      ( RootOperationTypeDefinition Query "Query",-        RootOperationTypeDefinition Mutation "Mutation",-        RootOperationTypeDefinition Subscription "Subscription"-      )-      >>= defineSchemaWith types+mkSchema :: (Monad m, MonadError GQLError m) => [TypeDefinition ANY s] -> m (Schema s)+mkSchema types =+  traverse3+    (popByKey types)+    ( RootOperationTypeDefinition Query "Query",+      RootOperationTypeDefinition Mutation "Mutation",+      RootOperationTypeDefinition Subscription "Subscription"+    )+    >>= defineSchemaWith types  defineSchemaWith ::   ( Monad f,-    Failure ValidationErrors f+    MonadError GQLError f   ) =>   [TypeDefinition cat s] ->   ( Maybe (TypeDefinition OBJECT s),@@ -333,7 +336,7 @@   let types = excludeTypes [Just query, mutation, subscription] oTypes   let schema = (initTypeLib query) {mutation, subscription}   foldlM (flip defineType) schema types-defineSchemaWith _ (Nothing, _, _) = failure ["Query root type must be provided." :: ValidationError]+defineSchemaWith _ (Nothing, _, _) = throwError "Query root type must be provided."  excludeTypes :: [Maybe (TypeDefinition c1 s)] -> [TypeDefinition c2 s] -> [TypeDefinition c2 s] excludeTypes exclusionTypes = filter ((`notElem` blacklist) . typeName)@@ -342,29 +345,30 @@     blacklist = fmap typeName (catMaybes exclusionTypes)  withDirectives ::-  [DirectiveDefinition s] ->+  (Monad m, MonadError GQLError m) =>+  DirectivesDefinition s ->   Schema s ->-  Schema s-withDirectives dirs Schema {..} =-  Schema-    { directiveDefinitions = directiveDefinitions <> dirs,-      ..-    }+  m (Schema s)+withDirectives dirs Schema {..} = do+  dirs' <- directiveDefinitions <:> dirs+  pure $+    Schema+      { directiveDefinitions = dirs',+        ..+      }  buildSchema ::-  (Monad m, Failure ValidationErrors m) =>+  (Monad m, MonadError GQLError m) =>   ( Maybe SchemaDefinition,     [TypeDefinition ANY s],-    [DirectiveDefinition s]+    DirectivesDefinition s   ) ->   m (Schema s)-buildSchema (Nothing, types, dirs) = withDirectives dirs <$> fromElems types+buildSchema (Nothing, types, dirs) = mkSchema types >>= withDirectives dirs buildSchema (Just schemaDef, types, dirs) =-  withDirectives-    dirs-    <$> ( traverse3 selectOp (Query, Mutation, Subscription)-            >>= defineSchemaWith types-        )+  traverse3 selectOp (Query, Mutation, Subscription)+    >>= defineSchemaWith types+    >>= withDirectives dirs   where     selectOp op = selectOperation schemaDef op types @@ -372,26 +376,26 @@ traverse3 f (a1, a2, a3) = (,,) <$> f a1 <*> f a2 <*> f a3  typeReference ::-  (Monad m, Failure ValidationErrors m) =>+  (Monad m, MonadError GQLError m) =>   [TypeDefinition ANY s] ->   RootOperationTypeDefinition ->   m (Maybe (TypeDefinition OBJECT s)) typeReference types rootOperation =   popByKey types rootOperation     >>= maybe-      (failure ["Unknown type " <> msgValidation (rootOperationTypeDefinitionName rootOperation) <> "."])+      (throwError $ "Unknown type " <> msg (rootOperationTypeDefinitionName rootOperation) <> ".")       (pure . Just)  selectOperation ::   ( Monad f,-    Failure ValidationErrors f+    MonadError GQLError f   ) =>   SchemaDefinition ->   OperationType ->   [TypeDefinition ANY s] ->   f (Maybe (TypeDefinition OBJECT s))-selectOperation schemaDef operationType lib =-  selectOr (pure Nothing) (typeReference lib) operationType schemaDef+selectOperation SchemaDefinition {unSchemaDefinition} operationType lib =+  selectOr (pure Nothing) (typeReference lib) operationType unSchemaDefinition  initTypeLib :: TypeDefinition OBJECT s -> Schema s initTypeLib query =@@ -413,7 +417,7 @@   isType name query     <|> (mutation >>= isType name)     <|> (subscription >>= isType name)-    <|> selectOr Nothing Just name types+    <|> lookup name types  -- 3.4 Types : https://graphql.github.io/graphql-spec/June2018/#sec-Types -------------------------------------------------------------------------@@ -433,14 +437,20 @@   }   deriving (Show, Lift, Eq) +instance Ord (TypeDefinition k s) where+  compare a b =+    compare (indexOf $ typeContent a) (indexOf $ typeContent b)+      <> compare (typeName a) (typeName b)+ instance KeyOf TypeName (TypeDefinition a s) where   keyOf = typeName  instance Strictness (TypeDefinition k s) where   isResolverType = isResolverType . typeContent -instance NameCollision (TypeDefinition cat s) where-  nameCollision x = "There can Be only One TypeDefinition Named " <> msgValidation (typeName x) <> "."+instance NameCollision GQLError (TypeDefinition cat s) where+  nameCollision x =+    "There can Be only One TypeDefinition Named " <> msg (typeName x) <> "."  instance   ToCategory (TypeContent TRUE) cat cat' =>@@ -467,7 +477,10 @@   TypeName ->   Schema s ->   [TypeDefinition ANY s]-possibleInterfaceTypes name schema = mapMaybe (isPossibleInterfaceType name) (elems schema)+possibleInterfaceTypes name schema =+  mapMaybe+    (isPossibleInterfaceType name)+    (toList $ typeDefinitions schema)  isPossibleInterfaceType ::   TypeName ->@@ -506,7 +519,7 @@     } ->     CondTypeContent INPUT_OBJECT a s   DataInputUnion ::-    { inputUnionMembers :: DataInputUnion s+    { inputUnionMembers :: UnionTypeDefinition IN s     } ->     CondTypeContent IN a s   DataObject ::@@ -515,7 +528,7 @@     } ->     CondTypeContent OBJECT a s   DataUnion ::-    { unionMembers :: DataUnion s+    { unionMembers :: UnionTypeDefinition OUT s     } ->     CondTypeContent OUT a s   DataInterface ::@@ -529,6 +542,15 @@  deriving instance Lift (TypeContent a b s) +indexOf :: TypeContent b a s -> Int+indexOf DataScalar {} = 0+indexOf DataEnum {} = 1+indexOf DataInputObject {} = 2+indexOf DataInputUnion {} = 3+indexOf DataInterface {} = 4+indexOf DataObject {} = 5+indexOf DataUnion {} = 6+ instance Strictness (TypeContent TRUE k s) where   isResolverType DataObject {} = True   isResolverType DataUnion {} = True@@ -579,7 +601,7 @@   TypeDefinition     { typeName,       typeDescription = Nothing,-      typeDirectives = [],+      typeDirectives = empty,       typeContent     } @@ -590,14 +612,14 @@ mkEnumContent typeData = DataEnum (fmap mkEnumValue typeData)  mkUnionContent :: [TypeName] -> TypeContent TRUE OUT s-mkUnionContent typeData = DataUnion $ fmap mkUnionMember typeData+mkUnionContent typeData = DataUnion $ unsafeFromList $ map (toPair . mkUnionMember) typeData  mkEnumValue :: TypeName -> DataEnumValue s mkEnumValue enumName =   DataEnumValue     { enumName,       enumDescription = Nothing,-      enumDirectives = []+      enumDirectives = empty     }  isLeaf :: TypeContent TRUE a s -> Bool@@ -616,13 +638,9 @@     __kind DataInputUnion {} = KindInputUnion     __kind DataInterface {} = KindInterface -fromOperation :: Maybe (TypeDefinition OBJECT s) -> [TypeDefinition ANY s]-fromOperation (Just datatype) = [toAny datatype]-fromOperation Nothing = []- defineType ::   ( Monad m,-    Failure ValidationErrors m+    MonadError GQLError m   ) =>   TypeDefinition k s ->   Schema s ->@@ -635,7 +653,7 @@ lookupWith f key = find ((== key) . f)  popByKey ::-  (Applicative m, Failure ValidationErrors m) =>+  (MonadError GQLError m) =>   [TypeDefinition ANY s] ->   RootOperationTypeDefinition ->   m (Maybe (TypeDefinition OBJECT s))@@ -643,28 +661,41 @@   Just dt@TypeDefinition {typeContent = DataObject {}} ->     pure (fromAny dt)   Just {} ->-    failure-      [ msgValidation (show opType)-          <> " root type must be Object type if provided, it cannot be "-          <> msgValidation name-      ]+    throwError $+      msg (show opType)+        <> " root type must be Object type if provided, it cannot be "+        <> msg name   _ -> pure Nothing  -- -- OTHER -------------------------------------------------------------------------------------------------- +hasDefaultOperationName :: RootOperationTypeDefinition -> Bool+hasDefaultOperationName+  RootOperationTypeDefinition+    { rootOperationType,+      rootOperationTypeDefinitionName = name+    } = show rootOperationType == T.unpack (unpackName name)+ instance RenderGQL (Schema s) where-  renderGQL schema =-    intercalate newline (fmap renderGQL visibleTypes <> [renderSchemaDefinition entries])+  renderGQL schema@Schema {..} =+    intercalate newline (fmap renderGQL visibleTypes <> schemaDefinition)     where+      schemaDefinition+        | all hasDefaultOperationName entries = []+        | otherwise = [renderSchemaDefinition entries]       entries =-        RootOperationTypeDefinition Query (typeName $ query schema)-          : catMaybes-            [ RootOperationTypeDefinition Mutation . typeName <$> mutation schema,-              RootOperationTypeDefinition Subscription . typeName <$> subscription schema-            ]-      visibleTypes = filter (isNotSystemTypeName . typeName) (elems schema)+        catMaybes+          [ RootOperationTypeDefinition Query . typeName <$> Just query,+            RootOperationTypeDefinition Mutation . typeName <$> mutation,+            RootOperationTypeDefinition Subscription . typeName <$> subscription+          ]+      visibleTypes =+        filter+          (isNotSystemTypeName . typeName)+          (sort $ toList types)+          <> rootTypeDefinitions schema  instance RenderGQL (TypeDefinition a s) where   renderGQL TypeDefinition {typeName, typeContent} = __render typeContent <> newline
src/Data/Morpheus/Types/Internal/AST/Union.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveLift #-}+{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE NamedFieldPuns #-}@@ -12,46 +13,46 @@   ( constraintInputUnion,     mkUnionMember,     mkNullaryMember,-    DataUnion,-    DataInputUnion,+    UnionTypeDefinition,     UnionMember (..),     mkInputUnionFields,     getInputUnionValue,   ) where +import Control.Monad.Except (throwError)+import Data.Mergeable (NameCollision (..), OrdMap) import Data.Morpheus.Internal.Utils-  ( Failure (..),+  ( Empty (empty),     KeyOf (..),-    elems,     selectBy,   ) import Data.Morpheus.Rendering.RenderGQL   ( RenderGQL (..),   )-import Data.Morpheus.Types.Internal.AST.Base-  ( FieldName (..),-    Message (..),+import Data.Morpheus.Types.Internal.AST.Error+  ( GQLError,     Msg (..),-    TypeName (..),-    toFieldName,-    unitTypeName,+    msg,   ) import Data.Morpheus.Types.Internal.AST.Fields   ( FieldDefinition (..),     FieldsDefinition,     unsafeFromFields,   )+import Data.Morpheus.Types.Internal.AST.Name+  ( TypeName,+    unitTypeName,+  ) import Data.Morpheus.Types.Internal.AST.Stage   ( Stage,   ) import Data.Morpheus.Types.Internal.AST.Type   ( TypeRef (..),-    TypeWrapper (..),+    mkMaybeType,   ) import Data.Morpheus.Types.Internal.AST.TypeCategory   ( IN,-    OUT,     TypeCategory,   ) import Data.Morpheus.Types.Internal.AST.Value@@ -60,7 +61,7 @@     Value (..),   ) import Language.Haskell.TH.Syntax (Lift (..))-import Relude+import Relude hiding (empty)  mkUnionMember :: TypeName -> UnionMember cat s mkUnionMember name = UnionMember name False@@ -74,9 +75,12 @@   }   deriving (Show, Lift, Eq) -type DataUnion s = [UnionMember OUT s]+instance NameCollision GQLError (UnionMember c s) where+  nameCollision UnionMember {memberName} =+    "There can Be only one union variant named "+      <> msg memberName -type DataInputUnion s = [UnionMember IN s]+type UnionTypeDefinition k s = OrdMap TypeName (UnionMember k s)  instance RenderGQL (UnionMember cat s) where   renderGQL = renderGQL . memberName@@ -90,44 +94,44 @@ getInputUnionValue ::   forall stage.   Object stage ->-  Either Message (TypeName, Value stage)+  Either GQLError (TypeName, Value stage) getInputUnionValue hm =-  case elems hm of-    [] -> failure ("Exclusive input objects must provide a value for at least one field." :: Message)-    [ObjectEntry (FieldName name) value] -> pure (TypeName name, value)-    _ -> failure ("Exclusive input objects are not allowed to provide values for multiple fields." :: Message)+  case toList hm of+    [] -> throwError "Exclusive input objects must provide a value for at least one field."+    [ObjectEntry name value] -> pure (coerce name, value)+    _ -> throwError "Exclusive input objects are not allowed to provide values for multiple fields."  constraintInputUnion ::   forall stage schemaStage.-  [UnionMember IN schemaStage] ->+  UnionTypeDefinition IN schemaStage ->   Object stage ->-  Either Message (UnionMember IN schemaStage, Value stage)+  Either GQLError (UnionMember IN schemaStage, Value stage) constraintInputUnion tags hm = do   (name, value) <- getInputUnionValue hm   (,value) <$> isPossibleInputUnion tags name -isPossibleInputUnion :: [UnionMember IN s] -> TypeName -> Either Message (UnionMember IN s)+isPossibleInputUnion :: UnionTypeDefinition IN s -> TypeName -> Either GQLError (UnionMember IN s) isPossibleInputUnion tags name =   selectBy     (msg name <> " is not possible union type")     name     tags -mkInputUnionFields :: [UnionMember IN s] -> FieldsDefinition IN s-mkInputUnionFields = unsafeFromFields . fmap mkInputUnionField+mkInputUnionFields :: Foldable t => t (UnionMember IN s) -> FieldsDefinition IN s+mkInputUnionFields = unsafeFromFields . fmap mkInputUnionField . toList  mkInputUnionField :: UnionMember IN s -> FieldDefinition IN s mkInputUnionField UnionMember {memberName, nullary} =   FieldDefinition-    { fieldName = toFieldName memberName,+    { fieldName = coerce memberName,       fieldDescription = Nothing,       fieldContent = Nothing,       fieldType =         TypeRef           { typeConName,-            typeWrappers = [TypeMaybe]+            typeWrappers = mkMaybeType           },-      fieldDirectives = []+      fieldDirectives = empty     }   where     typeConName
src/Data/Morpheus/Types/Internal/AST/Value.hs view
@@ -43,17 +43,13 @@   ) import Data.Foldable (foldr') import qualified Data.HashMap.Lazy as M-import Data.Morpheus.Error.NameCollision+import Data.Mergeable   ( NameCollision (..),-  )-import Data.Morpheus.Ext.OrdMap-  ( OrdMap,-    unsafeFromList,+    OrdMap,   ) import Data.Morpheus.Internal.Utils   ( KeyOf (..),-    elems,-    mapTuple,+    unsafeFromList,   ) import Data.Morpheus.Rendering.RenderGQL   ( RenderGQL (..),@@ -63,15 +59,20 @@     space,   ) import Data.Morpheus.Types.Internal.AST.Base-  ( FieldName,-    FieldName (..),-    Msg (..),-    Position,+  ( Position,     Ref (..),-    TypeName (..),-    ValidationError (..),-    msgValidation,   )+import Data.Morpheus.Types.Internal.AST.Error+  ( GQLError,+    Msg (..),+    at,+  )+import Data.Morpheus.Types.Internal.AST.Name+  ( FieldName,+    TypeName,+    packName,+    unpackName,+  ) import Data.Morpheus.Types.Internal.AST.Stage   ( CONST,     CONST_OR_VALID,@@ -88,6 +89,7 @@ import Instances.TH.Lift () import Language.Haskell.TH.Syntax (Lift (..)) import Relude+import qualified Data.Text as T  -- | Primitive Values for GQLScalar: 'Int', 'Float', 'String', 'Boolean'. -- for performance reason type 'Text' represents GraphQl 'String' value@@ -99,6 +101,9 @@   | Value A.Value   deriving (Show, Eq, Generic, Lift) +instance IsString ScalarValue where+  fromString = String . T.pack+ instance RenderGQL ScalarValue where   renderGQL (Int x) = renderGQL x   renderGQL (Float x) = renderGQL x@@ -146,12 +151,10 @@ instance KeyOf FieldName (Variable s) where   keyOf = variableName -instance NameCollision (Variable s) where+instance NameCollision GQLError (Variable s) where   nameCollision Variable {variableName, variablePosition} =-    ValidationError-      { validationMessage = "There can Be only One Variable Named " <> msg variableName,-        validationLocations = [variablePosition]-      }+    ("There can Be only One Variable Named " <> msg variableName)+      `at` variablePosition  type VariableDefinitions s = OrdMap FieldName (Variable s) @@ -164,6 +167,9 @@   Scalar :: ScalarValue -> Value stage   Null :: Value stage +instance IsString (Value stage) where+  fromString = Scalar . fromString+ deriving instance Show (Value a)  deriving instance Eq (Value s)@@ -175,11 +181,12 @@   deriving (Eq, Show)  instance RenderGQL (ObjectEntry a) where-  renderGQL (ObjectEntry (FieldName name) value) = fromText name <> ": " <> renderGQL value+  renderGQL (ObjectEntry name value) = fromText (unpackName name) <> ": " <> renderGQL value -instance NameCollision (ObjectEntry s) where+instance NameCollision GQLError (ObjectEntry s) where   nameCollision ObjectEntry {entryName} =-    "There can Be only One field Named " <> msgValidation entryName :: ValidationError+    "There can Be only One field Named "+      <> msg entryName  instance KeyOf FieldName (ObjectEntry s) where   keyOf = entryName@@ -211,8 +218,8 @@   renderGQL (Object xs) = "{" <> entries <> "}"     where       entries-        | null (elems xs) = ""-        | otherwise = space <> renderInputSeq (elems xs) <> space+        | null xs = ""+        | otherwise = space <> renderInputSeq (toList xs) <> space   renderGQL (List list) = "[" <> renderInputSeq list <> "]"  instance Msg (Value a) where@@ -222,14 +229,14 @@   toJSON (ResolvedVariable _ Variable {variableValue = ValidVariableValue x}) =     A.toJSON x   toJSON (VariableValue Ref {refName}) =-    A.String $ "($ref:" <> readName refName <> ")"+    A.String $ "($ref:" <> unpackName refName <> ")"   toJSON Null = A.Null-  toJSON (Enum (TypeName x)) = A.String x+  toJSON (Enum x) = A.String (unpackName x)   toJSON (Scalar x) = A.toJSON x   toJSON (List x) = A.toJSON x-  toJSON (Object fields) = A.object $ fmap toEntry (elems fields)+  toJSON (Object fields) = A.object $ fmap toEntry (toList fields)     where-      toEntry (ObjectEntry (FieldName name) value) = name A..= A.toJSON value+      toEntry (ObjectEntry name value) = unpackName name A..= A.toJSON value    -------------------------------------------   toEncoding (ResolvedVariable _ Variable {variableValue = ValidVariableValue x}) =@@ -240,9 +247,9 @@   toEncoding (Enum x) = A.toEncoding x   toEncoding (Scalar x) = A.toEncoding x   toEncoding (List x) = A.toEncoding x-  toEncoding (Object ordMap) = A.pairs $ renderSeries encodeField (elems ordMap)+  toEncoding (Object ordMap) = A.pairs $ renderSeries encodeField (toList ordMap)     where-      encodeField (ObjectEntry (FieldName key) value) = key A..= value+      encodeField (ObjectEntry key value) = unpackName key A..= value  -- fixes GHC 8.2.2, which can't deduce (Semigroup p) from context (Monoid p) renderSeries :: (Semigroup p, Monoid p) => (e -> p) -> [e] -> p@@ -261,7 +268,7 @@ replaceValue (A.Object v) =   mkObject $     fmap-      (mapTuple FieldName replaceValue)+      (bimap packName replaceValue)       (M.toList v) replaceValue (A.Array li) = List (fmap replaceValue (V.toList li)) replaceValue A.Null = Null
src/Data/Morpheus/Types/Internal/Validation.hs view
@@ -17,17 +17,12 @@     InputSource (..),     OperationContext (..),     runValidator,-    DirectiveValidator,     askType,     askTypeMember,     selectRequired,     selectKnown,     Constraint (..),     constraint,-    withScope,-    withScopeType,-    withPosition,-    asks,     asksScope,     selectWithDefaultValue,     startInput,@@ -37,54 +32,55 @@     Prop (..),     constraintInputUnion,     ScopeKind (..),-    withDirective,+    setDirective,     inputValueSource,     askVariables,     Scope (..),     MissingRequired (..),     InputContext,-    GetWith,-    SetWith,     Unknown,-    askSchema,     askFragments,-    MonadContext,-    CurrentSelection (..),     getOperationType,     selectType,     FragmentValidator,     askInterfaceTypes,+    askTypeDefinitions,+    withScope,+    setPosition,+    setSelection,+    ValidatorContext (..),   ) where +-- Resolution,++import Control.Monad.Except (throwError) import Data.Morpheus.Internal.Utils-  ( Failure (..),+  ( IsMap,     KeyOf (..),-    Selectable,     member,     selectBy,     selectOr,+    throwErrors,   ) import Data.Morpheus.Types.Internal.AST   ( ANY,     FieldContent (..),     FieldDefinition (..),-    FieldName (..),+    FieldName,     IN,     Position (..),     Ref (..),     TRUE,-    TypeCategory,-    TypeContent (..),-    TypeDefinition (..),-    TypeName (..),-    ValidationError,+    TypeName,     Value (..),     constraintInputUnion,     fromAny,     isNullable,-    msgValidation,+    msg,+    withPath,   )+import Data.Morpheus.Types.Internal.AST.TypeSystem import Data.Morpheus.Types.Internal.Validation.Error   ( KindViolation (..),     MissingRequired (..),@@ -98,63 +94,26 @@     getOperationType,   ) import Data.Morpheus.Types.Internal.Validation.Validator-  ( BaseValidator,-    Constraint (..),-    CurrentSelection (..),-    DirectiveValidator,-    FragmentValidator,-    GetWith (..),-    InputContext,-    InputSource (..),-    InputValidator,-    MonadContext (..),-    OperationContext (..),-    Prop (..),-    -- Resolution,-    Scope (..),-    ScopeKind (..),-    SelectionValidator,-    SetWith (..),-    Validator (..),-    ValidatorContext (..),-    askFragments,-    askSchema,-    askVariables,-    asks,-    asksScope,-    inField,-    inputMessagePrefix,-    inputValueSource,-    runValidator,-    startInput,-    withDirective,-    withPosition,-    withScope,-    withScopeType,-  )-import Relude hiding-  ( Constraint,-    asks,-  )+import Relude hiding (Constraint) -getUnused :: (KeyOf k b, Selectable k a c) => c -> [b] -> [b]-getUnused uses = filter (not . (`member` uses) . keyOf)+getUnused :: (KeyOf k b, IsMap k c, Foldable t) => c a -> t b -> [b]+getUnused uses = filter (not . (`member` uses) . keyOf) . toList -failOnUnused :: Unused ctx b => [b] -> Validator s ctx ()-failOnUnused x-  | null x = pure ()-  | otherwise = do-    ctx <- validatorCTX <$> Validator ask-    failure $ fmap (unused ctx) x+failOnUnused :: Unused a => [a] -> Validator s (OperationContext s1 s2) ()+failOnUnused [] = pure ()+failOnUnused (x : xs) = do+  ctx <- Validator ask+  throwErrors $ (`withPath` path (scope ctx)) . unused (localContext ctx) <$> (x :| xs)  checkUnused ::   ( KeyOf k b,-    Selectable k a ca,-    Unused ctx b+    IsMap k c,+    Unused b,+    Foldable t   ) =>-  ca ->-  [b] ->-  Validator s ctx ()+  c a ->+  t b ->+  Validator s (OperationContext s1 s2) () checkUnused uses = failOnUnused . getUnused uses  constraint ::@@ -167,34 +126,33 @@   pure TypeDefinition {typeContent = DataObject {objectFields, ..}, ..} constraint IMPLEMENTABLE _ TypeDefinition {typeContent = DataInterface fields, ..} =   pure TypeDefinition {typeContent = DataInterface fields, ..}-constraint INPUT ctx x = maybe (failure [kindViolation INPUT ctx]) pure (fromAny x)-constraint target ctx _ = failure [kindViolation target ctx]+constraint INPUT ctx x = maybe (throwError (kindViolation INPUT ctx)) pure (fromAny x)+constraint target ctx _ = throwError (kindViolation target ctx)  selectRequired ::-  ( Selectable FieldName value c,-    MissingRequired c ctx+  ( IsMap FieldName c,+    MissingRequired (c a) ctx   ) =>   Ref FieldName ->-  c ->-  Validator s ctx value+  c a ->+  Validator s ctx a selectRequired selector container =   do-    ValidatorContext {scope, validatorCTX} <- Validator ask+    ValidatorContext {scope, localContext} <- Validator ask     selectBy-      [missingRequired scope validatorCTX selector container]+      (missingRequired scope localContext selector container)       (keyOf selector)       container  selectWithDefaultValue ::-  forall ctx values value s validValue.-  ( Selectable FieldName value values,-    MissingRequired values ctx,-    MonadContext (Validator s) s ctx+  forall ctx c s validValue a.+  ( IsMap FieldName c,+    MissingRequired (c a) ctx   ) =>   (Value s -> Validator s ctx validValue) ->-  (value -> Validator s ctx validValue) ->+  (a -> Validator s ctx validValue) ->   FieldDefinition IN s ->-  values ->+  c a ->   Validator s ctx validValue selectWithDefaultValue   f@@ -220,30 +178,30 @@         | otherwise = failSelection       -----------------       failSelection = do-        ValidatorContext {scope, validatorCTX} <- Validator ask+        ValidatorContext {scope, localContext} <- Validator ask         position <- asksScope position-        failure [missingRequired scope validatorCTX (Ref fieldName (fromMaybe (Position 0 0) position)) values]+        throwError $ missingRequired scope localContext (Ref fieldName (fromMaybe (Position 0 0) position)) values  selectType ::   TypeName ->   Validator s ctx (TypeDefinition ANY s) selectType name =-  askSchema >>= selectBy err name+  asks schema >>= maybe (throwError err) pure . lookupDataType name   where-    err = "Unknown Type " <> msgValidation name <> "." :: ValidationError+    err = "Unknown Type " <> msg name <> "."  selectKnown ::-  ( Selectable k a c,-    Unknown c sel ctx,+  ( IsMap k c,+    Unknown sel ctx,     KeyOf k sel   ) =>   sel ->-  c ->+  c a ->   Validator s ctx a selectKnown selector lib =   do-    ValidatorContext {scope, validatorCTX} <- Validator ask+    ValidatorContext {scope, localContext} <- Validator ask     selectBy-      (unknown scope validatorCTX lib selector)+      (unknown scope localContext selector)       (keyOf selector)       lib
src/Data/Morpheus/Types/Internal/Validation/Error.hs view
@@ -19,36 +19,29 @@ import Data.Morpheus.Types.Internal.AST   ( Argument (..),     Arguments,-    CONST,     Directive (..),-    DirectiveDefinition (..),-    DirectiveDefinitions,-    FieldDefinition (..),     FieldName,-    FieldsDefinition,     Fragment (..),-    Fragments,+    FragmentName,+    GQLError,     IMPLEMENTABLE,     IN,-    OUT,     Object,     ObjectEntry (..),     Ref (..),-    Schema,     TypeCategory,     TypeName,     TypeRef (..),-    ValidationError (..),     Variable (..),     VariableDefinitions,+    at,+    atPositions,     getOperationName,     msg,-    msgValidation,-    withPosition,+    withPath,   ) import Data.Morpheus.Types.Internal.Validation.Validator-  ( CurrentSelection (..),-    InputContext (..),+  ( InputContext (..),     OperationContext (..),     Scope (..),     ScopeKind (..),@@ -56,154 +49,148 @@   ) import Relude -class Unused ctx c where-  unused :: ctx -> c -> ValidationError+class Unused c where+  unused :: OperationContext s1 s2 -> c -> GQLError  -- query M ( $v : String ) { a } -> "Variable \"$bla\" is never used in operation \"MyMutation\".",-instance Unused (OperationContext s1 s2) (Variable s) where+instance Unused (Variable s) where   unused-    OperationContext {selection = CurrentSelection {operationName}}+    OperationContext {operationName}     Variable {variableName, variablePosition} =-      ValidationError-        { validationMessage =-            "Variable " <> msg ("$" <> variableName)-              <> " is never used in operation "-              <> msg (getOperationName operationName)-              <> ".",-          validationLocations = [variablePosition]-        }+      ( "Variable " <> msg ("$" <> variableName)+          <> " is never used in operation "+          <> msg (getOperationName operationName)+          <> "."+      )+        `at` variablePosition -instance Unused (OperationContext s1 s2) (Fragment s) where+instance Unused (Fragment s) where   unused     _     Fragment {fragmentName, fragmentPosition} =-      ValidationError-        { validationMessage =-            "Fragment " <> msg fragmentName-              <> " is never used.",-          validationLocations = [fragmentPosition]-        }+      ( "Fragment " <> msg fragmentName+          <> " is never used."+      )+        `at` fragmentPosition  class MissingRequired c ctx where-  missingRequired :: Scope -> ctx -> Ref FieldName -> c -> ValidationError+  missingRequired :: Scope -> ctx -> Ref FieldName -> c -> GQLError  instance MissingRequired (Arguments s) ctx where   missingRequired-    Scope {position, kind, fieldname}+    Scope {position, kind, fieldName, path}     _     Ref {refName}     _ =-      ValidationError-        { validationMessage =-            inScope kind-              <> " argument "-              <> msg refName-              <> " is required but not provided.",-          validationLocations = maybeToList position-        }+      ( ( inScope kind+            <> " argument "+            <> msg refName+            <> " is required but not provided."+        )+          `atPositions` position+      )+        `withPath` path       where-        inScope DIRECTIVE = "Directive " <> msg ("@" <> fieldname)-        inScope _ = "Field " <> msg fieldname+        inScope DIRECTIVE = "Directive " <> msg fieldName+        inScope _ = "Field " <> msg fieldName  instance MissingRequired (Object s) (InputContext ctx) where   missingRequired-    Scope {position}+    Scope {position, path}     ctx     Ref {refName}     _ =-      withPosition-        position-        ( renderInputPrefix+      ( ( renderInputPrefix             ctx             <> "Undefined Field "-            <> msgValidation refName+            <> msg refName             <> "."         )+          `atPositions` position+      )+        `withPath` path  instance MissingRequired (VariableDefinitions s) (OperationContext s1 s2) where   missingRequired-    _+    Scope {path}     OperationContext-      { selection = CurrentSelection {operationName}+      { operationName       }     Ref {refName, refPosition}     _ =-      ValidationError-        { validationMessage =-            "Variable "-              <> msg refName-              <> " is not defined by operation "-              <> msg (getOperationName operationName)-              <> ".",-          validationLocations = [refPosition]-        }+      ( ( "Variable "+            <> msg refName+            <> " is not defined by operation "+            <> msg (getOperationName operationName)+            <> "."+        )+          `at` refPosition+      )+        `withPath` path -class Unknown c ref ctx where-  -- type UnknownSelector c-  unknown :: Scope -> ctx -> c -> ref -> ValidationError+class Unknown ref ctx where+  unknown :: Scope -> ctx -> ref -> GQLError  -- {...H} -> "Unknown fragment \"H\"."-instance Unknown (Fragments s) (Ref FieldName) ctx where-  unknown _ _ _ Ref {refName, refPosition} =-    ValidationError-      { validationMessage = "Unknown Fragment " <> msg refName <> ".",-        validationLocations = [refPosition]-      }+instance Unknown (Ref FragmentName) ctx where+  unknown Scope {path} _ Ref {refName, refPosition} =+    (("Unknown Fragment " <> msg refName <> ".") `at` refPosition) `withPath` path -instance Unknown (Schema s) (Ref TypeName) ctx where-  unknown _ _ _ Ref {refName, refPosition} =-    ValidationError-      { validationMessage = "Unknown type " <> msg refName <> ".",-        validationLocations = [refPosition]-      }+instance Unknown (Ref TypeName) ctx where+  unknown Scope {path} _ Ref {refName, refPosition} =+    (("Unknown type " <> msg refName <> ".") `at` refPosition) `withPath` path -instance Unknown (FieldDefinition OUT s) (Argument CONST) ctx where-  unknown _ _ FieldDefinition {fieldName} Argument {argumentName, argumentPosition} =-    ValidationError-      { validationMessage = "Unknown Argument " <> msg argumentName <> " on Field " <> msg fieldName <> ".",-        validationLocations = [argumentPosition]-      }+instance Unknown (Argument s') ctx where+  unknown Scope {kind, path, fieldName} _ Argument {argumentName, argumentPosition} =+    ( ( "Unknown Argument "+          <> msg argumentName+          <> " on "+          <> scope kind+          <> " "+          <> msg fieldName+          <> "."+      )+        `at` argumentPosition+    )+      `withPath` path+    where+      scope DIRECTIVE = "Directive"+      scope _ = "Field" -instance Unknown (FieldsDefinition IN s) (ObjectEntry valueS) (InputContext ctx) where+instance Unknown (Ref FieldName) ctx where+  unknown Scope {currentTypeName, path} _ ref =+    unknownSelectionField currentTypeName ref `withPath` path++instance Unknown (ObjectEntry valueS) (InputContext ctx) where   unknown-    Scope {position}+    Scope {position, path}     ctx-    _     ObjectEntry {entryName} =-      withPosition position $-        renderInputPrefix ctx <> "Unknown Field " <> msgValidation entryName <> "."--instance Unknown (DirectiveDefinition s) (Argument s') ctx where-  unknown _ _ DirectiveDefinition {directiveDefinitionName} Argument {argumentName, argumentPosition} =-    ValidationError-      { validationMessage = "Unknown Argument " <> msg argumentName <> " on Directive " <> msg directiveDefinitionName <> ".",-        validationLocations = [argumentPosition]-      }--instance Unknown (DirectiveDefinitions s) (Directive s') ctx where-  unknown _ _ _ Directive {directiveName, directivePosition} =-    ValidationError-      { validationMessage = "Unknown Directive " <> msg directiveName <> ".",-        validationLocations = [directivePosition]-      }+      ( ( renderInputPrefix ctx+            <> "Unknown Field "+            <> msg entryName+            <> "."+        )+          `atPositions` position+      )+        `withPath` path -instance Unknown (FieldsDefinition OUT s) (Ref FieldName) (OperationContext s1 s2) where-  unknown Scope {currentTypeName} _ _ = unknownSelectionField currentTypeName+instance Unknown (Directive s') ctx where+  unknown Scope {path} _ Directive {directiveName, directivePosition} =+    (("Unknown Directive " <> msg directiveName <> ".") `at` directivePosition) `withPath` path  class KindViolation (t :: TypeCategory) ctx where-  kindViolation :: c t -> ctx -> ValidationError+  kindViolation :: c t -> ctx -> GQLError  instance KindViolation IMPLEMENTABLE (Fragment s) where   kindViolation _ Fragment {fragmentName, fragmentType, fragmentPosition} =-    ValidationError-      { validationMessage =-          "Fragment "-            <> msg fragmentName-            <> " cannot condition on non composite type "-            <> msg fragmentType-            <> ".",-        validationLocations = [fragmentPosition]-      }+    ( "Fragment "+        <> msg fragmentName+        <> " cannot condition on non composite type "+        <> msg fragmentType+        <> "."+    )+      `at` fragmentPosition  instance KindViolation IN (Variable s) where   kindViolation@@ -213,12 +200,10 @@         variablePosition,         variableType = TypeRef {typeConName}       } =-      ValidationError-        { validationMessage =-            "Variable "-              <> msg ("$" <> variableName)-              <> " cannot be non-input type "-              <> msg typeConName-              <> ".",-          validationLocations = [variablePosition]-        }+      ( "Variable "+          <> msg ("$" <> variableName)+          <> " cannot be non-input type "+          <> msg typeConName+          <> "."+      )+        `at` variablePosition
src/Data/Morpheus/Types/Internal/Validation/Internal.hs view
@@ -20,105 +20,97 @@   ) where +import Control.Monad.Except (MonadError (throwError)) import Data.Morpheus.Internal.Utils-  ( Failure (..),-    selectBy,+  ( fromElems,   ) import Data.Morpheus.Types.Internal.AST   ( ANY,     FromCategory,+    GQLError,     IMPLEMENTABLE,     IN,-    InternalError,     OBJECT,     OUT,-    Operation,     Operation (..),+    OrdMap,     TRUE,     ToOBJECT,     Token,-    TypeContent (..),-    TypeContent,-    TypeDefinition (..),-    TypeName (..),+    TypeName,     TypeRef,-    Typed,     UnionMember (..),     VALID,     fromAny,     fromCategory,     getOperationDataType,-    msgInternal,-    possibleInterfaceTypes,+    internal,+    msg,     typeConName,-    typed,-    untyped,   )+import Data.Morpheus.Types.Internal.AST.TypeSystem import Data.Morpheus.Types.Internal.Validation.Validator-  ( MonadContext,-    SelectionValidator,-    askSchema,+  ( SelectionValidator,+    ValidatorContext (schema),   ) import Relude  askType ::-  Constraints m c cat s =>+  Constraints m c cat s ctx =>   Typed cat s TypeRef ->-  m c (TypeDefinition cat s)+  m (TypeDefinition cat s) askType = untyped (__askType . typeConName)  askType2 ::-  Constraints m c cat s =>+  Constraints m c cat s ctx =>   Typed cat s TypeName ->-  m c (TypeDefinition cat s)+  m (TypeDefinition cat s) askType2 = untyped __askType  __askType ::-  Constraints m c cat s => TypeName -> m c (TypeDefinition cat s)+  Constraints m c cat s ctx => TypeName -> m (TypeDefinition cat s) __askType name =-  askSchema-    >>= selectBy (unknownType name) name+  asks schema+    >>= maybe (throwError (unknownType name)) pure . lookupDataType name     >>= kindConstraint  askTypeMember ::-  Constraints m c cat s =>+  Constraints m c cat s ctx =>   UnionMember cat s ->-  m c (TypeDefinition (ToOBJECT cat) s)+  m (TypeDefinition (ToOBJECT cat) s) askTypeMember = askType2 . typed memberName >=> constraintObject  askInterfaceTypes ::-  ( Failure InternalError (m c),-    Monad (m c),-    MonadContext m s c,+  ( MonadError GQLError m,+    MonadReader (ValidatorContext s ctx) m,     FromCategory (TypeContent TRUE) ANY IMPLEMENTABLE   ) =>   TypeDefinition IMPLEMENTABLE s ->-  m c [TypeDefinition IMPLEMENTABLE s]+  m (OrdMap TypeName (TypeDefinition IMPLEMENTABLE s)) askInterfaceTypes typeDef@TypeDefinition {typeName} =-  (typeDef :)-    <$> ( askSchema-            >>= traverse (validate . fromCategory) . possibleInterfaceTypes typeName-        )+  asks schema+    >>= traverse (validate . fromCategory) . possibleInterfaceTypes typeName+    >>= fromElems . (typeDef :)   where     validate (Just x) = pure x-    validate Nothing = failure ("TODO: invalid interface Types" :: InternalError)+    validate Nothing = throwError (internal "Invalid interface Types") -type Constraints m c cat s =-  ( Failure InternalError (m c),-    Monad (m c),-    MonadContext m s c,+type Constraints m c cat s ctx =+  ( MonadError GQLError m,+    Monad m,+    MonadReader (ValidatorContext s ctx) m,     KindErrors cat,     FromCategory (TypeContent TRUE) ANY cat   )  getOperationType :: Operation a -> SelectionValidator (TypeDefinition OBJECT VALID)-getOperationType operation = askSchema >>= getOperationDataType operation+getOperationType operation = asks schema >>= getOperationDataType operation -unknownType :: TypeName -> InternalError-unknownType name = "Type \"" <> msgInternal name <> "\" can't found in Schema."+unknownType :: TypeName -> GQLError+unknownType name = internal $ "Type \"" <> msg name <> "\" can't found in Schema."  type KindConstraint f c =-  ( Failure InternalError f,+  ( MonadError GQLError f,     FromCategory TypeDefinition ANY c   ) @@ -129,7 +121,7 @@   f (TypeDefinition k s) _kindConstraint err anyType =   maybe-    (failure $ violation err (typeName anyType))+    (throwError $ violation err (typeName anyType))     pure     (fromAny anyType) @@ -137,7 +129,7 @@   kindConstraint :: KindConstraint f c => TypeDefinition ANY s -> f (TypeDefinition c s)   constraintObject ::     ( Applicative f,-      Failure InternalError f+      MonadError GQLError f     ) =>     TypeDefinition c s ->     f (TypeDefinition (ToOBJECT c) s)@@ -145,19 +137,20 @@ instance KindErrors IN where   kindConstraint = _kindConstraint "input type"   constraintObject TypeDefinition {typeContent = DataInputObject {..}, ..} = pure TypeDefinition {typeContent = DataInputObject {..}, ..}-  constraintObject TypeDefinition {typeName} = failure (violation "input object" typeName)+  constraintObject TypeDefinition {typeName} = throwError (violation "input object" typeName)  instance KindErrors OUT where   kindConstraint = _kindConstraint "output type"   constraintObject TypeDefinition {typeContent = DataObject {..}, ..} = pure TypeDefinition {typeContent = DataObject {..}, ..}-  constraintObject TypeDefinition {typeName} = failure (violation "object" typeName)+  constraintObject TypeDefinition {typeName} = throwError (violation "object" typeName)  violation ::   Token ->   TypeName ->-  InternalError+  GQLError violation kind typeName =-  "Type \"" <> msgInternal typeName-    <> "\" must be an"-    <> msgInternal kind-    <> "."+  internal $+    "Type \"" <> msg typeName+      <> "\" must be an"+      <> msg kind+      <> "."
src/Data/Morpheus/Types/Internal/Validation/SchemaValidator.hs view
@@ -8,7 +8,6 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TupleSections #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE NoImplicitPrelude #-} @@ -16,76 +15,113 @@   ( SchemaValidator,     TypeSystemContext (..),     constraintInterface,-    inField,+    renderField,+    withLocalContext,+    runSchemaValidator,+    inInterface,     inType,+    inField,     inArgument,-    inInterface,+    ON_INTERFACE,+    ON_TYPE,+    TypeEntity (..),     Field (..),-    Interface (..),-    renderField,+    InterfaceName (..),+    PLACE,   ) where -import Data.Morpheus.Internal.Utils-  ( Failure (..),-  )+import Control.Monad.Except (throwError)+import Data.Morpheus.Ext.Result (GQLResult) import Data.Morpheus.Types.Internal.AST   ( ANY,     CONST,     FieldName,     FieldsDefinition,+    Name (unpackName),     OUT,     TypeContent (..),     TypeDefinition (..),     TypeName,-    ValidationError,-    msgValidation,+    mkBaseType,+    msg,   )+import Data.Morpheus.Types.Internal.AST.Type (TypeKind (KindObject))+import Data.Morpheus.Types.Internal.AST.TypeSystem (Schema)+import Data.Morpheus.Types.Internal.Config (Config)+import Data.Morpheus.Types.Internal.Validation (Scope (..), ScopeKind (TYPE), runValidator) import Data.Morpheus.Types.Internal.Validation.Validator   ( Validator (..),     renderField,     withContext,+    withScope,   ) import Relude hiding (local) -newtype TypeSystemContext c = TypeSystemContext-  {local :: c}-  deriving (Show)+inInterface ::+  TypeName ->+  SchemaValidator (TypeEntity 'ON_INTERFACE) v ->+  SchemaValidator (TypeEntity 'ON_TYPE) v+inInterface name = pushPath (unpackName name) . withLocalContext (\t -> t {interfaceName = OnInterface name})  inType ::   TypeName ->-  SchemaValidator TypeName v ->+  SchemaValidator (TypeEntity 'ON_TYPE) v ->   SchemaValidator () v-inType name = withLocalContext (const name)--inInterface ::-  TypeName ->-  SchemaValidator Interface v ->-  SchemaValidator TypeName v-inInterface interfaceName = withLocalContext (Interface interfaceName)+inType name = pushPath (unpackName name) . withLocalContext (const (TypeEntity OnType name))  inField ::   FieldName ->-  SchemaValidator (t, FieldName) v ->-  SchemaValidator t v-inField fname = withLocalContext (,fname)+  SchemaValidator (Field p) v ->+  SchemaValidator (TypeEntity p) v+inField fieldName = pushPath (unpackName fieldName) . withLocalContext (Field fieldName Nothing)  inArgument ::   FieldName ->-  SchemaValidator (t, Field) v ->-  SchemaValidator (t, FieldName) v-inArgument aname = withLocalContext (\(t1, f1) -> (t1, Field f1 aname))+  SchemaValidator (Field p) v ->+  SchemaValidator (Field p) v+inArgument name = pushPath (unpackName name) . withLocalContext (\field -> field {fieldArgument = Just name}) -data Interface = Interface-  { interfaceName :: TypeName,+data PLACE = ON_INTERFACE | ON_TYPE++type ON_INTERFACE = 'ON_INTERFACE++type ON_TYPE = 'ON_TYPE++data InterfaceName (p :: PLACE) where+  OnInterface :: TypeName -> InterfaceName 'ON_INTERFACE+  OnType :: InterfaceName 'ON_TYPE++data TypeEntity (p :: PLACE) = TypeEntity+  { interfaceName :: InterfaceName p,     typeName :: TypeName   } -data Field = Field+data Field p = Field   { fieldName :: FieldName,-    fieldArgument :: FieldName+    fieldArgument :: Maybe FieldName,+    fieldOf :: TypeEntity p   } +initialScope :: Scope+initialScope =+  Scope+    { position = Nothing,+      currentTypeName = "Root",+      currentTypeKind = KindObject Nothing,+      currentTypeWrappers = mkBaseType,+      kind = TYPE,+      fieldName = "Root",+      path = []+    }++newtype TypeSystemContext c = TypeSystemContext+  {local :: c}+  deriving (Show)++pushPath :: Text -> SchemaValidator a v -> SchemaValidator a v+pushPath name = withScope (\x -> x {path = path x <> [name]})+ withLocalContext :: (a -> b) -> SchemaValidator b v -> SchemaValidator a v withLocalContext = withContext . updateLocal @@ -94,6 +130,17 @@  type SchemaValidator c = Validator CONST (TypeSystemContext c) +runSchemaValidator :: Validator s (TypeSystemContext ()) a -> Config -> Schema s -> GQLResult a+runSchemaValidator value config sysSchema =+  runValidator+    value+    config+    sysSchema+    initialScope+    TypeSystemContext+      { local = ()+      }+ constraintInterface ::   TypeDefinition ANY CONST ->   SchemaValidator ctx (TypeName, FieldsDefinition OUT CONST)@@ -103,4 +150,4 @@       typeContent = DataInterface fields     } = pure (typeName, fields) constraintInterface TypeDefinition {typeName} =-  failure ["type " <> msgValidation typeName <> " must be an interface" :: ValidationError]+  throwError $ "type " <> msg typeName <> " must be an interface"
+ src/Data/Morpheus/Types/Internal/Validation/Scope.hs view
@@ -0,0 +1,110 @@+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE NoImplicitPrelude #-}++module Data.Morpheus.Types.Internal.Validation.Scope+  ( Scope (..),+    ScopeKind (..),+    renderScope,+    renderSection,+    setPosition,+    setSelection,+    setDirective,+    setType,+  )+where++import Data.Morpheus.Rendering.RenderGQL (RenderGQL, render)+import Data.Morpheus.Types.Internal.AST+  ( Directive (..),+    FieldName,+    GQLError,+    Msg (msg),+    Position,+    Ref (..),+    TypeDefinition (..),+    TypeKind,+    TypeName,+    TypeWrapper,+    kindOf,+  )+import Relude++data ScopeKind+  = DIRECTIVE+  | SELECTION+  | TYPE+  deriving (Show)++data Scope = Scope+  { position :: Maybe Position,+    currentTypeName :: TypeName,+    currentTypeKind :: TypeKind,+    currentTypeWrappers :: TypeWrapper,+    fieldName :: FieldName,+    kind :: ScopeKind,+    path :: [Text]+  }+  deriving (Show)++setSelection :: TypeDefinition a s -> Ref FieldName -> Scope -> Scope+setSelection currentType Ref {refName, refPosition} Scope {..} =+  Scope+    { fieldName = refName,+      -- path = path <> [unpackName refName],+      currentTypeName = typeName currentType,+      currentTypeKind = kindOf currentType,+      position = Just refPosition,+      ..+    }++setPosition ::+  Position ->+  Scope ->+  Scope+setPosition pos Scope {..} = Scope {position = Just pos, ..}++setDirective :: Directive s -> Scope -> Scope+setDirective Directive {..} Scope {..} =+  Scope+    { fieldName = directiveName,+      position = Just directivePosition,+      kind = DIRECTIVE,+      ..+    }++setType :: TypeDefinition c s -> TypeWrapper -> Scope -> Scope+setType t wrappers Scope {..} =+  Scope+    { currentTypeName = typeName t,+      currentTypeKind = kindOf t,+      currentTypeWrappers = wrappers,+      ..+    }++renderScope :: Scope -> GQLError+renderScope+  Scope+    { currentTypeName,+      currentTypeKind,+      fieldName+    } =+    renderSection+      "Scope"+      ( "referenced by type "+          <> render currentTypeName+          <> " of kind "+          <> render currentTypeKind+          <> " in field "+          <> render fieldName+      )++renderSection :: RenderGQL a => GQLError -> a -> GQLError+renderSection label content =+  "\n\n" <> label <> ":\n" <> line+    <> "\n\n"+    <> msg (render content)+    <> "\n\n"+  where+    line = stimes (50 :: Int) "-"
src/Data/Morpheus/Types/Internal/Validation/Validator.hs view
@@ -3,9 +3,9 @@ {-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RankNTypes #-}@@ -22,88 +22,76 @@     BaseValidator,     runValidator,     Constraint (..),-    withScope,-    withScopeType,-    withPosition,+    setSelection,     inField,     inputMessagePrefix,     InputSource (..),     InputContext (..),     OperationContext (..),-    CurrentSelection (..),     renderInputPrefix,     Prop (..),     --  Resolution,     ScopeKind (..),     inputValueSource,     Scope (..),-    withDirective,+    setDirective,     startInput,-    GetWith (..),-    SetWith (..),-    MonadContext (..),     withContext,     renderField,-    asks,+    -- asks,     asksScope,-    askSchema,     askVariables,     askFragments,-    DirectiveValidator,     ValidatorContext (..),     FragmentValidator,+    askTypeDefinitions,+    withScope,+    setPosition,   ) where -import Data.Morpheus.Error.Utils-  ( validationErrorMessage,-  )+import Control.Monad.Except (MonadError (catchError, throwError))+import Control.Monad.Reader (asks) import Data.Morpheus.Ext.Result-  ( Eventless,-  )-import Data.Morpheus.Internal.Utils-  ( Failure (..),-  )-import Data.Morpheus.Rendering.RenderGQL-  ( RenderGQL,-    render,+  ( GQLResult,   ) import Data.Morpheus.Types.Internal.AST-  ( Directive (..),+  ( ANY,     FieldDefinition (..),-    FieldName (..),+    FieldName,     Fragments,-    GQLError (..),-    GQLErrors,     IMPLEMENTABLE,     IN,-    InternalError,-    Message,-    Position,     RAW,-    Ref (..),     Schema,     Stage,     TypeCategory,     TypeDefinition (..),-    TypeKind (..),-    TypeName (..),+    TypeName,     TypeRef (..),-    TypeWrapper,     VALID,-    ValidationError (..),     Variable (..),     VariableDefinitions,-    intercalateName,-    kindOf,-    msg,-    msgValidation,+    intercalate,+    typeDefinitions,+    unpackName,   )+import Data.Morpheus.Types.Internal.AST.Error import Data.Morpheus.Types.Internal.Config (Config (..))+import Data.Morpheus.Types.Internal.Validation.Scope+  ( Scope (..),+    ScopeKind (..),+    renderScope,+    renderSection,+    setDirective,+    setPosition,+    setSelection,+  ) import Relude hiding   ( Constraint,     asks,     get,+    intercalate,   )  data Prop = Prop@@ -114,57 +102,33 @@  type Path = [Prop] -renderPath :: Path -> ValidationError+renderPath :: Path -> GQLError renderPath [] = ""-renderPath path = "in field " <> msgValidation (intercalateName "." $ fmap propName path) <> ": "+renderPath path = "in field " <> msg (intercalate "." $ fmap propName path) <> ": " -renderInputPrefix :: InputContext c -> ValidationError+renderInputPrefix :: InputContext c -> GQLError renderInputPrefix InputContext {inputPath, inputSource} =   renderSource inputSource <> renderPath inputPath -renderSource :: InputSource -> ValidationError+renderSource :: InputSource -> GQLError renderSource (SourceArgument argumentName) =-  "Argument " <> msgValidation argumentName <> " got invalid value. "+  "Argument " <> msg argumentName <> " got invalid value. " renderSource (SourceVariable Variable {variableName} _) =-  "Variable " <> msgValidation ("$" <> variableName) <> " got invalid value. "+  "Variable " <> msg ("$" <> variableName) <> " got invalid value. " renderSource SourceInputField {sourceTypeName, sourceFieldName, sourceArgumentName} =   "Field " <> renderField sourceTypeName sourceFieldName sourceArgumentName <> " got invalid default value. " -renderField :: TypeName -> FieldName -> Maybe FieldName -> ValidationError-renderField (TypeName tname) (FieldName fname) arg =-  msgValidation (tname <> "." <> fname <> renderArg arg)+renderField :: TypeName -> FieldName -> Maybe FieldName -> GQLError+renderField tname fname arg =+  msg (unpackName tname <> "." <> unpackName fname <> renderArg arg)   where-    renderArg (Just (FieldName argName)) = "(" <> argName <> ":)"+    renderArg (Just argName) = "(" <> unpackName argName <> ":)"     renderArg Nothing = "" -data ScopeKind-  = DIRECTIVE-  | SELECTION-  | TYPE-  deriving (Show)--data-  OperationContext-    (s1 :: Stage)-    (s2 :: Stage) = OperationContext+data OperationContext (s1 :: Stage) (s2 :: Stage) = OperationContext   { fragments :: Fragments s2,     variables :: VariableDefinitions s1,-    selection :: CurrentSelection-  }-  deriving (Show)--newtype CurrentSelection = CurrentSelection-  { operationName :: Maybe FieldName-  }-  deriving (Show)--data Scope = Scope-  { position :: Maybe Position,-    currentTypeName :: TypeName,-    currentTypeKind :: TypeKind,-    currentTypeWrappers :: [TypeWrapper],-    fieldname :: FieldName,-    kind :: ScopeKind+    operationName :: Maybe FieldName   }   deriving (Show) @@ -209,140 +173,37 @@               ..             } -inputValueSource ::-  forall m c s.-  ( GetWith c InputSource,-    MonadContext m s c-  ) =>-  m c InputSource-inputValueSource = get--asks ::-  ( MonadContext m s c,-    GetWith c t-  ) =>-  (t -> a) ->-  m c a-asks f = f <$> get--asksScope ::-  ( MonadContext m s c-  ) =>-  (Scope -> a) ->-  m c a-asksScope f = f <$> getGlobalContext scope+inputValueSource :: MonadReader (ValidatorContext s (InputContext c)) m => m InputSource+inputValueSource = asksLocal inputSource -setSelectionName ::-  (MonadContext m s c) =>-  FieldName ->-  m c a ->-  m c a-setSelectionName fieldname = setScope update-  where-    update ctx = ctx {fieldname}+asksScope :: MonadReader (ValidatorContext s ctx) m => (Scope -> a) -> m a+asksScope f = asks (f . scope) -askSchema ::-  ( MonadContext m s c-  ) =>-  m c (Schema s)-askSchema = getGlobalContext schema+askTypeDefinitions ::+  MonadReader (ValidatorContext s ctx) m =>+  m (HashMap TypeName (TypeDefinition ANY s))+askTypeDefinitions = asks (typeDefinitions . schema) -askVariables ::-  ( MonadContext m s c,-    GetWith c (VariableDefinitions VALID)-  ) =>-  m c (VariableDefinitions VALID)-askVariables = get+askVariables :: MonadReader (ValidatorContext s1 (OperationContext s2 s3)) m => m (VariableDefinitions s2)+askVariables = asksLocal variables -askFragments ::-  ( MonadContext m s c,-    GetWith c (Fragments s')-  ) =>-  m c (Fragments s')-askFragments = get+askFragments :: MonadReader (ValidatorContext s1 (OperationContext s2 s3)) m => m (Fragments s3)+askFragments = asksLocal fragments -runValidator :: Validator s ctx a -> Config -> Schema s -> Scope -> ctx -> Eventless a-runValidator (Validator x) config schema scope validatorCTX =+runValidator :: Validator s ctx a -> Config -> Schema s -> Scope -> ctx -> GQLResult a+runValidator (Validator x) config schema scope localContext =   runReaderT x ValidatorContext {..} -withContext ::-  (c' -> c) ->-  Validator s c a ->-  Validator s c' a+withContext :: (c' -> c) -> Validator s c a -> Validator s c' a withContext f = Validator . withReaderT (fmap f) . _runValidator -withDirective ::-  ( MonadContext m schemaS c-  ) =>-  Directive s ->-  m c a ->-  m c a-withDirective-  Directive-    { directiveName,-      directivePosition-    } = setSelectionName directiveName . setScope update-    where-      update Scope {..} =-        Scope-          { position = Just directivePosition,-            kind = DIRECTIVE,-            ..-          }--withScope ::-  ( MonadContext m s c-  ) =>-  TypeDefinition cat s ->-  Ref FieldName ->-  m c a ->-  m c a-withScope t@TypeDefinition {typeName} (Ref selName pos) =-  setSelectionName selName . setScope update-  where-    update Scope {..} =-      Scope-        { currentTypeName = typeName,-          currentTypeKind = kindOf t,-          position = Just pos,-          ..-        }--withScopeType ::-  ( MonadContext m s c-  ) =>-  (TypeDefinition cat s, [TypeWrapper]) ->-  m c a ->-  m c a-withScopeType (t@TypeDefinition {typeName}, wrappers) = setScope update-  where-    update Scope {..} =-      Scope-        { currentTypeName = typeName,-          currentTypeKind = kindOf t,-          currentTypeWrappers = wrappers,-          ..-        }--withPosition ::-  ( MonadContext m s c-  ) =>-  Position ->-  m c a ->-  m c a-withPosition pos = setScope update-  where-    update Scope {..} = Scope {position = Just pos, ..}--inputMessagePrefix :: InputValidator s ctx ValidationError+inputMessagePrefix :: InputValidator s ctx GQLError inputMessagePrefix =   renderInputPrefix-    . validatorCTX <$> Validator ask+    . localContext+    <$> Validator ask -startInput ::-  InputSource ->-  InputValidator s ctx a ->-  Validator s ctx a+startInput :: InputSource -> InputValidator s ctx a -> Validator s ctx a startInput inputSource = withContext update   where     update sourceContext =@@ -352,136 +213,82 @@           sourceContext         } -data ValidatorContext (s :: Stage) (ctx :: *) = ValidatorContext+data ValidatorContext (s :: Stage) (ctx :: Type) = ValidatorContext   { scope :: Scope,     schema :: Schema s,-    validatorCTX :: ctx,+    localContext :: ctx,     config :: Config   }-  deriving (Show, Functor)+  deriving+    ( Show,+      Functor+    )  newtype Validator s ctx a = Validator   { _runValidator ::       ReaderT         (ValidatorContext s ctx)-        Eventless+        GQLResult         a   }   deriving newtype     ( Functor,       Applicative,-      Monad+      Monad,+      MonadReader (ValidatorContext s ctx)     ) -instance MonadReader ctx (Validator s ctx) where-  ask = validatorCTX <$> Validator ask-  local = withContext+data ValidationTarget+  = Base+  | Fragments+  | Selections -type BaseValidator = Validator VALID (OperationContext RAW RAW)+type family ValidationStage (s :: ValidationTarget) where+  ValidationStage 'Base = OperationContext RAW RAW+  ValidationStage 'Fragments = OperationContext VALID RAW+  ValidationStage 'Selections = OperationContext VALID VALID +type ValidatorM (s :: ValidationTarget) = Validator VALID (ValidationStage s)++type BaseValidator = ValidatorM 'Base+ type FragmentValidator (s :: Stage) = Validator VALID (OperationContext VALID s) -type SelectionValidator = Validator VALID (OperationContext VALID VALID)+type SelectionValidator = ValidatorM 'Selections  type InputValidator s ctx = Validator s (InputContext ctx) -type DirectiveValidator ctx = Validator ctx--setScope ::-  (MonadContext m s c) =>+withScope ::+  (MonadReader (ValidatorContext s c) m) =>   (Scope -> Scope) ->-  m c b ->-  m c b-setScope f = setGlobalContext (mapScope f)--mapScope :: (Scope -> Scope) -> ValidatorContext s ctx -> ValidatorContext s ctx-mapScope f ValidatorContext {scope, ..} = ValidatorContext {scope = f scope, ..}---- Helpers-get :: (MonadContext m s ctx, GetWith ctx a) => m ctx a-get = getContext getWith--class-  Monad (m c) =>-  MonadContext m s c-    | m -> s-  where-  getGlobalContext :: (ValidatorContext s c -> a) -> m c a-  setGlobalContext :: (ValidatorContext s c -> ValidatorContext s c) -> m c b -> m c b-  getContext :: (c -> a) -> m c a-  setContext :: (c -> c) -> m c b -> m c b--instance MonadContext (Validator s) s c where-  getGlobalContext f = f <$> Validator ask-  getContext f = f . validatorCTX <$> Validator ask-  setGlobalContext f = Validator . withReaderT f . _runValidator-  setContext = withContext--class GetWith (c :: *) (v :: *) where-  getWith :: c -> v--instance GetWith (OperationContext VALID fragStage) (VariableDefinitions VALID) where-  getWith = variables--instance GetWith (InputContext ctx) InputSource where-  getWith = inputSource--instance GetWith (OperationContext varStage fragStage) (Fragments fragStage) where-  getWith = fragments---- Setters-class SetWith (c :: *) (v :: *) where-  setWith :: (v -> v) -> c -> c--instance SetWith (OperationContext s1 s2) CurrentSelection where-  setWith f OperationContext {selection = selection, ..} =-    OperationContext-      { selection = f selection,-        ..-      }--instance Failure [ValidationError] (Validator s ctx) where-  failure errors = do-    ctx <- Validator ask-    failValidator (fmap (fromValidatinError ctx) errors)+  m b ->+  m b+withScope f = local (\ValidatorContext {..} -> ValidatorContext {scope = f scope, ..}) -instance Failure ValidationError (Validator s ctx) where-  failure err = failure [err]+asksLocal :: MonadReader (ValidatorContext s c) m => (c -> a) -> m a+asksLocal f = asks (f . localContext) -failValidator :: GQLErrors -> Validator s ctx a-failValidator = Validator . lift . failure+instance MonadError GQLError (Validator s ctx) where+  throwError err = Validator $ do+    ctx <- ask+    throwError (fromValidationError ctx err)+  catchError (Validator x) f = Validator (catchError x (_runValidator . f)) -fromValidatinError :: ValidatorContext s ctx -> ValidationError -> GQLError-fromValidatinError+fromValidationError :: ValidatorContext s ctx -> GQLError -> GQLError+fromValidationError   context@ValidatorContext-    { config+    { config,+      scope = Scope {position, path}     }-  (ValidationError text locations) =-    GQLError-      { message,-        locations-      }-    where-      message-        | debug config = text <> renderContext context-        | otherwise = text---- can be only used for internal errors-instance-  (MonadContext (Validator s) s ctx) =>-  Failure InternalError (Validator s ctx)-  where-  failure inputMessage = do-    ctx <- Validator ask-    failure-      ( validationErrorMessage-          (position $ scope ctx)-          $ msg-            inputMessage-            <> renderContext ctx+  err+    | isInternal err || debug config =+      ( err <> renderContext context+          `atPositions` position       )+        `withPath` path+    | otherwise = err -renderContext :: ValidatorContext s ctx -> Message+renderContext :: ValidatorContext s ctx -> GQLError renderContext   ValidatorContext     { schema,@@ -489,29 +296,3 @@     } =     renderScope scope       <> renderSection "SchemaDefinition" schema--renderScope :: Scope -> Message-renderScope-  Scope-    { currentTypeName,-      currentTypeKind,-      fieldname-    } =-    renderSection-      "Scope"-      ( "referenced by type "-          <> render currentTypeName-          <> " of kind "-          <> render currentTypeKind-          <> " in field "-          <> render fieldname-      )--renderSection :: RenderGQL a => Message -> a -> Message-renderSection label content =-  "\n\n" <> label <> ":\n" <> line-    <> "\n\n"-    <> msg (render content)-    <> "\n\n"-  where-    line = stimes (50 :: Int) "-"
src/Data/Morpheus/Types/SelectionTree.hs view
@@ -8,14 +8,13 @@ -- Description : A simple interface for Morpheus internal Selection Set's representation. module Data.Morpheus.Types.SelectionTree where -import Data.Morpheus.Internal.Utils (elems, keyOf)+import Data.Morpheus.Internal.Utils (keyOf) import Data.Morpheus.Types.Internal.AST-  ( FieldName (..),-    Selection (..),-    Selection (selectionContent),-    SelectionContent (SelectionField, SelectionSet, UnionSelection),+  ( Selection (..),+    SelectionContent (..),     UnionTag (..),     VALID,+    unpackName,   ) import Data.Text (unpack) import Relude@@ -41,14 +40,15 @@    getChildrenList node = case selectionContent node of     SelectionField -> mempty-    (SelectionSet deeperSel) -> elems deeperSel-    (UnionSelection sel) ->-      concatMap-        (elems . unionTagSelection)-        (elems sel)+    (SelectionSet deeperSel) -> toList deeperSel+    (UnionSelection interfaceSelection sel) ->+      toList interfaceSelection+        <> concatMap+          (toList . unionTagSelection)+          (toList sel)    getName =     fromString       . unpack-      . readName+      . unpackName       . keyOf
+ src/Data/Morpheus/Validation/Document/Interface.hs view
@@ -0,0 +1,114 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DuplicateRecordFields #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE TypeFamilies #-}++module Data.Morpheus.Validation.Document.Interface+  ( validateImplements,+  )+where++import Control.Monad.Except (throwError)+import Data.Morpheus.Error.Document.Interface+  ( ImplementsError (..),+    partialImplements,+  )+import Data.Morpheus.Internal.Utils+  ( KeyOf (..),+    empty,+    selectOr,+  )+import Data.Morpheus.Types.Internal.AST+  ( ArgumentDefinition (..),+    ArgumentsDefinition,+    CONST,+    FieldContent (..),+    FieldDefinition (..),+    FieldsDefinition,+    OUT,+    Subtyping (..),+    TRUE,+    TypeName,+    TypeRef (..),+  )+import Data.Morpheus.Types.Internal.Validation+  ( ValidatorContext (localContext),+    selectType,+  )+import Data.Morpheus.Types.Internal.Validation.SchemaValidator+  ( Field (..),+    ON_INTERFACE,+    ON_TYPE,+    PLACE,+    SchemaValidator,+    TypeEntity (..),+    TypeSystemContext (..),+    constraintInterface,+    inArgument,+    inField,+    inInterface,+  )+import Relude hiding (empty, local)++validateImplements ::+  [TypeName] ->+  FieldsDefinition OUT CONST ->+  SchemaValidator (TypeEntity ON_TYPE) [TypeName]+validateImplements interfaceNames objectFields =+  traverse (selectType >=> constraintInterface >=> hasCompatibleFields) interfaceNames+    $> interfaceNames+  where+    hasCompatibleFields :: (TypeName, FieldsDefinition OUT CONST) -> SchemaValidator (TypeEntity ON_TYPE) ()+    hasCompatibleFields (typeName, fields) = inInterface typeName $ isCompatibleTo objectFields fields++class StructuralCompatibility a where+  type Context a :: PLACE -> Type+  type Context a = Field++  -- Object (which implements interface) -> Interface -> Validation+  isCompatibleTo :: a -> a -> SchemaValidator ((Context a) ON_INTERFACE) ()++  isCompatibleBy :: (t -> a) -> t -> t -> SchemaValidator ((Context a) ON_INTERFACE) ()+  isCompatibleBy f a b = f a `isCompatibleTo` f b++instance StructuralCompatibility (FieldsDefinition OUT s) where+  type Context (FieldsDefinition OUT s) = TypeEntity+  isCompatibleTo objFields = traverse_ checkInterfaceField+    where+      checkInterfaceField interfaceField@FieldDefinition {fieldName} =+        inField fieldName $ selectOr err (`isCompatibleTo` interfaceField) fieldName objFields+        where+          err = failImplements Missing++instance StructuralCompatibility (FieldDefinition OUT s) where+  f1 `isCompatibleTo` f2 =+    isCompatibleBy fieldType f1 f2+      *> isCompatibleBy (fieldArgs . fieldContent) f1 f2++fieldArgs :: Maybe (FieldContent TRUE OUT s) -> ArgumentsDefinition s+fieldArgs (Just (FieldArgs args)) = args+fieldArgs _ = empty++instance StructuralCompatibility (ArgumentsDefinition s) where+  subArguments `isCompatibleTo` arguments = traverse_ hasCompatibleSubArgument arguments+    where+      hasCompatibleSubArgument argument =+        inArgument (keyOf argument) $+          selectOr (failImplements Missing) (`isCompatibleTo` argument) (keyOf argument) subArguments++instance StructuralCompatibility (ArgumentDefinition s) where+  isCompatibleTo = isCompatibleBy (fieldType . argument)++instance StructuralCompatibility TypeRef where+  t1 `isCompatibleTo` t2+    | t1 `isSubtype` t2 = pure ()+    | otherwise = failImplements UnexpectedType {expectedType = t2, foundType = t1}++failImplements ::+  ImplementsError ->+  SchemaValidator (Field ON_INTERFACE) a+failImplements err = do+  x <- asks (local . localContext)+  throwError $ partialImplements x err
src/Data/Morpheus/Validation/Document/Validation.hs view
@@ -4,13 +4,13 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-}-{-# LANGUAGE KindSignatures #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Validation.Document.Validation@@ -18,75 +18,52 @@   ) where -import Data.Morpheus.Error.Document.Interface-  ( ImplementsError (..),-    PartialImplements (..),-  ) import Data.Morpheus.Ext.Result-  ( Eventless,-  )-import Data.Morpheus.Ext.SemigroupM-  ( (<:>),-  )-import Data.Morpheus.Internal.Utils-  ( KeyOf (..),-    Selectable (..),-    elems,-    empty,-    failure,+  ( GQLResult,   )+import Data.Morpheus.Internal.Utils ((<:>)) import Data.Morpheus.Schema.Schema   ( internalSchema,   ) import Data.Morpheus.Types.Internal.AST   ( ArgumentDefinition (..),-    ArgumentsDefinition,     CONST,     DataEnumValue (..),     DirectiveDefinition (..),     DirectiveLocation (..),     FieldContent (..),     FieldDefinition (..),-    FieldName (..),-    FieldsDefinition,+    FieldName,     IN,     OUT,     Schema (..),-    Schema (..),     TRUE,     TypeCategory,     TypeContent (..),     TypeDefinition (..),-    TypeKind (..),-    TypeName,     TypeRef (..),     Typed (..),     UnionMember (..),     VALID,     Value,-    isWeaker,   ) import Data.Morpheus.Types.Internal.Config (Config (..)) import Data.Morpheus.Types.Internal.Validation   ( InputSource (..),-    InputValidator,-    Scope (..),-    ScopeKind (..),-    runValidator,-    selectType,+    ValidatorContext (localContext),     startInput,   ) import Data.Morpheus.Types.Internal.Validation.SchemaValidator   ( Field (..),-    Interface (..),+    ON_TYPE,     SchemaValidator,+    TypeEntity (..),     TypeSystemContext (..),-    constraintInterface,-    inArgument,     inField,-    inInterface,     inType,+    runSchemaValidator,   )+import Data.Morpheus.Validation.Document.Interface (validateImplements) import Data.Morpheus.Validation.Internal.Directive   ( validateDirectives,   )@@ -96,70 +73,58 @@ import Relude hiding (empty, local)  class ValidateSchema s where-  validateSchema :: Bool -> Config -> Schema s -> Eventless (Schema VALID)+  validateSchema :: Bool -> Config -> Schema s -> GQLResult (Schema VALID)  instance ValidateSchema CONST where-  validateSchema-    withSystem-    config-    schema@Schema+  validateSchema withSystem config schema = do+    sysSchema <-+      if withSystem+        then internalSchema <:> schema+        else pure schema+    runSchemaValidator (typeCheck schema) config sysSchema++instance ValidateSchema VALID where+  validateSchema _ _ = pure++----- TypeCheck -------------------------------+---+---+---+class TypeCheck a where+  type TypeContext a :: Type+  type TypeContext a = ()+  typeCheck :: a CONST -> SchemaValidator (TypeContext a) (a VALID)++instance TypeCheck Schema where+  typeCheck+    Schema       { types,         query,         mutation,         subscription,         directiveDefinitions-      } = do-      sysSchema <--        if withSystem-          then internalSchema <:> schema-          else pure schema-      runValidator-        __validateSchema-        config-        sysSchema-        Scope-          { position = Nothing,-            currentTypeName = "Root",-            currentTypeKind = KindObject Nothing,-            currentTypeWrappers = [],-            kind = TYPE,-            fieldname = "Root"-          }-        TypeSystemContext-          { local = ()-          }-      where-        __validateSchema :: SchemaValidator () (Schema VALID)-        __validateSchema =-          Schema-            <$> traverse validateType types-            <*> validateType query-            <*> validateOptional validateType mutation-            <*> validateOptional validateType subscription-            <*> traverse validateDirectiveDefinition directiveDefinitions--validateOptional :: Applicative f => (a -> f b) -> Maybe a -> f (Maybe b)-validateOptional f = maybe (pure Nothing) (fmap Just . f)--instance ValidateSchema VALID where-  validateSchema _ _ = pure+      } =+      Schema+        <$> traverse typeCheck types+        <*> typeCheck query+        <*> traverse typeCheck mutation+        <*> traverse typeCheck subscription+        <*> traverse typeCheck directiveDefinitions -validateType ::-  TypeDefinition cat CONST ->-  SchemaValidator () (TypeDefinition cat VALID)-validateType-  TypeDefinition-    { typeName,-      typeDescription,-      typeDirectives,-      typeContent-    } =-    inType typeName $-      TypeDefinition-        typeDescription-        typeName-        <$> validateDirectives (typeDirectiveLocation typeContent) typeDirectives-        <*> validateTypeContent typeContent+instance TypeCheck (TypeDefinition cat) where+  typeCheck+    TypeDefinition+      { typeName,+        typeDescription,+        typeDirectives,+        typeContent+      } =+      inType typeName $+        TypeDefinition+          typeDescription+          typeName+          <$> validateDirectives (typeDirectiveLocation typeContent) typeDirectives+          <*> typeCheck typeContent  typeDirectiveLocation :: TypeContent a b c -> DirectiveLocation typeDirectiveLocation DataObject {} = OBJECT@@ -170,36 +135,37 @@ typeDirectiveLocation DataUnion {} = UNION typeDirectiveLocation DataInterface {} = INTERFACE -validateTypeContent ::-  TypeContent TRUE cat CONST ->-  SchemaValidator TypeName (TypeContent TRUE cat VALID)-validateTypeContent-  DataObject-    { objectImplements,-      objectFields-    } =+instance TypeCheck (TypeContent TRUE cat) where+  type TypeContext (TypeContent TRUE cat) = TypeEntity ON_TYPE+  typeCheck DataObject {objectImplements, objectFields} =     DataObject       <$> validateImplements objectImplements objectFields-      <*> traverse validateField objectFields-validateTypeContent DataInputObject {inputObjectFields} =-  DataInputObject <$> traverse validateField inputObjectFields-validateTypeContent DataScalar {..} = pure DataScalar {..}-validateTypeContent DataEnum {enumMembers} = DataEnum <$> traverse validateEnumMember enumMembers-validateTypeContent DataInputUnion {inputUnionMembers} =-  DataInputUnion <$> traverse validateUnionMember inputUnionMembers-validateTypeContent DataUnion {unionMembers} = DataUnion <$> traverse validateUnionMember unionMembers-validateTypeContent (DataInterface fields) =-  DataInterface <$> traverse validateField fields--validateEnumMember ::-  DataEnumValue CONST -> SchemaValidator TypeName (DataEnumValue VALID)-validateEnumMember DataEnumValue {enumDirectives = directives, ..} =-  DataEnumValue enumDescription enumName-    <$> validateDirectives ENUM_VALUE directives+      <*> traverse typeCheck objectFields+  typeCheck DataInputObject {inputObjectFields} =+    DataInputObject <$> traverse typeCheck inputObjectFields+  typeCheck DataScalar {..} = pure DataScalar {..}+  typeCheck DataEnum {enumMembers} = DataEnum <$> traverse typeCheck enumMembers+  typeCheck DataInputUnion {inputUnionMembers} =+    DataInputUnion <$> traverse typeCheck inputUnionMembers+  typeCheck DataUnion {unionMembers} = DataUnion <$> traverse typeCheck unionMembers+  typeCheck (DataInterface fields) = DataInterface <$> traverse typeCheck fields -validateUnionMember ::-  UnionMember cat CONST -> SchemaValidator TypeName (UnionMember cat VALID)-validateUnionMember UnionMember {..} = pure UnionMember {..}+instance FieldDirectiveLocation cat => TypeCheck (FieldDefinition cat) where+  type TypeContext (FieldDefinition cat) = TypeEntity ON_TYPE+  typeCheck FieldDefinition {..} =+    inField+      fieldName+      ( FieldDefinition+          fieldDescription+          fieldName+          fieldType+          <$> traverse checkFieldContent fieldContent+          <*> validateDirectives (directiveLocation (Proxy @cat)) fieldDirectives+      )+    where+      checkFieldContent :: FieldContent TRUE cat CONST -> SchemaValidator (Field ON_TYPE) (FieldContent TRUE cat VALID)+      checkFieldContent (FieldArgs args) = FieldArgs <$> traverse typeCheck args+      checkFieldContent (DefaultInputValue value) = DefaultInputValue <$> validateDefaultValue fieldType Nothing value  class FieldDirectiveLocation (cat :: TypeCategory) where   directiveLocation :: Proxy cat -> DirectiveLocation@@ -210,181 +176,44 @@ instance FieldDirectiveLocation IN where   directiveLocation _ = INPUT_FIELD_DEFINITION -validateField ::-  forall cat.-  FieldDirectiveLocation cat =>-  FieldDefinition cat CONST ->-  SchemaValidator TypeName (FieldDefinition cat VALID)-validateField field@FieldDefinition {..} =-  inField-    fieldName-    ( FieldDefinition-        fieldDescription-        fieldName-        fieldType-        <$> validateOptional (checkFieldContent field) fieldContent-        <*> validateDirectives (directiveLocation (Proxy @cat)) fieldDirectives-    )--checkFieldContent ::-  FieldDefinition cat CONST ->-  FieldContent TRUE cat CONST ->-  SchemaValidator (TypeName, FieldName) (FieldContent TRUE cat VALID)-checkFieldContent _ (FieldArgs argsDef) = FieldArgs <$> validateArgumentsDefinition argsDef-checkFieldContent FieldDefinition {fieldType} (DefaultInputValue value) = do-  (typeName, fName) <- asks local-  DefaultInputValue-    <$> startInput-      (SourceInputField typeName fName Nothing)-      (validateDefaultValue fieldType value)--validateArgumentsDefinition ::-  ArgumentsDefinition CONST ->-  SchemaValidator (TypeName, FieldName) (ArgumentsDefinition VALID)-validateArgumentsDefinition = traverse validateArgumentDefinition--validateArgumentDefinition ::-  ArgumentDefinition CONST ->-  SchemaValidator (TypeName, FieldName) (ArgumentDefinition VALID)-validateArgumentDefinition (ArgumentDefinition FieldDefinition {..}) =-  ArgumentDefinition-    <$> ( FieldDefinition-            fieldDescription-            fieldName-            fieldType-            <$> validateOptional (validateArgumentDefaultValue fieldName fieldType) fieldContent-            <*> validateDirectives ARGUMENT_DEFINITION fieldDirectives-        )--validateArgumentDefaultValue ::-  FieldName ->-  TypeRef ->-  FieldContent TRUE IN CONST ->-  SchemaValidator (TypeName, FieldName) (FieldContent TRUE IN VALID)-validateArgumentDefaultValue argName fieldType (DefaultInputValue value) =-  do-    (typeName, fName) <- asks local-    v <--      startInput-        (SourceInputField typeName fName (Just argName))-        (validateDefaultValue fieldType value)-    pure (DefaultInputValue v)---- INETRFACE------------------------------validateImplements ::-  [TypeName] ->-  FieldsDefinition OUT CONST ->-  SchemaValidator TypeName [TypeName]-validateImplements objectImplements objectFields =-  ( traverse selectInterface objectImplements-      >>= traverse_ (mustBeSubset objectFields)-  )-    $> objectImplements--mustBeSubset ::-  FieldsDefinition OUT CONST ->-  (TypeName, FieldsDefinition OUT CONST) ->-  SchemaValidator TypeName ()-mustBeSubset objFields (typeName, fields) =-  inInterface typeName $-    traverse_ (checkInterfaceField objFields) (elems fields)--checkInterfaceField ::-  FieldsDefinition OUT CONST ->-  FieldDefinition OUT CONST ->-  SchemaValidator Interface ()-checkInterfaceField-  objFields-  interfaceField@FieldDefinition-    { fieldName,-      fieldDirectives-    } =-    inField fieldName $-      validateDirectives FIELD_DEFINITION fieldDirectives-        *> selectOr err (isSuptype interfaceField) fieldName objFields-    where-      err = failImplements Missing--class PartialImplements ctx => TypeEq a ctx where-  isSuptype :: a -> a -> SchemaValidator ctx ()--instance TypeEq (FieldDefinition OUT CONST) (Interface, FieldName) where-  FieldDefinition-    { fieldType,-      fieldContent = args1-    }-    `isSuptype` FieldDefinition-      { fieldType = fieldType',-        fieldContent = args2-      } = (fieldType `isSuptype` fieldType') *> (args1 `isSuptype` args2)--instance TypeEq (Maybe (FieldContent TRUE OUT s)) (Interface, FieldName) where-  f1 `isSuptype` f2 = toARgs f1 `isSuptype` toARgs f2-    where-      toARgs :: Maybe (FieldContent TRUE OUT s) -> ArgumentsDefinition s-      toARgs (Just (FieldArgs args)) = args-      toARgs _ = empty--instance (PartialImplements ctx) => TypeEq TypeRef ctx where-  t1@TypeRef-    { typeConName,-      typeWrappers = w1-    }-    `isSuptype` t2@TypeRef-      { typeConName = name',-        typeWrappers = w2-      }-      | typeConName == name' && not (isWeaker w2 w1) = pure ()-      | otherwise =-        failImplements UnexpectedType {expectedType = t1, foundType = t2}--elemIn ::-  ( KeyOf k a,-    Selectable k a c,-    TypeEq a ctx-  ) =>-  a ->-  c ->-  SchemaValidator ctx ()-elemIn el = selectOr (failImplements Missing) (isSuptype el) (keyOf el)+instance TypeCheck DirectiveDefinition where+  typeCheck DirectiveDefinition {directiveDefinitionArgs = arguments, ..} =+    inType "Directive" $+      inField directiveDefinitionName $ do+        directiveDefinitionArgs <- traverse typeCheck arguments+        pure DirectiveDefinition {..} -instance TypeEq (ArgumentsDefinition s) (Interface, FieldName) where-  args1 `isSuptype` args2 = traverse_ validateArg (elems args1)+instance TypeCheck ArgumentDefinition where+  type TypeContext ArgumentDefinition = Field ON_TYPE+  typeCheck (ArgumentDefinition FieldDefinition {..}) =+    ArgumentDefinition+      <$> ( FieldDefinition+              fieldDescription+              fieldName+              fieldType+              <$> traverse checkArgumentDefaultValue fieldContent+              <*> validateDirectives ARGUMENT_DEFINITION fieldDirectives+          )     where-      validateArg arg = inArgument (keyOf arg) $ elemIn arg args2--instance TypeEq (ArgumentDefinition s) (Interface, Field) where-  arg1 `isSuptype` arg2 = fieldType (argument arg1) `isSuptype` fieldType (argument arg2)----------------------------------selectInterface ::-  TypeName ->-  SchemaValidator ctx (TypeName, FieldsDefinition OUT CONST)-selectInterface = selectType >=> constraintInterface--failImplements ::-  PartialImplements ctx =>-  ImplementsError ->-  SchemaValidator ctx a-failImplements err = do-  x <- asks local-  failure $ partialImplements x err---- DEFAULT VALUE+      checkArgumentDefaultValue (DefaultInputValue value) =+        DefaultInputValue+          <$> validateDefaultValue fieldType (Just fieldName) value  validateDefaultValue ::   TypeRef ->+  Maybe FieldName ->   Value CONST ->-  InputValidator-    CONST-    (TypeSystemContext (TypeName, FieldName))-    (Value VALID)-validateDefaultValue typeRef =-  validateInputByTypeRef (Typed typeRef)+  SchemaValidator (Field ON_TYPE) (Value VALID)+validateDefaultValue typeRef argName value = do+  Field fName _ (TypeEntity _ typeName) <- asks (local . localContext)+  startInput (SourceInputField typeName fName argName) (validateInputByTypeRef (Typed typeRef) value) -validateDirectiveDefinition :: DirectiveDefinition CONST -> SchemaValidator () (DirectiveDefinition VALID)-validateDirectiveDefinition DirectiveDefinition {directiveDefinitionArgs = args, ..} =-  inType "Directive" $ inField directiveDefinitionName $ do-    directiveDefinitionArgs <- validateArgumentsDefinition args-    pure DirectiveDefinition {..}+instance TypeCheck DataEnumValue where+  type TypeContext DataEnumValue = TypeEntity ON_TYPE+  typeCheck DataEnumValue {enumDirectives = directives, ..} =+    DataEnumValue enumDescription enumName+      <$> validateDirectives ENUM_VALUE directives++instance TypeCheck (UnionMember cat) where+  type TypeContext (UnionMember cat) = TypeEntity ON_TYPE+  typeCheck UnionMember {..} = pure UnionMember {..}
src/Data/Morpheus/Validation/Internal/Arguments.hs view
@@ -18,16 +18,12 @@   ) where -import Data.Morpheus.Internal.Utils-  ( empty,-  ) import Data.Morpheus.Types.Internal.AST   ( Argument (..),     ArgumentDefinition (..),     Arguments,     ArgumentsDefinition,     CONST,-    DirectiveDefinition,     DirectiveDefinition (..),     FieldDefinition (..),     IN,@@ -38,14 +34,14 @@     VALID,     Value (..),     VariableDefinitions,-    fieldContentArgs,+    fieldArguments,     typed,   ) import Data.Morpheus.Types.Internal.Validation   ( FragmentValidator,-    GetWith,     InputSource (..),     MissingRequired,+    OperationContext,     Scope (..),     Validator,     askVariables,@@ -53,8 +49,9 @@     selectKnown,     selectRequired,     selectWithDefaultValue,+    setPosition,     startInput,-    withPosition,+    withScope,   ) import Data.Morpheus.Validation.Internal.Value   ( ValidateWithDefault,@@ -63,8 +60,7 @@ import Relude hiding (empty)  type VariableConstraints ctx =-  ( GetWith ctx (VariableDefinitions VALID),-    MissingRequired (VariableDefinitions VALID) ctx+  ( MissingRequired (VariableDefinitions VALID) ctx   )  type ArgumentsConstraints c schemaS valueS =@@ -104,23 +100,23 @@ validateArgumentValue   field   Argument {argumentValue, ..} =-    withPosition argumentPosition-      $ startInput (SourceArgument argumentName)-      $ Argument-        argumentPosition-        argumentName-        <$> validateInputByTypeRef (typed fieldType field) argumentValue+    withScope (setPosition argumentPosition) $+      startInput (SourceArgument argumentName) $+        Argument+          argumentPosition+          argumentName+          <$> validateInputByTypeRef (typed fieldType field) argumentValue  validateFieldArguments ::   FieldDefinition OUT VALID ->   Arguments RAW ->   FragmentValidator s (Arguments VALID)-validateFieldArguments fieldDef@FieldDefinition {fieldContent} =+validateFieldArguments field =   validateArguments-    (`selectKnown` fieldDef)-    argsDef+    (`selectKnown` arguments)+    arguments   where-    argsDef = maybe empty fieldContentArgs fieldContent+    arguments = fieldArguments field  validateDirectiveArguments ::   ArgumentsConstraints ctx schemaStage valueStage =>@@ -128,11 +124,11 @@   Arguments valueStage ->   Validator schemaStage ctx (Arguments VALID) validateDirectiveArguments-  directiveDef@DirectiveDefinition+  DirectiveDefinition     { directiveDefinitionArgs     } =     validateArguments-      (`selectKnown` directiveDef)+      (`selectKnown` directiveDefinitionArgs)       directiveDefinitionArgs  validateArguments ::@@ -149,13 +145,13 @@ class Resolve f s ctx where   resolve :: f s -> Validator schemaS ctx (f CONST) -instance VariableConstraints ctx => Resolve Argument RAW ctx where+instance VariableConstraints (OperationContext VALID s) => Resolve Argument RAW (OperationContext VALID s) where   resolve (Argument key position val) = Argument key position <$> resolve val  instance Resolve f CONST ctx where   resolve = pure -instance VariableConstraints ctx => Resolve Value RAW ctx where+instance VariableConstraints (OperationContext VALID s) => Resolve Value RAW (OperationContext VALID s) where   resolve Null = pure Null   resolve (Scalar x) = pure $ Scalar x   resolve (Enum x) = pure $ Enum x@@ -166,5 +162,5 @@       >>= fmap (ResolvedVariable ref)         . selectRequired ref -instance VariableConstraints ctx => Resolve ObjectEntry RAW ctx where+instance VariableConstraints (OperationContext VALID s) => Resolve ObjectEntry RAW (OperationContext VALID s) where   resolve (ObjectEntry name value) = ObjectEntry name <$> resolve value
src/Data/Morpheus/Validation/Internal/Directive.hs view
@@ -17,12 +17,9 @@   ) where -import Data.Morpheus.Error.Utils-  ( validationErrorMessage,-  )+import Control.Monad.Except (throwError) import Data.Morpheus.Internal.Utils-  ( Failure (..),-    selectOr,+  ( selectOr,   ) import Data.Morpheus.Types.Internal.AST   ( Argument (..),@@ -36,14 +33,16 @@     Schema (..),     VALID,     Value (..),+    at,     msg,   ) import Data.Morpheus.Types.Internal.Validation   ( Validator,-    askSchema,+    ValidatorContext (schema),     selectKnown,     selectRequired,-    withDirective,+    setDirective,+    withScope,   ) import Data.Morpheus.Validation.Internal.Arguments   ( ArgumentsConstraints,@@ -64,8 +63,8 @@   Directive s ->   Validator schemaS c (Directive VALID) validate location directive@Directive {..} =-  withDirective directive $ do-    Schema {directiveDefinitions} <- askSchema+  withScope (setDirective directive) $ do+    directiveDefinitions <- asks (directiveDefinitions . schema)     directiveDef <- selectKnown directive directiveDefinitions     Directive directivePosition directiveName       <$> ( validateDirectiveLocation location directive directiveDef@@ -83,10 +82,9 @@   DirectiveDefinition {directiveDefinitionLocations}     | loc `elem` directiveDefinitionLocations = pure ()     | otherwise =-      failure $-        validationErrorMessage-          (Just directivePosition)-          ("Directive " <> msg directiveName <> " may not to be used on " <> msg loc)+      throwError $+        ("Directive " <> msg directiveName <> " may not to be used on " <> msg loc)+          `at` directivePosition  directiveFulfilled ::   Bool ->@@ -117,7 +115,9 @@   Validator schemaS ctx Bool assertArgument asserted Argument {argumentValue = Scalar (Boolean actual)} = pure (asserted == actual) assertArgument _ Argument {argumentValue, argumentPosition} =-  failure-    $ validationErrorMessage-      (Just argumentPosition)-    $ "Expected type Boolean!, found " <> msg argumentValue <> "."+  throwError $+    ( "Expected type Boolean!, found "+        <> msg argumentValue+        <> "."+    )+      `at` argumentPosition
src/Data/Morpheus/Validation/Internal/Value.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE DuplicateRecordFields #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-}@@ -14,21 +15,20 @@   ) where +import Control.Monad.Except (throwError) import Data.Morpheus.Error.Input (typeViolation) import Data.Morpheus.Error.Variable (incompatibleVariableType) import Data.Morpheus.Internal.Utils-  ( Failure (..),-    singleton,+  ( singleton,   ) import Data.Morpheus.Types.Internal.AST   ( CONST,     DataEnumValue (..),-    DataInputUnion,     FieldDefinition (..),     FieldName,     FieldsDefinition,+    GQLError,     IN,-    Message,     Object,     ObjectEntry (..),     Ref (..),@@ -37,51 +37,43 @@     TRUE,     TypeContent (..),     TypeDefinition (..),-    TypeName (..),+    TypeName,     TypeRef (..),     TypeWrapper (..),     Typed (..),     UnionMember (..),+    UnionTypeDefinition,     VALID,     ValidValue,     Value (..),     Variable (..),-    Variable (..),     VariableContent (..),+    atPositions,     isNullable,-    isWeaker,+    isSubtype,+    mkMaybeType,     mkTypeRef,     msg,-    msgValidation,+    packName,     toCategory,-    toFieldName,     typed,     unitFieldName,     unitTypeName,     untyped,-    withPosition,   ) import Data.Morpheus.Types.Internal.Validation-  ( InputContext,-    InputSource (..),-    InputValidator,-    Scope (..),-    Validator,-    askType,+  ( askType,     askTypeMember,-    asksScope,     constraintInputUnion,-    inField,-    inputMessagePrefix,-    inputValueSource,     selectKnown,     selectWithDefaultValue,-    withScopeType,   )+import Data.Morpheus.Types.Internal.Validation.Scope (setType)+import Data.Morpheus.Types.Internal.Validation.Validator import Relude  violation ::-  Maybe Message ->+  Maybe GQLError ->   Value s ->   InputValidator schemaS ctx a violation message value = do@@ -92,33 +84,23 @@     } <-     asksScope id   prefix <- inputMessagePrefix-  failure-    $ withPosition position-    $ prefix-      <> typeViolation-        (TypeRef currentTypeName currentTypeWrappers)-        value-      <> maybe "" ((" " <>) . msgValidation) message+  throwError $+    ( prefix+        <> typeViolation+          (TypeRef currentTypeName currentTypeWrappers)+          value+        <> maybe "" (" " <>) message+    )+      `atPositions` position -checkTypeEquality ::-  (TypeName, [TypeWrapper]) ->+checkTypeCompatibility ::+  TypeRef ->   Ref FieldName ->   Variable VALID ->   InputValidator schemaS ctx ValidValue-checkTypeEquality (tyConName, tyWrappers) ref var@Variable {variableValue = ValidVariableValue value, variableType}-  | typeConName variableType == tyConName-      && not-        (isWeaker (typeWrappers variableType) tyWrappers) =-    pure value-  | otherwise =-    failure $-      incompatibleVariableType-        ref-        var-        TypeRef-          { typeConName = tyConName,-            typeWrappers = tyWrappers-          }+checkTypeCompatibility valueType ref var@Variable {variableValue = ValidVariableValue value, variableType}+  | variableType `isSubtype` valueType = pure value+  | otherwise = throwError $ incompatibleVariableType ref var valueType  validateInputByTypeRef ::   ValidateWithDefault c schemaS s =>@@ -147,37 +129,33 @@ -- Validate input Values validateInputByType ::   ValidateWithDefault ctx schemaS valueS =>-  [TypeWrapper] ->+  TypeWrapper ->   TypeDefinition IN schemaS ->   Value valueS ->   InputValidator schemaS ctx ValidValue validateInputByType tyWrappers typeDef =-  withScopeType (typeDef, tyWrappers) . validateWrapped tyWrappers typeDef+  withScope (setType typeDef tyWrappers) . validateWrapped tyWrappers typeDef  -- VALIDATION validateWrapped ::   ValidateWithDefault ctx schemaS valueS =>-  [TypeWrapper] ->+  TypeWrapper ->   TypeDefinition IN schemaS ->   Value valueS ->   InputValidator schemaS ctx ValidValue -- Validate Null. value = null ? validateWrapped wrappers _ (ResolvedVariable ref variable) = do   typeName <- asksScope currentTypeName-  checkTypeEquality (typeName, wrappers) ref variable+  checkTypeCompatibility (TypeRef typeName wrappers) ref variable validateWrapped wrappers _ Null   | isNullable wrappers = pure Null   | otherwise = violation Nothing Null -- Validate LIST-validateWrapped [TypeMaybe] TypeDefinition {typeContent} entryValue =-  validateUnwrapped typeContent entryValue-validateWrapped (TypeMaybe : wrappers) typeDef value =-  validateInputByType wrappers typeDef value-validateWrapped (TypeList : wrappers) tyCont (List list) =+validateWrapped (TypeList wrappers _) tyCont (List list) =   List <$> traverse (validateInputByType wrappers tyCont) list {-- 2. VALIDATE TYPES, all wrappers are already Processed --} {-- VALIDATE OBJECT--}-validateWrapped [] TypeDefinition {typeContent} entryValue =+validateWrapped BaseType {} TypeDefinition {typeContent} entryValue =   validateUnwrapped typeContent entryValue {-- 3. THROW ERROR: on invalid values --} validateWrapped _ _ entryValue = violation Nothing entryValue@@ -200,12 +178,12 @@ -- INPUT UNION validatInputUnion ::   ValidateWithDefault ctx schemaS s =>-  DataInputUnion schemaS ->+  UnionTypeDefinition IN schemaS ->   Object s ->   InputValidator schemaS ctx (Value VALID) validatInputUnion inputUnion rawFields =   case constraintInputUnion inputUnion rawFields of-    Left message -> violation (Just message) (Object rawFields)+    Left message -> violation (Just $ msg message) (Object rawFields)     Right (name, value) -> validatInputUnionMember name value  validatInputUnionMember ::@@ -215,7 +193,7 @@   InputValidator schemaS ctx (Value VALID) validatInputUnionMember member value = do   inputDef <- askDef-  mkInputUnionValue member <$> validateInputByType [TypeMaybe] inputDef value+  mkInputUnionValue member <$> validateInputByType mkMaybeType inputDef value   where     askDef       | nullary member = askType (Typed $ mkTypeRef unitTypeName)@@ -226,13 +204,13 @@   UnionMember     { memberName,       nullary-    } = Object . singleton . ObjectEntry (toFieldName memberName) . packNullary+    } = Object . singleton . ObjectEntry (coerce memberName) . packNullary     where       packNullary         | nullary = Object . singleton . ObjectEntry unitFieldName         | otherwise = id --- INUT Object+-- INPUT Object validateInputObject ::   ValidateWithDefault ctx schemaS valueS =>   FieldsDefinition IN schemaS ->@@ -322,10 +300,10 @@   Value valueS ->   InputValidator schemaS c ValidValue validateEnum enumValues value@(Scalar (String enumValue))-  | TypeName enumValue `elem` tags = do+  | packName enumValue `elem` tags = do     isFromVariable <- isVariableValue     if isFromVariable-      then pure (Enum (TypeName enumValue))+      then pure (Enum (packName enumValue))       else violation Nothing value   where     tags = fmap enumName enumValues
src/Data/Morpheus/Validation/Query/Fragment.hs view
@@ -11,32 +11,31 @@ module Data.Morpheus.Validation.Query.Fragment   ( validateFragments,     castFragmentType,-    resolveSpread,     validateFragment,     selectFragmentType,-    ResolveFragment (..),+    ValidateFragmentSelection,+    validateSpread,   ) where +import Control.Monad.Except (throwError) import Data.Morpheus.Error.Fragment   ( cannotBeSpreadOnType,   ) import Data.Morpheus.Internal.Utils-  ( Failure (..),+  ( Empty (empty),   ) import Data.Morpheus.Types.Internal.AST   ( Directives,-    FieldName,     Fragment (..),+    FragmentName,     Fragments,     IMPLEMENTABLE,     Position,     RAW,     Ref (..),-    Schema,     SelectionSet,     Stage,-    Stage,     TypeDefinition,     TypeName,     UnionTag (..),@@ -46,29 +45,35 @@   ( Constraint (..),     FragmentValidator,     askFragments,-    askSchema,+    askTypeDefinitions,     constraint,     selectKnown,   )-import Relude+import Relude hiding (empty) -class ResolveFragment (s :: Stage) where-  resolveValidFragment ::-    (Fragment RAW -> FragmentValidator s (SelectionSet VALID)) ->-    [TypeName] ->-    Ref FieldName ->-    FragmentValidator s UnionTag+class ValidateFragmentSelection (s :: Stage) where+  validateFragmentSelection ::+    Applicative m =>+    (Fragment RAW -> m (SelectionSet VALID)) ->+    Fragment s ->+    m (SelectionSet VALID) -instance ResolveFragment VALID where-  resolveValidFragment _ allowedTargets ref = do-    Fragment {fragmentType, fragmentSelection} <- resolveSpread allowedTargets ref-    pure $ UnionTag fragmentType fragmentSelection+instance ValidateFragmentSelection VALID where+  validateFragmentSelection _ = pure . fragmentSelection -instance ResolveFragment RAW where-  resolveValidFragment f allowedTargets ref = do-    fragment@Fragment {fragmentType} <- resolveSpread allowedTargets ref-    UnionTag fragmentType <$> f fragment+instance ValidateFragmentSelection RAW where+  validateFragmentSelection f = f +validateSpread ::+  ValidateFragmentSelection s =>+  (Fragment RAW -> FragmentValidator s (SelectionSet VALID)) ->+  [TypeName] ->+  Ref FragmentName ->+  FragmentValidator s UnionTag+validateSpread f allowedTargets ref = do+  fragment@Fragment {fragmentType} <- resolveSpread allowedTargets ref+  UnionTag fragmentType <$> validateFragmentSelection f fragment+ validateFragment ::   (Fragment RAW -> FragmentValidator s (SelectionSet VALID)) ->   [TypeName] ->@@ -95,19 +100,19 @@     <$> validate f <*> validateFragmentDirectives fragmentDirectives  validateFragmentDirectives :: Directives RAW -> FragmentValidator s (Directives VALID)-validateFragmentDirectives _ = pure [] --TODO: validate fragment directives+validateFragmentDirectives _ = pure empty --TODO: validate fragment directives  castFragmentType ::-  Maybe FieldName ->+  Maybe FragmentName ->   Position ->   [TypeName] ->   Fragment s ->   FragmentValidator s1 (Fragment s) castFragmentType key position typeMembers fragment@Fragment {fragmentType}   | fragmentType `elem` typeMembers = pure fragment-  | otherwise = failure $ cannotBeSpreadOnType key fragmentType position typeMembers+  | otherwise = throwError $ cannotBeSpreadOnType key fragmentType position typeMembers -resolveSpread :: [TypeName] -> Ref FieldName -> FragmentValidator s (Fragment s)+resolveSpread :: [TypeName] -> Ref FragmentName -> FragmentValidator s (Fragment s) resolveSpread allowedTargets ref@Ref {refName, refPosition} =   askFragments     >>= selectKnown ref@@ -115,6 +120,5 @@  selectFragmentType :: Fragment RAW -> FragmentValidator s (TypeDefinition IMPLEMENTABLE VALID) selectFragmentType fr@Fragment {fragmentType, fragmentPosition} = do-  (schema :: Schema VALID) <- askSchema-  typeDef <- selectKnown (Ref fragmentType fragmentPosition) schema+  typeDef <- askTypeDefinitions >>= selectKnown (Ref fragmentType fragmentPosition)   constraint IMPLEMENTABLE fr typeDef
src/Data/Morpheus/Validation/Query/FragmentPreconditions.hs view
@@ -12,6 +12,8 @@   ) where +import Control.Monad.Except (throwError)+import Data.Mergeable import Data.Morpheus.Error.Fragment   ( cannotSpreadWithinItself,   )@@ -22,13 +24,11 @@     cycleChecking,   ) import Data.Morpheus.Internal.Utils-  ( Failure (..),-    elems,-    selectOr,+  ( selectOr,   ) import Data.Morpheus.Types.Internal.AST-  ( FieldName,-    Fragment (..),+  ( Fragment (..),+    FragmentName,     Fragments,     RAW,     Ref (..),@@ -46,18 +46,18 @@ checkUnusedFragments :: SelectionSet RAW -> BaseValidator () checkUnusedFragments selectionSet = do   fragments <- askFragments-  checkUnused-    (usedFragments fragments (elems selectionSet))-    (elems fragments)+  usages <- usedFragments fragments selectionSet+  checkUnused usages fragments -usedFragments :: Fragments RAW -> [Selection RAW] -> [Node FieldName]-usedFragments fragments = concatMap findAllUses+usedFragments :: Fragments RAW -> SelectionSet RAW -> BaseValidator (HashMap FragmentName [Node FragmentName])+usedFragments fragments = collect . map toEntry . concatMap findAllUses . toList   where-    findUsesSelectionContent :: SelectionContent RAW -> [Node FieldName]+    toEntry (Ref x y) = (x, [Ref x y])+    findUsesSelectionContent :: SelectionContent RAW -> [Node FragmentName]     findUsesSelectionContent (SelectionSet selectionSet) =       concatMap findAllUses selectionSet     findUsesSelectionContent SelectionField = []-    findAllUses :: Selection RAW -> [Node FieldName]+    findAllUses :: Selection RAW -> [Node FragmentName]     findAllUses Selection {selectionContent} =       findUsesSelectionContent selectionContent     findAllUses (InlineFragment Fragment {fragmentSelection}) =@@ -74,18 +74,18 @@  checkFragmentPreconditions :: SelectionSet RAW -> BaseValidator () checkFragmentPreconditions selection =-  (exploreSpreads >>= cycleChecking (failure . cannotSpreadWithinItself))+  (exploreSpreads >>= cycleChecking (throwError . cannotSpreadWithinItself))     *> checkUnusedFragments selection -exploreSpreads :: BaseValidator (Graph FieldName)-exploreSpreads = fmap exploreFragmentSpreads . elems <$> askFragments+exploreSpreads :: BaseValidator (Graph FragmentName)+exploreSpreads = fmap exploreFragmentSpreads . toList <$> askFragments -exploreFragmentSpreads :: Fragment RAW -> Edges FieldName+exploreFragmentSpreads :: Fragment RAW -> Edges FragmentName exploreFragmentSpreads Fragment {fragmentName, fragmentSelection, fragmentPosition} =   (Ref fragmentName fragmentPosition, concatMap scanSpread fragmentSelection)  class ScanSpread a where-  scanSpread :: a -> [Node FieldName]+  scanSpread :: a -> [Node FragmentName]  instance ScanSpread (Selection RAW) where   scanSpread Selection {selectionContent} =
src/Data/Morpheus/Validation/Query/Selection.hs view
@@ -14,28 +14,32 @@   ) where +import Control.Monad.Except (throwError)+import Data.Mergeable+  ( toNonEmpty,+  ) import Data.Morpheus.Error.Selection   ( hasNoSubfields,     subfieldsNotSelected,   )-import Data.Morpheus.Ext.SemigroupM-  ( concatTraverse,-  )+import Data.Morpheus.Ext.Empty (Empty (..)) import Data.Morpheus.Internal.Utils-  ( Failure (..),-    elems,-    empty,-    keyOf,+  ( keyOf,+    mergeConcat,     singleton,+    startHistory,+    throwErrors,   ) import Data.Morpheus.Types.Internal.AST   ( Arguments,     DirectiveLocation (FIELD, FRAGMENT_SPREAD, INLINE_FRAGMENT, MUTATION, QUERY, SUBSCRIPTION),     Directives,-    FieldDefinition (fieldType),+    FieldDefinition (..),     FieldName,     FieldsDefinition,     Fragment (..),+    FragmentName,+    GQLError,     IMPLEMENTABLE,     OUT,     Operation (..),@@ -50,21 +54,22 @@     TypeDefinition (..),     UnionTag (..),     VALID,-    ValidationError (..),+    at,     isLeaf,-    msgValidation,+    mkTypeRef,+    msg,     possibleTypes,     toCategory,     typed,-    withPosition,   ) import Data.Morpheus.Types.Internal.Validation   ( FragmentValidator,     SelectionValidator,-    askSchema,     askType,     getOperationType,+    schema,     selectKnown,+    setSelection,     withScope,   ) import Data.Morpheus.Validation.Internal.Arguments@@ -75,35 +80,34 @@     validateDirectives,   ) import Data.Morpheus.Validation.Query.Fragment-  ( ResolveFragment (..),-    resolveValidFragment,+  ( ValidateFragmentSelection,     selectFragmentType,     validateFragment,+    validateSpread,   ) import Data.Morpheus.Validation.Query.UnionSelection   ( validateInterfaceSelection,     validateUnionSelection,   )-import Relude hiding (empty)+import Relude hiding (empty, join)  selectionsWithoutTypename :: SelectionSet VALID -> [Selection VALID]-selectionsWithoutTypename = filter (("__typename" /=) . keyOf) . elems+selectionsWithoutTypename = filter (("__typename" /=) . keyOf) . toList  singleTopLevelSelection :: Operation RAW -> SelectionSet VALID -> SelectionValidator () singleTopLevelSelection Operation {operationType = Subscription, operationName} selSet =   case selectionsWithoutTypename selSet of-    (_ : xs) | not (null xs) -> failure $ fmap (singleTopLevelSelectionError operationName) xs+    (_ : (x : xs)) -> throwErrors $ fmap (singleTopLevelSelectionError operationName) (x :| xs)     _ -> pure () singleTopLevelSelection _ _ = pure () -singleTopLevelSelectionError :: Maybe FieldName -> Selection VALID -> ValidationError+singleTopLevelSelectionError :: Maybe FieldName -> Selection VALID -> GQLError singleTopLevelSelectionError name Selection {selectionPosition} =-  withPosition (Just selectionPosition) $-    subscriptionName+  ( maybe "Anonymous Subscription" (("Subscription " <>) . msg) name       <> " must select "       <> "only one top level field."-  where-    subscriptionName = maybe "Anonymous Subscription" (("Subscription " <>) . msgValidation) name+  )+    `at` selectionPosition  validateOperation ::   Operation RAW ->@@ -143,17 +147,17 @@   DirectiveLocation ->   Directives RAW ->   (Directives VALID -> FragmentValidator s (SelectionSet VALID)) ->-  FragmentValidator s (SelectionSet VALID)+  FragmentValidator s (Maybe (SelectionSet VALID)) processSelectionDirectives location rawDirectives sel = do   directives <- validateDirectives location rawDirectives   include <- shouldIncludeSelection directives   selection <- sel directives   pure $     if include-      then selection-      else empty+      then Just selection+      else Nothing -validateFragmentSelection :: (ResolveFragment s) => Fragment RAW -> FragmentValidator s (SelectionSet VALID)+validateFragmentSelection :: (ValidateFragmentSelection s) => Fragment RAW -> FragmentValidator s (SelectionSet VALID) validateFragmentSelection f@Fragment {fragmentSelection} = do   typeDef <- selectFragmentType f   validateSelectionSet typeDef fragmentSelection@@ -163,90 +167,92 @@ getFields TypeDefinition {typeContent = DataInterface fields} = fields  validateSelectionSet ::-  forall s.-  ( ResolveFragment s-  ) =>+  (ValidateFragmentSelection s) =>   TypeDefinition IMPLEMENTABLE VALID ->   SelectionSet RAW ->   FragmentValidator s (SelectionSet VALID) validateSelectionSet typeDef =-  concatTraverse validateSelection+  traverse (validateSelection typeDef) . toList+    >=> toNonEmpty . catMaybes+    >=> startHistory . mergeConcat++-- validate single selection: InlineFragments and Spreads will Be resolved and included in SelectionSet+validateSelection :: ValidateFragmentSelection s => TypeDefinition IMPLEMENTABLE VALID -> Selection RAW -> FragmentValidator s (Maybe (SelectionSet VALID))+validateSelection typeDef Selection {..} =+  withScope (setSelection typeDef selectionRef) $+    processSelectionDirectives FIELD selectionDirectives validateContent   where-    -- validate single selection: InlineFragments and Spreads will Be resolved and included in SelectionSet-    validateSelection :: Selection RAW -> FragmentValidator s (SelectionSet VALID)-    validateSelection-      sel@Selection-        { selectionName,-          selectionArguments,-          selectionContent,-          selectionPosition,-          selectionDirectives-        } =-        withScope-          typeDef-          currentSelectionRef-          $ processSelectionDirectives-            FIELD-            selectionDirectives-            (`validateSelectionContent` selectionContent)-        where-          currentSelectionRef = Ref selectionName selectionPosition-          commonValidation :: FragmentValidator s (TypeDefinition OUT VALID, Arguments VALID)-          commonValidation = do-            fieldDef <- selectKnown (Ref selectionName selectionPosition) (getFields typeDef)-            (,)-              <$> askType (typed fieldType fieldDef)-              <*> validateFieldArguments fieldDef selectionArguments-          ------------------------------------------------------------------------------------          validateSelectionContent :: Directives VALID -> SelectionContent RAW -> FragmentValidator s (SelectionSet VALID)-          validateSelectionContent directives SelectionField-            | null selectionArguments && selectionName == "__typename" =-              pure $ singleton $-                sel-                  { selectionArguments = empty,-                    selectionDirectives = directives,-                    selectionContent = SelectionField-                  }-            | otherwise = do-              (datatype, validArgs) <- commonValidation-              selContent <--                validateContentLeaf currentSelectionRef datatype-              pure $-                singleton-                  ( sel-                      { selectionArguments = validArgs,-                        selectionDirectives = directives,-                        selectionContent = selContent-                      }-                  )-          ----- SelectionSet-          validateSelectionContent directives (SelectionSet rawSelectionSet) =-            do-              (tyDef, validArgs) <- commonValidation-              selContent <- validateByTypeContent tyDef currentSelectionRef rawSelectionSet-              pure $ singleton $-                sel-                  { selectionArguments = validArgs,-                    selectionDirectives = directives,-                    selectionContent = selContent-                  }-    validateSelection (Spread dirs ref) = do-      types <- possibleTypes typeDef <$> askSchema-      processSelectionDirectives-        FRAGMENT_SPREAD-        dirs-        (const $ unionTagSelection <$> resolveValidFragment validateFragmentSelection types ref)-    validateSelection-      ( InlineFragment-          fragment@Fragment-            { fragmentDirectives-            }-        ) = do-        types <- possibleTypes typeDef <$> askSchema-        processSelectionDirectives INLINE_FRAGMENT fragmentDirectives $-          const (validate types fragment)-    validate types = fmap fragmentSelection . validateFragment validateFragmentSelection types+    selectionRef = Ref selectionName selectionPosition+    validateContent directives = do+      (validArgs, content) <- validateSelectionContent typeDef selectionRef selectionArguments selectionContent+      pure $+        singleton+          ( Selection+              { selectionArguments = validArgs,+                selectionDirectives = directives,+                selectionContent = content,+                ..+              }+          )+validateSelection typeDef (Spread dirs ref) = do+  processSelectionDirectives FRAGMENT_SPREAD dirs $+    const $ validateSpreadSelection typeDef ref+validateSelection typeDef (InlineFragment fragment@Fragment {fragmentDirectives}) = do+  processSelectionDirectives INLINE_FRAGMENT fragmentDirectives $+    const $ validateInlineFragmentSelection typeDef fragment +validateSpreadSelection ::+  ValidateFragmentSelection s =>+  TypeDefinition a VALID ->+  Ref FragmentName ->+  FragmentValidator s (SelectionSet VALID)+validateSpreadSelection typeDef ref = do+  types <- possibleTypes typeDef <$> asks schema+  unionTagSelection <$> validateSpread validateFragmentSelection types ref++validateInlineFragmentSelection ::+  ValidateFragmentSelection s =>+  TypeDefinition IMPLEMENTABLE VALID ->+  Fragment RAW ->+  FragmentValidator s (SelectionSet VALID)+validateInlineFragmentSelection typeDef x = do+  types <- possibleTypes typeDef <$> asks schema+  fragmentSelection <$> validateFragment validateFragmentSelection types x++selectSelectionField ::+  Ref FieldName ->+  TypeDefinition IMPLEMENTABLE s ->+  FragmentValidator s' (FieldDefinition OUT s)+selectSelectionField ref typeDef+  | refName ref == "__typename" =+    pure+      FieldDefinition+        { fieldDescription = Nothing,+          fieldName = "__typename",+          fieldType = mkTypeRef "String",+          fieldContent = Nothing,+          fieldDirectives = empty+        }+  | otherwise = selectKnown ref (getFields typeDef)++validateSelectionContent ::+  forall s.+  ValidateFragmentSelection s =>+  TypeDefinition IMPLEMENTABLE VALID ->+  Ref FieldName ->+  Arguments RAW ->+  SelectionContent RAW ->+  FragmentValidator s (Arguments VALID, SelectionContent VALID)+validateSelectionContent typeDef ref selectionArguments content = do+  fieldDef <- selectSelectionField ref typeDef+  fieldTypeDef <- askType (typed fieldType fieldDef)+  validArgs <- validateFieldArguments fieldDef selectionArguments+  validContent <- validateContent fieldTypeDef content+  pure (validArgs, validContent)+  where+    validateContent fieldTypeDef SelectionField = validateContentLeaf ref fieldTypeDef+    validateContent fieldTypeDef (SelectionSet rawSelectionSet) = validateByTypeContent fieldTypeDef ref rawSelectionSet+ validateContentLeaf ::   Ref FieldName ->   TypeDefinition OUT VALID ->@@ -256,11 +262,11 @@   TypeDefinition {typeName, typeContent}     | isLeaf typeContent = pure SelectionField     | otherwise =-      failure $ subfieldsNotSelected selectionName typeName selectionPosition+      throwError $ subfieldsNotSelected selectionName typeName selectionPosition  validateByTypeContent ::   forall s.-  (ResolveFragment s) =>+  (ValidateFragmentSelection s) =>   TypeDefinition OUT VALID ->   Ref FieldName ->   SelectionSet RAW ->@@ -268,7 +274,7 @@ validateByTypeContent   typeDef@TypeDefinition {typeContent, ..}   currentSelectionRef =-    withScope typeDef currentSelectionRef+    withScope (setSelection typeDef currentSelectionRef)       . __validate typeContent     where       __validate ::@@ -291,8 +297,8 @@           validateSelectionSet           (TypeDefinition {typeContent = DataInterface {..}, ..})       __validate _ =-        const-          $ failure-          $ hasNoSubfields-            currentSelectionRef-            typeDef+        const $+          throwError $+            hasNoSubfields+              currentSelectionRef+              typeDef
src/Data/Morpheus/Validation/Query/UnionSelection.hs view
@@ -14,37 +14,36 @@   ) where -import Data.List (lookup)-import Data.Morpheus.Ext.SemigroupM-  ( (<:>),-    join,-  )+import qualified Data.HashMap.Lazy as HM+import Data.Mergeable (OrdMap) import Data.Morpheus.Internal.Utils-  ( elems,-    empty,+  ( empty,     fromElems,-    member,-    singleton,+    mergeConcat,+    selectOr,+    startHistory,   )-import Data.Morpheus.Types.Internal.AST-  ( DataUnion,-    FieldName,-    Fragment (..),-    IMPLEMENTABLE,-    Position (..),-    RAW,+import Data.Morpheus.Types.Internal.AST.Base (Position (..))+import Data.Morpheus.Types.Internal.AST.Name (TypeName)+import Data.Morpheus.Types.Internal.AST.Selection+  ( Fragment (..),     Selection (..),     SelectionContent (..),     SelectionSet,-    SelectionSet,-    TypeContent (..),-    TypeDefinition (..),-    TypeName,     UnionTag (..),-    VALID,-    mkType,+  )+import Data.Morpheus.Types.Internal.AST.Stage (RAW, VALID)+import Data.Morpheus.Types.Internal.AST.TypeCategory+  ( IMPLEMENTABLE,+    OUT,     toCategory,   )+import Data.Morpheus.Types.Internal.AST.TypeSystem+  ( TypeContent (..),+    TypeDefinition (..),+    UnionTypeDefinition,+    mkType,+  ) import Data.Morpheus.Types.Internal.Validation   ( FragmentValidator,     Scope (..),@@ -53,118 +52,103 @@     asksScope,   ) import Data.Morpheus.Validation.Query.Fragment-  ( ResolveFragment (resolveValidFragment),+  ( ValidateFragmentSelection,     castFragmentType,+    validateSpread,   ) import Relude hiding (empty, join)  -- returns all Fragments used for Possible Types splitFragment ::-  (ResolveFragment s) =>+  (ValidateFragmentSelection s) =>   ( Fragment RAW ->     FragmentValidator s (SelectionSet VALID)   ) ->   [TypeDefinition IMPLEMENTABLE VALID] ->   Selection RAW ->-  FragmentValidator s ([UnionTag], [Selection RAW])-splitFragment _ _ x@Selection {} = pure ([], [x])-splitFragment f types (Spread _ ref) = pureFirst <$> resolveValidFragment f (typeName <$> types) ref+  FragmentValidator s (Either UnionTag (Selection RAW))+splitFragment _ _ x@Selection {} = pure (Right x)+splitFragment f types (Spread _ ref) = Left <$> validateSpread f (typeName <$> types) ref splitFragment f types (InlineFragment fragment@Fragment {fragmentType}) =-  pureFirst . UnionTag fragmentType+  Left . UnionTag fragmentType     <$> ( castFragmentType Nothing (fragmentPosition fragment) (typeName <$> types) fragment             >>= f         ) -pureFirst :: a1 -> ([a1], [a2])-pureFirst x = ([x], [])--joinExploredSelection :: [([UnionTag], [Selection RAW])] -> FragmentValidator s ([UnionTag], SelectionSet RAW)-joinExploredSelection i = do-  let (x, y) = unzip i-  let x' = concat x-  let y' = concat y-  (x',) <$> fromElems y'- exploreFragments ::-  (ResolveFragment s) =>+  (ValidateFragmentSelection s) =>   ( Fragment RAW ->     FragmentValidator s (SelectionSet VALID)   ) ->-  [TypeDefinition IMPLEMENTABLE VALID] ->+  OrdMap TypeName (TypeDefinition IMPLEMENTABLE VALID) ->   SelectionSet RAW ->   FragmentValidator s ([UnionTag], SelectionSet RAW)-exploreFragments validateFragment types selectionSet =-  traverse (splitFragment validateFragment types) (elems selectionSet)-    >>= joinExploredSelection+exploreFragments validateFragment types selectionSet = do+  (tags, selections) <- partitionEithers <$> traverse (splitFragment validateFragment (toList types)) (toList selectionSet)+  selectionPosition <- fromMaybe (Position 0 0) <$> asksScope position+  (tags,)+    <$> fromElems+      ( ( Selection+            { selectionName = "__typename",+              selectionAlias = Nothing,+              selectionPosition,+              selectionArguments = empty,+              selectionContent = SelectionField,+              selectionDirectives = empty+            }+        ) :+        selections+      ) --- sorts Fragment by contitional Types+-- sorts Fragment by conditional Types -- [ --   ( Type for Tag User , [ Fragment for User] ) --   ( Type for Tag Product , [ Fragment for Product] ) -- ] tagUnionFragments ::-  Bool ->-  [TypeDefinition IMPLEMENTABLE VALID] ->   [UnionTag] ->-  [(TypeName, [SelectionSet VALID])]-tagUnionFragments hasTypeName types fragments-  | hasTypeName = categorizeType <$> types-  | otherwise = filter notEmpty (categorizeType <$> types)+  OrdMap TypeName (TypeDefinition IMPLEMENTABLE VALID) ->+  HashMap TypeName [SelectionSet VALID]+tagUnionFragments fragments types = fmap categorizeType getSelectedTypes   where-    notEmpty = not . null . snd-    categorizeType ::-      TypeDefinition IMPLEMENTABLE VALID ->-      (TypeName, [SelectionSet VALID])-    categorizeType datatype = (typeName datatype, unionTagSelection <$> filter matches fragments)+    getSelectedTypes :: HashMap TypeName [TypeName]+    getSelectedTypes = fromList (map select fragments)       where-        matches = (`elem` subTypes datatype) . unionTagName+        select UnionTag {unionTagName} =+          ( unionTagName,+            selectOr+              [unionTagName]+              getCompatibleTypes+              unionTagName+              types+          )+    categorizeType ::+      [TypeName] -> [SelectionSet VALID]+    categorizeType compatibleTypes =+      unionTagSelection+        <$> filter+          ((`elem` compatibleTypes) . unionTagName)+          fragments -subTypes :: TypeDefinition a s -> [TypeName]-subTypes TypeDefinition {typeName, typeContent = DataObject {objectImplements}} =-  typeName : objectImplements-subTypes TypeDefinition {typeName} = [typeName]+getCompatibleTypes :: TypeDefinition a s -> [TypeName]+getCompatibleTypes TypeDefinition {typeName, typeContent = DataObject {objectImplements}} = typeName : objectImplements+getCompatibleTypes TypeDefinition {typeName} = [typeName] -{--    - all Variable and Fragment references will be: resolved and validated-    - unionTypes: will be clustered under type names-      ...A on T1 {<SelectionA>}-      ...B on T2 {<SelectionB>}-      ...C on T2 {<SelectionC>}-      will be become : [-          UnionTag "T1" {<SelectionA>},-          UnionTag "T2" {<SelectionB>,<SelectionC>}-      ]- -} joinClusters ::-  forall s.   SelectionSet VALID ->-  [(TypeName, [SelectionSet VALID])] ->+  HashMap TypeName [SelectionSet VALID] ->   FragmentValidator s (SelectionContent VALID)-joinClusters selSet =-  traverse joinCluster-    >=> fmap UnionSelection . fromElems+joinClusters selSet typedSelections+  | null typedSelections = pure (SelectionSet selSet)+  | otherwise =+    traverse mkUnionTag (HM.toList typedSelections)+      >>= fmap (UnionSelection selSet) . startHistory . fromElems   where-    joinCluster (typeName, fragments) = UnionTag typeName <$> join (selSet : fragments)--withTypename ::-  SelectionSet VALID ->-  FragmentValidator s (SelectionSet VALID)-withTypename sel = do-  selectionPosition <- fromMaybe (Position 0 0) <$> asksScope position-  sel-    <:> singleton-      ( Selection-          { selectionName = "__typename",-            selectionAlias = Nothing,-            selectionPosition,-            selectionArguments = empty,-            selectionContent = SelectionField,-            selectionDirectives = empty-          }-      )+    mkUnionTag :: (TypeName, [SelectionSet VALID]) -> FragmentValidator s UnionTag+    mkUnionTag (typeName, fragments) = UnionTag typeName <$> startHistory (mergeConcat (selSet :| fragments))  validateInterfaceSelection ::-  ResolveFragment s =>+  ValidateFragmentSelection s =>   (Fragment RAW -> FragmentValidator s (SelectionSet VALID)) ->   (TypeDefinition IMPLEMENTABLE VALID -> SelectionSet RAW -> FragmentValidator s (SelectionSet VALID)) ->   TypeDefinition IMPLEMENTABLE VALID ->@@ -173,42 +157,29 @@ validateInterfaceSelection   validateFragment   validate-  typeDef+  typeDef@TypeDefinition {typeName}   inputSelectionSet = do     possibleTypes <- askInterfaceTypes typeDef     (spreads, selectionSet) <- exploreFragments validateFragment possibleTypes inputSelectionSet     validSelectionSet <- validate typeDef selectionSet-    let categories = tagUnionFragments (isTypenameSelected selectionSet) possibleTypes spreads-    if null categories-      then pure (SelectionSet validSelectionSet)-      else do-        validSelectionSetWithTypename <- withTypename validSelectionSet-        joinClusters validSelectionSetWithTypename (insertDefault (typeName typeDef) categories)--insertDefault :: TypeName -> [(TypeName, [a])] -> [(TypeName, [a])]-insertDefault interfaceName categories-  | isJust (lookup interfaceName categories) = categories-  | otherwise = (interfaceName, []) : categories+    let tags = tagUnionFragments spreads possibleTypes+    let interfaces = selectOr [] id typeName tags+    defaultSelection <- startHistory $ mergeConcat (validSelectionSet :| interfaces)+    joinClusters defaultSelection (HM.delete typeName tags)  mkUnionRootType :: FragmentValidator s (TypeDefinition IMPLEMENTABLE VALID) mkUnionRootType = (`mkType` DataObject [] empty) <$> asksScope currentTypeName -isTypenameSelected :: SelectionSet s -> Bool-isTypenameSelected = member ("__typename" :: FieldName)- validateUnionSelection ::-  ResolveFragment s =>+  ValidateFragmentSelection s =>   (Fragment RAW -> FragmentValidator s (SelectionSet VALID)) ->   (TypeDefinition IMPLEMENTABLE VALID -> SelectionSet RAW -> FragmentValidator s (SelectionSet VALID)) ->-  DataUnion VALID ->+  UnionTypeDefinition OUT VALID ->   SelectionSet RAW ->   FragmentValidator s (SelectionContent VALID) validateUnionSelection validateFragment validate members selectionSet = do-  -- get union Types defined in GraphQL schema -> (union Tag, union Selection set)-  -- [("User", FieldsDefinition { ... }), ("Product", FieldsDefinition { ...   unionTypes <- traverse (fmap toCategory . askTypeMember) members-  -- find all Fragments used in Selection   (spreads, selSet) <- exploreFragments validateFragment unionTypes selectionSet   typeDef <- mkUnionRootType   validSelection <- validate typeDef selSet-  joinClusters validSelection (tagUnionFragments (isTypenameSelected selectionSet) unionTypes spreads)+  joinClusters validSelection (tagUnionFragments spreads unionTypes)
src/Data/Morpheus/Validation/Query/Validation.hs view
@@ -11,7 +11,7 @@ where  import Data.Morpheus.Ext.Result-  ( Eventless,+  ( GQLResult,   ) import Data.Morpheus.Internal.Utils (empty) import Data.Morpheus.Types.Internal.AST@@ -20,11 +20,11 @@     Schema (..),     TypeKind (..),     VALID,+    mkBaseType,   ) import Data.Morpheus.Types.Internal.Config (Config (..)) import Data.Morpheus.Types.Internal.Validation-  ( CurrentSelection (..),-    OperationContext (..),+  ( OperationContext (..),     Scope (..),     ScopeKind (..),     runValidator,@@ -51,7 +51,7 @@   Config ->   Schema VALID ->   ExecutableDocument ->-  Eventless (Operation VALID)+  GQLResult (Operation VALID) validateRequest   config   schema@@ -73,7 +73,7 @@           schema           scope           ( OperationContext-              { selection,+              { operationName,                 fragments,                 variables = empty               }@@ -85,7 +85,7 @@           schema           scope           ( OperationContext-              { selection,+              { operationName,                 fragments,                 variables               }@@ -96,7 +96,7 @@         schema         scope         ( OperationContext-            { selection,+            { operationName,               fragments = validFragments,               variables             }@@ -107,11 +107,11 @@           { kind = SELECTION,             currentTypeName = "Root",             currentTypeKind = KindObject Nothing,-            currentTypeWrappers = [],-            fieldname = "Root",-            position = Just operationPosition+            currentTypeWrappers = mkBaseType,+            fieldName = "Root",+            position = Just operationPosition,+            path = []           }-      selection = CurrentSelection {operationName}       validateHelpers =         checkFragmentPreconditions operationSelection           *> resolveOperationVariables
src/Data/Morpheus/Validation/Query/Variable.hs view
@@ -9,11 +9,11 @@   ) where +import Control.Monad.Except (throwError)+import Data.Mergeable import Data.Morpheus.Error.Variable (uninitializedVariable) import Data.Morpheus.Internal.Utils-  ( Failure (..),-    elems,-    selectOr,+  ( selectOr,   ) import Data.Morpheus.Types.Internal.AST   ( Argument (..),@@ -24,6 +24,7 @@     IN,     ObjectEntry (..),     Operation (..),+    Position,     RAW,     RawValue,     Ref (..),@@ -51,12 +52,13 @@     Constraint (..),     InputSource (..),     askFragments,-    askSchema,+    askTypeDefinitions,     checkUnused,     constraint,     selectKnown,+    setPosition,     startInput,-    withPosition,+    withScope,   ) import Data.Morpheus.Validation.Internal.Value   ( validateInputByType,@@ -81,9 +83,10 @@ mapSelection :: (Selection RAW -> BaseValidator [b]) -> SelectionSet RAW -> BaseValidator [b] mapSelection f = fmap concat . traverse f -allVariableRefs :: [SelectionSet RAW] -> BaseValidator [Ref FieldName]-allVariableRefs = fmap concat . traverse (mapSelection searchRefs)+allVariableRefs :: [SelectionSet RAW] -> BaseValidator (HashMap FieldName [Position])+allVariableRefs = collect <=< fmap (map toEntry . concat) . traverse (mapSelection searchRefs)   where+    toEntry (Ref x y) = (x, [y])     exploreSelectionContent :: SelectionContent RAW -> BaseValidator [Ref FieldName]     exploreSelectionContent SelectionField = pure []     exploreSelectionContent (SelectionSet selSet) = mapSelection searchRefs selSet@@ -102,7 +105,7 @@         <$> ( askFragments                 >>= selectKnown reference                 >>= mapSelection searchRefs-                . fragmentSelection+                  . fragmentSelection             )  resolveOperationVariables ::@@ -123,7 +126,7 @@       checkUnusedVariables :: BaseValidator ()       checkUnusedVariables = do         uses <- allVariableRefs [operationSelection]-        checkUnused uses (elems operationArguments)+        checkUnused uses (toList operationArguments)  lookupAndValidateValueOnBody ::   Variables ->@@ -139,9 +142,9 @@       variablePosition,       variableValue = DefaultValue defaultValue     } =-    withPosition variablePosition $+    withScope (setPosition variablePosition) $       toVariable-        <$> ( askSchema+        <$> ( askTypeDefinitions                 >>= selectKnown (Ref typeConName variablePosition)                 >>= constraint INPUT var                 >>= checkType getVariable defaultValue@@ -163,7 +166,7 @@       checkType Nothing (Just defValue) varType = validator varType True defValue       checkType Nothing Nothing varType         | validationMode /= WITHOUT_VARIABLES && not (isNullable variableType) =-          failure $ uninitializedVariable var+          throwError $ uninitializedVariable var         | otherwise =           returnNull         where
test/Spec.hs view
@@ -6,43 +6,59 @@   ) where -import Relude-import Test.Tasty-  ( defaultMain,-    testGroup,+import Data.ByteString.Lazy.Internal (ByteString)+import Data.Morpheus.Core+  ( defaultConfig,+    parseRequest,+    parseRequestWith,+    parseSchema,+    render,   )-import qualified Utils.Rendering as Rendering-import Utils.Schema-  ( testSchema,+import Data.Morpheus.Internal.Ext+  ( toEither,   )+import Data.Morpheus.Types.IO (GQLRequest)+import Data.Morpheus.Types.Internal.AST (GQLError, Schema, VALID)+import Relude ((.), Either, Functor (fmap), IO, NonEmpty, map)+import Test.Morpheus+  ( FileUrl,+    cd,+    deepScan,+    mainTest,+    mkUrl,+    scan,+    testQuery,+    testQueryRendering,+    testQueryValidation,+    testSchema,+  )+import Test.Tasty+  ( TestTree,+  ) +runQueryTest :: FileUrl -> TestTree+runQueryTest = testQuery (toEither . parseRequest)++runSchemaTest :: FileUrl -> TestTree+runSchemaTest = testSchema (toEither . parseSchema)++runRenderingTest :: FileUrl -> [FileUrl] -> [TestTree]+runRenderingTest url = map (testQueryRendering (parseQuery, toEither . parseSchema) url)++runQueryValidationTest :: FileUrl -> [FileUrl] -> [TestTree]+runQueryValidationTest url = map (testQueryValidation (parseQuery, toEither . parseSchema) url)++parseQuery :: Schema VALID -> GQLRequest -> Either (NonEmpty GQLError) ByteString+parseQuery schema =+  toEither . fmap render+    . parseRequestWith defaultConfig schema+ main :: IO ()-main = do-  schema <- testSchema-  defaultMain $-    testGroup-      "core tests"-      [ schema,-        Rendering.test-          "rendering/simple"-          [ "simple",-            "nested",-            "query",-            "mutation",-            "subscription",-            "directive"-          ],-        Rendering.test-          "rendering/union"-          [ "interface",-            "union"-          ],-        Rendering.test-          "rendering/variable"-          [ "simple",-            "input",-            "enum",-            "list",-            "include-exclude"-          ]-      ]+main =+  mainTest+    "Core tests"+    [ scan runQueryTest (cd (mkUrl "query") "parsing"),+      scan runSchemaTest (mkUrl "schema"),+      deepScan runQueryValidationTest (cd (mkUrl "query") "validation"),+      deepScan runRenderingTest (mkUrl "rendering")+    ]
− test/Utils/Rendering.hs
@@ -1,73 +0,0 @@-{-# LANGUAGE DuplicateRecordFields #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE NoImplicitPrelude #-}--module Utils.Rendering-  ( test,-  )-where--import Data.Aeson (encode)-import Data.ByteString.Lazy.Char8-  ( ByteString,-  )-import qualified Data.ByteString.Lazy.Char8 as LB-import Data.Morpheus.Core-  ( defaultConfig,-    parseRequestWith,-    render,-  )-import Data.Morpheus.Internal.Ext-  ( Eventless,-    Result (..),-  )-import Data.Morpheus.Types.Internal.AST-  ( FieldName (..),-    Operation,-    VALID,-  )-import qualified Data.Text as T-import Relude hiding (ByteString)-import Test.Tasty-  ( TestTree,-    testGroup,-  )-import Test.Tasty.HUnit-  ( assertFailure,-    testCase,-  )-import Utils.Utils-  ( assertValidSchema,-    getRequest,-    readSource,-  )--assertion :: ByteString -> Eventless (Operation VALID) -> IO ()-assertion expected Success {result = actual}-  | expected == actualValue = pure ()-  | otherwise =-    assertFailure-      ("expected: \n\n " <> show expected <> " \n\n but got: \n\n " <> show actualValue)-  where-    actualValue = render actual-assertion _ Failure {errors} = assertFailure $ LB.unpack (encode errors)--test :: FieldName -> [FieldName] -> TestTree-test apiPath requestPath =-  testGroup (T.unpack $ readName apiPath) $-    fmap (testRendering apiPath) requestPath--getExpectedRendering :: FieldName -> IO ByteString-getExpectedRendering = readSource . (<> "/rendering.gql")--testRendering ::-  FieldName ->-  FieldName ->-  TestTree-testRendering apiPath path = testCase (T.unpack $ readName path) $ do-  schema <- assertValidSchema apiPath-  let fullPath = apiPath <> "/" <> path-  actual <- parseRequestWith defaultConfig schema <$> getRequest fullPath-  expected <- getExpectedRendering fullPath-  assertion expected actual
− test/Utils/Schema.hs
@@ -1,89 +0,0 @@-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE DuplicateRecordFields #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE NoImplicitPrelude #-}--module Utils.Schema-  ( testSchema,-  )-where--import Data.Aeson ((.:), (.=), FromJSON (..), ToJSON (..), Value (..), eitherDecode, encode, object)-import qualified Data.ByteString.Lazy as L (readFile)-import Data.ByteString.Lazy.Char8 (ByteString)-import Data.Morpheus.Core (parseFullSchema)-import Data.Morpheus.Internal.Ext-  ( Eventless,-    Result (..),-  )-import Data.Morpheus.Types.Internal.AST-  ( GQLErrors,-    Schema,-    VALID,-  )-import Data.Text (pack)-import Relude hiding (ByteString, toString)-import Test.Tasty (TestTree, testGroup)-import Test.Tasty.HUnit (testCase)-import Utils.Utils-  ( CaseTree (..),-    FileUrl (..),-    caseFailure,-    scanSchemaTests,-    toString,-  )--readSource :: FilePath -> IO ByteString-readSource = L.readFile--readSchema :: FilePath -> IO (Eventless (Schema VALID))-readSchema = fmap parseFullSchema . readSource . (<> "/schema.gql")--readResponse :: FilePath -> IO Response-readResponse = fmap (either AesonError id . eitherDecode) . readSource . (<> "/response.json")--data Response-  = OK-  | Errors {errors :: GQLErrors}-  | AesonError String-  deriving (Generic)--instance FromJSON Response where-  parseJSON (Object v) =-    Errors <$> v .: "errors"-  parseJSON (String "OK") = pure OK-  parseJSON v = pure $ AesonError (show v)--instance ToJSON Response where-  toJSON OK = String "OK"-  toJSON (Errors err) = object ["errors" .= toJSON err]-  toJSON (AesonError err) = String (pack err)--toTests :: CaseTree -> TestTree-toTests CaseTree {caseUrl, children = Left {}} = schemaCase caseUrl-toTests CaseTree {caseUrl = FileUrl {fileName}, children = Right children} =-  testGroup-    fileName-    (fmap toTests children)--testSchema :: IO TestTree-testSchema = toTests <$> scanSchemaTests "test/schema"--schemaCase :: FileUrl -> TestTree-schemaCase url = testCase (fileName url) $ do-  schema <- readSchema (toString url)-  expected <- readResponse (toString url)-  assertion expected schema--assertion :: Response -> Eventless (Schema VALID) -> IO ()-assertion OK Success {} = pure ()-assertion Errors {errors = err} Failure {errors}-  | err == errors =-    pure-      ()-assertion expected Success {} = caseFailure (encode expected) "OK"-assertion expected Failure {errors} =-  caseFailure-    (encode expected)-    (encode (Errors errors))
− test/Utils/Utils.hs
@@ -1,137 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE NoImplicitPrelude #-}--module Utils.Utils-  ( getGQLBody,-    expectedResponse,-    getCases,-    maybeVariables,-    readSource,-    scanSchemaTests,-    FileUrl (..),-    CaseTree (..),-    toString,-    getRequest,-    assertValidSchema,-    getSchema,-    caseFailure,-  )-where--import Data.Aeson (FromJSON, Value (..), decode)-import qualified Data.ByteString.Lazy as L (readFile)-import qualified Data.ByteString.Lazy.Char8 as LB (unpack)-import Data.ByteString.Lazy.Char8 (ByteString)-import Data.Morpheus.Core (parseSchema)-import Data.Morpheus.Internal.Ext-  ( Eventless,-    resultOr,-  )-import Data.Morpheus.Types.IO-  ( GQLRequest (..),-  )-import Data.Morpheus.Types.Internal.AST-  ( FieldName (..),-    Schema (..),-    VALID,-  )-import Data.Text (unpack)-import qualified Data.Text.IO as T-import Relude hiding (ByteString, toString)-import System.Directory (doesDirectoryExist, listDirectory)-import Test.Tasty.HUnit-  ( assertFailure,-  )--readSource :: FieldName -> IO ByteString-readSource = L.readFile . path . readName--path :: Text -> FilePath-path name = "test/" <> unpack name--gqlLib :: Text -> FilePath-gqlLib x = path x <> "/query.gql"--resLib :: Text -> FilePath-resLib x = path x <> "/response.json"--data FileUrl = FileUrl-  { filePath :: [FilePath],-    fileName :: FilePath-  }-  deriving (Show)--data CaseTree = CaseTree-  { caseUrl :: FileUrl,-    children :: Either [FilePath] [CaseTree]-  }-  deriving (Show)--prefix :: FileUrl -> FilePath -> FileUrl-prefix FileUrl {..} x =-  FileUrl-    { filePath = fileName : filePath,-      fileName = x-    }--toString :: FileUrl -> FilePath-toString FileUrl {..} = foldl' (\y x -> x <> "/" <> y) fileName filePath--scanSchemaTests :: FilePath -> IO CaseTree-scanSchemaTests = deepScan--deepScan :: FilePath -> IO CaseTree-deepScan = shouldScan . FileUrl []-  where-    shouldScan :: FileUrl -> IO CaseTree-    shouldScan caseUrl = do-      children <- prefixed caseUrl-      pure CaseTree {..}-    isDirectory :: FileUrl -> IO Bool-    isDirectory = doesDirectoryExist . toString-    prefixed :: FileUrl -> IO (Either [FilePath] [CaseTree])-    prefixed p = do-      dir <- isDirectory p-      if dir-        then do-          list <- map (prefix p) <$> listDirectory (toString p)-          areDirectories <- traverse isDirectory list-          if and areDirectories-            then Right <$> traverse shouldScan list-            else pure $ Left []-        else pure $ Left []--maybeVariables :: FieldName -> IO (Maybe Value)-maybeVariables (FieldName x) = decode <$> (L.readFile (path x <> "/variables.json") <|> pure "{}")--getGQLBody :: FieldName -> IO ByteString-getGQLBody (FieldName p) = L.readFile (gqlLib p)--getCases :: FromJSON a => FilePath -> IO [a]-getCases dir = fromMaybe [] . decode <$> L.readFile ("test/" <> dir <> "/cases.json")--getSchema :: FieldName -> IO (Eventless (Schema VALID))-getSchema (FieldName x) = parseSchema <$> L.readFile (path x <> "/schema.gql")--assertValidSchema :: FieldName -> IO (Schema VALID)-assertValidSchema = getSchema >=> resultOr failedSchema pure-  where-    failedSchema err = assertFailure ("unexpected schema validation error: \n " <> show err)--expectedResponse :: FieldName -> IO Value-expectedResponse (FieldName p) = fromMaybe Null . decode <$> L.readFile (resLib p)--getRequest :: FieldName -> IO GQLRequest-getRequest p =-  GQLRequest-    Nothing-    <$> T.readFile (gqlLib $ readName p)-    <*> maybeVariables p--caseFailure :: ByteString -> ByteString -> IO a-caseFailure expected actualValue =-  assertFailure $-    LB.unpack-      ("expected: \n\n " <> expected <> " \n\n but got: \n\n " <> actualValue)
+ test/query/parsing/selection-set/empty-selection/query.gql view
@@ -0,0 +1,4 @@+query {+  field1 {+  }+}
+ test/query/parsing/selection-set/empty-selection/response.json view
@@ -0,0 +1,5 @@+[+  {+    "message": "empty selection sets are not supported."+  }+]
+ test/query/parsing/selection-set/non-empty-selection/query.gql view
@@ -0,0 +1,5 @@+query {+  field1 {+    name+  }+}
+ test/query/parsing/selection-set/non-empty-selection/response.json view
@@ -0,0 +1,1 @@+"OK"
+ test/query/validation/__typename/arguments/query.gql view
@@ -0,0 +1,3 @@+query {+  __typename(myArg: 1)+}
+ test/query/validation/__typename/arguments/response.json view
@@ -0,0 +1,6 @@+[+  {+    "message": "Unknown Argument \"myArg\" on Field \"__typename\".",+    "locations": [{ "line": 2, "column": 14 }]+  }+]
+ test/query/validation/__typename/schema.gql view
@@ -0,0 +1,3 @@+type Query {+  field: String+}
+ test/query/validation/__typename/selection-set/query.gql view
@@ -0,0 +1,5 @@+query {+  __typename {+    someSelection+  }+}
+ test/query/validation/__typename/selection-set/response.json view
@@ -0,0 +1,6 @@+[+  {+    "message": "Field \"__typename\" must not have a selection since type \"String\" has no subfields.",+    "locations": [{ "line": 2, "column": 3 }]+  }+]
+ test/query/validation/__typename/success/query.gql view
@@ -0,0 +1,3 @@+query {+  __typename+}
+ test/query/validation/__typename/success/response.json view
@@ -0,0 +1,1 @@+"OK"
test/rendering/simple/fragment/query.gql view
@@ -1,12 +1,13 @@ query {-  character {-    ...OnCharacter-    ... on Hero {-      hobby-    }+  deity {+    ...OnDeity   } } -fragment OnCharacter on Character {+fragment OnDeity on Deity {   name+  power+  friends {+    name+  } }
test/rendering/simple/fragment/rendering.gql view
@@ -1,17 +1,9 @@ query {-  character {-    ... on Character {-      __typename-      name-    }-    ... on Deity {-      __typename-      name-    }-    ... on Hero {-      __typename+  deity {+    name+    power+    friends {       name-      hobby     }   } }
− test/rendering/simple/fragment/variables.json
@@ -1,3 +0,0 @@-{-  "name": "value 1"-}
test/rendering/union/interface/rendering.gql view
@@ -1,13 +1,7 @@ query {   character {-    ... on Character {-      __typename-      name-    }-    ... on Deity {-      __typename-      name-    }+    __typename+    name     ... on Hero {       __typename       name
− test/rendering/union/interface/variables.json
@@ -1,3 +0,0 @@-{-  "name": "value 1"-}
test/rendering/union/union/rendering.gql view
@@ -1,10 +1,13 @@ query {   mortal {-    ... on Human {-      name-    }+    __typename     ... on Animal {+      __typename       weight+    }+    ... on Human {+      __typename+      name     }   } }
− test/rendering/union/union/variables.json
@@ -1,3 +0,0 @@-{-  "name": "value 1"-}
+ test/schema/parsing/descriptions/grave-accent/response.json view
@@ -0,0 +1,1 @@+"OK"
+ test/schema/parsing/descriptions/grave-accent/schema.gql view
@@ -0,0 +1,7 @@+"""+A condition to be used against `ActivityLog` object types. All fields are tested+for equality and combined with a logical ‘and.’+"""+type Query {+  field: Int+}
+ test/schema/parsing/descriptions/ok/response.json view
@@ -0,0 +1,1 @@+"OK"
+ test/schema/parsing/descriptions/ok/schema.gql view
@@ -0,0 +1,24 @@+"""+qw+q+haha52352 "+""++3434+"+"""+type MyType {+  field: Int+}++"""+qw+q+haha52352 "+""++""+"""+type Query {+  name: String+}
test/schema/parsing/schema-definition/fail/dupplicate-field/query-mutation-subscription/response.json view
@@ -1,32 +1,15 @@-{-  "errors": [-    {-      "message": "There can Be only One TypeDefinition for schema.\"query\"",-      "locations": []-    },-    {-      "message": "There can Be only One TypeDefinition for schema.\"query\"",-      "locations": []-    },-    {-      "message": "There can Be only One TypeDefinition for schema.\"mutation\"",-      "locations": []-    },-    {-      "message": "There can Be only One TypeDefinition for schema.\"mutation\"",-      "locations": []-    },-    {-      "message": "There can Be only One TypeDefinition for schema.\"subscription\"",-      "locations": []-    },-    {-      "message": "There can Be only One TypeDefinition for schema.\"subscription\"",-      "locations": []-    },-    {-      "message": "There can Be only One TypeDefinition for schema.\"subscription\"",-      "locations": []-    }-  ]-}+[+  { "message": "There can Be only One TypeDefinition for schema.\"mutation\"" },+  { "message": "There can Be only One TypeDefinition for schema.\"mutation\"" },+  { "message": "There can Be only One TypeDefinition for schema.\"query\"" },+  { "message": "There can Be only One TypeDefinition for schema.\"query\"" },+  {+    "message": "There can Be only One TypeDefinition for schema.\"subscription\""+  },+  {+    "message": "There can Be only One TypeDefinition for schema.\"subscription\""+  },+  {+    "message": "There can Be only One TypeDefinition for schema.\"subscription\""+  }+]
test/schema/parsing/schema-definition/fail/dupplicate-field/query/response.json view
@@ -1,16 +1,11 @@-{-  "errors": [-    {-      "message": "There can Be only One TypeDefinition for schema.\"query\"",-      "locations": []-    },-    {-      "message": "There can Be only One TypeDefinition for schema.\"query\"",-      "locations": []-    },-    {-      "message": "There can Be only One TypeDefinition for schema.\"query\"",-      "locations": []-    }-  ]-}+[+  {+    "message": "There can Be only One TypeDefinition for schema.\"query\""+  },+  {+    "message": "There can Be only One TypeDefinition for schema.\"query\""+  },+  {+    "message": "There can Be only One TypeDefinition for schema.\"query\""+  }+]
test/schema/parsing/schema-definition/fail/dupplicate-schema-definition/response.json view
@@ -1,6 +1,5 @@-{-  "errors": [-    { "message": "There can Be only One SchemaDefinition.", "locations": [] },-    { "message": "There can Be only One SchemaDefinition.", "locations": [] }-  ]-}+[+  { "message": "There can Be only One SchemaDefinition." },+  { "message": "There can Be only One SchemaDefinition." },+  { "message": "There can Be only One SchemaDefinition." }+]
test/schema/parsing/schema-definition/fail/unknown-fields/bla/response.json view
@@ -1,8 +1,6 @@-{-  "errors": [-    {-      "message": "offset=78:\nunexpected 'b'\nexpecting '}', Ignored, IgnoredTokens, OperationType, or white space\n",-      "locations": [{ "line": 8, "column": 3 }]-    }-  ]-}+[+  {+    "message": "offset=78:\nunexpected 'b'\nexpecting '#', '}', IgnoredTokens, or OperationType\n",+    "locations": [{ "line": 8, "column": 3 }]+  }+]
test/schema/parsing/schema-definition/fail/unknown-fields/uppercase/response.json view
@@ -1,8 +1,6 @@-{-  "errors": [-    {-      "message": "offset=43:\nunexpected 'Q'\nexpecting '}', Ignored, OperationType, or white space\n",-      "locations": [{ "line": 6, "column": 3 }]-    }-  ]-}+[+  {+    "message": "offset=43:\nunexpected 'Q'\nexpecting '#', '}', or OperationType\n",+    "locations": [{ "line": 6, "column": 3 }]+  }+]
test/schema/validation/default-value/argument/missing-field/response.json view
@@ -1,24 +1,22 @@-{-  "errors": [-    {-      "message": "Field Query.field(i1:) got invalid default value. in field \"field\": Undefined Field \"field\".",-      "locations": []-    },-    {-      "message": "Field Query.field(i1:) got invalid default value. in field \"field\": Undefined Field \"field2\".",-      "locations": []-    },-    {-      "message": "Field Query.field(i3:) got invalid default value. in field \"field.field\": Undefined Field \"field\".",-      "locations": []-    },-    {-      "message": "Field Query.field(i3:) got invalid default value. in field \"field\": Undefined Field \"field2\".",-      "locations": []-    },-    {-      "message": "Field Query.field(i2:) got invalid default value. Undefined Field \"field\".",-      "locations": []-    }-  ]-}+[+  {+    "message": "Field Query.field(i1:) got invalid default value. in field \"field\": Undefined Field \"field\".",+    "path": ["Query", "field"]+  },+  {+    "message": "Field Query.field(i1:) got invalid default value. in field \"field\": Undefined Field \"field2\".",+    "path": ["Query", "field"]+  },+  {+    "message": "Field Query.field(i2:) got invalid default value. Undefined Field \"field\".",+    "path": ["Query", "field"]+  },+  {+    "message": "Field Query.field(i3:) got invalid default value. in field \"field\": Undefined Field \"field2\".",+    "path": ["Query", "field"]+  },+  {+    "message": "Field Query.field(i3:) got invalid default value. in field \"field.field\": Undefined Field \"field\".",+    "path": ["Query", "field"]+  }+]
test/schema/validation/default-value/argument/unexpected-value/response.json view
@@ -1,32 +1,23 @@-{-  "errors": [-    {-      "message": "Field Query.field(i1:) got invalid default value. in field \"field1.field2\": Expected type \"String\" found 1.",-      "locations": []-    },-    {-      "message": "Field Query.field(i1:) got invalid default value. in field \"field2\": Expected type \"String\" found true.",-      "locations": []-    },-    {-      "message": "Field Query.field(i5:) got invalid default value. Expected type \"Int\" found \"some text\".",-      "locations": []-    },-    {-      "message": "Field Query.field(i3:) got invalid default value. Expected type \"TestEnum\" found EnumBB.",-      "locations": []-    },-    {-      "message": "Field Query.field(i4:) got invalid default value. Expected type \"ID\" found true.",-      "locations": []-    },-    {-      "message": "Field Query.field(i2:) got invalid default value. in field \"field1\": Expected type \"ID\" found { field3: 2344 }.",-      "locations": []-    },-    {-      "message": "Field Query.field(i2:) got invalid default value. in field \"field2\": Expected type \"String\" found 123.",-      "locations": []-    }-  ]-}+[+  {+    "message": "Field Query.field(i1:) got invalid default value. in field \"field1.field2\": Expected type \"String\" found 1."+  },+  {+    "message": "Field Query.field(i1:) got invalid default value. in field \"field2\": Expected type \"String\" found true."+  },+  {+    "message": "Field Query.field(i2:) got invalid default value. in field \"field1\": Expected type \"ID\" found { field3: 2344 }."+  },+  {+    "message": "Field Query.field(i2:) got invalid default value. in field \"field2\": Expected type \"String\" found 123."+  },+  {+    "message": "Field Query.field(i3:) got invalid default value. Expected type \"TestEnum\" found EnumBB."+  },+  {+    "message": "Field Query.field(i4:) got invalid default value. Expected type \"ID\" found true."+  },+  {+    "message": "Field Query.field(i5:) got invalid default value. Expected type \"Int\" found \"some text\"."+  }+]
test/schema/validation/default-value/argument/unknown-field/response.json view
@@ -1,16 +1,14 @@-{-  "errors": [-    {-      "message": "Field Query.field(i1:) got invalid default value. Unknown Field \"field2\".",-      "locations": []-    },-    {-      "message": "Field Query.field(i1:) got invalid default value. in field \"field\": Unknown Field \"field2\".",-      "locations": []-    },-    {-      "message": "Field Query.field(i1:) got invalid default value. in field \"field.field\": Unknown Field \"field3\".",-      "locations": []-    }-  ]-}+[+  {+    "message": "Field Query.field(i1:) got invalid default value. Unknown Field \"field2\".",+    "path": ["Query", "field"]+  },+  {+    "message": "Field Query.field(i1:) got invalid default value. in field \"field\": Unknown Field \"field2\".",+    "path": ["Query", "field"]+  },+  {+    "message": "Field Query.field(i1:) got invalid default value. in field \"field.field\": Unknown Field \"field3\".",+    "path": ["Query", "field"]+  }+]
test/schema/validation/default-value/field/missing-field/response.json view
@@ -1,12 +1,10 @@-{-  "errors": [-    {-      "message": "Field Input3.field1 got invalid default value. in field \"field\": Undefined Field \"field\".",-      "locations": []-    },-    {-      "message": "Field Input3.field1 got invalid default value. Undefined Field \"field2\".",-      "locations": []-    }-  ]-}+[+  {+    "message": "Field Input3.field1 got invalid default value. Undefined Field \"field2\".",+    "path": ["Input3", "field1"]+  },+  {+    "message": "Field Input3.field1 got invalid default value. in field \"field\": Undefined Field \"field\".",+    "path": ["Input3", "field1"]+  }+]
test/schema/validation/default-value/field/unexpected-value/response.json view
@@ -1,44 +1,32 @@-{-  "errors": [-    {-      "message": "Field Input2.objectField got invalid default value. in field \"field1\": Expected type \"ID!\" found true.",-      "locations": []-    },-    {-      "message": "Field Input2.objectField got invalid default value. in field \"field4\": Expected type \"TestEnum!\" found 1.",-      "locations": []-    },-    {-      "message": "Field Input2.objectField got invalid default value. in field \"field5\": Expected type \"TestEnum\" found \"some text\".",-      "locations": []-    },-    {-      "message": "Field Input2.objectField got invalid default value. in field \"field2\": Expected type \"String!\" found true.",-      "locations": []-    },-    {-      "message": "Field Input2.objectField got invalid default value. in field \"field3\": Expected type \"TestEnum\" found true.",-      "locations": []-    },-    {-      "message": "Field Input1.field1 got invalid default value. Expected type \"ID!\" found EnumA.",-      "locations": []-    },-    {-      "message": "Field Input1.field4 got invalid default value. Expected type \"TestEnum!\" found 1.",-      "locations": []-    },-    {-      "message": "Field Input1.field5 got invalid default value. Expected type \"TestEnum\" found \"some text\".",-      "locations": []-    },-    {-      "message": "Field Input1.field2 got invalid default value. Expected type \"String!\" found EnumA.",-      "locations": []-    },-    {-      "message": "Field Input1.field3 got invalid default value. Expected type \"TestEnum\" found UnknownEnum.",-      "locations": []-    }-  ]-}+[+  {+    "message": "Field Input1.field1 got invalid default value. Expected type \"ID!\" found EnumA."+  },+  {+    "message": "Field Input1.field2 got invalid default value. Expected type \"String!\" found EnumA."+  },+  {+    "message": "Field Input1.field3 got invalid default value. Expected type \"TestEnum\" found UnknownEnum."+  },+  {+    "message": "Field Input1.field4 got invalid default value. Expected type \"TestEnum!\" found 1."+  },+  {+    "message": "Field Input1.field5 got invalid default value. Expected type \"TestEnum\" found \"some text\"."+  },+  {+    "message": "Field Input2.objectField got invalid default value. in field \"field1\": Expected type \"ID!\" found true."+  },+  {+    "message": "Field Input2.objectField got invalid default value. in field \"field2\": Expected type \"String!\" found true."+  },+  {+    "message": "Field Input2.objectField got invalid default value. in field \"field3\": Expected type \"TestEnum\" found true."+  },+  {+    "message": "Field Input2.objectField got invalid default value. in field \"field4\": Expected type \"TestEnum!\" found 1."+  },+  {+    "message": "Field Input2.objectField got invalid default value. in field \"field5\": Expected type \"TestEnum\" found \"some text\"."+  }+]
test/schema/validation/default-value/field/unknown-field/response.json view
@@ -1,16 +1,14 @@-{-  "errors": [-    {-      "message": "Field Input3.field got invalid default value. Unknown Field \"field2\".",-      "locations": []-    },-    {-      "message": "Field Input3.field got invalid default value. in field \"field\": Unknown Field \"field2\".",-      "locations": []-    },-    {-      "message": "Field Input3.field got invalid default value. in field \"field\": Unknown Field \"field3\".",-      "locations": []-    }-  ]-}+[+  {+    "message": "Field Input3.field got invalid default value. Unknown Field \"field2\".",+    "path": ["Input3", "field"]+  },+  {+    "message": "Field Input3.field got invalid default value. in field \"field\": Unknown Field \"field2\".",+    "path": ["Input3", "field"]+  },+  {+    "message": "Field Input3.field got invalid default value. in field \"field\": Unknown Field \"field3\".",+    "path": ["Input3", "field"]+  }+]
test/schema/validation/directive/fail/at-invalid-place/response.json view
@@ -1,36 +1,34 @@-{-  "errors": [-    {-      "message": "Directive \"DirectiveA\" may not to be used on SCALAR",-      "locations": [{ "line": 9, "column": 17 }]-    },-    {-      "message": "Directive \"DirectiveB\" may not to be used on ENUM",-      "locations": [{ "line": 11, "column": 15 }]-    },-    {-      "message": "Directive \"DirectiveC\" may not to be used on ENUM_VALUE",-      "locations": [{ "line": 12, "column": 9 }]-    },-    {-      "message": "Directive \"deprecated\" may not to be used on INPUT_OBJECT",-      "locations": [{ "line": 16, "column": 14 }]-    },-    {-      "message": "Directive \"include\" may not to be used on INPUT_FIELD_DEFINITION",-      "locations": [{ "line": 17, "column": 14 }]-    },-    {-      "message": "Directive \"deprecated\" may not to be used on OBJECT",-      "locations": [{ "line": 21, "column": 12 }]-    },-    {-      "message": "Directive \"DirectiveD\" may not to be used on ARGUMENT_DEFINITION",-      "locations": [{ "line": 22, "column": 17 }]-    },-    {-      "message": "Directive \"include\" may not to be used on FIELD_DEFINITION",-      "locations": [{ "line": 22, "column": 35 }]-    }-  ]-}+[+  {+    "message": "Directive \"DirectiveA\" may not to be used on SCALAR",+    "locations": [{ "line": 9, "column": 17 }]+  },+  {+    "message": "Directive \"DirectiveB\" may not to be used on ENUM",+    "locations": [{ "line": 11, "column": 15 }]+  },+  {+    "message": "Directive \"DirectiveC\" may not to be used on ENUM_VALUE",+    "locations": [{ "line": 12, "column": 9 }]+  },+  {+    "message": "Directive \"deprecated\" may not to be used on INPUT_OBJECT",+    "locations": [{ "line": 16, "column": 14 }]+  },+  {+    "message": "Directive \"include\" may not to be used on INPUT_FIELD_DEFINITION",+    "locations": [{ "line": 17, "column": 14 }]+  },+  {+    "message": "Directive \"deprecated\" may not to be used on OBJECT",+    "locations": [{ "line": 21, "column": 12 }]+  },+  {+    "message": "Directive \"DirectiveD\" may not to be used on ARGUMENT_DEFINITION",+    "locations": [{ "line": 22, "column": 17 }]+  },+  {+    "message": "Directive \"include\" may not to be used on FIELD_DEFINITION",+    "locations": [{ "line": 22, "column": 35 }]+  }+]
test/schema/validation/directive/fail/missing-argument/response.json view
@@ -1,48 +1,57 @@-{-  "errors": [-    {-      "message": "Directive \"@DirectiveA\" argument \"a2\" is required but not provided.",-      "locations": [{ "line": 9, "column": 17 }]-    },-    {-      "message": "Directive \"@DirectiveA\" argument \"a1\" is required but not provided.",-      "locations": [{ "line": 9, "column": 17 }]-    },-    {-      "message": "Directive \"@DirectiveA\" argument \"a2\" is required but not provided.",-      "locations": [{ "line": 11, "column": 13 }]-    },-    {-      "message": "Directive \"@DirectiveA\" argument \"a1\" is required but not provided.",-      "locations": [{ "line": 11, "column": 13 }]-    },-    {-      "message": "Directive \"@DirectiveA\" argument \"a2\" is required but not provided.",-      "locations": [{ "line": 12, "column": 9 }]-    },-    {-      "message": "Directive \"@DirectiveA\" argument \"a1\" is required but not provided.",-      "locations": [{ "line": 12, "column": 9 }]-    },-    {-      "message": "Directive \"@DirectiveB\" argument \"a1\" is required but not provided.",-      "locations": [{ "line": 15, "column": 15 }]-    },-    {-      "message": "Directive \"@DirectiveB\" argument \"a1\" is required but not provided.",-      "locations": [{ "line": 16, "column": 17 }]-    },-    {-      "message": "Directive \"@DirectiveC\" argument \"arg\" is required but not provided.",-      "locations": [{ "line": 19, "column": 13 }]-    },-    {-      "message": "Directive \"@DirectiveC\" argument \"arg\" is required but not provided.",-      "locations": [{ "line": 20, "column": 17 }]-    },-    {-      "message": "Directive \"@DirectiveC\" argument \"arg\" is required but not provided.",-      "locations": [{ "line": 20, "column": 38 }]-    }-  ]-}+[+  {+    "message": "Directive \"DirectiveA\" argument \"a1\" is required but not provided.",+    "path": ["MyScalar"],+    "locations": [{ "line": 9, "column": 17 }]+  },+  {+    "message": "Directive \"DirectiveA\" argument \"a2\" is required but not provided.",+    "path": ["MyScalar"],+    "locations": [{ "line": 9, "column": 17 }]+  },+  {+    "message": "Directive \"DirectiveA\" argument \"a1\" is required but not provided.",+    "path": ["MyEnum"],+    "locations": [{ "line": 11, "column": 13 }]+  },+  {+    "message": "Directive \"DirectiveA\" argument \"a2\" is required but not provided.",+    "path": ["MyEnum"],+    "locations": [{ "line": 11, "column": 13 }]+  },+  {+    "message": "Directive \"DirectiveA\" argument \"a1\" is required but not provided.",+    "path": ["MyEnum"],+    "locations": [{ "line": 12, "column": 9 }]+  },+  {+    "message": "Directive \"DirectiveA\" argument \"a2\" is required but not provided.",+    "path": ["MyEnum"],+    "locations": [{ "line": 12, "column": 9 }]+  },+  {+    "message": "Directive \"DirectiveB\" argument \"a1\" is required but not provided.",+    "path": ["MyInput"],+    "locations": [{ "line": 15, "column": 15 }]+  },+  {+    "message": "Directive \"DirectiveB\" argument \"a1\" is required but not provided.",+    "path": ["MyInput", "field"],+    "locations": [{ "line": 16, "column": 17 }]+  },+  {+    "message": "Directive \"DirectiveC\" argument \"arg\" is required but not provided.",+    "path": ["MyType"],+    "locations": [{ "line": 19, "column": 13 }]+  },+  {+    "message": "Directive \"DirectiveC\" argument \"arg\" is required but not provided.",+    "path": ["MyType", "field"],+    "locations": [{ "line": 20, "column": 17 }]+  },+  {+    "message": "Directive \"DirectiveC\" argument \"arg\" is required but not provided.",+    "path": ["MyType", "field"],+    "locations": [{ "line": 20, "column": 38 }]+  }+]
test/schema/validation/directive/fail/sopthisticated/response.json view
@@ -1,64 +1,69 @@-{-  "errors": [-    {-      "message": "Directive \"DirectiveA\" may not to be used on ENUM_VALUE",-      "locations": [{ "line": 6, "column": 9 }]-    },-    {-      "message": "Directive \"@DirectiveA\" argument \"a1\" is required but not provided.",-      "locations": [{ "line": 6, "column": 9 }]-    },-    {-      "message": "Unknown Directive \"SomeDirective\".",-      "locations": [{ "line": 9, "column": 13 }]-    },-    {-      "message": "Unknown Argument \"someargs\" on Directive \"DirectiveC\".",-      "locations": [{ "line": 10, "column": 40 }]-    },-    {-      "message": "Argument \"arg\" got invalid value. Expected type \"Int!\" found True.",-      "locations": [{ "line": 10, "column": 29 }]-    },-    {-      "message": "Directive \"DirectiveC\" may not to be used on FIELD_DEFINITION",-      "locations": [{ "line": 10, "column": 62 }]-    },-    {-      "message": "Directive \"@DirectiveC\" argument \"arg\" is required but not provided.",-      "locations": [{ "line": 10, "column": 62 }]-    },-    {-      "message": "Directive \"include\" may not to be used on INPUT_OBJECT",-      "locations": [{ "line": 13, "column": 13 }]-    },-    {-      "message": "Directive \"@include\" argument \"if\" is required but not provided.",-      "locations": [{ "line": 13, "column": 13 }]-    },-    {-      "message": "Directive \"skip\" may not to be used on INPUT_FIELD_DEFINITION",-      "locations": [{ "line": 14, "column": 13 }]-    },-    {-      "message": "Directive \"@skip\" argument \"if\" is required but not provided.",-      "locations": [{ "line": 14, "column": 13 }]-    },-    {-      "message": "Directive \"DirectiveC\" may not to be used on OBJECT",-      "locations": [{ "line": 17, "column": 12 }]-    },-    {-      "message": "Argument \"arg\" got invalid value. Expected type \"Int!\" found \"bla\".",-      "locations": [{ "line": 17, "column": 24 }]-    },-    {-      "message": "Directive \"skip\" may not to be used on FIELD_DEFINITION",-      "locations": [{ "line": 18, "column": 23 }]-    },-    {-      "message": "Directive \"@skip\" argument \"if\" is required but not provided.",-      "locations": [{ "line": 18, "column": 23 }]-    }-  ]-}+[+  {+    "message": "Directive \"DirectiveA\" argument \"a1\" is required but not provided.",+    "path": ["MyEnum"],+    "locations": [{ "line": 6, "column": 9 }]+  },+  {+    "message": "Directive \"DirectiveA\" may not to be used on ENUM_VALUE",+    "locations": [{ "line": 6, "column": 9 }]+  },+  {+    "message": "Unknown Directive \"SomeDirective\".",+    "path": ["MyType"],+    "locations": [{ "line": 9, "column": 13 }]+  },+  {+    "message": "Argument \"arg\" got invalid value. Expected type \"Int!\" found True.",+    "locations": [{ "line": 10, "column": 29 }]+  },+  {+    "message": "Unknown Argument \"someargs\" on Directive \"DirectiveC\".",+    "path": ["MyType", "field"],+    "locations": [{ "line": 10, "column": 40 }]+  },+  {+    "message": "Directive \"DirectiveC\" argument \"arg\" is required but not provided.",+    "path": ["MyType", "field"],+    "locations": [{ "line": 10, "column": 62 }]+  },+  {+    "message": "Directive \"DirectiveC\" may not to be used on FIELD_DEFINITION",+    "locations": [{ "line": 10, "column": 62 }]+  },+  {+    "message": "Directive \"include\" argument \"if\" is required but not provided.",+    "path": ["Input"],+    "locations": [{ "line": 13, "column": 13 }]+  },+  {+    "message": "Directive \"include\" may not to be used on INPUT_OBJECT",+    "locations": [{ "line": 13, "column": 13 }]+  },+  {+    "message": "Directive \"skip\" argument \"if\" is required but not provided.",+    "path": ["Input", "field"],+    "locations": [{ "line": 14, "column": 13 }]+  },+  {+    "message": "Directive \"skip\" may not to be used on INPUT_FIELD_DEFINITION",+    "locations": [{ "line": 14, "column": 13 }]+  },+  {+    "message": "Directive \"DirectiveC\" may not to be used on OBJECT",+    "locations": [{ "line": 17, "column": 12 }]+  },+  {+    "message": "Argument \"arg\" got invalid value. Expected type \"Int!\" found \"bla\".",+    "locations": [{ "line": 17, "column": 24 }]+  },+  {+    "message": "Directive \"skip\" argument \"if\" is required but not provided.",+    "path": ["Query", "field"],+    "locations": [{ "line": 18, "column": 23 }]+  },+  {+    "message": "Directive \"skip\" may not to be used on FIELD_DEFINITION",+    "locations": [{ "line": 18, "column": 23 }]+  }+]
test/schema/validation/directive/fail/unexpected-value/response.json view
@@ -1,36 +1,34 @@-{-  "errors": [-    {-      "message": "Argument \"a1\" got invalid value. Expected type \"Int!\" found 0.1.",-      "locations": [{ "line": 9, "column": 29 }]-    },-    {-      "message": "Argument \"a1\" got invalid value. Expected type \"Int!\" found \"some string\".",-      "locations": [{ "line": 10, "column": 30 }]-    },-    {-      "message": "Argument \"a1\" got invalid value. Expected type \"Int!\" found True.",-      "locations": [{ "line": 11, "column": 30 }]-    },-    {-      "message": "Argument \"reason\" got invalid value. Expected type \"String\" found EnumA.",-      "locations": [{ "line": 14, "column": 21 }]-    },-    {-      "message": "Argument \"reason\" got invalid value. Expected type \"String\" found 1.",-      "locations": [{ "line": 15, "column": 21 }]-    },-    {-      "message": "Argument \"reason\" got invalid value. Expected type \"String\" found Bool.",-      "locations": [{ "line": 16, "column": 21 }]-    },-    {-      "message": "Argument \"a1\" got invalid value. in field \"field\": Expected type \"String\" found 2394.",-      "locations": [{ "line": 20, "column": 26 }]-    },-    {-      "message": "Argument \"a1\" got invalid value. Expected type \"MyInput!\" found [\"some deprication\"].",-      "locations": [{ "line": 21, "column": 30 }]-    }-  ]-}+[+  {+    "message": "Argument \"a1\" got invalid value. Expected type \"Int!\" found 0.1.",+    "locations": [{ "line": 9, "column": 29 }]+  },+  {+    "message": "Argument \"a1\" got invalid value. Expected type \"Int!\" found \"some string\".",+    "locations": [{ "line": 10, "column": 30 }]+  },+  {+    "message": "Argument \"a1\" got invalid value. Expected type \"Int!\" found True.",+    "locations": [{ "line": 11, "column": 30 }]+  },+  {+    "message": "Argument \"reason\" got invalid value. Expected type \"String\" found EnumA.",+    "locations": [{ "line": 14, "column": 21 }]+  },+  {+    "message": "Argument \"reason\" got invalid value. Expected type \"String\" found 1.",+    "locations": [{ "line": 15, "column": 21 }]+  },+  {+    "message": "Argument \"reason\" got invalid value. Expected type \"String\" found Bool.",+    "locations": [{ "line": 16, "column": 21 }]+  },+  {+    "message": "Argument \"a1\" got invalid value. in field \"field\": Expected type \"String\" found 2394.",+    "locations": [{ "line": 20, "column": 26 }]+  },+  {+    "message": "Argument \"a1\" got invalid value. Expected type \"MyInput!\" found [\"some deprication\"].",+    "locations": [{ "line": 21, "column": 30 }]+  }+]
test/schema/validation/directive/fail/unknown-directive/response.json view
@@ -1,57 +1,67 @@-{-  "errors": [-    {-      "message": "Unknown Directive \"DirectveA\".",-      "locations": [{ "line": 1, "column": 17 }]-    },-    {-      "message": "Unknown Directive \"DirectveB\".",-      "locations": [{ "line": 3, "column": 15 }]-    },-    {-      "message": "Unknown Directive \"DirectveB\".",-      "locations": [{ "line": 4, "column": 9 }]-    },-    {-      "message": "Unknown Directive \"DirectveC\".",-      "locations": [{ "line": 7, "column": 8 }]-    },-    {-      "message": "Unknown Directive \"DirectveC\".",-      "locations": [{ "line": 8, "column": 17 }]-    },-    {-      "message": "Unknown Directive \"DirectveC\".",-      "locations": [{ "line": 11, "column": 8 }]-    },-    {-      "message": "Unknown Directive \"DirectveC\".",-      "locations": [{ "line": 12, "column": 17 }]-    },-    {-      "message": "Unknown Directive \"DirectveD\".",-      "locations": [{ "line": 15, "column": 15 }]-    },-    {-      "message": "Unknown Directive \"DirectveE\".",-      "locations": [{ "line": 17, "column": 14 }]-    },-    {-      "message": "Unknown Directive \"DirectveE\".",-      "locations": [{ "line": 18, "column": 14 }]-    },--    {-      "message": "Unknown Directive \"DirectveF\".",-      "locations": [{ "line": 22, "column": 12 }]-    },-    {-      "message": "Unknown Directive \"DirectveF\".",-      "locations": [{ "line": 23, "column": 34 }]-    },-    {-      "message": "Unknown Directive \"DirectveF\".",-      "locations": [{ "line": 23, "column": 17 }]-    }-  ]-}+[+  {+    "message": "Unknown Directive \"DirectveA\".",+    "path": ["MyScalar"],+    "locations": [{ "line": 1, "column": 17 }]+  },+  {+    "message": "Unknown Directive \"DirectveB\".",+    "path": ["TestEnum"],+    "locations": [{ "line": 3, "column": 15 }]+  },+  {+    "message": "Unknown Directive \"DirectveB\".",+    "path": ["TestEnum"],+    "locations": [{ "line": 4, "column": 9 }]+  },+  {+    "message": "Unknown Directive \"DirectveC\".",+    "path": ["A"],+    "locations": [{ "line": 7, "column": 8 }]+  },+  {+    "message": "Unknown Directive \"DirectveC\".",+    "path": ["A", "name"],+    "locations": [{ "line": 8, "column": 17 }]+  },+  {+    "message": "Unknown Directive \"DirectveC\".",+    "path": ["B"],+    "locations": [{ "line": 11, "column": 8 }]+  },+  {+    "message": "Unknown Directive \"DirectveC\".",+    "path": ["B", "name"],+    "locations": [{ "line": 12, "column": 17 }]+  },+  {+    "message": "Unknown Directive \"DirectveD\".",+    "path": ["MyUnion"],+    "locations": [{ "line": 15, "column": 15 }]+  },+  {+    "message": "Unknown Directive \"DirectveE\".",+    "path": ["Input1"],+    "locations": [{ "line": 17, "column": 14 }]+  },+  {+    "message": "Unknown Directive \"DirectveE\".",+    "path": ["Input1", "field1"],+    "locations": [{ "line": 18, "column": 14 }]+  },+  {+    "message": "Unknown Directive \"DirectveF\".",+    "path": ["Query"],+    "locations": [{ "line": 22, "column": 12 }]+  },+  {+    "message": "Unknown Directive \"DirectveF\".",+    "path": ["Query", "field"],+    "locations": [{ "line": 23, "column": 17 }]+  },+  {+    "message": "Unknown Directive \"DirectveF\".",+    "path": ["Query", "field"],+    "locations": [{ "line": 23, "column": 34 }]+  }+]
test/schema/validation/interface/field-args/fail/response.json view
@@ -1,16 +1,14 @@-{-  "errors": [-    {-      "message": "Interface field argument Character.name(id:) expected but Deity.name does not provide it.",-      "locations": []-    },-    {-      "message": "Interface field argument Supernatural.power(id:) expects type\"ID!\" but Deity.power(id:) is type \"String!\".",-      "locations": []-    },-    {-      "message": "Interface field argument Supernatural.power(id:) expects type\"ID!\" but Hero.power(id:) is type \"ID\".",-      "locations": []-    }-  ]-}+[+  {+    "message": "Interface field Supernatural.power expects type \"[String!]!\" but Hero.power is type \"String!\"."+  },+  {+    "message": "Interface field argument Character.name(id:) expected but Deity.name does not provide it."+  },+  {+    "message": "Interface field argument Supernatural.power(id:) expects type \"ID!\" but Deity.power(id:) is type \"String!\"."+  },+  {+    "message": "Interface field argument Supernatural.power(id:) expects type \"ID!\" but Hero.power(id:) is type \"ID\"."+  }+]
test/schema/validation/interface/field-type/fail/response.json view
@@ -1,16 +1,11 @@-{-  "errors": [-    {-      "message": "Interface field Character.name expects type \"String\" but Deity.name is type \"Int\".",-      "locations": []-    },-    {-      "message": "Interface field Supernatural.power expects type \"[String!]!\" but Deity.power is type \"[String!]\".",-      "locations": []-    },-    {-      "message": "Interface field Character.name expected but \"Hero\" does not provide it.",-      "locations": []-    }-  ]-}+[+  {+    "message": "Interface field Character.name expected but \"Hero\" does not provide it."+  },+  {+    "message": "Interface field Character.name expects type \"String\" but Deity.name is type \"Int\"."+  },+  {+    "message": "Interface field Supernatural.power expects type \"[String!]!\" but Deity.power is type \"[String!]\"."+  }+]
test/schema/validation/schema-definition/fail/non-object-kind/from-schema/response.json view
@@ -1,16 +1,11 @@-{-  "errors": [-    {-      "message": "Query root type must be Object type if provided, it cannot be \"MyType\"",-      "locations": []-    },-    {-      "message": "Mutation root type must be Object type if provided, it cannot be \"MyUnion\"",-      "locations": []-    },-    {-      "message": "Subscription root type must be Object type if provided, it cannot be \"MyEnum\"",-      "locations": []-    }-  ]-}+[+  {+    "message": "Mutation root type must be Object type if provided, it cannot be \"MyUnion\""+  },+  {+    "message": "Query root type must be Object type if provided, it cannot be \"MyType\""+  },+  {+    "message": "Subscription root type must be Object type if provided, it cannot be \"MyEnum\""+  }+]
test/schema/validation/schema-definition/fail/non-object-kind/without-schema/response.json view
@@ -1,16 +1,11 @@-{-  "errors": [-    {-      "message": "Query root type must be Object type if provided, it cannot be \"Query\"",-      "locations": []-    },-    {-      "message": "Mutation root type must be Object type if provided, it cannot be \"Mutation\"",-      "locations": []-    },-    {-      "message": "Subscription root type must be Object type if provided, it cannot be \"Subscription\"",-      "locations": []-    }-  ]-}+[+  {+    "message": "Mutation root type must be Object type if provided, it cannot be \"Mutation\""+  },+  {+    "message": "Query root type must be Object type if provided, it cannot be \"Query\""+  },+  {+    "message": "Subscription root type must be Object type if provided, it cannot be \"Subscription\""+  }+]
test/schema/validation/schema-definition/fail/required query/empty/response.json view
@@ -1,8 +1,5 @@-{-  "errors": [-    {-      "message": "Query root type must be provided.",-      "locations": []-    }-  ]-}+[+  {+    "message": "Query root type must be provided."+  }+]
test/schema/validation/schema-definition/fail/required query/no-query/response.json view
@@ -1,8 +1,5 @@-{-  "errors": [-    {-      "message": "Query root type must be provided.",-      "locations": []-    }-  ]-}+[+  {+    "message": "Query root type must be provided."+  }+]
test/schema/validation/schema-definition/fail/required query/no-schema-no-query/response.json view
@@ -1,8 +1,5 @@-{-  "errors": [-    {-      "message": "Query root type must be provided.",-      "locations": []-    }-  ]-}+[+  {+    "message": "Query root type must be provided."+  }+]
test/schema/validation/schema-definition/fail/required query/schema-with-query/response.json view
@@ -1,8 +1,5 @@-{-  "errors": [-    {-      "message": "Query root type must be provided.",-      "locations": []-    }-  ]-}+[+  {+    "message": "Query root type must be provided."+  }+]
test/schema/validation/schema-definition/fail/unknown-type/unknown/response.json view
@@ -1,16 +1,5 @@-{-  "errors": [-    {-      "message": "Unknown type \"MyType1\".",-      "locations": []-    },-    {-      "message": "Unknown type \"Asfwe\".",-      "locations": []-    },-    {-      "message": "Unknown type \"GjsO\".",-      "locations": []-    }-  ]-}+[+  { "message": "Unknown type \"Asfwe\"." },+  { "message": "Unknown type \"GjsO\"." },+  { "message": "Unknown type \"MyType1\"." }+]