packages feed

morpheus-graphql-core 0.23.0 → 0.24.0

raw patch · 15 files changed

+115/−50 lines, 15 filesdep ~morpheus-graphql-testsPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: morpheus-graphql-tests

API changes (from Hackage documentation)

+ Data.Morpheus.Error: printError :: String -> String -> GQLError -> String
+ Data.Morpheus.Error: printWarning :: GQLError -> String
- Data.Morpheus.Types.Internal.AST: [Selection] :: Position -> Maybe FieldName -> FieldName -> Arguments s -> Directives s -> SelectionContent s -> Selection s
+ Data.Morpheus.Types.Internal.AST: [Selection] :: Position -> Maybe FieldName -> FieldName -> Arguments s -> Directives s -> SelectionContent s -> Maybe FragmentName -> Selection s
- Data.Morpheus.Types.Internal.AST: [UnionSelection] :: SelectionSet VALID -> UnionSelection VALID -> SelectionContent VALID
+ Data.Morpheus.Types.Internal.AST: [UnionSelection] :: Maybe (SelectionSet VALID) -> UnionSelection VALID -> SelectionContent VALID

Files

morpheus-graphql-core.cabal view
@@ -1,11 +1,11 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.34.4.+-- This file has been generated from package.yaml by hpack version 0.35.0. -- -- see: https://github.com/sol/hpack  name:           morpheus-graphql-core-version:        0.23.0+version:        0.24.0 synopsis:       Morpheus GraphQL Core description:    Build GraphQL APIs with your favorite functional language! category:       web, graphql@@ -21,7 +21,9 @@     README.md     changelog.md data-files:+    test/query/parsing/selection-set/empty-selection-2/query.gql     test/query/parsing/selection-set/empty-selection/query.gql+    test/query/parsing/selection-set/non-empty-selection-2/query.gql     test/query/parsing/selection-set/non-empty-selection/query.gql     test/query/validation/__typename/arguments/query.gql     test/query/validation/__typename/schema.gql@@ -98,7 +100,9 @@     "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/query/parsing/selection-set/empty-selection-2/response.json     test/query/parsing/selection-set/empty-selection/response.json+    test/query/parsing/selection-set/non-empty-selection-2/response.json     test/query/parsing/selection-set/non-empty-selection/response.json     test/query/validation/__typename/arguments/response.json     test/query/validation/__typename/selection-set/response.json@@ -270,7 +274,7 @@     , hashable >=1.0.0 && <2.0.0     , megaparsec >=7.0.0 && <10.0.0     , morpheus-graphql-core-    , morpheus-graphql-tests >=0.23.0 && <0.24.0+    , morpheus-graphql-tests >=0.24.0 && <0.25.0     , mtl >=2.0.0 && <3.0.0     , relude >=0.3.0 && <2.0.0     , scientific >=0.3.6.2 && <0.4.0
src/Data/Morpheus/Error.hs view
@@ -8,6 +8,8 @@     subfieldsNotSelected,     NameCollision (..),     gqlWarnings,+    printWarning,+    printError,   ) where 
src/Data/Morpheus/Error/Warning.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-} {-# LANGUAGE NoImplicitPrelude #-}  module Data.Morpheus.Error.Warning@@ -7,6 +8,8 @@     deprecatedEnum,     deprecatedField,     gqlWarnings,+    printWarning,+    printError,   ) where @@ -14,17 +17,20 @@ import Data.ByteString.Lazy.Char8 (unpack) import Data.Morpheus.Types.Internal.AST.Base   ( Description,+    Position (..),     Ref (..),   ) import Data.Morpheus.Types.Internal.AST.Error-  ( GQLError,+  ( GQLError (..),     GQLErrors,+    PropName (..),     at,     msg,   ) import Data.Morpheus.Types.Internal.AST.Name   ( FieldName,   )+import qualified Data.Text as T import Language.Haskell.TH import Relude @@ -54,7 +60,38 @@  gqlWarnings :: [GQLError] -> Q () gqlWarnings [] = pure ()-gqlWarnings warnings = traverse_ handleWarning warnings+gqlWarnings warnings = traverse_ (reportWarning . printWarning) warnings++printWarning :: GQLError -> String+printWarning = printError "warning" "\x1b[33m"++printError :: String -> String -> GQLError -> String+printError label color warning =+  withColor (label <> ":")+    <> description+    <> loc+    <> printedPath+    <> "\n"   where-    handleWarning warning =-      reportWarning ("Morpheus GraphQL Warning: " <> (unpack . encode) warning)+    propPath = concat $ toList $ path warning+    propLoc = concat $ toList $ locations warning+    description = indent <> withColor (toString (message warning))+    loc+      | null propPath = ""+      | otherwise = indent <> "  locations: " <> concatMap printLocation propLoc+    printedPath+      | null propPath = ""+      | otherwise = indent <> "  path: " <> intercalate "." (map printPath propPath)++    withColor :: String -> String+    withColor x = color <> x <> "\x1b[0m"++indent :: String+indent = "\n      "++printPath :: PropName -> String+printPath (PropIndex x) = show x+printPath (PropName x) = T.unpack x++printLocation :: Position -> String+printLocation Position {..} = show line <> ":" <> show column
src/Data/Morpheus/Parsing/Request/Selection.hs view
@@ -80,6 +80,7 @@       <*> maybeArguments       <*> optionalDirectives       <*> parseSelectionContent+      <*> pure empty  parseSelectionContent :: Parser (SelectionContent RAW) parseSelectionContent =
src/Data/Morpheus/Types/Internal/AST/Error.hs view
@@ -18,7 +18,8 @@     GQLErrors,     GQLError       ( message,-        locations+        locations,+        path       ),     manyMsg,     Msg (..),@@ -80,7 +81,7 @@ {-# INLINE atPositions #-}  withExtensions :: GQLError -> Map Text Value -> GQLError-withExtensions gqlerr ext = gqlerr {extensions = Just ext}+withExtensions gqlErr ext = gqlErr {extensions = Just ext}  withPath :: GQLError -> [PropName] -> GQLError withPath err [] = err
src/Data/Morpheus/Types/Internal/AST/Selection.hs view
@@ -126,7 +126,7 @@   SelectionField :: SelectionContent s   SelectionSet :: SelectionSet s -> SelectionContent s   UnionSelection ::-    { defaultSelection :: SelectionSet VALID,+    { defaultSelection :: Maybe (SelectionSet VALID),       conditionalSelections :: UnionSelection VALID     } ->     SelectionContent VALID@@ -142,7 +142,7 @@     where       unionSelectionElements :: [Either (Selection VALID) UnionTag]       unionSelectionElements =-        map Left (toList interfaceFields)+        map Left (concatMap toList $ maybeToList interfaceFields)           <> map Right (sortOn unionTagName $ toList unionSets)  instance@@ -153,7 +153,7 @@   Merge (HistoryT m) (SelectionContent s)   where   merge (SelectionSet s1) (SelectionSet s2) = SelectionSet <$> merge s1 s2-  merge (UnionSelection m1 u1) (UnionSelection m2 u2) = UnionSelection <$> merge m1 m2 <*> merge u1 u2+  merge (UnionSelection m1 u1) (UnionSelection m2 u2) = UnionSelection <$> withMaybe m1 m2 <*> merge u1 u2   merge oldC currentC     | oldC == currentC = pure oldC     | otherwise = do@@ -163,6 +163,12 @@               `atPositions` fmap refPosition path           ) +withMaybe :: (Merge f a, Monad f) => Maybe a -> Maybe a -> f (Maybe a)+withMaybe (Just x) (Just y) = Just <$> merge x y+withMaybe (Just x) Nothing = pure $ Just x+withMaybe Nothing (Just y) = pure $ Just y+withMaybe Nothing Nothing = pure Nothing+ deriving instance Show (SelectionContent a)  deriving instance Eq (SelectionContent a)@@ -227,7 +233,8 @@       selectionName :: FieldName,       selectionArguments :: Arguments s,       selectionDirectives :: Directives s,-      selectionContent :: SelectionContent s+      selectionContent :: SelectionContent s,+      selectionOrigin :: Maybe FragmentName     } ->     Selection s   InlineFragment :: Fragment RAW -> Selection RAW@@ -287,6 +294,7 @@             { selectionAlias = mergeAlias,               selectionPosition = pos1,               selectionDirectives = dirs,+              selectionOrigin = Nothing,               ..             }     where
src/Data/Morpheus/Types/SelectionTree.hs view
@@ -86,7 +86,7 @@     SelectionField -> mempty     (SelectionSet deeperSel) -> toList deeperSel     (UnionSelection interfaceSelection sel) ->-      toList interfaceSelection+      concatMap toList (toList interfaceSelection)         <> concatMap           (toList . unionTagSelection)           (toList sel)@@ -94,7 +94,7 @@   getChild name node = case selectionContent node of     SelectionField -> Nothing     (SelectionSet deeperSel) -> __lookup name deeperSel-    (UnionSelection interfaceSelection sel) -> select (interfaceSelection : map unionTagSelection (toList sel))+    (UnionSelection interfaceSelection sel) -> select (toList interfaceSelection <> map unionTagSelection (toList sel))       where         select (x : xs) = __lookup name x <|> select xs         select [] = Nothing
src/Data/Morpheus/Validation/Query/Fragment.hs view
@@ -34,6 +34,7 @@     Position,     RAW,     Ref (..),+    Selection (..),     SelectionSet,     Stage,     TypeDefinition,@@ -71,8 +72,8 @@   Ref FragmentName ->   FragmentValidator s UnionTag validateSpread f allowedTargets ref = do-  fragment@Fragment {fragmentType} <- resolveSpread allowedTargets ref-  UnionTag fragmentType <$> validateFragmentSelection f fragment+  fragment@Fragment {fragmentType, fragmentName} <- resolveSpread allowedTargets ref+  UnionTag fragmentType . fmap (\s -> s {selectionOrigin = Just fragmentName}) <$> validateFragmentSelection f fragment  validateFragment ::   (Fragment RAW -> FragmentValidator s (SelectionSet VALID)) ->
src/Data/Morpheus/Validation/Query/UnionSelection.hs view
@@ -14,6 +14,7 @@   ) where +import Control.Monad.Except (MonadError (throwError)) import qualified Data.HashMap.Lazy as HM import Data.Mergeable (OrdMap) import Data.Morpheus.Internal.Utils@@ -23,7 +24,6 @@     selectOr,     startHistory,   )-import Data.Morpheus.Types.Internal.AST.Base (Position (..)) import Data.Morpheus.Types.Internal.AST.Name (TypeName) import Data.Morpheus.Types.Internal.AST.Selection   ( Fragment (..),@@ -82,23 +82,13 @@   ) ->   OrdMap TypeName (TypeDefinition IMPLEMENTABLE VALID) ->   SelectionSet RAW ->-  FragmentValidator s ([UnionTag], SelectionSet RAW)+  FragmentValidator s ([UnionTag], Maybe (SelectionSet RAW)) exploreFragments validateFragment types selectionSet = do   (tags, selections) <- partitionEithers <$> traverse (splitFragment validateFragment (toList types)) (toList selectionSet)-  selectionPosition <- fromMaybe (Position 0 0) <$> asksScope position   (tags,)-    <$> fromElems-      ( ( Selection-            { selectionName = "__typename",-              selectionAlias = Nothing,-              selectionPosition,-              selectionArguments = empty,-              selectionContent = SelectionField,-              selectionDirectives = empty-            }-        )-          : selections-      )+    <$> if null selections+      then pure Nothing+      else Just <$> fromElems selections  -- sorts Fragment by conditional Types -- [@@ -134,18 +124,25 @@ getCompatibleTypes TypeDefinition {typeName, typeContent = DataObject {objectImplements}} = typeName : objectImplements getCompatibleTypes TypeDefinition {typeName} = [typeName] +maybeMerge :: [SelectionSet VALID] -> FragmentValidator s (Maybe (SelectionSet VALID))+maybeMerge [] = pure Nothing+maybeMerge (x : xs) = Just <$> startHistory (mergeConcat (x :| xs))++noEmptySelection :: FragmentValidator s a+noEmptySelection = throwError "empty selection sets are not supported."+ joinClusters ::-  SelectionSet VALID ->+  Maybe (SelectionSet VALID) ->   HashMap TypeName [SelectionSet VALID] ->   FragmentValidator s (SelectionContent VALID)-joinClusters selSet typedSelections-  | null typedSelections = pure (SelectionSet selSet)+joinClusters maybeSelSet typedSelections+  | null typedSelections = maybe noEmptySelection (pure . SelectionSet) maybeSelSet   | otherwise =       traverse mkUnionTag (HM.toList typedSelections)-        >>= fmap (UnionSelection selSet) . startHistory . fromElems+        >>= fmap (UnionSelection maybeSelSet) . startHistory . fromElems   where     mkUnionTag :: (TypeName, [SelectionSet VALID]) -> FragmentValidator s UnionTag-    mkUnionTag (typeName, fragments) = UnionTag typeName <$> startHistory (mergeConcat (selSet :| fragments))+    mkUnionTag (typeName, fragments) = UnionTag typeName <$> (maybeMerge (toList maybeSelSet <> fragments) >>= maybe noEmptySelection pure)  validateInterfaceSelection ::   ValidateFragmentSelection s =>@@ -161,10 +158,9 @@   inputSelectionSet = do     possibleTypes <- askInterfaceTypes typeDef     (spreads, selectionSet) <- exploreFragments validateFragment possibleTypes inputSelectionSet-    validSelectionSet <- validate typeDef selectionSet+    validSelectionSet <- traverse (validate typeDef) selectionSet     let tags = tagUnionFragments spreads possibleTypes-    let interfaces = selectOr [] id typeName tags-    defaultSelection <- startHistory $ mergeConcat (validSelectionSet :| interfaces)+    defaultSelection <- maybeMerge (toList validSelectionSet <> selectOr [] id typeName tags)     joinClusters defaultSelection (HM.delete typeName tags)  mkUnionRootType :: FragmentValidator s (TypeDefinition IMPLEMENTABLE VALID)@@ -177,9 +173,10 @@   UnionTypeDefinition OUT VALID ->   SelectionSet RAW ->   FragmentValidator s (SelectionContent VALID)-validateUnionSelection validateFragment validate members selectionSet = do-  unionTypes <- traverse (fmap toCategory . askTypeMember) members-  (spreads, selSet) <- exploreFragments validateFragment unionTypes selectionSet+validateUnionSelection validateFragment validate members inputSelectionSet = do   typeDef <- mkUnionRootType-  validSelection <- validate typeDef selSet-  joinClusters validSelection (tagUnionFragments spreads unionTypes)+  possibleTypes <- traverse (fmap toCategory . askTypeMember) members+  (spreads, selectionSet) <- exploreFragments validateFragment possibleTypes inputSelectionSet+  validSelectionSet <- traverse (validate typeDef) selectionSet+  let tags = tagUnionFragments spreads possibleTypes+  joinClusters validSelectionSet tags
+ test/query/parsing/selection-set/empty-selection-2/query.gql view
@@ -0,0 +1,6 @@+query {+  field1 {+    ... on X {+    }+  }+}
+ test/query/parsing/selection-set/empty-selection-2/response.json view
@@ -0,0 +1,5 @@+[+  {+    "message": "empty selection sets are not supported."+  }+]
+ test/query/parsing/selection-set/non-empty-selection-2/query.gql view
@@ -0,0 +1,7 @@+query {+  field1 {+    ... on X {+      name+    }+  }+}
+ test/query/parsing/selection-set/non-empty-selection-2/response.json view
@@ -0,0 +1,1 @@+"OK"
test/rendering/union/interface/rendering.gql view
@@ -1,9 +1,7 @@ query {   character {-    __typename     name     ... on Hero {-      __typename       name       hobby     }
test/rendering/union/union/rendering.gql view
@@ -1,12 +1,9 @@ query {   mortal {-    __typename     ... on Animal {-      __typename       weight     }     ... on Human {-      __typename       name     }   }