packages feed

morpheus-graphql-core 0.13.0 → 0.14.0

raw patch · 166 files changed

+7196/−4053 lines, 166 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Data.Morpheus.Core: decodeIntrospection :: ByteString -> Eventless Schema
- Data.Morpheus.Core: type EventCon event = (Eq (StreamChannel event), Typeable event, GQLChannel event)
- Data.Morpheus.Error: internalError :: Message -> Eventless a
- Data.Morpheus.Error: internalTypeMismatch :: Message -> ValidValue -> Eventless a
- Data.Morpheus.Internal.TH: applyT :: Name -> [Q Type] -> Q Type
- Data.Morpheus.Internal.TH: instanceFunD :: Name -> [TypeName] -> ExpQ -> Q Dec
- Data.Morpheus.Internal.TH: instanceHeadMultiT :: Name -> Q Type -> [Q Type] -> Q Type
- Data.Morpheus.Internal.TH: instanceHeadT :: Name -> TypeName -> [TypeName] -> Q Type
- Data.Morpheus.Internal.TH: instanceProxyFunD :: (Name, ExpQ) -> DecQ
- Data.Morpheus.Internal.TH: mkFieldName :: FieldName -> Name
- Data.Morpheus.Internal.TH: mkTypeName :: TypeName -> Name
- Data.Morpheus.Internal.TH: nameConE :: TypeName -> ExpQ
- Data.Morpheus.Internal.TH: nameConT :: TypeName -> Q Type
- Data.Morpheus.Internal.TH: nameConType :: TypeName -> Type
- Data.Morpheus.Internal.TH: nameLitP :: TypeName -> PatQ
- Data.Morpheus.Internal.TH: nameStringE :: TypeName -> ExpQ
- Data.Morpheus.Internal.TH: nameStringL :: TypeName -> Lit
- Data.Morpheus.Internal.TH: nameVarE :: FieldName -> ExpQ
- Data.Morpheus.Internal.TH: nameVarP :: FieldName -> PatQ
- Data.Morpheus.Internal.TH: nameVarT :: TypeName -> Q Type
- Data.Morpheus.Internal.TH: typeT :: Name -> [TypeName] -> Q Type
- Data.Morpheus.Internal.Utils: instance (Data.Hashable.Class.Hashable k, Data.Morpheus.Internal.Utils.KeyOf v, k Data.Type.Equality.~ Data.Morpheus.Internal.Utils.KEY v) => Data.Morpheus.Internal.Utils.Collection v (Data.HashMap.Base.HashMap k v)
- Data.Morpheus.Internal.Utils: instance (Data.Morpheus.Internal.Utils.KEY a Data.Type.Equality.~ k, GHC.Classes.Eq k, Data.Hashable.Class.Hashable k) => Data.Morpheus.Internal.Utils.Selectable (Data.HashMap.Base.HashMap k a) a
- Data.Morpheus.Internal.Utils: instance (Text.Megaparsec.Stream.Stream s, GHC.Classes.Ord e, Data.Morpheus.Internal.Utils.Failure [a] m) => Data.Morpheus.Internal.Utils.Failure [a] (Text.Megaparsec.Internal.ParsecT e s m)
- Data.Morpheus.Internal.Utils: instance Data.Morpheus.Internal.Utils.KeyOf Data.Morpheus.Types.Internal.AST.Base.Ref
- Data.Morpheus.Internal.Utils: instance Data.Morpheus.Internal.Utils.KeyOf Data.Morpheus.Types.Internal.AST.Base.TypeNameRef
- Data.Morpheus.Internal.Utils: instance Data.Morpheus.Internal.Utils.KeyOf a => Data.Morpheus.Internal.Utils.Selectable [a] a
- Data.Morpheus.Internal.Utils: type KEY a = FieldName;
- Data.Morpheus.Internal.Utils: type family KEY a :: *;
- Data.Morpheus.Internal.Utils: }
- Data.Morpheus.Types.IO: instance Data.Morpheus.Types.IO.MapAPI Data.ByteString.Internal.ByteString
- Data.Morpheus.Types.IO: instance Data.Morpheus.Types.IO.MapAPI Data.ByteString.Lazy.Internal.ByteString
- Data.Morpheus.Types.IO: instance Data.Morpheus.Types.IO.MapAPI Data.Text.Internal.Lazy.Text
- Data.Morpheus.Types.IO: instance Data.Morpheus.Types.IO.MapAPI Data.Text.Internal.Text
- Data.Morpheus.Types.Internal.AST: FULL_VALIDATION :: VALIDATION_MODE
- Data.Morpheus.Types.Internal.AST: WITHOUT_VARIABLES :: VALIDATION_MODE
- Data.Morpheus.Types.Internal.AST: class FromAny a (k :: TypeCategory)
- Data.Morpheus.Types.Internal.AST: class ToAny a
- Data.Morpheus.Types.Internal.AST: createAlias :: TypeName -> TypeRef
- Data.Morpheus.Types.Internal.AST: createArgument :: FieldName -> ([TypeWrapper], TypeName) -> FieldDefinition IN
- Data.Morpheus.Types.Internal.AST: createEnumType :: TypeName -> [TypeName] -> TypeDefinition a
- Data.Morpheus.Types.Internal.AST: createEnumValue :: TypeName -> DataEnumValue
- Data.Morpheus.Types.Internal.AST: createField :: Maybe (FieldContent TRUE cat) -> FieldName -> ([TypeWrapper], TypeName) -> FieldDefinition cat
- Data.Morpheus.Types.Internal.AST: createInputUnionFields :: TypeName -> [UnionMember IN] -> [FieldDefinition IN]
- Data.Morpheus.Types.Internal.AST: createType :: TypeName -> TypeContent TRUE a -> TypeDefinition a
- Data.Morpheus.Types.Internal.AST: createUnionType :: TypeName -> [TypeName] -> TypeDefinition OUT
- Data.Morpheus.Types.Internal.AST: data OrderedMap k a
- Data.Morpheus.Types.Internal.AST: data VALIDATION_MODE
- Data.Morpheus.Types.Internal.AST: defineType :: TypeDefinition cat -> Schema -> Schema
- Data.Morpheus.Types.Internal.AST: isFieldNullable :: FieldDefinition cat -> Bool
- Data.Morpheus.Types.Internal.AST: isNullableWrapper :: [TypeWrapper] -> Bool
- Data.Morpheus.Types.Internal.AST: isSystemTypeName :: TypeName -> Bool
- Data.Morpheus.Types.Internal.AST: mkField :: FieldName -> ([TypeWrapper], TypeName) -> FieldDefinition cat
- Data.Morpheus.Types.Internal.AST: sysTypes :: [TypeName]
- Data.Morpheus.Types.Internal.AST: toNullableField :: FieldDefinition cat -> FieldDefinition cat
- Data.Morpheus.Types.Internal.AST: type RESOLVED = 'RESOLVED
- Data.Morpheus.Types.Internal.AST: type TypeUpdater = LibUpdater Schema
- Data.Morpheus.Types.Internal.Resolving: Context :: Selection VALID -> Schema -> Operation VALID -> TypeName -> Context
- Data.Morpheus.Types.Internal.Resolving: class GQLChannel a where {
- Data.Morpheus.Types.Internal.Resolving: class MapStrategy (from :: OperationType) (to :: OperationType)
- Data.Morpheus.Types.Internal.Resolving: data Context
- Data.Morpheus.Types.Internal.Resolving: liftStateless :: (LiftOperation o, Monad m) => Eventless a -> Resolver o e m a
- Data.Morpheus.Types.Internal.Resolving: mapStrategy :: (MapStrategy from to, Monad m) => Resolver from e m (ResModel from e m) -> Resolver to e m (ResModel to e m)
- Data.Morpheus.Types.Internal.Resolving: resolveUpdates :: Monad m => lib -> [lib -> m lib] -> m lib
- Data.Morpheus.Types.Internal.Resolving: setTypeName :: Monad m => TypeName -> Resolver o e m a -> Resolver o e m a
- Data.Morpheus.Types.Internal.Resolving: streamChannels :: GQLChannel a => a -> [Channel a]
- Data.Morpheus.Types.Internal.Resolving: toResolver :: forall o e m a b. (LiftOperation o, Monad m) => (Arguments VALID -> Eventless a) -> (a -> Resolver o e m b) -> Resolver o e m b
- Data.Morpheus.Types.Internal.Resolving: type LibUpdater lib = lib -> Eventless lib
- Data.Morpheus.Types.Internal.Resolving: type family StreamChannel a :: *;
- Data.Morpheus.Types.Internal.Resolving: unsafeBind :: forall o e m a b. Monad m => Resolver o e m a -> (a -> Resolver o e m b) -> Resolver o e m b
- Data.Morpheus.Types.Internal.Resolving: }
+ Data.Morpheus.Core: Config :: Bool -> VALIDATION_MODE -> Config
+ Data.Morpheus.Core: FULL_VALIDATION :: VALIDATION_MODE
+ Data.Morpheus.Core: WITHOUT_VARIABLES :: VALIDATION_MODE
+ Data.Morpheus.Core: [debug] :: Config -> Bool
+ Data.Morpheus.Core: [validationMode] :: Config -> VALIDATION_MODE
+ Data.Morpheus.Core: data Config
+ Data.Morpheus.Core: data VALIDATION_MODE
+ Data.Morpheus.Core: debugConfig :: Config
+ Data.Morpheus.Core: defaultConfig :: Config
+ Data.Morpheus.Internal.TH: _' :: PatQ
+ Data.Morpheus.Internal.TH: _2' :: PatQ
+ 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: cat' :: Type
+ Data.Morpheus.Internal.TH: class ToName a
+ Data.Morpheus.Internal.TH: decodeObjectE :: (Bool -> Name) -> TypeName -> [FieldDefinition cat s] -> ExpQ
+ Data.Morpheus.Internal.TH: e' :: Type
+ Data.Morpheus.Internal.TH: funDProxy :: [(Name, ExpQ)] -> [DecQ]
+ 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 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: matchWith :: Bool -> (t -> (PatQ, ExpQ)) -> [t] -> ExpQ
+ Data.Morpheus.Internal.TH: mkFieldsE :: Name -> [FieldDefinition cat s] -> Exp
+ Data.Morpheus.Internal.TH: o' :: Type
+ Data.Morpheus.Internal.TH: toCon :: ToCon a b => a -> b
+ Data.Morpheus.Internal.TH: toConE :: ToCon a Exp => a -> ExpQ
+ Data.Morpheus.Internal.TH: toConT :: ToName a => a -> Q Type
+ Data.Morpheus.Internal.TH: toName :: ToName a => a -> Name
+ Data.Morpheus.Internal.TH: toString :: ToString a b => a -> b
+ Data.Morpheus.Internal.TH: toVarE :: ToVar a Exp => a -> ExpQ
+ Data.Morpheus.Internal.TH: toVarT :: ToVar a TypeQ => a -> TypeQ
+ Data.Morpheus.Internal.TH: v' :: ToVar Name a => a
+ Data.Morpheus.Internal.TH: vars :: ToVar a b => [a] -> [b]
+ Data.Morpheus.Internal.Utils: (<.>) :: SemigroupM m a => a -> a -> m a
+ Data.Morpheus.Internal.Utils: UpdateT :: (a -> m a) -> UpdateT m a
+ Data.Morpheus.Internal.Utils: [updateTState] :: UpdateT m a -> a -> m a
+ Data.Morpheus.Internal.Utils: class SemigroupM m a
+ Data.Morpheus.Internal.Utils: concatUpdates :: Monad m => [UpdateT m a] -> UpdateT m a
+ Data.Morpheus.Internal.Utils: failUpdates :: Failure e m => e -> UpdateT m a
+ Data.Morpheus.Internal.Utils: instance (Data.Morpheus.Error.NameCollision.NameCollision a, Data.Morpheus.Internal.Utils.KeyOf k a) => Data.Morpheus.Internal.Utils.Listable a (Data.HashMap.Internal.HashMap k a)
+ Data.Morpheus.Internal.Utils: instance (Data.Morpheus.Error.NameCollision.NameCollision a, Data.Morpheus.Internal.Utils.KeyOf k a) => Data.Morpheus.Internal.Utils.Merge (Data.HashMap.Internal.HashMap k a)
+ Data.Morpheus.Internal.Utils: instance (GHC.Base.Monad m, Data.Morpheus.Internal.Utils.Failure errors m) => Data.Morpheus.Internal.Utils.Failure errors (Control.Monad.Trans.Reader.ReaderT ctx m)
+ Data.Morpheus.Internal.Utils: instance (GHC.Classes.Eq k, Data.Hashable.Class.Hashable k) => Data.Morpheus.Internal.Utils.KeyOf k (k, a)
+ Data.Morpheus.Internal.Utils: instance (Text.Megaparsec.Stream.Stream s, GHC.Classes.Ord e, Data.Morpheus.Internal.Utils.Failure Data.Morpheus.Types.Internal.AST.Base.GQLErrors m) => Data.Morpheus.Internal.Utils.Failure Data.Morpheus.Types.Internal.AST.Base.ValidationErrors (Text.Megaparsec.Internal.ParsecT e s m)
+ Data.Morpheus.Internal.Utils: instance Data.Morpheus.Internal.Utils.KeyOf Data.Morpheus.Types.Internal.AST.Base.FieldName Data.Morpheus.Types.Internal.AST.Base.Ref
+ Data.Morpheus.Internal.Utils: instance Data.Morpheus.Internal.Utils.KeyOf Data.Morpheus.Types.Internal.AST.Base.TypeName Data.Morpheus.Types.Internal.AST.Base.TypeNameRef
+ Data.Morpheus.Internal.Utils: instance Data.Morpheus.Internal.Utils.KeyOf k a => Data.Morpheus.Internal.Utils.Selectable k a (Data.HashMap.Internal.HashMap k a)
+ Data.Morpheus.Internal.Utils: instance Data.Morpheus.Internal.Utils.KeyOf k a => Data.Morpheus.Internal.Utils.Selectable k a [a]
+ Data.Morpheus.Internal.Utils: instance Data.Morpheus.Internal.Utils.KeyOf k v => Data.Morpheus.Internal.Utils.Collection v (Data.HashMap.Internal.HashMap k v)
+ Data.Morpheus.Internal.Utils: mergeM :: SemigroupM m a => [Ref] -> a -> a -> m a
+ Data.Morpheus.Internal.Utils: newtype UpdateT m a
+ Data.Morpheus.Internal.Utils: ordTraverse :: (Monad f, KeyOf k b, Listable a (t a), Listable b (t b), Failure ValidationErrors f) => (a -> f b) -> t a -> f (t b)
+ Data.Morpheus.Internal.Utils: ordTraverse_ :: (Monad f, Listable a (t a)) => (a -> f b) -> t a -> f ()
+ Data.Morpheus.Internal.Utils: resolveUpdates :: Monad m => a -> [UpdateT m a] -> m a
+ Data.Morpheus.Internal.Utils: traverseCollection :: (Monad f, KeyOf k b, Listable a (t a), Listable b (t' b), Failure ValidationErrors f) => (a -> f b) -> t a -> f (t' b)
+ Data.Morpheus.Types.ID: instance GHC.Classes.Eq Data.Morpheus.Types.ID.ID
+ Data.Morpheus.Types.IO: instance Data.Morpheus.Types.IO.MapAPI Data.ByteString.Internal.ByteString Data.ByteString.Internal.ByteString
+ Data.Morpheus.Types.IO: instance Data.Morpheus.Types.IO.MapAPI Data.ByteString.Lazy.Internal.ByteString Data.ByteString.Lazy.Internal.ByteString
+ Data.Morpheus.Types.IO: instance Data.Morpheus.Types.IO.MapAPI Data.Morpheus.Types.IO.GQLRequest Data.Morpheus.Types.IO.GQLResponse
+ Data.Morpheus.Types.IO: instance Data.Morpheus.Types.IO.MapAPI Data.Text.Internal.Lazy.Text Data.Text.Internal.Lazy.Text
+ Data.Morpheus.Types.IO: instance Data.Morpheus.Types.IO.MapAPI Data.Text.Internal.Text Data.Text.Internal.Text
+ Data.Morpheus.Types.Internal.AST: InternalError :: Text -> InternalError
+ Data.Morpheus.Types.Internal.AST: RawDirectiveDefinition :: DirectiveDefinition CONST -> RawTypeDefinition
+ Data.Morpheus.Types.Internal.AST: RawSchemaDefinition :: SchemaDefinition -> RawTypeDefinition
+ Data.Morpheus.Types.Internal.AST: RawTypeDefinition :: TypeDefinition ANY CONST -> RawTypeDefinition
+ Data.Morpheus.Types.Internal.AST: RootOperationTypeDefinition :: OperationType -> TypeName -> RootOperationTypeDefinition
+ Data.Morpheus.Types.Internal.AST: SchemaDefinition :: Directives CONST -> OrdMap OperationType RootOperationTypeDefinition -> SchemaDefinition
+ Data.Morpheus.Types.Internal.AST: Typed :: a -> Typed a
+ Data.Morpheus.Types.Internal.AST: ValidationError :: Message -> [Position] -> ValidationError
+ Data.Morpheus.Types.Internal.AST: [directiveDefinitions] :: Schema -> [DirectiveDefinition s]
+ Data.Morpheus.Types.Internal.AST: [readInternalError] :: InternalError -> Text
+ Data.Morpheus.Types.Internal.AST: [rootOperationTypeDefinitionName] :: RootOperationTypeDefinition -> TypeName
+ Data.Morpheus.Types.Internal.AST: [rootOperationType] :: RootOperationTypeDefinition -> OperationType
+ Data.Morpheus.Types.Internal.AST: [schemaDirectives] :: SchemaDefinition -> Directives CONST
+ Data.Morpheus.Types.Internal.AST: [unSchemaDefinition] :: SchemaDefinition -> OrdMap OperationType RootOperationTypeDefinition
+ Data.Morpheus.Types.Internal.AST: [validationLocations] :: ValidationError -> [Position]
+ Data.Morpheus.Types.Internal.AST: [validationMessage] :: ValidationError -> Message
+ 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: class FromCategory a (k :: TypeCategory) (k' :: TypeCategory)
+ Data.Morpheus.Types.Internal.AST: class ToCategory a (k :: TypeCategory) (k' :: TypeCategory)
+ Data.Morpheus.Types.Internal.AST: data OrdMap k a
+ Data.Morpheus.Types.Internal.AST: data RawTypeDefinition
+ Data.Morpheus.Types.Internal.AST: data RootOperationTypeDefinition
+ Data.Morpheus.Types.Internal.AST: data SchemaDefinition
+ Data.Morpheus.Types.Internal.AST: data ValidationError
+ Data.Morpheus.Types.Internal.AST: fromCategory :: FromCategory a k k' => a k (s :: Stage) -> Maybe (a k' s)
+ Data.Morpheus.Types.Internal.AST: isNotSystemTypeName :: TypeName -> Bool
+ Data.Morpheus.Types.Internal.AST: mkEnumContent :: ELEM LEAF a ~ TRUE => [TypeName] -> TypeContent TRUE a s
+ Data.Morpheus.Types.Internal.AST: mkInputUnionFields :: TypeName -> [UnionMember IN s] -> FieldsDefinition IN s
+ Data.Morpheus.Types.Internal.AST: mkInputValue :: FieldName -> [TypeWrapper] -> TypeName -> FieldDefinition cat s
+ Data.Morpheus.Types.Internal.AST: mkType :: TypeName -> TypeContent TRUE a s -> TypeDefinition a s
+ Data.Morpheus.Types.Internal.AST: mkTypeRef :: TypeName -> TypeRef
+ Data.Morpheus.Types.Internal.AST: mkUnionContent :: [TypeName] -> TypeContent TRUE OUT s
+ Data.Morpheus.Types.Internal.AST: msgInternal :: Msg a => a -> InternalError
+ Data.Morpheus.Types.Internal.AST: msgValidation :: Msg a => a -> ValidationError
+ Data.Morpheus.Types.Internal.AST: newtype InternalError
+ Data.Morpheus.Types.Internal.AST: newtype Typed (cat :: TypeCategory) (s :: Stage) a
+ Data.Morpheus.Types.Internal.AST: possibleInterfaceTypes :: TypeName -> Schema s -> [TypeDefinition ANY s]
+ Data.Morpheus.Types.Internal.AST: possibleTypes :: TypeDefinition a s -> Schema s' -> [TypeName]
+ Data.Morpheus.Types.Internal.AST: toCategory :: ToCategory a k k' => a k (s :: Stage) -> a k' s
+ Data.Morpheus.Types.Internal.AST: toGQLError :: ValidationError -> GQLError
+ Data.Morpheus.Types.Internal.AST: toNullable :: Nullable a => a -> a
+ Data.Morpheus.Types.Internal.AST: type CONST = 'CONST
+ Data.Morpheus.Types.Internal.AST: type IMPLEMENTABLE = 'IMPLEMENTABLE
+ Data.Morpheus.Types.Internal.AST: type LEAF = 'LEAF
+ Data.Morpheus.Types.Internal.AST: type OBJECT = 'OBJECT
+ Data.Morpheus.Types.Internal.AST: type REQURE_IMPLEMENTABLE cat = ELEM cat IMPLEMENTABLE ~ TRUE
+ Data.Morpheus.Types.Internal.AST: type UnionSelection (s :: Stage) = MergeSet s UnionTag
+ Data.Morpheus.Types.Internal.AST: type ValidationErrors = [ValidationError]
+ Data.Morpheus.Types.Internal.AST: type family ELEM (elemKind :: TypeCategory) (setOfKind :: TypeCategory) :: Bool
+ Data.Morpheus.Types.Internal.AST: typed :: (a c s -> b) -> a c s -> Typed c s b
+ Data.Morpheus.Types.Internal.AST: untyped :: (a -> b) -> Typed c s a -> b
+ Data.Morpheus.Types.Internal.AST: withPosition :: Maybe Position -> ValidationError -> ValidationError
+ Data.Morpheus.Types.Internal.Resolving: ResolverContext :: Selection VALID -> Schema VALID -> Operation VALID -> TypeName -> Config -> ResolverContext
+ Data.Morpheus.Types.Internal.Resolving: [Channel] :: a -> Channel (Event a c)
+ Data.Morpheus.Types.Internal.Resolving: [SubscriptionField] :: {channel :: forall e m v. a ~ Resolver SUBSCRIPTION e m v => Channel e, unSubscribe :: a} -> SubscriptionField a
+ Data.Morpheus.Types.Internal.Resolving: [channelMap] :: RootResModel e m -> Maybe (Selection VALID -> ResolverState (Channel e))
+ Data.Morpheus.Types.Internal.Resolving: [config] :: ResolverContext -> Config
+ Data.Morpheus.Types.Internal.Resolving: data Channel (event :: *)
+ Data.Morpheus.Types.Internal.Resolving: data ResolverContext
+ Data.Morpheus.Types.Internal.Resolving: data SubscriptionField (a :: *)
+ Data.Morpheus.Types.Internal.Resolving: eventChannels :: Event e c -> [Channel (Event e c)]
+ Data.Morpheus.Types.Internal.Resolving: getArguments :: (LiftOperation o, Monad m) => Resolver o e m (Arguments VALID)
+ Data.Morpheus.Types.Internal.Resolving: liftResolverState :: (LiftOperation o, Monad m) => ResolverState a -> Resolver o e m a
+ Data.Morpheus.Types.Internal.Resolving: mkValue :: (LiftOperation o, Monad m) => Value -> ResModel o e m
+ Data.Morpheus.Types.Internal.Resolving: type ResolverState = ResolverStateT () Identity
+ Data.Morpheus.Types.SelectionTree: class SelectionTree nodeType
+ Data.Morpheus.Types.SelectionTree: getChildrenList :: SelectionTree nodeType => nodeType -> [nodeType]
+ Data.Morpheus.Types.SelectionTree: getName :: (SelectionTree nodeType, IsString name) => nodeType -> name
+ Data.Morpheus.Types.SelectionTree: instance Data.Morpheus.Types.SelectionTree.SelectionTree (Data.Morpheus.Types.Internal.AST.Selection.Selection Data.Morpheus.Types.Internal.AST.Stage.VALID)
+ Data.Morpheus.Types.SelectionTree: isLeaf :: SelectionTree nodeType => nodeType -> Bool
- Data.Morpheus.Core: getName :: SelectionTree nodeType => nodeType -> FieldName
+ Data.Morpheus.Core: getName :: (SelectionTree nodeType, IsString name) => nodeType -> name
- Data.Morpheus.Core: parseDSL :: ByteString -> Either String Schema
+ Data.Morpheus.Core: parseDSL :: ByteString -> Either String (Schema VALID)
- Data.Morpheus.Core: parseFullGQLDocument :: ByteString -> Eventless Schema
+ Data.Morpheus.Core: parseFullGQLDocument :: ByteString -> Eventless (Schema VALID)
- Data.Morpheus.Core: parseGQLDocument :: ByteString -> Eventless Schema
+ Data.Morpheus.Core: parseGQLDocument :: ByteString -> Eventless (Schema VALID)
- Data.Morpheus.Core: parseRequestWith :: Schema -> GQLRequest -> Eventless (Operation VALID)
+ Data.Morpheus.Core: parseRequestWith :: Config -> Schema VALID -> GQLRequest -> Eventless (Operation VALID)
- Data.Morpheus.Core: parseTypeDefinitions :: Text -> Eventless [TypeDefinition ANY]
+ Data.Morpheus.Core: parseTypeDefinitions :: Text -> Eventless [TypeDefinition ANY CONST]
- Data.Morpheus.Core: parseTypeSystemDefinition :: Text -> Eventless Schema
+ Data.Morpheus.Core: parseTypeSystemDefinition :: Text -> Eventless (Schema VALID)
- Data.Morpheus.Core: runApi :: forall event m. Monad m => Schema -> RootResModel event m -> GQLRequest -> ResponseStream event m (Value VALID)
+ Data.Morpheus.Core: runApi :: forall event m s. (Monad m, ValidateSchema s) => Schema s -> RootResModel event m -> Config -> GQLRequest -> ResponseStream event m (Value VALID)
- Data.Morpheus.Core: validateRequest :: Schema -> VALIDATION_MODE -> GQLQuery -> Eventless (Operation VALID)
+ Data.Morpheus.Core: validateRequest :: Config -> Schema VALID -> GQLQuery -> Eventless (Operation VALID)
- Data.Morpheus.Core: validateSchema :: Schema -> Eventless Schema
+ Data.Morpheus.Core: validateSchema :: ValidateSchema s => Bool -> Config -> Schema s -> Eventless (Schema VALID)
- Data.Morpheus.Internal.TH: apply :: Name -> [Q Exp] -> Q Exp
+ Data.Morpheus.Internal.TH: apply :: (Apply a, ToCon i a) => i -> [a] -> a
- Data.Morpheus.Internal.TH: declareTypeRef :: Bool -> TypeRef -> Type
+ Data.Morpheus.Internal.TH: declareTypeRef :: TypeRef -> Type
- Data.Morpheus.Internal.TH: destructRecord :: TypeName -> [FieldName] -> PatQ
+ Data.Morpheus.Internal.TH: destructRecord :: TypeName -> [FieldDefinition cat s] -> PatQ
- Data.Morpheus.Internal.TH: isEnum :: [ConsD cat] -> Bool
+ Data.Morpheus.Internal.TH: isEnum :: [ConsD cat s] -> Bool
- Data.Morpheus.Internal.Utils: (<:>) :: (Monad m, Merge a, Failure GQLErrors m) => a -> a -> m a
+ Data.Morpheus.Internal.Utils: (<:>) :: (Monad m, Merge a, Failure ValidationErrors m) => a -> a -> m a
- Data.Morpheus.Internal.Utils: class Eq (KEY a) => KeyOf a where {
+ Data.Morpheus.Internal.Utils: class (Eq k, Hashable k) => KeyOf k a | a -> k
- Data.Morpheus.Internal.Utils: class Selectable c a | c -> a
+ Data.Morpheus.Internal.Utils: class Selectable k a c | c -> a
- Data.Morpheus.Internal.Utils: fromElems :: (Listable a coll, KeyOf a, Monad m, Failure GQLErrors m) => [a] -> m coll
+ Data.Morpheus.Internal.Utils: fromElems :: (Listable a coll, Monad m, Failure ValidationErrors m) => [a] -> m coll
- Data.Morpheus.Internal.Utils: keyOf :: KeyOf a => a -> KEY a
+ Data.Morpheus.Internal.Utils: keyOf :: KeyOf k a => a -> k
- Data.Morpheus.Internal.Utils: keys :: (KeyOf a, Listable a coll) => coll -> [KEY a]
+ Data.Morpheus.Internal.Utils: keys :: (KeyOf k a, Listable a coll) => coll -> [k]
- Data.Morpheus.Internal.Utils: member :: forall a c. Selectable c a => KEY a -> c -> Bool
+ Data.Morpheus.Internal.Utils: member :: Selectable k a c => k -> c -> Bool
- Data.Morpheus.Internal.Utils: merge :: (Merge a, Monad m, Failure GQLErrors m) => [Ref] -> a -> a -> m a
+ Data.Morpheus.Internal.Utils: merge :: (Merge a, Monad m, Failure ValidationErrors m) => [Ref] -> a -> a -> m a
- Data.Morpheus.Internal.Utils: selectBy :: (Failure e m, Selectable c a, Monad m) => e -> KEY a -> c -> m a
+ Data.Morpheus.Internal.Utils: selectBy :: (Failure e m, Selectable k a c, Monad m) => e -> k -> c -> m a
- Data.Morpheus.Internal.Utils: selectOr :: Selectable c a => d -> (a -> d) -> KEY a -> c -> d
+ Data.Morpheus.Internal.Utils: selectOr :: Selectable k a c => d -> (a -> d) -> k -> c -> d
- Data.Morpheus.Internal.Utils: toPair :: KeyOf a => a -> (KEY a, a)
+ Data.Morpheus.Internal.Utils: toPair :: KeyOf k a => a -> (k, a)
- Data.Morpheus.Types.IO: class MapAPI a
+ Data.Morpheus.Types.IO: class MapAPI a b
- Data.Morpheus.Types.IO: mapAPI :: (MapAPI a, Applicative m) => (GQLRequest -> m GQLResponse) -> a -> m a
+ Data.Morpheus.Types.IO: mapAPI :: (MapAPI a b, Applicative m) => (GQLRequest -> m GQLResponse) -> a -> m b
- Data.Morpheus.Types.Internal.AST: Argument :: FieldName -> Value valid -> Position -> Argument
+ Data.Morpheus.Types.Internal.AST: Argument :: FieldName -> Position -> Value valid -> Argument
- Data.Morpheus.Types.Internal.AST: ArgumentsDefinition :: Maybe TypeName -> OrderedMap FieldName ArgumentDefinition -> ArgumentsDefinition
+ Data.Morpheus.Types.Internal.AST: ArgumentsDefinition :: Maybe TypeName -> OrdMap FieldName (ArgumentDefinition s) -> ArgumentsDefinition s
- Data.Morpheus.Types.Internal.AST: ConsD :: TypeName -> [FieldDefinition cat] -> ConsD cat
+ Data.Morpheus.Types.Internal.AST: ConsD :: TypeName -> [FieldDefinition cat s] -> ConsD cat s
- Data.Morpheus.Types.Internal.AST: DataEnumValue :: TypeName -> Maybe Description -> [Directive VALID] -> DataEnumValue
+ Data.Morpheus.Types.Internal.AST: DataEnumValue :: TypeName -> Maybe Description -> [Directive s] -> DataEnumValue s
- Data.Morpheus.Types.Internal.AST: DirectiveDefinition :: FieldName -> Maybe Description -> [DirectiveLocation] -> ArgumentsDefinition -> DirectiveDefinition
+ Data.Morpheus.Types.Internal.AST: DirectiveDefinition :: FieldName -> Maybe Description -> [DirectiveLocation] -> ArgumentsDefinition s -> DirectiveDefinition s
- Data.Morpheus.Types.Internal.AST: FieldDefinition :: FieldName -> Maybe Description -> TypeRef -> Maybe (FieldContent TRUE cat) -> [Directive VALID] -> FieldDefinition
+ Data.Morpheus.Types.Internal.AST: FieldDefinition :: FieldName -> Maybe Description -> TypeRef -> [Directive s] -> Maybe (FieldContent TRUE cat s) -> FieldDefinition
- Data.Morpheus.Types.Internal.AST: Fields :: OrderedMap FieldName def -> Fields def
+ Data.Morpheus.Types.Internal.AST: Fields :: OrdMap FieldName def -> Fields def
- Data.Morpheus.Types.Internal.AST: Fragment :: FieldName -> TypeName -> Position -> SelectionSet RAW -> Directives RAW -> Fragment
+ Data.Morpheus.Types.Internal.AST: Fragment :: FieldName -> TypeName -> Position -> SelectionSet stage -> Directives stage -> Fragment
- Data.Morpheus.Types.Internal.AST: GQLQuery :: Fragments -> Operation RAW -> [(FieldName, ResolvedValue)] -> GQLQuery
+ Data.Morpheus.Types.Internal.AST: GQLQuery :: Fragments RAW -> Operation RAW -> [(FieldName, ResolvedValue)] -> GQLQuery
- Data.Morpheus.Types.Internal.AST: ScalarDefinition :: (ValidValue -> Either Token ValidValue) -> ScalarDefinition
+ Data.Morpheus.Types.Internal.AST: ScalarDefinition :: (Value VALID -> Either Token (Value VALID)) -> ScalarDefinition
- Data.Morpheus.Types.Internal.AST: Schema :: TypeLib -> TypeDefinition 'Out -> Maybe (TypeDefinition 'Out) -> Maybe (TypeDefinition 'Out) -> Schema
+ Data.Morpheus.Types.Internal.AST: Schema :: TypeLib s -> TypeDefinition OBJECT s -> Maybe (TypeDefinition OBJECT s) -> Maybe (TypeDefinition OBJECT s) -> [DirectiveDefinition s] -> Schema
- Data.Morpheus.Types.Internal.AST: TypeDefinition :: TypeName -> DataFingerprint -> Maybe Description -> Directives VALID -> TypeContent TRUE a -> TypeDefinition
+ Data.Morpheus.Types.Internal.AST: TypeDefinition :: TypeName -> DataFingerprint -> Maybe Description -> Directives s -> TypeContent TRUE a s -> TypeDefinition
- Data.Morpheus.Types.Internal.AST: Variable :: FieldName -> TypeRef -> Position -> VariableContent (VAR stage) -> Variable
+ Data.Morpheus.Types.Internal.AST: Variable :: FieldName -> TypeRef -> Position -> VariableContent (CONST_OR_VALID stage) -> Variable
- Data.Morpheus.Types.Internal.AST: [$sel:fragments:GQLQuery] :: GQLQuery -> Fragments
+ Data.Morpheus.Types.Internal.AST: [$sel:fragments:GQLQuery] :: GQLQuery -> Fragments RAW
- Data.Morpheus.Types.Internal.AST: [DataEnum] :: {enumMembers :: DataEnum} -> TypeContent TRUE a
+ Data.Morpheus.Types.Internal.AST: [DataEnum] :: {enumMembers :: DataEnum s} -> TypeContent (ELEM LEAF a) a s
- Data.Morpheus.Types.Internal.AST: [DataInputObject] :: {inputObjectFields :: FieldsDefinition IN} -> TypeContent (IsSelected a IN) a
+ Data.Morpheus.Types.Internal.AST: [DataInputObject] :: {inputObjectFields :: FieldsDefinition IN s} -> TypeContent (ELEM IN a) a s
- Data.Morpheus.Types.Internal.AST: [DataInputUnion] :: {inputUnionMembers :: DataInputUnion} -> TypeContent (IsSelected a IN) a
+ Data.Morpheus.Types.Internal.AST: [DataInputUnion] :: {inputUnionMembers :: DataInputUnion s} -> TypeContent (ELEM IN a) a s
- Data.Morpheus.Types.Internal.AST: [DataInterface] :: {interfaceFields :: FieldsDefinition OUT} -> TypeContent (IsSelected a OUT) a
+ Data.Morpheus.Types.Internal.AST: [DataInterface] :: {interfaceFields :: FieldsDefinition OUT s} -> TypeContent (ELEM IMPLEMENTABLE a) a s
- Data.Morpheus.Types.Internal.AST: [DataObject] :: {objectImplements :: [TypeName], objectFields :: FieldsDefinition OUT} -> TypeContent (IsSelected a OUT) a
+ Data.Morpheus.Types.Internal.AST: [DataObject] :: {objectImplements :: [TypeName], objectFields :: FieldsDefinition OUT s} -> TypeContent (ELEM OBJECT a) a s
- Data.Morpheus.Types.Internal.AST: [DataScalar] :: {dataScalar :: ScalarDefinition} -> TypeContent TRUE a
+ Data.Morpheus.Types.Internal.AST: [DataScalar] :: {dataScalar :: ScalarDefinition} -> TypeContent (ELEM LEAF a) a s
- Data.Morpheus.Types.Internal.AST: [DataUnion] :: {unionMembers :: DataUnion} -> TypeContent (IsSelected a OUT) a
+ Data.Morpheus.Types.Internal.AST: [DataUnion] :: {unionMembers :: DataUnion s} -> TypeContent (ELEM OUT a) a s
- Data.Morpheus.Types.Internal.AST: [DefaultInputValue] :: {defaultInputValue :: Value RESOLVED} -> FieldContent (IsSelected cat IN) cat
+ Data.Morpheus.Types.Internal.AST: [DefaultInputValue] :: {defaultInputValue :: Value s} -> FieldContent (ELEM IN cat) cat s
- Data.Morpheus.Types.Internal.AST: [DefaultValue] :: Maybe ResolvedValue -> VariableContent RESOLVED
+ Data.Morpheus.Types.Internal.AST: [DefaultValue] :: Maybe ResolvedValue -> VariableContent CONST
- Data.Morpheus.Types.Internal.AST: [FieldArgs] :: {fieldArgsDef :: ArgumentsDefinition} -> FieldContent (IsSelected cat OUT) cat
+ Data.Morpheus.Types.Internal.AST: [FieldArgs] :: {fieldArgsDef :: ArgumentsDefinition s} -> FieldContent (ELEM OUT cat) cat s
- Data.Morpheus.Types.Internal.AST: [InlineFragment] :: Fragment -> Selection RAW
+ Data.Morpheus.Types.Internal.AST: [InlineFragment] :: Fragment RAW -> Selection RAW
- Data.Morpheus.Types.Internal.AST: [ResolvedVariable] :: Ref -> Variable VALID -> Value RESOLVED
+ Data.Morpheus.Types.Internal.AST: [ResolvedVariable] :: Ref -> Variable VALID -> Value CONST
- Data.Morpheus.Types.Internal.AST: [argumentsTypename] :: ArgumentsDefinition -> Maybe TypeName
+ Data.Morpheus.Types.Internal.AST: [argumentsTypename] :: ArgumentsDefinition s -> Maybe TypeName
- Data.Morpheus.Types.Internal.AST: [arguments] :: ArgumentsDefinition -> OrderedMap FieldName ArgumentDefinition
+ Data.Morpheus.Types.Internal.AST: [arguments] :: ArgumentsDefinition s -> OrdMap FieldName (ArgumentDefinition s)
- Data.Morpheus.Types.Internal.AST: [cFields] :: ConsD cat -> [FieldDefinition cat]
+ Data.Morpheus.Types.Internal.AST: [cFields] :: ConsD cat s -> [FieldDefinition cat s]
- Data.Morpheus.Types.Internal.AST: [cName] :: ConsD cat -> TypeName
+ Data.Morpheus.Types.Internal.AST: [cName] :: ConsD cat s -> TypeName
- Data.Morpheus.Types.Internal.AST: [directiveDefinitionArgs] :: DirectiveDefinition -> ArgumentsDefinition
+ Data.Morpheus.Types.Internal.AST: [directiveDefinitionArgs] :: DirectiveDefinition s -> ArgumentsDefinition s
- Data.Morpheus.Types.Internal.AST: [directiveDefinitionDescription] :: DirectiveDefinition -> Maybe Description
+ Data.Morpheus.Types.Internal.AST: [directiveDefinitionDescription] :: DirectiveDefinition s -> Maybe Description
- Data.Morpheus.Types.Internal.AST: [directiveDefinitionLocations] :: DirectiveDefinition -> [DirectiveLocation]
+ Data.Morpheus.Types.Internal.AST: [directiveDefinitionLocations] :: DirectiveDefinition s -> [DirectiveLocation]
- Data.Morpheus.Types.Internal.AST: [directiveDefinitionName] :: DirectiveDefinition -> FieldName
+ Data.Morpheus.Types.Internal.AST: [directiveDefinitionName] :: DirectiveDefinition s -> FieldName
- Data.Morpheus.Types.Internal.AST: [enumDescription] :: DataEnumValue -> Maybe Description
+ Data.Morpheus.Types.Internal.AST: [enumDescription] :: DataEnumValue s -> Maybe Description
- Data.Morpheus.Types.Internal.AST: [enumDirectives] :: DataEnumValue -> [Directive VALID]
+ Data.Morpheus.Types.Internal.AST: [enumDirectives] :: DataEnumValue s -> [Directive s]
- Data.Morpheus.Types.Internal.AST: [enumName] :: DataEnumValue -> TypeName
+ Data.Morpheus.Types.Internal.AST: [enumName] :: DataEnumValue s -> TypeName
- Data.Morpheus.Types.Internal.AST: [fieldContent] :: FieldDefinition -> Maybe (FieldContent TRUE cat)
+ Data.Morpheus.Types.Internal.AST: [fieldContent] :: FieldDefinition -> Maybe (FieldContent TRUE cat s)
- Data.Morpheus.Types.Internal.AST: [fieldDirectives] :: FieldDefinition -> [Directive VALID]
+ Data.Morpheus.Types.Internal.AST: [fieldDirectives] :: FieldDefinition -> [Directive s]
- Data.Morpheus.Types.Internal.AST: [fragmentDirectives] :: Fragment -> Directives RAW
+ Data.Morpheus.Types.Internal.AST: [fragmentDirectives] :: Fragment -> Directives stage
- Data.Morpheus.Types.Internal.AST: [fragmentSelection] :: Fragment -> SelectionSet RAW
+ Data.Morpheus.Types.Internal.AST: [fragmentSelection] :: Fragment -> SelectionSet stage
- Data.Morpheus.Types.Internal.AST: [mutation] :: Schema -> Maybe (TypeDefinition 'Out)
+ Data.Morpheus.Types.Internal.AST: [mutation] :: Schema -> Maybe (TypeDefinition OBJECT s)
- Data.Morpheus.Types.Internal.AST: [query] :: Schema -> TypeDefinition 'Out
+ Data.Morpheus.Types.Internal.AST: [query] :: Schema -> TypeDefinition OBJECT s
- Data.Morpheus.Types.Internal.AST: [subscription] :: Schema -> Maybe (TypeDefinition 'Out)
+ Data.Morpheus.Types.Internal.AST: [subscription] :: Schema -> Maybe (TypeDefinition OBJECT s)
- Data.Morpheus.Types.Internal.AST: [typeContent] :: TypeDefinition -> TypeContent TRUE a
+ Data.Morpheus.Types.Internal.AST: [typeContent] :: TypeDefinition -> TypeContent TRUE a s
- Data.Morpheus.Types.Internal.AST: [typeDirectives] :: TypeDefinition -> Directives VALID
+ Data.Morpheus.Types.Internal.AST: [typeDirectives] :: TypeDefinition -> Directives s
- Data.Morpheus.Types.Internal.AST: [types] :: Schema -> TypeLib
+ Data.Morpheus.Types.Internal.AST: [types] :: Schema -> TypeLib s
- Data.Morpheus.Types.Internal.AST: [unFields] :: Fields def -> OrderedMap FieldName def
+ Data.Morpheus.Types.Internal.AST: [unFields] :: Fields def -> OrdMap FieldName def
- Data.Morpheus.Types.Internal.AST: [validateValue] :: ScalarDefinition -> ValidValue -> Either Token ValidValue
+ Data.Morpheus.Types.Internal.AST: [validateValue] :: ScalarDefinition -> Value VALID -> Either Token (Value VALID)
- Data.Morpheus.Types.Internal.AST: [variableValue] :: Variable -> VariableContent (VAR stage)
+ Data.Morpheus.Types.Internal.AST: [variableValue] :: Variable -> VariableContent (CONST_OR_VALID stage)
- Data.Morpheus.Types.Internal.AST: createScalarType :: TypeName -> TypeDefinition a
+ Data.Morpheus.Types.Internal.AST: createScalarType :: ELEM LEAF a ~ TRUE => TypeName -> TypeDefinition a s
- Data.Morpheus.Types.Internal.AST: data ArgumentsDefinition
+ Data.Morpheus.Types.Internal.AST: data ArgumentsDefinition s
- Data.Morpheus.Types.Internal.AST: data ConsD cat
+ Data.Morpheus.Types.Internal.AST: data ConsD cat s
- Data.Morpheus.Types.Internal.AST: data DataEnumValue
+ Data.Morpheus.Types.Internal.AST: data DataEnumValue s
- Data.Morpheus.Types.Internal.AST: data DirectiveDefinition
+ Data.Morpheus.Types.Internal.AST: data DirectiveDefinition s
- Data.Morpheus.Types.Internal.AST: data FieldContent (bool :: Bool) (cat :: TypeCategory)
+ Data.Morpheus.Types.Internal.AST: data FieldContent (bool :: Bool) (cat :: TypeCategory) (s :: Stage)
- Data.Morpheus.Types.Internal.AST: data FieldDefinition (cat :: TypeCategory)
+ Data.Morpheus.Types.Internal.AST: data FieldDefinition (cat :: TypeCategory) (s :: Stage)
- Data.Morpheus.Types.Internal.AST: data Fragment
+ Data.Morpheus.Types.Internal.AST: data Fragment (stage :: Stage)
- Data.Morpheus.Types.Internal.AST: data Schema
+ Data.Morpheus.Types.Internal.AST: data Schema (s :: Stage)
- Data.Morpheus.Types.Internal.AST: data TypeContent (b :: Bool) (a :: TypeCategory)
+ Data.Morpheus.Types.Internal.AST: data TypeContent (b :: Bool) (a :: TypeCategory) (s :: Stage)
- Data.Morpheus.Types.Internal.AST: data TypeDefinition (a :: TypeCategory)
+ Data.Morpheus.Types.Internal.AST: data TypeDefinition (a :: TypeCategory) (s :: Stage)
- Data.Morpheus.Types.Internal.AST: data UnionMember (cat :: TypeCategory)
+ Data.Morpheus.Types.Internal.AST: data UnionMember (cat :: TypeCategory) (s :: Stage)
- Data.Morpheus.Types.Internal.AST: fieldContentArgs :: FieldContent b cat -> OrderedMap FieldName ArgumentDefinition
+ Data.Morpheus.Types.Internal.AST: fieldContentArgs :: FieldContent b cat s -> ArgumentsDefinition s
- Data.Morpheus.Types.Internal.AST: fieldVisibility :: FieldDefinition cat -> Bool
+ Data.Morpheus.Types.Internal.AST: fieldVisibility :: FieldDefinition cat s -> Bool
- Data.Morpheus.Types.Internal.AST: fieldsToArguments :: FieldsDefinition IN -> ArgumentsDefinition
+ Data.Morpheus.Types.Internal.AST: fieldsToArguments :: FieldsDefinition IN s -> ArgumentsDefinition s
- Data.Morpheus.Types.Internal.AST: fromAny :: FromAny a k => a ANY -> Maybe (a k)
+ Data.Morpheus.Types.Internal.AST: fromAny :: FromCategory a ANY k => a ANY (s :: Stage) -> Maybe (a k s)
- Data.Morpheus.Types.Internal.AST: getOperationDataType :: Failure GQLErrors m => Operation a -> Schema -> m (TypeDefinition OUT)
+ Data.Morpheus.Types.Internal.AST: getOperationDataType :: Failure ValidationError m => Operation s -> Schema VALID -> m (TypeDefinition OBJECT VALID)
- Data.Morpheus.Types.Internal.AST: initTypeLib :: TypeDefinition 'Out -> Schema
+ Data.Morpheus.Types.Internal.AST: initTypeLib :: TypeDefinition OBJECT s -> Schema s
- Data.Morpheus.Types.Internal.AST: insertType :: TypeDefinition ANY -> TypeUpdater
+ Data.Morpheus.Types.Internal.AST: insertType :: (Monad m, Failure ValidationErrors m) => TypeDefinition cat s -> UpdateT m (Schema s)
- Data.Morpheus.Types.Internal.AST: isEntNode :: TypeContent TRUE a -> Bool
+ Data.Morpheus.Types.Internal.AST: isEntNode :: TypeContent TRUE a s -> Bool
- Data.Morpheus.Types.Internal.AST: isEnum :: [ConsD cat] -> Bool
+ Data.Morpheus.Types.Internal.AST: isEnum :: [ConsD cat s] -> Bool
- Data.Morpheus.Types.Internal.AST: isNullable :: TypeRef -> Bool
+ Data.Morpheus.Types.Internal.AST: isNullable :: Nullable a => a -> Bool
- Data.Morpheus.Types.Internal.AST: kindOf :: TypeDefinition a -> TypeKind
+ Data.Morpheus.Types.Internal.AST: kindOf :: TypeDefinition a s -> TypeKind
- Data.Morpheus.Types.Internal.AST: lookupDeprecated :: [Directive VALID] -> Maybe (Directive VALID)
+ Data.Morpheus.Types.Internal.AST: lookupDeprecated :: [Directive s] -> Maybe (Directive s)
- Data.Morpheus.Types.Internal.AST: lookupDeprecatedReason :: Directive VALID -> Maybe Description
+ Data.Morpheus.Types.Internal.AST: lookupDeprecatedReason :: Directive s -> Maybe Description
- Data.Morpheus.Types.Internal.AST: mkCons :: TypeName -> FieldsDefinition cat -> ConsD cat
+ Data.Morpheus.Types.Internal.AST: mkCons :: TypeName -> FieldsDefinition cat s -> ConsD cat s
- Data.Morpheus.Types.Internal.AST: mkConsEnum :: DataEnumValue -> ConsD cat
+ Data.Morpheus.Types.Internal.AST: mkConsEnum :: DataEnumValue s -> ConsD cat s
- Data.Morpheus.Types.Internal.AST: mkObjectField :: ArgumentsDefinition -> FieldName -> ([TypeWrapper], TypeName) -> FieldDefinition OUT
+ Data.Morpheus.Types.Internal.AST: mkObjectField :: ArgumentsDefinition s -> FieldName -> [TypeWrapper] -> TypeName -> FieldDefinition OUT s
- Data.Morpheus.Types.Internal.AST: mkUnionMember :: TypeName -> UnionMember cat
+ Data.Morpheus.Types.Internal.AST: mkUnionMember :: TypeName -> UnionMember cat s
- Data.Morpheus.Types.Internal.AST: toAny :: ToAny a => a (k :: TypeCategory) -> a ANY
+ Data.Morpheus.Types.Internal.AST: toAny :: ToCategory a k ANY => a (k :: TypeCategory) (s :: Stage) -> a ANY s
- Data.Morpheus.Types.Internal.AST: toListField :: FieldDefinition cat -> FieldDefinition cat
+ Data.Morpheus.Types.Internal.AST: toListField :: FieldDefinition cat s -> FieldDefinition cat s
- Data.Morpheus.Types.Internal.AST: type ANY = 'Any
+ Data.Morpheus.Types.Internal.AST: type ANY = 'ANY
- Data.Morpheus.Types.Internal.AST: type Arguments s = OrderedMap FieldName (Argument s)
+ Data.Morpheus.Types.Internal.AST: type Arguments (s :: Stage) = OrdMap FieldName (Argument s)
- Data.Morpheus.Types.Internal.AST: type DataEnum = [DataEnumValue]
+ Data.Morpheus.Types.Internal.AST: type DataEnum s = [DataEnumValue s]
- Data.Morpheus.Types.Internal.AST: type DataInputUnion = [UnionMember IN]
+ Data.Morpheus.Types.Internal.AST: type DataInputUnion s = [UnionMember IN s]
- Data.Morpheus.Types.Internal.AST: type DataUnion = [UnionMember OUT]
+ Data.Morpheus.Types.Internal.AST: type DataUnion s = [UnionMember OUT s]
- Data.Morpheus.Types.Internal.AST: type DirectiveDefinitions = [DirectiveDefinition]
+ Data.Morpheus.Types.Internal.AST: type DirectiveDefinitions s = [DirectiveDefinition s]
- Data.Morpheus.Types.Internal.AST: type FieldsDefinition cat = Fields (FieldDefinition cat)
+ Data.Morpheus.Types.Internal.AST: type FieldsDefinition cat s = Fields (FieldDefinition cat s)
- Data.Morpheus.Types.Internal.AST: type Fragments = OrderedMap FieldName Fragment
+ Data.Morpheus.Types.Internal.AST: type Fragments (s :: Stage) = OrdMap FieldName (Fragment s)
- Data.Morpheus.Types.Internal.AST: type IN = 'In
+ Data.Morpheus.Types.Internal.AST: type IN = 'IN
- Data.Morpheus.Types.Internal.AST: type InputFieldsDefinition = Fields InputValueDefinition
+ Data.Morpheus.Types.Internal.AST: type InputFieldsDefinition s = Fields (InputValueDefinition s)
- Data.Morpheus.Types.Internal.AST: type OUT = 'Out
+ Data.Morpheus.Types.Internal.AST: type OUT = 'OUT
- Data.Morpheus.Types.Internal.AST: type Object a = OrderedMap FieldName (ObjectEntry a)
+ Data.Morpheus.Types.Internal.AST: type Object a = OrdMap FieldName (ObjectEntry a)
- Data.Morpheus.Types.Internal.AST: type ResolvedObject = Object RESOLVED
+ Data.Morpheus.Types.Internal.AST: type ResolvedObject = Object CONST
- Data.Morpheus.Types.Internal.AST: type ResolvedValue = Value RESOLVED
+ Data.Morpheus.Types.Internal.AST: type ResolvedValue = Value CONST
- Data.Morpheus.Types.Internal.AST: type TypeLib = HashMap TypeName (TypeDefinition ANY)
+ Data.Morpheus.Types.Internal.AST: type TypeLib s = SafeHashMap TypeName (TypeDefinition ANY s)
- Data.Morpheus.Types.Internal.AST: type VariableDefinitions s = OrderedMap FieldName (Variable s)
+ Data.Morpheus.Types.Internal.AST: type VariableDefinitions s = OrdMap FieldName (Variable s)
- Data.Morpheus.Types.Internal.AST: unsafeFromFields :: [FieldDefinition cat] -> FieldsDefinition cat
+ Data.Morpheus.Types.Internal.AST: unsafeFromFields :: [FieldDefinition cat s] -> FieldsDefinition cat s
- Data.Morpheus.Types.Internal.AST: updateSchema :: TypeName -> DataFingerprint -> [TypeUpdater] -> (a -> TypeDefinition cat) -> a -> TypeUpdater
+ Data.Morpheus.Types.Internal.AST: updateSchema :: (Monad m, Failure ValidationErrors m) => TypeName -> DataFingerprint -> [UpdateT m (Schema s)] -> (a -> TypeDefinition cat s) -> a -> UpdateT m (Schema s)
- Data.Morpheus.Types.Internal.Resolving: RootResModel :: Eventless (ResModel QUERY e m) -> Eventless (ResModel MUTATION e m) -> Eventless (ResModel SUBSCRIPTION e m) -> RootResModel e m
+ Data.Morpheus.Types.Internal.Resolving: RootResModel :: ResolverState (ResModel QUERY e m) -> ResolverState (ResModel MUTATION e m) -> ResolverState (ResModel SUBSCRIPTION e m) -> Maybe (Selection VALID -> ResolverState (Channel e)) -> RootResModel e m
- Data.Morpheus.Types.Internal.Resolving: [currentSelection] :: Context -> Selection VALID
+ Data.Morpheus.Types.Internal.Resolving: [currentSelection] :: ResolverContext -> Selection VALID
- Data.Morpheus.Types.Internal.Resolving: [currentTypeName] :: Context -> TypeName
+ Data.Morpheus.Types.Internal.Resolving: [currentTypeName] :: ResolverContext -> TypeName
- Data.Morpheus.Types.Internal.Resolving: [mutation] :: RootResModel e m -> Eventless (ResModel MUTATION e m)
+ Data.Morpheus.Types.Internal.Resolving: [mutation] :: RootResModel e m -> ResolverState (ResModel MUTATION e m)
- Data.Morpheus.Types.Internal.Resolving: [operation] :: Context -> Operation VALID
+ Data.Morpheus.Types.Internal.Resolving: [operation] :: ResolverContext -> Operation VALID
- Data.Morpheus.Types.Internal.Resolving: [query] :: RootResModel e m -> Eventless (ResModel QUERY e m)
+ Data.Morpheus.Types.Internal.Resolving: [query] :: RootResModel e m -> ResolverState (ResModel QUERY e m)
- Data.Morpheus.Types.Internal.Resolving: [schema] :: Context -> Schema
+ Data.Morpheus.Types.Internal.Resolving: [schema] :: ResolverContext -> Schema VALID
- Data.Morpheus.Types.Internal.Resolving: [subscription] :: RootResModel e m -> Eventless (ResModel SUBSCRIPTION e m)
+ Data.Morpheus.Types.Internal.Resolving: [subscription] :: RootResModel e m -> ResolverState (ResModel SUBSCRIPTION e m)
- Data.Morpheus.Types.Internal.Resolving: runRootResModel :: Monad m => RootResModel e m -> Context -> ResponseStream e m (Value VALID)
+ Data.Morpheus.Types.Internal.Resolving: runRootResModel :: Monad m => RootResModel e m -> ResolverContext -> ResponseStream e m (Value VALID)
- Data.Morpheus.Types.Internal.Resolving: subscribe :: forall e m a. (PushEvents (Channel e) (ResolverState (Channel e) m), Monad m) => [StreamChannel e] -> Resolver QUERY e m (e -> Resolver QUERY e m a) -> Resolver SUBSCRIPTION e m a
+ Data.Morpheus.Types.Internal.Resolving: subscribe :: forall e channel cont m a. (Monad m, Event channel cont ~ e) => channel -> Resolver QUERY e m (e -> Resolver SUBSCRIPTION e m a) -> SubscriptionField (Resolver SUBSCRIPTION e m a)
- Data.Morpheus.Types.Internal.Resolving: unsafeInternalContext :: (Monad m, LiftOperation o) => Resolver o e m Context
+ Data.Morpheus.Types.Internal.Resolving: unsafeInternalContext :: (Monad m, LiftOperation o) => Resolver o e m ResolverContext
- Data.Morpheus.Types.Internal.Resolving: withArguments :: forall o e m a. (LiftOperation o, Monad m) => (Arguments VALID -> Resolver o e m a) -> Resolver o e m a
+ Data.Morpheus.Types.Internal.Resolving: withArguments :: (LiftOperation o, Monad m) => (Arguments VALID -> Resolver o e m a) -> Resolver o e m a

Files

README.md view
@@ -9,10 +9,9 @@ ## Build GraphQL api with Core  ```hs-getSchema :: Monad m => ResponseStream e m Schema-getSchema =-  fromList-    [dsl|+schema :: Schema VALID+schema =+  [dsl|   type Query {     deity(name: String): Deity!   }@@ -45,7 +44,5 @@       ]  api :: GQLRequest -> ResponseStream e Identity (Value VALID)-api request = do-  schema <- getSchema-  runApi schema resolver request+api = runApi schema resolver ```
changelog.md view
@@ -1,6 +1,85 @@ # Changelog -## 0.13.0 - Unreleased Changes+## 0.14.0 - 15.08.2020++### new features++- query validation supports interfaces+- exposed: `Data.Morpheus.Types.SelectionTree`+- configurable api: `Data.Morpheus.Core` exports++  - `Config`+  - `defaultConfig`+  - `debugConfig`++- for better debuging, internal errors messages will display resolving state:+  - `current TypeName`+  - `current Selection`+  - `OperationDefinition`+  - `SchemaDefinition`+- rendering graphql "AST". e.g `render ( slection :: Selection VALID)` will render++```graphql+{+  user(arg1: 1) {+    name+  }+}+```++- quasiqouter `[dsl| <type definitions> |]` generates `Schema VALID`.+- parser supports custom directive definition. e.g++```graphql+directive @MyDirective on FIELD_DEFINITION | OBJECT+```++- directive Validation for Document (TypeSystem).+- supports of block string values. e.g:++  ```graphql+  query {+    createDeity(+      name: """+      powerqwe+      bla \n sd+      blu \\ dete+      """+    ) {+      name+    }+  }+  ```++- support of `schema`. issue #412++  ```graphql+  schema {+    query: MyQuery+  }+  ```++### Breaking Changes++- `Context' renamed to`ResolverContext'+- removed : `EventCon` from `Data.Morpheus.Core`+- internal refactoring: changed AST.+  Schema AST Types now need parameter `stage = RAW | CONST | VALID`.+  - `Schema VALID`+  - `TypeDefinition VALID`+  - `FieldDefinition IN VALID`+  - ...+- runApi requires argument config+  ```hs+    runApi ::+      Schema s ->+      RootResModel event m ->+      Config ->+      GQLRequest ->+      ResponseStream event m (Value VALID)+  ```++## 0.13.0 - 22.06.2020  ### new features 
morpheus-graphql-core.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: b13e1668b9269ab28dfdd66f04b342a5bdbec82e6ba59c98c0467604df7270a6+-- hash: b767cd6b24899f096032a5231c2edb2e7fb1e5d3c29e1a8b775ecbb1ca730ebd  name:           morpheus-graphql-core-version:        0.13.0+version:        0.14.0 synopsis:       Morpheus GraphQL Core description:    Build GraphQL APIs with your favourite functional language! category:       web, graphql@@ -23,8 +23,28 @@     changelog.md     README.md data-files:-    test/api/interface/query.gql-    test/api/simple/query.gql+    test/api/deity/interface/query.gql+    test/api/deity/schema.gql+    test/api/deity/simple/query.gql+    test/api/validation/fragment/fail-unknown-field-on-interface/query.gql+    test/api/validation/fragment/on-interface-fail-without-casting/query.gql+    test/api/validation/fragment/on-interface-inline/query.gql+    test/api/validation/fragment/on-interface-type-casting-inline/query.gql+    test/api/validation/fragment/on-interface-type-casting/query.gql+    test/api/validation/fragment/on-interface/query.gql+    test/api/validation/fragment/on-type/query.gql+    test/api/validation/fragment/on-union-type/query.gql+    test/api/validation/fragment/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+    test/schema/parsing/schema-definition/fail/dupplicate-field/query/schema.gql+    test/schema/parsing/schema-definition/fail/dupplicate-schema-definition/schema.gql+    test/schema/parsing/schema-definition/fail/unknown-fields/bla/schema.gql+    test/schema/parsing/schema-definition/fail/unknown-fields/uppercase/schema.gql+    test/schema/parsing/schema-definition/ok/query-mutation-subscription/schema.gql+    test/schema/parsing/schema-definition/ok/query-mutation/schema.gql+    test/schema/parsing/schema-definition/ok/query/schema.gql     test/schema/validation/default-value/argument/compound-ok/schema.gql     test/schema/validation/default-value/argument/missing-field/schema.gql     test/schema/validation/default-value/argument/unexpected-value/schema.gql@@ -33,12 +53,47 @@     test/schema/validation/default-value/field/missing-field/schema.gql     test/schema/validation/default-value/field/unexpected-value/schema.gql     test/schema/validation/default-value/field/unknown-field/schema.gql+    test/schema/validation/directive/fail/at-invalid-place/schema.gql+    test/schema/validation/directive/fail/missing-argument/schema.gql+    test/schema/validation/directive/fail/sopthisticated/schema.gql+    test/schema/validation/directive/fail/unexpected-value/schema.gql+    test/schema/validation/directive/fail/unknown-directive/schema.gql+    test/schema/validation/directive/ok/deprecated/custom-directive/schema.gql+    test/schema/validation/directive/ok/deprecated/schema.gql     test/schema/validation/interface/field-args/fail/schema.gql     test/schema/validation/interface/field-args/ok/schema.gql     test/schema/validation/interface/field-type/fail/schema.gql     test/schema/validation/interface/field-type/ok/schema.gql-    test/api/interface/response.json-    test/api/simple/response.json+    test/schema/validation/schema-definition/fail/non-object-kind/from-schema/schema.gql+    test/schema/validation/schema-definition/fail/non-object-kind/without-schema/schema.gql+    "test/schema/validation/schema-definition/fail/required query/empty/schema.gql"+    "test/schema/validation/schema-definition/fail/required query/no-query/schema.gql"+    "test/schema/validation/schema-definition/fail/required query/no-schema-no-query/schema.gql"+    "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/api/deity/interface/response.json+    test/api/deity/resolvers.json+    test/api/deity/simple/response.json+    test/api/validation/fragment/fail-unknown-field-on-interface/response.json+    test/api/validation/fragment/on-interface-fail-without-casting/response.json+    test/api/validation/fragment/on-interface-inline/response.json+    test/api/validation/fragment/on-interface-type-casting-inline/response.json+    test/api/validation/fragment/on-interface-type-casting/response.json+    test/api/validation/fragment/on-interface/response.json+    test/api/validation/fragment/on-type/response.json+    test/api/validation/fragment/on-union-type/response.json+    test/api/validation/fragment/resolvers.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+    test/schema/parsing/schema-definition/fail/dupplicate-field/query/response.json+    test/schema/parsing/schema-definition/fail/dupplicate-schema-definition/response.json+    test/schema/parsing/schema-definition/fail/unknown-fields/bla/response.json+    test/schema/parsing/schema-definition/fail/unknown-fields/uppercase/response.json+    test/schema/parsing/schema-definition/ok/query-mutation-subscription/response.json+    test/schema/parsing/schema-definition/ok/query-mutation/response.json+    test/schema/parsing/schema-definition/ok/query/response.json     test/schema/validation/default-value/argument/compound-ok/response.json     test/schema/validation/default-value/argument/missing-field/response.json     test/schema/validation/default-value/argument/unexpected-value/response.json@@ -47,10 +102,25 @@     test/schema/validation/default-value/field/missing-field/response.json     test/schema/validation/default-value/field/unexpected-value/response.json     test/schema/validation/default-value/field/unknown-field/response.json+    test/schema/validation/directive/fail/at-invalid-place/response.json+    test/schema/validation/directive/fail/missing-argument/response.json+    test/schema/validation/directive/fail/sopthisticated/response.json+    test/schema/validation/directive/fail/unexpected-value/response.json+    test/schema/validation/directive/fail/unknown-directive/response.json+    test/schema/validation/directive/ok/deprecated/custom-directive/response.json+    test/schema/validation/directive/ok/deprecated/response.json     test/schema/validation/interface/field-args/fail/response.json     test/schema/validation/interface/field-args/ok/response.json     test/schema/validation/interface/field-type/fail/response.json     test/schema/validation/interface/field-type/ok/response.json+    test/schema/validation/schema-definition/fail/non-object-kind/from-schema/response.json+    test/schema/validation/schema-definition/fail/non-object-kind/without-schema/response.json+    "test/schema/validation/schema-definition/fail/required query/empty/response.json"+    "test/schema/validation/schema-definition/fail/required query/no-query/response.json"+    "test/schema/validation/schema-definition/fail/required query/no-schema-no-query/response.json"+    "test/schema/validation/schema-definition/fail/required query/schema-with-query/response.json"+    test/schema/validation/schema-definition/fail/unknown-type/unknown/response.json+    test/schema/validation/schema-definition/ok/full/response.json  source-repository head   type: git@@ -68,11 +138,11 @@       Data.Morpheus.Types.Internal.Resolving       Data.Morpheus.Types.GQLScalar       Data.Morpheus.Types.ID+      Data.Morpheus.Types.SelectionTree   other-modules:       Data.Morpheus.Error.Document.Interface       Data.Morpheus.Error.Fragment       Data.Morpheus.Error.Input-      Data.Morpheus.Error.Internal       Data.Morpheus.Error.NameCollision       Data.Morpheus.Error.Operation       Data.Morpheus.Error.Schema@@ -80,6 +150,7 @@       Data.Morpheus.Error.Utils       Data.Morpheus.Error.Variable       Data.Morpheus.Error.Warning+      Data.Morpheus.Internal.Graph       Data.Morpheus.Parser       Data.Morpheus.Parsing.Document.TypeSystem       Data.Morpheus.Parsing.Internal.Arguments@@ -87,38 +158,42 @@       Data.Morpheus.Parsing.Internal.Pattern       Data.Morpheus.Parsing.Internal.Terms       Data.Morpheus.Parsing.Internal.Value-      Data.Morpheus.Parsing.JSONSchema.Parse-      Data.Morpheus.Parsing.JSONSchema.Types       Data.Morpheus.Parsing.Request.Operation       Data.Morpheus.Parsing.Request.Parser       Data.Morpheus.Parsing.Request.Selection       Data.Morpheus.Rendering.RenderGQL       Data.Morpheus.Rendering.RenderIntrospection-      Data.Morpheus.Schema.Directives       Data.Morpheus.Schema.DSL       Data.Morpheus.Schema.Schema       Data.Morpheus.Schema.SchemaAPI-      Data.Morpheus.Schema.TypeKind       Data.Morpheus.Types.Internal.AST.Base       Data.Morpheus.Types.Internal.AST.DirectiveLocation+      Data.Morpheus.Types.Internal.AST.Fields       Data.Morpheus.Types.Internal.AST.MergeSet-      Data.Morpheus.Types.Internal.AST.OrderedMap+      Data.Morpheus.Types.Internal.AST.OrdMap+      Data.Morpheus.Types.Internal.AST.SafeHashMap       Data.Morpheus.Types.Internal.AST.Selection+      Data.Morpheus.Types.Internal.AST.Stage       Data.Morpheus.Types.Internal.AST.TH+      Data.Morpheus.Types.Internal.AST.TypeCategory       Data.Morpheus.Types.Internal.AST.TypeSystem       Data.Morpheus.Types.Internal.AST.Value+      Data.Morpheus.Types.Internal.Config       Data.Morpheus.Types.Internal.Resolving.Core+      Data.Morpheus.Types.Internal.Resolving.Event       Data.Morpheus.Types.Internal.Resolving.Resolver+      Data.Morpheus.Types.Internal.Resolving.ResolverState       Data.Morpheus.Types.Internal.Validation       Data.Morpheus.Types.Internal.Validation.Error+      Data.Morpheus.Types.Internal.Validation.Internal       Data.Morpheus.Types.Internal.Validation.SchemaValidator       Data.Morpheus.Types.Internal.Validation.Validator-      Data.Morpheus.Types.SelectionTree       Data.Morpheus.Validation.Document.Validation+      Data.Morpheus.Validation.Internal.Arguments       Data.Morpheus.Validation.Internal.Directive       Data.Morpheus.Validation.Internal.Value-      Data.Morpheus.Validation.Query.Arguments       Data.Morpheus.Validation.Query.Fragment+      Data.Morpheus.Validation.Query.FragmentPreconditions       Data.Morpheus.Validation.Query.Selection       Data.Morpheus.Validation.Query.UnionSelection       Data.Morpheus.Validation.Query.Validation@@ -148,7 +223,8 @@   main-is: Spec.hs   other-modules:       Lib-      Schema+      Utils.Api+      Utils.Schema       Paths_morpheus_graphql_core   hs-source-dirs:       test
src/Data/Morpheus/Core.hs view
@@ -9,11 +9,9 @@  module Data.Morpheus.Core   ( runApi,-    EventCon,     parseDSL,     parseFullGQLDocument,     parseGQLDocument,-    decodeIntrospection,     parseTypeSystemDefinition,     parseTypeDefinitions,     validateRequest,@@ -22,6 +20,10 @@     parseRequest,     RenderGQL (..),     SelectionTree (..),+    Config (..),+    VALIDATION_MODE (..),+    defaultConfig,+    debugConfig,   ) where @@ -31,7 +33,8 @@   ( ByteString,   ) import Data.Morpheus.Internal.Utils-  ( empty,+  ( (<:>),+    empty,   ) import Data.Morpheus.Parser   ( parseRequest,@@ -39,13 +42,10 @@     parseTypeDefinitions,     parseTypeSystemDefinition,   )-import Data.Morpheus.Parsing.JSONSchema.Parse-  ( decodeIntrospection,-  ) import Data.Morpheus.Rendering.RenderGQL   ( RenderGQL (..),   )-import Data.Morpheus.Schema.Schema (withSystemTypes)+import Data.Morpheus.Schema.Schema (internalSchema) import Data.Morpheus.Schema.SchemaAPI (withSystemFields) import Data.Morpheus.Types.IO   ( GQLRequest (..),@@ -58,10 +58,15 @@     VALID,     Value,   )+import Data.Morpheus.Types.Internal.Config+  ( Config (..),+    VALIDATION_MODE (..),+    debugConfig,+    defaultConfig,+  ) import Data.Morpheus.Types.Internal.Resolving-  ( Context (..),-    Eventless,-    GQLChannel (..),+  ( Eventless,+    ResolverContext (..),     ResponseStream,     ResultT (..),     RootResModel,@@ -70,7 +75,7 @@     runRootResModel,   ) import Data.Morpheus.Types.SelectionTree (SelectionTree (..))-import Data.Morpheus.Validation.Document.Validation (validateSchema)+import Data.Morpheus.Validation.Document.Validation (ValidateSchema (..)) import Data.Morpheus.Validation.Query.Validation   ( validateRequest,   )@@ -78,50 +83,54 @@   ( toStrict,   ) import Data.Text.Lazy.Encoding (decodeUtf8)-import Data.Typeable (Typeable) -type EventCon event =-  (Eq (StreamChannel event), Typeable event, GQLChannel event)- runApi ::-  forall event m.-  (Monad m) =>-  Schema ->+  forall event m s.+  (Monad m, ValidateSchema s) =>+  Schema s ->   RootResModel event m ->+  Config ->   GQLRequest ->   ResponseStream event m (Value VALID)-runApi inputSchema resModel request = do-  ctx <- validRequest-  model <- withSystemFields (schema ctx) resModel-  runRootResModel model ctx-  where-    validRequest ::-      Monad m => ResponseStream event m Context-    validRequest = cleanEvents $ ResultT $ pure $ do-      validSchema <- validateSchema inputSchema-      schema <- withSystemTypes validSchema-      operation <- parseRequestWith schema request-      pure $-        Context-          { schema,-            operation,-            currentTypeName = "Root",-            currentSelection =-              Selection-                { selectionName = "Root",-                  selectionArguments = empty,-                  selectionPosition = operationPosition operation,-                  selectionAlias = Nothing,-                  selectionContent = SelectionSet (operationSelection operation),-                  selectionDirectives = []-                }-          }+runApi inputSchema resModel config request = do+  validRequest <- validateReq inputSchema config request+  resovers <- withSystemFields (schema validRequest) resModel+  runRootResModel resovers validRequest -parseDSL :: ByteString -> Either String Schema+validateReq ::+  ( Monad m,+    ValidateSchema s+  ) =>+  Schema s ->+  Config ->+  GQLRequest ->+  ResponseStream event m ResolverContext+validateReq inputSchema config request = cleanEvents $ ResultT $ pure $ do+  validSchema <- validateSchema True config inputSchema+  schema <- internalSchema <:> validSchema+  operation <- parseRequestWith config schema request+  pure $+    ResolverContext+      { schema,+        config,+        operation,+        currentTypeName = "Root",+        currentSelection =+          Selection+            { selectionName = "Root",+              selectionArguments = empty,+              selectionPosition = operationPosition operation,+              selectionAlias = Nothing,+              selectionContent = SelectionSet (operationSelection operation),+              selectionDirectives = []+            }+      }++parseDSL :: ByteString -> Either String (Schema VALID) parseDSL = resultOr (Left . show) pure . parseGQLDocument -parseGQLDocument :: ByteString -> Eventless Schema+parseGQLDocument :: ByteString -> Eventless (Schema VALID) parseGQLDocument = parseTypeSystemDefinition . LT.toStrict . decodeUtf8 -parseFullGQLDocument :: ByteString -> Eventless Schema-parseFullGQLDocument = parseGQLDocument >=> withSystemTypes+parseFullGQLDocument :: ByteString -> Eventless (Schema VALID)+parseFullGQLDocument = parseGQLDocument >=> (internalSchema <:>)
src/Data/Morpheus/Error.hs view
@@ -1,15 +1,12 @@ module Data.Morpheus.Error   ( errorMessage,     globalErrorMessage,-    internalError,-    internalTypeMismatch,     gqlWarnings,     renderGQLErrors,     deprecatedField,   ) where -import Data.Morpheus.Error.Internal import Data.Morpheus.Error.Utils import Data.Morpheus.Error.Warning   ( deprecatedField,
src/Data/Morpheus/Error/Document/Interface.hs view
@@ -1,6 +1,7 @@ {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Error.Document.Interface   ( unknownInterface,@@ -10,14 +11,13 @@   ) where -import Data.Morpheus.Error.Utils (globalErrorMessage)+import Data.Maybe (Maybe (..)) import Data.Morpheus.Types.Internal.AST.Base   ( FieldName (..),-    GQLError (..),-    GQLErrors,     TypeName (..),     TypeRef,-    msg,+    ValidationError,+    msgValidation,   ) import Data.Morpheus.Types.Internal.Validation.SchemaValidator   ( Field (..),@@ -26,10 +26,8 @@   ) import Data.Semigroup ((<>)) -unknownInterface :: TypeName -> GQLErrors-unknownInterface name = globalErrorMessage message-  where-    message = "Unknown Interface " <> msg name <> "."+unknownInterface :: TypeName -> ValidationError+unknownInterface name = "Unknown Interface " <> msgValidation name <> "."  data ImplementsError   = UnexpectedType@@ -45,31 +43,25 @@   }  class PartialImplements ctx where-  partialImplements :: ctx -> ImplementsError -> GQLErrors+  partialImplements :: ctx -> ImplementsError -> ValidationError  instance PartialImplements (Interface, FieldName) where   partialImplements (Interface interfaceName typename, fieldname) errorType =-    [ GQLError-        { message = message,-          locations = []-        }-    ]+    "Interface field "+      <> renderField interfaceName fieldname Nothing+      <> detailedMessage errorType     where-      message =-        "Interface field "-          <> renderField interfaceName fieldname Nothing-          <> detailedMessage errorType       detailedMessage UnexpectedType {expectedType, foundType} =         " expects type "-          <> msg expectedType+          <> msgValidation expectedType           <> " but "           <> renderField typename fieldname Nothing           <> " is type "-          <> msg foundType+          <> msgValidation foundType           <> "."       detailedMessage Missing =         " expected but "-          <> msg typename+          <> msgValidation typename           <> " does not provide it."  -- Interface field TestInterface.name expected but User does not provide it.@@ -77,24 +69,17 @@  instance PartialImplements (Interface, Field) where   partialImplements (Interface interfaceName typename, Field fieldname argName) errorType =-    [ GQLError-        { message = message,-          locations = []-        }-    ]+    "Interface field argument "+      <> renderField interfaceName fieldname (Just argName)+      <> detailedMessage errorType     where-      ---      message =-        "Interface field argument "-          <> renderField interfaceName fieldname (Just argName)-          <> detailedMessage errorType       detailedMessage UnexpectedType {expectedType, foundType} =         " expects type"-          <> msg expectedType+          <> msgValidation expectedType           <> " but "           <> renderField typename fieldname (Just argName)           <> " is type "-          <> msg foundType+          <> msgValidation foundType           <> "."       detailedMessage Missing =         " expected but "
src/Data/Morpheus/Error/Fragment.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Error.Fragment   ( cannotSpreadWithinItself,@@ -7,18 +8,20 @@ where  -- MORPHEUS-import Data.Morpheus.Error.Utils (errorMessage)++import Data.Maybe (Maybe (..))+import Data.Morpheus.Error.Utils (validationErrorMessage) import Data.Morpheus.Types.Internal.AST.Base   ( FieldName,-    GQLError (..),-    GQLErrors,     Position,     Ref (..),     TypeName,+    ValidationError (..),     msg,     msgSepBy,   ) import Data.Semigroup ((<>))+import Prelude (($), fmap, head)  {-   FRAGMENT:@@ -32,21 +35,21 @@     {...H} -> "Unknown fragment \"H\"." -} -cannotSpreadWithinItself :: [Ref] -> GQLErrors-cannotSpreadWithinItself fragments = [GQLError {message = text, locations = map refPosition fragments}]+cannotSpreadWithinItself :: [Ref] -> ValidationError+cannotSpreadWithinItself fragments = ValidationError text (fmap refPosition fragments)   where     text =       "Cannot spread fragment "         <> msg (refName $ head fragments)         <> " within itself via "-        <> msgSepBy ", " (map refName fragments)+        <> msgSepBy ", " (fmap refName fragments)         <> "."  -- 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] -> GQLErrors+cannotBeSpreadOnType :: Maybe FieldName -> TypeName -> Position -> [TypeName] -> ValidationError cannotBeSpreadOnType key fragmentType position typeMembers =-  errorMessage-    position+  validationErrorMessage+    (Just position)     text   where     text =
src/Data/Morpheus/Error/Input.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Error.Input   ( typeViolation,@@ -6,19 +7,19 @@ where  import Data.Morpheus.Types.Internal.AST-  ( Message,-    ResolvedValue,-    TypeRef (..),-    msg,+  ( TypeRef (..),+    ValidationError,+    Value,+    msgValidation,   ) import Data.Semigroup ((<>)) -typeViolation :: TypeRef -> ResolvedValue -> Message+typeViolation :: TypeRef -> Value s -> ValidationError typeViolation expected found =   "Expected type "-    <> msg expected+    <> msgValidation expected     <> " found "-    <> msg found+    <> msgValidation found     <> "."  {-
− src/Data/Morpheus/Error/Internal.hs
@@ -1,37 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}--module Data.Morpheus.Error.Internal-  ( internalTypeMismatch,-    internalError,-    internalResolvingError,-  )-where---- MORPHEUS-import Data.Morpheus.Error.Utils (globalErrorMessage)-import Data.Morpheus.Types.Internal.AST.Base-  ( GQLErrors,-    Message,-    msg,-  )-import Data.Morpheus.Types.Internal.AST.Value-  ( ValidValue,-  )-import Data.Morpheus.Types.Internal.Resolving.Core-  ( Eventless,-    Failure (..),-  )-import Data.Semigroup ((<>))---- GQL:: if no mutation defined -> "Schema is not configured for mutations."--- all kind internal error in development-internalError :: Message -> Eventless a-internalError x = failure $ globalErrorMessage $ "INTERNAL ERROR: " <> x--internalResolvingError :: Message -> GQLErrors-internalResolvingError = globalErrorMessage . ("INTERNAL ERROR:" <>)---- if value is already validated but value has different type-internalTypeMismatch :: Message -> ValidValue -> Eventless a-internalTypeMismatch text jsType =-  internalError $ "Type mismatch " <> text <> msg jsType
src/Data/Morpheus/Error/NameCollision.hs view
@@ -1,12 +1,13 @@+{-# LANGUAGE NoImplicitPrelude #-}+ module Data.Morpheus.Error.NameCollision   ( NameCollision (..),   ) where -import Data.Morpheus.Internal.Utils (KeyOf (..)) import Data.Morpheus.Types.Internal.AST.Base-  ( GQLError (..),+  ( ValidationError,   )  class NameCollision a where-  nameCollision :: KEY a -> a -> GQLError+  nameCollision :: a -> ValidationError
src/Data/Morpheus/Error/Operation.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Error.Operation   ( mutationIsNotDefined,@@ -6,16 +7,19 @@   ) where -import Data.Morpheus.Error.Utils (errorMessage) import Data.Morpheus.Types.Internal.AST.Base-  ( GQLErrors,-    Position,+  ( Position,+    ValidationError (..),   ) -mutationIsNotDefined :: Position -> GQLErrors+mutationIsNotDefined :: Position -> ValidationError mutationIsNotDefined position =-  errorMessage position "Schema is not configured for mutations."+  ValidationError+    "Schema is not configured for mutations."+    [position] -subscriptionIsNotDefined :: Position -> GQLErrors+subscriptionIsNotDefined :: Position -> ValidationError subscriptionIsNotDefined position =-  errorMessage position "Schema is not configured for subscriptions."+  ValidationError+    "Schema is not configured for subscriptions."+    [position]
src/Data/Morpheus/Error/Schema.hs view
@@ -1,27 +1,25 @@ {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Error.Schema   ( nameCollisionError,-    schemaValidationError,   ) where -import Data.Morpheus.Error.Utils (globalErrorMessage) import Data.Morpheus.Types.Internal.AST.Base-  ( GQLErrors,-    Message,-    TypeName,-    msg,+  ( TypeName,+    ValidationError,+    msgValidation,   ) import Data.Semigroup ((<>))+import Prelude (($)) -schemaValidationError :: Message -> GQLErrors-schemaValidationError error' =-  globalErrorMessage $ "Schema Validation Error, " <> error'+schemaValidationError :: ValidationError -> ValidationError+schemaValidationError error = "Schema Validation Error, " <> error -nameCollisionError :: TypeName -> GQLErrors+nameCollisionError :: TypeName -> ValidationError nameCollisionError typeName =   schemaValidationError $     "Name collision: "-      <> msg typeName+      <> msgValidation typeName       <> " is used for different dataTypes in two separate modules"
src/Data/Morpheus/Error/Selection.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Error.Selection   ( unknownSelectionField,@@ -8,20 +9,21 @@   ) where -import Data.Morpheus.Error.Utils (errorMessage)-import Data.Morpheus.Types.Internal.AST.Base+import Data.Morpheus.Types.Internal.AST   ( FieldName,-    GQLErrors,     Position,     Ref (..),+    TypeDefinition (..),     TypeName,+    VALID,+    ValidationError (..),     msg,   ) import Data.Semigroup ((<>))  -- GQL: "Field \"default\" must not have a selection since type \"String!\" has no subfields."-hasNoSubfields :: Ref -> TypeName -> GQLErrors-hasNoSubfields (Ref selectionName position) typeName = errorMessage position text+hasNoSubfields :: Ref -> TypeDefinition s VALID -> ValidationError+hasNoSubfields (Ref selectionName position) TypeDefinition {typeName} = ValidationError text [position]   where     text =       "Field "@@ -30,8 +32,8 @@         <> msg typeName         <> " has no subfields." -unknownSelectionField :: TypeName -> Ref -> GQLErrors-unknownSelectionField typeName Ref {refName, refPosition} = errorMessage refPosition text+unknownSelectionField :: TypeName -> Ref -> ValidationError+unknownSelectionField typeName Ref {refName, refPosition} = ValidationError text [refPosition]   where     text =       "Cannot query field " <> msg refName@@ -40,8 +42,8 @@         <> "."  -- GQL:: Field \"hobby\" of type \"Hobby!\" must have a selection of subfields. Did you mean \"hobby { ... }\"?-subfieldsNotSelected :: FieldName -> TypeName -> Position -> GQLErrors-subfieldsNotSelected fieldName typeName position = errorMessage position text+subfieldsNotSelected :: FieldName -> TypeName -> Position -> ValidationError+subfieldsNotSelected fieldName typeName position = ValidationError text [position]   where     text =       "Field " <> msg fieldName <> " of type "
src/Data/Morpheus/Error/Utils.hs view
@@ -1,10 +1,12 @@ {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Error.Utils   ( errorMessage,     globalErrorMessage,     badRequestError,+    validationErrorMessage,   ) where @@ -12,13 +14,19 @@   ( ByteString,     pack,   )+import Data.Maybe (Maybe, maybeToList) import Data.Morpheus.Types.Internal.AST.Base   ( GQLError (..),     GQLErrors,     Message,     Position (..),+    ValidationError (..),   ) import Data.Semigroup ((<>))+import Prelude ((.), String)++validationErrorMessage :: Maybe Position -> Message -> ValidationError+validationErrorMessage pos message = ValidationError message (maybeToList pos)  errorMessage :: Position -> Message -> GQLErrors errorMessage position message = [GQLError {message, locations = [position]}]
src/Data/Morpheus/Error/Variable.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Error.Variable   ( uninitializedVariable,@@ -7,23 +8,24 @@   ) where -import Data.Morpheus.Error.Utils (errorMessage)+import Data.Morpheus.Error.Utils (validationErrorMessage) import Data.Morpheus.Types.Internal.AST-  ( GQLErrors,-    Ref (..),+  ( Ref (..),     TypeRef,+    ValidationError,     Variable (..),     msg,   ) import Data.Semigroup ((<>))+import Prelude (($), Maybe (..))  -- query M ( $v : String ) { a(p:$v) } -> "Variable \"$v\" of type \"String\" used in position expecting type \"LANGUAGE\"."-incompatibleVariableType :: Ref -> Variable s -> TypeRef -> GQLErrors+incompatibleVariableType :: Ref -> Variable s -> TypeRef -> ValidationError incompatibleVariableType   (Ref variableName argPosition)   Variable {variableType}   argumentType =-    errorMessage argPosition text+    validationErrorMessage (Just argPosition) text     where       text =         "Variable "@@ -34,10 +36,10 @@           <> msg argumentType           <> "." -uninitializedVariable :: Variable s -> GQLErrors+uninitializedVariable :: Variable s -> ValidationError uninitializedVariable Variable {variableName, variableType, variablePosition} =-  errorMessage-    variablePosition+  validationErrorMessage+    (Just variablePosition)     $ "Variable "       <> msg ("$" <> variableName)       <> " of required type "
src/Data/Morpheus/Error/Warning.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Error.Warning   ( renderGQLErrors,@@ -13,6 +14,8 @@ import Data.ByteString.Lazy.Char8 (unpack) import Data.Foldable (traverse_) -- MORPHEUS++import Data.Maybe (Maybe (..), maybe) import Data.Morpheus.Error.Utils (errorMessage) import Data.Morpheus.Types.Internal.AST.Base   ( Description,@@ -25,6 +28,12 @@ import Language.Haskell.TH   ( Q,     reportWarning,+  )+import Prelude+  ( ($),+    (.),+    String,+    pure,   )  renderGQLErrors :: GQLErrors -> String
+ src/Data/Morpheus/Internal/Graph.hs view
@@ -0,0 +1,62 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE NoImplicitPrelude #-}++module Data.Morpheus.Internal.Graph+  ( cycleChecking,+    Node,+    Graph,+    Edges,+  )+where++import Control.Applicative (Applicative, pure)+import Data.Foldable (traverse_)+import Data.List (elem, lookup)+import Data.Maybe (Maybe (..))+-- MORPHEUS+import Data.Morpheus.Types.Internal.AST+  ( Ref (..),+  )+import Data.Semigroup ((<>))+import Prelude+  ( otherwise,+  )++type Node = Ref++type Edges = (Ref, [Ref])++type Graph = [Edges]++cycleChecking ::+  Applicative m =>+  ([Ref] -> m ()) ->+  Graph ->+  m ()+cycleChecking fail graph = traverse_ checkNode graph+  where+    checkNode (node, _) = cycleCheckingWith graph node [node] fail++cycleCheckingWith ::+  Applicative m =>+  Graph ->+  Ref ->+  [Ref] ->+  ([Ref] -> m ()) ->+  m ()+cycleCheckingWith graph parentNode history fail =+  case lookup parentNode graph of+    Just node -> traverse_ checkNode node+    Nothing -> pure ()+  where+    checkNode node+      | node `elem` history =+        fail (node : history)+      | otherwise =+        cycleCheckingWith+          graph+          node+          (history <> [node])+          fail
src/Data/Morpheus/Internal/TH.hs view
@@ -1,78 +1,117 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-}+{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE TemplateHaskellQuotes #-}-{-# LANGUAGE TypeApplications #-}+-- MORPHEUS+{-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Internal.TH-  ( tyConArgs,+  ( _',     apply,-    applyT,-    typeT,-    instanceHeadT,-    instanceProxyFunD,-    instanceFunD,-    instanceHeadMultiT,-    destructRecord,-    typeInstanceDec,-    infoTyVars,+    applyCons,+    applyVars,     decArgs,-    nameLitP,-    nameStringE,-    nameStringL,-    nameConT,-    nameVarE,-    nameVarT,-    nameConType,-    nameConE,-    nameVarP,-    mkTypeName,-    mkFieldName,     declareTypeRef,+    destructRecord,+    funDProxy,+    funDSimple,+    infoTyVars,+    isEnum,+    m',+    m_,+    mkFieldsE,     nameSpaceField,     nameSpaceType,-    m_,-    m',-    isEnum,+    toCon,+    toConE,+    toConT,+    ToName (..),+    toString,+    toVarE,+    toVarT,+    tyConArgs,+    typeInstanceDec,+    v',+    cat',+    _2',+    o',+    e',+    vars,+    decodeObjectE,+    matchWith,   ) where --- MORPHEUS+import Control.Applicative ((<*>), pure)+import Control.Monad.Fail (fail)+import Data.Foldable (foldl, foldr1)+import Data.Functor ((<$>))+import Data.Maybe (Maybe (..)) import Data.Morpheus.Internal.Utils   ( nameSpaceField,     nameSpaceType,   ) import Data.Morpheus.Types.Internal.AST-  ( FieldName,-    TypeKind (..),+  ( FieldDefinition (..),+    FieldName (..),     TypeKind (..),     TypeName (..),     TypeRef (..),     TypeWrapper (..),     convertToHaskellName,     isEnum,+    isNullable,     isOutputObject,     readName,   )-import Data.Morpheus.Types.Internal.Resolving-  ( UnSubResolver,-  )+import Data.Semigroup ((<>)) import Data.Text (unpack) import Language.Haskell.TH--m' :: Type-m' = VarT $ mkTypeName m_+import Prelude+  ( ($),+    (.),+    (==),+    Bool (..),+    id,+    map,+    otherwise,+    show,+    (||),+  )  m_ :: TypeName m_ = "m" -declareTypeRef :: Bool -> TypeRef -> Type-declareTypeRef isSub TypeRef {typeConName, typeWrappers, typeArgs} =+m' :: Type+m' = VarT (mkName "m")++o' :: Type+o' = VarT (mkName "o")++e' :: Type+e' = VarT (mkName "event")++_' :: PatQ+_' = toVar (mkName "_")++_2' :: PatQ+_2' = toVar (mkName "_2")++v' :: ToVar Name a => a+v' = toVar (mkName "v")++cat' :: Type+cat' = VarT (mkName "cat")++declareTypeRef :: TypeRef -> Type+declareTypeRef TypeRef {typeConName, typeWrappers, typeArgs} =   wrappedT     typeWrappers   where@@ -80,63 +119,133 @@     wrappedT (TypeList : xs) = AppT (ConT ''[]) $ wrappedT xs     wrappedT (TypeMaybe : xs) = AppT (ConT ''Maybe) $ wrappedT xs     wrappedT [] = decType typeArgs-    -------------------------------------------------------    typeName = nameConType typeConName     ---------------------------------------------    decType _-      | isSub =-        AppT typeName (AppT (ConT ''UnSubResolver) m')-    decType (Just par) = AppT typeName (VarT $ mkTypeName par)-    decType _ = typeName+    decType (Just par) = apply typeConName [toVar par]+    decType _ = toCon typeConName  tyConArgs :: TypeKind -> [TypeName] tyConArgs kindD   | isOutputObject kindD || kindD == KindUnion = [m_]   | otherwise = [] -apply :: Name -> [Q Exp] -> Q Exp-apply n = foldl appE (conE n)+cons :: ToCon a b => [a] -> [b]+cons = map toCon -applyT :: Name -> [Q Type] -> Q Type-applyT name = foldl appT (conT name)+vars :: ToVar a b => [a] -> [b]+vars = map toVar -typeT :: Name -> [TypeName] -> Q Type-typeT name li = applyT name (map (varT . mkTypeName) li)+class ToName a where+  toName :: a -> Name -instanceHeadT :: Name -> TypeName -> [TypeName] -> Q Type-instanceHeadT cName iType tArgs = applyT cName [applyT (mkTypeName iType) (map (varT . mkTypeName) tArgs)]+instance ToName Name where+  toName = id -instanceProxyFunD :: (Name, ExpQ) -> DecQ-instanceProxyFunD (name, body) = instanceFunD name ["_"] body+instance ToName TypeName where+  toName = mkName . unpack . readTypeName -instanceFunD :: Name -> [TypeName] -> ExpQ -> Q Dec-instanceFunD name args body = funD name [clause (map (varP . mkTypeName) args) (normalB body) []]+instance ToName FieldName where+  toName = mkName . unpack . readName . convertToHaskellName -instanceHeadMultiT :: Name -> Q Type -> [Q Type] -> Q Type-instanceHeadMultiT className iType li = applyT className (iType : li)+class ToString a b where+  toString :: a -> b --- "User" -> ["name","id"] -> (User name id)-destructRecord :: TypeName -> [FieldName] -> PatQ-destructRecord conName fields = conP (mkTypeName conName) (map (varP . mkFieldName) fields)+instance ToString a b => ToString a (Q b) where+  toString = pure . toString -typeInstanceDec :: Name -> Type -> Type -> Dec+instance ToString TypeName Lit where+  toString = stringL . unpack . readTypeName -nameLitP :: TypeName -> PatQ-nameLitP = litP . nameStringL+instance ToString TypeName Pat where+  toString = LitP . toString -nameStringL :: TypeName -> Lit-nameStringL = stringL . unpack . readTypeName+instance ToString FieldName Lit where+  toString (FieldName x) = stringL (unpack x) -nameStringE :: TypeName -> ExpQ-nameStringE = stringE . (unpack . readTypeName)+instance ToString TypeName Exp where+  toString = LitE . toString -#if MIN_VERSION_template_haskell(2,15,0)--- fix breaking changes-typeInstanceDec typeFamily arg res = TySynInstD (TySynEqn Nothing (AppT (ConT typeFamily) arg) res)-#else+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)++funDProxy :: [(Name, ExpQ)] -> [DecQ]+funDProxy = map fun+  where+    fun (name, body) = funDSimple name [_'] body++funDSimple :: Name -> [PatQ] -> ExpQ -> DecQ+funDSimple name args body = funD name [clause args (normalB body) []]++-- |+-- input:+-- >>>+-- destructRecord "User" ["name","id"]+-- >>> ---typeInstanceDec typeFamily arg res = TySynInstD typeFamily (TySynEqn [arg] res)-#endif+-- expression:+-- >>>+-- (User name id)+-- >>>+destructRecord :: TypeName -> [FieldDefinition cat s] -> PatQ+destructRecord conName fields = conP (toName conName) (vars names)+  where+    names = map fieldName fields  infoTyVars :: Info -> [TyVarBndr] infoTyVars (TyConI x) = decArgs x@@ -148,26 +257,92 @@ decArgs (TySynD _ args _) = args decArgs _ = [] -mkTypeName :: TypeName -> Name-mkTypeName = mkName . unpack . readTypeName+toConT :: ToName a => a -> Q Type+toConT = conT . toName -mkFieldName :: FieldName -> Name-mkFieldName = mkName . unpack . readName . convertToHaskellName+toVarT :: ToVar a TypeQ => a -> TypeQ+toVarT = toVar -nameConT :: TypeName -> Q Type-nameConT = conT . mkTypeName+toVarE :: ToVar a Exp => a -> ExpQ+toVarE = toVar -nameConType :: TypeName -> Type-nameConType = ConT . mkTypeName+toConE :: ToCon a Exp => a -> ExpQ+toConE = toCon -nameVarT :: TypeName -> Q Type-nameVarT = varT . mkTypeName+-- | 'mkFieldsE'+--+--  input :+--  >>>+--       mkFieldsE 'mkValue [FieldDefinition { fieldName = \"field1" ,..} ,..]+--  >>>+--+--  expression :+--  >>>+--    [ mkValue \"field1\" field1,+--    ..+--    ]+-- >>>+mkFieldsE :: Name -> [FieldDefinition cat s] -> Exp+mkFieldsE name = ListE . map (mkEntryWith name) -nameVarE :: FieldName -> ExpQ-nameVarE = varE . mkFieldName+--  input : mkFieldWith 'mkValue (FieldDefinition { fieldName = "field1", ..})+--  expression: mkValue "field1"  field1+mkEntryWith ::+  Name ->+  FieldDefinition cat s ->+  Exp+mkEntryWith f FieldDefinition {fieldName} =+  AppE+    (AppE (VarE f) (toString fieldName))+    (toVar fieldName) -nameConE :: TypeName -> ExpQ-nameConE = conE . mkTypeName+decodeObjectE :: (Bool -> Name) -> TypeName -> [FieldDefinition cat s] -> ExpQ+decodeObjectE _ conName [] = appE (varE 'pure) (toCon conName)+decodeObjectE funName conName fields =+  uInfixE+    (toCon conName)+    (varE '(<$>))+    (foldr1 withApplicative $ map (defField funName) fields) -nameVarP :: FieldName -> PatQ-nameVarP = varP . mkFieldName+withApplicative :: ExpQ -> ExpQ -> ExpQ+withApplicative x = uInfixE x (varE '(<*>))++matchWith ::+  Bool ->+  (t -> (PatQ, ExpQ)) ->+  [t] ->+  ExpQ+matchWith isClosed f xs = lamCaseE (map buildMatch xs <> fallback)+  where+    fallback+      | isClosed = []+      | otherwise = [elseCaseEXP]+    buildMatch x = match pat (normalB body) []+      where+        (pat, body) = f x++elseCaseEXP :: MatchQ+elseCaseEXP = match v' body []+  where+    body =+      normalB $+        appE+          (toVarE 'fail)+          ( uInfixE+              (appE (varE 'show) v')+              (varE '(<>))+              (stringE " is Not Valid Union Constructor")+          )++defField :: (Bool -> Name) -> FieldDefinition cat s -> ExpQ+defField f field@FieldDefinition {fieldName} = uInfixE v' (varE $ f (isNullable field)) (toString fieldName)++#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
@@ -2,9 +2,7 @@ {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE PolyKinds #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Internal.Utils   ( capital,@@ -27,17 +25,36 @@     mapFst,     mapSnd,     mapTuple,+    UpdateT (..),+    resolveUpdates,+    concatUpdates,+    failUpdates,+    ordTraverse,+    ordTraverse_,+    traverseCollection,+    (<.>),+    SemigroupM (..),   ) where +import Control.Applicative (Applicative (..))+import Control.Monad ((=<<), foldM)+import Control.Monad.Trans.Class (lift)+import Control.Monad.Trans.Reader+  ( ReaderT (..),+  ) import Data.Char   ( toLower,     toUpper,   )+import Data.Foldable (null, traverse_)+import Data.Function ((&)) import Data.HashMap.Lazy (HashMap) import qualified Data.HashMap.Lazy as HM import Data.Hashable (Hashable) import Data.List (find)+import Data.Maybe (isJust, maybe)+import Data.Morpheus.Error.NameCollision (NameCollision (..)) import Data.Morpheus.Types.Internal.AST.Base   ( FieldName,     FieldName (..),@@ -46,22 +63,42 @@     Token,     TypeName (..),     TypeNameRef (..),+    ValidationErrors,+    toGQLError,   )-import Data.Semigroup ((<>))+import Data.Semigroup (Semigroup (..)) import qualified Data.Text as T   ( concat,     pack,     unpack,   )+import Data.Traversable (traverse) import Instances.TH.Lift () import Text.Megaparsec.Internal (ParsecT (..)) import Text.Megaparsec.Stream (Stream)+import Prelude+  ( ($),+    (.),+    Bool (..),+    Either (..),+    Eq (..),+    Functor (..),+    Int,+    Monad,+    Ord,+    String,+    const,+    fst,+    length,+    otherwise,+    snd,+  )  mapText :: (String -> String) -> Token -> Token mapText f = T.pack . f . T.unpack  nameSpaceType :: [FieldName] -> TypeName -> TypeName-nameSpaceType list (TypeName name) = TypeName . T.concat $ map capital (map readName list <> [name])+nameSpaceType list (TypeName name) = TypeName . T.concat $ fmap capital (fmap readName list <> [name])  nameSpaceField :: TypeName -> FieldName -> FieldName nameSpaceField nSpace (FieldName name) = FieldName (nonCapital nSpace <> capital name)@@ -90,61 +127,111 @@   empty = []   singleton x = [x] -instance (Hashable k, KeyOf v, k ~ KEY v) => Collection v (HashMap k v) where+instance KeyOf k v => Collection v (HashMap k v) where   empty = HM.empty   singleton x = HM.singleton (keyOf x) x -class Selectable c a | c -> a where-  selectOr :: d -> (a -> d) -> KEY a -> c -> d+class Selectable k a c | c -> a where+  selectOr :: d -> (a -> d) -> k -> c -> d -instance KeyOf a => Selectable [a] a where+instance KeyOf k a => Selectable k a [a] where   selectOr fb f key lib = maybe fb f (find ((key ==) . keyOf) lib) -instance (KEY a ~ k, Eq k, Hashable k) => Selectable (HashMap k a) a where+instance KeyOf k a => Selectable k a (HashMap k a) where   selectOr fb f key lib = maybe fb f (HM.lookup key lib) -selectBy :: (Failure e m, Selectable c a, Monad m) => e -> KEY a -> c -> m a+selectBy :: (Failure e m, Selectable k a c, Monad m) => e -> k -> c -> m a selectBy err = selectOr (failure err) pure -member :: forall a c. Selectable c a => KEY a -> c -> Bool+member :: Selectable k a c => k -> c -> Bool member = selectOr False toTrue   where     toTrue :: a -> Bool     toTrue _ = True -class Eq (KEY a) => KeyOf a where-  type KEY a :: *-  type KEY a = FieldName-  keyOf :: a -> KEY a+ordTraverse ::+  ( Monad f,+    KeyOf k b,+    Listable a (t a),+    Listable b (t b),+    Failure ValidationErrors f+  ) =>+  (a -> f b) ->+  t a ->+  f (t b)+ordTraverse = traverseCollection -instance KeyOf Ref where+traverseCollection ::+  ( Monad f,+    KeyOf k b,+    Listable a (t a),+    Listable b (t' b),+    Failure ValidationErrors f+  ) =>+  (a -> f b) ->+  t a ->+  f (t' b)+traverseCollection f a = fromElems =<< traverse f (elems a)++ordTraverse_ ::+  ( Monad f,+    Listable a (t a)+  ) =>+  (a -> f b) ->+  t a ->+  f ()+ordTraverse_ f a = traverse_ f (elems a)++class (Eq k, Hashable k) => KeyOf k a | a -> k where+  keyOf :: a -> k++instance (Eq k, Hashable k) => KeyOf k (k, a) where+  keyOf = fst++instance KeyOf FieldName Ref where   keyOf = refName -instance KeyOf TypeNameRef where-  type KEY TypeNameRef = TypeName+instance KeyOf TypeName TypeNameRef where   keyOf = typeNameRef -toPair :: KeyOf a => a -> (KEY a, a)+toPair :: KeyOf k a => a -> (k, a) toPair x = (keyOf x, x)  -- list Like Collections class Listable a coll | coll -> a where   elems :: coll -> [a]-  fromElems :: (KeyOf a, Monad m, Failure GQLErrors m) => [a] -> m coll+  fromElems :: (Monad m, Failure ValidationErrors m) => [a] -> m coll -keys :: (KeyOf a, Listable a coll) => coll -> [KEY a]-keys = map keyOf . elems+instance (NameCollision a, KeyOf k a) => Listable a (HashMap k a) where+  fromElems = safeFromList+  elems = HM.elems +keys :: (KeyOf k a, Listable a coll) => coll -> [k]+keys = fmap keyOf . elems+ size :: Listable a coll => coll -> Int size = length . elems  -- Merge Object with of Failure as an Option class Merge a where-  merge :: (Monad m, Failure GQLErrors m) => [Ref] -> a -> a -> m a+  merge :: (Monad m, Failure ValidationErrors m) => [Ref] -> a -> a -> m a -(<:>) :: (Monad m, Merge a, Failure GQLErrors m) => a -> a -> m a+instance (NameCollision a, KeyOf k a) => Merge (HashMap k a) where+  merge _ = safeJoin++(<:>) :: (Monad m, Merge a, Failure ValidationErrors m) => a -> a -> m a (<:>) = merge [] +class SemigroupM m a where+  mergeM :: [Ref] -> a -> a -> m a++(<.>) ::+  (SemigroupM m a) =>+  a ->+  a ->+  m a+(<.>) = mergeM []+ -- Failure: for custome Morpheus GrapHQL errors class Applicative f => Failure error (f :: * -> *) where   failure :: error -> f v@@ -152,9 +239,12 @@ instance Failure error (Either error) where   failure = Left -instance (Stream s, Ord e, Failure [a] m) => Failure [a] (ParsecT e s m) where-  failure x = ParsecT $ \_ _ _ _ _ -> failure x+instance (Monad m, Failure errors m) => Failure errors (ReaderT ctx m) where+  failure = lift . failure +instance (Stream s, Ord e, Failure GQLErrors m) => Failure ValidationErrors (ParsecT e s m) where+  failure x = ParsecT $ \_ _ _ _ _ -> failure (fmap toGQLError x)+ mapFst :: (a -> a') -> (a, b) -> (a', b) mapFst f (a, b) = (f a, b) @@ -163,3 +253,53 @@  mapTuple :: (a -> a') -> (b -> b') -> (a, b) -> (a', b') mapTuple f1 f2 (a, b) = (f1 a, f2 b)++-- Helper Functions+newtype UpdateT m a = UpdateT {updateTState :: a -> m a}++failUpdates :: (Failure e m) => e -> UpdateT m a+failUpdates = UpdateT . const . failure++concatUpdates :: Monad m => [UpdateT m a] -> UpdateT m a+concatUpdates x = UpdateT (`resolveUpdates` x)++resolveUpdates :: Monad m => a -> [UpdateT m a] -> m a+resolveUpdates a = foldM (&) a . fmap updateTState++safeFromList ::+  ( Failure ValidationErrors m,+    Applicative m,+    NameCollision a,+    Eq k,+    Hashable k,+    KeyOf k a+  ) =>+  [a] ->+  m (HashMap k a)+safeFromList values = safeUnionWith HM.empty (fmap toPair values)++safeJoin :: (Failure ValidationErrors m, Eq k, Hashable k, Applicative m, NameCollision a) => HashMap k a -> HashMap k a -> m (HashMap k a)+safeJoin hm newls = safeUnionWith hm (HM.toList newls)++safeUnionWith ::+  ( Failure ValidationErrors m,+    Applicative m,+    Eq k,+    Hashable k,+    NameCollision a+  ) =>+  HashMap k a ->+  [(k, a)] ->+  m (HashMap k a)+safeUnionWith hm names = case insertNoDups (hm, []) names of+  (res, dupps)+    | null dupps -> pure res+    | otherwise -> failure $ fmap (nameCollision . snd) dupps++type NoDupHashMap k a = (HashMap k a, [(k, a)])++insertNoDups :: (Eq k, Hashable k) => NoDupHashMap k a -> [(k, a)] -> NoDupHashMap k a+insertNoDups collected [] = collected+insertNoDups (coll, errors) (pair@(name, value) : xs)+  | isJust (name `HM.lookup` coll) = insertNoDups (coll, errors <> [pair]) xs+  | otherwise = insertNoDups (HM.insert name value coll, errors) xs
src/Data/Morpheus/Parser.hs view
@@ -7,28 +7,32 @@ where  import Control.Monad ((>=>))-import Data.Morpheus.Internal.Utils-  ( fromElems,+import qualified Data.Morpheus.Parsing.Document.TypeSystem as P+  ( parseSchema,+    parseTypeDefinitions,   )-import Data.Morpheus.Parsing.Document.TypeSystem (parseSchema) import Data.Morpheus.Parsing.Request.Parser (parseGQL) import Data.Morpheus.Types.IO   ( GQLRequest (..),   ) import Data.Morpheus.Types.Internal.AST   ( ANY,+    CONST,     GQLQuery (..),     Operation,     Schema (..),     TypeDefinition (..),     VALID,+  )+import Data.Morpheus.Types.Internal.Config+  ( Config (..),     VALIDATION_MODE (..),   ) import Data.Morpheus.Types.Internal.Resolving   ( Eventless,   ) import Data.Morpheus.Validation.Document.Validation-  ( validatePartialDocument,+  ( validateSchema,   ) import Data.Morpheus.Validation.Query.Validation   ( validateRequest,@@ -36,17 +40,22 @@ import Data.Text (Text)  parseTypeSystemDefinition ::-  Text -> Eventless Schema+  Text -> Eventless (Schema VALID) parseTypeSystemDefinition =-  parseSchema >=> fromElems+  P.parseSchema+    >=> validateSchema+      True+      Config+        { debug = False,+          validationMode = FULL_VALIDATION+        }  parseTypeDefinitions ::-  Text -> Eventless [TypeDefinition ANY]-parseTypeDefinitions =-  parseSchema >=> validatePartialDocument+  Text -> Eventless [TypeDefinition ANY CONST]+parseTypeDefinitions = P.parseTypeDefinitions  parseRequest :: GQLRequest -> Eventless GQLQuery parseRequest = parseGQL -parseRequestWith :: Schema -> GQLRequest -> Eventless (Operation VALID)-parseRequestWith schema = parseRequest >=> validateRequest schema FULL_VALIDATION+parseRequestWith :: Config -> Schema VALID -> GQLRequest -> Eventless (Operation VALID)+parseRequestWith config schema = parseRequest >=> validateRequest config schema
src/Data/Morpheus/Parsing/Document/TypeSystem.hs view
@@ -1,50 +1,77 @@+{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Parsing.Document.TypeSystem   ( parseSchema,+    parseTypeDefinitions,   ) where  -- MORPHEUS++import Control.Applicative ((*>), pure)+import Control.Monad ((>=>))+import Data.Foldable (foldr)+import Data.Functor ((<$>), fmap)+import Data.Maybe (Maybe (..))+import Data.Morpheus.Error.NameCollision (NameCollision (..)) import Data.Morpheus.Parsing.Internal.Internal   ( Parser,     processParser,   ) import Data.Morpheus.Parsing.Internal.Pattern-  ( enumValueDefinition,+  ( argumentsDefinition,+    enumValueDefinition,     fieldsDefinition,     inputFieldsDefinition,     optionalDirectives,+    parseDirectiveLocation,+    parseOperationType,     typeDeclaration,   ) import Data.Morpheus.Parsing.Internal.Terms   ( collection,+    ignoredTokens,     keyword,-    operator,     optDescription,+    optionalCollection,+    parseName,     parseTypeName,-    pipeLiteral,+    pipe,     sepByAnd,-    spaceAndComments,+    setOf,+    symbol,   )+import Data.Morpheus.Parsing.Internal.Value+  ( Parse (..),+  ) import Data.Morpheus.Types.Internal.AST   ( ANY,+    CONST,     DataFingerprint (..),     Description,+    DirectiveDefinition (..),     IN,     OUT,+    RawTypeDefinition (..),+    RootOperationTypeDefinition (..),     ScalarDefinition (..),+    Schema,+    SchemaDefinition (..),     TypeContent (..),     TypeDefinition (..),     TypeName,-    UnionMember (..),+    Value,+    buildSchema,     mkUnionMember,     toAny,   ) import Data.Morpheus.Types.Internal.Resolving   ( Eventless,+    failure,   ) import Data.Text (Text) import Text.Megaparsec@@ -52,15 +79,22 @@     eof,     label,     manyTill,-    sepBy1,+    optional,   )+import Prelude+  ( ($),+    (.),+  )  -- Scalars : https://graphql.github.io/graphql-spec/June2018/#sec-Scalars -- --  ScalarTypeDefinition: --    Description(opt) scalar Name Directives(Const)(opt) ---scalarTypeDefinition :: Maybe Description -> Parser (TypeDefinition ANY)+scalarTypeDefinition ::+  Parse (Value s) =>+  Maybe Description ->+  Parser (TypeDefinition ANY s) scalarTypeDefinition typeDescription = label "ScalarTypeDefinition" $ do   typeName <- typeDeclaration "scalar"   typeDirectives <- optionalDirectives@@ -86,7 +120,10 @@ --  FieldDefinition --    Description(opt) Name ArgumentsDefinition(opt) : Type Directives(Const)(opt) ---objectTypeDefinition :: Maybe Description -> Parser (TypeDefinition OUT)+objectTypeDefinition ::+  Parse (Value s) =>+  Maybe Description ->+  Parser (TypeDefinition OUT s) objectTypeDefinition typeDescription = label "ObjectTypeDefinition" $ do   typeName <- typeDeclaration "type"   objectImplements <- optionalImplementsInterfaces@@ -111,7 +148,10 @@ --  InterfaceTypeDefinition --    Description(opt) interface Name Directives(Const)(opt) FieldsDefinition(opt) ---interfaceTypeDefinition :: Maybe Description -> Parser (TypeDefinition OUT)+interfaceTypeDefinition ::+  Parse (Value s) =>+  Maybe Description ->+  Parser (TypeDefinition OUT s) interfaceTypeDefinition typeDescription = label "InterfaceTypeDefinition" $ do   typeName <- typeDeclaration "interface"   typeDirectives <- optionalDirectives@@ -131,7 +171,10 @@ --    = |(opt) NamedType --      UnionMemberTypes | NamedType ---unionTypeDefinition :: Maybe Description -> Parser (TypeDefinition OUT)+unionTypeDefinition ::+  Parse (Value s) =>+  Maybe Description ->+  Parser (TypeDefinition OUT s) unionTypeDefinition typeDescription = label "UnionTypeDefinition" $ do   typeName <- typeDeclaration "union"   typeDirectives <- optionalDirectives@@ -142,7 +185,9 @@         ..       }   where-    unionMemberTypes = operator '=' *> (mkUnionMember <$> parseTypeName) `sepBy1` pipeLiteral+    unionMemberTypes =+      symbol '='+        *> pipe (mkUnionMember <$> parseTypeName)  -- Enums : https://graphql.github.io/graphql-spec/June2018/#sec-Enums --@@ -155,7 +200,10 @@ --  EnumValueDefinition --    Description(opt) EnumValue Directives(Const)(opt) ---enumTypeDefinition :: Maybe Description -> Parser (TypeDefinition ANY)+enumTypeDefinition ::+  Parse (Value s) =>+  Maybe Description ->+  Parser (TypeDefinition ANY s) enumTypeDefinition typeDescription = label "EnumTypeDefinition" $ do   typeName <- typeDeclaration "enum"   typeDirectives <- optionalDirectives@@ -174,7 +222,10 @@ --   InputFieldsDefinition: --     { InputValueDefinition(list) } ---inputObjectTypeDefinition :: Maybe Description -> Parser (TypeDefinition IN)+inputObjectTypeDefinition ::+  Parse (Value s) =>+  Maybe Description ->+  Parser (TypeDefinition IN s) inputObjectTypeDefinition typeDescription =   label "InputObjectTypeDefinition" $ do     typeName <- typeDeclaration "input"@@ -187,20 +238,145 @@           ..         } -parseDataType :: Parser (TypeDefinition ANY)-parseDataType = label "TypeDefinition" $ do-  description <- optDescription-  -- scalar | enum |  input | object | union | interface-  (toAny <$> inputObjectTypeDefinition description)-    <|> (toAny <$> unionTypeDefinition description)-    <|> enumTypeDefinition description-    <|> scalarTypeDefinition description-    <|> (toAny <$> objectTypeDefinition description)-    <|> (toAny <$> interfaceTypeDefinition description)+-- 3.13 DirectiveDefinition+--+--  DirectiveDefinition:+--     Description[opt] directive @ Name ArgumentsDefinition[opt] repeatable[opt] on DirectiveLocations+--+--  DirectiveLocations:+--    DirectiveLocations | DirectiveLocation+--    |[opt] DirectiveLocation -parseSchema :: Text -> Eventless [TypeDefinition ANY]-parseSchema = processParser request+parseDirectiveDefinition ::+  Maybe Description ->+  Parser RawTypeDefinition+parseDirectiveDefinition directiveDefinitionDescription = label "DirectiveDefinition" $ do+  keyword "directive"+  symbol '@'+  directiveDefinitionName <- parseName+  directiveDefinitionArgs <- optionalCollection argumentsDefinition+  _ <- optional (keyword "repeatable")+  keyword "on"+  directiveDefinitionLocations <- pipe parseDirectiveLocation+  pure+    $ RawDirectiveDefinition+    $ DirectiveDefinition+      { directiveDefinitionName,+        directiveDefinitionDescription,+        directiveDefinitionLocations,+        directiveDefinitionArgs+      }++-- 3.2 Schema+-- SchemaDefinition:+--    schema Directives[Const,opt]+--      { RootOperationTypeDefinitionlist }+--+--  RootOperationTypeDefinition:+--    OperationType: NamedType++-- data SchemaDefinition = SchemaDefinition+--   { query :: TypeName,+--     mutation :: Maybe TypeName,+--     subscription :: Maybe TypeName+--   }++parseSchemaDefinition :: Maybe Description -> Parser RawTypeDefinition+parseSchemaDefinition _schemaDescription = label "SchemaDefinition" $ do+  keyword "schema"+  schemaDirectives <- optionalDirectives+  unSchemaDefinition <- setOf parseRootOperationTypeDefinition+  pure+    $ RawSchemaDefinition+    $ SchemaDefinition {schemaDirectives, unSchemaDefinition}++parseRootOperationTypeDefinition :: Parser RootOperationTypeDefinition+parseRootOperationTypeDefinition = do+  operationType <- parseOperationType+  symbol ':'+  RootOperationTypeDefinition operationType <$> parseTypeName++parseTypeSystemUnit ::+  Parser RawTypeDefinition+parseTypeSystemUnit =+  label "TypeDefinition" $+    do+      description <- optDescription+      -- scalar | enum |  input | object | union | interface+      types description+        <|> parseSchemaDefinition description+        <|> parseDirectiveDefinition description   where-    request = label "DocumentTypes" $ do-      spaceAndComments-      manyTill parseDataType eof+    types description =+      RawTypeDefinition+        <$> ( (toAny <$> inputObjectTypeDefinition description)+                <|> (toAny <$> unionTypeDefinition description)+                <|> enumTypeDefinition description+                <|> scalarTypeDefinition description+                <|> (toAny <$> objectTypeDefinition description)+                <|> (toAny <$> interfaceTypeDefinition description)+            )++typePartition ::+  [RawTypeDefinition] ->+  ( [SchemaDefinition],+    [TypeDefinition ANY CONST],+    [DirectiveDefinition CONST]+  )+typePartition = foldr split ([], [], [])++split ::+  RawTypeDefinition ->+  ( [SchemaDefinition],+    [TypeDefinition ANY CONST],+    [DirectiveDefinition CONST]+  ) ->+  ( [SchemaDefinition],+    [TypeDefinition ANY CONST],+    [DirectiveDefinition CONST]+  )+split (RawSchemaDefinition schema) (schemas, types, dirs) = (schema : schemas, types, dirs)+split (RawTypeDefinition ty) (schemas, types, dirs) = (schemas, ty : types, dirs)+split (RawDirectiveDefinition dir) (schemas, types, dirs) = (schemas, types, dir : dirs)++--  split (RawDirectiveDefinition d)++withSchemaDefinition ::+  ( [SchemaDefinition],+    [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)++parseTypeSystemDefinition :: Parser [RawTypeDefinition]+parseTypeSystemDefinition = label "TypeSystemDefinitions" $ do+  ignoredTokens+  manyTill parseTypeSystemUnit eof++typeSystemDefinition ::+  Text ->+  Eventless+    ( Maybe SchemaDefinition,+      [TypeDefinition ANY CONST],+      [DirectiveDefinition CONST]+    )+typeSystemDefinition =+  processParser parseTypeSystemDefinition+    >=> withSchemaDefinition . typePartition++parseTypeDefinitions :: Text -> Eventless [TypeDefinition ANY CONST]+parseTypeDefinitions = fmap snd3 . typeSystemDefinition++snd3 :: (a, b, c) -> b+snd3 (_, x, _) = x++parseSchema ::+  Text ->+  Eventless (Schema CONST)+parseSchema =+  typeSystemDefinition+    >=> buildSchema
src/Data/Morpheus/Parsing/Internal/Pattern.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-}  module Data.Morpheus.Parsing.Internal.Pattern@@ -8,9 +9,13 @@     optionalDirectives,     enumValueDefinition,     inputFieldsDefinition,+    parseOperationType,+    argumentsDefinition,+    parseDirectiveLocation,   ) where +import Data.Functor (($>)) -- MORPHEUS import Data.Morpheus.Parsing.Internal.Arguments   ( maybeArguments,@@ -20,14 +25,14 @@     getLocation,   ) import Data.Morpheus.Parsing.Internal.Terms-  ( keyword,-    litAssignment,-    operator,+  ( ignoredTokens,+    keyword,     optDescription,     parseName,     parseType,     parseTypeName,     setOf,+    symbol,     uniqTuple,   ) import Data.Morpheus.Parsing.Internal.Value@@ -38,6 +43,7 @@   ( ArgumentsDefinition (..),     DataEnumValue (..),     Directive (..),+    DirectiveLocation (..),     FieldContent (..),     FieldDefinition (..),     FieldName,@@ -45,21 +51,28 @@     IN,     InputFieldsDefinition,     OUT,+    OperationType (..),     TypeName,     Value,   )+import Data.Text (pack) import Text.Megaparsec-  ( label,+  ( (<|>),+    choice,+    label,     many,     optional,   )+import Text.Megaparsec.Char (string)  --  EnumValueDefinition: https://graphql.github.io/graphql-spec/June2018/#EnumValueDefinition -- --  EnumValueDefinition --    Description(opt) EnumValue Directives(Const)(opt) ---enumValueDefinition :: Parser DataEnumValue+enumValueDefinition ::+  Parse (Value s) =>+  Parser (DataEnumValue s) enumValueDefinition = label "EnumValueDefinition" $ do   enumDescription <- optDescription   enumName <- parseTypeName@@ -71,11 +84,13 @@ -- InputValueDefinition --   Description(opt) Name : Type DefaultValue(opt) Directives (Const)(opt) ---inputValueDefinition :: Parser (FieldDefinition IN)+inputValueDefinition ::+  Parse (Value s) =>+  Parser (FieldDefinition IN s) inputValueDefinition = label "InputValueDefinition" $ do   fieldDescription <- optDescription   fieldName <- parseName-  litAssignment -- ':'+  symbol ':'   fieldType <- parseType   fieldContent <- optional (DefaultInputValue <$> parseDefaultValue)   fieldDirectives <- optionalDirectives@@ -86,7 +101,9 @@ -- ArgumentsDefinition: --   ( InputValueDefinition(list) ) ---argumentsDefinition :: Parser ArgumentsDefinition+argumentsDefinition ::+  Parse (Value s) =>+  Parser (ArgumentsDefinition s) argumentsDefinition =   label "ArgumentsDefinition" $     uniqTuple inputValueDefinition@@ -96,18 +113,20 @@ --  FieldsDefinition : --    { FieldDefinition(list) } ---fieldsDefinition :: Parser (FieldsDefinition OUT)+fieldsDefinition ::+  Parse (Value s) =>+  Parser (FieldsDefinition OUT s) fieldsDefinition = label "FieldsDefinition" $ setOf fieldDefinition  --  FieldDefinition --    Description(opt) Name ArgumentsDefinition(opt) : Type Directives(Const)(opt) ---fieldDefinition :: Parser (FieldDefinition OUT)+fieldDefinition :: Parse (Value s) => Parser (FieldDefinition OUT s) fieldDefinition = label "FieldDefinition" $ do   fieldDescription <- optDescription   fieldName <- parseName   fieldContent <- optional (FieldArgs <$> argumentsDefinition)-  litAssignment -- ':'+  symbol ':'   fieldType <- parseType   fieldDirectives <- optionalDirectives   pure FieldDefinition {..}@@ -116,7 +135,9 @@ --   InputFieldsDefinition: --     { InputValueDefinition(list) } ---inputFieldsDefinition :: Parser InputFieldsDefinition+inputFieldsDefinition ::+  Parse (Value s) =>+  Parser (InputFieldsDefinition s) inputFieldsDefinition = label "InputFieldsDefinition" $ setOf inputValueDefinition  -- Directives : https://graphql.github.io/graphql-spec/June2018/#sec-Language.Directives@@ -135,7 +156,7 @@ directive :: Parse (Value s) => Parser (Directive s) directive = label "Directive" $ do   directivePosition <- getLocation-  operator '@'+  symbol '@'   directiveName <- parseName   directiveArgs <- maybeArguments   pure Directive {..}@@ -149,3 +170,43 @@ typeDeclaration kind = do   keyword kind   parseTypeName++parseOperationType :: Parser OperationType+parseOperationType = label "OperationType" $ do+  kind <-+    (string "query" $> Query)+      <|> (string "mutation" $> Mutation)+      <|> (string "subscription" $> Subscription)+  ignoredTokens+  return kind++parseDirectiveLocation :: Parser DirectiveLocation+parseDirectiveLocation =+  label+    "DirectiveLocation"+    ( choice $+        toKeyword+          <$> [ FIELD_DEFINITION,+                FRAGMENT_DEFINITION,+                FRAGMENT_SPREAD,+                INLINE_FRAGMENT,+                ARGUMENT_DEFINITION,+                INTERFACE,+                ENUM_VALUE,+                INPUT_OBJECT,+                INPUT_FIELD_DEFINITION,+                SCHEMA,+                SCALAR,+                OBJECT,+                QUERY,+                MUTATION,+                SUBSCRIPTION,+                UNION,+                ENUM,+                FIELD+              ]+    )+    <* ignoredTokens++toKeyword :: Show a => a -> Parser a+toKeyword x = string (pack $ show x) $> x
src/Data/Morpheus/Parsing/Internal/Terms.hs view
@@ -3,12 +3,10 @@ {-# LANGUAGE TupleSections #-}  module Data.Morpheus.Parsing.Internal.Terms-  ( token,-    qualifier,+  ( name,     variable,-    spaceAndComments,-    spaceAndComments1,-    pipeLiteral,+    ignoredTokens,+    parseString,     -------------     collection,     setOf,@@ -19,19 +17,17 @@     parseNonNull,     parseAssignment,     parseWrappedType,-    litEquals,-    litAssignment,-    parseTuple,     parseAlias,     sepByAnd,     parseName,     parseType,     keyword,-    operator,+    symbol,     optDescription,-    optionalList,+    optionalCollection,     parseNegativeSign,     parseTypeName,+    pipe,   ) where @@ -40,8 +36,10 @@ -- MORPHEUS  import Data.Morpheus.Internal.Utils-  ( KeyOf,+  ( Collection,+    KeyOf,     Listable (..),+    empty,     fromElems,   ) import Data.Morpheus.Parsing.Internal.Internal@@ -67,16 +65,16 @@   ( (<?>),     (<|>),     between,+    choice,     label,     many,     manyTill,     optional,     sepBy,+    sepBy1,     sepEndBy,-    skipMany,     skipManyTill,     try,-    try,   ) import Text.Megaparsec.Char   ( char,@@ -89,57 +87,55 @@     string,   ) --- Name : https://graphql.github.io/graphql-spec/June2018/#sec-Names------ Name :: /[_A-Za-z][_0-9A-Za-z]*/---- parseNegativeSign :: Parser Bool-parseNegativeSign = (char '-' $> True <* spaceAndComments) <|> pure False+parseNegativeSign = (char '-' $> True <* ignoredTokens) <|> pure False  parseName :: Parser FieldName-parseName = FieldName <$> token+parseName = FieldName <$> name  parseTypeName :: Parser TypeName-parseTypeName = TypeName <$> token+parseTypeName = label "TypeName" $ TypeName <$> name  keyword :: FieldName -> Parser ()-keyword (FieldName word) = string word *> space1 *> spaceAndComments+keyword (FieldName word) = string word *> space1 *> ignoredTokens -operator :: Char -> Parser ()-operator x = char x *> spaceAndComments+symbol :: Char -> Parser ()+symbol x = char x *> ignoredTokens  -- LITERALS braces :: Parser [a] -> Parser [a] braces =   between-    (char '{' *> spaceAndComments)-    (char '}' *> spaceAndComments)--pipeLiteral :: Parser ()-pipeLiteral = char '|' *> spaceAndComments--litEquals :: Parser ()-litEquals = char '=' *> spaceAndComments--litAssignment :: Parser ()-litAssignment = char ':' *> spaceAndComments+    (char '{' *> ignoredTokens)+    (char '}' *> ignoredTokens)  -- PRIMITIVE -------------------------------------token :: Parser Token-token = label "token" $ do-  firstChar <- letterChar <|> char '_'-  restToken <- many $ letterChar <|> char '_' <|> digitChar-  spaceAndComments-  return $ pack $ firstChar : restToken -qualifier :: Parser (FieldName, Position)-qualifier = label "qualifier" $ do-  position <- getLocation-  value <- parseName-  return (value, position)+-- 2.1.9 Names+-- https://spec.graphql.org/draft/#Name+-- Name ::+--  NameStart NameContinue[list,opt]+--+name :: Parser Token+name = label "Name" $ do+  start <- nameStart+  continue <- nameContinue+  ignoredTokens+  pure $ pack (start : continue) +-- NameStart::+--   Letter+--   _+nameStart :: Parser Char+nameStart = letterChar <|> char '_'++--  NameContinue::+--   Letter+--   Digit+nameContinue :: Parser String+nameContinue = many (letterChar <|> char '_' <|> digitChar)+ -- Variable : https://graphql.github.io/graphql-spec/June2018/#Variable -- -- Variable :  $Name@@ -149,37 +145,61 @@   refPosition <- getLocation   _ <- char '$'   refName <- parseName-  spaceAndComments+  ignoredTokens   pure $ Ref {refName, refPosition} -spaceAndComments1 :: Parser ()-spaceAndComments1 = space1 *> spaceAndComments- -- Descriptions: https://graphql.github.io/graphql-spec/June2018/#Description -- -- Description: --   StringValue--- TODO: should support """ and "---+parseDescription :: Parser Description+parseDescription = strip <$> parseString+ optDescription :: Parser (Maybe Description) optDescription = optional parseDescription -parseDescription :: Parser Description-parseDescription =-  strip . pack <$> (blockDescription <|> singleLine) <* spaceAndComments+parseString :: Parser Token+parseString = blockString <|> singleLineString++blockString :: Parser Token+blockString = stringWith (string "\"\"\"") (printChar <|> newline)++singleLineString :: Parser Token+singleLineString = stringWith (char '"') escapedChar++stringWith :: Parser quote -> Parser Char -> Parser Token+stringWith quote parser =+  pack+    <$> ( quote+            *> manyTill parser quote+            <* ignoredTokens+        )++escapedChar :: Parser Char+escapedChar = label "EscapedChar" $ printChar >>= handleEscape++handleEscape :: Char -> Parser Char+handleEscape '\\' = choice escape+handleEscape x = pure x++escape :: [Parser Char]+escape = map escapeCh escapeOptions   where-    blockDescription =-      blockQuotes-        *> manyTill (printChar <|> newline) blockQuotes-        <* spaceAndComments-      where-        blockQuotes = string "\"\"\""-    -----------------------------    singleLine =-      stringQuote *> manyTill printChar stringQuote <* spaceAndComments-      where-        stringQuote = char '"'+    escapeCh :: (Char, Char) -> Parser Char+    escapeCh (code, replacement) = char code $> replacement +escapeOptions :: [(Char, Char)]+escapeOptions =+  [ ('b', '\b'),+    ('n', '\n'),+    ('f', '\f'),+    ('r', '\r'),+    ('t', '\t'),+    ('\\', '\\'),+    ('\"', '\"'),+    ('/', '/')+  ]+ -- Ignored Tokens : https://graphql.github.io/graphql-spec/June2018/#sec-Source-Text.Ignored-Tokens --  Ignored: --    UnicodeBOM@@ -187,57 +207,67 @@ --    LineTerminator --    Comment --    Comma--- TODO: implement as in specification-spaceAndComments :: Parser ()-spaceAndComments = ignoredTokens- ignoredTokens :: Parser () ignoredTokens =-  label "IgnoredTokens" $ space *> skipMany inlineComment *> space-  where-    inlineComment = char '#' *> skipManyTill printChar newline *> space+  label "IgnoredTokens" $+    space+      *> many ignored+      *> space +ignored :: Parser ()+ignored =+  label "Ignored" $+    comment+      <|> comma++comment :: Parser ()+comment =+  label "Comment" $+    char '#' *> skipManyTill printChar newline *> space++comma :: Parser ()+comma = label "Comma" $ char ',' *> space+ ------------------------------------------------------------------------ --- COMPLEX sepByAnd :: Parser a -> Parser [a]-sepByAnd entry = entry `sepBy` (optional (char '&') *> spaceAndComments)+sepByAnd entry = entry `sepBy` (optional (symbol '&') *> ignoredTokens) +pipe :: Parser a -> Parser [a]+pipe x = optional (symbol '|') *> (x `sepBy1` symbol '|')+ ----------------------------- collection :: Parser a -> Parser [a]-collection entry = braces (entry `sepEndBy` many (char ',' *> spaceAndComments))+collection entry = braces (entry `sepEndBy` ignoredTokens) -setOf :: (Listable a coll, KeyOf a) => Parser a -> Parser coll+setOf :: (Listable a coll, KeyOf k a) => Parser a -> Parser coll setOf = collection >=> fromElems +optionalCollection :: Collection a c => Parser c -> Parser c+optionalCollection x = x <|> pure empty+ parseNonNull :: Parser [DataTypeWrapper] parseNonNull = do   wrapper <- (char '!' $> [NonNullType]) <|> pure []-  spaceAndComments+  ignoredTokens   return wrapper -optionalList :: Parser [a] -> Parser [a]-optionalList x = x <|> pure []--parseTuple :: Parser a -> Parser [a]-parseTuple parser =+uniqTuple :: (Listable a coll, KeyOf k a) => Parser a -> Parser coll+uniqTuple parser =   label "Tuple" $     between-      (char '(' *> spaceAndComments)-      (char ')' *> spaceAndComments)-      ( parser `sepBy` (many (char ',') *> spaceAndComments) <?> "empty Tuple value!"-      )--uniqTuple :: (Listable a coll, KeyOf a) => Parser a -> Parser coll-uniqTuple = parseTuple >=> fromElems+      (char '(' *> ignoredTokens)+      (char ')' *> ignoredTokens)+      (parser `sepBy` ignoredTokens <?> "empty Tuple value!")+      >>= fromElems -uniqTupleOpt :: (Listable a coll, KeyOf a) => Parser a -> Parser coll-uniqTupleOpt = optionalList . parseTuple >=> fromElems+uniqTupleOpt :: (Listable a coll, Collection a coll, KeyOf k a) => Parser a -> Parser coll+uniqTupleOpt x = uniqTuple x <|> pure empty  parseAssignment :: (Show a, Show b) => Parser a -> Parser b -> Parser (a, b) parseAssignment nameParser valueParser = label "assignment" $ do   name' <- nameParser-  litAssignment+  symbol ':'   value' <- valueParser   pure (name', value') @@ -248,8 +278,7 @@ -- parseTypeCondition :: Parser TypeName parseTypeCondition = do-  _ <- string "on"-  space1+  keyword "on"   parseTypeName  spreadLiteral :: Parser Position@@ -259,30 +288,13 @@   space   return index -parseWrappedType :: Parser ([DataTypeWrapper], TypeName)-parseWrappedType = (unwrapped <|> wrapped) <* spaceAndComments-  where-    unwrapped :: Parser ([DataTypeWrapper], TypeName)-    unwrapped = ([],) <$> parseTypeName <* spaceAndComments-    -----------------------------------------------    wrapped :: Parser ([DataTypeWrapper], TypeName)-    wrapped =-      between-        (char '[' *> spaceAndComments)-        (char ']' *> spaceAndComments)-        ( do-            (wrappers, name) <- unwrapped <|> wrapped-            nonNull' <- parseNonNull-            return ((ListType : nonNull') ++ wrappers, name)-        )- -- Field Alias : https://graphql.github.io/graphql-spec/June2018/#sec-Field-Alias -- Alias --  Name: parseAlias :: Parser (Maybe FieldName) parseAlias = try (optional alias) <|> pure Nothing   where-    alias = label "alias" $ parseName <* char ':' <* spaceAndComments+    alias = label "alias" $ parseName <* char ':' <* ignoredTokens  parseType :: Parser TypeRef parseType = do@@ -294,3 +306,20 @@         typeArgs = Nothing,         typeWrappers = toHSWrappers $ nonNull ++ wrappers       }++parseWrappedType :: Parser ([DataTypeWrapper], TypeName)+parseWrappedType = (unwrapped <|> wrapped) <* ignoredTokens+  where+    unwrapped :: Parser ([DataTypeWrapper], TypeName)+    unwrapped = ([],) <$> parseTypeName <* ignoredTokens+    ----------------------------------------------+    wrapped :: Parser ([DataTypeWrapper], TypeName)+    wrapped =+      between+        (char '[' *> ignoredTokens)+        (char ']' *> ignoredTokens)+        ( do+            (wrappers, tname) <- unwrapped <|> wrapped+            nonNull' <- parseNonNull+            return ((ListType : nonNull') ++ wrappers, tname)+        )
src/Data/Morpheus/Parsing/Internal/Value.hs view
@@ -17,32 +17,29 @@   ( Parser,   ) import Data.Morpheus.Parsing.Internal.Terms-  ( litEquals,+  ( ignoredTokens,     parseAssignment,     parseName,     parseNegativeSign,+    parseString,     parseTypeName,     setOf,-    spaceAndComments,+    symbol,     variable,   ) import Data.Morpheus.Types.Internal.AST-  ( FieldName,+  ( CONST,+    FieldName,     ObjectEntry (..),-    OrderedMap,+    OrdMap,     RAW,-    ResolvedValue,     ScalarValue (..),-    VALID,     Value (..),     decodeScientific,   )-import Data.Text (pack) import Text.Megaparsec   ( (<|>),-    anySingleBut,     between,-    choice,     label,     many,     sepBy,@@ -74,53 +71,38 @@ enumValue :: Parser (Value a) enumValue = do   enum <- Enum <$> parseTypeName-  spaceAndComments+  ignoredTokens   return enum -escaped :: Parser Char-escaped = label "escaped" $ do-  x <- anySingleBut '\"'-  if x == '\\' then choice (zipWith escapeChar codes replacements) else pure x-  where-    replacements = ['\b', '\n', '\f', '\r', '\t', '\\', '\"', '/']-    codes = ['b', 'n', 'f', 'r', 't', '\\', '\"', '/']-    escapeChar code replacement = char code >> return replacement- stringValue :: Parser (Value a)-stringValue =-  label "stringValue" $-    Scalar . String . pack-      <$> between-        (char '"')-        (char '"')-        (many escaped)+stringValue = label "stringValue" $ Scalar . String <$> parseString  listValue :: Parser a -> Parser [a] listValue parser =   label "ListValue" $     between-      (char '[' *> spaceAndComments)-      (char ']' *> spaceAndComments)-      (parser `sepBy` (many (char ',') *> spaceAndComments))+      (char '[' *> ignoredTokens)+      (char ']' *> ignoredTokens)+      (parser `sepBy` (many (char ',') *> ignoredTokens))  objectEntry :: Parser (Value a) -> Parser (ObjectEntry a) objectEntry parser = label "ObjectEntry" $ do   (entryName, entryValue) <- parseAssignment parseName parser   pure ObjectEntry {entryName, entryValue} -objectValue :: Parser (Value a) -> Parser (OrderedMap FieldName (ObjectEntry a))+objectValue :: Parser (Value a) -> Parser (OrdMap FieldName (ObjectEntry a)) objectValue = label "ObjectValue" . setOf . objectEntry  parsePrimitives :: Parser (Value a) parsePrimitives =   valueNull <|> booleanValue <|> valueNumber <|> enumValue <|> stringValue -parseDefaultValue :: Parser ResolvedValue+parseDefaultValue :: Parser (Value s) parseDefaultValue = do-  litEquals+  symbol '='   parseV   where-    parseV :: Parser ResolvedValue+    parseV :: Parser (Value s)     parseV = structValue parseV  class Parse a where@@ -129,7 +111,7 @@ instance Parse (Value RAW) where   parse = (VariableValue <$> variable) <|> structValue parse -instance Parse (Value VALID) where+instance Parse (Value CONST) where   parse = structValue parse  structValue :: Parser (Value a) -> Parser (Value a)@@ -139,4 +121,4 @@         <|> (Object <$> objectValue parser)         <|> (List <$> listValue parser)     )-      <* spaceAndComments+      <* ignoredTokens
− src/Data/Morpheus/Parsing/JSONSchema/Parse.hs
@@ -1,116 +0,0 @@-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeOperators #-}--module Data.Morpheus.Parsing.JSONSchema.Parse-  ( decodeIntrospection,-  )-where--import Data.Aeson-import Data.ByteString.Lazy (ByteString)-import Data.Morpheus.Error.Internal (internalError)-import Data.Morpheus.Internal.Utils-  ( fromElems,-  )-import Data.Morpheus.Parsing.JSONSchema.Types-  ( EnumValue (..),-    Field (..),-    InputValue (..),-    Introspection (..),-    Schema (..),-    Type (..),-  )-import Data.Morpheus.Schema.TypeKind (TypeKind (..))-import Data.Morpheus.Types.IO (JSONResponse (..))-import qualified Data.Morpheus.Types.Internal.AST as AST-  ( Schema,-  )-import Data.Morpheus.Types.Internal.AST-  ( ANY,-    ArgumentsDefinition (..),-    DataTypeWrapper (..),-    FieldDefinition,-    IN,-    OUT,-    TypeContent (..),-    TypeDefinition (..),-    TypeName,-    TypeWrapper,-    createArgument,-    createEnumType,-    createScalarType,-    createType,-    createUnionType,-    mkField,-    mkObjectField,-    msg,-    toAny,-    toHSWrappers,-  )-import Data.Morpheus.Types.Internal.Resolving-  ( Eventless,-  )-import Data.Semigroup ((<>))--decodeIntrospection :: ByteString -> Eventless AST.Schema-decodeIntrospection jsonDoc = case jsonSchema of-  Left errors -> internalError $ msg errors-  Right JSONResponse {responseData = Just Introspection {__schema = Schema {types}}} ->-    traverse parse types >>= fromElems . concat-  Right res -> internalError (msg $ show res)-  where-    jsonSchema :: Either String (JSONResponse Introspection)-    jsonSchema = eitherDecode jsonDoc--class ParseJSONSchema a b where-  parse :: a -> Eventless b--instance ParseJSONSchema Type [TypeDefinition ANY] where-  parse Type {name = Just typeName, kind = SCALAR} =-    pure [createScalarType typeName]-  parse Type {name = Just typeName, kind = ENUM, enumValues = Just enums} =-    pure [createEnumType typeName (map enumName enums)]-  parse Type {name = Just typeName, kind = UNION, possibleTypes = Just unions} =-    case traverse name unions of-      Nothing -> internalError "ERROR: GQL ERROR"-      Just uni -> pure [toAny $ createUnionType typeName uni]-  parse Type {name = Just typeName, kind = INPUT_OBJECT, inputFields = Just iFields} =-    do-      (fields :: [FieldDefinition IN]) <- traverse parse iFields-      fs <- fromElems fields-      pure [createType typeName $ DataInputObject fs]-  parse Type {name = Just typeName, kind = OBJECT, fields = Just oFields} =-    do-      (fields :: [FieldDefinition OUT]) <- traverse parse oFields-      fs <- fromElems fields-      pure [createType typeName $ DataObject [] fs]-  parse _ = pure []--instance ParseJSONSchema Field (FieldDefinition OUT) where-  parse Field {fieldName, fieldArgs, fieldType} = do-    fType <- fieldTypeFromJSON fieldType-    args <- traverse genArg fieldArgs >>= fromElems-    pure $ mkObjectField (ArgumentsDefinition Nothing args) fieldName fType-    where-      genArg InputValue {inputName = argName, inputType = argType} =-        createArgument argName <$> fieldTypeFromJSON argType--instance ParseJSONSchema InputValue (FieldDefinition IN) where-  parse InputValue {inputName, inputType} = mkField inputName <$> fieldTypeFromJSON inputType--fieldTypeFromJSON :: Type -> Eventless ([TypeWrapper], TypeName)-fieldTypeFromJSON = fmap toHs . fieldTypeRec []-  where-    toHs (w, t) = (toHSWrappers w, t)-    fieldTypeRec ::-      [DataTypeWrapper] -> Type -> Eventless ([DataTypeWrapper], TypeName)-    fieldTypeRec acc Type {kind = LIST, ofType = Just ofType} =-      fieldTypeRec (ListType : acc) ofType-    fieldTypeRec acc Type {kind = NON_NULL, ofType = Just ofType} =-      fieldTypeRec (NonNullType : acc) ofType-    fieldTypeRec acc Type {name = Just name} = pure (acc, name)-    fieldTypeRec _ x = internalError $ "Unsuported Field" <> msg (show x)
− src/Data/Morpheus/Parsing/JSONSchema/Types.hs
@@ -1,86 +0,0 @@-{-# LANGUAGE DeriveAnyClass #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeOperators #-}--module Data.Morpheus.Parsing.JSONSchema.Types-  ( Introspection (..),-    Schema (..),-    Type (..),-    Field (..),-    InputValue (..),-    EnumValue (..),-  )-where--import Data.Aeson------ MORPHEUS-import Data.Morpheus.Schema.TypeKind (TypeKind)-import Data.Morpheus.Types.Internal.AST-  ( FieldName,-    TypeName,-  )-import GHC.Generics (Generic)---- TYPES FOR DECODING JSON INTROSPECTION----newtype Introspection = Introspection-  { __schema :: Schema-  }-  deriving (Generic, Show, FromJSON)--newtype Schema = Schema-  { types :: [Type]-  }-  deriving (Generic, Show, FromJSON)---- TYPE-data Type = Type-  { kind :: TypeKind,-    name :: Maybe TypeName,-    fields :: Maybe [Field],-    interfaces :: Maybe [Type],-    possibleTypes :: Maybe [Type],-    enumValues :: Maybe [EnumValue],-    inputFields :: Maybe [InputValue],-    ofType :: Maybe Type-  }-  deriving (Generic, Show, FromJSON)---- FIELD-data Field = Field-  { fieldName :: FieldName,-    fieldArgs :: [InputValue],-    fieldType :: Type-  }-  deriving (Show, Generic)--instance FromJSON Field where-  parseJSON = withObject "Field" objectParser-    where-      objectParser o = Field <$> o .: "name" <*> o .: "args" <*> o .: "type"---- INPUT-data InputValue = InputValue-  { inputName :: FieldName,-    inputType :: Type-  }-  deriving (Show, Generic)--instance FromJSON InputValue where-  parseJSON = withObject "InputValue" objectParser-    where-      objectParser o = InputValue <$> o .: "name" <*> o .: "type"---- ENUM-newtype EnumValue = EnumValue-  { enumName :: TypeName-  }-  deriving (Generic, Show)--instance FromJSON EnumValue where-  parseJSON = withObject "EnumValue" objectParser-    where-      objectParser o = EnumValue <$> o .: "name"
src/Data/Morpheus/Parsing/Request/Operation.hs view
@@ -6,10 +6,6 @@   ) where -import Data.Functor (($>))------ MORPHEUS- import Data.Morpheus.Internal.Utils   ( empty,   )@@ -19,12 +15,12 @@   ) import Data.Morpheus.Parsing.Internal.Pattern   ( optionalDirectives,+    parseOperationType,   ) import Data.Morpheus.Parsing.Internal.Terms-  ( operator,-    parseName,+  ( parseName,     parseType,-    spaceAndComments1,+    symbol,     uniqTupleOpt,     variable,   )@@ -48,7 +44,6 @@     label,     optional,   )-import Text.Megaparsec.Char (string)  -- Variables :  https://graphql.github.io/graphql-spec/June2018/#VariableDefinition --@@ -58,7 +53,7 @@ variableDefinition :: Parser (Variable RAW) variableDefinition = label "VariableDefinition" $ do   (Ref variableName variablePosition) <- variable-  operator ':'+  symbol ':'   variableType <- parseType   variableValue <- DefaultValue <$> optional parseDefaultValue   pure Variable {..}@@ -79,15 +74,6 @@   operationDirectives <- optionalDirectives   operationSelection <- parseSelectionSet   pure Operation {..}--parseOperationType :: Parser OperationType-parseOperationType = label "OperationType" $ do-  kind <--    (string "query" $> Query)-      <|> (string "mutation" $> Mutation)-      <|> (string "subscription" $> Subscription)-  spaceAndComments1-  return kind  parseAnonymousQuery :: Parser (Operation RAW) parseAnonymousQuery = label "AnonymousQuery" $ do
src/Data/Morpheus/Parsing/Request/Parser.hs view
@@ -18,7 +18,7 @@     processParser,   ) import Data.Morpheus.Parsing.Internal.Terms-  ( spaceAndComments,+  ( ignoredTokens,   ) import Data.Morpheus.Parsing.Request.Operation   ( parseOperation,@@ -44,7 +44,7 @@  request :: Parser GQLQuery request = label "GQLQuery" $ do-  spaceAndComments+  ignoredTokens   operation <- parseOperation   fragments <- manyTill parseFragmentDefinition eof >>= fromElems   pure GQLQuery {operation, fragments, inputVariables = []}
src/Data/Morpheus/Parsing/Request/Selection.hs view
@@ -108,7 +108,7 @@ --  FragmentDefinition: --   fragment FragmentName TypeCondition Directives(opt) SelectionSet ---parseFragmentDefinition :: Parser Fragment+parseFragmentDefinition :: Parser (Fragment RAW) parseFragmentDefinition = label "FragmentDefinition" $ do   keyword "fragment"   fragmentPosition <- getLocation@@ -125,7 +125,7 @@   fragmentPosition <- spreadLiteral   InlineFragment <$> fragmentBody "INLINE_FRAGMENT" fragmentPosition -fragmentBody :: FieldName -> Position -> Parser Fragment+fragmentBody :: FieldName -> Position -> Parser (Fragment RAW) fragmentBody fragmentName fragmentPosition = label "FragmentBody" $ do   fragmentType <- parseTypeCondition   fragmentDirectives <- optionalDirectives
src/Data/Morpheus/QuasiQuoter.hs view
@@ -19,7 +19,7 @@   ) import Data.Morpheus.Parser   ( parseRequest,-    parseTypeDefinitions,+    parseTypeSystemDefinition,   ) import Data.Morpheus.Types.IO (GQLRequest (..)) import Data.Morpheus.Types.Internal.Resolving@@ -72,7 +72,7 @@       error $ things ++ " are not supported by the GraphQL QuasiQuoter"  dslExpression :: Text -> Q Exp-dslExpression doc = case parseTypeDefinitions doc of+dslExpression doc = case parseTypeSystemDefinition doc of   Failure errors -> fail (renderGQLErrors errors)   Success {result, warnings} ->     gqlWarnings warnings >> [|result|]
src/Data/Morpheus/Rendering/RenderGQL.hs view
@@ -1,26 +1,51 @@ {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Rendering.RenderGQL   ( RenderGQL (..),     renderObject,-    renderIndent,+    renderMembers,+    newline,+    renderArguments,+    renderEntry,+    space,+    Rendering,   ) where  -- MORPHEUS++import Data.Foldable (null)+import Data.Functor ((<$>))+import Data.Maybe (Maybe, maybe) import Data.Semigroup ((<>)) import Data.Text   ( Text,     intercalate,     pack,   )+import Prelude+  ( (.),+    Bool (..),+    Float,+    Int,+    fmap,+    otherwise,+    show,+  )  type Rendering = Text  class RenderGQL a where   render :: a -> Rendering +instance+  RenderGQL a =>+  RenderGQL (Maybe a)+  where+  render = maybe "" render+ instance RenderGQL Int where   render = pack . show @@ -34,9 +59,35 @@   render True = "true"   render False = "false" -renderIndent :: Rendering-renderIndent = "  "+indent :: Rendering+indent = "  " -renderObject :: (a -> Rendering) -> [a] -> Rendering-renderObject f list =-  " { \n  " <> intercalate ("\n" <> renderIndent) (map f list) <> "\n}"+space :: Rendering+space = " "++newline :: Rendering+newline = "\n"++indentNewline :: Rendering+indentNewline = newline <> indent++renderAtNewLine :: (RenderGQL a) => [a] -> Rendering+renderAtNewLine elems = indentNewline <> intercalate indentNewline (fmap render elems)++renderObject :: (RenderGQL a) => [a] -> Rendering+renderObject fields = " {" <> renderAtNewLine fields <> "\n}"++renderMembers :: (RenderGQL a) => [a] -> Rendering+renderMembers members = intercalate (space <> "|" <> space) (fmap render members)++renderArguments :: (RenderGQL a) => [a] -> Rendering+renderArguments arguments+  | null arguments = ""+  | otherwise = "(" <> intercalate ", " (render <$> arguments) <> ")"++renderEntry ::+  (RenderGQL name, RenderGQL value) =>+  name ->+  value ->+  Rendering+renderEntry name value = render name <> ": " <> render value
src/Data/Morpheus/Rendering/RenderIntrospection.hs view
@@ -2,13 +2,11 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-}-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE TupleSections #-}-{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Rendering.RenderIntrospection   ( render,@@ -16,20 +14,21 @@   ) where -import Data.Maybe (isJust) -- Morpheus +import Control.Applicative (pure)+import Control.Monad (Monad (..))+import Data.Foldable (foldr)+import Data.Functor ((<$>))+import Data.List (filter)+import Data.Maybe (Maybe (..), isJust, maybe) import Data.Morpheus.Internal.Utils   ( Failure,     elems,     failure,-    fromElems,     selectBy,-    selectOr,   ) import qualified Data.Morpheus.Rendering.RenderGQL as GQL (RenderGQL (..))-import Data.Morpheus.Schema.TypeKind (TypeKind (..))-import qualified Data.Morpheus.Types.Internal.AST as AST (TypeKind (..)) import Data.Morpheus.Types.Internal.AST   ( ANY,     ArgumentsDefinition (..),@@ -47,31 +46,30 @@     IN,     Message,     OUT,-    Object,-    ObjectEntry (..),     QUERY,-    RESOLVED,     Schema,     TRUE,     TypeContent (..),     TypeDefinition (..),+    TypeKind (..),     TypeName (..),     TypeRef (..),     UnionMember (..),     VALID,     Value (..),-    createInputUnionFields,     fieldVisibility,     kindOf,     lookupDeprecated,     lookupDeprecatedReason,+    mkInputUnionFields,     msg,+    possibleInterfaceTypes,     toGQLWrapper,   ) import Data.Morpheus.Types.Internal.Resolving-  ( Context (..),-    ResModel,+  ( ResModel,     Resolver,+    ResolverContext (..),     mkBoolean,     mkList,     mkNull,@@ -81,8 +79,13 @@   ) import Data.Semigroup ((<>)) import Data.Text (pack)--type Result e m a = Resolver QUERY e m a+import Data.Traversable (traverse)+import Prelude+  ( ($),+    (.),+    Bool,+    show,+  )  class   ( Monad m,@@ -91,7 +94,7 @@   ) =>   WithSchema m   where-  getSchema :: m Schema+  getSchema :: m (Schema VALID)  instance Monad m => WithSchema (Resolver QUERY e m) where   getSchema = schema <$> unsafeInternalContext@@ -99,7 +102,7 @@ selectType ::   WithSchema m =>   TypeName ->-  m (TypeDefinition ANY)+  m (TypeDefinition ANY VALID) selectType name =   getSchema     >>= selectBy (" INTERNAL: INTROSPECTION Type not Found: \"" <> msg name <> "\"") name@@ -119,13 +122,20 @@ instance RenderIntrospection Description where   render = pure . mkString -instance RenderIntrospection TypeKind where-  render = pure . mkString . pack . show- instance RenderIntrospection a => RenderIntrospection [a] where   render ls = mkList <$> traverse render ls -instance RenderIntrospection DirectiveDefinition where+instance RenderIntrospection a => RenderIntrospection (Maybe a) where+  render (Just value) = render value+  render Nothing = pure mkNull++instance RenderIntrospection Bool where+  render = pure . mkBoolean++instance RenderIntrospection TypeKind where+  render = pure . mkString . GQL.render++instance RenderIntrospection (DirectiveDefinition VALID) where   render     DirectiveDefinition       { directiveDefinitionName,@@ -145,7 +155,7 @@ instance RenderIntrospection DirectiveLocation where   render locations = pure $ mkString (pack $ show locations) -instance RenderIntrospection (TypeDefinition a) where+instance RenderIntrospection (TypeDefinition cat VALID) where   render     TypeDefinition       { typeName,@@ -153,44 +163,66 @@         typeContent       } = pure $ renderContent typeContent       where-        __type :: Monad m => TypeKind -> [(FieldName, Resolver QUERY e m (ResModel QUERY e m))] -> ResModel QUERY e m+        __type ::+          Monad m =>+          TypeKind ->+          [(FieldName, Resolver QUERY e m (ResModel QUERY e m))] ->+          ResModel QUERY e m         __type kind = mkType kind typeName typeDescription-        renderContent :: Monad m => TypeContent bool a -> ResModel QUERY e m-        renderContent DataScalar {} = __type SCALAR []-        renderContent (DataEnum enums) = __type ENUM [("enumValues", render enums)]+        renderContent ::+          Monad m =>+          TypeContent bool a VALID ->+          ResModel QUERY e m+        renderContent DataScalar {} = __type KindScalar []+        renderContent (DataEnum enums) = __type KindEnum [("enumValues", render enums)]         renderContent (DataInputObject inputFiels) =           __type-            INPUT_OBJECT+            KindInputObject             [("inputFields", render inputFiels)]         renderContent DataObject {objectImplements, objectFields} =           createObjectType typeName typeDescription objectImplements objectFields         renderContent (DataUnion union) =           __type-            UNION+            KindUnion             [("possibleTypes", render union)]         renderContent (DataInputUnion members) =           __type-            INPUT_OBJECT+            KindInputObject             [ ( "inputFields",                 render-                  $ createInputUnionFields typeName-                  $ filter visibility members+                  ( mkInputUnionFields typeName $+                      filter visibility members ::+                      FieldsDefinition IN VALID+                  )               )             ]         renderContent (DataInterface fields) =           __type-            INTERFACE+            KindInterface             [ ("fields", render fields),-              ("possibleTypes", interfacePossibleTypes typeName)+              ("possibleTypes", renderPossibleTypes typeName)             ] -instance RenderIntrospection (UnionMember OUT) where+instance RenderIntrospection (UnionMember OUT s) where   render UnionMember {memberName} = selectType memberName >>= render -instance RenderIntrospection (FieldDefinition cat) => RenderIntrospection (FieldsDefinition cat) where+instance+  RenderIntrospection (FieldDefinition cat s) =>+  RenderIntrospection (FieldsDefinition cat s)+  where   render = render . filter fieldVisibility . elems -instance RenderIntrospection (FieldDefinition OUT) where+instance RenderIntrospection (FieldContent TRUE IN VALID) where+  render = render . defaultInputValue++instance RenderIntrospection (Value VALID) where+  render Null = pure mkNull+  render x = pure $ mkString $ GQL.render x++instance+  RenderIntrospection+    (FieldDefinition OUT VALID)+  where   render FieldDefinition {..} =     pure       $ mkObject "__Field"@@ -201,13 +233,13 @@         ]         <> renderDeprecated fieldDirectives -instance RenderIntrospection (FieldContent TRUE OUT) where+instance RenderIntrospection (FieldContent TRUE OUT VALID) where   render (FieldArgs args) = render args -instance RenderIntrospection ArgumentsDefinition where+instance RenderIntrospection (ArgumentsDefinition VALID) where   render ArgumentsDefinition {arguments} = mkList <$> traverse render (elems arguments) -instance RenderIntrospection (FieldDefinition IN) where+instance RenderIntrospection (FieldDefinition IN VALID) where   render FieldDefinition {..} =     pure $       mkObject@@ -215,10 +247,10 @@         [ renderName fieldName,           description fieldDescription,           type' fieldType,-          defaultValue fieldType (fmap defaultInputValue fieldContent)+          defaultValue fieldContent         ] -instance RenderIntrospection DataEnumValue where+instance RenderIntrospection (DataEnumValue VALID) where   render DataEnumValue {enumName, enumDescription, enumDirectives} =     pure $ mkObject "__Field" $       [ renderName enumName,@@ -228,7 +260,7 @@  instance RenderIntrospection TypeRef where   render TypeRef {typeConName, typeWrappers} = do-    kind <- lookupKind typeConName+    kind <- kindOf <$> selectType typeConName     let currentType = mkType kind typeConName Nothing []     pure $ foldr wrap currentType (toGQLWrapper typeWrappers)     where@@ -239,50 +271,30 @@           [ renderKind (wrapperKind wrapper),             ("ofType", pure contentType)           ]-      wrapperKind ListType = LIST-      wrapperKind NonNullType = NON_NULL+      wrapperKind ListType = KindList+      wrapperKind NonNullType = KindNonNull -interfacePossibleTypes ::+renderPossibleTypes ::   (Monad m) =>   TypeName ->   Resolver QUERY e m (ResModel QUERY e m)-interfacePossibleTypes interfaceName =+renderPossibleTypes name =   mkList     <$> ( getSchema-            >>= sequence-              . concatMap implements-              . elems+            >>= traverse render . possibleInterfaceTypes name         )-  where-    implements typeDef@TypeDefinition {typeContent = DataObject {objectImplements}, ..}-      | interfaceName `elem` objectImplements = [render typeDef]-    implements _ = []  renderDeprecated ::   (Monad m) =>-  Directives VALID ->+  Directives s ->   [(FieldName, Resolver QUERY e m (ResModel QUERY e m))] renderDeprecated dirs =-  [ ("isDeprecated", pure $ mkBoolean (isJust $ lookupDeprecated dirs)),-    ("deprecationReason", opt (pure . mkString) (lookupDeprecated dirs >>= lookupDeprecatedReason))+  [ ("isDeprecated", render (isJust $ lookupDeprecated dirs)),+    ("deprecationReason", render (lookupDeprecated dirs >>= lookupDeprecatedReason))   ]  description :: Monad m => Maybe Description -> (FieldName, Resolver QUERY e m (ResModel QUERY e m))-description desc = ("description", opt render desc)--lookupKind :: (Monad m) => TypeName -> Result e m TypeKind-lookupKind = fmap (renderTypeKind . kindOf) . selectType--renderTypeKind :: AST.TypeKind -> TypeKind-renderTypeKind AST.KindScalar = SCALAR-renderTypeKind (AST.KindObject _) = OBJECT-renderTypeKind AST.KindUnion = UNION-renderTypeKind AST.KindInputUnion = INPUT_OBJECT-renderTypeKind AST.KindEnum = ENUM-renderTypeKind AST.KindInputObject = INPUT_OBJECT-renderTypeKind AST.KindList = LIST-renderTypeKind AST.KindNonNull = NON_NULL-renderTypeKind AST.KindInterface = INTERFACE+description = ("description",) . render  mkType ::   (Monad m, RenderIntrospection name) =>@@ -302,9 +314,14 @@     )  createObjectType ::-  Monad m => TypeName -> Maybe Description -> [TypeName] -> FieldsDefinition OUT -> ResModel QUERY e m+  Monad m =>+  TypeName ->+  Maybe Description ->+  [TypeName] ->+  FieldsDefinition OUT VALID ->+  ResModel QUERY e m createObjectType name desc interfaces fields =-  mkType OBJECT name desc [("fields", render fields), ("interfaces", mkList <$> traverse implementedInterface interfaces)]+  mkType (KindObject Nothing) name desc [("fields", render fields), ("interfaces", mkList <$> traverse implementedInterface interfaces)]  implementedInterface ::   (Monad m) =>@@ -317,10 +334,6 @@     renderContent typeDef@TypeDefinition {typeContent = DataInterface {}} = render typeDef     renderContent _ = failure ("Type " <> msg name <> " must be an Interface" :: Message) -opt :: Monad m => (a -> Resolver QUERY e m (ResModel QUERY e m)) -> Maybe a -> Resolver QUERY e m (ResModel QUERY e m)-opt f (Just x) = f x-opt _ Nothing = pure mkNull- renderName ::   ( RenderIntrospection name,     Monad m@@ -333,70 +346,12 @@ renderKind = ("kind",) . render  type' :: Monad m => TypeRef -> (FieldName, Resolver QUERY e m (ResModel QUERY e m))-type' ref = ("type", render ref)+type' = ("type",) . render  defaultValue ::   Monad m =>-  TypeRef ->-  Maybe (Value RESOLVED) ->+  Maybe (FieldContent TRUE IN VALID) ->   ( FieldName,     Resolver QUERY e m (ResModel QUERY e m)   )-defaultValue-  typeRef-  value =-    ( "defaultValue",-      opt-        ( fmap-            (mkString . GQL.render)-            . fulfill typeRef-            . Just-        )-        value-    )--fulfill ::-  WithSchema m =>-  TypeRef ->-  Maybe (Value RESOLVED) ->-  m (Value RESOLVED)-fulfill TypeRef {typeConName} (Just (Object fields)) =-  selectType typeConName-    >>= \case-      TypeDefinition-        { typeContent =-            DataInputObject {inputObjectFields}-        } ->-          Object-            <$> ( traverse-                    (handleField fields)-                    (elems inputObjectFields)-                    >>= fromElems-                )-      _ -> failure (msg typeConName <> "is not must be Object")-fulfill typeRef (Just (List values)) =-  List <$> traverse (fulfill typeRef . Just) values-fulfill _ (Just v) = pure v-fulfill _ Nothing = pure Null--handleField ::-  WithSchema m =>-  Object RESOLVED ->-  FieldDefinition IN ->-  m (ObjectEntry RESOLVED)-handleField-  fields-  FieldDefinition-    { fieldName,-      fieldType,-      fieldContent = x-    } =-    ObjectEntry fieldName-      <$> fulfill-        fieldType-        ( selectOr-            (fmap defaultInputValue x)-            (Just . entryValue)-            fieldName-            fields-        )+defaultValue = ("defaultValue",) . render
src/Data/Morpheus/Schema/DSL.hs view
@@ -3,6 +3,7 @@ {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE RecordWildCards #-} {-# LANGUAGE TemplateHaskell #-}  module Data.Morpheus.Schema.DSL (dsl) where@@ -11,11 +12,11 @@   ( gqlWarnings,     renderGQLErrors,   )-import Data.Morpheus.Parsing.Document.TypeSystem (parseSchema)-import Data.Morpheus.Types.Internal.AST (ANY, TypeDefinition)+import Data.Morpheus.Parsing.Document.TypeSystem+  ( parseSchema,+  ) import Data.Morpheus.Types.Internal.Resolving-  ( Eventless,-    Result (..),+  ( Result (..),   ) import Data.Text   ( Text,@@ -37,7 +38,6 @@       error $ things ++ " are not supported by the GraphQL QuasiQuoter"  dslExpression :: Text -> Q Exp-dslExpression doc = case (parseSchema doc :: Eventless [TypeDefinition ANY]) of+dslExpression doc = case parseSchema doc of   Failure errors -> fail (renderGQLErrors errors)-  Success {result, warnings} ->-    gqlWarnings warnings >> [|result|]+  Success {result, warnings} -> gqlWarnings warnings >> [|result|]
− src/Data/Morpheus/Schema/Directives.hs
@@ -1,43 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}--module Data.Morpheus.Schema.Directives (defaultDirectives) where--import Data.Morpheus.Internal.Utils-  ( singleton,-  )-import Data.Morpheus.Types.Internal.AST-  ( ArgumentsDefinition (..),-    DirectiveDefinition (..),-    DirectiveLocation (..),-    TypeWrapper (..),-    mkField,-  )--defaultDirectives :: [DirectiveDefinition]-defaultDirectives =-  [ DirectiveDefinition-      { directiveDefinitionName = "skip",-        directiveDefinitionDescription = Just "Directs the executor to skip this field or fragment when the `if` argument is true.",-        directiveDefinitionLocations = [FIELD, FRAGMENT_SPREAD, INLINE_FRAGMENT],-        directiveDefinitionArgs = argumentsIf-      },-    DirectiveDefinition-      { directiveDefinitionName = "include",-        directiveDefinitionDescription = Just "Directs the executor to include this field or fragment only when the `if` argument is true.",-        directiveDefinitionLocations = [FIELD, FRAGMENT_SPREAD, INLINE_FRAGMENT],-        directiveDefinitionArgs = argumentsIf-      },-    DirectiveDefinition-      { directiveDefinitionName = "deprecated",-        directiveDefinitionDescription = Just "Marks an element of a GraphQL schema as no longer supported.",-        directiveDefinitionLocations = [FIELD_DEFINITION, ENUM_VALUE],-        directiveDefinitionArgs =-          singleton $-            mkField-              "reason"-              ([TypeMaybe], "String")-      }-  ]--argumentsIf :: ArgumentsDefinition-argumentsIf = singleton $ mkField "if" ([], "Boolean")
src/Data/Morpheus/Schema/Schema.hs view
@@ -3,80 +3,61 @@ {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-}  module Data.Morpheus.Schema.Schema-  ( withSystemTypes,-    systemTypes,+  ( internalSchema,   ) where  -- MORPHEUS -import Data.Morpheus.Internal.Utils-  ( (<:>),-    singleton,-  ) import Data.Morpheus.Schema.DSL (dsl) import Data.Morpheus.Types.Internal.AST-  ( ANY,-    DataFingerprint (..),-    FieldsDefinition,-    Message,-    OUT,+  ( DataFingerprint (..),     Schema (..),-    TypeContent (..),     TypeDefinition (..),-    TypeUpdater,-    TypeWrapper (..),-    createArgument,-    insertType,     internalFingerprint,-    mkField,-    mkObjectField,-    unsafeFromFields,   )-import Data.Morpheus.Types.Internal.Resolving-  ( failure,-    resolveUpdates,-  ) -withSystemTypes :: TypeUpdater-withSystemTypes s@Schema {query = q@TypeDefinition {typeContent = DataObject inter fields}} =-  ( do-      fs <- fields <:> hiddenFields-      pure $ s {query = q {typeContent = DataObject inter fs}}-  )-    >>= (`resolveUpdates` map (insertType . internalType) systemTypes)-withSystemTypes _ = failure ("Query must be an Object Type" :: Message)--hiddenFields :: FieldsDefinition OUT-hiddenFields =-  unsafeFromFields-    [ mkObjectField-        (singleton (createArgument "name" ([], "String")))-        "__type"-        ([TypeMaybe], "__Type"),-      mkField-        "__schema"-        ([], "__Schema")-    ]+toInternalSchema :: Schema s -> Schema s+toInternalSchema Schema {..} = Schema {types = fmap toInternalType types, ..} -internalType :: TypeDefinition a -> TypeDefinition a-internalType+toInternalType :: TypeDefinition a s -> TypeDefinition a s+toInternalType   tyDef@TypeDefinition     { typeFingerprint = DataFingerprint name xs     } =     tyDef {typeFingerprint = internalFingerprint name xs} -systemTypes :: [TypeDefinition ANY]-systemTypes =-  [dsl|+internalSchema :: Schema s+internalSchema =+  toInternalSchema+    [dsl| -# default scalars+"""+Directs the executor to skip this field or fragment when the `if` argument is true.+"""+directive @skip(if: Boolean!) +  on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT++"""+Directs the executor to include this field or fragment only when the `if` argument is true.+"""+directive @include(if: Boolean!) +  on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT++"""+Marks an element of a GraphQL schema as no longer supported.+"""+directive @deprecated(reason: String) +  on FIELD_DEFINITION | ENUM_VALUE++ scalar Boolean scalar Int scalar Float@@ -175,6 +156,11 @@   INPUT_OBJECT   LIST   NON_NULL+}++type Query {+  __type(name: String!): __Type+  __schema: __Schema! }  |]
src/Data/Morpheus/Schema/SchemaAPI.hs view
@@ -3,7 +3,6 @@ {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE TypeOperators #-}  module Data.Morpheus.Schema.SchemaAPI   ( withSystemFields,@@ -12,7 +11,7 @@  -- MORPHEUS import Data.Morpheus.Internal.Utils-  ( (<:>),+  ( (<.>),     elems,     empty,     selectOr,@@ -21,20 +20,19 @@   ( createObjectType,     render,   )-import Data.Morpheus.Schema.Directives-  ( defaultDirectives,-  ) import Data.Morpheus.Schema.Schema   (   ) import Data.Morpheus.Types.Internal.AST   ( Argument (..),-    OUT,+    FieldName,+    OBJECT,     QUERY,     ScalarValue (..),     Schema (..),     TypeDefinition (..),     TypeName (..),+    VALID,     Value (..),   ) import Data.Morpheus.Types.Internal.Resolving@@ -49,35 +47,28 @@   )  resolveTypes ::-  Monad m => Schema -> Resolver QUERY e m (ResModel QUERY e m)+  Monad m => Schema VALID -> Resolver QUERY e m (ResModel QUERY e m) resolveTypes schema = mkList <$> traverse render (elems schema)  renderOperation ::-  Monad m => Maybe (TypeDefinition OUT) -> Resolver QUERY e m (ResModel QUERY e m)+  Monad m =>+  Maybe (TypeDefinition OBJECT VALID) ->+  Resolver QUERY e m (ResModel QUERY e m) renderOperation (Just TypeDefinition {typeName}) = pure $ createObjectType typeName Nothing [] empty renderOperation Nothing = pure mkNull  findType ::   Monad m =>   TypeName ->-  Schema ->+  Schema VALID ->   Resolver QUERY e m (ResModel QUERY e m) findType = selectOr (pure mkNull) render -renderDirectives ::-  Monad m =>-  Resolver QUERY e m (ResModel QUERY e m)-renderDirectives =-  mkList-    <$> traverse-      render-      defaultDirectives- schemaResolver ::   Monad m =>-  Schema ->+  Schema VALID ->   Resolver QUERY e m (ResModel QUERY e m)-schemaResolver schema@Schema {query, mutation, subscription} =+schemaResolver schema@Schema {query, mutation, subscription, directiveDefinitions} =   pure $     mkObject       "__Schema"@@ -85,10 +76,10 @@         ("queryType", renderOperation (Just query)),         ("mutationType", renderOperation mutation),         ("subscriptionType", renderOperation subscription),-        ("directives", renderDirectives)+        ("directives", render directiveDefinitions)       ] -schemaAPI :: Monad m => Schema -> ResModel QUERY e m+schemaAPI :: Monad m => Schema VALID -> ResModel QUERY e m schemaAPI schema =   mkObject     "Root"@@ -96,7 +87,7 @@       ("__schema", schemaResolver schema)     ]   where-    typeResolver = selectOr (pure mkNull) handleArg "name"+    typeResolver = selectOr (pure mkNull) handleArg ("name" :: FieldName)       where         handleArg           Argument@@ -104,10 +95,14 @@             } = findType (TypeName typename) schema         handleArg _ = pure mkNull -withSystemFields :: Monad m => Schema -> RootResModel e m -> ResultT e' m (RootResModel e m)+withSystemFields ::+  Monad m =>+  Schema VALID ->+  RootResModel e m ->+  ResultT e' m (RootResModel e m) withSystemFields schema RootResModel {query, ..} =   pure $     RootResModel-      { query = query >>= (<:> schemaAPI schema),+      { query = query >>= (<.> schemaAPI schema),         ..       }
− src/Data/Morpheus/Schema/TypeKind.hs
@@ -1,22 +0,0 @@-{-# LANGUAGE DeriveAnyClass #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE TypeFamilies #-}--module Data.Morpheus.Schema.TypeKind-  ( TypeKind (..),-  )-where--import Data.Aeson (FromJSON (..))-import GHC.Generics--data TypeKind-  = SCALAR-  | OBJECT-  | INTERFACE-  | UNION-  | ENUM-  | INPUT_OBJECT-  | LIST-  | NON_NULL-  deriving (Eq, Generic, FromJSON, Show)
src/Data/Morpheus/Types/GQLScalar.hs view
@@ -2,6 +2,7 @@ {-# LANGUAGE GADTs #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Types.GQLScalar   ( GQLScalar (..),@@ -11,8 +12,9 @@   ) where -import Control.Monad.Fail (MonadFail)+import Control.Monad.Fail (MonadFail (..)) import qualified Data.Aeson as A+import Data.Either (Either (..), either) import Data.Morpheus.Types.Internal.AST   ( ScalarDefinition (..),     ScalarValue (..),@@ -22,6 +24,17 @@   ) import Data.Proxy (Proxy (..)) import Data.Text (Text, unpack)+import Prelude+  ( ($),+    (.),+    Bool,+    Float,+    Int,+    Monad,+    fromInteger,+    pure,+    toInteger,+  )  toScalar :: ValidValue -> Either Text ScalarValue toScalar (Scalar x) = pure x@@ -53,7 +66,7 @@       validator value = do         scalarValue' <- toScalar value         (_ :: a) <- parseValue scalarValue'-        return value+        pure value  instance GQLScalar Text where   parseValue (String x) = pure x
src/Data/Morpheus/Types/ID.hs view
@@ -1,6 +1,7 @@ {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Types.ID   ( ID (..),@@ -21,6 +22,13 @@     pack,   ) import GHC.Generics (Generic)+import Prelude+  ( ($),+    Either (..),+    Eq,+    Show (..),+    pure,+  )  -- | default GraphQL type, -- parses only 'String' and 'Int' values,@@ -28,12 +36,12 @@ newtype ID = ID   { unpackID :: Text   }-  deriving (Show, Generic)+  deriving (Show, Generic, Eq)  instance GQLScalar ID where-  parseValue (Int x) = return (ID $ pack $ show x)-  parseValue (String x) = return (ID x)-  parseValue _ = Left ""+  parseValue (Int x) = pure (ID $ pack $ show x)+  parseValue (String x) = pure (ID x)+  parseValue _ = Left "ID can only be String or number"   serialize (ID x) = String x  instance ToJSON ID where
src/Data/Morpheus/Types/IO.hs view
@@ -1,8 +1,10 @@ {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Types.IO   ( GQLRequest (..),@@ -13,6 +15,10 @@   ) where +-- MORPHEUS++import Control.Applicative (Applicative (..))+import Control.Monad.Fail (fail) import Data.Aeson   ( (.:?),     (.=),@@ -40,10 +46,12 @@     fromStrict,     toStrict,   )+import Data.Either (Either (..))+import Data.Functor ((<$>), fmap) import qualified Data.HashMap.Lazy as LH   ( toList,   )--- MORPHEUS+import Data.Maybe (Maybe (..)) import Data.Morpheus.Error.Utils (badRequestError) import Data.Morpheus.Types.Internal.AST   ( FieldName,@@ -66,27 +74,31 @@     encodeUtf8,   ) import GHC.Generics (Generic)+import Prelude (($), (.), Show, String)  decodeNoDup :: Failure String m => LB.ByteString -> m GQLRequest decodeNoDup str = case eitherDecodeWith jsonNoDup ifromJSON str of   Left (path, x) -> failure $ formatError path x   Right value -> pure value -class MapAPI a where-  mapAPI :: Applicative m => (GQLRequest -> m GQLResponse) -> a -> m a+class MapAPI a b where+  mapAPI :: Applicative m => (GQLRequest -> m GQLResponse) -> a -> m b -instance MapAPI LB.ByteString where+instance MapAPI GQLRequest GQLResponse where+  mapAPI f = f++instance MapAPI LB.ByteString LB.ByteString where   mapAPI api request = case decodeNoDup request of     Left aesonError -> pure $ badRequestError aesonError     Right req -> encode <$> api req -instance MapAPI LT.Text where+instance MapAPI LT.Text LT.Text where   mapAPI api = fmap decodeUtf8 . mapAPI api . encodeUtf8 -instance MapAPI ByteString where+instance MapAPI ByteString ByteString where   mapAPI api = fmap LB.toStrict . mapAPI api . LB.fromStrict -instance MapAPI Text where+instance MapAPI Text Text where   mapAPI api = fmap LT.toStrict . mapAPI api . LT.fromStrict  renderResponse :: Result e ValidValue -> GQLResponse
src/Data/Morpheus/Types/Internal/AST.hs view
@@ -2,6 +2,7 @@ {-# LANGUAGE DuplicateRecordFields #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Types.Internal.AST   ( -- BASE@@ -12,10 +13,9 @@     FieldName (..),     Description,     Stage,-    RESOLVED,+    CONST,     VALID,     RAW,-    VALIDATION_MODE (..),     -- VALUE     Value (..),     ScalarValue (..),@@ -47,7 +47,6 @@     VariableDefinitions,     DefaultValue,     getOperationName,-    getOperationDataType,     -- DSL     ScalarDefinition (..),     DataEnum,@@ -71,17 +70,14 @@     MUTATION,     SUBSCRIPTION,     Directive (..),-    TypeUpdater,     ConsD (..),     TypeCategory,     DataInputUnion,     VariableContent (..),     TypeLib,     initTypeLib,-    defineType,-    isFieldNullable,     kindOf,-    toNullableField,+    toNullable,     toListField,     isObject,     isInput,@@ -91,19 +87,14 @@     isWeaker,     isSubscription,     isOutputObject,-    sysTypes,-    isSystemTypeName,+    isNotSystemTypeName,     isEntNode,-    createField,-    createArgument,-    createEnumType,+    mkEnumContent,     createScalarType,-    createType,-    createUnionType,-    createAlias,-    createInputUnionFields,+    mkUnionContent,+    mkTypeRef,+    mkInputUnionFields,     fieldVisibility,-    createEnumValue,     insertType,     lookupDeprecated,     lookupDeprecatedReason,@@ -113,9 +104,8 @@     -- LOCAL     GQLQuery (..),     Variables,-    isNullableWrapper,     unsafeFromFields,-    OrderedMap,+    OrdMap,     GQLError (..),     GQLErrors,     ObjectEntry (..),@@ -126,8 +116,10 @@     ANY,     IN,     OUT,-    FromAny (..),-    ToAny (..),+    OBJECT,+    IMPLEMENTABLE,+    fromAny,+    toAny,     TRUE,     FALSE,     TypeName (..),@@ -147,30 +139,59 @@     DirectiveLocation (..),     FieldContent (..),     fieldContentArgs,-    mkField,+    mkInputValue,+    mkType,     TypeNameTH (..),     isOutput,     mkObjectField,     UnionMember (..),     mkUnionMember,+    RawTypeDefinition (..),+    RootOperationTypeDefinition (..),+    UnionSelection,+    SchemaDefinition (..),+    buildSchema,+    InternalError (..),+    ValidationError (..),+    msgInternal,+    getOperationDataType,+    Typed (Typed),+    typed,+    untyped,+    msgValidation,+    withPosition,+    ValidationErrors,+    toGQLError,+    ELEM,+    LEAF,+    REQURE_IMPLEMENTABLE,+    ToCategory (..),+    FromCategory (..),+    possibleTypes,+    possibleInterfaceTypes,   ) where  import Data.HashMap.Lazy (HashMap) -- Morpheus+ import Data.Morpheus.Types.Internal.AST.Base import Data.Morpheus.Types.Internal.AST.DirectiveLocation (DirectiveLocation (..))-import Data.Morpheus.Types.Internal.AST.OrderedMap+import Data.Morpheus.Types.Internal.AST.Fields+import Data.Morpheus.Types.Internal.AST.OrdMap 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.TypeCategory import Data.Morpheus.Types.Internal.AST.TypeSystem import Data.Morpheus.Types.Internal.AST.Value import Language.Haskell.TH.Syntax (Lift)+import Prelude (Show)  type Variables = HashMap FieldName ResolvedValue  data GQLQuery = GQLQuery-  { fragments :: Fragments,+  { fragments :: Fragments RAW,     operation :: Operation RAW,     inputVariables :: [(FieldName, ResolvedValue)]   }
src/Data/Morpheus/Types/Internal/AST/Base.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveGeneric #-}@@ -8,6 +9,8 @@ {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Types.Internal.AST.Base   ( Ref (..),@@ -15,13 +18,8 @@     Message (..),     FieldName (..),     Description,-    VALID,-    RAW,     TypeWrapper (..),-    Stage (..),-    RESOLVED,     TypeRef (..),-    VALIDATION_MODE (..),     OperationType (..),     QUERY,     MUTATION,@@ -33,15 +31,13 @@     anonymousRef,     toHSWrappers,     toGQLWrapper,-    sysTypes,-    isNullable,+    Nullable (..),     isWeaker,     isSubscription,     isOutputObject,-    isSystemTypeName,+    isNotSystemTypeName,     isObject,     isInput,-    isNullableWrapper,     sysFields,     hsTypeName,     toOperationType,@@ -60,6 +56,14 @@     convertToJSONName,     convertToHaskellName,     isOutput,+    mkTypeRef,+    InternalError (..),+    msgInternal,+    ValidationError (..),+    msgValidation,+    ValidationErrors,+    withPosition,+    toGQLError,   ) where @@ -70,16 +74,43 @@     encode,   ) import Data.ByteString.Lazy.Char8 (ByteString, unpack)+import Data.Char (toLower) import Data.Hashable (Hashable)+import Data.Maybe (Maybe (..), maybeToList) import Data.Morpheus.Rendering.RenderGQL (RenderGQL (..)) import Data.Semigroup (Semigroup (..))-import Data.String (IsString)+import Data.String (IsString (..)) import Data.Text (Text, intercalate, pack) import qualified Data.Text as T import GHC.Generics (Generic)--- import Instances.TH.Lift ()-import Language.Haskell.TH (stringE)-import Language.Haskell.TH.Syntax (Lift (..))+import Language.Haskell.TH+  ( ExpQ,+    stringE,+  )+import Language.Haskell.TH.Syntax+  ( Lift (..),+    Q,+    TExp,+    unsafeTExpCoerce,+  )+import Prelude+  ( ($),+    (&&),+    (.),+    Bool (..),+    Eq (..),+    Functor (..),+    Int,+    Ord (..),+    Show (..),+    String,+    elem,+    fst,+    id,+    not,+    notElem,+    otherwise,+  )  type TRUE = 'True @@ -96,13 +127,65 @@     (Show, Eq, Ord, IsString, Semigroup, Hashable, FromJSON, ToJSON)  instance Lift Message where-  lift = stringE . T.unpack . readMessage+  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 . map (readMessage . msg)+  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 @@ -115,6 +198,10 @@ instance Msg Value where   msg = msg . encode +class Nullable a where+  isNullable :: a -> Bool+  toNullable :: a -> a+ -- FieldName : lower case names newtype FieldName = FieldName {readName :: Text}   deriving@@ -123,8 +210,12 @@     (Show, Ord, Eq, IsString, Hashable, Semigroup, FromJSON, ToJSON)  instance Lift FieldName where-  lift = stringE . T.unpack . readName+  lift = liftString . readName +#if MIN_VERSION_template_haskell(2,16,0)+  liftTyped = liftTypedString . readName+#endif+ instance Msg FieldName where   msg FieldName {readName} = Message $ "\"" <> readName <> "\"" @@ -132,7 +223,7 @@   render = readName  intercalateName :: FieldName -> [FieldName] -> FieldName-intercalateName (FieldName x) = FieldName . intercalate x . map readName+intercalateName (FieldName x) = FieldName . intercalate x . fmap readName  toFieldName :: TypeName -> FieldName toFieldName = FieldName . readTypeName@@ -145,8 +236,18 @@     (Show, Ord, Eq, IsString, Hashable, Semigroup, FromJSON, ToJSON)  instance Lift TypeName where-  lift = stringE . T.unpack . readTypeName+  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 <> "\"" @@ -156,8 +257,6 @@ -- Description type Description = Text -data Stage = RAW | RESOLVED | VALID- data Position = Position   { line :: Int,     column :: Int@@ -177,17 +276,6 @@  type GQLErrors = [GQLError] -type RAW = 'RAW--type RESOLVED = 'RESOLVED--type VALID = 'VALID--data VALIDATION_MODE-  = WITHOUT_VARIABLES-  | FULL_VALIDATION-  deriving (Eq, Show)- data DataFingerprint = DataFingerprint TypeName [String] deriving (Show, Eq, Ord, Lift)  internalFingerprint :: TypeName -> [String] -> DataFingerprint@@ -197,8 +285,16 @@   = Query   | Subscription   | Mutation-  deriving (Show, Eq, Lift)+  deriving (Show, Eq, Lift, Generic, Hashable) +instance RenderGQL OperationType where+  render = pack . 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@@ -236,9 +332,14 @@   }   deriving (Show, Eq, Lift) -isNullable :: TypeRef -> Bool-isNullable TypeRef {typeWrappers = typeWrappers} = isNullableWrapper typeWrappers+mkTypeRef :: TypeName -> TypeRef+mkTypeRef typeConName =+  TypeRef {typeConName, typeWrappers = [], typeArgs = Nothing} +instance Nullable TypeRef where+  isNullable = isNullable . typeWrappers+  toNullable TypeRef {..} = TypeRef {typeWrappers = toNullable typeWrappers, ..}+ instance RenderGQL TypeRef where   render TypeRef {typeConName, typeWrappers} = renderWrapped typeConName typeWrappers @@ -259,6 +360,17 @@   | KindInterface   deriving (Eq, Show, Lift) +instance RenderGQL TypeKind where+  render KindScalar = "SCALAR"+  render KindObject {} = "OBJECT"+  render KindUnion = "UNION"+  render KindInputUnion = "INPUT_OBJECT"+  render KindEnum = "ENUM"+  render KindInputObject = "INPUT_OBJECT"+  render KindList = "LIST"+  render KindNonNull = "NON_NULL"+  render KindInterface = "INTERFACE"+ isSubscription :: TypeKind -> Bool isSubscription (KindObject (Just Subscription)) = True isSubscription _ = False@@ -296,9 +408,11 @@   | NonNullType   deriving (Show, Lift) -isNullableWrapper :: [TypeWrapper] -> Bool-isNullableWrapper (TypeMaybe : _) = True-isNullableWrapper _ = False+instance Nullable [TypeWrapper] where+  isNullable (TypeMaybe : _) = True+  isNullable _ = False+  toNullable (TypeMaybe : xs) = TypeMaybe : xs+  toNullable xs = TypeMaybe : xs  isWeaker :: [TypeWrapper] -> [TypeWrapper] -> Bool isWeaker (TypeMaybe : xs1) (TypeMaybe : xs2) = isWeaker xs1 xs2@@ -328,25 +442,24 @@     showGQLWrapper (ListType : xs) = "[" <> showGQLWrapper xs <> "]"     showGQLWrapper (NonNullType : xs) = showGQLWrapper xs <> "!" -isSystemTypeName :: TypeName -> Bool-isSystemTypeName = (`elem` sysTypes)--sysTypes :: [TypeName]-sysTypes =-  [ "__Schema",-    "__Type",-    "__Directive",-    "__TypeKind",-    "__Field",-    "__DirectiveLocation",-    "__InputValue",-    "__EnumValue",-    "String",-    "Float",-    "Int",-    "Boolean",-    "ID"-  ]+isNotSystemTypeName :: TypeName -> Bool+isNotSystemTypeName =+  ( `notElem`+      [ "__Schema",+        "__Type",+        "__Directive",+        "__TypeKind",+        "__Field",+        "__DirectiveLocation",+        "__InputValue",+        "__EnumValue",+        "String",+        "Float",+        "Int",+        "Boolean",+        "ID"+      ]+  )  sysFields :: [FieldName] sysFields = ["__typename", "__schema", "__type"]
src/Data/Morpheus/Types/Internal/AST/DirectiveLocation.hs view
@@ -1,9 +1,14 @@ {-# LANGUAGE DeriveLift #-}+{-# LANGUAGE NoImplicitPrelude #-} -module Data.Morpheus.Types.Internal.AST.DirectiveLocation (DirectiveLocation (..)) where+module Data.Morpheus.Types.Internal.AST.DirectiveLocation+  ( DirectiveLocation (..),+  )+where  import Data.Morpheus.Types.Internal.AST.Base (Msg (..)) import Language.Haskell.TH.Syntax (Lift)+import Prelude ((.), Eq, Show (..))  data DirectiveLocation   = QUERY
+ src/Data/Morpheus/Types/Internal/AST/Fields.hs view
@@ -0,0 +1,368 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveLift #-}+{-# LANGUAGE DeriveTraversable #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE NoImplicitPrelude #-}++module Data.Morpheus.Types.Internal.AST.Fields+  ( Arguments,+    Argument (..),+    ArgumentDefinition,+    ArgumentsDefinition (..),+    FieldDefinition (..),+    FieldsDefinition,+    Fields (..),+    FieldContent (..),+    InputFieldsDefinition,+    DirectiveDefinitions,+    DirectiveDefinition (..),+    Directives,+    Directive (..),+    fieldVisibility,+    toListField,+    lookupDeprecated,+    lookupDeprecatedReason,+    unsafeFromFields,+    fieldsToArguments,+    fieldContentArgs,+    mkInputValue,+    mkObjectField,+  )+where++-- MORPHEUS++import Data.Foldable (Foldable)+import Data.Functor ((<$>), Functor (..))+import Data.List (find)+import Data.Maybe (Maybe (..))+import Data.Morpheus.Error.NameCollision+  ( NameCollision (..),+  )+import Data.Morpheus.Internal.Utils+  ( Collection (..),+    KeyOf (..),+    Listable (..),+    Merge (..),+    Selectable (..),+    elems,+  )+import Data.Morpheus.Rendering.RenderGQL+  ( RenderGQL (..),+    renderArguments,+    renderEntry,+    renderObject,+  )+import Data.Morpheus.Types.Internal.AST.Base+  ( Description,+    FieldName,+    FieldName (..),+    Msg (..),+    Nullable (..),+    Position,+    TRUE,+    TypeName,+    TypeRef (..),+    TypeWrapper (..),+    ValidationError (..),+    msgValidation,+    sysFields,+  )+import Data.Morpheus.Types.Internal.AST.DirectiveLocation (DirectiveLocation)+import Data.Morpheus.Types.Internal.AST.OrdMap+  ( OrdMap,+    unsafeFromValues,+  )+import Data.Morpheus.Types.Internal.AST.Stage+  ( Stage,+  )+import Data.Morpheus.Types.Internal.AST.TypeCategory+  ( ANY,+    ELEM,+    IN,+    OUT,+    ToCategory (..),+    TypeCategory,+    toAny,+  )+import Data.Morpheus.Types.Internal.AST.Value+  ( ScalarValue (..),+    Value (..),+  )+import Data.Semigroup (Semigroup ((<>)))+import Data.Traversable (Traversable)+import Instances.TH.Lift ()+import Language.Haskell.TH.Syntax (Lift (..))+import Prelude+  ( ($),+    (.),+    Bool (..),+    Eq,+    Show,+    filter,+    notElem,+  )++-- scalar+------------------------------------------------------------------+data Argument (valid :: Stage) = Argument+  { argumentName :: FieldName,+    argumentPosition :: Position,+    argumentValue :: Value valid+  }+  deriving (Show, Eq, Lift)++instance KeyOf FieldName (Argument stage) where+  keyOf = argumentName++instance RenderGQL (Argument s) where+  render Argument {argumentName, argumentValue} =+    renderEntry argumentName argumentValue++instance NameCollision (Argument s) where+  nameCollision Argument {argumentName, argumentPosition} =+    ValidationError+      { validationMessage = "There can Be only One Argument Named " <> msg argumentName,+        validationLocations = [argumentPosition]+      }++type Arguments (s :: Stage) = OrdMap FieldName (Argument s)++-- directive+------------------------------------------------------------------+data Directive (s :: Stage) = Directive+  { directiveName :: FieldName,+    directivePosition :: Position,+    directiveArgs :: Arguments s+  }+  deriving (Show, Lift, Eq)++instance KeyOf FieldName (Directive s) where+  keyOf = directiveName++type Directives s = [Directive s]++data DirectiveDefinition s = DirectiveDefinition+  { directiveDefinitionName :: FieldName,+    directiveDefinitionDescription :: Maybe Description,+    directiveDefinitionLocations :: [DirectiveLocation],+    directiveDefinitionArgs :: ArgumentsDefinition s+  }+  deriving (Show, Lift)++type DirectiveDefinitions s = [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++lookupDeprecated :: [Directive s] -> Maybe (Directive s)+lookupDeprecated = find isDeprecation+  where+    isDeprecation Directive {directiveName = "deprecated"} = True+    isDeprecation _ = False++lookupDeprecatedReason :: Directive s -> Maybe Description+lookupDeprecatedReason Directive {directiveArgs} =+  selectOr+    Nothing+    argumentStringValue+    ("reason" :: FieldName)+    directiveArgs++argumentStringValue :: Argument s -> Maybe Description+argumentStringValue Argument {argumentValue = Null} = Nothing+argumentStringValue Argument {argumentValue = (Scalar (String x))} = Just x+argumentStringValue _ = Just "can't read deprecated Reason Value"++instance ToCategory FieldDefinition a ANY where+  toCategory FieldDefinition {fieldContent, ..} = FieldDefinition {fieldContent = toAny <$> fieldContent, ..}++instance ToCategory (FieldContent TRUE) a ANY where+  toCategory (FieldArgs x) = FieldArgs x+  toCategory (DefaultInputValue x) = DefaultInputValue x++newtype Fields def = Fields+  {unFields :: OrdMap FieldName def}+  deriving+    ( Show,+      Lift,+      Functor,+      Foldable,+      Traversable+    )++deriving instance (KeyOf FieldName def) => Collection def (Fields def)++instance Merge (FieldsDefinition cat s) where+  merge path (Fields x) (Fields y) = Fields <$> merge path x y++instance Selectable FieldName (FieldDefinition cat s) (Fields (FieldDefinition cat s)) where+  selectOr fb f name (Fields lib) = selectOr fb f name lib++unsafeFromFields :: [FieldDefinition cat s] -> FieldsDefinition cat s+unsafeFromFields = Fields . unsafeFromValues++fieldsToArguments :: FieldsDefinition IN s -> ArgumentsDefinition s+fieldsToArguments = ArgumentsDefinition Nothing . unFields++instance (KeyOf FieldName def, NameCollision def) => Listable def (Fields def) where+  fromElems = fmap Fields . fromElems+  elems = elems . unFields++-- 3.6 Objects : https://graphql.github.io/graphql-spec/June2018/#sec-Objects+------------------------------------------------------------------------------+--  ObjectTypeDefinition:+--    Description(opt) type Name ImplementsInterfaces(opt) Directives(Const)(opt) FieldsDefinition(opt)+--+--  ImplementsInterfaces+--    implements &(opt) NamedType+--    ImplementsInterfaces & NamedType+--+--  FieldsDefinition+--    { FieldDefinition(list) }+--+type FieldsDefinition cat s = Fields (FieldDefinition cat s)++--  FieldDefinition+--    Description(opt) Name ArgumentsDefinition(opt) : Type Directives(Const)(opt)+--+-- InputValueDefinition+--   Description(opt) Name: Type DefaultValue(opt) Directives[Const](opt)++data FieldDefinition (cat :: TypeCategory) (s :: Stage) = FieldDefinition+  { fieldName :: FieldName,+    fieldDescription :: Maybe Description,+    fieldType :: TypeRef,+    fieldDirectives :: [Directive s],+    fieldContent :: Maybe (FieldContent TRUE cat s)+  }+  deriving (Show, Lift)++data FieldContent (bool :: Bool) (cat :: TypeCategory) (s :: Stage) where+  DefaultInputValue ::+    { defaultInputValue :: Value s+    } ->+    FieldContent (ELEM IN cat) cat s+  FieldArgs ::+    { fieldArgsDef :: ArgumentsDefinition s+    } ->+    FieldContent (ELEM OUT cat) cat s++fieldContentArgs :: FieldContent b cat s -> ArgumentsDefinition s+fieldContentArgs (FieldArgs args) = args+fieldContentArgs _ = empty++deriving instance Show (FieldContent bool cat s)++deriving instance Lift (FieldContent bool cat s)++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+  nameCollision FieldDefinition {fieldName} =+    "There can Be only One field Named " <> msgValidation fieldName++instance RenderGQL (FieldDefinition cat s) where+  render FieldDefinition {fieldName = FieldName name, fieldType, fieldContent = Just (FieldArgs args)} =+    name <> render args <> ": " <> render fieldType+  render FieldDefinition {fieldName, fieldType} =+    renderEntry fieldName fieldType++instance RenderGQL (FieldsDefinition cat s) where+  render = renderObject . filter fieldVisibility . elems++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++createField ::+  Maybe (FieldContent TRUE cat s) ->+  FieldName ->+  [TypeWrapper] ->+  TypeName ->+  FieldDefinition cat s+createField fieldContent fieldName typeWrappers typeConName =+  FieldDefinition+    { fieldName,+      fieldContent,+      fieldDescription = Nothing,+      fieldType = TypeRef {typeConName, typeWrappers, typeArgs = Nothing},+      fieldDirectives = []+    }++mkInputValue :: FieldName -> [TypeWrapper] -> TypeName -> FieldDefinition cat s+mkInputValue = createField Nothing++mkObjectField ::+  ArgumentsDefinition s ->+  FieldName ->+  [TypeWrapper] ->+  TypeName ->+  FieldDefinition OUT s+mkObjectField args = createField (Just $ FieldArgs args)++toListField :: FieldDefinition cat s -> FieldDefinition cat s+toListField dataField = dataField {fieldType = listW (fieldType dataField)}+  where+    listW alias@TypeRef {typeWrappers} =+      alias {typeWrappers = TypeList : typeWrappers}++-- 3.10 Input Objects: https://spec.graphql.org/June2018/#sec-Input-Objects+---------------------------------------------------------------------------+--- InputFieldsDefinition+-- { InputValueDefinition(list) }++type InputFieldsDefinition s = Fields (InputValueDefinition s)++type InputValueDefinition = FieldDefinition IN++-- 3.6.1 Field Arguments : https://graphql.github.io/graphql-spec/June2018/#sec-Field-Arguments+-----------------------------------------------------------------------------------------------+-- ArgumentsDefinition:+--   (InputValueDefinition(list))++data ArgumentsDefinition s = ArgumentsDefinition+  { argumentsTypename :: Maybe TypeName,+    arguments :: OrdMap FieldName (ArgumentDefinition s)+  }+  deriving (Show, Lift)++instance RenderGQL (ArgumentsDefinition s) where+  render ArgumentsDefinition {arguments} = renderArguments (elems arguments)++type ArgumentDefinition = FieldDefinition IN++instance Selectable FieldName (ArgumentDefinition s) (ArgumentsDefinition s) where+  selectOr fb f key (ArgumentsDefinition _ args) = selectOr fb f key args++instance Collection (ArgumentDefinition s) (ArgumentsDefinition s) where+  empty = ArgumentsDefinition Nothing empty+  singleton = ArgumentsDefinition Nothing . singleton++instance Listable (ArgumentDefinition s) (ArgumentsDefinition s) where+  elems (ArgumentsDefinition _ args) = elems args+  fromElems args = ArgumentsDefinition Nothing <$> fromElems args
src/Data/Morpheus/Types/Internal/AST/MergeSet.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE DataKinds #-}-{-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE DeriveLift #-} {-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE FlexibleContexts #-}@@ -9,19 +8,24 @@ {-# LANGUAGE KindSignatures #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Types.Internal.AST.MergeSet   ( MergeSet,-    toOrderedMap,+    toOrdMap,     concatTraverse,     join,   ) where -import Data.List ((\\), find)-import Data.Maybe (maybe) -- MORPHEUS +import Control.Applicative (Applicative (..))+import Control.Monad (Monad (..))+import Data.Foldable (Foldable (..))+import Data.Functor ((<$>), Functor (..))+import Data.List ((\\), find)+import Data.Maybe (maybe) import Data.Morpheus.Internal.Utils   ( (<:>),     Collection (..),@@ -33,19 +37,29 @@     elems,   ) import Data.Morpheus.Types.Internal.AST.Base-  ( FieldName,-    GQLErrors,-    RAW,-    Ref,+  ( Ref,+    ValidationErrors,+  )+import Data.Morpheus.Types.Internal.AST.OrdMap+  ( OrdMap (..),+  )+import qualified Data.Morpheus.Types.Internal.AST.OrdMap as OM+import Data.Morpheus.Types.Internal.AST.Stage+  ( RAW,     Stage,     VALID,   )-import Data.Morpheus.Types.Internal.AST.OrderedMap-  ( OrderedMap (..),-  )-import qualified Data.Morpheus.Types.Internal.AST.OrderedMap as OM-import Data.Semigroup ((<>))+import Data.Semigroup (Semigroup (..))+import Data.Traversable (Traversable (..)) import Language.Haskell.TH.Syntax (Lift (..))+import Prelude+  ( ($),+    (.),+    Eq (..),+    Show,+    flip,+    otherwise,+  )  -- set with mergeable components newtype MergeSet (dups :: Stage) a = MergeSet@@ -66,9 +80,9 @@     Eq b,     Merge a,     Merge b,-    KeyOf b,+    KeyOf k b,     Monad m,-    Failure GQLErrors m+    Failure ValidationErrors m   ) =>   (a -> m (MergeSet VALID b)) ->   MergeSet RAW a ->@@ -79,10 +93,10 @@  join ::   ( Eq a,-    KeyOf a,+    KeyOf k a,     Merge a,     Monad m,-    Failure GQLErrors m,+    Failure ValidationErrors m,     Listable a (MergeSet opt a),     Merge (MergeSet opt a)   ) =>@@ -93,16 +107,16 @@     __join acc [] = pure acc     __join acc (x : xs) = acc <:> x >>= (`__join` xs) -toOrderedMap :: (KEY a ~ FieldName, KeyOf a) => MergeSet opt a -> OrderedMap FieldName a-toOrderedMap = OM.unsafeFromValues . unpack+toOrdMap :: (KeyOf k a) => MergeSet opt a -> OrdMap k a+toOrdMap = OM.unsafeFromValues . unpack -instance (KeyOf a, k ~ KEY a) => Selectable (MergeSet opt a) a where+instance (KeyOf k a) => Selectable k a (MergeSet opt a) where   selectOr fb f key (MergeSet ls) = maybe fb f (find ((key ==) . keyOf) ls)  -- must merge files on collision  instance-  ( KeyOf a,+  ( KeyOf k a,     Listable a (MergeSet VALID a),     Merge a,     Eq a@@ -113,7 +127,7 @@  instance   ( Listable a (MergeSet VALID a),-    KeyOf a,+    KeyOf k a,     Merge a,     Eq a   ) =>@@ -129,17 +143,17 @@   fromElems = pure . MergeSet   elems = unpack -safeFromList :: (Monad m, KeyOf a, Eq a, Merge a, Failure GQLErrors m) => [a] -> m (MergeSet opt a)+safeFromList :: (Monad m, Eq a, KeyOf k a, Merge a, Failure ValidationErrors m) => [a] -> m (MergeSet opt a) safeFromList = insertList [] empty -safeJoin :: (Monad m, KeyOf a, Eq a, Listable a (MergeSet opt a), Merge a, Failure GQLErrors m) => [Ref] -> MergeSet opt a -> MergeSet opt a -> m (MergeSet opt a)+safeJoin :: (Monad m, KeyOf k a, Eq a, Listable a (MergeSet opt a), Merge a, Failure ValidationErrors m) => [Ref] -> MergeSet opt a -> MergeSet opt a -> m (MergeSet opt a) safeJoin path hm1 hm2 = insertList path hm1 (elems hm2) -insertList :: (Monad m, Eq a, KeyOf a, Merge a, Failure GQLErrors m) => [Ref] -> MergeSet opt a -> [a] -> m (MergeSet opt a)+insertList :: (Monad m, Eq a, KeyOf k a, Merge a, Failure ValidationErrors m) => [Ref] -> MergeSet opt a -> [a] -> m (MergeSet opt a) insertList _ smap [] = pure smap insertList path smap (x : xs) = insert path smap x >>= flip (insertList path) xs -insert :: (Monad m, Eq a, KeyOf a, Merge a, Failure GQLErrors m) => [Ref] -> MergeSet opt a -> a -> m (MergeSet opt a)+insert :: (Monad m, Eq a, KeyOf k a, Merge a, Failure ValidationErrors m) => [Ref] -> MergeSet opt a -> a -> m (MergeSet opt a) insert path mSet@(MergeSet ls) currentValue = MergeSet <$> __insert   where     __insert =
+ src/Data/Morpheus/Types/Internal/AST/OrdMap.hs view
@@ -0,0 +1,100 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE NoImplicitPrelude #-}++module Data.Morpheus.Types.Internal.AST.OrdMap+  ( OrdMap (..),+    unsafeFromValues,+  )+where++-- MORPHEUS+import Data.Foldable (Foldable (..))+import Data.Functor ((<$>), Functor (..))+import Data.HashMap.Lazy (HashMap)+import qualified Data.HashMap.Lazy as HM+import Data.Hashable (Hashable)+import Data.Maybe (fromMaybe, maybe)+import Data.Morpheus.Error.NameCollision (NameCollision (..))+import Data.Morpheus.Internal.Utils+  ( Collection (..),+    KeyOf (..),+    Listable (..),+    Merge (..),+    Selectable (..),+    toPair,+  )+import Data.Semigroup ((<>))+import Data.Traversable (Traversable (..))+import Language.Haskell.TH.Syntax (Lift (..))+import Prelude+  ( ($),+    (.),+    Eq,+    Show,+    error,+  )++-- OrdMap+data OrdMap k a = OrdMap+  { mapKeys :: [k],+    mapEntries :: HashMap k a+  }+  deriving+    ( Show,+      Eq,+      Functor+    )++instance (Lift a, Lift k, Eq k, Hashable k) => Lift (OrdMap k a) where+  lift (OrdMap names x) = [|OrdMap names (HM.fromList ls)|]+    where+      ls = HM.toList x++#if MIN_VERSION_template_haskell(2,16,0)+  liftTyped (OrdMap names x) = [||OrdMap names (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 OrdMap {mapKeys, mapEntries} = fmap takeValue mapKeys+  where+    takeValue key = fromMaybe (error "TODO: invalid Ordered Map") (key `HM.lookup` mapEntries)++instance (Eq k, Hashable k) => Traversable (OrdMap k) where+  traverse f (OrdMap names values) = OrdMap names <$> traverse f values++instance (KeyOf k a, Hashable k) => Collection a (OrdMap k a) where+  empty = OrdMap [] HM.empty+  singleton x = OrdMap [keyOf x] $ HM.singleton (keyOf x) x++instance (Eq k, Hashable k) => Selectable k a (OrdMap k a) where+  selectOr fb f key OrdMap {mapEntries} = maybe fb f (HM.lookup key mapEntries)++instance (NameCollision a, KeyOf k a) => Merge (OrdMap k a) where+  merge ref (OrdMap k1 x) (OrdMap k2 y) = OrdMap (k1 <> k2) <$> merge ref x y++instance (NameCollision a, KeyOf k a, Hashable k) => Listable a (OrdMap k a) where+  fromElems values = OrdMap (fmap keyOf values) <$> fromElems values+  elems = getElements++unsafeFromValues ::+  ( KeyOf k a,+    Hashable k+  ) =>+  [a] ->+  OrdMap k a+unsafeFromValues x = OrdMap (fmap keyOf x) $ HM.fromList $ fmap toPair x
− src/Data/Morpheus/Types/Internal/AST/OrderedMap.hs
@@ -1,122 +0,0 @@-{-# LANGUAGE DeriveFunctor #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE TemplateHaskell #-}--module Data.Morpheus.Types.Internal.AST.OrderedMap-  ( OrderedMap (..),-    unsafeFromValues,-  )-where--import Data.HashMap.Lazy (HashMap)-import qualified Data.HashMap.Lazy as HM-import Data.Hashable (Hashable)-import Data.Maybe (fromMaybe, isJust)--- MORPHEUS-import Data.Morpheus.Error.NameCollision (NameCollision (..))-import Data.Morpheus.Internal.Utils-  ( Collection (..),-    Failure (..),-    KeyOf (..),-    Listable (..),-    Merge (..),-    Selectable (..),-    toPair,-  )-import Data.Morpheus.Types.Internal.AST.Base-  ( GQLErrors,-  )-import Data.Semigroup ((<>))-import Language.Haskell.TH.Syntax (Lift (..))---- OrderedMap-data OrderedMap k a = OrderedMap-  { mapKeys :: [k],-    mapEntries :: HashMap k a-  }-  deriving (Show, Eq, Functor)--instance (Lift a, Lift k) => Lift (OrderedMap k a) where-  lift (OrderedMap names x) = [|OrderedMap names (HM.fromList ls)|]-    where-      ls = HM.toList x--instance (Eq k, Hashable k) => Foldable (OrderedMap k) where-  foldMap f = foldMap f . getElements--getElements :: (Eq k, Hashable k) => OrderedMap k b -> [b]-getElements OrderedMap {mapKeys, mapEntries} = map takeValue mapKeys-  where-    takeValue key = fromMaybe (error "TODO: invalid Ordered Map") (key `HM.lookup` mapEntries)--instance (Eq k, Hashable k) => Traversable (OrderedMap k) where-  traverse f (OrderedMap names values) = OrderedMap names <$> traverse f values--instance (KeyOf a, Hashable k, KEY a ~ k) => Collection a (OrderedMap k a) where-  empty = OrderedMap [] HM.empty-  singleton x = OrderedMap [keyOf x] $ HM.singleton (keyOf x) x--instance (Eq k, Hashable k, k ~ KEY a) => Selectable (OrderedMap k a) a where-  selectOr fb f key OrderedMap {mapEntries} = maybe fb f (HM.lookup key mapEntries)--instance (NameCollision a, Eq k, Hashable k, k ~ KEY a) => Merge (OrderedMap k a) where-  merge _ (OrderedMap k1 x) (OrderedMap k2 y) = OrderedMap (k1 <> k2) <$> safeJoin x y--instance (NameCollision a, Eq k, Hashable k, k ~ KEY a) => Listable a (OrderedMap k a) where-  fromElems = safeFromList-  elems = getElements--safeFromList ::-  ( Failure GQLErrors m,-    Applicative m,-    NameCollision a,-    Eq (KEY a),-    Hashable (KEY a),-    KeyOf a-  ) =>-  [a] ->-  m (OrderedMap (KEY a) a)-safeFromList values = OrderedMap (map keyOf values) <$> safeUnionWith HM.empty (map toPair values)--unsafeFromValues ::-  ( KeyOf a,-    Eq (KEY a),-    Hashable (KEY a)-  ) =>-  [a] ->-  OrderedMap (KEY a) a-unsafeFromValues x = OrderedMap (map keyOf x) $ HM.fromList $ fmap toPair x--safeJoin :: (Failure GQLErrors m, Eq k, Hashable k, KEY a ~ k, Applicative m, NameCollision a) => HashMap k a -> HashMap k a -> m (HashMap k a)-safeJoin hm newls = safeUnionWith hm (HM.toList newls)--safeUnionWith ::-  ( Failure GQLErrors m,-    Applicative m,-    Eq k,-    Hashable k,-    NameCollision a,-    KEY a ~ k-  ) =>-  HashMap k a ->-  [(k, a)] ->-  m (HashMap k a)-safeUnionWith hm names = case insertNoDups (hm, []) names of-  (res, dupps)-    | null dupps -> pure res-    | otherwise -> failure $ map (uncurry nameCollision) dupps--type NoDupHashMap k a = (HashMap k a, [(k, a)])--insertNoDups :: (Eq k, Hashable k) => NoDupHashMap k a -> [(k, a)] -> NoDupHashMap k a-insertNoDups collected [] = collected-insertNoDups (coll, errors) (pair@(name, value) : xs)-  | isJust (name `HM.lookup` coll) = insertNoDups (coll, errors <> [pair]) xs-  | otherwise = insertNoDups (HM.insert name value coll, errors) xs
+ src/Data/Morpheus/Types/Internal/AST/SafeHashMap.hs view
@@ -0,0 +1,86 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveTraversable #-}+{-# LANGUAGE DerivingStrategies #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE NoImplicitPrelude #-}++module Data.Morpheus.Types.Internal.AST.SafeHashMap+  ( SafeHashMap,+    insert,+  )+where++-- MORPHEUS+import Control.Monad (Monad)+import Data.Foldable (Foldable (..))+import Data.Functor ((<$>), Functor (..))+import Data.HashMap.Lazy (HashMap)+import qualified Data.HashMap.Lazy as HM+import Data.Hashable (Hashable)+import Data.Morpheus.Error.NameCollision (NameCollision (..))+import Data.Morpheus.Internal.Utils+  ( (<:>),+    Collection (..),+    Failure (..),+    KeyOf (..),+    Listable (..),+    Merge (..),+    Selectable (..),+  )+import Data.Morpheus.Types.Internal.AST.Base (ValidationErrors)+import Data.Traversable (Traversable (..))+import Language.Haskell.TH.Syntax (Lift (..))+import Prelude+  ( (.),+    Eq,+    Show,+  )++newtype SafeHashMap k a = SafeHashMap+  { unpackSafeHashMap :: HashMap k a+  }+  deriving+    ( Show,+      Eq,+      Functor,+      Foldable,+      Traversable+    )+  deriving newtype+    ( Collection a,+      Selectable k a+    )++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, KeyOf k a) => Merge (SafeHashMap k a) where+  merge ref (SafeHashMap x) (SafeHashMap y) = SafeHashMap <$> merge ref x y++instance (NameCollision a, KeyOf k a, Hashable k) => Listable a (SafeHashMap k a) where+  fromElems = fmap SafeHashMap . fromElems+  elems = elems . unpackSafeHashMap++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/Types/Internal/AST/Selection.hs view
@@ -3,12 +3,14 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-}+{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Types.Internal.AST.Selection   ( Selection (..),@@ -27,9 +29,10 @@   ) where -import Data.Maybe (fromMaybe, isJust)--- MORPHEUS-+import Control.Applicative (pure)+import Data.Foldable (all, foldr)+import Data.Functor ((<$>), fmap)+import Data.Maybe (Maybe (..), fromMaybe, isJust, maybe) import Data.Morpheus.Error.NameCollision   ( NameCollision (..),   )@@ -41,34 +44,50 @@   ( Failure (..),     KeyOf (..),     Merge (..),+    elems,   )+import Data.Morpheus.Rendering.RenderGQL+  ( RenderGQL (..),+    Rendering,+    renderArguments,+    renderObject,+    space,+  ) import Data.Morpheus.Types.Internal.AST.Base   ( FieldName,-    GQLError (..),-    GQLErrors,     Message,+    Msg (..),     OperationType (..),     Position,-    RAW,     Ref (..),-    Stage,     TypeName (..),-    VALID,+    ValidationError (..),+    ValidationErrors,     intercalateName,     msg,+    msgValidation,     readName,   )+import Data.Morpheus.Types.Internal.AST.Fields+  ( Arguments,+    Directives,+  ) import Data.Morpheus.Types.Internal.AST.MergeSet   ( MergeSet,   )-import Data.Morpheus.Types.Internal.AST.OrderedMap-  ( OrderedMap,+import Data.Morpheus.Types.Internal.AST.OrdMap+  ( OrdMap,   )+import Data.Morpheus.Types.Internal.AST.Stage+  ( RAW,+    Stage,+    VALID,+  )+import Data.Morpheus.Types.Internal.AST.TypeCategory+  ( OBJECT,+  ) import Data.Morpheus.Types.Internal.AST.TypeSystem-  ( Arguments,-    Directives,-    OUT,-    Schema (..),+  ( Schema (..),     TypeDefinition (..),   ) import Data.Morpheus.Types.Internal.AST.Value@@ -78,34 +97,48 @@   ) import Data.Semigroup ((<>)) import Language.Haskell.TH.Syntax (Lift (..))+import Prelude+  ( ($),+    (.),+    Eq (..),+    Show (..),+    otherwise,+  ) -data Fragment = Fragment+data Fragment (stage :: Stage) = Fragment   { fragmentName :: FieldName,     fragmentType :: TypeName,     fragmentPosition :: Position,-    fragmentSelection :: SelectionSet RAW,-    fragmentDirectives :: Directives RAW+    fragmentSelection :: SelectionSet stage,+    fragmentDirectives :: Directives stage   }   deriving (Show, Eq, Lift)  -- ERRORs-instance NameCollision Fragment where-  nameCollision _ Fragment {fragmentName, fragmentPosition} =-    GQLError-      { message = "There can be only one fragment named " <> msg fragmentName <> ".",-        locations = [fragmentPosition]-      }+instance NameCollision (Fragment s) where+  nameCollision Fragment {fragmentName, fragmentPosition} =+    ValidationError+      ("There can be only one fragment named " <> msg fragmentName <> ".")+      [fragmentPosition] -instance KeyOf Fragment where+instance KeyOf FieldName (Fragment s) where   keyOf = fragmentName -type Fragments = OrderedMap FieldName Fragment+type Fragments (s :: Stage) = OrdMap FieldName (Fragment s)  data SelectionContent (s :: Stage) where   SelectionField :: SelectionContent s   SelectionSet :: SelectionSet s -> SelectionContent s   UnionSelection :: UnionSelection VALID -> SelectionContent VALID +renderSelectionSet :: SelectionSet VALID -> Rendering+renderSelectionSet = renderObject . elems++instance RenderGQL (SelectionContent VALID) where+  render SelectionField = ""+  render (SelectionSet selSet) = renderSelectionSet selSet+  render (UnionSelection unionSets) = renderObject (elems unionSets)+ instance   Merge (SelectionSet s) =>   Merge (SelectionContent s)@@ -116,9 +149,9 @@     | oldC == currC = pure oldC     | otherwise =       failure-        [ GQLError-            { message = msg (intercalateName "." $ map refName path),-              locations = map refPosition path+        [ ValidationError+            { validationMessage = msg (intercalateName "." $ fmap refName path),+              validationLocations = fmap refPosition path             }         ] @@ -134,12 +167,22 @@   }   deriving (Show, Eq, Lift) -mergeConflict :: [Ref] -> GQLError -> GQLErrors+instance KeyOf TypeName UnionTag where+  keyOf = unionTagName++instance RenderGQL UnionTag where+  render UnionTag {unionTagName, unionTagSelection} =+    "... on "+      <> render unionTagName+      <> space+      <> renderSelectionSet unionTagSelection++mergeConflict :: [Ref] -> ValidationError -> ValidationErrors mergeConflict [] err = [err] mergeConflict refs@(rootField : xs) err =-  [ GQLError-      { message = renderSubfields <> message err,-        locations = map refPosition refs <> locations err+  [ ValidationError+      { validationMessage = renderSubfields <> validationMessage err,+        validationLocations = fmap refPosition refs <> validationLocations err       }   ]   where@@ -156,10 +199,6 @@   merge path (UnionTag oldTag oldSel) (UnionTag _ currentSel) =     UnionTag oldTag <$> merge path oldSel currentSel -instance KeyOf UnionTag where-  type KEY UnionTag = TypeName-  keyOf = unionTagName- type UnionSelection (s :: Stage) = MergeSet s UnionTag  type SelectionSet (s :: Stage) = MergeSet s (Selection s)@@ -174,10 +213,19 @@       selectionDirectives :: Directives s     } ->     Selection s-  InlineFragment :: Fragment -> Selection RAW+  InlineFragment :: Fragment RAW -> Selection RAW   Spread :: Directives RAW -> Ref -> Selection RAW -instance KeyOf (Selection s) where+instance RenderGQL (Selection VALID) where+  render+    Selection+      { ..+      } =+      render (fromMaybe selectionName selectionAlias)+        <> renderArguments (elems selectionArguments)+        <> render selectionContent++instance KeyOf FieldName (Selection s) where   keyOf     Selection       { selectionName,@@ -223,12 +271,12 @@           | selectionName old == selectionName current = pure $ selectionName current           | otherwise =             failure $ mergeConflict path $-              GQLError-                { message =+              ValidationError+                { validationMessage =                     "" <> msg (selectionName old) <> " and " <> msg (selectionName current)                       <> " are different fields. "                       <> useDufferentAliases,-                  locations = [pos1, pos2]+                  validationLocations = [pos1, pos2]                 }         ---------------------         -- allias name is relevant only if they collide by allias like:@@ -243,16 +291,15 @@           | selectionArguments old == selectionArguments current = pure $ selectionArguments current           | otherwise =             failure $ mergeConflict currentPath $-              GQLError-                { message = "they have differing arguments. " <> useDufferentAliases,-                  locations = [pos1, pos2]+              ValidationError+                { validationMessage = "they have differing arguments. " <> useDufferentAliases,+                  validationLocations = [pos1, pos2]                 }   merge path _ _ =-    failure $ mergeConflict path $-      GQLError-        { message = "INTERNAL: can't merge. " <> useDufferentAliases,-          locations = []-        }+    failure $+      mergeConflict+        path+        ("INTERNAL: can't merge. " <> msgValidation useDufferentAliases :: ValidationError)  deriving instance Show (Selection a) @@ -272,16 +319,25 @@   }   deriving (Show, Lift) +instance RenderGQL (Operation VALID) where+  render+    Operation+      { operationName,+        operationType,+        operationSelection+      } =+      render operationType+        <> space+        <> render operationName+        <> space+        <> renderSelectionSet operationSelection+ getOperationName :: Maybe FieldName -> TypeName getOperationName = maybe "AnonymousOperation" (TypeName . readName) -getOperationDataType :: Failure GQLErrors m => Operation a -> Schema -> m (TypeDefinition OUT)+getOperationDataType :: Failure ValidationError m => Operation s -> Schema VALID -> m (TypeDefinition OBJECT VALID) getOperationDataType Operation {operationType = Query} lib = pure (query lib) getOperationDataType Operation {operationType = Mutation, operationPosition} lib =-  case mutation lib of-    Just x -> pure x-    Nothing -> failure $ mutationIsNotDefined operationPosition+  maybe (failure $ mutationIsNotDefined operationPosition) pure (mutation lib) getOperationDataType Operation {operationType = Subscription, operationPosition} lib =-  case subscription lib of-    Just x -> pure x-    Nothing -> failure $ subscriptionIsNotDefined operationPosition+  maybe (failure $ subscriptionIsNotDefined operationPosition) pure (subscription lib)
+ src/Data/Morpheus/Types/Internal/AST/Stage.hs view
@@ -0,0 +1,31 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE NoImplicitPrelude #-}++module Data.Morpheus.Types.Internal.AST.Stage+  ( CONST,+    VALID,+    RAW,+    Stage (..),+    CONST_OR_VALID,+  )+where++type CONST = 'CONST++type VALID = 'VALID++type RAW = 'RAW++data Stage+  = RAW+  | CONST+  | VALID++type family CONST_OR_VALID (a :: Stage) :: Stage++type instance CONST_OR_VALID RAW = CONST++type instance CONST_OR_VALID CONST = CONST++type instance CONST_OR_VALID VALID = VALID
src/Data/Morpheus/Types/Internal/AST/TH.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Types.Internal.AST.TH   ( ConsD (..),@@ -17,13 +18,23 @@     TypeRef (..),     hsTypeName,   )+import Data.Morpheus.Types.Internal.AST.Fields+  ( FieldDefinition (..),+    FieldsDefinition,+  ) import Data.Morpheus.Types.Internal.AST.TypeSystem   ( DataEnumValue (..),-    FieldDefinition (..),-    FieldsDefinition,   )+import Prelude+  ( (.),+    Bool (..),+    Show,+    all,+    fmap,+    null,+  ) -toHSFieldDefinition :: FieldDefinition cat -> FieldDefinition cat+toHSFieldDefinition :: FieldDefinition cat s -> FieldDefinition cat s toHSFieldDefinition field@FieldDefinition {fieldType = tyRef@TypeRef {typeConName}} =   field     { fieldType = tyRef {typeConName = hsTypeName typeConName}@@ -37,21 +48,21 @@  -- Template Haskell Types -data ConsD cat = ConsD+data ConsD cat s = ConsD   { cName :: TypeName,-    cFields :: [FieldDefinition cat]+    cFields :: [FieldDefinition cat s]   }   deriving (Show) -mkCons :: TypeName -> FieldsDefinition cat -> ConsD cat+mkCons :: TypeName -> FieldsDefinition cat s -> ConsD cat s mkCons typename fields =   ConsD     { cName = hsTypeName typename,-      cFields = map toHSFieldDefinition (elems fields)+      cFields = fmap toHSFieldDefinition (elems fields)     } -isEnum :: [ConsD cat] -> Bool+isEnum :: [ConsD cat s] -> Bool isEnum = all (null . cFields) -mkConsEnum :: DataEnumValue -> ConsD cat+mkConsEnum :: DataEnumValue s -> ConsD cat s mkConsEnum DataEnumValue {enumName} = ConsD {cName = hsTypeName enumName, cFields = []}
+ src/Data/Morpheus/Types/Internal/AST/TypeCategory.hs view
@@ -0,0 +1,133 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE NoImplicitPrelude #-}++module Data.Morpheus.Types.Internal.AST.TypeCategory+  ( TypeCategory,+    ELEM,+    OUT,+    IN,+    ANY,+    LEAF,+    OBJECT,+    IMPLEMENTABLE,+    fromAny,+    toAny,+    REQURE_IMPLEMENTABLE,+    ToCategory (..),+    FromCategory (..),+  )+where++import Data.Maybe (Maybe (..))+import Data.Morpheus.Types.Internal.AST.Base+  ( FALSE,+    TRUE,+  )+import Data.Morpheus.Types.Internal.AST.Stage (Stage)+import Prelude (Bool (..))++data TypeCategory+  = IN+  | OUT+  | ANY+  | LEAF+  | OBJECT+  | IMPLEMENTABLE++type IN = 'IN++type OUT = 'OUT++type ANY = 'ANY++type OBJECT = 'OBJECT++type IMPLEMENTABLE = 'IMPLEMENTABLE++type LEAF = 'LEAF++toAny ::+  (ToCategory a k ANY) =>+  a (k :: TypeCategory) (s :: Stage) ->+  a ANY s+toAny = toCategory++fromAny ::+  (FromCategory a ANY k) =>+  a ANY (s :: Stage) ->+  Maybe (a k s)+fromAny = fromCategory++class ToCategory a (k :: TypeCategory) (k' :: TypeCategory) where+  toCategory :: a k (s :: Stage) -> a k' s++class FromCategory a (k :: TypeCategory) (k' :: TypeCategory) where+  fromCategory :: a k (s :: Stage) -> Maybe (a k' s)++type family+  ELEM+    (elemKind :: TypeCategory)+    (setOfKind :: TypeCategory) ::+    Bool++type REQURE_IMPLEMENTABLE cat = ELEM cat IMPLEMENTABLE ~ TRUE++-- ANY+type instance ELEM ANY a = TRUE++type instance ELEM a ANY = TRUE++-- LEAF+type instance ELEM LEAF LEAF = TRUE++type instance ELEM LEAF IN = TRUE++type instance ELEM LEAF OUT = TRUE++type instance ELEM LEAF OBJECT = FALSE++type instance ELEM LEAF IMPLEMENTABLE = FALSE++-- IN+type instance ELEM IN IN = TRUE++type instance ELEM IN OUT = FALSE++type instance ELEM IN OBJECT = FALSE++type instance ELEM IN IMPLEMENTABLE = FALSE++-- OUT+type instance ELEM OUT OUT = TRUE++type instance ELEM OUT IN = FALSE++type instance ELEM OUT OBJECT = FALSE++type instance ELEM OUT IMPLEMENTABLE = FALSE++-- IMPLEMENTABLE+type instance ELEM IMPLEMENTABLE IMPLEMENTABLE = TRUE++type instance ELEM IMPLEMENTABLE OUT = TRUE++type instance ELEM IMPLEMENTABLE IN = FALSE++type instance ELEM IMPLEMENTABLE LEAF = FALSE++type instance ELEM IMPLEMENTABLE OBJECT = FALSE++-- OUTPUT_OBJECT+type instance ELEM OBJECT OBJECT = TRUE++type instance ELEM OBJECT IMPLEMENTABLE = TRUE++type instance ELEM OBJECT OUT = TRUE++type instance ELEM OBJECT IN = FALSE++type instance ELEM OBJECT LEAF = FALSE
src/Data/Morpheus/Types/Internal/AST/TypeSystem.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveLift #-} {-# LANGUAGE DeriveTraversable #-}@@ -16,164 +17,195 @@ {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Types.Internal.AST.TypeSystem-  ( Arguments,-    ScalarDefinition (..),+  ( ScalarDefinition (..),     DataEnum,-    FieldsDefinition,-    ArgumentDefinition,     DataUnion,-    ArgumentsDefinition (..),-    FieldDefinition (..),-    InputFieldsDefinition,     TypeContent (..),     TypeDefinition (..),     Schema (..),     DataEnumValue (..),     TypeLib,-    Directive (..),-    TypeUpdater,     TypeCategory,     DataInputUnion,-    Argument (..),-    Fields (..),-    createField,-    createArgument,-    createEnumType,+    mkEnumContent,+    mkUnionContent,+    mkType,     createScalarType,-    createType,-    createUnionType,-    createAlias,-    createInputUnionFields,-    createEnumValue,-    defineType,-    isTypeDefined,+    mkInputUnionFields,     initTypeLib,-    isFieldNullable,     insertType,-    fieldVisibility,     kindOf,-    toNullableField,-    toListField,     isEntNode,-    lookupDeprecated,-    lookupDeprecatedReason,     lookupWith,-    unsafeFromFields,     __inputname,     updateSchema,-    OUT,-    IN,-    ANY,-    FromAny (..),-    ToAny (..),-    DirectiveDefinitions,-    DirectiveDefinition (..),-    Directives,-    fieldsToArguments,-    FieldContent (..),-    fieldContentArgs,-    mkField,-    mkObjectField,     UnionMember (..),     mkUnionMember,+    RawTypeDefinition (..),+    RootOperationTypeDefinition (..),+    SchemaDefinition (..),+    buildSchema,+    Typed (Typed),+    untyped,+    typed,+    possibleTypes,+    possibleInterfaceTypes,   ) where -import Data.HashMap.Lazy-  ( HashMap,-    union,-  )-import qualified Data.HashMap.Lazy as HM-import Data.List (find) -- MORPHEUS -import Data.Morpheus.Error (globalErrorMessage)+import Control.Applicative ((<|>), Applicative (..))+import Control.Monad (Monad (..), foldM)+import Data.Either (Either (..))+import Data.Foldable (concatMap)+import Data.Functor ((<$>), fmap)+import Data.List (elem, filter, find, notElem)+import Data.Maybe (Maybe (..), catMaybes, mapMaybe, maybe) import Data.Morpheus.Error.NameCollision   ( NameCollision (..),   ) import Data.Morpheus.Error.Schema (nameCollisionError) import Data.Morpheus.Internal.Utils-  ( Collection (..),+  ( (<:>),+    Collection (..),+    Failure (..),     KeyOf (..),     Listable (..),     Merge (..),     Selectable (..),+    UpdateT (..),+    concatUpdates,     elems,+    resolveUpdates,   ) import Data.Morpheus.Rendering.RenderGQL   ( RenderGQL (..),-    renderIndent,+    newline,+    renderMembers,     renderObject,   ) import Data.Morpheus.Types.Internal.AST.Base   ( DataFingerprint (..),     Description,-    FALSE,     FieldName,     FieldName (..),-    GQLError (..),     Msg (..),-    Position,-    RESOLVED,-    Stage,+    OperationType (..),     TRUE,     Token,     TypeKind (..),     TypeName,     TypeRef (..),     TypeWrapper (..),-    VALID,-    isNullable,-    isSystemTypeName,+    ValidationError,+    ValidationErrors,+    isNotSystemTypeName,+    mkTypeRef,     msg,-    sysFields,+    msgValidation,     toFieldName,     toOperationType,   )-import Data.Morpheus.Types.Internal.AST.DirectiveLocation (DirectiveLocation)-import Data.Morpheus.Types.Internal.AST.OrderedMap-  ( OrderedMap,-    unsafeFromValues,+import Data.Morpheus.Types.Internal.AST.Fields+  ( Directive,+    DirectiveDefinition (..),+    Directives,+    FieldDefinition (..),+    FieldsDefinition,+    unsafeFromFields,   )-import Data.Morpheus.Types.Internal.AST.Value-  ( ScalarValue (..),-    ValidValue,-    Value (..),+import Data.Morpheus.Types.Internal.AST.OrdMap+  ( OrdMap,   )-import Data.Morpheus.Types.Internal.Resolving.Core-  ( Failure (..),-    LibUpdater,-    resolveUpdates,+import Data.Morpheus.Types.Internal.AST.SafeHashMap+  ( SafeHashMap,+    insert,   )+import Data.Morpheus.Types.Internal.AST.Stage+  ( CONST,+    Stage,+    VALID,+  )+import Data.Morpheus.Types.Internal.AST.TypeCategory+  ( ANY,+    ELEM,+    FromCategory (..),+    IMPLEMENTABLE,+    IN,+    LEAF,+    OBJECT,+    OUT,+    ToCategory (..),+    TypeCategory,+    fromAny,+    toAny,+  )+import Data.Morpheus.Types.Internal.AST.Value+  ( Value (..),+  ) import Data.Semigroup (Semigroup (..)) import Data.Text (intercalate) import Instances.TH.Lift () import Language.Haskell.TH.Syntax (Lift (..))+import Prelude+  ( ($),+    (.),+    Bool (..),+    Eq (..),+    Show (..),+    const,+    flip,+    otherwise,+  ) -type DataEnum = [DataEnumValue]+type DataEnum s = [DataEnumValue s] -mkUnionMember :: TypeName -> UnionMember cat+-- used for perserving type information from untyped values+-- e.g+-- unionType :: UnionMember IN VALID -> Typed IN VALID TypeName+-- unionType = typed memberName+typed :: (a c s -> b) -> a c s -> Typed c s b+typed f = Typed . f++untyped :: (a -> b) -> Typed c s a -> b+untyped f = f . _untyped++-- | used for perserving type information from untyped values+-- see function typed+newtype Typed (cat :: TypeCategory) (s :: Stage) a = Typed+  { _untyped :: a+  }++mkUnionMember :: TypeName -> UnionMember cat s mkUnionMember name = UnionMember name True -data UnionMember (cat :: TypeCategory) = UnionMember+data UnionMember (cat :: TypeCategory) (s :: Stage) = UnionMember   { memberName :: TypeName,     visibility :: Bool   }   deriving (Show, Lift, Eq) -type DataUnion = [UnionMember OUT]+type DataUnion s = [UnionMember OUT s] -type DataInputUnion = [UnionMember IN]+type DataInputUnion s = [UnionMember IN s] -instance RenderGQL (UnionMember cat) where+instance RenderGQL (UnionMember cat s) where   render = render . memberName +instance Msg (UnionMember cat s) where+  msg = msg . memberName++instance KeyOf TypeName (UnionMember cat s) where+  keyOf = memberName+ -- scalar ------------------------------------------------------------------ newtype ScalarDefinition = ScalarDefinition-  {validateValue :: ValidValue -> Either Token ValidValue}+  {validateValue :: Value VALID -> Either Token (Value VALID)}  instance Show ScalarDefinition where   show _ = "ScalarDefinition"@@ -181,79 +213,19 @@ instance Lift ScalarDefinition where   lift _ = [|ScalarDefinition pure|] -data Argument (valid :: Stage) = Argument-  { argumentName :: FieldName,-    argumentValue :: Value valid,-    argumentPosition :: Position-  }-  deriving (Show, Eq, Lift)--instance KeyOf (Argument stage) where-  keyOf = argumentName--instance NameCollision (Argument s) where-  nameCollision _ Argument {argumentName, argumentPosition} =-    GQLError-      { message = "There can Be only One Argument Named " <> msg argumentName,-        locations = [argumentPosition]-      }--type Arguments s = OrderedMap FieldName (Argument s)---- directive--------------------------------------------------------------------data Directive (s :: Stage) = Directive-  { directiveName :: FieldName,-    directivePosition :: Position,-    directiveArgs :: Arguments s-  }-  deriving (Show, Lift, Eq)--instance KeyOf (Directive s) where-  keyOf = directiveName--type Directives s = [Directive s]--data DirectiveDefinition = DirectiveDefinition-  { directiveDefinitionName :: FieldName,-    directiveDefinitionDescription :: Maybe Description,-    directiveDefinitionLocations :: [DirectiveLocation],-    directiveDefinitionArgs :: ArgumentsDefinition-  }-  deriving (Show, Lift)--type DirectiveDefinitions = [DirectiveDefinition]--instance KeyOf DirectiveDefinition where-  keyOf = directiveDefinitionName--instance Selectable DirectiveDefinition ArgumentDefinition where-  selectOr fb f key DirectiveDefinition {directiveDefinitionArgs} =-    selectOr fb f key directiveDefinitionArgs--lookupDeprecated :: [Directive VALID] -> Maybe (Directive VALID)-lookupDeprecated = find isDeprecation-  where-    isDeprecation Directive {directiveName = "deprecated"} = True-    isDeprecation _ = False--lookupDeprecatedReason :: Directive VALID -> Maybe Description-lookupDeprecatedReason Directive {directiveArgs} =-  selectOr Nothing (Just . maybeString) "reason" directiveArgs-  where-    maybeString :: Argument VALID -> Description-    maybeString Argument {argumentValue = (Scalar (String x))} = x-    maybeString _ = "can't read deprecated Reason Value"+#if MIN_VERSION_template_haskell(2,16,0)+  liftTyped _ = [||ScalarDefinition pure||]+#endif  -- ENUM VALUE-data DataEnumValue = DataEnumValue+data DataEnumValue s = DataEnumValue   { enumName :: TypeName,     enumDescription :: Maybe Description,-    enumDirectives :: [Directive VALID]+    enumDirectives :: [Directive s]   }   deriving (Show, Lift) -instance RenderGQL DataEnumValue where+instance RenderGQL (DataEnumValue s) where   render DataEnumValue {enumName} = render enumName  -- 3.2 Schema : https://graphql.github.io/graphql-spec/June2018/#sec-Schema@@ -264,47 +236,195 @@ -- RootOperationTypeDefinition : --    OperationType: NamedType -data Schema = Schema-  { types :: TypeLib,-    query :: TypeDefinition 'Out,-    mutation :: Maybe (TypeDefinition 'Out),-    subscription :: Maybe (TypeDefinition 'Out)+data Schema (s :: Stage) = Schema+  { types :: TypeLib s,+    query :: TypeDefinition OBJECT s,+    mutation :: Maybe (TypeDefinition OBJECT s),+    subscription :: Maybe (TypeDefinition OBJECT s),+    directiveDefinitions :: [DirectiveDefinition s]   }+  deriving (Show, Lift)++instance Merge (Schema s) where+  merge _ s1 s2 =+    Schema+      <$> (types s1 <:> types s2)+      <*> mergeOperation (query s1) (query s2)+      <*> mergeOptional (mutation s1) (mutation s2)+      <*> mergeOptional (subscription s1) (subscription s2)+      <*> pure (directiveDefinitions s1 <> directiveDefinitions s2)++mergeOptional ::+  (Monad m, Failure ValidationErrors m) =>+  Maybe (TypeDefinition OBJECT s) ->+  Maybe (TypeDefinition OBJECT s) ->+  m (Maybe (TypeDefinition OBJECT s))+mergeOptional Nothing y = pure y+mergeOptional (Just x) Nothing = pure (Just x)+mergeOptional (Just x) (Just y) = Just <$> mergeOperation x y++mergeOperation ::+  (Monad m, Failure ValidationErrors m) =>+  TypeDefinition OBJECT s ->+  TypeDefinition OBJECT s ->+  m (TypeDefinition OBJECT s)+mergeOperation+  TypeDefinition {typeContent = DataObject i1 fields1}+  TypeDefinition {typeContent = DataObject i2 fields2, ..} =+    do+      fields <- fields1 <:> fields2+      pure $ TypeDefinition {typeContent = DataObject (i1 <> i2) fields, ..}++data SchemaDefinition = SchemaDefinition+  { schemaDirectives :: Directives CONST,+    unSchemaDefinition :: OrdMap OperationType RootOperationTypeDefinition+  }   deriving (Show) -type TypeLib = HashMap TypeName (TypeDefinition ANY)+instance Selectable OperationType RootOperationTypeDefinition SchemaDefinition where+  selectOr fallback f key SchemaDefinition {unSchemaDefinition} =+    selectOr fallback f key unSchemaDefinition -instance Selectable Schema (TypeDefinition ANY) where+instance NameCollision SchemaDefinition where+  nameCollision _ = "There can Be only One SchemaDefinition."++instance KeyOf TypeName SchemaDefinition where+  keyOf _ = "schema"++data RawTypeDefinition+  = RawSchemaDefinition SchemaDefinition+  | RawTypeDefinition (TypeDefinition ANY CONST)+  | RawDirectiveDefinition (DirectiveDefinition CONST)+  deriving (Show)++data RootOperationTypeDefinition = RootOperationTypeDefinition+  { rootOperationType :: OperationType,+    rootOperationTypeDefinitionName :: TypeName+  }+  deriving (Show, Eq)++instance NameCollision RootOperationTypeDefinition where+  nameCollision RootOperationTypeDefinition {rootOperationType} =+    "There can Be only One TypeDefinition for schema." <> msgValidation rootOperationType++instance KeyOf OperationType RootOperationTypeDefinition where+  keyOf = rootOperationType++type TypeLib 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) -instance Listable (TypeDefinition ANY) Schema where-  elems = HM.elems . typeRegister-  fromElems types = case popByKey "Query" types of-    (Nothing, _) -> failure (globalErrorMessage "INTERNAL: Query Not Defined")-    (Just query, lib1) -> do-      let (mutation, lib2) = popByKey "Mutation" lib1-      let (subscription, lib3) = popByKey "Subscription" lib2-      pure $ (foldr defineType (initTypeLib query) lib3) {mutation, subscription}+instance Listable (TypeDefinition ANY s) (Schema s) where+  elems Schema {..} =+    elems types+      <> concatMap fromOperation [Just query, mutation, subscription]+  fromElems types =+    traverse3+      (popByKey types)+      ( RootOperationTypeDefinition Query "Query",+        RootOperationTypeDefinition Mutation "Mutation",+        RootOperationTypeDefinition Subscription "Subscription"+      )+      >>= buildWith types -initTypeLib :: TypeDefinition 'Out -> Schema+buildWith ::+  ( Monad f,+    Failure ValidationErrors f+  ) =>+  [TypeDefinition cat s] ->+  ( Maybe (TypeDefinition OBJECT s),+    Maybe (TypeDefinition OBJECT s),+    Maybe (TypeDefinition OBJECT s)+  ) ->+  f (Schema s)+buildWith otypes (Just query, mutation, subscription) = do+  let types = excludeTypes [Just query, mutation, subscription] otypes+  let schema = (initTypeLib query) {mutation, subscription}+  foldM (flip safeDefineType) schema types+buildWith _ (Nothing, _, _) = failure ["Query root type must be provided." :: ValidationError]++excludeTypes :: [Maybe (TypeDefinition c1 s)] -> [TypeDefinition c2 s] -> [TypeDefinition c2 s]+excludeTypes excusionTypes = filter ((`notElem` blacklist) . typeName)+  where+    blacklist :: [TypeName]+    blacklist = fmap typeName (catMaybes excusionTypes)++withDirectives ::+  [DirectiveDefinition s] ->+  Schema s ->+  Schema s+withDirectives dirs Schema {..} =+  Schema+    { directiveDefinitions = directiveDefinitions <> dirs,+      ..+    }++buildSchema ::+  (Monad m, Failure ValidationErrors m) =>+  ( Maybe SchemaDefinition,+    [TypeDefinition ANY s],+    [DirectiveDefinition s]+  ) ->+  m (Schema s)+buildSchema (Nothing, types, dirs) = withDirectives dirs <$> fromElems types+buildSchema (Just schemaDef, types, dirs) =+  withDirectives+    dirs+    <$> ( traverse3 selectOp (Query, Mutation, Subscription)+            >>= buildWith types+        )+  where+    selectOp op = selectOperation schemaDef op types++traverse3 :: Applicative t => (a -> t b) -> (a, a, a) -> t (b, b, b)+traverse3 f (a1, a2, a3) = (,,) <$> f a1 <*> f a2 <*> f a3++typeReference ::+  (Monad m, Failure ValidationErrors m) =>+  [TypeDefinition ANY s] ->+  RootOperationTypeDefinition ->+  m (Maybe (TypeDefinition OBJECT s))+typeReference types rootOperation =+  popByKey types rootOperation+    >>= maybe+      (failure ["Unknown type " <> msgValidation (rootOperationTypeDefinitionName rootOperation) <> "."])+      (pure . Just)++selectOperation ::+  ( Monad f,+    Failure ValidationErrors f+  ) =>+  SchemaDefinition ->+  OperationType ->+  [TypeDefinition ANY s] ->+  f (Maybe (TypeDefinition OBJECT s))+selectOperation schemaDef operationType lib =+  selectOr (pure Nothing) (typeReference lib) operationType schemaDef++initTypeLib :: TypeDefinition OBJECT s -> Schema s initTypeLib query =   Schema     { types = empty,       query = query,       mutation = Nothing,-      subscription = Nothing+      subscription = Nothing,+      directiveDefinitions = empty     } -typeRegister :: Schema -> TypeLib-typeRegister Schema {types, query, mutation, subscription} =-  types-    `union` HM.fromList-      (concatMap fromOperation [Just query, mutation, subscription])+isType :: TypeName -> TypeDefinition OBJECT s -> Maybe (TypeDefinition ANY s)+isType name x+  | name == typeName x = Just (toAny x)+  | otherwise = Nothing -lookupDataType :: TypeName -> Schema -> Maybe (TypeDefinition ANY)-lookupDataType name = HM.lookup name . typeRegister+lookupDataType :: TypeName -> Schema s -> Maybe (TypeDefinition ANY s)+lookupDataType name Schema {types, query, mutation, subscription} =+  isType name query+    <|> (mutation >>= isType name)+    <|> (subscription >>= isType name)+    <|> selectOr Nothing Just name types -isTypeDefined :: TypeName -> Schema -> Maybe DataFingerprint+isTypeDefined :: TypeName -> Schema s -> Maybe DataFingerprint isTypeDefined name lib = typeFingerprint <$> lookupDataType name lib  -- 3.4 Types : https://graphql.github.io/graphql-spec/June2018/#sec-Types@@ -317,123 +437,142 @@ --   EnumTypeDefinition --   InputObjectTypeDefinition -data TypeDefinition (a :: TypeCategory) = TypeDefinition+data TypeDefinition (a :: TypeCategory) (s :: Stage) = TypeDefinition   { typeName :: TypeName,     typeFingerprint :: DataFingerprint,     typeDescription :: Maybe Description,-    typeDirectives :: Directives VALID,-    typeContent :: TypeContent TRUE a+    typeDirectives :: Directives s,+    typeContent :: TypeContent TRUE a s   }   deriving (Show, Lift) -instance KeyOf (TypeDefinition a) where-  type KEY (TypeDefinition a) = TypeName+instance KeyOf TypeName (TypeDefinition a s) where   keyOf = typeName -data TypeCategory = In | Out | Any--type IN = 'In--type OUT = 'Out--type ANY = 'Any--class ToAny a where-  toAny :: a (k :: TypeCategory) -> a ANY--instance ToAny TypeDefinition where-  toAny TypeDefinition {typeContent, ..} = TypeDefinition {typeContent = toAny typeContent, ..}+instance NameCollision (TypeDefinition cat s) where+  nameCollision x = "There can Be only One TypeDefinition Named " <> msgValidation (typeName x) <> "." -instance ToAny (TypeContent TRUE) where-  toAny DataScalar {..} = DataScalar {..}-  toAny DataEnum {..} = DataEnum {..}-  toAny DataInputObject {..} = DataInputObject {..}-  toAny DataInputUnion {..} = DataInputUnion {..}-  toAny DataObject {..} = DataObject {..}-  toAny DataUnion {..} = DataUnion {..}-  toAny DataInterface {..} = DataInterface {..}+instance+  ToCategory (TypeContent TRUE) cat cat' =>+  ToCategory TypeDefinition cat cat'+  where+  toCategory TypeDefinition {typeContent, ..} =+    TypeDefinition+      { typeContent = toCategory typeContent,+        ..+      } -instance ToAny FieldDefinition where-  toAny FieldDefinition {fieldContent, ..} = FieldDefinition {fieldContent = toAny <$> fieldContent, ..}+possibleTypes :: TypeDefinition a s -> Schema s' -> [TypeName]+possibleTypes+  TypeDefinition+    { typeName,+      typeContent = DataObject {objectImplements}+    }+  _ = typeName : objectImplements+possibleTypes TypeDefinition {typeName = name, typeContent = DataInterface {}} schema =+  name : fmap typeName (possibleInterfaceTypes name schema)+possibleTypes TypeDefinition {typeName} _ = [typeName] -instance ToAny (FieldContent TRUE) where-  toAny (FieldArgs x) = FieldArgs x-  toAny (DefaultInputValue x) = DefaultInputValue x+possibleInterfaceTypes ::+  TypeName ->+  Schema s ->+  [TypeDefinition ANY s]+possibleInterfaceTypes name schema = mapMaybe (isPosibleInterfaceType name) (elems schema) -class FromAny a (k :: TypeCategory) where-  fromAny :: a ANY -> Maybe (a k)+isPosibleInterfaceType ::+  TypeName ->+  TypeDefinition c s ->+  Maybe (TypeDefinition c s)+isPosibleInterfaceType name typeDef@TypeDefinition {typeName, typeContent = DataObject {objectImplements}}+  | name `elem` (typeName : objectImplements) = Just typeDef+isPosibleInterfaceType _ _ = Nothing -instance (FromAny (TypeContent TRUE) a) => FromAny TypeDefinition a where-  fromAny TypeDefinition {typeContent, ..} = bla <$> fromAny typeContent+instance+  (FromCategory (TypeContent TRUE) cat cat') =>+  FromCategory TypeDefinition cat cat'+  where+  fromCategory TypeDefinition {typeContent, ..} = bla <$> fromCategory typeContent     where       bla x = TypeDefinition {typeContent = x, ..} -instance FromAny (TypeContent TRUE) IN where-  fromAny DataScalar {..} = Just DataScalar {..}-  fromAny DataEnum {..} = Just DataEnum {..}-  fromAny DataInputObject {..} = Just DataInputObject {..}-  fromAny DataInputUnion {..} = Just DataInputUnion {..}-  fromAny _ = Nothing--instance FromAny (TypeContent TRUE) OUT where-  fromAny DataScalar {..} = Just DataScalar {..}-  fromAny DataEnum {..} = Just DataEnum {..}-  fromAny DataObject {..} = Just DataObject {..}-  fromAny DataUnion {..} = Just DataUnion {..}-  fromAny DataInterface {..} = Just DataInterface {..}-  fromAny _ = Nothing--type family IsSelected (c :: TypeCategory) (a :: TypeCategory) :: Bool--type instance IsSelected ANY a = TRUE--type instance IsSelected OUT OUT = TRUE--type instance IsSelected IN IN = TRUE--type instance IsSelected IN OUT = FALSE--type instance IsSelected OUT IN = FALSE--type instance IsSelected a ANY = TRUE--data TypeContent (b :: Bool) (a :: TypeCategory) where+data+  TypeContent+    (b :: Bool)+    (a :: TypeCategory)+    (s :: Stage)+  where   DataScalar ::     { dataScalar :: ScalarDefinition     } ->-    TypeContent TRUE a+    TypeContent (ELEM LEAF a) a s   DataEnum ::-    { enumMembers :: DataEnum+    { enumMembers :: DataEnum s     } ->-    TypeContent TRUE a+    TypeContent (ELEM LEAF a) a s   DataInputObject ::-    { inputObjectFields :: FieldsDefinition IN+    { inputObjectFields :: FieldsDefinition IN s     } ->-    TypeContent (IsSelected a IN) a+    TypeContent (ELEM IN a) a s   DataInputUnion ::-    { inputUnionMembers :: DataInputUnion+    { inputUnionMembers :: DataInputUnion s     } ->-    TypeContent (IsSelected a IN) a+    TypeContent (ELEM IN a) a s   DataObject ::     { objectImplements :: [TypeName],-      objectFields :: FieldsDefinition OUT+      objectFields :: FieldsDefinition OUT s     } ->-    TypeContent (IsSelected a OUT) a+    TypeContent (ELEM OBJECT a) a s   DataUnion ::-    { unionMembers :: DataUnion+    { unionMembers :: DataUnion s     } ->-    TypeContent (IsSelected a OUT) a+    TypeContent (ELEM OUT a) a s   DataInterface ::-    { interfaceFields :: FieldsDefinition OUT+    { interfaceFields :: FieldsDefinition OUT s     } ->-    TypeContent (IsSelected a OUT) a+    TypeContent (ELEM IMPLEMENTABLE a) a s -deriving instance Show (TypeContent a b)+deriving instance Show (TypeContent a b s) -deriving instance Lift (TypeContent a b)+deriving instance Lift (TypeContent a b s) -createType :: TypeName -> TypeContent TRUE a -> TypeDefinition a-createType typeName typeContent =+instance ToCategory (TypeContent TRUE) a ANY where+  toCategory DataScalar {..} = DataScalar {..}+  toCategory DataEnum {..} = DataEnum {..}+  toCategory DataInputObject {..} = DataInputObject {..}+  toCategory DataInputUnion {..} = DataInputUnion {..}+  toCategory DataObject {..} = DataObject {..}+  toCategory DataUnion {..} = DataUnion {..}+  toCategory DataInterface {..} = DataInterface {..}++instance ToCategory (TypeContent TRUE) OBJECT IMPLEMENTABLE where+  toCategory DataObject {..} = DataObject {..}++instance FromCategory (TypeContent TRUE) ANY IN where+  fromCategory DataScalar {..} = Just DataScalar {..}+  fromCategory DataEnum {..} = Just DataEnum {..}+  fromCategory DataInputObject {..} = Just DataInputObject {..}+  fromCategory DataInputUnion {..} = Just DataInputUnion {..}+  fromCategory _ = Nothing++instance FromCategory (TypeContent TRUE) ANY OUT where+  fromCategory DataScalar {..} = Just DataScalar {..}+  fromCategory DataEnum {..} = Just DataEnum {..}+  fromCategory DataObject {..} = Just DataObject {..}+  fromCategory DataUnion {..} = Just DataUnion {..}+  fromCategory DataInterface {..} = Just DataInterface {..}+  fromCategory _ = Nothing++instance FromCategory (TypeContent TRUE) ANY OBJECT where+  fromCategory DataObject {..} = Just DataObject {..}+  fromCategory _ = Nothing++instance FromCategory (TypeContent TRUE) ANY IMPLEMENTABLE where+  fromCategory DataObject {..} = Just DataObject {..}+  fromCategory DataInterface {..} = Just DataInterface {..}+  fromCategory _ = Nothing++mkType :: TypeName -> TypeContent TRUE a s -> TypeDefinition a s+mkType typeName typeContent =   TypeDefinition     { typeName,       typeDescription = Nothing,@@ -442,31 +581,29 @@       typeContent     } -createScalarType :: TypeName -> TypeDefinition a-createScalarType typeName = createType typeName $ DataScalar (ScalarDefinition pure)+createScalarType :: ELEM LEAF a ~ TRUE => TypeName -> TypeDefinition a s+createScalarType typeName = mkType typeName $ DataScalar (ScalarDefinition pure) -createEnumType :: TypeName -> [TypeName] -> TypeDefinition a-createEnumType typeName typeData = createType typeName (DataEnum enumValues)-  where-    enumValues = map createEnumValue typeData+mkEnumContent :: ELEM LEAF a ~ TRUE => [TypeName] -> TypeContent TRUE a s+mkEnumContent typeData = DataEnum (fmap mkEnumValue typeData) -createEnumValue :: TypeName -> DataEnumValue-createEnumValue enumName =+mkUnionContent :: [TypeName] -> TypeContent TRUE OUT s+mkUnionContent typeData = DataUnion $ fmap mkUnionMember typeData++mkEnumValue :: TypeName -> DataEnumValue s+mkEnumValue enumName =   DataEnumValue     { enumName,       enumDescription = Nothing,       enumDirectives = []     } -createUnionType :: TypeName -> [TypeName] -> TypeDefinition OUT-createUnionType typeName typeData = createType typeName (DataUnion $ map mkUnionMember typeData)--isEntNode :: TypeContent TRUE a -> Bool+isEntNode :: TypeContent TRUE a s -> Bool isEntNode DataScalar {} = True isEntNode DataEnum {} = True isEntNode _ = False -kindOf :: TypeDefinition a -> TypeKind+kindOf :: TypeDefinition a s -> TypeKind kindOf TypeDefinition {typeName, typeContent} = __kind typeContent   where     __kind DataScalar {} = KindScalar@@ -477,268 +614,95 @@     __kind DataInputUnion {} = KindInputUnion     __kind DataInterface {} = KindInterface -fromOperation :: Maybe (TypeDefinition OUT) -> [(TypeName, TypeDefinition ANY)]-fromOperation (Just datatype) = [(typeName datatype, toAny datatype)]+fromOperation :: Maybe (TypeDefinition OBJECT s) -> [TypeDefinition ANY s]+fromOperation (Just datatype) = [toAny datatype] fromOperation Nothing = [] -defineType :: TypeDefinition cat -> Schema -> Schema-defineType dt@TypeDefinition {typeName, typeContent = DataInputUnion enumKeys, typeFingerprint} lib =-  lib {types = HM.insert name unionTags (HM.insert typeName (toAny dt) (types lib))}+safeDefineType ::+  ( Monad m,+    Failure ValidationErrors m+  ) =>+  TypeDefinition cat s ->+  Schema s ->+  m (Schema s)+safeDefineType dt@TypeDefinition {typeName, typeContent = DataInputUnion enumKeys, typeFingerprint} lib = do+  types <- insert unionTags (types lib) >>= insert (toAny dt)+  pure lib {types}   where-    name = typeName <> "Tags"     unionTags =       TypeDefinition-        { typeName = name,+        { typeName = typeName <> "Tags",           typeFingerprint,           typeDescription = Nothing,           typeDirectives = [],-          typeContent = DataEnum $ map (createEnumValue . memberName) enumKeys+          typeContent = mkEnumContent (fmap memberName enumKeys)         }-defineType datatype lib =-  lib {types = HM.insert (typeName datatype) (toAny datatype) (types lib)}+safeDefineType datatype lib = do+  types <- insert (toAny datatype) (types lib)+  pure lib {types}  insertType ::-  TypeDefinition ANY ->-  TypeUpdater-insertType datatype@TypeDefinition {typeName} lib = case isTypeDefined typeName lib of-  Nothing -> resolveUpdates (defineType datatype lib) []-  Just fingerprint-    | fingerprint == typeFingerprint datatype -> return lib-    -- throw error if 2 different types has same name-    | otherwise -> failure $ nameCollisionError typeName+  (Monad m, Failure ValidationErrors m) =>+  TypeDefinition cat s ->+  UpdateT m (Schema s)+insertType datatype@TypeDefinition {typeName, typeFingerprint} =+  updateSchema typeName typeFingerprint [] (const datatype) ()  updateSchema ::+  (Monad m, Failure ValidationErrors m) =>   TypeName ->   DataFingerprint ->-  [TypeUpdater] ->-  (a -> TypeDefinition cat) ->+  [UpdateT m (Schema s)] ->+  (a -> TypeDefinition cat s) ->   a ->-  TypeUpdater-updateSchema name fingerprint stack f x lib =-  case isTypeDefined name lib of-    Nothing ->-      resolveUpdates-        (defineType (f x) lib)-        stack-    Just fingerprint' | fingerprint' == fingerprint -> return lib-    -- throw error if 2 different types has same name-    Just _ -> failure $ nameCollisionError name+  UpdateT m (Schema s)+updateSchema name fingerprint stack f x+  | isNotSystemTypeName name = UpdateT $ \lib ->+    case isTypeDefined name lib of+      Nothing -> do+        t <- safeDefineType (f x) lib+        resolveUpdates t stack+      Just fingerprint' | fingerprint' == fingerprint -> pure lib+      -- throw error if 2 different types has same name+      Just _ -> failure [nameCollisionError name]+  | otherwise = concatUpdates stack  lookupWith :: Eq k => (a -> k) -> k -> [a] -> Maybe a lookupWith f key = find ((== key) . f) --- lookups and removes TypeDefinition from hashmap-popByKey :: TypeName -> [TypeDefinition ANY] -> (Maybe (TypeDefinition OUT), [TypeDefinition ANY])-popByKey name types = case lookupWith typeName name types of+popByKey ::+  (Applicative m, Failure ValidationErrors m) =>+  [TypeDefinition ANY s] ->+  RootOperationTypeDefinition ->+  m (Maybe (TypeDefinition OBJECT s))+popByKey types (RootOperationTypeDefinition opType name) = case lookupWith typeName name types of   Just dt@TypeDefinition {typeContent = DataObject {}} ->-    (fromAny dt, filter ((/= name) . typeName) types)-  _ -> (Nothing, types)--newtype Fields def = Fields-  {unFields :: OrderedMap FieldName def}-  deriving-    ( Show,-      Lift,-      Functor,-      Foldable,-      Traversable-    )--deriving instance (KEY def ~ FieldName, KeyOf def) => Collection def (Fields def)--instance Merge (FieldsDefinition cat) where-  merge path (Fields x) (Fields y) = Fields <$> merge path x y--instance Selectable (Fields (FieldDefinition cat)) (FieldDefinition cat) where-  selectOr fb f name (Fields lib) = selectOr fb f name lib--unsafeFromFields :: [FieldDefinition cat] -> FieldsDefinition cat-unsafeFromFields = Fields . unsafeFromValues--fieldsToArguments :: FieldsDefinition IN -> ArgumentsDefinition-fieldsToArguments = ArgumentsDefinition Nothing . unFields--instance (KEY def ~ FieldName, KeyOf def, NameCollision def) => Listable def (Fields def) where-  fromElems = fmap Fields . fromElems-  elems = elems . unFields---- 3.6 Objects : https://graphql.github.io/graphql-spec/June2018/#sec-Objects----------------------------------------------------------------------------------  ObjectTypeDefinition:---    Description(opt) type Name ImplementsInterfaces(opt) Directives(Const)(opt) FieldsDefinition(opt)------  ImplementsInterfaces---    implements &(opt) NamedType---    ImplementsInterfaces & NamedType------  FieldsDefinition---    { FieldDefinition(list) }----type FieldsDefinition cat = Fields (FieldDefinition cat)----  FieldDefinition---    Description(opt) Name ArgumentsDefinition(opt) : Type Directives(Const)(opt)------ https://spec.graphql.org/June2018/#InputValueDefinition--- InputValueDefinition---   Description(opt) Name: Type DefaultValue(opt) Directives[Const](opt)--data FieldDefinition (cat :: TypeCategory) = FieldDefinition-  { fieldName :: FieldName,-    fieldDescription :: Maybe Description,-    fieldType :: TypeRef,-    fieldContent :: Maybe (FieldContent TRUE cat),-    fieldDirectives :: [Directive VALID]-  }-  deriving (Show, Lift)--data FieldContent (bool :: Bool) (cat :: TypeCategory) where-  DefaultInputValue ::-    { defaultInputValue :: Value RESOLVED-    } ->-    FieldContent (IsSelected cat IN) cat-  FieldArgs ::-    { fieldArgsDef :: ArgumentsDefinition-    } ->-    FieldContent (IsSelected cat OUT) cat--fieldContentArgs :: FieldContent b cat -> OrderedMap FieldName ArgumentDefinition-fieldContentArgs (FieldArgs (ArgumentsDefinition _ argsD)) = argsD-fieldContentArgs _ = empty--deriving instance Show (FieldContent bool cat)--deriving instance Lift (FieldContent bool cat)--instance KeyOf (FieldDefinition cat) where-  keyOf = fieldName--instance Selectable (FieldDefinition OUT) ArgumentDefinition where-  selectOr fb f key FieldDefinition {fieldContent = Just (FieldArgs args)} = selectOr fb f key args-  selectOr fb _ _ _ = fb--instance NameCollision (FieldDefinition cat) where-  nameCollision name _ =-    GQLError-      { message = "There can Be only One field Named " <> msg name,-        locations = []-      }--instance RenderGQL (FieldDefinition cat) where-  render FieldDefinition {fieldName = FieldName name, fieldType, fieldContent = Just (FieldArgs args)} =-    name <> render args <> ": " <> render fieldType-  render FieldDefinition {fieldName = FieldName name, fieldType} =-    name <> ": " <> render fieldType--instance RenderGQL (FieldsDefinition OUT) where-  render = renderObject render . ignoreHidden . elems--instance RenderGQL (FieldsDefinition IN) where-  render = renderObject render . ignoreHidden . elems--fieldVisibility :: FieldDefinition cat -> Bool-fieldVisibility FieldDefinition {fieldName} = fieldName `notElem` sysFields--isFieldNullable :: FieldDefinition cat -> Bool-isFieldNullable = isNullable . fieldType--createField :: Maybe (FieldContent TRUE cat) -> FieldName -> ([TypeWrapper], TypeName) -> FieldDefinition cat-createField fieldContent fieldName (typeWrappers, typeConName) =-  FieldDefinition-    { fieldName,-      fieldContent,-      fieldDescription = Nothing,-      fieldType = TypeRef {typeConName, typeWrappers, typeArgs = Nothing},-      fieldDirectives = []-    }--mkField :: FieldName -> ([TypeWrapper], TypeName) -> FieldDefinition cat-mkField = createField Nothing--mkObjectField :: ArgumentsDefinition -> FieldName -> ([TypeWrapper], TypeName) -> FieldDefinition OUT-mkObjectField args = createField (Just $ FieldArgs args)--toNullableField :: FieldDefinition cat -> FieldDefinition cat-toNullableField dataField-  | isNullable (fieldType dataField) = dataField-  | otherwise = dataField {fieldType = nullable (fieldType dataField)}-  where-    nullable alias@TypeRef {typeWrappers} =-      alias {typeWrappers = TypeMaybe : typeWrappers}--toListField :: FieldDefinition cat -> FieldDefinition cat-toListField dataField = dataField {fieldType = listW (fieldType dataField)}-  where-    listW alias@TypeRef {typeWrappers} =-      alias {typeWrappers = TypeList : typeWrappers}---- 3.10 Input Objects: https://spec.graphql.org/June2018/#sec-Input-Objects------------------------------------------------------------------------------- InputObjectTypeDefinition--- Description(opt) input Name Directives(const,opt) InputFieldsDefinition(opt)------- InputFieldsDefinition--- { InputValueDefinition(list) }--type InputFieldsDefinition = Fields InputValueDefinition--type InputValueDefinition = FieldDefinition IN---- 3.6.1 Field Arguments : https://graphql.github.io/graphql-spec/June2018/#sec-Field-Arguments--------------------------------------------------------------------------------------------------- ArgumentsDefinition:---   (InputValueDefinition(list))--data ArgumentsDefinition = ArgumentsDefinition-  { argumentsTypename :: Maybe TypeName,-    arguments :: OrderedMap FieldName ArgumentDefinition-  }-  deriving (Show, Lift)--instance RenderGQL ArgumentsDefinition where-  render ArgumentsDefinition {arguments}-    | null arguments =-      ""-    | otherwise = "(" <> intercalate ", " (map render $ elems arguments) <> ")"--type ArgumentDefinition = FieldDefinition IN--instance Selectable ArgumentsDefinition ArgumentDefinition where-  selectOr fb f key (ArgumentsDefinition _ args) = selectOr fb f key args--instance Collection ArgumentDefinition ArgumentsDefinition where-  empty = ArgumentsDefinition Nothing empty-  singleton = ArgumentsDefinition Nothing . singleton--instance Listable ArgumentDefinition ArgumentsDefinition where-  elems (ArgumentsDefinition _ args) = elems args-  fromElems args = ArgumentsDefinition Nothing <$> fromElems args--createArgument :: FieldName -> ([TypeWrapper], TypeName) -> FieldDefinition IN-createArgument = mkField---- https://spec.graphql.org/June2018/#InputValueDefinition--- InputValueDefinition---   Description(opt) Name: TypeDefaultValue(opt) Directives[Const](opt)--- TODO: implement inputValue+    pure (fromAny dt)+  Just {} ->+    failure+      [ msgValidation (show opType)+          <> " root type must be Object type if provided, it cannot be "+          <> msgValidation name+      ]+  _ -> pure Nothing  __inputname :: FieldName __inputname = "inputname" -createInputUnionFields :: TypeName -> [UnionMember IN] -> [FieldDefinition IN]-createInputUnionFields name members = fieldTag : map unionField members+mkInputUnionFields :: TypeName -> [UnionMember IN s] -> FieldsDefinition IN s+mkInputUnionFields name members = unsafeFromFields $ fieldTag : fmap mkUnionField members   where     fieldTag =       FieldDefinition         { fieldName = __inputname,           fieldDescription = Nothing,           fieldContent = Nothing,-          fieldType = createAlias (name <> "Tags"),+          fieldType = mkTypeRef (name <> "Tags"),           fieldDirectives = []         } -unionField :: UnionMember IN -> FieldDefinition IN-unionField UnionMember {memberName} =+mkUnionField :: UnionMember IN s -> FieldDefinition IN s+mkUnionField UnionMember {memberName} =   FieldDefinition     { fieldName = toFieldName memberName,       fieldDescription = Nothing,@@ -756,35 +720,24 @@ -- OTHER -------------------------------------------------------------------------------------------------- -createAlias :: TypeName -> TypeRef-createAlias typeConName =-  TypeRef {typeConName, typeWrappers = [], typeArgs = Nothing}--type TypeUpdater = LibUpdater Schema--instance RenderGQL Schema where-  render schema = intercalate "\n\n" $ map render visibleTypes+instance RenderGQL (Schema s) where+  render schema = intercalate newline (fmap render visibleTypes)     where-      visibleTypes = filter (not . isSystemTypeName . typeName) (elems schema)+      visibleTypes = filter (isNotSystemTypeName . typeName) (elems schema) -instance RenderGQL (TypeDefinition a) where-  render TypeDefinition {typeName, typeContent} = __render typeContent+instance RenderGQL (TypeDefinition a s) where+  render TypeDefinition {typeName, typeContent} = __render typeContent <> newline     where       __render DataInterface {interfaceFields} = "interface " <> render typeName <> render interfaceFields       __render DataScalar {} = "scalar " <> render typeName-      __render (DataEnum tags) = "enum " <> render typeName <> renderObject render tags+      __render (DataEnum tags) = "enum " <> render typeName <> renderObject tags       __render (DataUnion members) =         "union "           <> render typeName-          <> " =\n    "-          <> intercalate ("\n" <> renderIndent <> "| ") (map render members)+          <> " = "+          <> renderMembers members       __render (DataInputObject fields) = "input " <> render typeName <> render fields-      __render (DataInputUnion members) = "input " <> render typeName <> render fieldsDef+      __render (DataInputUnion members) = "input " <> render typeName <> render fields         where-          fieldsDef = unsafeFromFields fields-          fields :: [FieldDefinition IN]-          fields = createInputUnionFields typeName members+          fields = mkInputUnionFields typeName members       __render DataObject {objectFields} = "type " <> render typeName <> render objectFields--ignoreHidden :: [FieldDefinition cat] -> [FieldDefinition cat]-ignoreHidden = filter fieldVisibility
src/Data/Morpheus/Types/Internal/AST/Value.hs view
@@ -1,14 +1,17 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DeriveLift #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-}+{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Types.Internal.AST.Value   ( Value (..),@@ -30,6 +33,10 @@   ) where +-- MORPHEUS++import Control.Applicative (pure)+import Control.Monad.Fail (MonadFail (fail)) import qualified Data.Aeson as A   ( (.=),     FromJSON (..),@@ -38,10 +45,13 @@     object,     pairs,   )+import Data.Either (Either (..))+import Data.Foldable (foldl, foldl1, null)+import Data.Functor (fmap) import qualified Data.HashMap.Strict as M   ( toList,   )--- MORPHEUS+import Data.Maybe (Maybe (..)) import Data.Morpheus.Error.NameCollision   ( NameCollision (..),   )@@ -54,22 +64,25 @@ import Data.Morpheus.Types.Internal.AST.Base   ( FieldName,     FieldName (..),-    GQLError (..),     Msg (..),     Position,-    RAW,-    RESOLVED,     Ref (..),-    Stage,     TypeName (..),     TypeRef,-    TypeRef (..),-    VALID,+    ValidationError (..),+    msgValidation,   )-import Data.Morpheus.Types.Internal.AST.OrderedMap-  ( OrderedMap,+import Data.Morpheus.Types.Internal.AST.OrdMap+  ( OrdMap,     unsafeFromValues,   )+import Data.Morpheus.Types.Internal.AST.Stage+  ( CONST,+    CONST_OR_VALID,+    RAW,+    Stage,+    VALID,+  ) import Data.Scientific   ( Scientific,     floatingOrInteger,@@ -84,6 +97,16 @@ import GHC.Generics (Generic) import Instances.TH.Lift () import Language.Haskell.TH.Syntax (Lift (..))+import Prelude+  ( ($),+    (.),+    Bool,+    Eq,+    Float,+    Int,+    Show (..),+    otherwise,+  )  -- | Primitive Values for GQLScalar: 'Int', 'Float', 'String', 'Boolean'. -- for performance reason type 'Text' represents GraphQl 'String' value@@ -112,22 +135,18 @@   parseJSON (A.String v) = pure $ String v   parseJSON notScalar = fail $ "Expected Scalar got :" <> show notScalar -type family VAR (a :: Stage) :: Stage--type instance VAR RAW = RESOLVED--type instance VAR RESOLVED = RESOLVED--type instance VAR VALID = VALID- data VariableContent (stage :: Stage) where-  DefaultValue :: Maybe ResolvedValue -> VariableContent RESOLVED+  DefaultValue :: Maybe ResolvedValue -> VariableContent CONST   ValidVariableValue :: {validVarContent :: ValidValue} -> VariableContent VALID  instance Lift (VariableContent a) where   lift (DefaultValue x) = [|DefaultValue x|]   lift (ValidVariableValue x) = [|ValidVariableValue x|] +#if MIN_VERSION_template_haskell(2,16,0)+  liftTyped (DefaultValue x) = [||DefaultValue x||]+  liftTyped (ValidVariableValue x) = [||ValidVariableValue x||]+#endif deriving instance Show (VariableContent a)  deriving instance Eq (VariableContent a)@@ -136,24 +155,24 @@   { variableName :: FieldName,     variableType :: TypeRef,     variablePosition :: Position,-    variableValue :: VariableContent (VAR stage)+    variableValue :: VariableContent (CONST_OR_VALID stage)   }   deriving (Show, Eq, Lift) -instance KeyOf (Variable s) where+instance KeyOf FieldName (Variable s) where   keyOf = variableName  instance NameCollision (Variable s) where-  nameCollision _ Variable {variableName, variablePosition} =-    GQLError-      { message = "There can Be only One Variable Named " <> msg variableName,-        locations = [variablePosition]+  nameCollision Variable {variableName, variablePosition} =+    ValidationError+      { validationMessage = "There can Be only One Variable Named " <> msg variableName,+        validationLocations = [variablePosition]       } -type VariableDefinitions s = OrderedMap FieldName (Variable s)+type VariableDefinitions s = OrdMap FieldName (Variable s)  data Value (stage :: Stage) where-  ResolvedVariable :: Ref -> Variable VALID -> Value RESOLVED+  ResolvedVariable :: Ref -> Variable VALID -> Value CONST   VariableValue :: Ref -> Value RAW   Object :: Object stage -> Value stage   List :: [Value stage] -> Value stage@@ -175,39 +194,34 @@   render (ObjectEntry (FieldName name) value) = name <> ": " <> render value  instance NameCollision (ObjectEntry s) where-  nameCollision _ ObjectEntry {entryName} =-    GQLError-      { message = "There can Be only One field Named " <> msg entryName,-        locations = []-      }+  nameCollision ObjectEntry {entryName} =+    "There can Be only One field Named " <> msgValidation entryName :: ValidationError -instance KeyOf (ObjectEntry s) where+instance KeyOf FieldName (ObjectEntry s) where   keyOf = entryName -type Object a = OrderedMap FieldName (ObjectEntry a)+type Object a = OrdMap FieldName (ObjectEntry a)  type ValidObject = Object VALID  type RawObject = Object RAW -type ResolvedObject = Object RESOLVED+type ResolvedObject = Object CONST  type RawValue = Value RAW  type ValidValue = Value VALID -type ResolvedValue = Value RESOLVED+type ResolvedValue = Value CONST  deriving instance Lift (Value a)  deriving instance Lift (ObjectEntry a)  instance RenderGQL (Value a) where-  -- TODO: fix   render (ResolvedVariable Ref {refName} _) =     "$" <> readName refName   render (VariableValue Ref {refName}) = "$" <> readName refName <> " "-  -- TODO: fix   render Null = "null"   render (Enum x) = readTypeName x   render (Scalar x) = render x@@ -236,7 +250,7 @@   toJSON (Enum (TypeName x)) = A.String x   toJSON (Scalar x) = A.toJSON x   toJSON (List x) = A.toJSON x-  toJSON (Object fields) = A.object $ map toEntry (elems fields)+  toJSON (Object fields) = A.object $ fmap toEntry (elems fields)     where       toEntry (ObjectEntry (FieldName name) value) = name A..= A.toJSON value @@ -251,7 +265,7 @@   toEncoding (List x) = A.toEncoding x   toEncoding (Object ordmap)     | null ordmap = A.toEncoding $ A.object []-    | otherwise = A.pairs $ foldl1 (<>) $ map encodeField (elems ordmap)+    | otherwise = A.pairs $ foldl1 (<>) $ fmap encodeField (elems ordmap)     where       encodeField (ObjectEntry (FieldName key) value) = key A..= value @@ -266,10 +280,10 @@ replaceValue (A.String v) = gqlString v replaceValue (A.Object v) =   gqlObject $-    map+    fmap       (mapTuple FieldName replaceValue)       (M.toList v)-replaceValue (A.Array li) = gqlList (map replaceValue (V.toList li))+replaceValue (A.Array li) = gqlList (fmap replaceValue (V.toList li)) replaceValue A.Null = gqlNull  instance A.FromJSON (Value a) where@@ -291,6 +305,6 @@   gqlBoolean = Scalar . Boolean   gqlString = Scalar . String   gqlList = List-  gqlObject = Object . unsafeFromValues . map toEntry+  gqlObject = Object . unsafeFromValues . fmap toEntry     where       toEntry (key, value) = ObjectEntry key value
+ src/Data/Morpheus/Types/Internal/Config.hs view
@@ -0,0 +1,40 @@+{-# LANGUAGE NoImplicitPrelude #-}++module Data.Morpheus.Types.Internal.Config+  ( Config (..),+    VALIDATION_MODE (..),+    defaultConfig,+    debugConfig,+  )+where++import Prelude+  ( Bool (..),+    Eq,+    Show,+  )++data VALIDATION_MODE+  = WITHOUT_VARIABLES+  | FULL_VALIDATION+  deriving (Eq, Show)++data Config = Config+  { debug :: Bool,+    validationMode :: VALIDATION_MODE+  }+  deriving (Show)++defaultConfig :: Config+defaultConfig =+  Config+    { debug = False,+      validationMode = FULL_VALIDATION+    }++debugConfig :: Config+debugConfig =+  Config+    { debug = True,+      validationMode = FULL_VALIDATION+    }
src/Data/Morpheus/Types/Internal/Resolving.hs view
@@ -1,38 +1,32 @@ {-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Types.Internal.Resolving   ( Event (..),-    UnSubResolver,     Resolver,-    MapStrategy (..),     LiftOperation,     runRootResModel,-    toResolver,     lift,     SubEvent,     Eventless,     Failure (..),-    GQLChannel (..),+    eventChannels,     ResponseEvent (..),     ResponseStream,     cleanEvents,     Result (..),     ResultT (..),     unpackEvents,-    LibUpdater,-    resolveUpdates,-    setTypeName,     ObjectResModel (..),     ResModel (..),     FieldResModel,     WithOperation,     PushEvents (..),     subscribe,-    Context (..),+    ResolverContext (..),     unsafeInternalContext,     RootResModel (..),-    unsafeBind,-    liftStateless,     resultOr,     withArguments,     -- Dynamic Resolver@@ -45,17 +39,48 @@     mkObject,     mkNull,     mkString,+    SubscriptionField (..),+    getArguments,+    Channel (..),+    ResolverState,+    liftResolverState,+    mkValue,   ) where +import Control.Applicative (pure)+import Control.Monad (Monad)+import qualified Data.Aeson as A+import Data.Functor (fmap)+import qualified Data.HashMap.Strict as HM+  ( lookup,+    toList,+  )+import Data.Maybe (maybe)+import Data.Morpheus.Internal.Utils+  ( mapTuple,+  ) import Data.Morpheus.Types.Internal.AST-  ( FieldName,+  ( FieldName (..),     ScalarValue (..),     Token,-    TypeName,+    TypeName (..),+    decodeScientific,   ) import Data.Morpheus.Types.Internal.Resolving.Core+import Data.Morpheus.Types.Internal.Resolving.Event import Data.Morpheus.Types.Internal.Resolving.Resolver+import Data.Morpheus.Types.Internal.Resolving.ResolverState+import qualified Data.Vector as V+  ( toList,+  )+import Prelude+  ( ($),+    (.),+    Bool,+    Float,+    Int,+  )  mkString :: Token -> ResModel o e m mkString = ResScalar . String@@ -80,6 +105,26 @@  mkNull :: ResModel o e m mkNull = ResNull++unPackName :: A.Value -> TypeName+unPackName (A.String x) = TypeName x+unPackName _ = "__JSON__"++mkValue ::+  (LiftOperation o, Monad m) =>+  A.Value ->+  ResModel o e m+mkValue (A.Object v) =+  mkObject+    (maybe "__JSON__" unPackName $ HM.lookup "__typename" v)+    $ fmap+      (mapTuple FieldName (pure . mkValue))+      (HM.toList v)+mkValue (A.Array ls) = mkList (fmap mkValue (V.toList ls))+mkValue A.Null = mkNull+mkValue (A.Number x) = ResScalar (decodeScientific x)+mkValue (A.String x) = ResScalar (String x)+mkValue (A.Bool x) = ResScalar (Boolean x)  mkObject ::   TypeName ->
src/Data/Morpheus/Types/Internal/Resolving/Core.hs view
@@ -1,13 +1,10 @@-{-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE PolyKinds #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Types.Internal.Resolving.Core   ( Eventless,@@ -15,32 +12,31 @@     Failure (..),     ResultT (..),     unpackEvents,-    LibUpdater,-    resolveUpdates,     mapEvent,     cleanEvents,-    Event (..),-    Channel (..),-    GQLChannel (..),     PushEvents (..),-    statelessToResultT,     resultOr,   ) where -import Control.Applicative (liftA2)-import Control.Monad (foldM)+import Control.Applicative (Applicative (..), liftA2)+import Control.Monad (Monad (..)) import Control.Monad.Trans.Class (MonadTrans (..))-import Data.Function ((&))+import Data.Functor ((<$>), Functor (..)) import Data.Morpheus.Internal.Utils   ( Failure (..),   ) import Data.Morpheus.Types.Internal.AST.Base   ( GQLError (..),     GQLErrors,-    Message,+    ValidationError (..),+    toGQLError,   ) import Data.Semigroup ((<>))+import Prelude+  ( ($),+    (.),+  )  type Eventless = Result () @@ -48,29 +44,6 @@ class PushEvents e m where   pushEvents :: [e] -> m () --- Channel-newtype Channel event = Channel-  { _unChannel :: StreamChannel event-  }--instance (Eq (StreamChannel event)) => Eq (Channel event) where-  Channel x == Channel y = x == y--class GQLChannel a where-  type StreamChannel a :: *-  streamChannels :: a -> [Channel a]--instance GQLChannel () where-  type StreamChannel () = ()-  streamChannels _ = []--instance GQLChannel (Event channel content) where-  type StreamChannel (Event channel content) = channel-  streamChannels Event {channels} = map Channel channels--data Event e c = Event-  {channels :: [e], content :: c}- unpackEvents :: Result event a -> [event] unpackEvents Success {events} = events unpackEvents _ = []@@ -101,13 +74,12 @@ instance Failure [GQLError] (Result ev) where   failure = Failure -instance Failure Message (Result e) where-  failure text =-    Failure [GQLError {message = "INTERNAL: " <> text, locations = []}]- instance PushEvents events (Result events) where   pushEvents events = Success {result = (), warnings = [], events} +instance Failure [ValidationError] (Result ev) where+  failure = failure . fmap toGQLError+ resultOr :: (GQLErrors -> a') -> (a -> a') -> Result e a -> a' resultOr _ f (Success x _ _) = f x resultOr f _ (Failure e) = f e@@ -118,15 +90,6 @@   }   deriving (Functor) -statelessToResultT ::-  Applicative m =>-  Eventless a ->-  ResultT e m a-statelessToResultT =-  cleanEvents-    . ResultT-    . pure- instance Applicative m => Applicative (ResultT event m) where   pure = ResultT . pure . pure   ResultT app1 <*> ResultT app2 = ResultT $ liftA2 (<*>) app1 app2@@ -146,16 +109,9 @@ instance MonadTrans (ResultT event) where   lift = ResultT . fmap pure --- instance Applicative m => Failure String (ResultT event m) where---   failure x =---     ResultT $ pure $ Failure [GQLError {message = pack x, locations = []}]- instance Monad m => Failure GQLErrors (ResultT event m) where   failure = ResultT . pure . failure -instance Applicative m => Failure Message (ResultT event m) where-  failure = ResultT . pure . failure- instance Applicative m => PushEvents event (ResultT event m) where   pushEvents = ResultT . pure . pushEvents @@ -176,11 +132,5 @@ mapEvent func (ResultT ma) = ResultT $ mapEv <$> ma   where     mapEv Success {result, warnings, events} =-      Success {result, warnings, events = map func events}+      Success {result, warnings, events = fmap func events}     mapEv (Failure err) = Failure err---- Helper Functions-type LibUpdater lib = lib -> Eventless lib--resolveUpdates :: Monad m => lib -> [lib -> m lib] -> m lib-resolveUpdates = foldM (&)
+ src/Data/Morpheus/Types/Internal/Resolving/Event.hs view
@@ -0,0 +1,32 @@+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE NoImplicitPrelude #-}++module Data.Morpheus.Types.Internal.Resolving.Event+  ( Event (..),+    Channel (..),+    eventChannels,+  )+where++import Prelude+  ( Eq (..),+    fmap,+  )++-- Channel+data Channel (event :: *) where+  Channel :: a -> Channel (Event a c)++data Event e c = Event+  { channels :: [e],+    content :: c+  }++eventChannels :: Event e c -> [Channel (Event e c)]+eventChannels Event {channels} = fmap Channel channels++instance (Eq ch) => Eq (Channel (Event ch con)) where+  Channel x == Channel y = x == y
src/Data/Morpheus/Types/Internal/Resolving/Resolver.hs view
@@ -6,7 +6,6 @@ {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE InstanceSigs #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-}@@ -15,47 +14,48 @@ {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Types.Internal.Resolving.Resolver   ( Event (..),-    UnSubResolver,     Resolver,-    MapStrategy (..),     LiftOperation,-    unsafeBind,-    toResolver,     lift,     subscribe,     SubEvent,-    GQLChannel (..),     ResponseEvent (..),     ResponseStream,     ObjectResModel (..),     ResModel (..),     FieldResModel,     WithOperation,-    Context (..),+    ResolverContext (..),     unsafeInternalContext,     runRootResModel,-    setTypeName,     RootResModel (..),-    liftStateless,     withArguments,+    getArguments,+    SubscriptionField (..),+    liftResolverState,   ) where +import Control.Applicative (Applicative (..))+import Control.Monad (Monad (..), join) import Control.Monad.Fail (MonadFail (..)) import Control.Monad.IO.Class (MonadIO (..))+import Control.Monad.Reader (MonadReader (..), asks) import Control.Monad.Trans.Class (MonadTrans (..))-import Control.Monad.Trans.Reader (ReaderT (..), ask, mapReaderT, withReaderT)-import Data.Maybe (maybe)--- MORPHEUS-import Data.Morpheus.Error.Internal (internalResolvingError)+import Control.Monad.Trans.Reader+  ( ReaderT (..),+    mapReaderT,+  )+import Data.Functor ((<$>), Functor (..))+import Data.Maybe (Maybe (..), maybe) import Data.Morpheus.Error.Selection (subfieldsNotSelected) import Data.Morpheus.Internal.Utils-  ( Merge (..),+  ( SemigroupM (..),     empty,     keyOf,     selectOr,@@ -64,60 +64,72 @@   ( GQLResponse,     renderResponse,   )-import Data.Morpheus.Types.Internal.AST.Base-  ( FieldName,-    GQLError (..),+import Data.Morpheus.Types.Internal.AST+  ( Arguments,+    FieldName,     GQLErrors,+    GQLValue (..),+    InternalError,     MUTATION,     Message,+    ObjectEntry (..),+    Operation (..),     OperationType,     OperationType (..),     QUERY,     SUBSCRIPTION,-    TypeName (..),-    VALID,-    msg,-  )-import Data.Morpheus.Types.Internal.AST.MergeSet-  ( toOrderedMap,-  )-import Data.Morpheus.Types.Internal.AST.Selection-  ( Operation (..),+    ScalarValue (..),     Selection (..),     SelectionContent (..),     SelectionSet,+    TypeName (..),     UnionSelection,     UnionTag (..),-  )-import Data.Morpheus.Types.Internal.AST.TypeSystem-  ( Arguments,-    Schema,-  )-import Data.Morpheus.Types.Internal.AST.Value-  ( GQLValue (..),-    ObjectEntry (..),-    ScalarValue (..),+    VALID,     ValidValue,     Value (..),+    msg,+    toGQLError,   )+import Data.Morpheus.Types.Internal.AST.MergeSet+  ( toOrdMap,+  ) import Data.Morpheus.Types.Internal.Resolving.Core-  ( Channel (..),-    Event (..),-    Eventless,+  ( Eventless,     Failure (..),-    GQLChannel (..),     PushEvents (..),     Result (..),     ResultT (..),-    StreamChannel,     cleanEvents,     mapEvent,-    statelessToResultT,   )+import Data.Morpheus.Types.Internal.Resolving.Event+  ( Channel (..),+    Event (..),+  )+import Data.Morpheus.Types.Internal.Resolving.ResolverState+  ( ResolverContext (..),+    ResolverState,+    ResolverStateT (..),+    clearStateResolverEvents,+    resolverFailureMessage,+    runResolverState,+    runResolverStateM,+    runResolverStateT,+    toResolverStateT,+  ) import Data.Semigroup-  ( (<>),-    Semigroup (..),+  ( Semigroup (..),   )+import Data.Traversable (traverse)+import Prelude+  ( ($),+    (.),+    Eq (..),+    Show (..),+    lookup,+    otherwise,+  )  type WithOperation (o :: OperationType) = LiftOperation o @@ -129,74 +141,24 @@  type SubEvent event m = Event (Channel event) (event -> m GQLResponse) --- | A datatype to expose 'Schema' and the query's AST information ('Selection', 'Operation').-data Context = Context-  { currentSelection :: Selection VALID,-    schema :: Schema,-    operation :: Operation VALID,-    currentTypeName :: TypeName-  }-  deriving (Show)---- Resolver Internal State-newtype ResolverState event m a = ResolverState-  { runResolverState :: ReaderT Context (ResultT event m) a-  }-  deriving-    ( Functor,-      Applicative,-      Monad-    )--instance MonadTrans (ResolverState e) where-  lift = ResolverState . lift . lift--instance (Monad m) => Failure Message (ResolverState e m) where-  failure message = ResolverState $ do-    selection <- currentSelection <$> ask-    lift $ failure [resolverFailureMessage selection message]--instance (Monad m) => Failure GQLErrors (ResolverState e m) where-  failure = ResolverState . lift . failure--instance (Monad m) => PushEvents e (ResolverState e m) where-  pushEvents = ResolverState . lift . pushEvents--mapResolverState ::-  ( ReaderT Context (ResultT e m) a ->-    ReaderT Context (ResultT e' m') a'-  ) ->-  ResolverState e m a ->-  ResolverState e' m' a'-mapResolverState f (ResolverState x) = ResolverState (f x)--getState :: (Monad m) => ResolverState e m (Selection VALID)-getState = ResolverState $ currentSelection <$> ask--mapState :: (Context -> Context) -> ResolverState e m a -> ResolverState e m a-mapState f = mapResolverState (withReaderT f)---- clear evets and starts new resolver with diferenct type of events but with same value--- use properly. only if you know what you are doing-clearStateResolverEvents :: (Functor m) => ResolverState e m a -> ResolverState e' m a-clearStateResolverEvents = mapResolverState (mapReaderT cleanEvents)--resolverFailureMessage :: Selection VALID -> Message -> GQLError-resolverFailureMessage Selection {selectionName, selectionPosition} message =-  GQLError-    { message = "Failure on Resolving Field " <> msg selectionName <> ": " <> message,-      locations = [selectionPosition]-    }+data SubscriptionField (a :: *) where+  SubscriptionField ::+    { channel :: forall e m v. a ~ Resolver SUBSCRIPTION e m v => Channel e,+      unSubscribe :: a+    } ->+    SubscriptionField a  -- -- GraphQL Field Resolver -- --------------------------------------------------------------- data Resolver (o :: OperationType) event (m :: * -> *) value where-  ResolverQ :: {runResolverQ :: ResolverState () m value} -> Resolver QUERY event m value-  ResolverM :: {runResolverM :: ResolverState event m value} -> Resolver MUTATION event m value-  ResolverS :: {runResolverS :: ResolverState (Channel event) m (ReaderT event (Resolver QUERY event m) value)} -> Resolver SUBSCRIPTION event m value+  ResolverQ :: {runResolverQ :: ResolverStateT () m value} -> Resolver QUERY event m value+  ResolverM :: {runResolverM :: ResolverStateT event m value} -> Resolver MUTATION event m value+  ResolverS :: {runResolverS :: ResolverStateT () m (SubEventRes event m value)} -> Resolver SUBSCRIPTION event m value +type SubEventRes event m value = ReaderT event (ResolverStateT () m) value+ instance Show (Resolver o e m value) where   show ResolverQ {} = "Resolver QUERY e m a"   show ResolverM {} = "Resolver MUTATION e m a"@@ -214,12 +176,24 @@ -- Monad instance (Monad m, LiftOperation o) => Monad (Resolver o e m) where   return = pure-  (>>=) = unsafeBind+  (ResolverQ x) >>= m2 = ResolverQ (x >>= runResolverQ . m2)+  (ResolverM x) >>= m2 = ResolverM (x >>= runResolverM . m2)+  (ResolverS res) >>= m2 = ResolverS (liftSubResolver m2 <$> res)  #if __GLASGOW_HASKELL__ < 808   fail = failure . msg # endif +liftSubResolver ::+  (Monad m) =>+  (t -> Resolver SUBSCRIPTION r m a) ->+  ReaderT r (ResolverStateT () m) t ->+  ReaderT r (ResolverStateT () m) a+liftSubResolver m2 readResA = ReaderT $ \e -> do+  a <- runReaderT readResA e+  readResB <- runResolverS (m2 a)+  runReaderT readResB e+ -- MonadIO instance (MonadIO m, LiftOperation o) => MonadIO (Resolver o e m) where   liftIO = lift . liftIO@@ -245,137 +219,74 @@ instance (Monad m, Semigroup a, LiftOperation o) => Semigroup (Resolver o e m a) where   x <> y = fmap (<>) x <*> y -liftStateless ::-  ( LiftOperation o,-    Monad m-  ) =>-  Eventless a ->-  Resolver o e m a-liftStateless =-  packResolver-    . ResolverState-    . ReaderT-    . const-    . statelessToResultT+instance (LiftOperation o, Monad m) => MonadReader ResolverContext (Resolver o e m) where+  ask = packResolver ask+  local f (ResolverQ res) = ResolverQ (local f res)+  local f (ResolverM res) = ResolverM (local f res)+  local f (ResolverS resM) = ResolverS $ mapReaderT (local f) <$> resM +-- | A function to return the internal 'ResolverContext' within a resolver's monad.+-- Using the 'ResolverContext' itself is unsafe because it expposes internal structures+-- of the AST, but you can use the "Data.Morpheus.Types.SelectionTree" typeclass to manipulate+-- the internal AST with a safe interface.+unsafeInternalContext :: (Monad m, LiftOperation o) => Resolver o e m ResolverContext+unsafeInternalContext = ask++liftResolverState :: (LiftOperation o, Monad m) => ResolverState a -> Resolver o e m a+liftResolverState = packResolver . toResolverStateT+ class LiftOperation (o :: OperationType) where-  packResolver :: Monad m => ResolverState e m a -> Resolver o e m a-  withResolver :: Monad m => ResolverState e m a -> (a -> Resolver o e m b) -> Resolver o e m b+  packResolver :: Monad m => ResolverStateT e m a -> Resolver o e m a --- packResolver instance LiftOperation QUERY where   packResolver = ResolverQ . clearStateResolverEvents-  withResolver ctxRes toRes = ResolverQ $ do-    v <- clearStateResolverEvents ctxRes-    runResolverQ $ toRes v  instance LiftOperation MUTATION where   packResolver = ResolverM-  withResolver ctxRes toRes = ResolverM $ ctxRes >>= runResolverM . toRes  instance LiftOperation SUBSCRIPTION where-  packResolver = ResolverS . pure . lift . packResolver-  withResolver ctxRes toRes = ResolverS $ do-    value <- clearStateResolverEvents ctxRes-    runResolverS $ toRes value--mapResolverContext :: Monad m => (Context -> Context) -> Resolver o e m a -> Resolver o e m a-mapResolverContext f (ResolverQ res) = ResolverQ (mapState f res)-mapResolverContext f (ResolverM res) = ResolverM (mapState f res)-mapResolverContext f (ResolverS resM) = ResolverS $ do-  res <- resM-  pure $ ReaderT $ \e -> ResolverQ $ mapState f (runResolverQ (runReaderT res e))--setSelection :: Monad m => Selection VALID -> Resolver o e m a -> Resolver o e m a-setSelection currentSelection =-  mapResolverContext (\ctx -> ctx {currentSelection})--setTypeName :: Monad m => TypeName -> Resolver o e m a -> Resolver o e m a-setTypeName currentTypeName =-  mapResolverContext (\ctx -> ctx {currentTypeName})---- unsafe variant of >>= , not for public api. user can be confused:---  ignores `channels` on second Subsciption, only returns events from first Subscription monad.---    reason: second monad is waiting for `event` until he does not have some event can't tell which---            channel does it have to listen-unsafeBind ::-  forall o e m a b.-  Monad m =>-  Resolver o e m a ->-  (a -> Resolver o e m b) ->-  Resolver o e m b-unsafeBind (ResolverQ x) m2 = ResolverQ (x >>= runResolverQ . m2)-unsafeBind (ResolverM x) m2 = ResolverM (x >>= runResolverM . m2)-unsafeBind (ResolverS res) m2 = ResolverS $ do-  (readResA :: ReaderT e (Resolver QUERY e m) a) <- res-  pure $ ReaderT $ \e -> ResolverQ $ do-    let (resA :: Resolver QUERY e m a) = runReaderT readResA e-    (valA :: a) <- runResolverQ resA-    (readResB :: ReaderT e (Resolver QUERY e m) b) <- clearStateResolverEvents $ runResolverS (m2 valA)-    runResolverQ $ runReaderT readResB e+  packResolver = ResolverS . pure . lift . clearStateResolverEvents  subscribe ::-  forall e m a.-  ( PushEvents (Channel e) (ResolverState (Channel e) m),-    Monad m-  ) =>-  [StreamChannel e] ->-  Resolver QUERY e m (e -> Resolver QUERY e m a) ->-  Resolver SUBSCRIPTION e m a-subscribe ch res = ResolverS $ do-  pushEvents (map Channel ch :: [Channel e])-  (eventRes :: e -> Resolver QUERY e m a) <- clearStateResolverEvents (runResolverQ res)-  pure $ ReaderT eventRes---- | A function to return the internal 'Context' within a resolver's monad.--- Using the 'Context' itself is unsafe because it expposes internal structures--- of the AST, but you can use the "Data.Morpheus.Types.SelectionTree" typeclass to manipulate--- the internal AST with a safe interface.-unsafeInternalContext :: (Monad m, LiftOperation o) => Resolver o e m Context-unsafeInternalContext = packResolver $ ResolverState ask---- Converts Subscription Resolver Type to Query Resolver-type family UnSubResolver (a :: * -> *) :: (* -> *)--type instance UnSubResolver (Resolver SUBSCRIPTION e m) = Resolver QUERY e m+  forall e channel cont m a.+  (Monad m, Event channel cont ~ e) =>+  channel ->+  Resolver QUERY e m (e -> Resolver SUBSCRIPTION e m a) ->+  SubscriptionField (Resolver SUBSCRIPTION e m a)+subscribe ch res =+  SubscriptionField (Channel ch)+    $ ResolverS+    $ fromSub <$> runResolverQ res+  where+    fromSub :: (e -> Resolver SUBSCRIPTION e m a) -> ReaderT e (ResolverStateT () m) a+    fromSub f = join (ReaderT $ \e -> runResolverS (f e))  withArguments ::-  forall o e m a.   (LiftOperation o, Monad m) =>   (Arguments VALID -> Resolver o e m a) ->   Resolver o e m a-withArguments = withResolver args-  where-    args :: ResolverState e m (Arguments VALID)-    args = selectionArguments <$> getState+withArguments = (getArguments >>=) ------ Selection Processing-toResolver ::-  forall o e m a b.+getArguments ::   (LiftOperation o, Monad m) =>-  (Arguments VALID -> Eventless a) ->-  (a -> Resolver o e m b) ->-  Resolver o e m b-toResolver toArgs = withResolver args-  where-    args :: ResolverState e m a-    args =-      ResultT . pure . toArgs . selectionArguments <$> getState-        >>= ResolverState . lift . cleanEvents+  Resolver o e m (Arguments VALID)+getArguments = selectionArguments . currentSelection <$> unsafeInternalContext  pickSelection :: TypeName -> UnionSelection VALID -> SelectionSet VALID pickSelection = selectOr empty unionTagSelection  withObject ::   (LiftOperation o, Monad m) =>+  TypeName ->   (SelectionSet VALID -> Resolver o e m value) ->   Selection VALID ->   Resolver o e m value-withObject f Selection {selectionName, selectionContent, selectionPosition} = checkContent selectionContent+withObject __typename f Selection {selectionName, selectionContent, selectionPosition} = checkContent selectionContent   where     checkContent (SelectionSet selection) = f selection-    checkContent _ = failure (subfieldsNotSelected selectionName "" selectionPosition)+    checkContent (UnionSelection unionSel) =+      f (selectOr empty unionTagSelection __typename unionSel)+    checkContent _ = failure [toGQLError $ subfieldsNotSelected selectionName "" selectionPosition]  lookupRes ::   (LiftOperation o, Monad m) =>@@ -388,7 +299,7 @@   | otherwise =     maybe       (pure gqlNull)-      (`unsafeBind` runDataResolver)+      (>>= runDataResolver)       . lookup selectionName       . objectFields @@ -399,30 +310,23 @@   ResModel o e m ->   Resolver o e m ValidValue resolveObject selectionSet (ResObject drv@ObjectResModel {__typename}) =-  Object . toOrderedMap <$> traverse resolver selectionSet+  Object . toOrdMap <$> traverse resolver selectionSet   where     resolver :: Selection VALID -> Resolver o e m (ObjectEntry VALID)-    resolver sel =-      setSelection sel-        $ setTypeName __typename-        $ ObjectEntry (keyOf sel) <$> lookupRes sel drv-resolveObject _ _ =-  failure $ internalResolvingError "expected object as resolver"--toEventResolver :: Monad m => ReaderT event (Resolver QUERY event m) ValidValue -> Context -> event -> m GQLResponse-toEventResolver (ReaderT subRes) sel event = do-  value <- runResultT $ runReaderT (runResolverState $ runResolverQ (subRes event)) sel-  pure $ renderResponse value+    resolver currentSelection =+      local (\ctx -> ctx {currentSelection, currentTypeName = __typename}) $+        ObjectEntry (keyOf currentSelection) <$> lookupRes currentSelection drv+resolveObject _ _ = packResolver $ failure ("expected object as resolver" :: InternalError)  runDataResolver :: (Monad m, LiftOperation o) => ResModel o e m -> Resolver o e m ValidValue-runDataResolver = withResolver getState . __encode+runDataResolver res = asks currentSelection >>= __encode res   where     __encode obj sel@Selection {selectionContent} = encodeNode obj selectionContent       where         -- LIST         encodeNode (ResList x) _ = List <$> traverse runDataResolver x         -- Object ------------------        encodeNode objDrv@ResObject {} _ = withObject (`resolveObject` objDrv) sel+        encodeNode objDrv@(ResObject ObjectResModel {__typename}) _ = withObject __typename (`resolveObject` objDrv) sel         -- ENUM         encodeNode (ResEnum _ enum) SelectionField = pure $ gqlString $ readTypeName enum         encodeNode (ResEnum typename enum) unionSel@UnionSelection {} =@@ -450,23 +354,39 @@  runResolver ::   Monad m =>+  Maybe (Selection VALID -> ResolverState (Channel event)) ->   Resolver o event m ValidValue ->-  Context ->+  ResolverContext ->   ResponseStream event m ValidValue-runResolver (ResolverQ resT) sel = cleanEvents $ runReaderT (runResolverState resT) sel-runResolver (ResolverM resT) sel = mapEvent Publish $ runReaderT (runResolverState resT) sel-runResolver (ResolverS resT) sel = ResultT $ do-  readResValue <- runResultT $ runReaderT (runResolverState resT) sel-  pure $ case readResValue of+runResolver _ (ResolverQ resT) sel = cleanEvents $ runResolverStateT resT sel+runResolver _ (ResolverM resT) sel = mapEvent Publish $ runResolverStateT resT sel+runResolver toChannel (ResolverS resT) ctx = ResultT $ do+  readResValue <- runResolverStateM resT ctx+  pure $ case readResValue >>= subscriptionEvents ctx toChannel . toEventResolver ctx of     Failure x -> Failure x-    Success {warnings, result, events = channels} -> do-      let eventRes = toEventResolver result sel+    Success {warnings, result} ->       Success-        { events = [Subscribe $ Event channels eventRes],+        { events = [result],           warnings,           result = gqlNull         } +toEventResolver :: Monad m => ResolverContext -> SubEventRes event m ValidValue -> (event -> m GQLResponse)+toEventResolver sel (ReaderT subRes) event = renderResponse <$> runResolverStateM (subRes event) sel++subscriptionEvents ::+  ResolverContext ->+  Maybe (Selection VALID -> ResolverState (Channel e)) ->+  (e -> m GQLResponse) ->+  Eventless (ResponseEvent e m)+subscriptionEvents ctx@ResolverContext {currentSelection} (Just channelGenerator) res =+  runResolverState handle ctx+  where+    handle = do+      channel <- channelGenerator currentSelection+      pure $ Subscribe (Event [channel] res)+subscriptionEvents ctx Nothing _ = failure [resolverFailureMessage ctx "channel Resolver is not defined"]+ -- Resolver Models ------------------------------------------------------------------- type FieldResModel o e m =   (FieldName, Resolver o e m (ResModel o e m))@@ -478,8 +398,8 @@   }   deriving (Show) -instance Merge (ObjectResModel o e m) where-  merge _ (ObjectResModel tyname x) (ObjectResModel _ y) =+instance Applicative f => SemigroupM f (ObjectResModel o e m) where+  mergeM _ (ObjectResModel tyname x) (ObjectResModel _ y) =     pure $ ObjectResModel tyname (x <> y)  data ResModel (o :: OperationType) e (m :: * -> *)@@ -491,86 +411,46 @@   | ResUnion TypeName (Resolver o e m (ResModel o e m))   deriving (Show) -instance Merge (ResModel o e m) where-  merge p (ResObject x) (ResObject y) =-    ResObject <$> merge p x y-  merge _ _ _ =-    failure $ internalResolvingError "can't merge: incompatible resolvers"+instance (Monad f, Failure InternalError f) => SemigroupM f (ResModel o e m) where+  mergeM p (ResObject x) (ResObject y) =+    ResObject <$> mergeM p x y+  mergeM _ _ _ = failure ("can't merge: incompatible resolvers" :: InternalError)  data RootResModel e m = RootResModel-  { query :: Eventless (ResModel QUERY e m),-    mutation :: Eventless (ResModel MUTATION e m),-    subscription :: Eventless (ResModel SUBSCRIPTION e m)+  { query :: ResolverState (ResModel QUERY e m),+    mutation :: ResolverState (ResModel MUTATION e m),+    subscription :: ResolverState (ResModel SUBSCRIPTION e m),+    channelMap :: Maybe (Selection VALID -> ResolverState (Channel e))   }  runRootDataResolver ::   (Monad m, LiftOperation o) =>-  Eventless (ResModel o e m) ->-  Context ->+  Maybe (Selection VALID -> ResolverState (Channel e)) ->+  ResolverState (ResModel o e m) ->+  ResolverContext ->   ResponseStream e m (Value VALID) runRootDataResolver+  channels   res-  ctx@Context {operation = Operation {operationSelection}} =+  ctx@ResolverContext {operation = Operation {operationSelection}} =     do-      root <- statelessToResultT res-      runResolver (resolveObject operationSelection root) ctx+      root <- runResolverStateT (toResolverStateT res) ctx+      runResolver channels (resolveObject operationSelection root) ctx -runRootResModel :: Monad m => RootResModel e m -> Context -> ResponseStream e m (Value VALID)+runRootResModel :: Monad m => RootResModel e m -> ResolverContext -> ResponseStream e m (Value VALID) runRootResModel   RootResModel     { query,       mutation,-      subscription+      subscription,+      channelMap     }-  ctx@Context {operation = Operation {operationType}} =+  ctx@ResolverContext {operation = Operation {operationType}} =     selectByOperation operationType     where       selectByOperation Query =-        runRootDataResolver query ctx+        runRootDataResolver channelMap query ctx       selectByOperation Mutation =-        runRootDataResolver mutation ctx+        runRootDataResolver channelMap mutation ctx       selectByOperation Subscription =-        runRootDataResolver subscription ctx---- map Resolving strategies-class-  MapStrategy-    (from :: OperationType)-    (to :: OperationType)-  where-  mapStrategy ::-    Monad m =>-    Resolver from e m (ResModel from e m) ->-    Resolver to e m (ResModel to e m)--instance MapStrategy o o where-  mapStrategy = id--instance MapStrategy QUERY SUBSCRIPTION where-  mapStrategy = ResolverS . pure . lift . fmap mapDeriving--mapDeriving ::-  ( MapStrategy o o',-    Monad m-  ) =>-  ResModel o e m ->-  ResModel o' e m-mapDeriving ResNull = ResNull-mapDeriving (ResScalar x) = ResScalar x-mapDeriving (ResEnum typeName enum) = ResEnum typeName enum-mapDeriving (ResList x) = ResList $ map mapDeriving x-mapDeriving (ResObject x) = ResObject (mapObjectDeriving x)-mapDeriving (ResUnion name x) = ResUnion name (mapStrategy x)--mapObjectDeriving ::-  ( MapStrategy o o',-    Monad m-  ) =>-  ObjectResModel o e m ->-  ObjectResModel o' e m-mapObjectDeriving (ObjectResModel tyname x) =-  ObjectResModel tyname $-    map (mapEntry mapStrategy) x--mapEntry :: (a -> b) -> (k, a) -> (k, b)-mapEntry f (name, value) = (name, f value)+        runRootDataResolver channelMap subscription ctx
+ src/Data/Morpheus/Types/Internal/Resolving/ResolverState.hs view
@@ -0,0 +1,202 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE NoImplicitPrelude #-}++module Data.Morpheus.Types.Internal.Resolving.ResolverState+  ( ResolverContext (..),+    ResolverStateT (..),+    resolverFailureMessage,+    clearStateResolverEvents,+    ResolverState,+    toResolverStateT,+    runResolverStateT,+    runResolverStateM,+    runResolverState,+  )+where++import Control.Applicative (Applicative (..))+import Control.Monad (Monad (..))+import Control.Monad.Reader (MonadReader (..), asks)+import Control.Monad.Trans.Class (MonadTrans (..))+import Control.Monad.Trans.Reader+  ( ReaderT (..),+    mapReaderT,+  )+import Data.Functor (Functor (..))+import Data.Functor.Identity (Identity (..))+import Data.Morpheus.Rendering.RenderGQL+  ( RenderGQL (..),+  )+import Data.Morpheus.Types.Internal.AST+  ( GQLError (..),+    GQLErrors,+    InternalError,+    Message,+    Operation,+    Schema,+    Selection (..),+    TypeName,+    VALID,+    msg,+  )+import Data.Morpheus.Types.Internal.Config (Config (..))+import Data.Morpheus.Types.Internal.Resolving.Core+  ( Eventless,+    Failure (..),+    PushEvents (..),+    Result,+    ResultT (..),+    cleanEvents,+  )+import Data.Semigroup+  ( Semigroup (..),+  )+import Prelude+  ( ($),+    (.),+    Bool (..),+    Int,+    Show (..),+    id,+  )++data ResolverContext = ResolverContext+  { currentSelection :: Selection VALID,+    schema :: Schema VALID,+    operation :: Operation VALID,+    currentTypeName :: TypeName,+    config :: Config+  }+  deriving (Show)++type ResolverState = ResolverStateT () Identity++runResolverStateT :: ResolverStateT e m a -> ResolverContext -> ResultT e m a+runResolverStateT = runReaderT . _runResolverStateT++runResolverStateM :: ResolverStateT e m a -> ResolverContext -> m (Result e a)+runResolverStateM res = runResultT . runResolverStateT res++runResolverState :: ResolverState a -> ResolverContext -> Eventless a+runResolverState res = runIdentity . runResolverStateM res++-- Resolver Internal State+newtype ResolverStateT event m a = ResolverStateT+  { _runResolverStateT :: ReaderT ResolverContext (ResultT event m) a+  }+  deriving+    ( Functor,+      Applicative,+      Monad,+      MonadReader ResolverContext+    )++instance MonadTrans (ResolverStateT e) where+  lift = ResolverStateT . lift . lift++instance (Monad m) => Failure Message (ResolverStateT e m) where+  failure message = do+    cxt <- asks id+    failure [resolverFailureMessage cxt message]++instance (Monad m) => Failure InternalError (ResolverStateT e m) where+  failure message = do+    ctx <- asks id+    failure [renderInternalResolverError ctx message]++instance (Monad m) => Failure GQLErrors (ResolverStateT e m) where+  failure = ResolverStateT . lift . failure++instance (Monad m) => PushEvents e (ResolverStateT e m) where+  pushEvents = ResolverStateT . lift . pushEvents++mapResolverState ::+  ( ResultT e m a ->+    ResultT e' m' a'+  ) ->+  ResolverStateT e m a ->+  ResolverStateT e' m' a'+mapResolverState f (ResolverStateT x) = ResolverStateT (mapReaderT f x)++toResolverStateT ::+  Applicative m =>+  ResolverState a ->+  ResolverStateT e m a+toResolverStateT = mapResolverState injectResult++injectResult ::+  (Applicative m) =>+  ResultT () Identity a ->+  ResultT e m a+injectResult (ResultT (Identity x)) =+  cleanEvents $ ResultT (pure x)++-- clear evets and starts new resolver with diferenct type of events but with same value+-- use properly. only if you know what you are doing+clearStateResolverEvents :: (Functor m) => ResolverStateT e m a -> ResolverStateT e' m a+clearStateResolverEvents = mapResolverState cleanEvents++resolverFailureMessage :: ResolverContext -> Message -> GQLError+resolverFailureMessage+  ctx@ResolverContext+    { currentSelection =+        Selection {selectionName, selectionPosition}+    }+  message =+    GQLError+      { message =+          "Failure on Resolving Field "+            <> msg selectionName+            <> ": "+            <> message+            <> withInternalContext ctx,+        locations = [selectionPosition]+      }++renderInternalResolverError :: ResolverContext -> InternalError -> GQLError+renderInternalResolverError ctx@ResolverContext {currentSelection} message =+  GQLError+    { message = msg message <> ". " <> renderContext ctx,+      locations = [selectionPosition currentSelection]+    }++withInternalContext :: ResolverContext -> Message+withInternalContext ResolverContext {config = Config {debug = False}} = ""+withInternalContext resCTX = renderContext resCTX++renderContext :: ResolverContext -> Message+renderContext+  ResolverContext+    { currentSelection,+      schema,+      operation,+      currentTypeName+    } =+    renderSection "Current Type" currentTypeName+      <> renderSection "Current Selection" currentSelection+      <> renderSection "OperationDefinition" operation+      <> renderSection "SchemaDefinition" schema++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/Internal/Validation.hs view
@@ -1,14 +1,13 @@ {-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GADTs #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RankNTypes #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Types.Internal.Validation   ( Validator,@@ -18,7 +17,8 @@     InputSource (..),     OperationContext (..),     runValidator,-    askFieldType,+    DirectiveValidator,+    askType,     askTypeMember,     selectRequired,     selectKnown,@@ -28,11 +28,10 @@     withScopeType,     withPosition,     asks,+    asksScope,     selectWithDefaultValue,-    askInputFieldType,-    askInputMember,     startInput,-    withInputScope,+    inField,     inputMessagePrefix,     checkUnused,     Prop (..),@@ -51,14 +50,25 @@     askFragments,     MonadContext,     CurrentSelection (..),+    getOperationType,+    selectType,+    FragmentValidator,+    askInterfaceTypes,   ) where +-- MORPHEUS++import Control.Applicative (pure)+import Control.Monad ((>>=)) import Control.Monad.Trans.Reader   ( ask,   )--- MORPHEUS-+import Data.Either (Either)+import Data.Foldable (null)+import Data.Functor ((<$>), fmap)+import Data.List (filter)+import Data.Maybe (Maybe (..), fromMaybe, maybe) import Data.Morpheus.Internal.Utils   ( Failure (..),     KeyOf (..),@@ -73,41 +83,45 @@     FieldContent (..),     FieldDefinition (..),     FieldName,-    FieldsDefinition,-    GQLErrors,     IN,     Message,-    OUT,     Object,     ObjectEntry (..),-    RESOLVED,+    Position (..),     Ref (..),-    Schema,     TRUE,     TypeContent (..),     TypeDefinition (..),-    TypeName (..),-    TypeRef (..),+    TypeName,     UnionMember (..),+    ValidationError,     Value (..),     __inputname,     entryValue,     fromAny,-    isFieldNullable,+    isNullable,     msg,+    msgValidation,     toFieldName,   ) import Data.Morpheus.Types.Internal.Validation.Error-  ( InternalError (..),-    KindViolation (..),+  ( KindViolation (..),     MissingRequired (..),     Unknown (..),     Unused (..),   )+import Data.Morpheus.Types.Internal.Validation.Internal+  ( askInterfaceTypes,+    askType,+    askTypeMember,+    getOperationType,+  ) import Data.Morpheus.Types.Internal.Validation.Validator   ( BaseValidator,     Constraint (..),     CurrentSelection (..),+    DirectiveValidator,+    FragmentValidator,     GetWith (..),     InputContext,     InputSource (..),@@ -122,16 +136,18 @@     SetWith (..),     Target (..),     Validator (..),+    ValidatorContext (..),     askFragments,     askSchema,     askVariables,     asks,+    asksScope,+    inField,     inputMessagePrefix,     inputValueSource,     runValidator,     startInput,     withDirective,-    withInputScope,     withPosition,     withScope,     withScopeType,@@ -139,62 +155,75 @@ import Data.Semigroup   ( (<>),   )+import Prelude+  ( ($),+    (.),+    not,+    otherwise,+  ) -getUnused :: (KeyOf b, KEY a ~ KEY b, Selectable ca a) => ca -> [b] -> [b]+getUnused :: (KeyOf k b, Selectable k a c) => c -> [b] -> [b] getUnused uses = filter (not . (`member` uses) . keyOf) -failOnUnused :: Unused ctx b => [b] -> Validator ctx ()+failOnUnused :: Unused ctx b => [b] -> Validator s ctx () failOnUnused x-  | null x = return ()+  | null x = pure ()   | otherwise = do-    ctx <- Validator ask-    failure $ map (unused ctx) x+    ctx <- validatorCTX <$> Validator ask+    failure $ fmap (unused ctx) x -checkUnused :: (KeyOf b, KEY a ~ KEY b, Selectable ca a, Unused ctx b) => ca -> [b] -> Validator ctx ()+checkUnused ::+  ( KeyOf k b,+    Selectable k a ca,+    Unused ctx b+  ) =>+  ca ->+  [b] ->+  Validator s ctx () checkUnused uses = failOnUnused . getUnused uses  constraint ::-  forall (a :: Target) inp ctx.   KindViolation a inp =>   Constraint (a :: Target) ->   inp ->-  TypeDefinition ANY ->-  Validator ctx (Resolution a)-constraint OBJECT _ TypeDefinition {typeContent = DataObject {objectFields}, typeName} =-  pure (typeName, objectFields)+  TypeDefinition ANY s ->+  Validator s ctx (Resolution s a)+constraint IMPLEMENTABLE _ TypeDefinition {typeContent = DataObject {objectFields, ..}, ..} =+  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]  selectRequired ::-  ( Selectable c value,-    MissingRequired c ctx,-    KEY Ref ~ KEY value+  ( Selectable FieldName value c,+    MissingRequired c ctx   ) =>   Ref ->   c ->-  Validator ctx value+  Validator s ctx value selectRequired selector container =   do-    ctx <- Validator ask+    ValidatorContext {scope, validatorCTX} <- Validator ask     selectBy-      [missingRequired ctx selector container]+      [missingRequired scope validatorCTX selector container]       (keyOf selector)       container  selectWithDefaultValue ::-  forall ctx values value.-  ( Selectable values value,+  forall ctx values value s validValue.+  ( Selectable FieldName value values,     MissingRequired values ctx,-    KEY value ~ FieldName,-    GetWith ctx Scope,-    MonadContext Validator ctx+    MonadContext (Validator s) s ctx   ) =>-  (Value RESOLVED -> value) ->-  FieldDefinition IN ->+  (Value s -> Validator s ctx validValue) ->+  (value -> Validator s ctx validValue) ->+  FieldDefinition IN s ->   values ->-  Validator ctx value+  Validator s ctx validValue selectWithDefaultValue   f+  validateF   field@FieldDefinition     { fieldName,       fieldContent@@ -202,175 +231,53 @@   values =     selectOr       (handeNull fieldContent)-      pure+      validateF       fieldName       values     where       -------------------      handeNull :: Maybe (FieldContent TRUE IN) -> Validator ctx value-      handeNull (Just (DefaultInputValue value)) = pure $ f value+      handeNull ::+        Maybe (FieldContent TRUE IN s) ->+        Validator s ctx validValue+      handeNull (Just (DefaultInputValue value)) = f value       handeNull Nothing-        | isFieldNullable field = pure $ f Null+        | isNullable field = f Null         | otherwise = failSelection       -----------------       failSelection = do-        ctx <- Validator ask-        position <- asks position-        failure [missingRequired ctx (Ref fieldName position) values]+        ValidatorContext {scope, validatorCTX} <- Validator ask+        position <- asksScope position+        failure [missingRequired scope validatorCTX (Ref fieldName (fromMaybe (Position 0 0) position)) values] +selectType ::+  TypeName ->+  Validator s ctx (TypeDefinition ANY s)+selectType name =+  askSchema >>= selectBy err name+  where+    err = "Unknown Type " <> msgValidation name <> "." :: ValidationError+ selectKnown ::-  ( Selectable c a,-    Unknown c ctx,-    KeyOf sel,-    sel ~ UnknownSelector c,-    KEY sel ~ KEY a+  ( Selectable k a c,+    Unknown c sel ctx,+    KeyOf k sel   ) =>   sel ->   c ->-  Validator ctx a+  Validator s ctx a selectKnown selector lib =   do-    ctx <- Validator ask+    ValidatorContext {scope, validatorCTX} <- Validator ask     selectBy-      (unknown ctx lib selector)+      (unknown scope validatorCTX lib selector)       (keyOf selector)       lib -askFieldType ::-  FieldDefinition OUT ->-  SelectionValidator (TypeDefinition OUT)-askFieldType field@FieldDefinition {fieldType = TypeRef {typeConName}} =-  do-    schema <- askSchema-    anyType <--      selectBy-        [internalError field]-        typeConName-        schema-    case fromAny anyType of-      Just x -> pure x-      Nothing ->-        failure $-          "Type \"" <> msg (typeName anyType)-            <> "\" referenced by OBJECT \""-            <> "\" must be an OUTPUT_TYPE."--askTypeMember ::-  UnionMember OUT ->-  SelectionValidator (TypeName, FieldsDefinition OUT)-askTypeMember UnionMember {memberName} =-  askSchema-    >>= selectOr notFound pure memberName-    >>= constraintOBJECT-  where-    notFound = do-      scopeType <- asks typename-      failure $-        "Type \""-          <> msg memberName-          <> "\" referenced by union \""-          <> msg scopeType-          <> "\" can't found in Schema."-    ---------------------------------------    constraintOBJECT :: TypeDefinition ANY -> SelectionValidator (TypeName, FieldsDefinition OUT)-    constraintOBJECT TypeDefinition {typeName, typeContent} = con typeContent-      where-        con DataObject {objectFields} = pure (typeName, objectFields)-        con _ = do-          scopeType <- asks typename-          failure $-            "Type \"" <> msg typeName-              <> "\" referenced by union \""-              <> msg scopeType-              <> "\" must be an OBJECT."--askInputFieldType ::-  ( Failure GQLErrors (m c),-    Failure Message (m c),-    Monad (m c),-    GetWith c Schema,-    MonadContext m c-  ) =>-  FieldDefinition IN ->-  m c (TypeDefinition IN)-askInputFieldType field@FieldDefinition {fieldName, fieldType = TypeRef {typeConName}} =-  askSchema-    >>= selectBy-      [internalError field]-      typeConName-    >>= constraintINPUT-  where-    constraintINPUT ::-      ( Failure Message m,-        Monad m-      ) =>-      TypeDefinition ANY ->-      m (TypeDefinition IN)-    constraintINPUT x = case (fromAny x :: Maybe (TypeDefinition IN)) of-      Just inputType -> pure inputType-      Nothing ->-        failure $-          "Type \""-            <> msg (typeName x)-            <> "\" referenced by field \""-            <> msg fieldName-            <> "\" must be an input type."--askInputMember ::-  ( GetWith c Schema,-    GetWith c Scope,-    Failure Message (m c),-    Monad (m c),-    MonadContext m c-  ) =>-  TypeName ->-  m c (TypeDefinition IN)-askInputMember name =-  askSchema-    >>= selectOr notFound pure name-    >>= constraintINPUT_OBJECT-  where-    typeInfo tName =-      "Type \"" <> msg tName <> "\" referenced by inputUnion "-    notFound = do-      scopeType <- asks typename-      failure $-        typeInfo name-          <> msg scopeType-          <> "\" can't found in Schema."-    ---------------------------------------    constraintINPUT_OBJECT ::-      ( Monad (m c),-        GetWith c Scope,-        Failure Message (m c),-        MonadContext m c-      ) =>-      TypeDefinition ANY ->-      m c (TypeDefinition IN)-    constraintINPUT_OBJECT TypeDefinition {typeContent, ..} = con (fromAny typeContent)-      where-        con ::-          ( Monad (m c),-            GetWith c Scope,-            Failure Message (m c),-            MonadContext m c-          ) =>-          Maybe (TypeContent a IN) ->-          m c (TypeDefinition IN)-        con (Just content@DataInputObject {}) = pure TypeDefinition {typeContent = content, ..}-        con _ = do-          scopeType <- asks typename-          failure $-            typeInfo typeName-              <> "\""-              <> msg scopeType-              <> "\" must be an INPUT_OBJECT."- constraintInputUnion ::-  forall stage.-  [UnionMember IN] ->+  forall stage schemaStage.+  [UnionMember IN schemaStage] ->   Object stage ->-  Either Message (TypeName, Maybe (Value stage))+  Either Message (UnionMember IN schemaStage, Maybe (Value stage)) constraintInputUnion tags hm = do   (enum :: Value stage) <-     entryValue@@ -381,24 +288,26 @@         )         __inputname         hm-  tyName <- isPosibeInputUnion tags enum+  unionMember <- isPosibeInputUnion tags enum   case size hm of-    1 -> pure (tyName, Nothing)+    1 -> pure (unionMember, Nothing)     2 -> do       value <-         entryValue           <$> selectBy             ( "value for Union \""-                <> msg tyName+                <> msg unionMember                 <> "\" was not Provided."             )-            (toFieldName tyName)+            (toFieldName $ memberName unionMember)             hm-      pure (tyName, Just value)+      pure (unionMember, Just value)     _ -> failure ("input union can have only one variant." :: Message) -isPosibeInputUnion :: [UnionMember IN] -> Value stage -> Either Message TypeName-isPosibeInputUnion tags (Enum name)-  | name `elem` map memberName tags = pure name-  | otherwise = failure $ msg name <> " is not posible union type"+isPosibeInputUnion :: [UnionMember IN s] -> Value stage -> Either Message (UnionMember IN s)+isPosibeInputUnion tags (Enum name) =+  selectBy+    (msg name <> " is not posible union type")+    name+    tags isPosibeInputUnion _ _ = failure $ "\"" <> msg __inputname <> "\" must be Enum"
src/Data/Morpheus/Types/Internal/Validation/Error.hs view
@@ -1,27 +1,28 @@ {-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Types.Internal.Validation.Error   ( MissingRequired (..),     KindViolation (..),     Unknown (..),-    InternalError (..),     Target (..),     Unused (..),   ) where  -- MORPHEUS-+import Data.Maybe (maybeToList) import Data.Morpheus.Error.Selection (unknownSelectionField)-import Data.Morpheus.Error.Utils (errorMessage) import Data.Morpheus.Types.Internal.AST   ( Argument (..),     Arguments,+    CONST,     Directive (..),     DirectiveDefinition (..),     DirectiveDefinitions,@@ -29,25 +30,21 @@     FieldsDefinition,     Fragment (..),     Fragments,-    GQLError (..),-    GQLErrors,     IN,     OUT,     Object,     ObjectEntry (..),-    RAW,-    RESOLVED,     Ref (..),     Schema,     TypeNameRef (..),     TypeRef (..),+    ValidationError (..),     Variable (..),     VariableDefinitions,     getOperationName,     msg,-  )-import Data.Morpheus.Types.Internal.Validation.SchemaValidator-  ( TypeSystemContext,+    msgValidation,+    withPosition,   ) import Data.Morpheus.Types.Internal.Validation.Validator   ( CurrentSelection (..),@@ -59,206 +56,155 @@     renderInputPrefix,   ) import Data.Semigroup ((<>))--class InternalError a where-  internalError :: a -> GQLError--instance InternalError (FieldDefinition cat) where-  internalError-    FieldDefinition-      { fieldName,-        fieldType = TypeRef {typeConName}-      } =-      GQLError-        { message =-            "INTERNAL: Type " <> msg typeConName-              <> " referenced by field "-              <> msg fieldName-              <> " can't found in Schema ",-          locations = []-        }+import Prelude (($))  class Unused ctx c where-  unused :: ctx -> c -> GQLError+  unused :: ctx -> c -> ValidationError  -- query M ( $v : String ) { a } -> "Variable \"$bla\" is never used in operation \"MyMutation\".",-instance Unused (OperationContext v) (Variable s) where+instance Unused (OperationContext s1 s2) (Variable s) where   unused     OperationContext {selection = CurrentSelection {operationName}}     Variable {variableName, variablePosition} =-      GQLError-        { message =+      ValidationError+        { validationMessage =             "Variable " <> msg ("$" <> variableName)               <> " is never used in operation "               <> msg (getOperationName operationName)               <> ".",-          locations = [variablePosition]+          validationLocations = [variablePosition]         } -instance Unused (OperationContext v) Fragment where+instance Unused (OperationContext s1 s2) (Fragment s) where   unused     _     Fragment {fragmentName, fragmentPosition} =-      GQLError-        { message =+      ValidationError+        { validationMessage =             "Fragment " <> msg fragmentName               <> " is never used.",-          locations = [fragmentPosition]+          validationLocations = [fragmentPosition]         }  class MissingRequired c ctx where-  missingRequired :: ctx -> Ref -> c -> GQLError+  missingRequired :: Scope -> ctx -> Ref -> c -> ValidationError -instance MissingRequired (Arguments s) (OperationContext v) where+instance MissingRequired (Arguments s) ctx where   missingRequired-    OperationContext-      { scope = Scope {position, kind},-        selection = CurrentSelection {selectionName}-      }+    Scope {position, kind, fieldname}+    _     Ref {refName}     _ =-      GQLError-        { message =+      ValidationError+        { validationMessage =             inScope kind               <> " argument "               <> msg refName               <> " is required but not provided.",-          locations = [position]+          validationLocations = maybeToList position         }       where-        inScope DIRECTIVE = "Directive " <> msg ("@" <> selectionName)-        inScope _ = "Field " <> msg selectionName--instance MissingRequired (Object s) (InputContext (OperationContext v)) where-  missingRequired-    input@InputContext-      { sourceContext =-          OperationContext-            { scope = Scope {position}-            }-      }-    Ref {refName}-    _ =-      GQLError-        { message =-            renderInputPrefix input-              <> "Undefined Field "-              <> msg refName-              <> ".",-          locations = [position]-        }+        inScope DIRECTIVE = "Directive " <> msg ("@" <> fieldname)+        inScope _ = "Field " <> msg fieldname -instance MissingRequired (Object s) (InputContext (TypeSystemContext ctx)) where+instance MissingRequired (Object s) (InputContext ctx) where   missingRequired-    input+    Scope {position}+    ctx     Ref {refName}     _ =-      GQLError-        { message =-            renderInputPrefix input-              <> "Undefined Field "-              <> msg refName-              <> ".",-          locations = []-        }+      withPosition+        position+        ( renderInputPrefix+            ctx+            <> "Undefined Field "+            <> msgValidation refName+            <> "."+        ) -instance MissingRequired (VariableDefinitions s) (OperationContext v) where+instance MissingRequired (VariableDefinitions s) (OperationContext s1 s2) where   missingRequired+    _     OperationContext       { selection = CurrentSelection {operationName}       }     Ref {refName, refPosition}     _ =-      GQLError-        { message =+      ValidationError+        { validationMessage =             "Variable "               <> msg refName               <> " is not defined by operation "               <> msg (getOperationName operationName)               <> ".",-          locations = [refPosition]+          validationLocations = [refPosition]         } -class Unknown c ctx where-  type UnknownSelector c-  unknown :: ctx -> c -> UnknownSelector c -> GQLErrors+class Unknown c ref ctx where+  -- type UnknownSelector c+  unknown :: Scope -> ctx -> c -> ref -> ValidationError  -- {...H} -> "Unknown fragment \"H\"."-instance Unknown Fragments ctx where-  type UnknownSelector Fragments = Ref-  unknown _ _ (Ref name pos) =-    errorMessage-      pos-      ("Unknown Fragment " <> msg name <> ".")--instance Unknown Schema ctx where-  type UnknownSelector Schema = TypeNameRef-  unknown _ _ TypeNameRef {typeNameRef, typeNamePosition} =-    errorMessage typeNamePosition ("Unknown type " <> msg typeNameRef <> ".")+instance Unknown (Fragments s) Ref ctx where+  unknown _ _ _ (Ref name pos) =+    ValidationError+      { validationMessage = "Unknown Fragment " <> msg name <> ".",+        validationLocations = [pos]+      } -instance Unknown (FieldDefinition OUT) ctx where-  type UnknownSelector (FieldDefinition OUT) = Argument RESOLVED-  unknown _ FieldDefinition {fieldName} Argument {argumentName, argumentPosition} =-    errorMessage-      argumentPosition-      ("Unknown Argument " <> msg argumentName <> " on Field " <> msg fieldName <> ".")+instance Unknown (Schema s) TypeNameRef ctx where+  unknown _ _ _ TypeNameRef {typeNameRef, typeNamePosition} =+    ValidationError+      { validationMessage = "Unknown type " <> msg typeNameRef <> ".",+        validationLocations = [typeNamePosition]+      } -instance Unknown (FieldsDefinition IN) (InputContext (OperationContext v)) where-  type UnknownSelector (FieldsDefinition IN) = ObjectEntry RESOLVED-  unknown-    input@InputContext {sourceContext = OperationContext {scope = Scope {position}}}-    _-    ObjectEntry {entryName} =-      [ GQLError-          { message = renderInputPrefix input <> "Unknown Field " <> msg entryName <> ".",-            locations = [position]-          }-      ]+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 (FieldsDefinition IN) (InputContext (TypeSystemContext ctx)) where-  type UnknownSelector (FieldsDefinition IN) = ObjectEntry RESOLVED+instance Unknown (FieldsDefinition IN s) (ObjectEntry valueS) (InputContext ctx) where   unknown-    input+    Scope {position}+    ctx     _     ObjectEntry {entryName} =-      [ GQLError-          { message = renderInputPrefix input <> "Unknown Field " <> msg entryName <> ".",-            locations = []-          }-      ]+      withPosition position $+        renderInputPrefix ctx <> "Unknown Field " <> msgValidation entryName <> "." -instance Unknown DirectiveDefinition ctx where-  type UnknownSelector DirectiveDefinition = Argument RESOLVED-  unknown _ DirectiveDefinition {directiveDefinitionName} Argument {argumentName, argumentPosition} =-    errorMessage-      argumentPosition-      ("Unknown Argument " <> msg argumentName <> " on Directive " <> msg directiveDefinitionName <> ".")+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 ctx where-  type UnknownSelector DirectiveDefinitions = Directive RAW-  unknown _ _ Directive {directiveName, directivePosition} =-    errorMessage-      directivePosition-      ("Unknown Directive " <> msg directiveName <> ".")+instance Unknown (DirectiveDefinitions s) (Directive s') ctx where+  unknown _ _ _ Directive {directiveName, directivePosition} =+    ValidationError+      { validationMessage = "Unknown Directive " <> msg directiveName <> ".",+        validationLocations = [directivePosition]+      } -instance Unknown (FieldsDefinition OUT) (OperationContext v) where-  type UnknownSelector (FieldsDefinition OUT) = Ref-  unknown OperationContext {scope = Scope {typename}} _ =-    unknownSelectionField typename+instance Unknown (FieldsDefinition OUT s) Ref (OperationContext s1 s2) where+  unknown Scope {currentTypeName} _ _ = unknownSelectionField currentTypeName  class KindViolation (t :: Target) ctx where-  kindViolation :: c t -> ctx -> GQLError+  kindViolation :: c t -> ctx -> ValidationError -instance KindViolation 'TARGET_OBJECT Fragment where+instance KindViolation 'TARGET_IMPLEMENTABLE (Fragment s) where   kindViolation _ Fragment {fragmentName, fragmentType, fragmentPosition} =-    GQLError-      { message =+    ValidationError+      { validationMessage =           "Fragment "             <> msg fragmentName             <> " cannot condition on non composite type "             <> msg fragmentType             <> ".",-        locations = [fragmentPosition]+        validationLocations = [fragmentPosition]       }  instance KindViolation 'TARGET_INPUT (Variable s) where@@ -269,12 +215,12 @@         variablePosition,         variableType = TypeRef {typeConName}       } =-      GQLError-        { message =+      ValidationError+        { validationMessage =             "Variable "               <> msg ("$" <> variableName)               <> " cannot be non-input type "               <> msg typeConName               <> ".",-          locations = [variablePosition]+          validationLocations = [variablePosition]         }
+ src/Data/Morpheus/Types/Internal/Validation/Internal.hs view
@@ -0,0 +1,184 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE NoImplicitPrelude #-}++module Data.Morpheus.Types.Internal.Validation.Internal+  ( askType,+    askTypeMember,+    getOperationType,+    askInterfaceTypes,+  )+where++-- MORPHEUS++import Control.Applicative (Applicative, pure)+import Control.Monad ((>=>), Monad ((>>=)))+import Data.Functor ((<$>))+import Data.Maybe (Maybe (..), maybe)+import Data.Morpheus.Internal.Utils+  ( Failure (..),+    selectBy,+  )+import Data.Morpheus.Types.Internal.AST+  ( ANY,+    FieldsDefinition,+    FromCategory,+    IMPLEMENTABLE,+    IN,+    InternalError,+    OBJECT,+    OUT,+    Operation,+    Operation (..),+    Stage,+    TRUE,+    Token,+    TypeCategory,+    TypeContent (..),+    TypeContent,+    TypeDefinition (..),+    TypeName (..),+    TypeRef,+    Typed,+    UnionMember (..),+    VALID,+    fromAny,+    fromCategory,+    getOperationDataType,+    msgInternal,+    possibleInterfaceTypes,+    typeConName,+    typed,+    untyped,+  )+import Data.Morpheus.Types.Internal.Validation.Validator+  ( MonadContext,+    SelectionValidator,+    askSchema,+  )+import Data.Semigroup+  ( (<>),+  )+import Data.Traversable (traverse)+import Prelude+  ( ($),+    (.),+  )++askType ::+  Constraints m c cat s =>+  Typed cat s TypeRef ->+  m c (TypeDefinition cat s)+askType = untyped (__askType . typeConName)++askType2 ::+  Constraints m c cat s =>+  Typed cat s TypeName ->+  m c (TypeDefinition cat s)+askType2 = untyped __askType++__askType ::+  Constraints m c cat s => TypeName -> m c (TypeDefinition cat s)+__askType name =+  askSchema+    >>= selectBy (unknownType name) name+    >>= kindConstraint++askTypeMember ::+  Constraints m c cat s =>+  UnionMember cat s ->+  m c (TypeMemberResponse cat s)+askTypeMember = askType2 . typed memberName >=> constraintObject++askInterfaceTypes ::+  ( Failure InternalError (m c),+    Monad (m c),+    MonadContext m s c,+    FromCategory (TypeContent TRUE) ANY IMPLEMENTABLE+  ) =>+  TypeDefinition IMPLEMENTABLE s ->+  m c [TypeDefinition IMPLEMENTABLE s]+askInterfaceTypes typeDef@TypeDefinition {typeName} =+  (typeDef :)+    <$> ( askSchema+            >>= traverse (validate . fromCategory) . possibleInterfaceTypes typeName+        )+  where+    validate (Just x) = pure x+    validate Nothing = failure ("TODO: invalid interface Types" :: InternalError)++type family TypeMemberResponse (cat :: TypeCategory) (s :: Stage)++type instance TypeMemberResponse OUT s = TypeDefinition OBJECT s++type instance TypeMemberResponse IN s = (TypeDefinition IN s, FieldsDefinition IN s)++type Constraints m c cat s =+  ( Failure InternalError (m c),+    Monad (m c),+    MonadContext m s c,+    KindErrors cat,+    FromCategory (TypeContent TRUE) ANY cat+  )++getOperationType :: Operation a -> SelectionValidator (TypeDefinition OBJECT VALID)+getOperationType operation = askSchema >>= getOperationDataType operation++unknownType :: TypeName -> InternalError+unknownType name = "Type \"" <> msgInternal name <> "\" can't found in Schema."++type KindConstraint f c =+  ( Failure InternalError f,+    FromCategory TypeDefinition ANY c+  )++_kindConstraint ::+  KindConstraint f k =>+  Token ->+  TypeDefinition ANY s ->+  f (TypeDefinition k s)+_kindConstraint err anyType =+  maybe+    (failure $ violation err (typeName anyType))+    pure+    (fromAny anyType)++class KindErrors c where+  kindConstraint :: KindConstraint f c => TypeDefinition ANY s -> f (TypeDefinition c s)+  constraintObject ::+    ( Applicative f,+      Failure InternalError f+    ) =>+    TypeDefinition c s ->+    f (TypeMemberResponse c s)++instance KindErrors IN where+  kindConstraint = _kindConstraint "input type"+  constraintObject typeDef@TypeDefinition {typeContent = DataInputObject inputFields} = pure (typeDef, inputFields)+  constraintObject TypeDefinition {typeName} = failure (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)++violation ::+  Token ->+  TypeName ->+  InternalError+violation kind typeName =+  "Type \"" <> msgInternal typeName+    <> "\" must be an"+    <> msgInternal kind+    <> "."
src/Data/Morpheus/Types/Internal/Validation/SchemaValidator.hs view
@@ -10,10 +10,10 @@ {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TupleSections #-} {-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Types.Internal.Validation.SchemaValidator   ( SchemaValidator,-    selectType,     TypeSystemContext (..),     constraintInterface,     inField,@@ -26,35 +26,28 @@   ) where -import Control.Monad.Reader (asks) --import Data.Morpheus.Error.Document.Interface (unknownInterface)-import Data.Morpheus.Error.Utils (globalErrorMessage)+ -- MORPHEUS +import Control.Applicative (pure) import Data.Morpheus.Internal.Utils   ( Failure (..),-    fromElems,-    selectBy,   ) import Data.Morpheus.Types.Internal.AST   ( ANY,+    CONST,     FieldName,     FieldsDefinition,     OUT,-    Position (..),-    Schema,     TypeContent (..),     TypeDefinition (..),     TypeName,-    msg,+    ValidationError,+    msgValidation,   )-import Data.Morpheus.Types.Internal.Resolving (Result (..)) import Data.Morpheus.Types.Internal.Validation.Validator-  ( GetWith (..),-    Scope (..),-    ScopeKind (..),-    SetWith (..),-    Validator (..),+  ( Validator (..),     renderField,     withContext,   )@@ -62,36 +55,16 @@   ( (<>),     Semigroup (..),   )+import Prelude+  ( (.),+    Show (..),+    const,+  ) -data TypeSystemContext c = TypeSystemContext-  { types :: [TypeDefinition ANY],-    local :: c-  }+newtype TypeSystemContext c = TypeSystemContext+  {local :: c}   deriving (Show) -instance GetWith (TypeSystemContext ctx) Schema where-  getWith ctx = case fromElems (types ctx) of-    Success {result} -> result-    Failure {errors} -> error (show errors)--instance GetWith (TypeSystemContext a) Scope where-  getWith _ =-    Scope-      { position = Position {line = 0, column = 0},-        typename = "TODO:",-        kind = TYPE-      }--instance SetWith (TypeSystemContext a) Scope where-  setWith _ = id --TODO:--selectType :: TypeName -> SchemaValidator ctx (TypeDefinition ANY)-selectType name =-  asks types-    >>= selectBy err name-  where-    err = globalErrorMessage $ "Unknown Type " <> msg name <> "."- inType ::   TypeName ->   SchemaValidator TypeName v ->@@ -126,19 +99,21 @@     fieldArgument :: FieldName   } -withLocalContext :: (a -> b) -> Validator (TypeSystemContext b) v -> Validator (TypeSystemContext a) v+withLocalContext :: (a -> b) -> SchemaValidator b v -> SchemaValidator a v withLocalContext = withContext . updateLocal  updateLocal :: (a -> b) -> TypeSystemContext a -> TypeSystemContext b updateLocal f ctx = ctx {local = f (local ctx)} -type SchemaValidator c = Validator (TypeSystemContext c)+type SchemaValidator c = Validator CONST (TypeSystemContext c) -constraintInterface :: TypeDefinition ANY -> SchemaValidator ctx (TypeName, FieldsDefinition OUT)+constraintInterface ::+  TypeDefinition ANY CONST ->+  SchemaValidator ctx (TypeName, FieldsDefinition OUT CONST) constraintInterface   TypeDefinition     { typeName,       typeContent = DataInterface fields     } = pure (typeName, fields) constraintInterface TypeDefinition {typeName} =-  failure $ globalErrorMessage $ "type " <> msg typeName <> " must be an interface"+  failure ["type " <> msgValidation typeName <> " must be an interface" :: ValidationError]
src/Data/Morpheus/Types/Internal/Validation/Validator.hs view
@@ -1,16 +1,19 @@ {-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Types.Internal.Validation.Validator   ( Validator (..),@@ -22,7 +25,7 @@     withScope,     withScopeType,     withPosition,-    withInputScope,+    inField,     inputMessagePrefix,     InputSource (..),     InputContext (..),@@ -43,53 +46,81 @@     withContext,     renderField,     asks,+    asksScope,     askSchema,     askVariables,     askFragments,+    DirectiveValidator,+    ValidatorContext (..),+    FragmentValidator,   ) where -import Control.Monad.Reader (MonadReader)+-- MORPHEUS++import Control.Applicative (Applicative)+import Control.Monad (Monad)+import Control.Monad.Reader (MonadReader (..)) import Control.Monad.Trans.Class (MonadTrans (..)) import Control.Monad.Trans.Reader   ( ReaderT (..),-    ask,     withReaderT,   )--- MORPHEUS+import Data.Functor ((<$>), Functor (..))+import Data.Maybe (Maybe (..))+import Data.Morpheus.Error.Utils+  ( validationErrorMessage,+  ) import Data.Morpheus.Internal.Utils   ( Failure (..),   )+import Data.Morpheus.Rendering.RenderGQL (RenderGQL (..)) import Data.Morpheus.Types.Internal.AST-  ( Argument (..),-    Directive (..),+  ( Directive (..),+    FieldDefinition (..),     FieldName (..),-    FieldsDefinition,     Fragments,     GQLError (..),     GQLErrors,+    IMPLEMENTABLE,     IN,+    InternalError,     Message,-    OUT,     Position,     RAW,-    RESOLVED,     Ref (..),     Schema,-    TypeDefinition,+    Stage,+    TypeDefinition (..),+    TypeKind (..),     TypeName (..),+    TypeRef (..),+    TypeWrapper,     VALID,+    ValidationError (..),     Variable (..),     VariableDefinitions,     intercalateName,+    kindOf,     msg,+    msgValidation,   )+import Data.Morpheus.Types.Internal.Config (Config (..)) import Data.Morpheus.Types.Internal.Resolving   ( Eventless,   ) import Data.Semigroup   ( (<>),+    stimes,   )+import Prelude+  ( ($),+    (.),+    Bool,+    Int,+    Show,+    otherwise,+  )  data Prop = Prop   { propName :: FieldName,@@ -99,25 +130,25 @@  type Path = [Prop] -renderPath :: Path -> Message+renderPath :: Path -> ValidationError renderPath [] = ""-renderPath path = "in field " <> msg (intercalateName "." $ map propName path) <> ": "+renderPath path = "in field " <> msgValidation (intercalateName "." $ fmap propName path) <> ": " -renderInputPrefix :: InputContext c -> Message+renderInputPrefix :: InputContext c -> ValidationError renderInputPrefix InputContext {inputPath, inputSource} =   renderSource inputSource <> renderPath inputPath -renderSource :: InputSource -> Message-renderSource (SourceArgument Argument {argumentName}) =-  "Argument " <> msg argumentName <> " got invalid value. "+renderSource :: InputSource -> ValidationError+renderSource (SourceArgument argumentName) =+  "Argument " <> msgValidation argumentName <> " got invalid value. " renderSource (SourceVariable Variable {variableName} _) =-  "Variable " <> msg ("$" <> variableName) <> " got invalid value. "+  "Variable " <> msgValidation ("$" <> variableName) <> " got invalid value. " renderSource SourceInputField {sourceTypeName, sourceFieldName, sourceArgumentName} =   "Field " <> renderField sourceTypeName sourceFieldName sourceArgumentName <> " got invalid default value. " -renderField :: TypeName -> FieldName -> Maybe FieldName -> Message+renderField :: TypeName -> FieldName -> Maybe FieldName -> ValidationError renderField (TypeName tname) (FieldName fname) arg =-  msg (tname <> "." <> fname <> renderArg arg)+  msgValidation (tname <> "." <> fname <> renderArg arg)   where     renderArg (Just (FieldName argName)) = "(" <> argName <> ":)"     renderArg Nothing = ""@@ -128,24 +159,27 @@   | TYPE   deriving (Show) -data OperationContext vars = OperationContext-  { schema :: Schema,-    scope :: Scope,-    fragments :: Fragments,-    selection :: CurrentSelection,-    variables :: vars+data+  OperationContext+    (s1 :: Stage)+    (s2 :: Stage) = OperationContext+  { fragments :: Fragments s2,+    variables :: VariableDefinitions s1,+    selection :: CurrentSelection   }   deriving (Show) -data CurrentSelection = CurrentSelection-  { operationName :: Maybe FieldName,-    selectionName :: FieldName+newtype CurrentSelection = CurrentSelection+  { operationName :: Maybe FieldName   }   deriving (Show)  data Scope = Scope-  { position :: Position,-    typename :: TypeName,+  { position :: Maybe Position,+    currentTypeName :: TypeName,+    currentTypeKind :: TypeKind,+    currentTypeWrappers :: [TypeWrapper],+    fieldname :: FieldName,     kind :: ScopeKind   }   deriving (Show)@@ -158,7 +192,7 @@   deriving (Show)  data InputSource-  = SourceArgument (Argument RESOLVED)+  = SourceArgument FieldName   | SourceVariable       { sourceVariable :: Variable RAW,         isDefaultValue :: Bool@@ -171,95 +205,102 @@   deriving (Show)  data Target-  = TARGET_OBJECT+  = TARGET_IMPLEMENTABLE   | TARGET_INPUT  data Constraint (a :: Target) where-  OBJECT :: Constraint 'TARGET_OBJECT+  IMPLEMENTABLE :: Constraint 'TARGET_IMPLEMENTABLE   INPUT :: Constraint 'TARGET_INPUT  --  UNION  :: Constraint 'TARGET_UNION -type family Resolution (a :: Target)+type family Resolution (s :: Stage) (a :: Target) -type instance Resolution 'TARGET_OBJECT = (TypeName, FieldsDefinition OUT)+type instance Resolution s 'TARGET_IMPLEMENTABLE = TypeDefinition IMPLEMENTABLE s -type instance Resolution 'TARGET_INPUT = TypeDefinition IN+type instance Resolution s 'TARGET_INPUT = TypeDefinition IN s -withInputScope :: Prop -> InputValidator c a -> InputValidator c a-withInputScope prop = withContext update-  where-    update-      InputContext-        { inputPath = old,-          ..-        } =+inField :: FieldDefinition IN s -> InputValidator s c a -> InputValidator s c a+inField+  FieldDefinition+    { fieldName,+      fieldType = TypeRef {typeConName}+    } = withContext update+    where+      update         InputContext-          { inputPath = old <> [prop],+          { inputPath = old,             ..-          }+          } =+          InputContext+            { inputPath = old <> [Prop fieldName typeConName],+              ..+            }  inputValueSource ::-  forall m c.+  forall m c s.   ( GetWith c InputSource,-    MonadContext m c+    MonadContext m s c   ) =>   m c InputSource inputValueSource = get  asks ::-  ( MonadContext m c,+  ( MonadContext m s c,     GetWith c t   ) =>   (t -> a) ->   m c a asks f = f <$> get -setSelectionName ::-  ( MonadContext m c,-    SetWith c CurrentSelection+asksScope ::+  ( MonadContext m s c   ) =>+  (Scope -> a) ->+  m c a+asksScope f = f <$> getGlobalContext scope++setSelectionName ::+  (MonadContext m s c) =>   FieldName ->   m c a ->   m c a-setSelectionName selectionName = set update+setSelectionName fieldname = setScope update   where-    update ctx = ctx {selectionName}+    update ctx = ctx {fieldname}  askSchema ::-  ( MonadContext m c,-    GetWith c Schema+  ( MonadContext m s c   ) =>-  m c Schema-askSchema = get+  m c (Schema s)+askSchema = getGlobalContext schema  askVariables ::-  ( MonadContext m c,+  ( MonadContext m s c,     GetWith c (VariableDefinitions VALID)   ) =>   m c (VariableDefinitions VALID) askVariables = get  askFragments ::-  ( MonadContext m c,-    GetWith c Fragments+  ( MonadContext m s c,+    GetWith c (Fragments s')   ) =>-  m c Fragments+  m c (Fragments s') askFragments = get -runValidator :: Validator ctx a -> ctx -> Eventless a-runValidator (Validator x) = runReaderT x+runValidator :: Validator s ctx a -> Config -> Schema s -> Scope -> ctx -> Eventless a+runValidator (Validator x) config schema scope validatorCTX =+  runReaderT x ValidatorContext {..}  withContext ::   (c' -> c) ->-  Validator c a ->-  Validator c' a-withContext f = Validator . withReaderT f . _runValidator+  Validator s c a ->+  Validator s c' a+withContext f = Validator . withReaderT (fmap f) . _runValidator  withDirective ::-  ( SetWith c CurrentSelection,-    SetWith c Scope,-    MonadContext m c+  ( MonadContext m schemaS c   ) =>   Directive s ->   m c a ->@@ -268,58 +309,68 @@   Directive     { directiveName,       directivePosition-    } = setSelectionName directiveName . set update+    } = setSelectionName directiveName . setScope update     where       update Scope {..} =         Scope-          { position = directivePosition,+          { position = Just directivePosition,             kind = DIRECTIVE,             ..           }  withScope ::-  ( SetWith c CurrentSelection,-    MonadContext m c,-    SetWith c Scope+  ( MonadContext m s c   ) =>-  TypeName ->+  TypeDefinition cat s ->   Ref ->   m c a ->   m c a-withScope typeName (Ref selName pos) =-  setSelectionName selName . set update+withScope t@TypeDefinition {typeName} (Ref selName pos) =+  setSelectionName selName . setScope update   where-    update Scope {..} = Scope {typename = typeName, position = pos, ..}+    update Scope {..} =+      Scope+        { currentTypeName = typeName,+          currentTypeKind = kindOf t,+          position = Just pos,+          ..+        } -withPosition ::-  ( MonadContext m c,-    SetWith c Scope+withScopeType ::+  ( MonadContext m s c   ) =>-  Position ->+  (TypeDefinition cat s, [TypeWrapper]) ->   m c a ->   m c a-withPosition pos = set update+withScopeType (t@TypeDefinition {typeName}, wrappers) = setScope update   where-    update Scope {..} = Scope {position = pos, ..}+    update Scope {..} =+      Scope+        { currentTypeName = typeName,+          currentTypeKind = kindOf t,+          currentTypeWrappers = wrappers,+          ..+        } -withScopeType ::-  ( MonadContext m c,-    SetWith c Scope+withPosition ::+  ( MonadContext m s c   ) =>-  TypeName ->+  Position ->   m c a ->   m c a-withScopeType name = set update+withPosition pos = setScope update   where-    update Scope {..} = Scope {typename = name, ..}+    update Scope {..} = Scope {position = Just pos, ..} -inputMessagePrefix :: InputValidator ctx Message-inputMessagePrefix = renderInputPrefix <$> Validator ask+inputMessagePrefix :: InputValidator s ctx ValidationError+inputMessagePrefix =+  renderInputPrefix+    . validatorCTX <$> Validator ask  startInput ::   InputSource ->-  InputValidator ctx a ->-  Validator ctx a+  InputValidator s ctx a ->+  Validator s ctx a startInput inputSource = withContext update   where     update sourceContext =@@ -329,114 +380,166 @@           sourceContext         } -newtype Validator ctx a = Validator+data ValidatorContext (s :: Stage) (ctx :: *) = ValidatorContext+  { scope :: Scope,+    schema :: Schema s,+    validatorCTX :: ctx,+    config :: Config+  }+  deriving (Show, Functor)++newtype Validator s ctx a = Validator   { _runValidator ::       ReaderT-        ctx+        (ValidatorContext s ctx)         Eventless         a   }   deriving newtype     ( Functor,       Applicative,-      Monad,-      MonadReader ctx+      Monad     ) -type BaseValidator = Validator (OperationContext ())+instance MonadReader ctx (Validator s ctx) where+  ask = validatorCTX <$> Validator ask+  local = withContext -type SelectionValidator = Validator (OperationContext (VariableDefinitions VALID))+type BaseValidator = Validator VALID (OperationContext RAW RAW) -type InputValidator ctx = Validator (InputContext ctx)+type FragmentValidator (s :: Stage) = Validator VALID (OperationContext VALID s) --- Helpers-get :: (MonadContext m ctx, GetWith ctx a) => m ctx a-get = getContext getWith+type SelectionValidator = Validator VALID (OperationContext VALID VALID) -set ::-  ( MonadContext m c,-    SetWith c a-  ) =>-  (a -> a) ->+type InputValidator s ctx = Validator s (InputContext ctx)++type DirectiveValidator ctx = Validator ctx++setScope ::+  (MonadContext m s c) =>+  (Scope -> Scope) ->   m c b ->   m c b-set f = setContext (setWith f)+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 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 c where-  getContext f = f <$> Validator ask+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 v) Scope where-  getWith = scope--instance GetWith c Scope => GetWith (InputContext c) Scope where-  getWith = getWith . sourceContext--instance GetWith (OperationContext c) Schema where-  getWith = schema--instance GetWith c Schema => GetWith (InputContext c) Schema where-  getWith = getWith . sourceContext--instance GetWith (OperationContext (VariableDefinitions VALID)) (VariableDefinitions VALID) where+instance GetWith (OperationContext VALID fragStage) (VariableDefinitions VALID) where   getWith = variables  instance GetWith (InputContext ctx) InputSource where   getWith = inputSource -instance GetWith (OperationContext v) Fragments where+instance GetWith (OperationContext varStage fragStage) (Fragments fragStage) where   getWith = fragments  -- Setters class SetWith (c :: *) (v :: *) where   setWith :: (v -> v) -> c -> c -instance SetWith (OperationContext v) CurrentSelection where+instance SetWith (OperationContext s1 s2) CurrentSelection where   setWith f OperationContext {selection = selection, ..} =     OperationContext       { selection = f selection,         ..       } -instance SetWith (OperationContext v) Scope where-  setWith f OperationContext {..} =-    OperationContext-      { scope = f scope,-        ..-      }+instance Failure [ValidationError] (Validator s ctx) where+  failure errors = do+    ctx <- Validator ask+    failValidator (fmap (fromValidatinError ctx) errors) -instance SetWith c Scope => SetWith (InputContext c) Scope where-  setWith f InputContext {..} =-    InputContext-      { sourceContext = setWith f sourceContext,-        ..+instance Failure ValidationError (Validator s ctx) where+  failure err = failure [err]++failValidator :: GQLErrors -> Validator s ctx a+failValidator = Validator . lift . failure++fromValidatinError :: ValidatorContext s ctx -> ValidationError -> GQLError+fromValidatinError+  context@ValidatorContext+    { config+    }+  (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 ctx,-    GetWith ctx Scope-  ) =>-  Failure Message (Validator ctx)+  (MonadContext (Validator s) s ctx) =>+  Failure InternalError (Validator s ctx)   where   failure inputMessage = do-    position <- asks position+    ctx <- Validator ask     failure-      [ GQLError-          { message = "INTERNAL: " <> inputMessage,-            locations = [position]-          }-      ]+      ( validationErrorMessage+          (position $ scope ctx)+          $ msg+            inputMessage+            <> renderContext ctx+      ) -instance Failure GQLErrors (Validator ctx) where-  failure = Validator . lift . failure+renderContext :: ValidatorContext s ctx -> Message+renderContext+  ValidatorContext+    { schema,+      scope+    } =+    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
@@ -1,18 +1,30 @@ {-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE NoImplicitPrelude #-}  -- | -- Module      : Data.Morpheus.Types.SelectionTree -- Description : A simple interface for Morpheus internal Selection Set's representation. module Data.Morpheus.Types.SelectionTree where +import Data.Bool (Bool (..))+import Data.Foldable (concatMap)+import Data.Monoid (mempty) import Data.Morpheus.Internal.Utils (elems, keyOf)-import Data.Morpheus.Types.Internal.AST.Base (FieldName, VALID)-import Data.Morpheus.Types.Internal.AST.Selection-  ( Selection (..),+import Data.Morpheus.Types.Internal.AST+  ( FieldName (..),+    Selection (..),     Selection (selectionContent),-    SelectionContent (SelectionField, SelectionSet),+    SelectionContent (SelectionField, SelectionSet, UnionSelection),+    UnionTag (..),+    VALID,   )+import Data.String+  ( IsString (..),+  )+import Data.Text (unpack)+import Prelude ((.))  -- | The 'SelectionTree' instance is a simple interface for interacting -- with morpheus's internal AST while keeping the ability to safely change the concrete@@ -26,7 +38,7 @@   getChildrenList :: nodeType -> [nodeType]    -- | get a node's name-  getName :: nodeType -> FieldName+  getName :: IsString name => nodeType -> name  instance SelectionTree (Selection VALID) where   isLeaf node = case selectionContent node of@@ -36,5 +48,13 @@   getChildrenList node = case selectionContent node of     SelectionField -> mempty     (SelectionSet deeperSel) -> elems deeperSel+    (UnionSelection sel) ->+      concatMap+        (elems . unionTagSelection)+        (elems sel) -  getName = keyOf+  getName =+    fromString+      . unpack+      . readName+      . keyOf
src/Data/Morpheus/Validation/Document/Validation.hs view
@@ -1,62 +1,84 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DataKinds #-} {-# LANGUAGE DuplicateRecordFields #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-}+{-# LANGUAGE KindSignatures #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Validation.Document.Validation-  ( validatePartialDocument,-    validateSchema,+  ( ValidateSchema (..),   ) where +import Control.Applicative ((*>), (<*>), Applicative (..), pure) import Control.Monad ((>=>)) import Control.Monad.Reader (asks) import Data.Foldable (traverse_)-import Data.Functor (($>))------ Morpheus-+import Data.Functor ((<$>), fmap)+import Data.Maybe (Maybe (..), maybe) import Data.Morpheus.Error.Document.Interface   ( ImplementsError (..),     PartialImplements (..),   ) import Data.Morpheus.Internal.Utils-  ( KeyOf (..),+  ( (<:>),+    KeyOf (..),     Selectable (..),     elems,     empty,     failure,+    ordTraverse,   )-import Data.Morpheus.Schema.Schema (systemTypes)+import Data.Morpheus.Schema.Schema+  ( internalSchema,+  ) import Data.Morpheus.Types.Internal.AST-  ( ANY,-    ArgumentDefinition,+  ( ArgumentDefinition,     ArgumentsDefinition (..),+    CONST,+    DataEnumValue (..),+    DirectiveDefinition (..),+    DirectiveLocation (..),     FieldContent (..),     FieldDefinition (..),     FieldName (..),     FieldsDefinition,     IN,     OUT,-    ObjectEntry (..),-    Schema,+    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.Resolving   ( Eventless,   ) import Data.Morpheus.Types.Internal.Validation   ( InputSource (..),     InputValidator,-    askInputFieldType,+    Scope (..),+    ScopeKind (..),     runValidator,+    selectType,     startInput,   ) import Data.Morpheus.Types.Internal.Validation.SchemaValidator@@ -69,82 +91,243 @@     inField,     inInterface,     inType,-    selectType,   )-import Data.Morpheus.Validation.Internal.Value (validateInput)-import Data.Semigroup ((<>))+import Data.Morpheus.Validation.Internal.Directive+  ( validateDirectives,+  )+import Data.Morpheus.Validation.Internal.Value+  ( validateInputByTypeRef,+  )+import Data.Proxy (Proxy (..))+import Data.Traversable (traverse)+import Prelude+  ( ($),+    (&&),+    (.),+    (==),+    Bool,+    not,+    otherwise,+  ) -validateSchema :: Schema -> Eventless Schema-validateSchema schema = validatePartialDocument (elems schema) $> schema+class ValidateSchema s where+  validateSchema :: Bool -> Config -> Schema s -> Eventless (Schema VALID) -validatePartialDocument :: [TypeDefinition ANY] -> Eventless [TypeDefinition ANY]-validatePartialDocument types =-  runValidator-    (traverse validateType types)-    TypeSystemContext-      { types = systemTypes <> types,-        local = ()-      }+instance ValidateSchema CONST where+  validateSchema+    withSystem+    config+    schema@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+ validateType ::-  TypeDefinition ANY ->-  SchemaValidator () (TypeDefinition ANY)+  TypeDefinition cat CONST ->+  SchemaValidator () (TypeDefinition cat VALID) validateType-  dt@TypeDefinition+  TypeDefinition     { typeName,-      typeContent =-        DataObject-          { objectImplements,-            objectFields-          }-    } = inType typeName $+      typeFingerprint,+      typeDescription,+      typeDirectives,+      typeContent+    } =+    inType typeName $+      TypeDefinition+        typeName+        typeFingerprint+        typeDescription+        <$> validateDirectives (typeDirectiveLocation typeContent) typeDirectives+        <*> validateTypeContent typeContent++typeDirectiveLocation :: TypeContent a b c -> DirectiveLocation+typeDirectiveLocation DataObject {} = OBJECT+typeDirectiveLocation DataInputObject {} = INPUT_OBJECT+typeDirectiveLocation DataScalar {} = SCALAR+typeDirectiveLocation DataEnum {} = ENUM+typeDirectiveLocation DataInputUnion {} = OBJECT+typeDirectiveLocation DataUnion {} = UNION+typeDirectiveLocation DataInterface {} = INTERFACE++validateTypeContent ::+  TypeContent TRUE cat CONST ->+  SchemaValidator TypeName (TypeContent TRUE cat VALID)+validateTypeContent+  DataObject+    { objectImplements,+      objectFields+    } =     do       validateImplements objectImplements objectFields-      traverse_ checkFieldArgsuments objectFields-      pure dt-validateType-  dt@TypeDefinition-    { typeContent = DataInputObject {inputObjectFields},-      typeName-    } = inType typeName $ do-    traverse_ validateFieldDefaultValue inputObjectFields-    pure dt-validateType x = pure x+      DataObject objectImplements <$> ordTraverse validateField objectFields+validateTypeContent DataInputObject {inputObjectFields} =+  DataInputObject <$> ordTraverse 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 <$> ordTraverse validateField fields +validateEnumMember ::+  DataEnumValue CONST -> SchemaValidator TypeName (DataEnumValue VALID)+validateEnumMember DataEnumValue {enumDirectives = directives, ..} = do+  enumDirectives <- validateDirectives ENUM_VALUE directives+  pure DataEnumValue {..}++validateUnionMember ::+  UnionMember cat CONST -> SchemaValidator TypeName (UnionMember cat VALID)+validateUnionMember UnionMember {..} = pure UnionMember {..}++class FieldDirectiveLocation (cat :: TypeCategory) where+  directiveLocation :: Proxy cat -> DirectiveLocation++instance FieldDirectiveLocation OUT where+  directiveLocation _ = FIELD_DEFINITION++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+        fieldName+        fieldDescription+        fieldType+        <$> validateDirectives (directiveLocation (Proxy @cat)) fieldDirectives+          <*> validateOptional (checkFieldContent field) fieldContent+    )++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 (ArgumentsDefinition meta args) =+  ArgumentsDefinition meta+    <$> ordTraverse+      validateArgumentDefinition+      args++validateArgumentDefinition ::+  ArgumentDefinition CONST ->+  SchemaValidator (TypeName, FieldName) (ArgumentDefinition VALID)+validateArgumentDefinition FieldDefinition {..} =+  FieldDefinition+    fieldName+    fieldDescription+    fieldType+    <$> validateDirectives ARGUMENT_DEFINITION fieldDirectives+    <*> validateOptional (validateArgumentDefaultValue fieldName fieldType) fieldContent++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 ->+  FieldsDefinition OUT CONST ->   SchemaValidator TypeName () validateImplements objectImplements objectFields = do   interface <- traverse selectInterface objectImplements   traverse_ (mustBeSubset objectFields) interface  mustBeSubset ::-  FieldsDefinition OUT -> (TypeName, FieldsDefinition OUT) -> SchemaValidator TypeName ()+  FieldsDefinition OUT CONST ->+  (TypeName, FieldsDefinition OUT CONST) ->+  SchemaValidator TypeName () mustBeSubset objFields (typeName, fields) =   inInterface typeName $     traverse_ (checkInterfaceField objFields) (elems fields)  checkInterfaceField ::-  FieldsDefinition OUT ->-  FieldDefinition OUT ->+  FieldsDefinition OUT CONST ->+  FieldDefinition OUT CONST ->   SchemaValidator Interface () checkInterfaceField   objFields   interfaceField@FieldDefinition-    { fieldName+    { fieldName,+      fieldDirectives     } =     inField fieldName $-      selectOr err (isSuptype interfaceField) fieldName objFields+      do+        _ <- 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) (Interface, FieldName) where+instance TypeEq (FieldDefinition OUT CONST) (Interface, FieldName) where   FieldDefinition     { fieldType,       fieldContent = args1@@ -154,10 +337,10 @@         fieldContent = args2       } = (fieldType `isSuptype` fieldType') *> (args1 `isSuptype` args2) -instance TypeEq (Maybe (FieldContent TRUE OUT)) (Interface, FieldName) where+instance TypeEq (Maybe (FieldContent TRUE OUT s)) (Interface, FieldName) where   f1 `isSuptype` f2 = toARgs f1 `isSuptype` toARgs f2     where-      toARgs :: Maybe (FieldContent TRUE OUT) -> ArgumentsDefinition+      toARgs :: Maybe (FieldContent TRUE OUT s) -> ArgumentsDefinition s       toARgs (Just (FieldArgs args)) = args       toARgs _ = empty @@ -175,8 +358,8 @@         failImplements UnexpectedType {expectedType = t1, foundType = t2}  elemIn ::-  ( KeyOf a,-    Selectable c a,+  ( KeyOf k a,+    Selectable k a c,     TypeEq a ctx   ) =>   a ->@@ -184,18 +367,18 @@   SchemaValidator ctx () elemIn el = selectOr (failImplements Missing) (isSuptype el) (keyOf el) -instance TypeEq ArgumentsDefinition (Interface, FieldName) where+instance TypeEq (ArgumentsDefinition s) (Interface, FieldName) where   args1 `isSuptype` args2 = traverse_ validateArg (elems args1)     where       validateArg arg = inArgument (keyOf arg) $ elemIn arg args2 -instance TypeEq ArgumentDefinition (Interface, Field) where+instance TypeEq (ArgumentDefinition s) (Interface, Field) where   arg1 `isSuptype` arg2 = fieldType arg1 `isSuptype` fieldType arg2  ------------------------------- selectInterface ::   TypeName ->-  SchemaValidator ctx (TypeName, FieldsDefinition OUT)+  SchemaValidator ctx (TypeName, FieldsDefinition OUT CONST) selectInterface = selectType >=> constraintInterface  failImplements ::@@ -206,47 +389,21 @@   x <- asks local   failure $ partialImplements x err -checkFieldArgsuments ::-  FieldDefinition OUT ->-  SchemaValidator TypeName ()-checkFieldArgsuments FieldDefinition {fieldContent = Nothing} = pure ()-checkFieldArgsuments FieldDefinition {fieldContent = Just (FieldArgs args), fieldName} = do-  typeName <- asks local-  traverse_ (validateArgumentDefaultValue typeName fieldName) (elems args)--validateArgumentDefaultValue ::-  TypeName ->-  FieldName ->-  ArgumentDefinition ->-  SchemaValidator TypeName ()-validateArgumentDefaultValue _ _ FieldDefinition {fieldContent = Nothing} = pure ()-validateArgumentDefaultValue-  typeName-  fName-  inputField@FieldDefinition {fieldName = argName} =-    startInput (SourceInputField typeName fName (Just argName)) $-      validateDefaultValue inputField- -- DEFAULT VALUE--- TODO: implement default value validation-validateFieldDefaultValue ::-  FieldDefinition IN ->-  SchemaValidator TypeName ()-validateFieldDefaultValue inputField@FieldDefinition {fieldName} = do-  typeName <- asks local-  startInput (SourceInputField typeName fieldName Nothing) $-    validateDefaultValue inputField  validateDefaultValue ::-  FieldDefinition IN ->-  InputValidator (TypeSystemContext TypeName) ()-validateDefaultValue FieldDefinition {fieldContent = Nothing} = pure ()-validateDefaultValue-  inputField@FieldDefinition-    { fieldName,-      fieldType = TypeRef {typeWrappers},-      fieldContent = Just DefaultInputValue {defaultInputValue}-    } = do-    datatype <- askInputFieldType inputField-    _ <- validateInput typeWrappers datatype (ObjectEntry fieldName defaultInputValue)-    pure ()+  TypeRef ->+  Value CONST ->+  InputValidator+    CONST+    (TypeSystemContext (TypeName, FieldName))+    (Value VALID)+validateDefaultValue typeRef =+  validateInputByTypeRef (Typed typeRef)++-- TODO: validate directives+validateDirectiveDefinition :: DirectiveDefinition CONST -> SchemaValidator () (DirectiveDefinition VALID)+validateDirectiveDefinition DirectiveDefinition {directiveDefinitionArgs = args, ..} =+  inType "Directive" $ inField directiveDefinitionName $ do+    directiveDefinitionArgs <- validateArgumentsDefinition args+    pure DirectiveDefinition {..}
+ src/Data/Morpheus/Validation/Internal/Arguments.hs view
@@ -0,0 +1,179 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE NoImplicitPrelude #-}++module Data.Morpheus.Validation.Internal.Arguments+  ( validateDirectiveArguments,+    validateFieldArguments,+    ArgumentsConstraints,+    Resolve,+  )+where++import Control.Applicative ((*>), pure)+import Control.Monad ((>=>), (>>=))+import Data.Functor ((<$>), fmap)+import Data.Maybe (fromMaybe, maybe)+import Data.Morpheus.Internal.Utils+  ( empty,+    ordTraverse,+    ordTraverse_,+  )+import Data.Morpheus.Types.Internal.AST+  ( Argument (..),+    ArgumentDefinition,+    Arguments,+    ArgumentsDefinition (..),+    CONST,+    DirectiveDefinition,+    DirectiveDefinition (..),+    FieldDefinition (..),+    IN,+    OUT,+    ObjectEntry (..),+    Position (..),+    RAW,+    VALID,+    Value (..),+    VariableDefinitions,+    fieldContentArgs,+    typed,+  )+import Data.Morpheus.Types.Internal.Validation+  ( FragmentValidator,+    GetWith,+    InputSource (..),+    MissingRequired,+    Scope (..),+    Validator,+    askVariables,+    asksScope,+    selectKnown,+    selectRequired,+    selectWithDefaultValue,+    startInput,+    withPosition,+  )+import Data.Morpheus.Validation.Internal.Value+  ( ValidateWithDefault,+    validateInputByTypeRef,+  )+import Data.Traversable (traverse)+import Prelude+  ( ($),+    (.),+    flip,+  )++type VariableConstraints ctx =+  ( GetWith ctx (VariableDefinitions VALID),+    MissingRequired (VariableDefinitions VALID) ctx+  )++type ArgumentsConstraints c schemaS valueS =+  ( Resolve Argument valueS c,+    ValidateWithDefault c schemaS schemaS,+    ValidateWithDefault c schemaS CONST+  )++validateArgument ::+  ( ValidateWithDefault ctx schemaS valueS,+    ValidateWithDefault ctx schemaS schemaS+  ) =>+  Arguments valueS ->+  FieldDefinition IN schemaS ->+  Validator schemaS ctx (Argument VALID)+validateArgument+  requestArgs+  argumentDef =+    selectWithDefaultValue+      (toArgument argumentDef >=> validateArgumentValue argumentDef)+      (validateArgumentValue argumentDef)+      argumentDef+      requestArgs++toArgument :: FieldDefinition IN s -> Value schemaS -> Validator schemaStage ctx (Argument schemaS)+toArgument+  FieldDefinition {fieldName}+  value = flip (Argument fieldName) value . fromMaybe (Position 0 0) <$> asksScope position++validateArgumentValue ::+  (ValidateWithDefault ctx schemaS valueS) =>+  FieldDefinition IN schemaS ->+  Argument valueS ->+  Validator schemaS ctx (Argument VALID)+validateArgumentValue+  field+  Argument {argumentValue, ..} =+    withPosition argumentPosition+      $ startInput (SourceArgument argumentName)+      $ Argument+        argumentName+        argumentPosition+        <$> validateInputByTypeRef (typed fieldType field) argumentValue++validateFieldArguments ::+  FieldDefinition OUT VALID ->+  Arguments RAW ->+  FragmentValidator s (Arguments VALID)+validateFieldArguments fieldDef@FieldDefinition {fieldContent} =+  validateArguments+    (`selectKnown` fieldDef)+    argsDef+  where+    argsDef = maybe empty fieldContentArgs fieldContent++validateDirectiveArguments ::+  ArgumentsConstraints ctx schemaStage valueStage =>+  DirectiveDefinition schemaStage ->+  Arguments valueStage ->+  Validator schemaStage ctx (Arguments VALID)+validateDirectiveArguments+  directiveDef@DirectiveDefinition+    { directiveDefinitionArgs+    } =+    validateArguments+      (`selectKnown` directiveDef)+      directiveDefinitionArgs++validateArguments ::+  ArgumentsConstraints ctx schemaStage s =>+  (Argument CONST -> Validator schemaStage ctx (ArgumentDefinition schemaStage)) ->+  ArgumentsDefinition schemaStage ->+  Arguments s ->+  Validator schemaStage ctx (Arguments VALID)+validateArguments checkUnknown argsDef rawArgs = do+  args <- ordTraverse resolve rawArgs+  ordTraverse_ checkUnknown args+    *> ordTraverse (validateArgument args) (arguments argsDef)++class Resolve f s ctx where+  resolve :: f s -> Validator schemaS ctx (f CONST)++instance VariableConstraints ctx => Resolve Argument RAW ctx 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+  resolve Null = pure Null+  resolve (Scalar x) = pure $ Scalar x+  resolve (Enum x) = pure $ Enum x+  resolve (List elems) = List <$> traverse resolve elems+  resolve (Object fields) = Object <$> traverse resolve fields+  resolve (VariableValue ref) =+    askVariables+      >>= fmap (ResolvedVariable ref)+        . selectRequired ref++instance VariableConstraints ctx => Resolve ObjectEntry RAW ctx where+  resolve (ObjectEntry name value) = ObjectEntry name <$> resolve value
src/Data/Morpheus/Validation/Internal/Directive.hs view
@@ -1,12 +1,16 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-}+{-# LANGUAGE KindSignatures #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Validation.Internal.Directive   ( shouldIncludeSelection,@@ -14,14 +18,17 @@   ) where --- MORPHEUS-import Data.Morpheus.Error (errorMessage, globalErrorMessage)+import Control.Applicative ((*>), pure)+import Control.Monad ((>>=))+import Data.Functor ((<$>))+import Data.List (elem)+import Data.Morpheus.Error.Utils+  ( validationErrorMessage,+  ) import Data.Morpheus.Internal.Utils   ( Failure (..),-    selectBy,     selectOr,   )-import Data.Morpheus.Schema.Directives (defaultDirectives) import Data.Morpheus.Types.Internal.AST   ( Argument (..),     Directive (..),@@ -29,35 +36,61 @@     DirectiveLocation (..),     Directives,     FieldName,-    RAW,+    Ref (..),     ScalarValue (..),+    Schema (..),     VALID,     Value (..),     msg,   ) import Data.Morpheus.Types.Internal.Validation-  ( SelectionValidator,+  ( Validator,+    askSchema,     selectKnown,+    selectRequired,     withDirective,   )-import Data.Morpheus.Validation.Query.Arguments-  ( validateDirectiveArguments,+import Data.Morpheus.Validation.Internal.Arguments+  ( ArgumentsConstraints,+    validateDirectiveArguments,   ) import Data.Semigroup ((<>))+import Data.Traversable (traverse)+import Prelude+  ( ($),+    (&&),+    (==),+    Bool (..),+    Maybe (..),+    otherwise,+  ) -validateDirective :: DirectiveLocation -> [DirectiveDefinition] -> Directive RAW -> SelectionValidator (Directive VALID)-validateDirective location directiveDefs directive@Directive {directiveArgs, ..} =+validateDirectives ::+  ArgumentsConstraints ctx schemaS s =>+  DirectiveLocation ->+  Directives s ->+  Validator schemaS ctx (Directives VALID)+validateDirectives location = traverse (validate location)++validate ::+  ArgumentsConstraints c schemaS s =>+  DirectiveLocation ->+  Directive s ->+  Validator schemaS c (Directive VALID)+validate location directive@Directive {..} =   withDirective directive $ do-    directiveDef <- selectKnown directive directiveDefs-    args <- validateDirectiveArguments directiveDef directiveArgs-    validateDirectiveLocation location directive directiveDef-    pure Directive {directiveArgs = args, ..}+    Schema {directiveDefinitions} <- askSchema+    directiveDef <- selectKnown directive directiveDefinitions+    Directive directiveName directivePosition+      <$> ( validateDirectiveLocation location directive directiveDef+              *> validateDirectiveArguments directiveDef directiveArgs+          )  validateDirectiveLocation ::   DirectiveLocation ->   Directive s ->-  DirectiveDefinition ->-  SelectionValidator ()+  DirectiveDefinition s' ->+  Validator schemaS ctx () validateDirectiveLocation   loc   Directive {directiveName, directivePosition}@@ -65,29 +98,40 @@     | loc `elem` directiveDefinitionLocations = pure ()     | otherwise =       failure $-        errorMessage-          directivePosition+        validationErrorMessage+          (Just directivePosition)           ("Directive " <> msg directiveName <> " may not to be used on " <> msg loc) -validateDirectives :: DirectiveLocation -> Directives RAW -> SelectionValidator (Directives VALID)-validateDirectives location = traverse (validateDirective location defaultDirectives)--directiveFulfilled :: Bool -> FieldName -> Directives s -> SelectionValidator Bool+directiveFulfilled ::+  Bool ->+  FieldName ->+  Directives s ->+  Validator schemaS ctx Bool directiveFulfilled target = selectOr (pure True) (argumentIf target) -shouldIncludeSelection :: Directives VALID -> SelectionValidator Bool+shouldIncludeSelection ::+  Directives VALID ->+  Validator schemaS ctx Bool shouldIncludeSelection directives = do   dontSkip <- directiveFulfilled False "skip" directives   include <- directiveFulfilled True "include" directives   pure (dontSkip && include) -argumentIf :: Bool -> Directive s -> SelectionValidator Bool-argumentIf target Directive {directiveName, directiveArgs} =-  selectBy err "if" directiveArgs+argumentIf ::+  Bool ->+  Directive s ->+  Validator schemaS ctx Bool+argumentIf target Directive {directiveArgs, directivePosition} =+  selectRequired (Ref "if" directivePosition) directiveArgs     >>= assertArgument target-  where-    err = globalErrorMessage $ "Directive " <> msg ("@" <> directiveName) <> " argument \"if\" of type \"Boolean!\" is required but not provided." -assertArgument :: Bool -> Argument s -> SelectionValidator Bool+assertArgument ::+  Bool ->+  Argument s ->+  Validator schemaS ctx Bool assertArgument asserted Argument {argumentValue = Scalar (Boolean actual)} = pure (asserted == actual)-assertArgument _ Argument {argumentValue} = failure $ "Expected type Boolean!, found " <> msg argumentValue <> "."+assertArgument _ Argument {argumentValue, argumentPosition} =+  failure+    $ validationErrorMessage+      (Just argumentPosition)+    $ "Expected type Boolean!, found " <> msg argumentValue <> "."
src/Data/Morpheus/Validation/Internal/Value.hs view
@@ -1,29 +1,34 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE NoImplicitPrelude #-} -module Data.Morpheus.Validation.Internal.Value (validateInput) where+module Data.Morpheus.Validation.Internal.Value+  ( validateInputByTypeRef,+    validateInputByType,+    ValidateWithDefault,+  )+where -import Data.Foldable (traverse_)+import Control.Applicative ((*>), pure)+import Data.Either (Either (..)) import Data.Function ((&))-import Data.List (elem)-import Data.Maybe (maybe)--- MORPHEUS-+import Data.Functor ((<$>), fmap)+import Data.List (any, elem)+import Data.Maybe (Maybe (..), maybe) import Data.Morpheus.Error.Input (typeViolation)-import Data.Morpheus.Error.Utils (errorMessage) import Data.Morpheus.Error.Variable (incompatibleVariableType) import Data.Morpheus.Internal.Utils   ( Failure (..),-    elems,-    fromElems,+    ordTraverse_,+    traverseCollection,   ) import Data.Morpheus.Types.Internal.AST-  ( DataEnumValue (..),+  ( CONST,+    DataEnumValue (..),     DataInputUnion,     FieldDefinition (..),     FieldsDefinition,@@ -31,79 +36,92 @@     Message,     Object,     ObjectEntry (..),-    RESOLVED,     Ref (..),-    ResolvedValue,     ScalarDefinition (..),     ScalarValue (..),-    Schema,     TRUE,     TypeContent (..),     TypeDefinition (..),     TypeName (..),     TypeRef (..),-    TypeRef (..),     TypeWrapper (..),+    Typed (..),+    UnionMember (..),     VALID,     ValidValue,     Value (..),     Variable (..),     Variable (..),     VariableContent (..),-    isNullableWrapper,+    isNullable,     isWeaker,     msg,+    msgValidation,     toFieldName,+    typed,+    untyped,+    withPosition,   )-import Data.Morpheus.Types.Internal.AST.OrderedMap+import Data.Morpheus.Types.Internal.AST.OrdMap   ( unsafeFromValues,   ) import Data.Morpheus.Types.Internal.Validation-  ( GetWith,-    InputContext,+  ( InputContext,     InputSource (..),     InputValidator,-    MissingRequired,-    MonadContext,-    Prop (..),     Scope (..),-    ScopeKind (..),-    SetWith,-    Unknown,     Validator,-    askInputFieldType,-    askInputMember,-    asks,+    askType,+    askTypeMember,+    asksScope,     constraintInputUnion,+    inField,     inputMessagePrefix,     inputValueSource,     selectKnown,     selectWithDefaultValue,-    withInputScope,     withScopeType,   ) import Data.Semigroup ((<>))+import Data.Traversable (traverse)+import Prelude+  ( ($),+    (&&),+    (.),+    Bool (..),+    Eq (..),+    const,+    fst,+    id,+    not,+    otherwise,+  ) -castFailure ::-  ( GetWith ctx Schema,-    GetWith ctx Scope-  ) =>-  TypeRef ->+violation ::   Maybe Message ->-  ResolvedValue ->-  InputValidator ctx a-castFailure expected message value = do-  pos <- asks position+  Value s ->+  InputValidator schemaS ctx a+violation message value = do+  Scope+    { position,+      currentTypeName,+      currentTypeWrappers+    } <-+    asksScope id   prefix <- inputMessagePrefix   failure-    $ errorMessage pos-    $ prefix <> typeViolation expected value <> maybe "" (" " <>) message+    $ withPosition position+    $ prefix+      <> typeViolation+        (TypeRef currentTypeName Nothing currentTypeWrappers)+        value+      <> maybe "" ((" " <>) . msgValidation) message  checkTypeEquality ::   (TypeName, [TypeWrapper]) ->   Ref ->   Variable VALID ->-  InputValidator ctx ValidValue+  InputValidator schemaS ctx ValidValue checkTypeEquality (tyConName, tyWrappers) ref var@Variable {variableValue = ValidVariableValue value, variableType}   | typeConName variableType == tyConName       && not@@ -120,202 +138,167 @@             typeArgs = Nothing           } -type InputConstraints ctx =-  ( GetWith ctx Schema,-    GetWith ctx Scope,-    GetWith (InputContext ctx) InputSource,-    SetWith ctx Scope,-    MissingRequired (Object RESOLVED) (InputContext ctx),-    Unknown (FieldsDefinition IN) (InputContext ctx)-  )+validateInputByTypeRef ::+  ValidateWithDefault c schemaS s =>+  Typed IN schemaS TypeRef ->+  Value s ->+  Validator schemaS (InputContext c) (Value VALID)+validateInputByTypeRef+  ref+  value = do+    inputTypeDef <- askType ref+    validateInputByType+      (untyped typeWrappers ref)+      inputTypeDef+      value +validateValueByField ::+  ValidateWithDefault c schemaS s =>+  FieldDefinition IN schemaS ->+  Value s ->+  Validator schemaS (InputContext c) (Value VALID)+validateValueByField field =+  inField field+    . validateInputByTypeRef+      (typed fieldType field)+ -- Validate input Values-validateInput ::-  forall ctx.-  ( InputConstraints ctx-  ) =>+validateInputByType ::+  ValidateWithDefault ctx schemaS valueS =>   [TypeWrapper] ->-  TypeDefinition IN ->-  ObjectEntry RESOLVED ->-  InputValidator ctx ValidValue-validateInput tyWrappers TypeDefinition {typeContent = tyCont, typeName} =-  withScopeType typeName-    . validateWrapped tyWrappers tyCont-  where-    mismatchError :: [TypeWrapper] -> Maybe Message -> ResolvedValue -> InputValidator ctx ValidValue-    mismatchError wrappers = castFailure (TypeRef typeName Nothing wrappers)-    -- VALIDATION-    validateWrapped ::-      [TypeWrapper] ->-      TypeContent TRUE IN ->-      ObjectEntry RESOLVED ->-      InputValidator ctx ValidValue-    -- Validate Null. value = null ?-    validateWrapped wrappers _ ObjectEntry {entryValue = ResolvedVariable ref variable} =-      checkTypeEquality (typeName, wrappers) ref variable-    validateWrapped wrappers _ ObjectEntry {entryValue = Null}-      | isNullableWrapper wrappers = pure Null-      | otherwise = mismatchError wrappers Nothing Null-    -- Validate LIST-    validateWrapped [TypeMaybe] dt ObjectEntry {entryValue} =-      validateUnwrapped (mismatchError [TypeMaybe]) dt entryValue-    validateWrapped (TypeMaybe : wrappers) _ value =-      validateWrapped wrappers tyCont value-    validateWrapped (TypeList : wrappers) _ (ObjectEntry key (List list)) =-      List <$> traverse validateElement list-      where-        validateElement = validateWrapped wrappers tyCont . ObjectEntry key-    {-- 2. VALIDATE TYPES, all wrappers are already Processed --}-    {-- VALIDATE OBJECT--}-    validateWrapped [] dt ObjectEntry {entryValue} =-      validateUnwrapped (mismatchError []) dt entryValue-    {-- 3. THROW ERROR: on invalid values --}-    validateWrapped wrappers _ ObjectEntry {entryValue} = mismatchError wrappers Nothing entryValue-    validateUnwrapped ::-      -- error-      (Maybe Message -> ResolvedValue -> InputValidator ctx ValidValue) ->-      TypeContent TRUE IN ->-      Value RESOLVED ->-      InputValidator ctx ValidValue-    validateUnwrapped _ (DataInputObject parentFields) (Object fields) =-      Object <$> validateInputObject parentFields fields-    validateUnwrapped _ (DataInputUnion inputUnion) (Object rawFields) =-      validatInputUnion typeName inputUnion rawFields-    validateUnwrapped err (DataEnum tags) value =-      validateEnum (err Nothing) tags value-    validateUnwrapped err (DataScalar dataScalar) value =-      validateScalar typeName dataScalar value err-    validateUnwrapped err _ value = err Nothing value+  TypeDefinition IN schemaS ->+  Value valueS ->+  InputValidator schemaS ctx ValidValue+validateInputByType tyWrappers typeDef =+  withScopeType (typeDef, tyWrappers) . validateWrapped tyWrappers typeDef +-- VALIDATION+validateWrapped ::+  ValidateWithDefault ctx schemaS valueS =>+  [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+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) =+  List <$> traverse (validateInputByType wrappers tyCont) list+{-- 2. VALIDATE TYPES, all wrappers are already Processed --}+{-- VALIDATE OBJECT--}+validateWrapped [] TypeDefinition {typeContent} entryValue =+  validateUnwrapped typeContent entryValue+{-- 3. THROW ERROR: on invalid values --}+validateWrapped _ _ entryValue = violation Nothing entryValue++validateUnwrapped ::+  ValidateWithDefault ctx schemaS valueS =>+  TypeContent TRUE IN schemaS ->+  Value valueS ->+  InputValidator schemaS ctx ValidValue+validateUnwrapped (DataInputObject parentFields) (Object fields) =+  Object <$> validateInputObject parentFields fields+validateUnwrapped (DataInputUnion inputUnion) (Object rawFields) =+  validatInputUnion inputUnion rawFields+validateUnwrapped (DataEnum tags) value =+  validateEnum tags value+validateUnwrapped (DataScalar dataScalar) value =+  validateScalar dataScalar value+validateUnwrapped _ value = violation Nothing value+ -- INPUT UNION validatInputUnion ::-  ( InputConstraints ctx-  ) =>-  TypeName ->-  DataInputUnion ->-  Object RESOLVED ->-  InputValidator ctx (Value VALID)-validatInputUnion typeName inputUnion rawFields =+  ValidateWithDefault ctx schemaS s =>+  DataInputUnion schemaS ->+  Object s ->+  InputValidator schemaS ctx (Value VALID)+validatInputUnion inputUnion rawFields =   case constraintInputUnion inputUnion rawFields of-    Left message -> castFailure (TypeRef typeName Nothing []) (Just message) (Object rawFields)-    Right (name, Nothing) -> pure (mkInputObject name [])+    Left message -> violation (Just message) (Object rawFields)+    Right (UnionMember {memberName}, Nothing) -> pure (mkInputObject memberName [])     Right (name, Just value) -> validatInputUnionMember name value  validatInputUnionMember ::-  ( InputConstraints ctx-  ) =>-  TypeName ->-  Value RESOLVED ->-  InputValidator ctx (Value VALID)-validatInputUnionMember name value = do-  inputDef <- askInputMember name-  validValue <--    validateInput-      [TypeMaybe]-      inputDef-      (ObjectEntry (toFieldName name) value)-  pure $ mkInputObject name [ObjectEntry (toFieldName name) validValue]+  ValidateWithDefault ctx schemaS valueS =>+  UnionMember IN schemaS ->+  Value valueS ->+  InputValidator schemaS ctx (Value VALID)+validatInputUnionMember member@UnionMember {memberName} value = do+  inputDef <- fst <$> askTypeMember member+  validValue <- validateInputByType [TypeMaybe] inputDef value+  pure $ mkInputObject memberName [ObjectEntry (toFieldName memberName) validValue]  mkInputObject :: TypeName -> [ObjectEntry s] -> Value s mkInputObject name xs = Object $ unsafeFromValues $ ObjectEntry "__typename" (Enum name) : xs  -- INUT Object validateInputObject ::-  ( InputConstraints ctx-  ) =>-  FieldsDefinition IN ->-  Object RESOLVED ->-  InputValidator ctx (Object VALID)+  ValidateWithDefault ctx schemaS valueS =>+  FieldsDefinition IN schemaS ->+  Object valueS ->+  InputValidator schemaS ctx (Object VALID) validateInputObject fieldsDef object =-  do-    kind <- asks kind-    case kind of-      TYPE ->-        traverse_ (`requiredFieldIsDefined` object) fieldsDef-          *> traverse (`validateField` fieldsDef) object-      _ ->-        traverse_ (`selectKnown` fieldsDef) object-          *> validateObjectWithDefaultValue object fieldsDef--validateField ::-  ( InputConstraints ctx-  ) =>-  ObjectEntry RESOLVED ->-  FieldsDefinition IN ->-  InputValidator ctx (ObjectEntry VALID)-validateField entry parentFields = do-  field <- selectKnown entry parentFields-  validateInputField field entry--validateObjectWithDefaultValue ::-  (InputConstraints c) =>-  Object RESOLVED ->-  FieldsDefinition IN ->-  Validator (InputContext c) (Object VALID)-validateObjectWithDefaultValue object fieldsDef =-  traverse (validateFieldWithDefaultValue object) (elems fieldsDef)-    >>= fromElems+  ordTraverse_ (`selectKnown` fieldsDef) object+    *> traverseCollection (validateWithDefault object) fieldsDef -validateFieldWithDefaultValue ::-  (InputConstraints c) =>-  Object RESOLVED ->-  FieldDefinition IN ->-  Validator (InputContext c) (ObjectEntry VALID)-validateFieldWithDefaultValue object fieldDef@FieldDefinition {fieldName} = do-  entry <- selectWithDefaultValue (ObjectEntry fieldName) fieldDef object-  validateInputField fieldDef entry+class ValidateWithDefault c schemaS s where+  validateWithDefault ::+    Object s ->+    FieldDefinition IN schemaS ->+    Validator schemaS (InputContext c) (ObjectEntry VALID) -validateInputField ::-  (InputConstraints c) =>-  FieldDefinition IN ->-  ObjectEntry RESOLVED ->-  Validator (InputContext c) (ObjectEntry VALID)-validateInputField fieldDef@FieldDefinition {fieldName, fieldType = TypeRef {typeConName, typeWrappers}} entry = do-  inputTypeDef <- askInputFieldType fieldDef-  withInputScope (Prop fieldName typeConName) $+instance ValidateWithDefault c VALID s where+  validateWithDefault object fieldDef@FieldDefinition {fieldName} =     ObjectEntry fieldName-      <$> validateInput-        typeWrappers-        inputTypeDef-        entry+      <$> selectWithDefaultValue+        pure+        (validateValueByField fieldDef . entryValue)+        fieldDef+        object -requiredFieldIsDefined ::-  ( MissingRequired (Object RESOLVED) (InputContext ctx),-    GetWith ctx Scope-  ) =>-  FieldDefinition IN ->-  Object RESOLVED ->-  InputValidator ctx (ObjectEntry RESOLVED)-requiredFieldIsDefined fieldDef@FieldDefinition {fieldName} =-  selectWithDefaultValue (ObjectEntry fieldName) fieldDef+instance ValidateWithDefault c CONST s where+  validateWithDefault object fieldDef@FieldDefinition {fieldName} =+    ObjectEntry fieldName+      <$> selectWithDefaultValue+        (validateValueByField fieldDef)+        (validateValueByField fieldDef . entryValue)+        fieldDef+        object  -- Leaf Validations validateScalar ::-  forall m.-  (Monad m) =>-  TypeName ->   ScalarDefinition ->-  ResolvedValue ->-  (Maybe Message -> ResolvedValue -> m ValidValue) ->-  m ValidValue-validateScalar typeName ScalarDefinition {validateValue} value err = do-  scalarValue <- toScalar value+  Value s ->+  InputValidator schemaS ctx ValidValue+validateScalar ScalarDefinition {validateValue} value = do+  typeName <- asksScope currentTypeName+  scalarValue <- toScalar typeName value   case validateValue scalarValue of     Right _ -> pure scalarValue-    Left "" -> err Nothing value-    Left message -> err (Just $ msg message) value+    Left "" -> violation Nothing value+    Left message -> violation (Just $ msg message) value   where-    toScalar :: ResolvedValue -> m ValidValue-    toScalar (Scalar x) | isValidDefault typeName x = pure (Scalar x)-    toScalar _ = err Nothing value-    isValidDefault :: TypeName -> ScalarValue -> Bool-    isValidDefault "Boolean" = isBoolean-    isValidDefault "String" = isString-    isValidDefault "Float" = oneOf [isFloat, isInt]-    isValidDefault "Int" = isInt-    isValidDefault "ID" = oneOf [isInt, isFloat, isString]-    isValidDefault _ = const True+    toScalar :: TypeName -> Value s -> InputValidator schemaS ctx ValidValue+    toScalar typeName (Scalar x) | isValidDefault typeName x = pure (Scalar x)+    toScalar _ _ = violation Nothing value +isValidDefault :: TypeName -> ScalarValue -> Bool+isValidDefault "Boolean" = isBoolean+isValidDefault "String" = isString+isValidDefault "Float" = oneOf [isFloat, isInt]+isValidDefault "Int" = isInt+isValidDefault "ID" = oneOf [isInt, isFloat, isString]+isValidDefault _ = const True+ oneOf :: [a -> Bool] -> a -> Bool oneOf ls v = any (v &) ls @@ -335,7 +318,7 @@ isInt Int {} = True isInt _ = False -isVariableValue :: (MonadContext m c, GetWith c InputSource) => m c Bool+isVariableValue :: InputValidator schemaS c Bool isVariableValue =   \case     SourceVariable {isDefaultValue} -> not isDefaultValue@@ -343,22 +326,20 @@     <$> inputValueSource  validateEnum ::-  (MonadContext m c, GetWith c InputSource) =>-  (ResolvedValue -> m c ValidValue) ->-  [DataEnumValue] ->-  ResolvedValue ->-  m c ValidValue-validateEnum err enumValues value@(Scalar (String enumValue))+  [DataEnumValue s] ->+  Value valueS ->+  InputValidator schemaS c ValidValue+validateEnum enumValues value@(Scalar (String enumValue))   | TypeName enumValue `elem` tags = do     isFromVariable <- isVariableValue     if isFromVariable       then pure (Enum (TypeName enumValue))-      else err value+      else violation Nothing value   where-    tags = map enumName enumValues-validateEnum err enumValues value@(Enum enumValue)+    tags = fmap enumName enumValues+validateEnum enumValues value@(Enum enumValue)   | enumValue `elem` tags = pure (Enum enumValue)-  | otherwise = err value+  | otherwise = violation Nothing value   where-    tags = map enumName enumValues-validateEnum err _ value = err value+    tags = fmap enumName enumValues+validateEnum _ value = violation Nothing value
− src/Data/Morpheus/Validation/Query/Arguments.hs
@@ -1,147 +0,0 @@-{-# LANGUAGE GADTs #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE RecordWildCards #-}--module Data.Morpheus.Validation.Query.Arguments-  ( validateDirectiveArguments,-    validateFieldArguments,-  )-where--import Data.Foldable (traverse_)-import Data.Morpheus.Internal.Utils-  ( elems,-    empty,-  )-import Data.Morpheus.Types.Internal.AST-  ( Argument (..),-    ArgumentDefinition,-    Arguments,-    ArgumentsDefinition (..),-    DirectiveDefinition,-    DirectiveDefinition (..),-    FieldDefinition (..),-    OUT,-    ObjectEntry (..),-    RAW,-    RESOLVED,-    RawValue,-    ResolvedValue,-    TypeRef (..),-    VALID,-    Value (..),-    fieldContentArgs,-  )-import Data.Morpheus.Types.Internal.Validation-  ( InputSource (..),-    Scope (..),-    SelectionValidator,-    askInputFieldType,-    askVariables,-    asks,-    selectKnown,-    selectRequired,-    selectWithDefaultValue,-    startInput,-    withPosition,-  )-import Data.Morpheus.Validation.Internal.Value-  ( validateInput,-  )---- only Resolves , doesnot checks the types-resolveObject :: RawValue -> SelectionValidator ResolvedValue-resolveObject = resolve-  where-    resolveEntry :: ObjectEntry RAW -> SelectionValidator (ObjectEntry RESOLVED)-    resolveEntry (ObjectEntry name v) = ObjectEntry name <$> resolve v-    -------------------------------------------------    resolve :: RawValue -> SelectionValidator ResolvedValue-    resolve Null = pure Null-    resolve (Scalar x) = pure $ Scalar x-    resolve (Enum x) = pure $ Enum x-    resolve (List x) = List <$> traverse resolve x-    resolve (Object obj) = Object <$> traverse resolveEntry obj-    resolve (VariableValue ref) =-      askVariables-        >>= fmap (ResolvedVariable ref)-          . selectRequired ref--resolveArgumentVariables ::-  Arguments RAW ->-  SelectionValidator (Arguments RESOLVED)-resolveArgumentVariables =-  traverse resolveVariable-  where-    resolveVariable :: Argument RAW -> SelectionValidator (Argument RESOLVED)-    resolveVariable (Argument key val position) = do-      constValue <- resolveObject val-      pure $ Argument key constValue position--validateArgument ::-  Arguments RESOLVED ->-  ArgumentDefinition ->-  SelectionValidator (Argument VALID)-validateArgument-  requestArgs-  argumentDef@FieldDefinition-    { fieldName,-      fieldType = TypeRef {typeWrappers}-    } =-    do-      argumentPosition <- asks position-      argument <--        selectWithDefaultValue-          (\argumentValue -> Argument {argumentName = fieldName, argumentValue, argumentPosition})-          argumentDef-          requestArgs-      validateArgumentValue argument-    where-      --------------------------------------------------------------------------      validateArgumentValue :: Argument RESOLVED -> SelectionValidator (Argument VALID)-      validateArgumentValue arg@Argument {argumentValue = value, ..} =-        withPosition argumentPosition-          $ startInput (SourceArgument arg)-          $ do-            datatype <- askInputFieldType argumentDef-            argumentValue <--              validateInput-                typeWrappers-                datatype-                (ObjectEntry fieldName value)-            pure Argument {argumentValue, ..}--validateFieldArguments ::-  FieldDefinition OUT ->-  Arguments RAW ->-  SelectionValidator (Arguments VALID)-validateFieldArguments-  fieldDef@FieldDefinition {fieldContent}-  rawArgs =-    do-      args <- resolveArgumentVariables rawArgs-      traverse_ checkUnknown (elems args)-      traverse (validateArgument args) argsDef-    where-      argsDef = maybe empty fieldContentArgs fieldContent-      --------------------------------------------------      checkUnknown :: Argument RESOLVED -> SelectionValidator ArgumentDefinition-      checkUnknown = (`selectKnown` fieldDef)--validateDirectiveArguments ::-  DirectiveDefinition ->-  Arguments RAW ->-  SelectionValidator (Arguments VALID)-validateDirectiveArguments-  directiveDef@DirectiveDefinition-    { directiveDefinitionArgs = ArgumentsDefinition _ argsDef-    }-  rawArgs =-    do-      args <- resolveArgumentVariables rawArgs-      traverse_ checkUnknown (elems args)-      traverse (validateArgument args) argsDef-    where-      --------------------------------------------------      checkUnknown :: Argument RESOLVED -> SelectionValidator ArgumentDefinition-      checkUnknown = (`selectKnown` directiveDef)
src/Data/Morpheus/Validation/Query/Fragment.hs view
@@ -1,150 +1,131 @@+{-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-}+{-# LANGUAGE KindSignatures #-} {-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Validation.Query.Fragment   ( validateFragments,     castFragmentType,     resolveSpread,+    validateFragment,+    selectFragmentType,+    ResolveFragment (..),   ) where -import Data.Foldable (traverse_)+import Control.Applicative ((<*>), pure)+import Control.Monad ((>>=))+import Data.Functor ((<$>))+import Data.List (elem)+import Data.Maybe (Maybe (..)) -- MORPHEUS import Data.Morpheus.Error.Fragment   ( cannotBeSpreadOnType,-    cannotSpreadWithinItself,   ) import Data.Morpheus.Internal.Utils   ( Failure (..),-    elems,-    selectOr,   ) import Data.Morpheus.Types.Internal.AST-  ( FieldName,+  ( Directives,+    FieldName,     Fragment (..),     Fragments,+    IMPLEMENTABLE,     Position,     RAW,     Ref (..),-    Selection (..),-    SelectionContent (..),+    Schema,     SelectionSet,+    Stage,+    Stage,+    TypeDefinition,     TypeName,     TypeNameRef (..),+    UnionTag (..),+    VALID,   ) import Data.Morpheus.Types.Internal.Validation-  ( BaseValidator,-    Constraint (..),-    OperationContext,-    Validator,+  ( Constraint (..),+    FragmentValidator,     askFragments,     askSchema,-    checkUnused,     constraint,     selectKnown,   )-import Data.Semigroup ((<>))+import Data.Traversable (traverse)+import Prelude+  ( ($),+    otherwise,+  ) -validateFragments :: SelectionSet RAW -> BaseValidator ()-validateFragments selectionSet =-  fragmentsCycleChecking-    *> checkUnusedFragments selectionSet-    *> fragmentsConditionTypeChecking+class ResolveFragment (s :: Stage) where+  resolveValidFragment ::+    (Fragment RAW -> FragmentValidator s (SelectionSet VALID)) ->+    [TypeName] ->+    Ref ->+    FragmentValidator s UnionTag -checkUnusedFragments :: SelectionSet RAW -> BaseValidator ()-checkUnusedFragments selectionSet = do-  fragments <- askFragments-  checkUnused-    (usedFragments fragments (elems selectionSet))-    (elems fragments)+instance ResolveFragment VALID where+  resolveValidFragment _ allowedTargets ref = do+    Fragment {fragmentType, fragmentSelection} <- resolveSpread allowedTargets ref+    pure $ UnionTag fragmentType fragmentSelection +instance ResolveFragment RAW where+  resolveValidFragment f allowedTargets ref = do+    fragment@Fragment {fragmentType} <- resolveSpread allowedTargets ref+    UnionTag fragmentType <$> f fragment++validateFragment ::+  (Fragment RAW -> FragmentValidator s (SelectionSet VALID)) ->+  [TypeName] ->+  Fragment RAW ->+  FragmentValidator s (Fragment VALID)+validateFragment validate allowedTypes fragment@Fragment {fragmentPosition} =+  castFragmentType Nothing fragmentPosition allowedTypes fragment+    >>= onlyValidateFrag validate++validateFragments ::+  (Fragment RAW -> FragmentValidator RAW (SelectionSet VALID)) ->+  FragmentValidator RAW (Fragments VALID)+validateFragments f = askFragments >>= traverse (onlyValidateFrag f)++onlyValidateFrag ::+  (Fragment RAW -> FragmentValidator s (SelectionSet VALID)) ->+  Fragment RAW ->+  FragmentValidator s (Fragment VALID)+onlyValidateFrag validate f@Fragment {..} =+  Fragment+    fragmentName+    fragmentType+    fragmentPosition+    <$> validate f <*> validateFragmentDirectives fragmentDirectives++validateFragmentDirectives :: Directives RAW -> FragmentValidator s (Directives VALID)+validateFragmentDirectives _ = pure [] --TODO: validate fragment directives+ castFragmentType ::-  Maybe FieldName -> Position -> [TypeName] -> Fragment -> Validator ctx Fragment+  Maybe FieldName ->+  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 -resolveSpread :: [TypeName] -> Ref -> Validator (OperationContext v) Fragment+resolveSpread :: [TypeName] -> Ref -> FragmentValidator s (Fragment s) resolveSpread allowedTargets ref@Ref {refName, refPosition} =   askFragments     >>= selectKnown ref     >>= castFragmentType (Just refName) refPosition allowedTargets -usedFragments :: Fragments -> [Selection RAW] -> [Node]-usedFragments fragments = concatMap findAllUses-  where-    findUsesSelectionContent :: SelectionContent RAW -> [Node]-    findUsesSelectionContent (SelectionSet selectionSet) =-      concatMap findAllUses selectionSet-    findUsesSelectionContent SelectionField = []-    findAllUses :: Selection RAW -> [Node]-    findAllUses Selection {selectionContent} =-      findUsesSelectionContent selectionContent-    findAllUses (InlineFragment Fragment {fragmentSelection}) =-      concatMap findAllUses fragmentSelection-    findAllUses (Spread _ Ref {refName, refPosition}) =-      [Ref refName refPosition] <> searchInFragment-      where-        searchInFragment =-          selectOr-            []-            (concatMap findAllUses . fragmentSelection)-            refName-            fragments--fragmentsConditionTypeChecking :: BaseValidator ()-fragmentsConditionTypeChecking =-  elems <$> askFragments-    >>= traverse_ checkTypeExistence--checkTypeExistence :: Fragment -> BaseValidator ()-checkTypeExistence fr@Fragment {fragmentType, fragmentPosition} =-  askSchema-    >>= selectKnown (TypeNameRef fragmentType fragmentPosition)-    >>= constraint OBJECT fr-    >> pure ()--fragmentsCycleChecking :: BaseValidator ()-fragmentsCycleChecking = exploreSpreads >>= fragmentCycleChecking--exploreSpreads :: BaseValidator Graph-exploreSpreads = map exploreFragmentSpreads . elems <$> askFragments--exploreFragmentSpreads :: Fragment -> NodeEdges-exploreFragmentSpreads Fragment {fragmentName, fragmentSelection, fragmentPosition} =-  (Ref fragmentName fragmentPosition, concatMap scanForSpread fragmentSelection)--scanForSpreadContent :: SelectionContent RAW -> [Node]-scanForSpreadContent SelectionField = []-scanForSpreadContent (SelectionSet selectionSet) =-  concatMap scanForSpread selectionSet--scanForSpread :: Selection RAW -> [Node]-scanForSpread Selection {selectionContent} =-  scanForSpreadContent selectionContent-scanForSpread (InlineFragment Fragment {fragmentSelection}) =-  concatMap scanForSpread fragmentSelection-scanForSpread (Spread _ Ref {refName, refPosition}) =-  [Ref refName refPosition]--type Node = Ref--type NodeEdges = (Node, [Node])--type Graph = [NodeEdges]--fragmentCycleChecking :: Graph -> BaseValidator ()-fragmentCycleChecking lib = traverse_ checkFragment lib-  where-    checkFragment (fragmentID, _) = checkForCycle lib fragmentID [fragmentID]--checkForCycle :: Graph -> Node -> [Node] -> BaseValidator Graph-checkForCycle lib parentNode history = case lookup parentNode lib of-  Just node -> concat <$> traverse checkNode node-  Nothing -> pure []-  where-    checkNode x = if x `elem` history then cycleError x else recurse x-    recurse node = checkForCycle lib node $ history ++ [node]-    cycleError n = failure $ cannotSpreadWithinItself (n : history)+selectFragmentType :: Fragment RAW -> FragmentValidator s (TypeDefinition IMPLEMENTABLE VALID)+selectFragmentType fr@Fragment {fragmentType, fragmentPosition} = do+  (schema :: Schema VALID) <- askSchema+  typeDef <- selectKnown (TypeNameRef fragmentType fragmentPosition) schema+  constraint IMPLEMENTABLE fr typeDef
+ src/Data/Morpheus/Validation/Query/FragmentPreconditions.hs view
@@ -0,0 +1,108 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE NoImplicitPrelude #-}++module Data.Morpheus.Validation.Query.FragmentPreconditions+  ( checkFragmentPreconditions,+  )+where++import Control.Applicative ((*>))+import Control.Monad ((>>=))+import Data.Foldable (concatMap)+import Data.Functor ((<$>), fmap)+-- MORPHEUS+import Data.Morpheus.Error.Fragment+  ( cannotSpreadWithinItself,+  )+import Data.Morpheus.Internal.Graph+  ( Edges,+    Graph,+    Node,+    cycleChecking,+  )+import Data.Morpheus.Internal.Utils+  ( Failure (..),+    elems,+    selectOr,+  )+import Data.Morpheus.Types.Internal.AST+  ( Fragment (..),+    Fragments,+    RAW,+    Ref (..),+    Selection (..),+    SelectionContent (..),+    SelectionSet,+  )+import Data.Morpheus.Types.Internal.Validation+  ( BaseValidator,+    askFragments,+    checkUnused,+  )+import Data.Semigroup ((<>))+import Prelude+  ( (.),+  )++checkUnusedFragments :: SelectionSet RAW -> BaseValidator ()+checkUnusedFragments selectionSet = do+  fragments <- askFragments+  checkUnused+    (usedFragments fragments (elems selectionSet))+    (elems fragments)++usedFragments :: Fragments RAW -> [Selection RAW] -> [Node]+usedFragments fragments = concatMap findAllUses+  where+    findUsesSelectionContent :: SelectionContent RAW -> [Node]+    findUsesSelectionContent (SelectionSet selectionSet) =+      concatMap findAllUses selectionSet+    findUsesSelectionContent SelectionField = []+    findAllUses :: Selection RAW -> [Node]+    findAllUses Selection {selectionContent} =+      findUsesSelectionContent selectionContent+    findAllUses (InlineFragment Fragment {fragmentSelection}) =+      concatMap findAllUses fragmentSelection+    findAllUses (Spread _ Ref {refName, refPosition}) =+      [Ref refName refPosition] <> searchInFragment+      where+        searchInFragment =+          selectOr+            []+            (concatMap findAllUses . fragmentSelection)+            refName+            fragments++checkFragmentPreconditions :: SelectionSet RAW -> BaseValidator ()+checkFragmentPreconditions selection =+  (exploreSpreads >>= cycleChecking (failure . cannotSpreadWithinItself))+    *> checkUnusedFragments selection++exploreSpreads :: BaseValidator Graph+exploreSpreads = fmap exploreFragmentSpreads . elems <$> askFragments++exploreFragmentSpreads :: Fragment RAW -> Edges+exploreFragmentSpreads Fragment {fragmentName, fragmentSelection, fragmentPosition} =+  (Ref fragmentName fragmentPosition, concatMap scanSpread fragmentSelection)++class ScanSpread a where+  scanSpread :: a -> [Node]++instance ScanSpread (Selection RAW) where+  scanSpread Selection {selectionContent} =+    scanSpread selectionContent+  scanSpread (InlineFragment Fragment {fragmentSelection}) =+    concatMap scanSpread fragmentSelection+  scanSpread (Spread _ Ref {refName, refPosition}) =+    [Ref refName refPosition]++instance ScanSpread (SelectionContent RAW) where+  scanSpread SelectionField = []+  scanSpread (SelectionSet selectionSet) =+    concatMap scanSpread selectionSet
src/Data/Morpheus/Validation/Query/Selection.hs view
@@ -6,14 +6,19 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Validation.Query.Selection   ( validateOperation,+    vaidateFragmentSelection,   ) where --- MORPHEUS+import Control.Applicative ((<*>), pure)+import Data.Foldable (null)+import Data.Functor ((<$>), fmap)+import Data.List (filter)+import Data.Maybe (Maybe (..), maybe) import Data.Morpheus.Error.Selection   ( hasNoSubfields,     subfieldsNotSelected,@@ -29,11 +34,11 @@   ( Arguments,     DirectiveLocation (FIELD, FRAGMENT_SPREAD, INLINE_FRAGMENT, MUTATION, QUERY, SUBSCRIPTION),     Directives,-    FieldDefinition,+    FieldDefinition (fieldType),     FieldName,     FieldsDefinition,     Fragment (..),-    GQLError (..),+    IMPLEMENTABLE,     OUT,     Operation (..),     OperationType (..),@@ -45,51 +50,55 @@     TRUE,     TypeContent (..),     TypeDefinition (..),-    TypeName,+    UnionTag (..),     VALID,-    getOperationDataType,+    ValidationError (..),     isEntNode,-    msg,+    msgValidation,+    possibleTypes,+    toCategory,+    typed,+    withPosition,   ) import Data.Morpheus.Types.Internal.AST.MergeSet   ( concatTraverse,   ) import Data.Morpheus.Types.Internal.Validation-  ( SelectionValidator,-    askFieldType,+  ( FragmentValidator,+    SelectionValidator,     askSchema,+    askType,+    getOperationType,     selectKnown,     withScope,   )+import Data.Morpheus.Validation.Internal.Arguments+  ( validateFieldArguments,+  ) import Data.Morpheus.Validation.Internal.Directive   ( shouldIncludeSelection,     validateDirectives,   )-import Data.Morpheus.Validation.Query.Arguments-  ( validateFieldArguments,-  ) import Data.Morpheus.Validation.Query.Fragment-  ( castFragmentType,-    resolveSpread,+  ( ResolveFragment (..),+    resolveValidFragment,+    selectFragmentType,+    validateFragment,   ) import Data.Morpheus.Validation.Query.UnionSelection-  ( validateUnionSelection,+  ( validateInterfaceSelection,+    validateUnionSelection,   ) import Data.Semigroup ((<>))--type TypeDef = (TypeName, FieldsDefinition OUT)--getOperationObject ::-  Operation a -> SelectionValidator (TypeName, FieldsDefinition OUT)-getOperationObject operation = do-  dt <- askSchema >>= getOperationDataType operation-  case dt of-    TypeDefinition {typeContent = DataObject {objectFields}, typeName} -> pure (typeName, objectFields)-    TypeDefinition {typeName} ->-      failure $-        "Type Mismatch: operation \""-          <> msg typeName-          <> "\" must be an Object"+import Prelude+  ( ($),+    (&&),+    (.),+    Eq (..),+    const,+    not,+    otherwise,+  )  selectionsWitoutTypename :: SelectionSet VALID -> [Selection VALID] selectionsWitoutTypename = filter (("__typename" /=) . keyOf) . elems@@ -97,21 +106,18 @@ singleTopLevelSelection :: Operation RAW -> SelectionSet VALID -> SelectionValidator () singleTopLevelSelection Operation {operationType = Subscription, operationName} selSet =   case selectionsWitoutTypename selSet of-    (_ : xs) | not (null xs) -> failure $ map (singleTopLevelSelectionError operationName) xs+    (_ : xs) | not (null xs) -> failure $ fmap (singleTopLevelSelectionError operationName) xs     _ -> pure () singleTopLevelSelection _ _ = pure () -singleTopLevelSelectionError :: Maybe FieldName -> Selection VALID -> GQLError+singleTopLevelSelectionError :: Maybe FieldName -> Selection VALID -> ValidationError singleTopLevelSelectionError name Selection {selectionPosition} =-  GQLError-    { message =-        subscriptionName-          <> " must select "-          <> "only one top level field.",-      locations = [selectionPosition]-    }+  withPosition (Just selectionPosition) $+    subscriptionName+      <> " must select "+      <> "only one top level field."   where-    subscriptionName = maybe "Anonymous Subscription" (("Subscription " <>) . msg) name+    subscriptionName = maybe "Anonymous Subscription" (("Subscription " <>) . msgValidation) name  validateOperation ::   Operation RAW ->@@ -125,8 +131,8 @@       ..     } =     do-      typeDef <- getOperationObject rawOperation-      selection <- validateSelectionSet typeDef operationSelection+      typeDef <- getOperationType rawOperation+      selection <- validateSelectionSet (toCategory typeDef) operationSelection       singleTopLevelSelection rawOperation selection       directives <-         validateDirectives@@ -150,8 +156,8 @@ processSelectionDirectives ::   DirectiveLocation ->   Directives RAW ->-  (Directives VALID -> SelectionValidator (SelectionSet VALID)) ->-  SelectionValidator (SelectionSet VALID)+  (Directives VALID -> FragmentValidator s (SelectionSet VALID)) ->+  FragmentValidator s (SelectionSet VALID) processSelectionDirectives location rawDirectives sel = do   directives <- validateDirectives location rawDirectives   include <- shouldIncludeSelection directives@@ -161,13 +167,27 @@       then selection       else empty +vaidateFragmentSelection :: (ResolveFragment s) => Fragment RAW -> FragmentValidator s (SelectionSet VALID)+vaidateFragmentSelection f@Fragment {fragmentSelection} = do+  typeDef <- selectFragmentType f+  validateSelectionSet typeDef fragmentSelection++getFields :: TypeDefinition IMPLEMENTABLE s -> FieldsDefinition OUT s+getFields TypeDefinition {typeContent = DataObject {objectFields}} = objectFields+getFields TypeDefinition {typeContent = DataInterface fields} = fields+ validateSelectionSet ::-  TypeDef -> SelectionSet RAW -> SelectionValidator (SelectionSet VALID)-validateSelectionSet dataType@(typeName, fieldsDef) =+  forall s.+  ( ResolveFragment s+  ) =>+  TypeDefinition IMPLEMENTABLE VALID ->+  SelectionSet RAW ->+  FragmentValidator s (SelectionSet VALID)+validateSelectionSet typeDef =   concatTraverse validateSelection   where     -- validate single selection: InlineFragments and Spreads will Be resolved and included in SelectionSet-    validateSelection :: Selection RAW -> SelectionValidator (SelectionSet VALID)+    validateSelection :: Selection RAW -> FragmentValidator s (SelectionSet VALID)     validateSelection       sel@Selection         { selectionName,@@ -177,7 +197,7 @@           selectionDirectives         } =         withScope-          typeName+          typeDef           currentSelectionRef           $ processSelectionDirectives             FIELD@@ -185,19 +205,14 @@             (`validateSelectionContent` selectionContent)         where           currentSelectionRef = Ref selectionName selectionPosition-          commonValidation :: SelectionValidator (TypeDefinition OUT, Arguments VALID)+          commonValidation :: FragmentValidator s (TypeDefinition OUT VALID, Arguments VALID)           commonValidation = do-            (fieldDef :: FieldDefinition OUT) <- selectKnown (Ref selectionName selectionPosition) fieldsDef-            -- validate field Argument ------            arguments <--              validateFieldArguments-                fieldDef-                selectionArguments-            -- check field Type existence  ------            (typeDef :: TypeDefinition OUT) <- askFieldType fieldDef-            pure (typeDef, arguments)+            fieldDef <- selectKnown (Ref selectionName selectionPosition) (getFields typeDef)+            (,)+              <$> askType (typed fieldType fieldDef)+              <*> validateFieldArguments fieldDef selectionArguments           ------------------------------------------------------------------------------------          validateSelectionContent :: Directives VALID -> SelectionContent RAW -> SelectionValidator (SelectionSet VALID)+          validateSelectionContent :: Directives VALID -> SelectionContent RAW -> FragmentValidator s (SelectionSet VALID)           validateSelectionContent directives SelectionField             | null selectionArguments && selectionName == "__typename" =               pure $ singleton $@@ -208,73 +223,90 @@                   }             | otherwise = do               (datatype, validArgs) <- commonValidation-              isLeaf datatype-              pure $ singleton $-                sel-                  { selectionArguments = validArgs,-                    selectionDirectives = directives,-                    selectionContent = SelectionField-                  }-            where-              -------------------------------------------------------------              isLeaf :: TypeDefinition OUT -> SelectionValidator ()-              isLeaf TypeDefinition {typeName = typename, typeContent}-                | isEntNode typeContent = pure ()-                | otherwise =-                  failure $-                    subfieldsNotSelected selectionName typename selectionPosition+              selContent <-+                validateContentLeaf currentSelectionRef datatype+              pure $+                singleton+                  ( sel+                      { selectionArguments = validArgs,+                        selectionDirectives = directives,+                        selectionContent = selContent+                      }+                  )           ----- SelectionSet           validateSelectionContent directives (SelectionSet rawSelectionSet) =             do-              (TypeDefinition {typeName = name, typeContent}, validArgs) <- commonValidation-              selContent <- withScope name currentSelectionRef $ validateByTypeContent name typeContent+              (tyDef, validArgs) <- commonValidation+              selContent <- validateByTypeContent tyDef currentSelectionRef rawSelectionSet               pure $ singleton $                 sel                   { selectionArguments = validArgs,                     selectionDirectives = directives,                     selectionContent = selContent                   }-            where-              validateByTypeContent :: TypeName -> TypeContent TRUE OUT -> SelectionValidator (SelectionContent VALID)-              -- Validate UnionSelection-              validateByTypeContent _ DataUnion {unionMembers} =-                validateUnionSelection-                  validateSelectionSet-                  rawSelectionSet-                  unionMembers-              -- Validate Regular selection set-              validateByTypeContent typename DataObject {objectFields} =-                SelectionSet-                  <$> validateSelectionSet-                    (typename, objectFields)-                    rawSelectionSet-              validateByTypeContent typename DataInterface {interfaceFields} =-                SelectionSet-                  <$> validateSelectionSet-                    (typename, interfaceFields)-                    rawSelectionSet-              validateByTypeContent typename _ =-                failure $-                  hasNoSubfields-                    (Ref selectionName selectionPosition)-                    typename-    validateSelection (Spread dirs ref) =-      processSelectionDirectives FRAGMENT_SPREAD dirs-        $ const-        -- TODO: add directives to selection-        $ resolveSpread [typeName] ref-          >>= validateFragment+    validateSelection (Spread dirs ref) = do+      types <- possibleTypes typeDef <$> askSchema+      processSelectionDirectives+        FRAGMENT_SPREAD+        dirs+        (const $ unionTagSelection <$> resolveValidFragment vaidateFragmentSelection types ref)     validateSelection       ( InlineFragment           fragment@Fragment-            { fragmentDirectives,-              fragmentPosition+            { fragmentDirectives             }-        ) =-        processSelectionDirectives INLINE_FRAGMENT fragmentDirectives-          $ const-          -- TODO: add directives to selection-          $ castFragmentType Nothing fragmentPosition [typeName] fragment-            >>= validateFragment-    ---------------------------------------------------------------------------------    validateFragment Fragment {fragmentSelection} = validateSelectionSet dataType fragmentSelection+        ) = do+        types <- possibleTypes typeDef <$> askSchema+        processSelectionDirectives INLINE_FRAGMENT fragmentDirectives $+          const (validate types fragment)+    validate types = fmap fragmentSelection . validateFragment vaidateFragmentSelection types++validateContentLeaf ::+  Ref ->+  TypeDefinition OUT VALID ->+  FragmentValidator s' (SelectionContent s)+validateContentLeaf+  (Ref selectionName selectionPosition)+  TypeDefinition {typeName, typeContent}+    | isEntNode typeContent = pure SelectionField+    | otherwise =+      failure $ subfieldsNotSelected selectionName typeName selectionPosition++validateByTypeContent ::+  forall s.+  (ResolveFragment s) =>+  TypeDefinition OUT VALID ->+  Ref ->+  SelectionSet RAW ->+  FragmentValidator s (SelectionContent VALID)+validateByTypeContent+  typeDef@TypeDefinition {typeContent, ..}+  currentSelectionRef =+    withScope typeDef currentSelectionRef+      . __validate typeContent+    where+      __validate ::+        TypeContent TRUE OUT VALID ->+        SelectionSet RAW ->+        FragmentValidator s (SelectionContent VALID)+      -- Validate UnionSelection+      __validate DataUnion {unionMembers} =+        validateUnionSelection+          vaidateFragmentSelection+          validateSelectionSet+          unionMembers+      -- Validate Regular selection set+      __validate DataObject {..} =+        fmap SelectionSet . validateSelectionSet (TypeDefinition {typeContent = DataObject {..}, ..})+      -- TODO: Union Like Validation+      __validate DataInterface {..} =+        validateInterfaceSelection+          vaidateFragmentSelection+          validateSelectionSet+          (TypeDefinition {typeContent = DataInterface {..}, ..})+      __validate _ =+        const+          $ failure+          $ hasNoSubfields+            currentSelectionRef+            typeDef
src/Data/Morpheus/Validation/Query/UnionSelection.hs view
@@ -3,94 +3,119 @@ {-# LANGUAGE GADTs #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TupleSections #-}  module Data.Morpheus.Validation.Query.UnionSelection   ( validateUnionSelection,+    validateInterfaceSelection,   ) where  import Control.Monad ((>=>))+import Data.Maybe (isJust) -- MORPHEUS-import Data.Morpheus.Error.Selection (unknownSelectionField) import Data.Morpheus.Internal.Utils-  ( Failure (..),-    elems,+  ( elems,     empty,     fromElems,-    selectOr,-    singleton,   ) import Data.Morpheus.Types.Internal.AST   ( DataUnion,-    FieldsDefinition,     Fragment (..),-    OUT,+    IMPLEMENTABLE,     RAW,-    Ref (..),     Selection (..),     SelectionContent (..),     SelectionSet,     SelectionSet,+    TypeContent (..),+    TypeDefinition (..),     TypeName,-    UnionMember (..),     UnionTag (..),     VALID,+    mkType,+    toCategory,   ) import qualified Data.Morpheus.Types.Internal.AST.MergeSet as MS   ( join,   ) import Data.Morpheus.Types.Internal.Validation-  ( Scope (..),-    SelectionValidator,+  ( FragmentValidator,+    Scope (..),+    askInterfaceTypes,     askTypeMember,-    asks,+    asksScope,   ) import Data.Morpheus.Validation.Query.Fragment-  ( castFragmentType,-    resolveSpread,+  ( ResolveFragment (resolveValidFragment),+    castFragmentType,   ) -type TypeDef = (TypeName, FieldsDefinition OUT)---- returns all Fragments used in Union-exploreUnionFragments ::-  [UnionMember OUT] ->+-- returns all Fragments used for Possible Types+splitFragment ::+  (ResolveFragment s) =>+  ( Fragment RAW ->+    FragmentValidator s (SelectionSet VALID)+  ) ->+  [TypeDefinition IMPLEMENTABLE VALID] ->   Selection RAW ->-  SelectionValidator [Fragment]-exploreUnionFragments unionTags = splitFrag-  where-    packFragment fragment = [fragment]-    splitFrag ::-      Selection RAW -> SelectionValidator [Fragment]-    splitFrag (Spread _ ref) = packFragment <$> resolveSpread (map memberName unionTags) ref-    splitFrag Selection {selectionName = "__typename", selectionContent = SelectionField} = pure []-    splitFrag Selection {selectionName, selectionPosition} = do-      typeName <- asks typename-      failure $ unknownSelectionField typeName (Ref selectionName selectionPosition)-    splitFrag (InlineFragment fragment) =-      packFragment-        <$> castFragmentType Nothing (fragmentPosition fragment) (map memberName unionTags) fragment+  FragmentValidator s ([UnionTag], [Selection RAW])+splitFragment _ _ x@Selection {} = pure ([], [x])+splitFragment f types (Spread _ ref) = pureFirst <$> resolveValidFragment f (typeName <$> types) ref+splitFragment f types (InlineFragment fragment@Fragment {fragmentType}) =+  pureFirst . 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) =>+  ( Fragment RAW ->+    FragmentValidator s (SelectionSet VALID)+  ) ->+  [TypeDefinition IMPLEMENTABLE VALID] ->+  SelectionSet RAW ->+  FragmentValidator s ([UnionTag], SelectionSet RAW)+exploreFragments validateFragment types selectionSet =+  traverse (splitFragment validateFragment types) (elems selectionSet)+    >>= joinExploredSelection+ -- sorts Fragment by contitional Types -- [ --   ( Type for Tag User , [ Fragment for User] ) --   ( Type for Tag Product , [ Fragment for Product] ) -- ] tagUnionFragments ::-  [TypeDef] -> [Fragment] -> [(TypeDef, [Fragment])]+  [TypeDefinition IMPLEMENTABLE VALID] ->+  [UnionTag] ->+  [(TypeName, [SelectionSet VALID])] tagUnionFragments types fragments =-  filter notEmpty $-    map categorizeType types+  filter notEmpty (map categorizeType types)   where     notEmpty = not . null . snd-    categorizeType :: (TypeName, FieldsDefinition OUT) -> (TypeDef, [Fragment])-    categorizeType datatype = (datatype, filter matches fragments)+    categorizeType ::+      TypeDefinition IMPLEMENTABLE VALID ->+      (TypeName, [SelectionSet VALID])+    categorizeType datatype = (typeName datatype, unionTagSelection <$> filter matches fragments)       where-        matches fragment = fragmentType fragment == fst datatype+        matches = (`elem` subTypes datatype) . unionTagName +subTypes :: TypeDefinition a s -> [TypeName]+subTypes TypeDefinition {typeName, typeContent = DataObject {objectImplements}} =+  typeName : objectImplements+subTypes TypeDefinition {typeName} = [typeName]+ {-     - all Variable and Fragment references will be: resolved and validated     - unionTypes: will be clustered under type names@@ -102,29 +127,58 @@           UnionTag "T2" {<SelectionB>,<SelectionC>}       ]  -}-validateCluster ::-  (TypeDef -> SelectionSet RAW -> SelectionValidator (SelectionSet VALID)) ->-  SelectionSet RAW ->-  [(TypeDef, [Fragment])] ->-  SelectionValidator (SelectionContent VALID)-validateCluster validator __typename = traverse _validateCluster >=> fmap UnionSelection . fromElems+joinClusters ::+  forall s.+  SelectionSet VALID ->+  [(TypeName, [SelectionSet VALID])] ->+  FragmentValidator s (SelectionContent VALID)+joinClusters selSet =+  traverse joinCluster+    >=> fmap UnionSelection . fromElems   where-    _validateCluster :: (TypeDef, [Fragment]) -> SelectionValidator UnionTag-    _validateCluster (unionType, fragmets) = do-      fragmentSelections <- MS.join (__typename : map fragmentSelection fragmets)-      UnionTag (fst unionType) <$> validator unionType fragmentSelections+    joinCluster (typeName, fragmets) = UnionTag typeName <$> MS.join (selSet : fragmets) +validateInterfaceSelection ::+  ResolveFragment s =>+  (Fragment RAW -> FragmentValidator s (SelectionSet VALID)) ->+  (TypeDefinition IMPLEMENTABLE VALID -> SelectionSet RAW -> FragmentValidator s (SelectionSet VALID)) ->+  TypeDefinition IMPLEMENTABLE VALID ->+  SelectionSet RAW ->+  FragmentValidator s (SelectionContent VALID)+validateInterfaceSelection+  validateFragment+  validate+  typeDef+  inputSelectionSet = do+    possibleTypes <- askInterfaceTypes typeDef+    (spreads, selectionSet) <- exploreFragments validateFragment possibleTypes inputSelectionSet+    validSelectionSet <- validate typeDef selectionSet+    let categories = tagUnionFragments possibleTypes spreads+    if null categories+      then pure (SelectionSet validSelectionSet)+      else joinClusters validSelectionSet (insertDefault (typeName typeDef) categories)++insertDefault :: TypeName -> [(TypeName, [a])] -> [(TypeName, [a])]+insertDefault interfaceName categories+  | isJust (lookup interfaceName categories) = categories+  | otherwise = (interfaceName, []) : categories++mkUnionRootType :: FragmentValidator s (TypeDefinition IMPLEMENTABLE VALID)+mkUnionRootType = (`mkType` DataObject [] empty) <$> asksScope currentTypeName+ validateUnionSelection ::-  (TypeDef -> SelectionSet RAW -> SelectionValidator (SelectionSet VALID)) ->+  ResolveFragment s =>+  (Fragment RAW -> FragmentValidator s (SelectionSet VALID)) ->+  (TypeDefinition IMPLEMENTABLE VALID -> SelectionSet RAW -> FragmentValidator s (SelectionSet VALID)) ->+  DataUnion VALID ->   SelectionSet RAW ->-  DataUnion ->-  SelectionValidator (SelectionContent VALID)-validateUnionSelection validate selectionSet members = do-  let (__typename :: SelectionSet RAW) = selectOr empty singleton "__typename" selectionSet+  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 askTypeMember members+  unionTypes <- traverse (fmap toCategory . askTypeMember) members   -- find all Fragments used in Selection-  spreads <- concat <$> traverse (exploreUnionFragments members) (elems selectionSet)-  let categories = tagUnionFragments unionTypes spreads-  validateCluster validate __typename categories+  (spreads, selSet) <- exploreFragments validateFragment unionTypes selectionSet+  typeDef <- mkUnionRootType+  validSelection <- validate typeDef selSet+  joinClusters validSelection (tagUnionFragments unionTypes spreads)
src/Data/Morpheus/Validation/Query/Validation.hs view
@@ -3,7 +3,6 @@ {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeOperators #-}  module Data.Morpheus.Validation.Query.Validation   ( validateRequest,@@ -11,13 +10,15 @@ where  import Data.HashMap.Lazy (fromList)+import Data.Morpheus.Internal.Utils (empty) import Data.Morpheus.Types.Internal.AST   ( GQLQuery (..),     Operation (..),     Schema (..),+    TypeKind (..),     VALID,-    VALIDATION_MODE,   )+import Data.Morpheus.Types.Internal.Config (Config (..)) import Data.Morpheus.Types.Internal.Resolving   ( Eventless,   )@@ -31,21 +32,25 @@ import Data.Morpheus.Validation.Query.Fragment   ( validateFragments,   )+import Data.Morpheus.Validation.Query.FragmentPreconditions+  ( checkFragmentPreconditions,+  ) import Data.Morpheus.Validation.Query.Selection-  ( validateOperation,+  ( vaidateFragmentSelection,+    validateOperation,   ) import Data.Morpheus.Validation.Query.Variable   ( resolveOperationVariables,   )  validateRequest ::-  Schema ->-  VALIDATION_MODE ->+  Config ->+  Schema VALID ->   GQLQuery ->   Eventless (Operation VALID) validateRequest+  config   schema-  validationMode   GQLQuery     { fragments,       inputVariables,@@ -57,20 +62,55 @@           }     } =     do-      variables <- runValidator validateHelpers (ctx ())-      runValidator (validateOperation operation) (ctx variables)+      variables <-+        runValidator+          validateHelpers+          config+          schema+          scope+          ( OperationContext+              { selection,+                fragments,+                variables = empty+              }+          )+      validFragments <-+        runValidator+          (validateFragments vaidateFragmentSelection)+          config+          schema+          scope+          ( OperationContext+              { selection,+                fragments,+                variables+              }+          )+      runValidator+        (validateOperation operation)+        config+        schema+        scope+        ( OperationContext+            { selection,+              fragments = validFragments,+              variables+            }+        )     where-      ctx variables =-        OperationContext-          { schema,-            fragments,-            scope = Scope {typename = "Root", position = operationPosition, kind = SELECTION},-            selection = CurrentSelection {operationName, selectionName = "Root"},-            variables+      scope =+        Scope+          { kind = SELECTION,+            currentTypeName = "Root",+            currentTypeKind = KindObject Nothing,+            currentTypeWrappers = [],+            fieldname = "Root",+            position = Just operationPosition           }+      selection = CurrentSelection {operationName}       validateHelpers =-        validateFragments operationSelection+        checkFragmentPreconditions operationSelection           *> resolveOperationVariables+            config             (fromList inputVariables)-            validationMode             operation
src/Data/Morpheus/Validation/Query/Variable.hs view
@@ -2,17 +2,21 @@ {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Validation.Query.Variable   ( resolveOperationVariables,   ) where +import Control.Applicative ((*>), pure)+import Control.Monad (Monad ((>>=)))+import Data.Foldable (concat, concatMap)+import Data.Functor ((<$>), fmap) import qualified Data.HashMap.Lazy as M   ( lookup,   )-import Data.Maybe (maybe)---- MORPHEUS+import Data.Maybe (Maybe (..), maybe) import Data.Morpheus.Error.Variable (uninitializedVariable) import Data.Morpheus.Internal.Utils   ( Failure (..),@@ -37,7 +41,6 @@     TypeNameRef (..),     TypeRef (..),     VALID,-    VALIDATION_MODE (..),     ValidValue,     Value (..),     Variable (..),@@ -46,6 +49,10 @@     Variables,     isNullable,   )+import Data.Morpheus.Types.Internal.Config+  ( Config (..),+    VALIDATION_MODE (..),+  ) import Data.Morpheus.Types.Internal.Validation   ( BaseValidator,     Constraint (..),@@ -59,9 +66,21 @@     withPosition,   ) import Data.Morpheus.Validation.Internal.Value-  ( validateInput,+  ( validateInputByType,   ) import Data.Semigroup ((<>))+import Data.Traversable+  ( traverse,+  )+import Prelude+  ( ($),+    (&&),+    (.),+    Bool (..),+    Eq (..),+    not,+    otherwise,+  )  class ExploreRefs a where   exploreRefs :: a -> [Ref]@@ -105,13 +124,13 @@             )  resolveOperationVariables ::+  Config ->   Variables ->-  VALIDATION_MODE ->   Operation RAW ->   BaseValidator (VariableDefinitions VALID) resolveOperationVariables+  Config {validationMode}   root-  validationMode   Operation     { operationSelection,       operationArguments@@ -134,14 +153,14 @@   validationMode   var@Variable     { variableName,-      variableType,+      variableType = variableType@TypeRef {typeWrappers, typeConName},       variablePosition,       variableValue = DefaultValue defaultValue     } =     withPosition variablePosition $       toVariable         <$> ( askSchema-                >>= selectKnown (TypeNameRef (typeConName variableType) variablePosition)+                >>= selectKnown (TypeNameRef typeConName variablePosition)                 >>= constraint INPUT var                 >>= checkType getVariable defaultValue             )@@ -154,11 +173,11 @@       checkType ::         Maybe ResolvedValue ->         DefaultValue ->-        TypeDefinition IN ->+        TypeDefinition IN VALID ->         BaseValidator ValidValue       checkType (Just variable) Nothing varType = validator varType False variable       checkType (Just variable) (Just defValue) varType =-        validator varType True defValue >> validator varType False variable+        validator varType True defValue *> validator varType False variable       checkType Nothing (Just defValue) varType = validator varType True defValue       checkType Nothing Nothing varType         | validationMode /= WITHOUT_VARIABLES && not (isNullable variableType) =@@ -169,10 +188,12 @@           returnNull =             maybe (pure Null) (validator varType False) (M.lookup variableName bodyVariables)       ------------------------------------------------------------------------------------------------      validator :: TypeDefinition IN -> Bool -> ResolvedValue -> BaseValidator ValidValue-      validator varType isDefaultValue varValue =-        startInput (SourceVariable var isDefaultValue) $-          validateInput-            (typeWrappers variableType)-            varType-            (ObjectEntry variableName varValue)+      validator :: TypeDefinition IN VALID -> Bool -> ResolvedValue -> BaseValidator ValidValue+      validator varTypeDef isDefaultValue varValue =+        startInput+          (SourceVariable var isDefaultValue)+          ( validateInputByType+              typeWrappers+              varTypeDef+              varValue+          )
test/Lib.hs view
@@ -1,9 +1,12 @@+{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE NoImplicitPrelude #-}  module Lib   ( getGQLBody,-    getResponseBody,+    expectedResponse,     getCases,     maybeVariables,     readSource,@@ -11,30 +14,69 @@     FileUrl (..),     CaseTree (..),     toString,+    getRequest,+    assertValidSchema,+    getSchema,+    getResolvers,   ) where -import Control.Applicative ((<|>))+import Control.Applicative ((<|>), pure)+import Control.Monad ((>=>), Monad) import Data.Aeson (FromJSON, Value (..), decode) import qualified Data.ByteString.Lazy as L (readFile) import Data.ByteString.Lazy.Char8 (ByteString)-import Data.Maybe (fromMaybe)-import Data.Morpheus.Types.Internal.AST (FieldName (..))+import Data.Either (Either (..))+import Data.Foldable (foldl)+import Data.Functor ((<$>))+import Data.HashMap.Lazy (lookup)+import Data.Maybe (Maybe (..), fromMaybe, maybe)+import Data.Morpheus.Core (parseGQLDocument)+import Data.Morpheus.Types.IO+  ( GQLRequest (..),+  )+import Data.Morpheus.Types.Internal.AST (FieldName (..), Schema (..), VALID)+import Data.Morpheus.Types.Internal.Resolving+  ( Eventless,+    ResModel,+    RootResModel (..),+    WithOperation,+    mkNull,+    mkValue,+    resultOr,+  ) import Data.Semigroup ((<>)) import Data.Text (Text, unpack)+import qualified Data.Text.Lazy as LT (toStrict)+import Data.Text.Lazy.Encoding (decodeUtf8)+import Data.Traversable (traverse) import System.Directory (doesDirectoryExist, listDirectory)+import Test.Tasty.HUnit+  ( assertFailure,+  )+import Prelude+  ( ($),+    (.),+    Bool,+    FilePath,+    IO,+    Show,+    and,+    map,+    show,+  )  readSource :: FieldName -> IO ByteString readSource = L.readFile . path . readName -path :: Text -> String-path name = "test/" ++ unpack name+path :: Text -> FilePath+path name = "test/" <> unpack name -gqlLib :: Text -> String-gqlLib x = path x ++ "/query.gql"+gqlLib :: Text -> FilePath+gqlLib x = path x <> "/query.gql" -resLib :: Text -> String-resLib x = path x ++ "/response.json"+resLib :: Text -> FilePath+resLib x = path x <> "/response.json"  data FileUrl = FileUrl   { filePath :: [FilePath],@@ -44,7 +86,7 @@  data CaseTree = CaseTree   { caseUrl :: FileUrl,-    children :: Either [String] [CaseTree]+    children :: Either [FilePath] [CaseTree]   }   deriving (Show) @@ -65,12 +107,12 @@ deepScan = shouldScan . FileUrl []   where     shouldScan :: FileUrl -> IO CaseTree-    shouldScan caseUrl@FileUrl {..} = do+    shouldScan caseUrl = do       children <- prefixed caseUrl       pure CaseTree {..}     isDirectory :: FileUrl -> IO Bool     isDirectory = doesDirectoryExist . toString-    prefixed :: FileUrl -> IO (Either [String] [CaseTree])+    prefixed :: FileUrl -> IO (Either [FilePath] [CaseTree])     prefixed p = do       dir <- isDirectory p       if dir@@ -83,13 +125,53 @@         else pure $ Left []  maybeVariables :: FieldName -> IO (Maybe Value)-maybeVariables (FieldName x) = decode <$> (L.readFile (path x ++ "/variables.json") <|> return "{}")+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 => String -> IO [a]-getCases dir = fromMaybe [] . decode <$> L.readFile ("test/" ++ dir ++ "/cases.json")+getCases :: FromJSON a => FilePath -> IO [a]+getCases dir = fromMaybe [] . decode <$> L.readFile ("test/" <> dir <> "/cases.json") -getResponseBody :: FieldName -> IO Value-getResponseBody (FieldName p) = fromMaybe Null . decode <$> L.readFile (resLib p)+getSchema :: FieldName -> IO (Eventless (Schema VALID))+getSchema (FieldName x) = parseGQLDocument <$> 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 = do+  queryBS <- LT.toStrict . decodeUtf8 <$> getGQLBody p+  variables <- maybeVariables p+  pure $+    GQLRequest+      { operationName = Nothing,+        query = queryBS,+        variables+      }++getResolvers :: Monad m => FieldName -> IO (RootResModel e m)+getResolvers (FieldName p) = do+  res <- fromMaybe Null . decode <$> L.readFile (path p <> "/resolvers.json")+  pure+    RootResModel+      { query = pure (lookupRes "query" res),+        mutation = pure (lookupRes "mutation" res),+        subscription = pure (lookupRes "subscription" res),+        channelMap = Nothing+      }++lookupRes ::+  ( WithOperation o,+    Monad m+  ) =>+  Text ->+  Value ->+  ResModel o e m+lookupRes name (Object fields) = maybe mkNull mkValue (lookup name fields)+lookupRes _ _ = mkNull
− test/Schema.hs
@@ -1,93 +0,0 @@-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE DuplicateRecordFields #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE OverloadedStrings #-}--module Schema-  ( testSchema,-  )-where--import Control.Monad ((<=<))-import Data.Aeson ((.:), (.=), FromJSON (..), ToJSON (..), Value (..), eitherDecode, encode, object)-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.Either (either)-import Data.Morpheus.Core (parseFullGQLDocument, validateSchema)-import Data.Morpheus.Types.Internal.AST-  ( GQLErrors,-    Schema,-  )-import Data.Morpheus.Types.Internal.Resolving-  ( Eventless,-    Result (..),-  )-import Data.Semigroup ((<>))-import Data.Text (pack)-import GHC.Generics (Generic)-import Lib-  ( CaseTree (..),-    FileUrl (..),-    scanSchemaTests,-    toString,-  )-import Test.Tasty (TestTree, testGroup)-import Test.Tasty.HUnit (assertFailure, testCase)--readSource :: String -> IO ByteString-readSource = L.readFile--readSchema :: String -> IO (Eventless Schema)-readSchema = fmap (validateSchema <=< parseFullGQLDocument) . readSource . (<> "/schema.gql")--readResponse :: String -> 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-    (map 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 -> IO ()-assertion OK Success {} = return ()-assertion Errors {errors = err} Failure {errors}-  | err == errors =-    pure-      ()-assertion expected Success {} =-  assertFailure $-    LB.unpack-      ("expected: \n " <> encode expected <> " \n but got: \n OK")-assertion expected Failure {errors} =-  assertFailure $-    LB.unpack-      ("expected: \n " <> encode expected <> " \n but got: \n " <> encode (Errors errors))
test/Spec.hs view
@@ -1,154 +1,43 @@-{-# LANGUAGE DuplicateRecordFields #-}-{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE NoImplicitPrelude #-}  module Main   ( main,   ) where -import qualified Data.Aeson as A-import Data.Aeson (decode, encode)-import Data.Functor.Identity (Identity (..))-import Data.Morpheus.Core (runApi)-import Data.Morpheus.Internal.Utils-  ( fromElems,-  )-import Data.Morpheus.QuasiQuoter (dsl)-import Data.Morpheus.Types.IO-  ( GQLRequest (..),-  )-import Data.Morpheus.Types.Internal.AST-  ( FieldName,-    Schema,-    VALID,-    Value (..),-    msg,-  )-import Data.Morpheus.Types.Internal.Resolving-  ( ResModel,-    Resolver,-    ResponseStream,-    Result (..),-    ResultT (..),-    RootResModel (..),-    WithOperation,-    mkList,-    mkNull,-    mkObject,-    mkString,+import Test.Tasty+  ( defaultMain,+    testGroup,   )-import Data.Semigroup ((<>))-import qualified Data.Text.Lazy as LT (toStrict)-import Data.Text.Lazy.Encoding (decodeUtf8)-import Lib-  ( getGQLBody,-    getResponseBody,-    maybeVariables,+import Utils.Api+  ( apiTest,   )-import Schema+import Utils.Schema   ( testSchema,   )-import Test.Tasty-  ( TestTree,-    defaultMain,-    testGroup,-  )-import Test.Tasty.HUnit-  ( assertFailure,-    testCase,+import Prelude+  ( ($),+    IO,   ) -getSchema :: Monad m => ResponseStream e m Schema-getSchema =-  fromElems-    [dsl|-  -  type Query {-    deity(name: String): Deity!-  }--  interface Character {-    name : String-  }--  interface Supernatural {-    power: [String!]!-  }--  type Hero implements Character {-    name: String-  }--  type Deity implements Character Supernatural {-    name: String!-    power: [String!]!-  }-|]--resolver :: Monad m => RootResModel e m-resolver =-  RootResModel-    { query =-        pure $-          mkObject-            "Query"-            [("deity", resolveDeity)],-      mutation = pure mkNull,-      subscription = pure mkNull-    }--resolveDeity :: (WithOperation o, Monad m) => Resolver o e m (ResModel o e m)-resolveDeity =-  pure $-    mkObject-      "Deity"-      [ ("name", pure $ mkString "Morpheus"),-        ("power", pure $ mkList [mkString "Shapeshifting"])-      ]- main :: IO () main = do   schema <- testSchema-  defaultMain-    $ testGroup+  defaultMain $+    testGroup       "core tests"-    $ map-      (uncurry basicTest)-      [ ("basic Test", "api/simple"),-        ("test interface", "api/interface")+      [ schema,+        apiTest "api/deity" ["simple", "interface"],+        apiTest+          "api/validation/fragment"+          [ "on-type",+            "on-interface",+            "on-interface-inline",+            "on-union-type",+            "fail-unknown-field-on-interface",+            "on-interface-type-casting",+            "on-interface-type-casting-inline",+            "on-interface-fail-without-casting"+          ]       ]-      <> [schema]--basicTest :: String -> FieldName -> TestTree-basicTest description path = testCase description $ do-  actual <- simpleTest <$> getRequest path-  expected <- expectedResponse path-  assertion expected actual--simpleTest :: GQLRequest -> ResponseStream e Identity (Value VALID)-simpleTest request = do-  schema <- getSchema-  runApi schema resolver request--expectedResponse :: FieldName -> IO A.Value-expectedResponse = getResponseBody--assertion :: A.Value -> ResponseStream e Identity (Value VALID) -> IO ()-assertion expected (ResultT (Identity Success {result}))-  | Just expected == decode (encode result) = return ()-  | otherwise =-    assertFailure $ show ("expected: \n " <> msg expected <> " \n but got: \n " <> msg result)-assertion _ (ResultT (Identity Failure {errors})) = assertFailure (show errors)--getRequest :: FieldName -> IO GQLRequest-getRequest path = do-  queryBS <- LT.toStrict . decodeUtf8 <$> getGQLBody path-  variables <- maybeVariables path-  pure $-    GQLRequest-      { operationName = Nothing,-        query = queryBS,-        variables-      }
+ test/Utils/Api.hs view
@@ -0,0 +1,77 @@+{-# LANGUAGE DuplicateRecordFields #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE NoImplicitPrelude #-}++module Utils.Api+  ( apiTest,+    assertion,+  )+where++import Control.Applicative (pure)+import qualified Data.Aeson as A+import Data.Aeson (decode, encode)+import qualified Data.ByteString.Lazy.Char8 as LB (unpack)+import Data.Functor ((<$>), fmap)+import Data.Functor.Identity (Identity (..))+import Data.Maybe (Maybe (..))+import Data.Morpheus.Core (defaultConfig, runApi)+import Data.Morpheus.Types.IO+import Data.Morpheus.Types.Internal.AST+  ( FieldName (..),+    VALID,+    Value (..),+  )+import Data.Morpheus.Types.Internal.Resolving+  ( ResponseStream,+    ResultT (..),+  )+import Data.Semigroup ((<>))+import Data.Text (unpack)+import Lib+  ( assertValidSchema,+    expectedResponse,+    getRequest,+    getResolvers,+  )+import Test.Tasty+  ( TestTree,+    testGroup,+  )+import Test.Tasty.HUnit+  ( assertFailure,+    testCase,+  )+import Prelude+  ( ($),+    (==),+    IO,+    otherwise,+  )++assertion :: A.Value -> ResponseStream e Identity (Value VALID) -> IO ()+assertion expected (ResultT (Identity actual))+  | Just expected == decode actualValue = pure ()+  | otherwise =+    assertFailure $+      LB.unpack+        ("expected: \n\n " <> encode expected <> " \n\n but got: \n\n " <> actualValue)+  where+    actualValue = encode (renderResponse actual)++apiTest :: FieldName -> [FieldName] -> TestTree+apiTest apiPath requestPath =+  testGroup (unpack $ readName apiPath) $+    fmap (testApiRequest apiPath) requestPath++testApiRequest ::+  FieldName ->+  FieldName ->+  TestTree+testApiRequest apiPath path = testCase (unpack $ readName path) $ do+  schema <- assertValidSchema apiPath+  resolvers <- getResolvers apiPath+  let fullPath = apiPath <> "/" <> path+  actual <- runApi schema resolvers defaultConfig <$> getRequest fullPath+  expected <- expectedResponse fullPath+  assertion expected actual
+ test/Utils/Schema.hs view
@@ -0,0 +1,106 @@+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DuplicateRecordFields #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE NoImplicitPrelude #-}++module Utils.Schema+  ( testSchema,+  )+where++import Control.Applicative (pure)+import Data.Aeson ((.:), (.=), FromJSON (..), ToJSON (..), Value (..), eitherDecode, encode, object)+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.Either (Either (..), either)+import Data.Functor ((<$>), fmap)+import Data.Morpheus.Core (parseFullGQLDocument)+import Data.Morpheus.Types.Internal.AST+  ( GQLErrors,+    Schema,+    VALID,+  )+import Data.Morpheus.Types.Internal.Resolving+  ( Eventless,+    Result (..),+  )+import Data.Semigroup ((<>))+import Data.Text (pack)+import GHC.Generics (Generic)+import Lib+  ( CaseTree (..),+    FileUrl (..),+    scanSchemaTests,+    toString,+  )+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.HUnit (assertFailure, testCase)+import Prelude+  ( ($),+    (.),+    Eq (..),+    FilePath,+    IO,+    String,+    id,+    show,+  )++readSource :: FilePath -> IO ByteString+readSource = L.readFile++readSchema :: FilePath -> IO (Eventless (Schema VALID))+readSchema = fmap parseFullGQLDocument . 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 {} =+  assertFailure $+    LB.unpack+      ("expected: \n " <> encode expected <> " \n but got: \n OK")+assertion expected Failure {errors} =+  assertFailure $+    LB.unpack+      ("expected: \n " <> encode expected <> " \n but got: \n " <> encode (Errors errors))
+ test/api/deity/interface/query.gql view
@@ -0,0 +1,79 @@+query Get__Type {+  interface: __type(name: "Character") {+    ...FullType+  }+  deity: __type(name: "Deity") {+    ...FullType+  }+}++fragment FullType on __Type {+  kind+  name+  fields(includeDeprecated: true) {+    name+    args {+      ...InputValue+    }+    type {+      ...TypeRef+    }+    isDeprecated+    deprecationReason+  }+  inputFields {+    ...InputValue+  }+  interfaces {+    ...TypeRef+  }+  enumValues(includeDeprecated: true) {+    name+    isDeprecated+    deprecationReason+  }+  possibleTypes {+    ...TypeRef+  }+}++fragment InputValue on __InputValue {+  name+  type {+    ...TypeRef+  }+  defaultValue+}++fragment TypeRef on __Type {+  kind+  name+  ofType {+    kind+    name+    ofType {+      kind+      name+      ofType {+        kind+        name+        ofType {+          kind+          name+          ofType {+            kind+            name+            ofType {+              kind+              name+              ofType {+                kind+                name+              }+            }+          }+        }+      }+    }+  }+}
+ test/api/deity/interface/response.json view
@@ -0,0 +1,67 @@+{+  "data": {+    "interface": {+      "kind": "INTERFACE",+      "name": "Character",+      "fields": [+        {+          "name": "name",+          "args": [],+          "type": { "kind": "SCALAR", "name": "String", "ofType": null },+          "isDeprecated": false,+          "deprecationReason": null+        }+      ],+      "inputFields": null,+      "interfaces": null,+      "enumValues": null,+      "possibleTypes": [+        { "kind": "OBJECT", "name": "Deity", "ofType": null },+        { "kind": "OBJECT", "name": "Hero", "ofType": null }+      ]+    },+    "deity": {+      "kind": "OBJECT",+      "name": "Deity",+      "fields": [+        {+          "name": "name",+          "args": [],+          "type": {+            "kind": "NON_NULL",+            "name": null,+            "ofType": { "kind": "SCALAR", "name": "String", "ofType": null }+          },+          "isDeprecated": false,+          "deprecationReason": null+        },+        {+          "name": "power",+          "args": [],+          "type": {+            "kind": "NON_NULL",+            "name": null,+            "ofType": {+              "kind": "LIST",+              "name": null,+              "ofType": {+                "kind": "NON_NULL",+                "name": null,+                "ofType": { "kind": "SCALAR", "name": "String", "ofType": null }+              }+            }+          },+          "isDeprecated": false,+          "deprecationReason": null+        }+      ],+      "inputFields": null,+      "interfaces": [+        { "kind": "INTERFACE", "name": "Character", "ofType": null },+        { "kind": "INTERFACE", "name": "Supernatural", "ofType": null }+      ],+      "enumValues": null,+      "possibleTypes": null+    }+  }+}
+ test/api/deity/resolvers.json view
@@ -0,0 +1,8 @@+{+  "query": {+    "deity": {+      "name": "Morpheus",+      "power": ["Shapeshifting"]+    }+  }+}
+ test/api/deity/schema.gql view
@@ -0,0 +1,20 @@+type Query {+  deity(name: String): Deity!+}++interface Character {+  name: String+}++interface Supernatural {+  power: [String!]!+}++type Hero implements Character {+  name: String+}++type Deity implements Character & Supernatural {+  name: String!+  power: [String!]!+}
+ test/api/deity/simple/query.gql view
@@ -0,0 +1,6 @@+{+  deity {+    name+    power+  }+}
+ test/api/deity/simple/response.json view
@@ -0,0 +1,8 @@+{+  "data": {+    "deity": {+      "name": "Morpheus",+      "power": ["Shapeshifting"]+    }+  }+}
− test/api/interface/query.gql
@@ -1,79 +0,0 @@-query Get__Type {-  interface: __type(name: "Character") {-    ...FullType-  }-  deity: __type(name: "Deity") {-    ...FullType-  }-}--fragment FullType on __Type {-  kind-  name-  fields(includeDeprecated: true) {-    name-    args {-      ...InputValue-    }-    type {-      ...TypeRef-    }-    isDeprecated-    deprecationReason-  }-  inputFields {-    ...InputValue-  }-  interfaces {-    ...TypeRef-  }-  enumValues(includeDeprecated: true) {-    name-    isDeprecated-    deprecationReason-  }-  possibleTypes {-    ...TypeRef-  }-}--fragment InputValue on __InputValue {-  name-  type {-    ...TypeRef-  }-  defaultValue-}--fragment TypeRef on __Type {-  kind-  name-  ofType {-    kind-    name-    ofType {-      kind-      name-      ofType {-        kind-        name-        ofType {-          kind-          name-          ofType {-            kind-            name-            ofType {-              kind-              name-              ofType {-                kind-                name-              }-            }-          }-        }-      }-    }-  }-}
− test/api/interface/response.json
@@ -1,65 +0,0 @@-{-  "interface": {-    "kind": "INTERFACE",-    "name": "Character",-    "fields": [-      {-        "name": "name",-        "args": [],-        "type": { "kind": "SCALAR", "name": "String", "ofType": null },-        "isDeprecated": false,-        "deprecationReason": null-      }-    ],-    "inputFields": null,-    "interfaces": null,-    "enumValues": null,-    "possibleTypes": [-      { "kind": "OBJECT", "name": "Deity", "ofType": null },-      { "kind": "OBJECT", "name": "Hero", "ofType": null }-    ]-  },-  "deity": {-    "kind": "OBJECT",-    "name": "Deity",-    "fields": [-      {-        "name": "name",-        "args": [],-        "type": {-          "kind": "NON_NULL",-          "name": null,-          "ofType": { "kind": "SCALAR", "name": "String", "ofType": null }-        },-        "isDeprecated": false,-        "deprecationReason": null-      },-      {-        "name": "power",-        "args": [],-        "type": {-          "kind": "NON_NULL",-          "name": null,-          "ofType": {-            "kind": "LIST",-            "name": null,-            "ofType": {-              "kind": "NON_NULL",-              "name": null,-              "ofType": { "kind": "SCALAR", "name": "String", "ofType": null }-            }-          }-        },-        "isDeprecated": false,-        "deprecationReason": null-      }-    ],-    "inputFields": null,-    "interfaces": [-      { "kind": "INTERFACE", "name": "Character", "ofType": null },-      { "kind": "INTERFACE", "name": "Supernatural", "ofType": null }-    ],-    "enumValues": null,-    "possibleTypes": null-  }-}
− test/api/simple/query.gql
@@ -1,6 +0,0 @@-{-  deity {-    name-    power-  }-}
− test/api/simple/response.json
@@ -1,6 +0,0 @@-{-  "deity": {-    "name": "Morpheus",-    "power": ["Shapeshifting"]-  }-}
+ test/api/validation/fragment/fail-unknown-field-on-interface/query.gql view
@@ -0,0 +1,16 @@+{+  deity {+    ...onSupernatural+  }+  character {+    ...OnCharacter+  }+}++fragment OnCharacter on Character {+  power+}++fragment onSupernatural on Supernatural {+  name+}
+ test/api/validation/fragment/fail-unknown-field-on-interface/response.json view
@@ -0,0 +1,12 @@+{+  "errors": [+    {+      "message": "Cannot query field \"power\" on type \"Character\".",+      "locations": [{ "line": 11, "column": 3 }]+    },+    {+      "message": "Cannot query field \"name\" on type \"Supernatural\".",+      "locations": [{ "line": 15, "column": 3 }]+    }+  ]+}
+ test/api/validation/fragment/on-interface-fail-without-casting/query.gql view
@@ -0,0 +1,7 @@+{+  character {+    name+    power+    nickname+  }+}
+ test/api/validation/fragment/on-interface-fail-without-casting/response.json view
@@ -0,0 +1,22 @@+{+  "errors": [+    {+      "message": "Cannot query field \"power\" on type \"Character\".",+      "locations": [+        {+          "line": 4,+          "column": 5+        }+      ]+    },+    {+      "message": "Cannot query field \"nickname\" on type \"Character\".",+      "locations": [+        {+          "line": 5,+          "column": 5+        }+      ]+    }+  ]+}
+ test/api/validation/fragment/on-interface-inline/query.gql view
@@ -0,0 +1,12 @@+{+  deity {+    ... on Supernatural {+      power+    }+  }+  character {+    ... on Character {+      name+    }+  }+}
+ test/api/validation/fragment/on-interface-inline/response.json view
@@ -0,0 +1,10 @@+{+  "data": {+    "deity": { "power": ["Shapeshifting"] },+    "character": [+      { "name": "Test Deity" },+      { "name": "Test Hero" },+      { "name": "Test Character" }+    ]+  }+}
+ test/api/validation/fragment/on-interface-type-casting-inline/query.gql view
@@ -0,0 +1,13 @@+{+  character {+    ... on Character {+      name+    }+    ... on Deity {+      power+    }+    ... on Hero {+      nickname+    }+  }+}
+ test/api/validation/fragment/on-interface-type-casting-inline/response.json view
@@ -0,0 +1,17 @@+{+  "data": {+    "character": [+      {+        "name": "Test Deity",+        "power": ["Show Only on Deity"]+      },+      {+        "name": "Test Hero",+        "nickname": "tets Hero NickName"+      },+      {+        "name": "Test Character"+      }+    ]+  }+}
+ test/api/validation/fragment/on-interface-type-casting/query.gql view
@@ -0,0 +1,19 @@+{+  character {+    ...OnCharacter+    ...onDeity+    ...onHero+  }+}++fragment OnCharacter on Character {+  name+}++fragment onDeity on Deity {+  power+}++fragment onHero on Hero {+  nickname+}
+ test/api/validation/fragment/on-interface-type-casting/response.json view
@@ -0,0 +1,17 @@+{+  "data": {+    "character": [+      {+        "name": "Test Deity",+        "power": ["Show Only on Deity"]+      },+      {+        "name": "Test Hero",+        "nickname": "tets Hero NickName"+      },+      {+        "name": "Test Character"+      }+    ]+  }+}
+ test/api/validation/fragment/on-interface/query.gql view
@@ -0,0 +1,16 @@+{+  deity {+    ...OnSupernatural+  }+  character {+    ...OnCharacter+  }+}++fragment OnSupernatural on Supernatural {+  power+}++fragment OnCharacter on Character {+  name+}
+ test/api/validation/fragment/on-interface/response.json view
@@ -0,0 +1,10 @@+{+  "data": {+    "deity": { "power": ["Shapeshifting"] },+    "character": [+      { "name": "Test Deity" },+      { "name": "Test Hero" },+      { "name": "Test Character" }+    ]+  }+}
+ test/api/validation/fragment/on-type/query.gql view
@@ -0,0 +1,9 @@+{+  deity {+    ...OnDeity+  }+}++fragment OnDeity on Deity {+  name+}
+ test/api/validation/fragment/on-type/response.json view
@@ -0,0 +1,7 @@+{+  "data": {+    "deity": {+      "name": "Morpheus"+    }+  }+}
+ test/api/validation/fragment/on-union-type/query.gql view
@@ -0,0 +1,9 @@+{+  myUnion {+    ...onDeity+  }+}++fragment onDeity on Deity {+  power+}
+ test/api/validation/fragment/on-union-type/response.json view
@@ -0,0 +1,5 @@+{+  "data": {+    "myUnion": null+  }+}
+ test/api/validation/fragment/resolvers.json view
@@ -0,0 +1,29 @@+{+  "query": {+    "deity": {+      "__typename": "Deity",+      "name": "Morpheus",+      "power": ["Shapeshifting"]+    },+    "character": [+      {+        "__typename": "Deity",+        "name": "Test Deity",+        "power": ["Show Only on Deity"],+        "nickname": "this should be skipped"+      },+      {+        "__typename": "Hero",+        "name": "Test Hero",+        "power": ["this should be skipped"],+        "nickname": "tets Hero NickName"+      },+      {+        "__typename": "Character",+        "name": "Test Character",+        "nickname": "this should be skipped",+        "power": ["this should be skipped"]+      }+    ]+  }+}
+ test/api/validation/fragment/schema.gql view
@@ -0,0 +1,25 @@+interface Character {+  name: String+}++interface Supernatural {+  power: [String!]!+}++type Hero implements Character {+  name: String+  nickname: String+}++type Deity implements Character & Supernatural {+  name: String!+  power: [String!]!+}++union MyUnion = Hero | Deity++type Query {+  deity: Deity!+  myUnion: MyUnion+  character: [Character!]+}
+ test/schema/parsing/directive/ok/simple/response.json view
@@ -0,0 +1,1 @@+"OK"
+ test/schema/parsing/directive/ok/simple/schema.gql view
@@ -0,0 +1,5 @@+directive @MyDirective on FIELD_DEFINITION | OBJECT++type Query {+  name: String+}
+ test/schema/parsing/directive/ok/sophisticated/response.json view
@@ -0,0 +1,1 @@+"OK"
+ test/schema/parsing/directive/ok/sophisticated/schema.gql view
@@ -0,0 +1,17 @@+directive @DirectiveA on SCALAR++directive @DirectiveB(arg: Int) on FIELD_DEFINITION | INPUT_OBJECT++directive @DirectiveC(arg: MyInput! = {}) on FIELD_DEFINITION | FIELD_DEFINITION++directive @DirectiveD(+  arg: String = "bla"+) on FIELD_DEFINITION | FIELD_DEFINITION++input MyInput {+  field: Int+}++type Query {+  name: String+}
+ test/schema/parsing/schema-definition/fail/dupplicate-field/query-mutation-subscription/response.json view
@@ -0,0 +1,20 @@+{+  "errors": [+    {+      "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.\"subscription\"",+      "locations": []+    },+    {+      "message": "There can Be only One TypeDefinition for schema.\"subscription\"",+      "locations": []+    }+  ]+}
+ test/schema/parsing/schema-definition/fail/dupplicate-field/query-mutation-subscription/schema.gql view
@@ -0,0 +1,21 @@+type Query {+  name: String+}++type Mutation {+  name: String+}++type Subscription {+  name: String+}++schema {+  query: Query+  query: Query+  mutation: Mutation+  mutation: Mutation+  subscription: Subscription+  subscription: Subscription+  subscription: Subscription+}
+ test/schema/parsing/schema-definition/fail/dupplicate-field/query/response.json view
@@ -0,0 +1,12 @@+{+  "errors": [+    {+      "message": "There can Be only One TypeDefinition for schema.\"query\"",+      "locations": []+    },+    {+      "message": "There can Be only One TypeDefinition for schema.\"query\"",+      "locations": []+    }+  ]+}
+ test/schema/parsing/schema-definition/fail/dupplicate-field/query/schema.gql view
@@ -0,0 +1,9 @@+type Query {+  name: String+}++schema {+  query: Query+  query: Query+  query: Query+}
+ test/schema/parsing/schema-definition/fail/dupplicate-schema-definition/response.json view
@@ -0,0 +1,6 @@+{+  "errors": [+    { "message": "There can Be only One SchemaDefinition.", "locations": [] },+    { "message": "There can Be only One SchemaDefinition.", "locations": [] }+  ]+}
+ test/schema/parsing/schema-definition/fail/dupplicate-schema-definition/schema.gql view
@@ -0,0 +1,29 @@+type Query {+  name: String+}++schema {+  query: Query+  mutation: Mutation+  subscription: Subscription+}++schema {+  query: Query+  mutation: Mutation+  subscription: Subscription+}++type Mutation {+  name: String+}++type Subscription {+  name: String+}++schema {+  query: Query+  mutation: Mutation+  subscription: Subscription+}
+ test/schema/parsing/schema-definition/fail/unknown-fields/bla/response.json view
@@ -0,0 +1,8 @@+{+  "errors": [+    {+      "message": "offset=78:\nunexpected 'b'\nexpecting '}', Ignored, IgnoredTokens, OperationType, or white space\n",+      "locations": [{ "line": 8, "column": 3 }]+    }+  ]+}
+ test/schema/parsing/schema-definition/fail/unknown-fields/bla/schema.gql view
@@ -0,0 +1,9 @@+type MyType {+  name: String+}++schema {+  query: MyType+  mutation: MyType+  bla: MyType+}
+ test/schema/parsing/schema-definition/fail/unknown-fields/uppercase/response.json view
@@ -0,0 +1,8 @@+{+  "errors": [+    {+      "message": "offset=43:\nunexpected 'Q'\nexpecting '}', Ignored, OperationType, or white space\n",+      "locations": [{ "line": 6, "column": 3 }]+    }+  ]+}
+ test/schema/parsing/schema-definition/fail/unknown-fields/uppercase/schema.gql view
@@ -0,0 +1,7 @@+type MyType {+  name: String+}++schema {+  Query: MyType+}
+ test/schema/parsing/schema-definition/ok/query-mutation-subscription/response.json view
@@ -0,0 +1,1 @@+"OK"
+ test/schema/parsing/schema-definition/ok/query-mutation-subscription/schema.gql view
@@ -0,0 +1,17 @@+type Query {+  name: String+}++type Mutation {+  name: String+}++type Subscription {+  name: String+}++schema {+  query: Query+  mutation: Mutation+  subscription: Subscription+}
+ test/schema/parsing/schema-definition/ok/query-mutation/response.json view
@@ -0,0 +1,1 @@+"OK"
+ test/schema/parsing/schema-definition/ok/query-mutation/schema.gql view
@@ -0,0 +1,12 @@+type Query {+  name: String+}++type Mutation {+  name: String+}++schema {+  query: Query+  mutation: Mutation+}
+ test/schema/parsing/schema-definition/ok/query/response.json view
@@ -0,0 +1,1 @@+"OK"
+ test/schema/parsing/schema-definition/ok/query/schema.gql view
@@ -0,0 +1,12 @@+type Query {+  name: String+}++type Mutation {+  name: String+}++schema {+  query: Query+  mutation: Mutation+}
test/schema/validation/default-value/argument/missing-field/response.json view
@@ -13,11 +13,11 @@       "locations": []     },     {-      "message": "Field Query.field(i3:) got invalid default value. in field \"field\": Undefined Field \"field2\".",+      "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.field\": Undefined Field \"field\".",+      "message": "Field Query.field(i3:) got invalid default value. in field \"field\": Undefined Field \"field2\".",       "locations": []     }   ]
test/schema/validation/default-value/argument/unexpected-value/response.json view
@@ -2,31 +2,31 @@   "errors": [     {       "message": "Field Query.field(i1:) got invalid default value. in field \"field1.field2\": Expected type \"String\" found 1.",-      "locations": [{ "line": 0, "column": 0 }]+      "locations": []     },     {       "message": "Field Query.field(i1:) got invalid default value. in field \"field2\": Expected type \"String\" found true.",-      "locations": [{ "line": 0, "column": 0 }]+      "locations": []     },     {       "message": "Field Query.field(i2:) got invalid default value. in field \"field1\": Expected type \"ID\" found {field3: 2344}.",-      "locations": [{ "line": 0, "column": 0 }]+      "locations": []     },     {       "message": "Field Query.field(i2:) got invalid default value. in field \"field2\": Expected type \"String\" found 123.",-      "locations": [{ "line": 0, "column": 0 }]+      "locations": []     },     {       "message": "Field Query.field(i3:) got invalid default value. Expected type \"TestEnum\" found EnumBB.",-      "locations": [{ "line": 0, "column": 0 }]+      "locations": []     },     {       "message": "Field Query.field(i4:) got invalid default value. Expected type \"ID\" found true.",-      "locations": [{ "line": 0, "column": 0 }]+      "locations": []     },     {       "message": "Field Query.field(i5:) got invalid default value. Expected type \"Int\" found \"some text\".",-      "locations": [{ "line": 0, "column": 0 }]+      "locations": []     }   ] }
test/schema/validation/default-value/argument/unknown-field/response.json view
@@ -1,7 +1,7 @@ {   "errors": [     {-      "message": "Field Query.field(i1:) got invalid default value. in field \"field.field\": Unknown Field \"field3\".",+      "message": "Field Query.field(i1:) got invalid default value. Unknown Field \"field2\".",       "locations": []     },     {@@ -9,7 +9,7 @@       "locations": []     },     {-      "message": "Field Query.field(i1:) got invalid default value. Unknown Field \"field2\".",+      "message": "Field Query.field(i1:) got invalid default value. in field \"field.field\": Unknown Field \"field3\".",       "locations": []     }   ]
test/schema/validation/default-value/field/missing-field/response.json view
@@ -1,11 +1,11 @@ {   "errors": [     {-      "message": "Field Input3.field1 got invalid default value. Undefined Field \"field2\".",+      "message": "Field Input3.field1 got invalid default value. in field \"field\": Undefined Field \"field\".",       "locations": []     },     {-      "message": "Field Input3.field1 got invalid default value. in field \"field\": Undefined Field \"field\".",+      "message": "Field Input3.field1 got invalid default value. Undefined Field \"field2\".",       "locations": []     }   ]
test/schema/validation/default-value/field/unexpected-value/response.json view
@@ -2,35 +2,43 @@   "errors": [     {       "message": "Field Input2.objectField got invalid default value. in field \"field1\": Expected type \"ID!\" found true.",-      "locations": [{ "line": 0, "column": 0 }]+      "locations": []     },     {       "message": "Field Input2.objectField got invalid default value. in field \"field2\": Expected type \"String!\" found true.",-      "locations": [{ "line": 0, "column": 0 }]+      "locations": []     },     {       "message": "Field Input2.objectField got invalid default value. in field \"field3\": Expected type \"TestEnum\" found true.",-      "locations": [{ "line": 0, "column": 0 }]+      "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 Input1.field1 got invalid default value. Expected type \"ID!\" found EnumA.",-      "locations": [{ "line": 0, "column": 0 }]+      "locations": []     },     {       "message": "Field Input1.field2 got invalid default value. Expected type \"String!\" found EnumA.",-      "locations": [{ "line": 0, "column": 0 }]+      "locations": []     },     {       "message": "Field Input1.field3 got invalid default value. Expected type \"TestEnum\" found UnknownEnum.",-      "locations": [{ "line": 0, "column": 0 }]+      "locations": []     },     {       "message": "Field Input1.field4 got invalid default value. Expected type \"TestEnum!\" found 1.",-      "locations": [{ "line": 0, "column": 0 }]+      "locations": []     },     {       "message": "Field Input1.field5 got invalid default value. Expected type \"TestEnum\" found \"some text\".",-      "locations": [{ "line": 0, "column": 0 }]+      "locations": []     }   ] }
test/schema/validation/default-value/field/unknown-field/response.json view
@@ -1,15 +1,15 @@ {   "errors": [     {-      "message": "Field Input3.field got invalid default value. in field \"field\": Unknown Field \"field2\".",+      "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 \"field3\".",+      "message": "Field Input3.field got invalid default value. in field \"field\": Unknown Field \"field2\".",       "locations": []     },     {-      "message": "Field Input3.field got invalid default value. Unknown Field \"field2\".",+      "message": "Field Input3.field got invalid default value. in field \"field\": Unknown Field \"field3\".",       "locations": []     }   ]
+ test/schema/validation/directive/fail/at-invalid-place/response.json view
@@ -0,0 +1,36 @@+{+  "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 \"include\" may not to be used on FIELD_DEFINITION",+      "locations": [{ "line": 22, "column": 35 }]+    },+    {+      "message": "Directive \"DirectiveD\" may not to be used on ARGUMENT_DEFINITION",+      "locations": [{ "line": 22, "column": 17 }]+    }+  ]+}
+ test/schema/validation/directive/fail/at-invalid-place/schema.gql view
@@ -0,0 +1,23 @@+directive @DirectiveA on INPUT_OBJECT++directive @DirectiveB on SCALAR++directive @DirectiveC on ENUM++directive @DirectiveD on INPUT_FIELD_DEFINITION++scalar MyScalar @DirectiveA++enum TestEnum @DirectiveB {+  EnumA @DirectiveC+  EnumB+}++input Input1 @deprecated {+  field1: ID @include(if: true)+  field2: String+}++type Query @deprecated {+  field(a1: Int @DirectiveD): Int @include(if: true)+}
+ test/schema/validation/directive/fail/missing-argument/response.json view
@@ -0,0 +1,48 @@+{+  "errors": [+    {+      "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": 9, "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": 38 }]+    },+    {+      "message": "Directive \"@DirectiveC\" argument \"arg\" is required but not provided.",+      "locations": [{ "line": 20, "column": 17 }]+    },+    {+      "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": 11, "column": 13 }]+    },+    {+      "message": "Directive \"@DirectiveA\" argument \"a1\" is required but not provided.",+      "locations": [{ "line": 12, "column": 9 }]+    },+    {+      "message": "Directive \"@DirectiveA\" argument \"a2\" 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 }]+    }+  ]+}
+ test/schema/validation/directive/fail/missing-argument/schema.gql view
@@ -0,0 +1,25 @@+directive @DirectiveA(a1: String!, a2: Int!) on SCALAR | ENUM | ENUM_VALUE++directive @DirectiveB(a1: Int!) on INPUT_FIELD_DEFINITION | INPUT_OBJECT++directive @DirectiveC(+  arg: MyInput!+) on FIELD_DEFINITION | OBJECT | ARGUMENT_DEFINITION++scalar MyScalar @DirectiveA++enum MyEnum @DirectiveA {+  EnumA @DirectiveA+}++input MyInput @DirectiveB {+  field: String @DirectiveB+}++type MyType @DirectiveC {+  field(a1: Int @DirectiveC): String @DirectiveC+}++type Query {+  name: String+}
+ test/schema/validation/directive/fail/sopthisticated/response.json view
@@ -0,0 +1,64 @@+{+  "errors": [+    {+      "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": "Unknown Directive \"SomeDirective\".",+      "locations": [{ "line": 9, "column": 13 }]+    },+    {+      "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": "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 \"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": "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 }]+    }+  ]+}
+ test/schema/validation/directive/fail/sopthisticated/schema.gql view
@@ -0,0 +1,19 @@+directive @DirectiveA(a1: String!) on SCALAR++directive @DirectiveC(arg: Int!) on ARGUMENT_DEFINITION++enum MyEnum {+  EnumA @DirectiveA+}++type MyType @SomeDirective {+  field(a1: Int @DirectiveC(arg: True, someargs: 1)): String @DirectiveC+}++input Input @include {+  field: ID @skip+}++type Query @DirectiveC(arg: "bla") {+  field(a1: Int): Int @skip+}
+ test/schema/validation/directive/fail/unexpected-value/response.json view
@@ -0,0 +1,36 @@+{+  "errors": [+    {+      "message": "Argument \"a1\" got invalid value. Expected type \"Int!\" found 0.1.",+      "locations": [{ "line": 9, "column": 29 }]+    },+    {+      "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 \"some string\".",+      "locations": [{ "line": 10, "column": 30 }]+    },+    {+      "message": "Argument \"a1\" got invalid value. Expected type \"Int!\" found True.",+      "locations": [{ "line": 11, "column": 30 }]+    }+  ]+}
+ test/schema/validation/directive/fail/unexpected-value/schema.gql view
@@ -0,0 +1,26 @@+directive @DirectiveA(a1: Int!) on SCALAR++directive @DirectiveB(a1: MyInput!) on INPUT_FIELD_DEFINITION++input MyInput {+  field: String+}++scalar MyScalar @DirectiveA(a1: 0.1)+scalar MyScalar2 @DirectiveA(a1: "some string")+scalar MyScalar3 @DirectiveA(a1: True)++enum TestEnum {+  EnumA @deprecated(reason: EnumA)+  EnumB @deprecated(reason: 1)+  EnumB @deprecated(reason: Bool)+}++input Input {+  field1: ID @DirectiveB(a1: { field: 2394 })+  field2: String @DirectiveB(a1: ["some deprication"])+}++type Query {+  field: Int+}
+ test/schema/validation/directive/fail/unknown-directive/response.json view
@@ -0,0 +1,56 @@+{+  "errors": [+    {+      "message": "Unknown Directive \"DirectveD\".",+      "locations": [{ "line": 15, "column": 15 }]+    },+    {+      "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 \"DirectveE\".",+      "locations": [{ "line": 17, "column": 14 }]+    },+    {+      "message": "Unknown Directive \"DirectveE\".",+      "locations": [{ "line": 18, "column": 14 }]+    },+    {+      "message": "Unknown Directive \"DirectveC\".",+      "locations": [{ "line": 11, "column": 8 }]+    },+    {+      "message": "Unknown Directive \"DirectveC\".",+      "locations": [{ "line": 12, "column": 17 }]+    },+    {+      "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 }]+    }+  ]+}
+ test/schema/validation/directive/fail/unknown-directive/schema.gql view
@@ -0,0 +1,24 @@+scalar MyScalar @DirectveA++enum TestEnum @DirectveB {+  EnumA @DirectveB+  EnumB+}+type A @DirectveC {+  name: String! @DirectveC+}++type B @DirectveC {+  name: String! @DirectveC+}++union MyUnion @DirectveD = A | B++input Input1 @DirectveE {+  field1: ID @DirectveE+  field2: String+}++type Query @DirectveF {+  field(a1: Int @DirectveF): Int @DirectveF+}
+ test/schema/validation/directive/ok/deprecated/custom-directive/response.json view
@@ -0,0 +1,1 @@+"OK"
+ test/schema/validation/directive/ok/deprecated/custom-directive/schema.gql view
@@ -0,0 +1,25 @@+directive @DirectiveA on SCALAR | ENUM | ENUM_VALUE++directive @DirectiveB(arg: Int) on INPUT_FIELD_DEFINITION | INPUT_OBJECT++directive @DirectiveC(+  arg: MyInput! = {}+) on FIELD_DEFINITION | OBJECT | ARGUMENT_DEFINITION++scalar MyScalar @DirectiveA++enum MyEnum @DirectiveA {+  EnumA @DirectiveA+}++input MyInput @DirectiveB {+  field: String @DirectiveB+}++type MyType @DirectiveC {+  field(a1: Int @DirectiveC): String @DirectiveC+}++type Query {+  name: String+}
+ test/schema/validation/directive/ok/deprecated/response.json view
@@ -0,0 +1,1 @@+"OK"
+ test/schema/validation/directive/ok/deprecated/schema.gql view
@@ -0,0 +1,15 @@+scalar MyScalar++enum TestEnum {+  EnumA @deprecated+  EnumB+}++input Input1 {+  field1: ID+  field2: String+}++type Query {+  field(a1: Int): Int @deprecated+}
+ test/schema/validation/schema-definition/fail/non-object-kind/from-schema/response.json view
@@ -0,0 +1,16 @@+{+  "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": []+    }+  ]+}
+ test/schema/validation/schema-definition/fail/non-object-kind/from-schema/schema.gql view
@@ -0,0 +1,19 @@+input MyType {+  name: String+}++type MyType1 {+  name: String+}++enum MyEnum {+  Enum1+}++union MyUnion = MyType1++schema {+  query: MyType+  mutation: MyUnion+  subscription: MyEnum+}
+ test/schema/validation/schema-definition/fail/non-object-kind/without-schema/response.json view
@@ -0,0 +1,16 @@+{+  "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": []+    }+  ]+}
+ test/schema/validation/schema-definition/fail/non-object-kind/without-schema/schema.gql view
@@ -0,0 +1,13 @@+type MyType1 {+  name: String+}++input Query {+  name: String+}++union Mutation = MyType1++enum Subscription {+  Enum1+}
+ test/schema/validation/schema-definition/fail/required query/empty/response.json view
@@ -0,0 +1,8 @@+{+  "errors": [+    {+      "message": "Query root type must be provided.",+      "locations": []+    }+  ]+}
+ test/schema/validation/schema-definition/fail/required query/empty/schema.gql view
@@ -0,0 +1,5 @@+type MyType {+  name: String+}++schema {}
+ test/schema/validation/schema-definition/fail/required query/no-query/response.json view
@@ -0,0 +1,8 @@+{+  "errors": [+    {+      "message": "Query root type must be provided.",+      "locations": []+    }+  ]+}
+ test/schema/validation/schema-definition/fail/required query/no-query/schema.gql view
@@ -0,0 +1,7 @@+type MyType {+  name: String+}++schema {+  mutation: MyType+}
+ test/schema/validation/schema-definition/fail/required query/no-schema-no-query/response.json view
@@ -0,0 +1,8 @@+{+  "errors": [+    {+      "message": "Query root type must be provided.",+      "locations": []+    }+  ]+}
+ test/schema/validation/schema-definition/fail/required query/no-schema-no-query/schema.gql view
@@ -0,0 +1,3 @@+type MyType {+  name: String+}
+ test/schema/validation/schema-definition/fail/required query/schema-with-query/response.json view
@@ -0,0 +1,8 @@+{+  "errors": [+    {+      "message": "Query root type must be provided.",+      "locations": []+    }+  ]+}
+ test/schema/validation/schema-definition/fail/required query/schema-with-query/schema.gql view
@@ -0,0 +1,11 @@+type MyType {+  name: String+}++type Query {+  name: String+}++schema {+  mutation: MyType+}
+ test/schema/validation/schema-definition/fail/unknown-type/unknown/response.json view
@@ -0,0 +1,16 @@+{+  "errors": [+    {+      "message": "Unknown type \"MyType1\".",+      "locations": []+    },+    {+      "message": "Unknown type \"Asfwe\".",+      "locations": []+    },+    {+      "message": "Unknown type \"GjsO\".",+      "locations": []+    }+  ]+}
+ test/schema/validation/schema-definition/fail/unknown-type/unknown/schema.gql view
@@ -0,0 +1,9 @@+type MyType {+  name: String+}++schema {+  query: MyType1+  mutation: Asfwe+  subscription: GjsO+}
+ test/schema/validation/schema-definition/ok/full/response.json view
@@ -0,0 +1,1 @@+"OK"
+ test/schema/validation/schema-definition/ok/full/schema.gql view
@@ -0,0 +1,17 @@+type Query {+  name: String+}++type Mutation {+  name: String+}++type Subscription {+  name: String+}++schema {+  query: Query+  mutation: Mutation+  subscription: Subscription+}