forked from OSS/graphql
		
	@@ -19,17 +19,23 @@ import Data.Sequence (Seq(..))
 | 
			
		||||
import Data.Text (Text)
 | 
			
		||||
import qualified Data.Text as Text
 | 
			
		||||
import qualified Data.Sequence as Seq
 | 
			
		||||
import Language.GraphQL.AST.Document (Name)
 | 
			
		||||
import Language.GraphQL.AST.Core
 | 
			
		||||
import Language.GraphQL.Error
 | 
			
		||||
import Language.GraphQL.Execute.Coerce
 | 
			
		||||
import Language.GraphQL.Execute.Transform
 | 
			
		||||
import Language.GraphQL.Trans
 | 
			
		||||
import Language.GraphQL.Type.Definition
 | 
			
		||||
import qualified Language.GraphQL.Type.Definition as Definition
 | 
			
		||||
import qualified Language.GraphQL.Type.In as In
 | 
			
		||||
import qualified Language.GraphQL.Type.Out as Out
 | 
			
		||||
import Language.GraphQL.Type.Schema
 | 
			
		||||
 | 
			
		||||
resolveFieldValue :: Monad m => Value -> Field m -> ActionT m a -> m (Either Text a)
 | 
			
		||||
resolveFieldValue result (Field _ _ args _) =
 | 
			
		||||
    flip runReaderT (Context {arguments=args, values=result})
 | 
			
		||||
resolveFieldValue :: Monad m
 | 
			
		||||
    => Definition.Value
 | 
			
		||||
    -> Definition.Subs
 | 
			
		||||
    -> ActionT m a
 | 
			
		||||
    -> m (Either Text a)
 | 
			
		||||
resolveFieldValue result args =
 | 
			
		||||
    flip runReaderT (Context {arguments = Arguments args, values = result})
 | 
			
		||||
    . runExceptT
 | 
			
		||||
    . runActionT
 | 
			
		||||
 | 
			
		||||
@@ -54,10 +60,10 @@ aliasOrName (Field alias name _ _) = fromMaybe name alias
 | 
			
		||||
 | 
			
		||||
resolveAbstractType :: Monad m
 | 
			
		||||
    => AbstractType m
 | 
			
		||||
    -> HashMap Name Value
 | 
			
		||||
    -> HashMap Name Definition.Value
 | 
			
		||||
    -> CollectErrsT m (Maybe (Out.ObjectType m))
 | 
			
		||||
resolveAbstractType abstractType values'
 | 
			
		||||
    | Just (String typeName) <- HashMap.lookup "__typename" values' = do
 | 
			
		||||
    | Just (Definition.String typeName) <- HashMap.lookup "__typename" values' = do
 | 
			
		||||
        types' <- gets types
 | 
			
		||||
        case HashMap.lookup typeName types' of
 | 
			
		||||
            Just (ObjectType objectType) ->
 | 
			
		||||
@@ -97,40 +103,44 @@ instanceOf objectType (AbstractUnionType unionType) =
 | 
			
		||||
         in acc || this == that
 | 
			
		||||
 | 
			
		||||
executeField :: Monad m
 | 
			
		||||
    => Value
 | 
			
		||||
    => Definition.Value
 | 
			
		||||
    -> Out.Resolver m
 | 
			
		||||
    -> Field m
 | 
			
		||||
    -> CollectErrsT m Aeson.Value
 | 
			
		||||
executeField prev (Out.Resolver fieldDefinition resolver) field = do
 | 
			
		||||
    let Out.Field _ fieldType _ = fieldDefinition
 | 
			
		||||
    answer <- lift $ resolveFieldValue prev field resolver
 | 
			
		||||
    case answer of
 | 
			
		||||
        Right result -> completeValue fieldType field result
 | 
			
		||||
        Left errorMessage -> errmsg errorMessage
 | 
			
		||||
    let Out.Field _ fieldType argumentDefinitions = fieldDefinition
 | 
			
		||||
    let Field _ _ arguments' _ = field
 | 
			
		||||
    case coerceArgumentValues argumentDefinitions arguments' of
 | 
			
		||||
        Nothing -> errmsg "Argument coercing failed."
 | 
			
		||||
        Just argumentValues -> do
 | 
			
		||||
            answer <- lift $ resolveFieldValue prev argumentValues resolver
 | 
			
		||||
            case answer of
 | 
			
		||||
                Right result -> completeValue fieldType field result
 | 
			
		||||
                Left errorMessage -> errmsg errorMessage
 | 
			
		||||
 | 
			
		||||
completeValue :: Monad m
 | 
			
		||||
    => Out.Type m
 | 
			
		||||
    -> Field m
 | 
			
		||||
    -> Value
 | 
			
		||||
    -> Definition.Value
 | 
			
		||||
    -> CollectErrsT m Aeson.Value
 | 
			
		||||
completeValue _ _ Null = pure Aeson.Null
 | 
			
		||||
completeValue _ _ (Int integer) = pure $ Aeson.toJSON integer
 | 
			
		||||
