packages feed

morpheus-graphql-app 0.18.0 → 0.19.0

raw patch · 24 files changed

+158/−153 lines, 24 filesdep ~aesondep ~morpheus-graphql-coredep ~morpheus-graphql-testsPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: aeson, morpheus-graphql-core, morpheus-graphql-tests

API changes (from Hackage documentation)

- Data.Morpheus.App: App :: AppData event m VALID -> App event (m :: * -> *)
+ Data.Morpheus.App: App :: AppData event m VALID -> App event (m :: Type -> Type)
- Data.Morpheus.App: AppData :: Config -> RootResolverValue event m -> Schema s -> AppData event (m :: * -> *) s
+ Data.Morpheus.App: AppData :: Config -> RootResolverValue event m -> Schema s -> AppData event (m :: Type -> Type) s
- Data.Morpheus.App: FailApp :: GQLErrors -> App event (m :: * -> *)
+ Data.Morpheus.App: FailApp :: GQLErrors -> App event (m :: Type -> Type)
- Data.Morpheus.App: [appConfig] :: AppData event (m :: * -> *) s -> Config
+ Data.Morpheus.App: [appConfig] :: AppData event (m :: Type -> Type) s -> Config
- Data.Morpheus.App: [appErrors] :: App event (m :: * -> *) -> GQLErrors
+ Data.Morpheus.App: [appErrors] :: App event (m :: Type -> Type) -> GQLErrors
- Data.Morpheus.App: [appResolvers] :: AppData event (m :: * -> *) s -> RootResolverValue event m
+ Data.Morpheus.App: [appResolvers] :: AppData event (m :: Type -> Type) s -> RootResolverValue event m
- Data.Morpheus.App: [appSchema] :: AppData event (m :: * -> *) s -> Schema s
+ Data.Morpheus.App: [appSchema] :: AppData event (m :: Type -> Type) s -> Schema s
- Data.Morpheus.App: [app] :: App event (m :: * -> *) -> AppData event m VALID
+ Data.Morpheus.App: [app] :: App event (m :: Type -> Type) -> AppData event m VALID
- Data.Morpheus.App: data App event (m :: * -> *)
+ Data.Morpheus.App: data App event (m :: Type -> Type)
- Data.Morpheus.App: data AppData event (m :: * -> *) s
+ Data.Morpheus.App: data AppData event (m :: Type -> Type) s
- Data.Morpheus.App.Internal.Resolving: NamedEnumResolver :: TypeName -> NamedResolverResult (m :: * -> *)
+ Data.Morpheus.App.Internal.Resolving: NamedEnumResolver :: TypeName -> NamedResolverResult (m :: Type -> Type)
- Data.Morpheus.App.Internal.Resolving: NamedObjectResolver :: ObjectTypeResolver m -> NamedResolverResult (m :: * -> *)
+ Data.Morpheus.App.Internal.Resolving: NamedObjectResolver :: ObjectTypeResolver m -> NamedResolverResult (m :: Type -> Type)
- Data.Morpheus.App.Internal.Resolving: NamedResolver :: TypeName -> (ValidValue -> m (NamedResolverResult m)) -> NamedResolver (m :: * -> *)
+ Data.Morpheus.App.Internal.Resolving: NamedResolver :: TypeName -> (ValidValue -> m (NamedResolverResult m)) -> NamedResolver (m :: Type -> Type)
- Data.Morpheus.App.Internal.Resolving: NamedUnionResolver :: NamedResolverRef -> NamedResolverResult (m :: * -> *)
+ Data.Morpheus.App.Internal.Resolving: NamedUnionResolver :: NamedResolverRef -> NamedResolverResult (m :: Type -> Type)
- Data.Morpheus.App.Internal.Resolving: [resolverName] :: NamedResolver (m :: * -> *) -> TypeName
+ Data.Morpheus.App.Internal.Resolving: [resolverName] :: NamedResolver (m :: Type -> Type) -> TypeName
- Data.Morpheus.App.Internal.Resolving: [resolver] :: NamedResolver (m :: * -> *) -> ValidValue -> m (NamedResolverResult m)
+ Data.Morpheus.App.Internal.Resolving: [resolver] :: NamedResolver (m :: Type -> Type) -> ValidValue -> m (NamedResolverResult m)
- Data.Morpheus.App.Internal.Resolving: data NamedResolver (m :: * -> *)
+ Data.Morpheus.App.Internal.Resolving: data NamedResolver (m :: Type -> Type)
- Data.Morpheus.App.Internal.Resolving: data NamedResolverResult (m :: * -> *)
+ Data.Morpheus.App.Internal.Resolving: data NamedResolverResult (m :: Type -> Type)
- Data.Morpheus.Types.GQLWrapper: class DecodeWrapper (f :: * -> *)
+ Data.Morpheus.Types.GQLWrapper: class DecodeWrapper (f :: Type -> Type)
- Data.Morpheus.Types.GQLWrapper: class EncodeWrapper (wrapper :: * -> *)
+ Data.Morpheus.Types.GQLWrapper: class EncodeWrapper (wrapper :: Type -> Type)
- Data.Morpheus.Types.GQLWrapper: type family DecodeWrapperConstraint (f :: * -> *) a :: Constraint
+ Data.Morpheus.Types.GQLWrapper: type family DecodeWrapperConstraint (f :: Type -> Type) a :: Constraint