completeValue _ _ (Boolean boolean') = pure $ Aeson.Bool boolean'
 | 
			
		||||
completeValue _ _ (Float float') = pure $ Aeson.toJSON float'
 | 
			
		||||
completeValue _ _ (Enum enum) = pure $ Aeson.String enum
 | 
			
		||||
completeValue _ _ (String string') = pure $ Aeson.String string'
 | 
			
		||||
completeValue _ _ Definition.Null = pure Aeson.Null
 | 
			
		||||
completeValue _ _ (Definition.Int integer) = pure $ Aeson.toJSON integer
 | 
			
		||||
completeValue _ _ (Definition.Boolean boolean') = pure $ Aeson.Bool boolean'
 | 
			
		||||
completeValue _ _ (Definition.Float float') = pure $ Aeson.toJSON float'
 | 
			
		||||
completeValue _ _ (Definition.Enum enum) = pure $ Aeson.String enum
 | 
			
		||||
completeValue _ _ (Definition.String string') = pure $ Aeson.String string'
 | 
			
		||||
completeValue (Out.ObjectBaseType objectType) (Field _ _ _ seqSelection) result =
 | 
			
		||||
    executeSelectionSet result objectType seqSelection
 | 
			
		||||
completeValue (Out.ListBaseType listType) selectionField (List list) =
 | 
			
		||||
completeValue (Out.ListBaseType listType) selectionField (Definition.List list) =
 | 
			
		||||
    Aeson.toJSON <$> traverse (completeValue listType selectionField) list
 | 
			
		||||
completeValue (Out.InterfaceBaseType interfaceType) (Field _ _ _ seqSelection) result
 | 
			
		||||
    | Object objectMap <- result = do
 | 
			
		||||
    | Definition.Object objectMap <- result = do
 | 
			
		||||
        abstractType <- resolveAbstractType (AbstractInterfaceType interfaceType) objectMap
 | 
			
		||||
        case abstractType of
 | 
			
		||||
            Just objectType -> executeSelectionSet result objectType seqSelection
 | 
			
		||||
            Nothing -> errmsg "Value completion failed."
 | 
			
		||||
completeValue (Out.UnionBaseType unionType) (Field _ _ _ seqSelection) result
 | 
			
		||||
    | Object objectMap <- result = do
 | 
			
		||||
    | Definition.Object objectMap <- result = do
 | 
			
		||||
        abstractType <- resolveAbstractType (AbstractUnionType unionType) objectMap
 | 
			
		||||
        case abstractType of
 | 
			
		||||
            Just objectType -> executeSelectionSet result objectType seqSelection
 | 
			
		||||
@@ -144,7 +154,7 @@ errmsg errorMessage = addErrMsg errorMessage >> pure Aeson.Null
 | 
			
		||||
-- to each 'Selection'. Resolves into a value containing the resolved
 | 
			
		||||
-- 'Selection', or a null value and error information.
 | 
			
		||||
executeSelectionSet :: Monad m
 | 
			
		||||
    => Value
 | 
			
		||||
    => Definition.Value
 | 
			
		||||
    -> Out.ObjectType m
 | 
			
		||||
    -> Seq (Selection m)
 | 
			
		||||
    -> CollectErrsT m Aeson.Value
 | 
			
		||||
@@ -161,3 +171,38 @@ executeSelectionSet result objectType@(Out.ObjectType _ _ _ resolvers) selection
 | 
			
		||||
        | Just typeField <- lookupResolver name =
 | 
			
		||||
            executeField result typeField fld
 | 
			
		||||
        | otherwise = errmsg $ Text.unwords ["field", name, "not resolved."]
 | 
			
		||||
 | 
			
		||||
coerceArgumentValues
 | 
			
		||||
    :: HashMap Name In.Argument
 | 
			
		||||
    -> HashMap Name Input
 | 
			
		||||
    -> Maybe Definition.Subs
 | 
			
		||||
coerceArgumentValues argumentDefinitions argumentValues =
 | 
			
		||||
    HashMap.foldrWithKey forEach (pure mempty) argumentDefinitions
 | 
			
		||||
  where
 | 
			
		||||
    forEach variableName (In.Argument _ variableType defaultValue) =
 | 
			
		||||
        matchFieldValues coerceArgumentValue argumentValues variableName variableType defaultValue
 | 
			
		||||
    coerceArgumentValue inputType (Int integer) =
 | 
			
		||||
        coerceInputLiteral inputType (Definition.Int integer)
 | 
			
		||||
    coerceArgumentValue inputType (Boolean boolean) =
 | 
			
		||||
        coerceInputLiteral inputType (Definition.Boolean boolean)
 | 
			
		||||
    coerceArgumentValue inputType (String string) =
 | 
			
		||||
        coerceInputLiteral inputType (Definition.String string)
 | 
			
		||||
    coerceArgumentValue inputType (Float float) =
 | 
			
		||||
        coerceInputLiteral inputType (Definition.Float float)
 | 
			
		||||
    coerceArgumentValue inputType (Enum enum) =
 | 
			
		||||
        coerceInputLiteral inputType (Definition.Enum enum)
 | 
			
		||||
    coerceArgumentValue inputType Null
 | 
			
		||||
        | In.isNonNullType inputType = Nothing
 | 
			
		||||
        | otherwise = coerceInputLiteral inputType Definition.Null
 | 
			
		||||
    coerceArgumentValue (In.ListBaseType inputType) (List list) =
 | 
			
		||||
        let coerceItem = coerceInputLiteral inputType
 | 
			
		||||
         in Definition.List <$> traverse coerceItem list
 | 
			
		||||
    coerceArgumentValue (In.InputObjectBaseType inputType) (Object object)
 | 
			
		||||
        | In.InputObjectType _ _ inputFields <- inputType = 
 | 
			
		||||
            let go = forEachField object
 | 
			
		||||
                resultMap = HashMap.foldrWithKey go (pure mempty) inputFields
 | 
			
		||||
             in Definition.Object <$> resultMap
 | 
			
		||||
    coerceArgumentValue _ (Variable variable) = pure variable
 | 
			
		||||
    coerceArgumentValue _ _ = Nothing
 | 
			
		||||
    forEachField object variableName (In.InputField _ variableType defaultValue) =
 | 
			
		||||
        matchFieldValues coerceArgumentValue object variableName variableType defaultValue
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user