Files

README.md view
@@ -4,27 +4,28 @@  ## Build schema-first GraphQL App with dynamic typings -```hs-schema :: Schema VALID-schema =-  [dsl|-  type Deity {-    name: String-    power: [String!]-  }+###### schema.gql -  type Query {-    deity(id: ID): Deity-  }-|]+```gql+type Deity {+  name: String+  power: [String!]+} +type Query {+  deity(id: ID): Deity+}+```++###### App.hs++```hs deityResolver :: Monad m => NamedResolverFunction QUERY e m-deityResolver "morpheus" =+deityResolver arg =   object     [ ("name", pure "Morpheus"),       ("power", pure $ list [enum "Shapeshifting"])     ]-deityResolver _ = object []  resolver :: Monad m => RootResolverValue e m resolver =@@ -34,5 +35,7 @@     ]  api :: ByteString -> IO  ByteString-api = runApp (mkApp schema resolver)+api query = do+  schema <- LBS.readFile "./schema.gql" >>= resultOr (fail . show) pure . parseSchema+  runApp (mkApp schema resolver) query ```
changelog.md view
@@ -1,5 +1,7 @@ # Changelog +## 0.19.0 - 21.03.2022+ ## 0.18.0 - 08.11.2021  - Data.Morpheus.App.NamedResolvers (inspired by apollo [named resolvers](https://www.apollographql.com/docs/apollo-server/data/resolvers/#as-this-example-shows)
morpheus-graphql-app.cabal view
@@ -3,11 +3,9 @@ -- This file has been generated from package.yaml by hpack version 0.34.4. -- -- see: https://github.com/sol/hpack------ hash: e84d4f16b2769bb325709eb8d8bb59c050c021ce4f9111621b7ec6e79d22b810  name:           morpheus-graphql-app-version:        0.18.0+version:        0.19.0 synopsis:       Morpheus GraphQL App description:    Build GraphQL APIs with your favourite functional language! category:       web, graphql@@ -35,13 +33,13 @@     test/api/validation/fragment/on-type/query.gql     test/api/validation/fragment/on-union-type/query.gql     test/api/validation/fragment/schema.gql-    test/merge/schema/query-subscription-mutation/app-ext.gql-    test/merge/schema/query-subscription-mutation/app-main.gql+    test/merge/schema/query-subscription-mutation/app-1.gql+    test/merge/schema/query-subscription-mutation/app-2.gql     test/merge/schema/query-subscription-mutation/mutation/query.gql     test/merge/schema/query-subscription-mutation/query/query.gql     test/merge/schema/query-subscription-mutation/rendering.gql-    test/merge/schema/simple-query/app-ext.gql-    test/merge/schema/simple-query/app-main.gql+    test/merge/schema/simple-query/app-1.gql+    test/merge/schema/simple-query/app-2.gql     test/merge/schema/simple-query/query/query.gql     test/merge/schema/simple-query/rendering.gql     test/named-resolvers/deities-ext/query.gql@@ -71,12 +69,12 @@     test/api/validation/fragment/on-type/response.json     test/api/validation/fragment/on-union-type/response.json     test/api/validation/fragment/resolvers.json-    test/merge/schema/query-subscription-mutation/app-ext.json-    test/merge/schema/query-subscription-mutation/app-main.json+    test/merge/schema/query-subscription-mutation/app-1.json+    test/merge/schema/query-subscription-mutation/app-2.json     test/merge/schema/query-subscription-mutation/mutation/response.json     test/merge/schema/query-subscription-mutation/query/response.json-    test/merge/schema/simple-query/app-ext.json-    test/merge/schema/simple-query/app-main.json+    test/merge/schema/simple-query/app-1.json+    test/merge/schema/simple-query/app-2.json     test/merge/schema/simple-query/query/response.json     test/named-resolvers/deities-ext/response.json     test/named-resolvers/deities/response.json@@ -119,13 +117,13 @@       src   ghc-options: -Wall   build-depends:-      aeson >=1.4.4.0 && <=1.6+      aeson >=1.4.4.0 && <3     , base >=4.7 && <5     , bytestring >=0.10.4 && <0.11     , containers >=0.4.2.1 && <0.7     , hashable >=1.0.0     , megaparsec >=7.0.0 && <10.0.0-    , morpheus-graphql-core >=0.18.0 && <0.19.0+    , morpheus-graphql-core >=0.19.0 && <0.20.0     , mtl >=2.0 && <=3.0     , relude >=0.3.0     , scientific >=0.3.6.2 && <0.4@@ -155,8 +153,8 @@     , hashable >=1.0.0     , megaparsec >=7.0.0 && <10.0.0     , morpheus-graphql-app-    , morpheus-graphql-core >=0.18.0 && <0.19.0-    , morpheus-graphql-tests >=0.18.0 && <0.19.0+    , morpheus-graphql-core >=0.19.0 && <0.20.0+    , morpheus-graphql-tests >=0.19.0 && <0.20.0     , mtl >=2.0 && <=3.0     , relude >=0.3.0     , scientific >=0.3.6.2 && <0.4
src/Data/Morpheus/App.hs view
@@ -78,7 +78,7 @@     (App . AppData defaultConfig appResolvers)     (validateSchema True defaultConfig appSchema) -data App event (m :: * -> *)+data App event (m :: Type -> Type)   = App {app :: AppData event m VALID}   | FailApp {appErrors :: GQLErrors} @@ -92,7 +92,7 @@   App {} <> FailApp {appErrors} = FailApp appErrors   (App x) <> (App y) = resultOr FailApp App (stitch x y) -data AppData event (m :: * -> *) s = AppData+data AppData event (m :: Type -> Type) s = AppData   { appConfig :: Config,     appResolvers :: RootResolverValue event m,     appSchema :: Schema s@@ -124,34 +124,34 @@   Config ->   GQLRequest ->   ResponseStream event m ResolverContext-validateReq inputSchema config request = ResultT-  $ pure-  $ do-    validSchema <- validateSchema True config inputSchema-    schema <- internalSchema <:> validSchema-    operation <- parseRequestWith config validSchema request-    pure-      ( [],-        ResolverContext-          { schema,-            config,-            operation,-            currentType =-              toAny $-                fromMaybe-                  (AST.query schema)-                  (rootType (operationType operation) schema),-            currentSelection =-              Selection-                { selectionName = "Root",-                  selectionArguments = empty,-                  selectionPosition = operationPosition operation,-                  selectionAlias = Nothing,-                  selectionContent = SelectionSet (operationSelection operation),-                  selectionDirectives = empty-                }-          }-      )+validateReq inputSchema config request = ResultT $+  pure $+    do+      validSchema <- validateSchema True config inputSchema+      schema <- internalSchema <:> validSchema+      operation <- parseRequestWith config validSchema request+      pure+        ( [],+          ResolverContext+            { schema,+              config,+              operation,+              currentType =+                toAny $+                  fromMaybe+                    (AST.query schema)+                    (rootType (operationType operation) schema),+              currentSelection =+                Selection+                  { selectionName = "Root",+                    selectionArguments = empty,+                    selectionPosition = operationPosition operation,+                    selectionAlias = Nothing,+                    selectionContent = SelectionSet (operationSelection operation),+                    selectionDirectives = empty+                  }+            }+        )  rootType :: OperationType -> Schema s -> Maybe (AST.TypeDefinition AST.OBJECT s) rootType Query = Just . AST.query
src/Data/Morpheus/App/Internal/Resolving/Resolver.hs view
@@ -172,8 +172,8 @@   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+-- Using the 'ResolverContext' itself is unsafe because it exposes 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@@ -199,9 +199,9 @@   Resolver QUERY e m (e -> Resolver SUBSCRIPTION e m a) ->   SubscriptionField (Resolver SUBSCRIPTION e m a) subscribe ch res =-  SubscriptionField ch $-    ResolverS $-      fromSub <$> runResolverQ res+  SubscriptionField ch+    $ ResolverS+    $ fromSub <$> runResolverQ res   where     fromSub :: Monad m => (e -> Resolver SUBSCRIPTION e m a) -> ReaderT e (ResolverStateT () m) a     fromSub f = join (ReaderT (runResolverS . f))
src/Data/Morpheus/App/Internal/Resolving/Types.hs view
@@ -48,9 +48,9 @@ import GHC.Show (Show (show)) import Relude hiding (show) -type ResolverMap (m :: * -> *) = HashMap TypeName (NamedResolver m)+type ResolverMap (m :: Type -> Type) = HashMap TypeName (NamedResolver m) -data NamedResolver (m :: * -> *) = NamedResolver+data NamedResolver (m :: Type -> Type) = NamedResolver   { resolverName :: TypeName,     resolver :: ValidValue -> m (NamedResolverResult m)   }@@ -72,7 +72,7 @@   }   deriving (Show) -data NamedResolverResult (m :: * -> *)+data NamedResolverResult (m :: Type -> Type)   = NamedObjectResolver (ObjectTypeResolver m)   | NamedUnionResolver NamedResolverRef   | NamedEnumResolver TypeName
src/Data/Morpheus/App/Internal/Resolving/Utils.hs view
@@ -21,7 +21,6 @@  import Control.Monad.Except (MonadError (throwError)) import qualified Data.Aeson as A-import qualified Data.HashMap.Lazy as HM import Data.Morpheus.App.Internal.Resolving.Types   ( NamedResolverRef (..),     ObjectTypeResolver (..),@@ -30,24 +29,27 @@     mkNull,     mkObjectMaybe,   )-import Data.Morpheus.Internal.Utils (selectOr)+import qualified Data.Morpheus.Internal.Utils as U+import Data.Morpheus.Internal.Utils (selectOr, toAssoc) import Data.Morpheus.Types.Internal.AST-  ( GQLError,+  ( FieldName,+    GQLError,     ScalarValue (..),     TypeName,     decodeScientific,     internal,     packName,+    unpackName,   ) import qualified Data.Vector as V import Relude -lookupResJSON :: (MonadError GQLError f, Monad m) => Text -> A.Value -> f (ObjectTypeResolver m)+lookupResJSON :: (MonadError GQLError f, Monad m) => FieldName -> A.Value -> f (ObjectTypeResolver m) lookupResJSON name (A.Object fields) =   selectOr     mkEmptyObject     (requireObject . mkValue)-    name+    (unpackName name)     fields lookupResJSON _ _ = mkEmptyObject @@ -60,10 +62,10 @@   ResolverValue m mkValue (A.Object v) =   mkObjectMaybe-    (HM.lookup "__typename" v >>= unpackJSONName)+    (U.lookup "__typename" v >>= unpackJSONName)     $ fmap       (bimap packName (pure . mkValue))-      (HM.toList v)+      (toAssoc v) mkValue (A.Array ls) = mkList (fmap mkValue (V.toList ls)) mkValue A.Null = mkNull mkValue (A.Number x) = ResScalar (decodeScientific x)
src/Data/Morpheus/Types/GQLWrapper.hs view
@@ -29,7 +29,7 @@ import Relude  -- | GraphQL Wrapper Serializer-class EncodeWrapper (wrapper :: * -> *) where+class EncodeWrapper (wrapper :: Type -> Type) where   encodeWrapper ::     (Monad m) =>     (a -> m (ResolverValue m)) ->@@ -67,12 +67,12 @@ instance EncodeWrapper SubscriptionField where   encodeWrapper encode (SubscriptionField _ res) = encode res -type family DecodeWrapperConstraint (f :: * -> *) a :: Constraint where+type family DecodeWrapperConstraint (f :: Type -> Type) a :: Constraint where   DecodeWrapperConstraint Set a = (Ord a)   DecodeWrapperConstraint f a = ()  -- | GraphQL Wrapper Deserializer-class DecodeWrapper (f :: * -> *) where+class DecodeWrapper (f :: Type -> Type) where   decodeWrapper ::     (Monad m, DecodeWrapperConstraint f a) =>     (ValidValue -> m a) ->@@ -110,7 +110,7 @@   ExceptT GQLError m (Set a) haveSameSize setVal listVal   | length setVal == length listVal = pure setVal-  | otherwise = ExceptT $ pure $ Left (fromString ("Expected a List without duplicates, found " <> show (length listVal - length listVal) <> " duplicates"))+  | otherwise = ExceptT $ pure $ Left (fromString ("Expected a List without duplicates, found " <> show (length listVal - length setVal) <> " duplicates"))  withRefinedList ::   Monad m =>
+ test/merge/schema/query-subscription-mutation/app-1.gql view
@@ -0,0 +1,7 @@+type Query {+  name: String+}++type Mutation {+  name(i: Int): String+}
+ test/merge/schema/query-subscription-mutation/app-1.json view
@@ -0,0 +1,8 @@+{+  "query": {+    "name": "query name from app"+  },+  "mutation": {+    "name": "mutation name from app"+  }+}
+ test/merge/schema/query-subscription-mutation/app-2.gql view
@@ -0,0 +1,12 @@+type Query {+  id: ID+  name: String+}++type Mutation {+  id: ID+}++type Subscription {+  name: String+}
+ test/merge/schema/query-subscription-mutation/app-2.json view
@@ -0,0 +1,9 @@+{+  "query": {+    "name": "query name from ext",+    "id": "query id from ext"+  },+  "mutation": {+    "id": "mutation id from ext"+  }+}
− test/merge/schema/query-subscription-mutation/app-ext.gql
@@ -1,12 +0,0 @@-type Query {-  id: ID-  name: String-}--type Mutation {-  id: ID-}--type Subscription {-  name: String-}
− test/merge/schema/query-subscription-mutation/app-ext.json
@@ -1,9 +0,0 @@-{-  "query": {-    "name": "query name from ext",-    "id": "query id from ext"-  },-  "mutation": {-    "id": "mutation id from ext"-  }-}
− test/merge/schema/query-subscription-mutation/app-main.gql
@@ -1,7 +0,0 @@-type Query {-  name: String-}--type Mutation {-  name(i: Int): String-}
− test/merge/schema/query-subscription-mutation/app-main.json
@@ -1,8 +0,0 @@-{-  "query": {-    "name": "query name from app"-  },-  "mutation": {-    "name": "mutation name from app"-  }-}
+ test/merge/schema/simple-query/app-1.gql view
@@ -0,0 +1,12 @@+type Type1 {+  name: String+}++type Type2 {+  name: String+  age: Int+}++type Query {+  type: Type2+}
+ test/merge/schema/simple-query/app-1.json view
@@ -0,0 +1,8 @@+{+  "query": {+    "type": {+      "name": "name from app",+      "age": 23+    }+  }+}
+ test/merge/schema/simple-query/app-2.gql view
@@ -0,0 +1,9 @@+type Type2 {+  name: String+  id: ID+}++type Query {+  id: ID+  type: Type2+}
+ test/merge/schema/simple-query/app-2.json view
@@ -0,0 +1,9 @@+{+  "query": {+    "type": {+      "name": "name from ext",+      "id": "id from ext"+    },+    "id": "id from ext"+  }+}
− test/merge/schema/simple-query/app-ext.gql
@@ -1,9 +0,0 @@-type Type2 {-  name: String-  id: ID-}--type Query {-  id: ID-  type: Type2-}
− test/merge/schema/simple-query/app-ext.json
@@ -1,9 +0,0 @@-{-  "query": {-    "type": {-      "name": "name from ext",-      "id": "id from ext"-    },-    "id": "id from ext"-  }-}
− test/merge/schema/simple-query/app-main.gql
@@ -1,12 +0,0 @@-type Type1 {-  name: String-}--type Type2 {-  name: String-  age: Int-}--type Query {-  type: Type2-}
− test/merge/schema/simple-query/app-main.json
@@ -1,8 +0,0 @@-{-  "query": {-    "type": {-      "name": "name from app",-      "age": 23-    }-  }-}