morpheus-graphql 0.18.0 → 0.19.0
raw patch · 59 files changed
+680/−161 lines, 59 filesdep ~aesondep ~morpheus-graphql-appdep ~morpheus-graphql-code-gensetup-changedPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: aeson, morpheus-graphql-app, morpheus-graphql-code-gen, morpheus-graphql-core, morpheus-graphql-subscriptions, morpheus-graphql-tests
API changes (from Hackage documentation)
- Data.Morpheus: deriveApp :: DeriveApp f m event query mut sub => f m event query mut sub -> App event m
+ Data.Morpheus: deriveApp :: DeriveApp f m event qu mu su => f m event qu mu su -> App event m
- Data.Morpheus.NamedResolvers: class (ToJSON (Dep a)) => ResolveNamed (m :: * -> *) a where {
+ Data.Morpheus.NamedResolvers: class (ToJSON (Dep a)) => ResolveNamed (m :: Type -> Type) a where {
- Data.Morpheus.NamedResolvers: data NamedResolverT (m :: * -> *) a
+ Data.Morpheus.NamedResolvers: data NamedResolverT (m :: Type -> Type) a
- Data.Morpheus.NamedResolvers: type family Dep a :: *;
+ Data.Morpheus.NamedResolvers: type family Dep a :: Type;
- Data.Morpheus.Types: NamedResolvers :: NamedResolvers (m :: * -> *) event (qu :: (* -> *) -> *) (mu :: (* -> *) -> *) (su :: (* -> *) -> *)
+ Data.Morpheus.Types: NamedResolvers :: NamedResolvers (m :: Type -> Type) event (qu :: (Type -> Type) -> Type) (mu :: (Type -> Type) -> Type) (su :: (Type -> Type) -> Type)
- Data.Morpheus.Types: RootResolver :: query (Resolver QUERY event m) -> mutation (Resolver MUTATION event m) -> subscription (Resolver SUBSCRIPTION event m) -> RootResolver (m :: * -> *) event (query :: (* -> *) -> *) (mutation :: (* -> *) -> *) (subscription :: (* -> *) -> *)
+ Data.Morpheus.Types: RootResolver :: query (Resolver QUERY event m) -> mutation (Resolver MUTATION event m) -> subscription (Resolver SUBSCRIPTION event m) -> RootResolver (m :: Type -> Type) event (query :: (Type -> Type) -> Type) (mutation :: (Type -> Type) -> Type) (subscription :: (Type -> Type) -> Type)
- Data.Morpheus.Types: Undefined :: Undefined (m :: * -> *)
+ Data.Morpheus.Types: Undefined :: Undefined (m :: Type -> Type)
- Data.Morpheus.Types: [mutationResolver] :: RootResolver (m :: * -> *) event (query :: (* -> *) -> *) (mutation :: (* -> *) -> *) (subscription :: (* -> *) -> *) -> mutation (Resolver MUTATION event m)
+ Data.Morpheus.Types: [mutationResolver] :: RootResolver (m :: Type -> Type) event (query :: (Type -> Type) -> Type) (mutation :: (Type -> Type) -> Type) (subscription :: (Type -> Type) -> Type) -> mutation (Resolver MUTATION event m)
- Data.Morpheus.Types: [queryResolver] :: RootResolver (m :: * -> *) event (query :: (* -> *) -> *) (mutation :: (* -> *) -> *) (subscription :: (* -> *) -> *) -> query (Resolver QUERY event m)
+ Data.Morpheus.Types: [queryResolver] :: RootResolver (m :: Type -> Type) event (query :: (Type -> Type) -> Type) (mutation :: (Type -> Type) -> Type) (subscription :: (Type -> Type) -> Type) -> query (Resolver QUERY event m)
- Data.Morpheus.Types: [subscriptionResolver] :: RootResolver (m :: * -> *) event (query :: (* -> *) -> *) (mutation :: (* -> *) -> *) (subscription :: (* -> *) -> *) -> subscription (Resolver SUBSCRIPTION event m)
+ Data.Morpheus.Types: [subscriptionResolver] :: RootResolver (m :: Type -> Type) event (query :: (Type -> Type) -> Type) (mutation :: (Type -> Type) -> Type) (subscription :: (Type -> Type) -> Type) -> subscription (Resolver SUBSCRIPTION event m)
- Data.Morpheus.Types: data NamedResolvers (m :: * -> *) event (qu :: (* -> *) -> *) (mu :: (* -> *) -> *) (su :: (* -> *) -> *)
+ Data.Morpheus.Types: data NamedResolvers (m :: Type -> Type) event (qu :: (Type -> Type) -> Type) (mu :: (Type -> Type) -> Type) (su :: (Type -> Type) -> Type)
- Data.Morpheus.Types: data RootResolver (m :: * -> *) event (query :: (* -> *) -> *) (mutation :: (* -> *) -> *) (subscription :: (* -> *) -> *)
+ Data.Morpheus.Types: data RootResolver (m :: Type -> Type) event (query :: (Type -> Type) -> Type) (mutation :: (Type -> Type) -> Type) (subscription :: (Type -> Type) -> Type)
- Data.Morpheus.Types: data Undefined (m :: * -> *)
+ Data.Morpheus.Types: data Undefined (m :: Type -> Type)
Files
- Setup.hs +0/−3
- changelog.md +14/−2
- morpheus-graphql.cabal +39/−12
- src/Data/Morpheus/NamedResolvers.hs +5/−5
- src/Data/Morpheus/Server/Deriving/App.hs +11/−2
- src/Data/Morpheus/Server/Deriving/Channels.hs +5/−4
- src/Data/Morpheus/Server/Deriving/Decode.hs +29/−20
- src/Data/Morpheus/Server/Deriving/Encode.hs +10/−18
- src/Data/Morpheus/Server/Deriving/Named/EncodeType.hs +2/−2
- src/Data/Morpheus/Server/Deriving/Named/EncodeValue.hs +2/−2
- src/Data/Morpheus/Server/Deriving/Schema.hs +5/−10
- src/Data/Morpheus/Server/Deriving/Schema/Internal.hs +1/−1
- src/Data/Morpheus/Server/Deriving/Schema/Object.hs +1/−1
- src/Data/Morpheus/Server/Deriving/Utils.hs +27/−29
- src/Data/Morpheus/Server/Deriving/Utils/Decode.hs +2/−2
- src/Data/Morpheus/Server/Deriving/Utils/GTraversable.hs +5/−5
- src/Data/Morpheus/Server/TH/Declare/GQLType.hs +1/−1
- src/Data/Morpheus/Server/TH/Declare/Type.hs +3/−3
- src/Data/Morpheus/Server/TH/Utils.hs +3/−3
- src/Data/Morpheus/Server/Types/GQLType.hs +22/−4
- src/Data/Morpheus/Server/Types/Types.hs +3/−6
- src/Data/Morpheus/Types.hs +13/−13
- test/Feature/Inference/TypeInference.hs +3/−3
- test/Feature/Inference/type-inference/introspection/union/positional-products/query.gql +1/−1
- test/Feature/Inference/type-inference/introspection/union/positional-products/response.json +2/−2
- test/Feature/Inference/type-inference/introspection/union/union/response.json +1/−1
- test/Feature/Inference/type-inference/resolving/complexUnion/query.gql +1/−1
- test/Feature/Inference/type-inference/resolving/complexUnion/response.json +1/−1
- test/Feature/Input/Collections.hs +83/−0
- test/Feature/Input/collections/assoc/invalid/query.gql +8/−0
- test/Feature/Input/collections/assoc/invalid/response.json +28/−0
- test/Feature/Input/collections/assoc/ok/query.gql +19/−0
- test/Feature/Input/collections/assoc/ok/response.json +10/−0
- test/Feature/Input/collections/map/invalid/query.gql +8/−0
- test/Feature/Input/collections/map/invalid/response.json +28/−0
- test/Feature/Input/collections/map/ok/query.gql +19/−0
- test/Feature/Input/collections/map/ok/response.json +10/−0
- test/Feature/Input/collections/nonempty/invalid/query.gql +3/−0
- test/Feature/Input/collections/nonempty/invalid/response.json +8/−0
- test/Feature/Input/collections/nonempty/ok/query.gql +4/−0
- test/Feature/Input/collections/nonempty/ok/response.json +6/−0
- test/Feature/Input/collections/product/invalid/query.gql +9/−0
- test/Feature/Input/collections/product/invalid/response.json +60/−0
- test/Feature/Input/collections/product/ok/query.gql +15/−0
- test/Feature/Input/collections/product/ok/response.json +16/−0
- test/Feature/Input/collections/seq/query.gql +5/−0
- test/Feature/Input/collections/seq/response.json +7/−0
- test/Feature/Input/collections/set/invalid/query.gql +5/−0
- test/Feature/Input/collections/set/invalid/response.json +16/−0
- test/Feature/Input/collections/set/ok/query.gql +5/−0
- test/Feature/Input/collections/set/ok/response.json +7/−0
- test/Feature/Input/collections/tuple/invalid/query.gql +9/−0
- test/Feature/Input/collections/tuple/invalid/response.json +40/−0
- test/Feature/Input/collections/tuple/ok/query.gql +10/−0
- test/Feature/Input/collections/tuple/ok/response.json +12/−0
- test/Feature/Input/collections/vector/query.gql +5/−0
- test/Feature/Input/collections/vector/response.json +7/−0
- test/Spec.hs +3/−1
- test/Subscription/Case/Publishing.hs +3/−3
− Setup.hs
@@ -1,3 +0,0 @@-import Distribution.Simple--main = defaultMain
changelog.md view
@@ -1,11 +1,23 @@ # Changelog +## 0.19.0 - 21.03.2022++### Breaking Changes++- Pair fields changed from `key`, `value` to `_0`, `_1`++### Minor Changes++- support: `NonEmpty`, `Vector`, `Seq`+- fixes decoding of types without record syntax (including tuples) (#667, #659, #665)+- support Aeson 2.0+ ## 0.18.0 - 08.11.2021 ### new Features -- `NamedResoplvers` (experimental featuure): typed Haskell approach of providing appollo- like named resolvers, apps with NamedResolvers theoretically can be safelly merged.+- `NamedResolvers` (experimental feature): typed Haskell approach of providing apollo+ like named resolvers, apps with NamedResolvers theoretically can be safely merged. - `TypeGuards`: as an alternative for interfaces
morpheus-graphql.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: 8115cd76f9c3ca8b90fafdd1b4dc9eb4409be0bef2501609bfe4675acba5d466 name: morpheus-graphql-version: 0.18.0+version: 0.19.0 synopsis: Morpheus GraphQL description: Build GraphQL APIs with your favourite functional language! category: web, graphql@@ -147,6 +145,20 @@ test/Feature/Inference/wrapped-type/ignoreQueryResolver/query.gql test/Feature/Inference/wrapped-type/ignoreSubscriptionResolver/query.gql test/Feature/Inference/wrapped-type/validWrappedTypes/query.gql+ test/Feature/Input/collections/assoc/invalid/query.gql+ test/Feature/Input/collections/assoc/ok/query.gql+ test/Feature/Input/collections/map/invalid/query.gql+ test/Feature/Input/collections/map/ok/query.gql+ test/Feature/Input/collections/nonempty/invalid/query.gql+ test/Feature/Input/collections/nonempty/ok/query.gql+ test/Feature/Input/collections/product/invalid/query.gql+ test/Feature/Input/collections/product/ok/query.gql+ test/Feature/Input/collections/seq/query.gql+ test/Feature/Input/collections/set/invalid/query.gql+ test/Feature/Input/collections/set/ok/query.gql+ test/Feature/Input/collections/tuple/invalid/query.gql+ test/Feature/Input/collections/tuple/ok/query.gql+ test/Feature/Input/collections/vector/query.gql test/Feature/Input/default-values-schema.gql test/Feature/Input/default-values/intorspection/arguments/query.gql test/Feature/Input/default-values/intorspection/input-compound/query.gql@@ -343,6 +355,20 @@ test/Feature/Inference/wrapped-type/ignoreQueryResolver/response.json test/Feature/Inference/wrapped-type/ignoreSubscriptionResolver/response.json test/Feature/Inference/wrapped-type/validWrappedTypes/response.json+ test/Feature/Input/collections/assoc/invalid/response.json+ test/Feature/Input/collections/assoc/ok/response.json+ test/Feature/Input/collections/map/invalid/response.json+ test/Feature/Input/collections/map/ok/response.json+ test/Feature/Input/collections/nonempty/invalid/response.json+ test/Feature/Input/collections/nonempty/ok/response.json+ test/Feature/Input/collections/product/invalid/response.json+ test/Feature/Input/collections/product/ok/response.json+ test/Feature/Input/collections/seq/response.json+ test/Feature/Input/collections/set/invalid/response.json+ test/Feature/Input/collections/set/ok/response.json+ test/Feature/Input/collections/tuple/invalid/response.json+ test/Feature/Input/collections/tuple/ok/response.json+ test/Feature/Input/collections/vector/response.json test/Feature/Input/default-values/intorspection/arguments/response.json test/Feature/Input/default-values/intorspection/input-compound/response.json test/Feature/Input/default-values/intorspection/input-simple/response.json@@ -472,13 +498,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- , morpheus-graphql-app >=0.18.0 && <0.19.0- , morpheus-graphql-code-gen >=0.18.0 && <0.19.0- , morpheus-graphql-core >=0.18.0 && <0.19.0+ , morpheus-graphql-app >=0.19.0 && <0.20.0+ , morpheus-graphql-code-gen >=0.19.0 && <0.20.0+ , morpheus-graphql-core >=0.19.0 && <0.20.0 , mtl >=2.0 && <=3.0 , relude >=0.3.0 , template-haskell >=2.0 && <=3.0@@ -503,6 +529,7 @@ Feature.Inference.TypeInference Feature.Inference.UnionType Feature.Inference.WrappedType+ Feature.Input.Collections Feature.Input.DefaultValues Feature.Input.Enums Feature.Input.Objects@@ -529,11 +556,11 @@ , bytestring >=0.10.4 && <0.11 , containers >=0.4.2.1 && <0.7 , morpheus-graphql- , morpheus-graphql-app >=0.18.0 && <0.19.0- , morpheus-graphql-code-gen >=0.18.0 && <0.19.0- , morpheus-graphql-core >=0.18.0 && <0.19.0- , morpheus-graphql-subscriptions >=0.18.0 && <0.19.0- , morpheus-graphql-tests >=0.18.0 && <0.19.0+ , morpheus-graphql-app >=0.19.0 && <0.20.0+ , morpheus-graphql-code-gen >=0.19.0 && <0.20.0+ , morpheus-graphql-core >=0.19.0 && <0.20.0+ , morpheus-graphql-subscriptions >=0.19.0 && <0.20.0+ , morpheus-graphql-tests >=0.19.0 && <0.20.0 , mtl >=2.0 && <=3.0 , relude >=0.3.0 , tasty
src/Data/Morpheus/NamedResolvers.hs view
@@ -26,20 +26,20 @@ type Dep Text = Text resolveNamed = pure -class (ToJSON (Dep a)) => ResolveNamed (m :: * -> *) a where- type Dep a :: *+class (ToJSON (Dep a)) => ResolveNamed (m :: Type -> Type) a where+ type Dep a :: Type resolveNamed :: Monad m => Dep a -> m a -instance (ResolveNamed m a) => ResolveNamed (m :: * -> *) (Maybe a) where+instance (ResolveNamed m a) => ResolveNamed (m :: Type -> Type) (Maybe a) where type Dep (Maybe a) = Maybe (Dep a) resolveNamed (Just x) = Just <$> resolveNamed x resolveNamed Nothing = pure Nothing -instance (ResolveNamed m a) => ResolveNamed (m :: * -> *) [a] where+instance (ResolveNamed m a) => ResolveNamed (m :: Type -> Type) [a] where type Dep [a] = [Dep a] resolveNamed = traverse resolveNamed -data NamedResolverT (m :: * -> *) a where+data NamedResolverT (m :: Type -> Type) a where Ref :: ResolveNamed m a => m (Dep a) -> NamedResolverT m a Refs :: ResolveNamed m a => m [Dep a] -> NamedResolverT m [a] Value :: m a -> NamedResolverT m a
src/Data/Morpheus/Server/Deriving/App.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE KindSignatures #-}@@ -51,8 +52,16 @@ Monad m ) -class DeriveApp f m (event :: *) (query :: (* -> *) -> *) (mut :: (* -> *) -> *) (sub :: (* -> *) -> *) where- deriveApp :: f m event query mut sub -> App event m+class+ DeriveApp+ f+ m+ (event :: Type)+ (qu :: (Type -> Type) -> Type)+ (mu :: (Type -> Type) -> Type)+ (su :: (Type -> Type) -> Type)+ where+ deriveApp :: f m event qu mu su -> App event m instance RootResolverConstraint m e query mut sub => DeriveApp RootResolver m e query mut sub where deriveApp root =
src/Data/Morpheus/Server/Deriving/Channels.hs view
@@ -56,9 +56,9 @@ { _unpackChannel :: Channel e } -type ChannelRes (e :: *) = Selection VALID -> ResolverState (DerivedChannel e)+type ChannelRes (e :: Type) = Selection VALID -> ResolverState (DerivedChannel e) -type ChannelsConstraint e m (subs :: (* -> *) -> *) =+type ChannelsConstraint e m (subs :: (Type -> Type) -> Type) = ExploreConstraint e (subs (Resolver SUBSCRIPTION e m)) channelResolver ::@@ -109,8 +109,9 @@ GetChannel e (arg -> SubscriptionField (Resolver SUBSCRIPTION e m a)) where getChannel f sel@Selection {selectionArguments} =- decodeArguments selectionArguments >>= (`getChannel` sel)- . f+ decodeArguments selectionArguments+ >>= (`getChannel` sel)+ . f ------------------------------------------------------
src/Data/Morpheus/Server/Deriving/Decode.hs view
@@ -21,6 +21,7 @@ where import Control.Monad.Except (MonadError (throwError))+import qualified Data.Map as M import Data.Morpheus.App.Internal.Resolving ( ResolverState, )@@ -33,7 +34,6 @@ ) import Data.Morpheus.Server.Deriving.Utils ( conNameProxy,- datatypeNameProxy, selNameProxy, symbolName, )@@ -68,6 +68,7 @@ import Data.Morpheus.Types.Internal.AST ( Argument (..), Arguments,+ FieldName, GQLError, IN, LEAF,@@ -122,7 +123,7 @@ Context { options = typeOptions (Proxy @a) defaultTypeOptions, contKind = D_CONS,- typeName = ""+ typeName = gqlTypeName $ __typeData (KindedProxy :: KindedProxy IN a) } instance (Decode a, DecodeWrapperConstraint f a, DecodeWrapper f) => DecodeKind WRAPPER (f a) where@@ -136,6 +137,10 @@ fieldDecoder = decodeFieldWith decode fieldName fieldName = symbolName (Proxy @name) +-- Map+instance (Ord k, Decode (k, v)) => DecodeKind CUSTOM (Map k v) where+ decodeKind _ v = M.fromList <$> (decode v :: ResolverState [(k, v)])+ -- data Input = -- InputHuman Human -- direct link: { __typename: Human, Human: {field: ""} } -- | InputRecord { name :: Text, age :: Int } -- { __typename: InputRecord, InputRecord: {field: ""} }@@ -198,9 +203,6 @@ type DecoderT = ReaderT Context ResolverState -withTypeName :: TypeName -> DecoderT a -> DecoderT a-withTypeName typeName = local (\ctx -> ctx {typeName})- withKind :: Tag -> DecoderT a -> DecoderT a withKind contKind = local (\ctx -> ctx {contKind}) @@ -220,16 +222,13 @@ -- -- GENERICS ---class DecodeRep (f :: * -> *) where+class DecodeRep (f :: Type -> Type) where tags :: Proxy f -> Context -> Info decodeRep :: ValidValue -> DecoderT (f a) instance (Datatype d, DecodeRep f) => DecodeRep (M1 D d f) where tags _ = tags (Proxy @f)- decodeRep value = do- gqlOptions <- asks options- let typeName = datatypeNameProxy gqlOptions (Proxy @d)- withTypeName typeName (M1 <$> decodeRep value)+ decodeRep value = M1 <$> decodeRep value instance (DecodeRep a, DecodeRep b) => DecodeRep (a :+: b) where tags _ = tags (Proxy @a) <> tags (Proxy @b)@@ -250,7 +249,7 @@ decodeRep _ = throwError (internal "lists and scalars are not allowed in Union") instance (Constructor c, DecodeFields a) => DecodeRep (M1 C c a) where- decodeRep = fmap M1 . decodeFields+ decodeRep = fmap M1 . decodeFields 0 tags _ Context {typeName, options} = getTag (refType (Proxy @a)) where getTag (Just memberRef)@@ -262,25 +261,35 @@ ---------- isUnionRef x = typeName <> x == consName -class DecodeFields (f :: * -> *) where+class DecodeFields (f :: Type -> Type) where refType :: Proxy f -> Maybe TypeName- decodeFields :: ValidValue -> DecoderT (f a)+ countFields :: Proxy f -> Int+ decodeFields :: Int -> ValidValue -> DecoderT (f a) instance (DecodeFields f, DecodeFields g) => DecodeFields (f :*: g) where refType _ = Nothing- decodeFields gql = (:*:) <$> decodeFields gql <*> decodeFields gql+ countFields _ = countFields (Proxy @f) + countFields (Proxy @g)+ decodeFields index gql =+ (:*:) <$> decodeFields index gql+ <*> decodeFields (index + countFields (Proxy @g)) gql instance (Selector s, GQLType a, Decode a) => DecodeFields (M1 S s (K1 i a)) where+ countFields _ = 1 refType _ = Just $ gqlTypeName $ __typeData (KindedProxy :: KindedProxy IN a)- decodeFields value = M1 . K1 <$> do+ decodeFields index value = M1 . K1 <$> do Context {options, contKind} <- ask- if contKind == D_UNION- then lift (decode value)- else- let fieldName = selNameProxy options (Proxy @s)+ case contKind of+ D_UNION -> lift (decode value)+ D_CONS ->+ let fieldName = getFieldName (selNameProxy options (Proxy @s)) index fieldDecoder = decodeFieldWith (lift . decode) fieldName in withInputObject fieldDecoder value +getFieldName :: FieldName -> Int -> FieldName+getFieldName "" index = "_" <> show index+getFieldName label _ = label+ instance DecodeFields U1 where+ countFields _ = 0 refType _ = Nothing- decodeFields _ = pure U1+ decodeFields _ _ = pure U1
src/Data/Morpheus/Server/Deriving/Encode.hs view
@@ -69,8 +69,7 @@ __isEmptyType, ) import Data.Morpheus.Server.Types.Types- ( Pair (..),- TypeGuard (..),+ ( TypeGuard (..), ) import Data.Morpheus.Types ( RootResolver (..),@@ -97,14 +96,14 @@ { unContextValue :: a } -class Encode (m :: * -> *) resolver where+class Encode (m :: Type -> Type) resolver where encode :: resolver -> m (ResolverValue m) instance (EncodeKind (KIND a) m a) => Encode m a where encode resolver = encodeKind (ContextValue resolver :: ContextValue (KIND a) a) -- ENCODE GQL KIND-class EncodeKind (kind :: DerivingKind) (m :: * -> *) (a :: *) where+class EncodeKind (kind :: DerivingKind) (m :: Type -> Type) (a :: Type) where encodeKind :: ContextValue kind a -> m (ResolverValue m) instance@@ -132,16 +131,9 @@ where encodeKind = pure . exploreResolvers . unContextValue --- Tuple (a,b)-instance- Encode m (Pair k v) =>- EncodeKind CUSTOM m (k, v)- where- encodeKind = encode . uncurry Pair . unContextValue- -- Map-instance (Monad m, Encode m [Pair k v]) => EncodeKind CUSTOM m (Map k v) where- encodeKind = encode . fmap (uncurry Pair) . M.toList . unContextValue+instance (Monad m, Encode m [(k, v)]) => EncodeKind CUSTOM m (Map k v) where+ encodeKind = encode . M.toList . unContextValue -- INTERFACE Types instance (MonadError GQLError m, EncodeConstraint m guard, EncodeConstraint m union) => EncodeKind CUSTOM m (TypeGuard guard union) where@@ -177,12 +169,12 @@ ResolverValue m convertNode DataType- { tyName,+ { dataTypeName, tyIsUnion, tyCons = cons@ConsRep {consFields, consName} } | tyIsUnion = encodeUnion consFields- | otherwise = mkObject tyName (toFieldRes <$> consFields)+ | otherwise = mkObject dataTypeName (toFieldRes <$> consFields) where -- ENUM encodeUnion ::@@ -191,7 +183,7 @@ encodeUnion [] = mkEnum consName -- Type References -------------------------------------------------------------- encodeUnion [FieldRep {fieldTypeRef = TypeRef {typeConName}, fieldValue}]- | isUnionRef tyName cons = ResLazy (ResObject (Just typeConName) <$> (fieldValue >>= requireObject))+ | isUnionRef dataTypeName cons = ResLazy (ResObject (Just typeConName) <$> (fieldValue >>= requireObject)) -- Inline Union Types ---------------------------------------------------------------------------- encodeUnion fields = mkUnion consName (toFieldRes <$> fields) @@ -220,13 +212,13 @@ ResolverState (ObjectTypeResolver m) objectResolvers value = requireObject (exploreResolvers value) -type EncodeConstraint (m :: * -> *) a =+type EncodeConstraint (m :: Type -> Type) a = ( GQLType a, Generic a, TypeRep (Encode m) (m (ResolverValue m)) (Rep a) ) -type EncodeObjectConstraint (o :: OperationType) e (m :: * -> *) a =+type EncodeObjectConstraint (o :: OperationType) e (m :: Type -> Type) a = EncodeConstraint (Resolver o e m) (a (Resolver o e m)) type EncodeConstraints e m query mut sub =
src/Data/Morpheus/Server/Deriving/Named/EncodeType.hs view
@@ -75,7 +75,7 @@ GQLType (a (NamedResolverT m)) ) -class DeriveNamedResolver (m :: * -> *) (k :: DerivingKind) a where+class DeriveNamedResolver (m :: Type -> Type) (k :: DerivingKind) a where deriveNamedResolver :: f k a -> [NamedResolver m] instance DeriveNamedResolver m SCALAR a where@@ -91,7 +91,7 @@ ResolveNamed (Resolver o e m) a, TypeRep (Encode (Resolver o e m)) (Resolver o e m (ResolverValue (Resolver o e m))) (Rep a) ) =>- DeriveNamedResolver (Resolver o e m) TYPE (a :: *)+ DeriveNamedResolver (Resolver o e m) TYPE (a :: Type) where deriveNamedResolver _ = [ NamedResolver
src/Data/Morpheus/Server/Deriving/Named/EncodeValue.hs view
@@ -94,13 +94,13 @@ TypeRep (Encode m) (m (ResolverValue m)) (Rep a) ) -class Encode (m :: * -> *) res where+class Encode (m :: Type -> Type) res where encodeField :: res -> m (ResolverValue m) instance (EncodeFieldKind (KIND a) m a) => Encode m a where encodeField resolver = encodeFieldKind (ContextValue resolver :: ContextValue (KIND a) a) -class EncodeFieldKind (k :: DerivingKind) (m :: * -> *) (a :: *) where+class EncodeFieldKind (k :: DerivingKind) (m :: Type -> Type) (a :: Type) where encodeFieldKind :: ContextValue k a -> m (ResolverValue m) instance (EncodeScalar a, Monad m) => EncodeFieldKind SCALAR m a where
src/Data/Morpheus/Server/Deriving/Schema.hs view
@@ -79,7 +79,6 @@ ) import Data.Morpheus.Server.Types.Types ( Arg (..),- Pair, TypeGuard, ) import Data.Morpheus.Types.GQLScalar@@ -115,7 +114,7 @@ import Language.Haskell.TH (Exp, Q) import Relude -type SchemaConstraints event (m :: * -> *) query mutation subscription =+type SchemaConstraints event (m :: Type -> Type) query mutation subscription = ( DeriveTypeConstraintOpt OUT (query (Resolver QUERY event m)), DeriveTypeConstraintOpt OUT (mutation (Resolver MUTATION event m)), DeriveTypeConstraintOpt OUT (subscription (Resolver SUBSCRIPTION event m))@@ -166,7 +165,7 @@ <*> deriveObjectType (Proxy @(subs (Resolver SUBSCRIPTION e m))) -- | Generates internal GraphQL Schema for query validation and introspection rendering-class DeriveType (kind :: TypeCategory) (a :: *) where+class DeriveType (kind :: TypeCategory) (a :: Type) where deriveType :: f a -> SchemaT kind () deriveContent :: f a -> TyContentM kind @@ -201,13 +200,9 @@ instance DeriveType cat a => DeriveKindedType cat CUSTOM (Resolver o e m a) where deriveKindedType _ = deriveType (Proxy @a) --- Tuple-instance DeriveType cat (Pair k v) => DeriveKindedType cat CUSTOM (k, v) where- deriveKindedType _ = deriveType (Proxy @(Pair k v))- -- Map-instance DeriveType cat [Pair k v] => DeriveKindedType cat CUSTOM (Map k v) where- deriveKindedType _ = deriveType (Proxy @[Pair k v])+instance DeriveType cat [(k, v)] => DeriveKindedType cat CUSTOM (Map k v) where+ deriveKindedType _ = deriveType (Proxy @[(k, v)]) instance ( DeriveTypeConstraint OUT interface,@@ -262,7 +257,7 @@ instance (KnownSymbol name, DeriveType IN a, GQLType a) => DeriveArguments CUSTOM (Arg name a) where deriveArgumentsDefinition _ = do withInput (deriveType proxy)- pure $ fieldsToArguments $ singleton $ mkField Nothing argName argTypeRef+ pure $ fieldsToArguments $ singleton argName $ mkField Nothing argName argTypeRef where proxy :: KindedProxy IN a proxy = KindedProxy
src/Data/Morpheus/Server/Deriving/Schema/Internal.hs view
@@ -11,7 +11,7 @@ {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE StandaloneDeriving #-}-{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TemplateHaskellQuotes #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-}
src/Data/Morpheus/Server/Deriving/Schema/Object.hs view
@@ -72,7 +72,7 @@ defineObjectType proxy ConsRep {consName, consFields} = insertType . mkType consName . mkObjectTypeContent proxy =<< fields where fields- | null consFields = defineEnumUnit $> singleton mkFieldUnit+ | null consFields = defineEnumUnit $> singleton unitFieldName mkFieldUnit | otherwise = pure $ unsafeFromFields $ map repToFieldDefinition consFields mkFieldUnit :: FieldDefinition cat s
src/Data/Morpheus/Server/Deriving/Utils.hs view
@@ -15,8 +15,7 @@ {-# LANGUAGE NoImplicitPrelude #-} module Data.Morpheus.Server.Deriving.Utils- ( datatypeNameProxy,- conNameProxy,+ ( conNameProxy, isRecordProxy, selNameProxy, TypeRep (..),@@ -47,8 +46,8 @@ ( GQLType (..), GQLTypeOptions (..), TypeData (..),- __typeData, defaultTypeOptions,+ __typeData, ) import Data.Morpheus.Types.Internal.AST ( FieldName,@@ -62,9 +61,7 @@ ) import qualified Data.Text as T import GHC.Generics- ( (:*:) (..),- (:+:) (..),- C,+ ( C, Constructor, D, Datatype,@@ -78,25 +75,23 @@ U1 (..), conIsRecord, conName,- datatypeName, selName,+ (:*:) (..),+ (:+:) (..), ) import GHC.TypeLits import Relude hiding (undefined) import Prelude (undefined) -datatypeNameProxy :: forall f (d :: Meta). Datatype d => GQLTypeOptions -> f d -> TypeName-datatypeNameProxy options _ = packName $ pack $ typeNameModifier options False $ datatypeName (undefined :: (M1 D d f a))- conNameProxy :: forall f (c :: Meta). Constructor c => GQLTypeOptions -> f c -> TypeName conNameProxy options _ = packName $ pack $ constructorTagModifier options $ conName (undefined :: M1 C c U1 a) selNameProxy :: forall f (s :: Meta). Selector s => GQLTypeOptions -> f s -> FieldName selNameProxy options _ =- fromHaskellName- $ fieldLabelModifier options- $ selName (undefined :: M1 S s f a)+ fromHaskellName $+ fieldLabelModifier options $+ selName (undefined :: M1 S s f a) fromHaskellName :: String -> FieldName fromHaskellName hsName@@ -109,12 +104,12 @@ isRecordProxy :: forall f (c :: Meta). Constructor c => f c -> Bool isRecordProxy _ = conIsRecord (undefined :: (M1 C c f a)) -newtype TypeConstraint (c :: * -> Constraint) (v :: *) (f :: * -> *) = TypeConstraint+newtype TypeConstraint (c :: Type -> Constraint) (v :: Type) (f :: Type -> Type) = TypeConstraint { typeConstraint :: forall a. c a => f a -> v } toRep ::- forall kinded constraint value (a :: *) (kind :: TypeCategory).+ forall kinded constraint value (a :: Type) (kind :: TypeCategory). (GQLType a, CategoryValue kind, TypeRep constraint value (Rep a)) => TypeConstraint constraint value Proxy -> kinded kind a ->@@ -122,22 +117,25 @@ toRep f proxy = typeRep (typeOptions proxy defaultTypeOptions, Proxy @kind, f) (Proxy @(Rep a)) toValue ::- forall proxy (kind :: TypeCategory) constraint value (a :: *).+ forall proxy (kind :: TypeCategory) constraint value (a :: Type). (GQLType a, CategoryValue kind, Generic a, TypeRep constraint value (Rep a)) => TypeConstraint constraint value Identity -> proxy kind -> a -> DataType value-toValue f proxy = toTypeRep (typeOptions (Proxy @a) defaultTypeOptions, proxy, f) . from+toValue f proxy = toTypeRep (typeName, options, proxy, f) . from+ where+ typeName = gqlTypeName $ __typeData (KindedProxy :: KindedProxy kind a)+ options = typeOptions (Proxy @a) defaultTypeOptions -- GENERIC UNION-class TypeRep (c :: * -> Constraint) (v :: *) f where+class TypeRep (c :: Type -> Constraint) (v :: Type) f where typeRep :: CategoryValue kind => (GQLTypeOptions, kinProxy (kind :: TypeCategory), TypeConstraint c v Proxy) -> proxy f -> [ConsRep v]- toTypeRep :: CategoryValue kind => (GQLTypeOptions, kinProxy (kind :: TypeCategory), TypeConstraint c v Identity) -> f a -> DataType v+ toTypeRep :: CategoryValue kind => (TypeName, GQLTypeOptions, kinProxy (kind :: TypeCategory), TypeConstraint c v Identity) -> f a -> DataType v instance (Datatype d, TypeRep c v f) => TypeRep c v (M1 D d f) where typeRep fun _ = typeRep fun (Proxy @f)- toTypeRep fun@(opt, _, _) (M1 src) = (toTypeRep fun src) {tyName = datatypeNameProxy opt (Proxy @d)}+ toTypeRep fun@(dataTypeName, _, _, _) (M1 src) = (toTypeRep fun src) {dataTypeName} -- | recursion for Object types, both of them : 'INPUT_OBJECT' and 'OBJECT' instance (TypeRep c v a, TypeRep c v b) => TypeRep c v (a :+: b) where@@ -147,11 +145,11 @@ instance (ConRep con v f, Constructor c) => TypeRep con v (M1 C c f) where typeRep f@(opt, _, _) _ = [deriveConsRep opt (Proxy @c) (conRep f (Proxy @f))]- toTypeRep f@(opt, _, _) (M1 src) =+ toTypeRep (_, opt, x, y) (M1 src) = DataType- { tyName = "",+ { dataTypeName = "", tyIsUnion = False,- tyCons = deriveConsRep opt (Proxy @c) (toFieldRep f src)+ tyCons = deriveConsRep opt (Proxy @c) (toFieldRep (opt, x, y) src) } deriveConsRep ::@@ -170,7 +168,7 @@ | isRecordProxy proxy = fields | otherwise = enumerate fields -class ConRep (c :: * -> Constraint) (v :: *) f where+class ConRep (c :: Type -> Constraint) (v :: Type) f where conRep :: CategoryValue kind => (GQLTypeOptions, kinProxy (kind :: TypeCategory), TypeConstraint c v Proxy) -> proxy f -> [FieldRep v] toFieldRep :: CategoryValue kind => (GQLTypeOptions, kinProxy (kind :: TypeCategory), TypeConstraint c v Identity) -> f a -> [FieldRep v] @@ -187,7 +185,7 @@ forall proxy (selector :: Meta)- (kindedProxy :: TypeCategory -> * -> *)+ (kindedProxy :: TypeCategory -> Type -> Type) a v (kind :: TypeCategory).@@ -220,18 +218,18 @@ conRep _ _ = [] toFieldRep _ _ = [] -data DataType (v :: *) = DataType- { tyName :: TypeName,+data DataType (v :: Type) = DataType+ { dataTypeName :: TypeName, tyIsUnion :: Bool, tyCons :: ConsRep v } -data ConsRep (v :: *) = ConsRep+data ConsRep (v :: Type) = ConsRep { consName :: TypeName, consFields :: [FieldRep v] } -data FieldRep (a :: *) = FieldRep+data FieldRep (a :: Type) = FieldRep { fieldSelector :: FieldName, fieldTypeRef :: TypeRef, fieldValue :: a
src/Data/Morpheus/Server/Deriving/Utils/Decode.hs view
@@ -57,9 +57,9 @@ ValidObject -> m a withInputUnion decoder unions =- either onFail onSucc (getInputUnionValue unions)+ either onFail onSuccess (getInputUnionValue unions) where- onSucc (name, value) = withInputObject (decoder name unions) value+ onSuccess (name, value) = withInputObject (decoder name unions) value onFail = throwError . internal . msg withScalar ::
src/Data/Morpheus/Server/Deriving/Utils/GTraversable.hs view
@@ -37,9 +37,9 @@ class (GFmap (ScanConstraint c) (KIND a) a, c (KIND a) a) => ScanConstraint- (c :: DerivingKind -> * -> Constraint)+ (c :: DerivingKind -> Type -> Constraint) (k :: DerivingKind)- (a :: *)+ (a :: Type) instance (GFmap (ScanConstraint c) (KIND a) a, c (KIND a) a) => ScanConstraint c k a @@ -62,12 +62,12 @@ withDerivable :: proxy a -> KindedProxy (KIND a) a withDerivable _ = KindedProxy -newtype Mappable (c :: DerivingKind -> * -> Constraint) (v :: *) (f :: DerivingKind -> * -> *) = Mappable+newtype Mappable (c :: DerivingKind -> Type -> Constraint) (v :: Type) (f :: DerivingKind -> Type -> Type) = Mappable { runMappable :: forall a. (GQLType a, c (KIND a) a) => KindedProxy (KIND a) a -> v } -- Map-class GFmap (c :: DerivingKind -> * -> Constraint) (t :: DerivingKind) a where+class GFmap (c :: DerivingKind -> Type -> Constraint) (t :: DerivingKind) a where gfmap :: (Monoid v, Semigroup v) => Mappable c v KindedProxy -> kinded t a -> v instance (GQLType a, c (KIND a) a) => GFmap c SCALAR a where@@ -90,7 +90,7 @@ -- GFunctor -- ---class GFunctor (c :: DerivingKind -> * -> Constraint) a where+class GFunctor (c :: DerivingKind -> Type -> Constraint) a where genericMap :: (Monoid v, Semigroup v) => Mappable c v p -> proxy a -> v instance (Datatype d, GFunctor c a) => GFunctor c (M1 D d a) where
src/Data/Morpheus/Server/TH/Declare/GQLType.hs view
@@ -6,7 +6,7 @@ {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TemplateHaskellQuotes #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE NoImplicitPrelude #-}
src/Data/Morpheus/Server/TH/Declare/Type.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE GADTs #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TemplateHaskellQuotes #-} {-# LANGUAGE NoImplicitPrelude #-} module Data.Morpheus.Server.TH.Declare.Type@@ -60,9 +60,9 @@ tCons, derives, typeParameters- } = [DataD [] (toName tName) vars Nothing cons [derivings]]+ } = [DataD [] (toName tName) vars Nothing cons [derivingClause]] where- derivings = DerivClause Nothing (map (ConT . genName) derives)+ derivingClause = DerivClause Nothing (map (ConT . genName) derives) cons = map declareCons tCons #if MIN_VERSION_template_haskell(2,17,0)
src/Data/Morpheus/Server/TH/Utils.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE GADTs #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TemplateHaskellQuotes #-} {-# LANGUAGE NoImplicitPrelude #-} module Data.Morpheus.Server.TH.Utils@@ -21,10 +21,10 @@ ( CodeGenConfig, ) import Data.Morpheus.CodeGen.Internal.TH- ( _',- apply,+ ( apply, funDSimple, vars,+ _', ) import Data.Morpheus.Types.Internal.AST ( TypeName,
src/Data/Morpheus/Server/Types/GQLType.hs view
@@ -67,6 +67,7 @@ toNullable, unpackName, )+import Data.Sequence (Seq) import Data.Text ( intercalate, pack,@@ -81,7 +82,8 @@ typeRep, typeRepTyCon, )-import Relude hiding (Undefined, intercalate)+import Data.Vector (Vector)+import Relude hiding (Seq, Undefined, intercalate) data TypeData = TypeData { gqlTypeName :: TypeName,@@ -125,7 +127,7 @@ } __typeData ::- forall kinded (kind :: TypeCategory) (a :: *).+ forall kinded (kind :: TypeCategory) (a :: Type). (GQLType a, CategoryValue kind) => kinded kind a -> TypeData@@ -140,6 +142,9 @@ getTypeConstructors :: Typeable a => f a -> [TyCon] getTypeConstructors = ignoreResolver . splitTyConApp . typeRep +prefixInputs :: GQLTypeOptions -> GQLTypeOptions+prefixInputs options = options {typeNameModifier = \isInput name -> if isInput then "Input" <> name else name}+ deriveTypeData :: Typeable a => f a -> (Bool -> String -> String) -> TypeCategory -> TypeData deriveTypeData proxy typeNameModifier cat = TypeData@@ -269,11 +274,24 @@ type KIND (Set a) = WRAPPER __type _ = __type $ Proxy @[a] +instance GQLType a => GQLType (NonEmpty a) where+ type KIND (NonEmpty a) = WRAPPER+ __type _ = __type $ Proxy @[a]++instance GQLType a => GQLType (Seq a) where+ type KIND (Seq a) = WRAPPER+ __type _ = __type $ Proxy @[a]++instance GQLType a => GQLType (Vector a) where+ type KIND (Vector a) = WRAPPER+ __type _ = __type $ Proxy @[a]+ instance GQLType a => GQLType (SubscriptionField a) where type KIND (SubscriptionField a) = WRAPPER __type _ = __type $ Proxy @a -instance (Typeable a, Typeable b, GQLType a, GQLType b) => GQLType (Pair a b)+instance (Typeable a, Typeable b, GQLType a, GQLType b) => GQLType (Pair a b) where+ typeOptions _ = prefixInputs -- Manual @@ -294,8 +312,8 @@ __type _ = __type $ Proxy @a instance (Typeable a, Typeable b, GQLType a, GQLType b) => GQLType (a, b) where- type KIND (a, b) = CUSTOM __type _ = __type $ Proxy @(Pair a b)+ typeOptions _ = prefixInputs instance (GQLType value) => GQLType (Arg name value) where type KIND (Arg name value) = CUSTOM
src/Data/Morpheus/Server/Types/Types.hs view
@@ -11,6 +11,7 @@ ) where +import Data.Kind (Type) import GHC.Generics ( Generic, )@@ -19,13 +20,9 @@ ( Show, ) -data Undefined (m :: * -> *) = Undefined deriving (Show, Generic)+data Undefined (m :: Type -> Type) = Undefined deriving (Show, Generic) -data Pair k v = Pair- { key :: k,- value :: v- }- deriving (Generic)+data Pair k v = Pair k v deriving (Generic) data TypeGuard interface union = ResolveInterface interface
src/Data/Morpheus/Types.hs view
@@ -121,15 +121,15 @@ ) import Relude hiding (Undefined) -class FlexibleResolver (f :: * -> *) (a :: k) where- type Flexible (m :: * -> *) a :: *- type Composed (m :: * -> *) f a :: *+class FlexibleResolver (f :: Type -> Type) (a :: k) where+ type Flexible (m :: Type -> Type) a :: Type+ type Composed (m :: Type -> Type) f a :: Type -instance FlexibleResolver f (a :: *) where+instance FlexibleResolver f (a :: Type) where type Flexible m a = m a type Composed m f a = m (f a) -instance FlexibleResolver f (a :: (* -> *) -> *) where+instance FlexibleResolver f (a :: (Type -> Type) -> Type) where type Flexible m a = m (a m) type Composed m f a = m (f (a m)) @@ -211,11 +211,11 @@ -- if your schema does not supports __mutation__ or __subscription__ , you can use __()__ for it. data RootResolver- (m :: * -> *)+ (m :: Type -> Type) event- (query :: (* -> *) -> *)- (mutation :: (* -> *) -> *)- (subscription :: (* -> *) -> *) = RootResolver+ (query :: (Type -> Type) -> Type)+ (mutation :: (Type -> Type) -> Type)+ (subscription :: (Type -> Type) -> Type) = RootResolver { queryResolver :: query (Resolver QUERY event m), mutationResolver :: mutation (Resolver MUTATION event m), subscriptionResolver :: subscription (Resolver SUBSCRIPTION event m)@@ -223,11 +223,11 @@ data NamedResolvers- (m :: * -> *)+ (m :: Type -> Type) event- (qu :: (* -> *) -> *)- (mu :: (* -> *) -> *)- (su :: (* -> *) -> *)+ (qu :: (Type -> Type) -> Type)+ (mu :: (Type -> Type) -> Type)+ (su :: (Type -> Type) -> Type) = ( ResolveNamed (Resolver QUERY event m) (qu (NamedResolverT (Resolver QUERY event m)))
test/Feature/Inference/TypeInference.hs view
@@ -52,13 +52,13 @@ deriving (Show, Generic, GQLType) data Character (m :: * -> *)- = CharacterDeity (Deity m) -- Only <tycon name><type ref name> should generate direct link+ = CharacterDeity (Deity m) -- Only <tyCon name><type ref name> should generate direct link | Creature {creatureName :: Text, creatureAge :: Int} | BoxedDeity {boxedDeity :: Deity m} | ScalarRecord {scalarText :: Text} | CharacterAge Int | SomeDeity (Deity m)- | SomeMutli Int Text+ | SomeCompound Int Text | Zeus | Cronus deriving (Generic, GQLType)@@ -71,7 +71,7 @@ ScalarRecord {scalarText = "Some Text"}, SomeDeity deityRes, CharacterAge 12,- SomeMutli 21 "some text",+ SomeCompound 21 "some text", Zeus, Cronus ]
test/Feature/Inference/type-inference/introspection/union/positional-products/query.gql view
@@ -2,7 +2,7 @@ someDeity: __type(name: "SomeDeity") { ...FullType }- someMutli: __type(name: "SomeMutli") {+ someCompound: __type(name: "SomeCompound") { ...FullType } }
test/Feature/Inference/type-inference/introspection/union/positional-products/response.json view
@@ -21,9 +21,9 @@ "enumValues": null, "possibleTypes": null },- "someMutli": {+ "someCompound": { "kind": "OBJECT",- "name": "SomeMutli",+ "name": "SomeCompound", "fields": [ { "name": "_0",
test/Feature/Inference/type-inference/introspection/union/union/response.json view
@@ -14,7 +14,7 @@ { "kind": "OBJECT", "name": "ScalarRecord", "ofType": null }, { "kind": "OBJECT", "name": "CharacterAge", "ofType": null }, { "kind": "OBJECT", "name": "SomeDeity", "ofType": null },- { "kind": "OBJECT", "name": "SomeMutli", "ofType": null },+ { "kind": "OBJECT", "name": "SomeCompound", "ofType": null }, { "kind": "OBJECT", "name": "Zeus", "ofType": null }, { "kind": "OBJECT", "name": "Cronus", "ofType": null } ]
test/Feature/Inference/type-inference/resolving/complexUnion/query.gql view
@@ -32,7 +32,7 @@ } } - ... on SomeMutli {+ ... on SomeCompound { _0 _1 }
test/Feature/Inference/type-inference/resolving/complexUnion/response.json view
@@ -27,7 +27,7 @@ "_0": 12 }, {- "__typename": "SomeMutli",+ "__typename": "SomeCompound", "_0": 21, "_1": "some text" },
+ test/Feature/Input/Collections.hs view
@@ -0,0 +1,83 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE TypeFamilies #-}++module Feature.Input.Collections+ ( api,+ )+where++import Data.List.NonEmpty (NonEmpty)+import Data.Map (Map)+import Data.Morpheus (deriveApp, runApp)+import Data.Morpheus.Types+ ( App,+ Arg (..),+ GQLRequest,+ GQLResponse,+ GQLType (..),+ GQLTypeOptions (..),+ GQLTypeOptions (..),+ RootResolver (..),+ Undefined (..),+ render,+ )+import Data.Sequence (Seq)+import Data.Set (Set)+import Data.Text+import Data.Vector (Vector)+import Debug.Trace (traceShow)+import GHC.Generics (Generic)++-- query+testRes :: Applicative m => Arg "value" a -> m a+testRes = pure . argValue++type Coll m a = Arg "value" a -> m a++data Product = Product Text Int Bool (Maybe Double)+ deriving (Generic)++instance GQLType Product where+ typeOptions _ options =+ options+ { typeNameModifier = \isInput name -> if isInput then "Input" <> name else name+ }++-- resolver+data Query m = Query+ { testSet :: Coll m (Set Int),+ testNonEmpty :: Coll m (NonEmpty Int),+ tesSeq :: Coll m (Seq Int),+ testVector :: Coll m (Vector Int),+ testProduct :: Coll m Product,+ testTuple :: Coll m (Text, Int),+ testMap :: Coll m (Map Text Int),+ testAssoc :: Coll m [(Text, Int)]+ }+ deriving (Generic, GQLType)++rootResolver :: RootResolver IO () Query Undefined Undefined+rootResolver =+ RootResolver+ { queryResolver =+ Query+ { testSet = testRes,+ testNonEmpty = testRes,+ tesSeq = testRes,+ testVector = testRes,+ testTuple = testRes,+ testProduct = testRes,+ testMap = testRes,+ testAssoc = testRes+ },+ mutationResolver = Undefined,+ subscriptionResolver = Undefined+ }++app :: App () IO+app = deriveApp rootResolver++api :: GQLRequest -> IO GQLResponse+api = runApp app
+ test/Feature/Input/collections/assoc/invalid/query.gql view
@@ -0,0 +1,8 @@+query InvalidAssoc {+ f1: testAssoc(value: {})+ f2: testAssoc(value: 635)+ f3: testAssoc(value: [{ _0: "235" }])+ f4: testAssoc(value: [{ _0: "235", _1: "235235" }])+ f5: testAssoc(value: [{ _0: "235", _1: false }])+ f6: testAssoc(value: [{ _0: "34", _1: 2353 }])+}
+ test/Feature/Input/collections/assoc/invalid/response.json view
@@ -0,0 +1,28 @@+{+ "errors": [+ {+ "message": "Argument \"value\" got invalid value. Expected type \"[InputPairTextInt!]!\" found {}.",+ "locations": [{ "line": 2, "column": 17 }]+ },+ {+ "message": "Argument \"value\" got invalid value. Expected type \"[InputPairTextInt!]!\" found 635.",+ "locations": [{ "line": 3, "column": 17 }]+ },+ {+ "message": "Argument \"value\" got invalid value. Undefined Field \"_1\".",+ "locations": [{ "line": 4, "column": 17 }]+ },+ {+ "message": "Argument \"value\" got invalid value. in field \"_1\": Expected type \"Int!\" found \"235235\".",+ "locations": [{ "line": 5, "column": 17 }]+ },+ {+ "message": "Argument \"value\" got invalid value. in field \"_1\": Expected type \"Int!\" found false.",+ "locations": [{ "line": 6, "column": 17 }]+ },+ {+ "message": "Field \"testAssoc\" of type \"PairTextInt\" must have a selection of subfields",+ "locations": [{ "line": 7, "column": 3 }]+ }+ ]+}
+ test/Feature/Input/collections/assoc/ok/query.gql view
@@ -0,0 +1,19 @@+query ValidAssoc {+ f1: testAssoc(value: []) {+ ...Entry+ }+ f2: testAssoc(+ value: [+ { _0: "zeus", _1: 3468 }+ { _0: "morpheus", _1: 4236 }+ { _0: "cronos", _1: 547 }+ ]+ ) {+ ...Entry+ }+}++fragment Entry on PairTextInt {+ _0+ _1+}
+ test/Feature/Input/collections/assoc/ok/response.json view
@@ -0,0 +1,10 @@+{+ "data": {+ "f2": [+ { "_0": "zeus", "_1": 3468 },+ { "_0": "morpheus", "_1": 4236 },+ { "_0": "cronos", "_1": 547 }+ ],+ "f1": []+ }+}
+ test/Feature/Input/collections/map/invalid/query.gql view
@@ -0,0 +1,8 @@+query InvalidMap {+ f1: testMap(value: {})+ f2: testMap(value: 635)+ f3: testMap(value: [{ _0: "235" }])+ f4: testMap(value: [{ _0: "235", _1: "235235" }])+ f5: testMap(value: [{ _0: "235", _1: false }])+ f6: testMap(value: [{ _0: "34", _1: 2353 }])+}
+ test/Feature/Input/collections/map/invalid/response.json view
@@ -0,0 +1,28 @@+{+ "errors": [+ {+ "message": "Argument \"value\" got invalid value. Expected type \"[InputPairTextInt!]!\" found {}.",+ "locations": [{ "line": 2, "column": 15 }]+ },+ {+ "message": "Argument \"value\" got invalid value. Expected type \"[InputPairTextInt!]!\" found 635.",+ "locations": [{ "line": 3, "column": 15 }]+ },+ {+ "message": "Argument \"value\" got invalid value. Undefined Field \"_1\".",+ "locations": [{ "line": 4, "column": 15 }]+ },+ {+ "message": "Argument \"value\" got invalid value. in field \"_1\": Expected type \"Int!\" found \"235235\".",+ "locations": [{ "line": 5, "column": 15 }]+ },+ {+ "message": "Argument \"value\" got invalid value. in field \"_1\": Expected type \"Int!\" found false.",+ "locations": [{ "line": 6, "column": 15 }]+ },+ {+ "message": "Field \"testMap\" of type \"PairTextInt\" must have a selection of subfields",+ "locations": [{ "line": 7, "column": 3 }]+ }+ ]+}
+ test/Feature/Input/collections/map/ok/query.gql view
@@ -0,0 +1,19 @@+query ValidMap {+ f1: testMap(value: []) {+ ...Entry+ }+ f2: testMap(+ value: [+ { _0: "zeus", _1: 3468 }+ { _0: "morpheus", _1: 4236 }+ { _0: "cronos", _1: 547 }+ ]+ ) {+ ...Entry+ }+}++fragment Entry on PairTextInt {+ _0+ _1+}
+ test/Feature/Input/collections/map/ok/response.json view
@@ -0,0 +1,10 @@+{+ "data": {+ "f1": [],+ "f2": [+ { "_0": "cronos", "_1": 547 },+ { "_0": "morpheus", "_1": 4236 },+ { "_0": "zeus", "_1": 3468 }+ ]+ }+}
+ test/Feature/Input/collections/nonempty/invalid/query.gql view
@@ -0,0 +1,3 @@+query FailOnEmpty {+ testNonEmpty(value: [])+}
+ test/Feature/Input/collections/nonempty/invalid/response.json view
@@ -0,0 +1,8 @@+{+ "errors": [+ {+ "message": "Failure on Resolving Field \"testNonEmpty\": Type mismatch! expected:Expected a NonEmpty list, got: []",+ "locations": [{ "line": 2, "column": 3 }]+ }+ ]+}
+ test/Feature/Input/collections/nonempty/ok/query.gql view
@@ -0,0 +1,4 @@+query ValidNonEmpty {+ f1: testNonEmpty(value: [32])+ f2: testNonEmpty(value: [32, 235, 235, 6463, 352123])+}
+ test/Feature/Input/collections/nonempty/ok/response.json view
@@ -0,0 +1,6 @@+{+ "data": {+ "f1": [32],+ "f2": [32, 235, 235, 6463, 352123]+ }+}
+ test/Feature/Input/collections/product/invalid/query.gql view
@@ -0,0 +1,9 @@+query InvalidProduct {+ f1: testProduct(value: [])+ f2: testProduct(value: {})+ f3: testProduct(value: { _0: 2 })+ f4: testProduct(value: { _0: "235" })+ f4: testProduct(value: { _0: "235", _1: "235235" })+ f4: testProduct(value: { _0: "235", _1: false })+ f5: testProduct(value: { _0: "34", _1: 2353, _2: false })+}
+ test/Feature/Input/collections/product/invalid/response.json view
@@ -0,0 +1,60 @@+{+ "errors": [+ {+ "message": "Argument \"value\" got invalid value. Expected type \"InputProduct!\" found [].",+ "locations": [{ "line": 2, "column": 19 }]+ },+ {+ "message": "Argument \"value\" got invalid value. Undefined Field \"_0\".",+ "locations": [{ "line": 3, "column": 19 }]+ },+ {+ "message": "Argument \"value\" got invalid value. Undefined Field \"_1\".",+ "locations": [{ "line": 3, "column": 19 }]+ },+ {+ "message": "Argument \"value\" got invalid value. Undefined Field \"_2\".",+ "locations": [{ "line": 3, "column": 19 }]+ },+ {+ "message": "Argument \"value\" got invalid value. Undefined Field \"_1\".",+ "locations": [{ "line": 4, "column": 19 }]+ },+ {+ "message": "Argument \"value\" got invalid value. Undefined Field \"_2\".",+ "locations": [{ "line": 4, "column": 19 }]+ },+ {+ "message": "Argument \"value\" got invalid value. in field \"_0\": Expected type \"String!\" found 2.",+ "locations": [{ "line": 4, "column": 19 }]+ },+ {+ "message": "Argument \"value\" got invalid value. Undefined Field \"_1\".",+ "locations": [{ "line": 5, "column": 19 }]+ },+ {+ "message": "Argument \"value\" got invalid value. Undefined Field \"_2\".",+ "locations": [{ "line": 5, "column": 19 }]+ },+ {+ "message": "Argument \"value\" got invalid value. Undefined Field \"_2\".",+ "locations": [{ "line": 6, "column": 19 }]+ },+ {+ "message": "Argument \"value\" got invalid value. in field \"_1\": Expected type \"Int!\" found \"235235\".",+ "locations": [{ "line": 6, "column": 19 }]+ },+ {+ "message": "Argument \"value\" got invalid value. Undefined Field \"_2\".",+ "locations": [{ "line": 7, "column": 19 }]+ },+ {+ "message": "Argument \"value\" got invalid value. in field \"_1\": Expected type \"Int!\" found false.",+ "locations": [{ "line": 7, "column": 19 }]+ },+ {+ "message": "Field \"testProduct\" of type \"Product\" must have a selection of subfields",+ "locations": [{ "line": 8, "column": 3 }]+ }+ ]+}
+ test/Feature/Input/collections/product/ok/query.gql view
@@ -0,0 +1,15 @@+query ValidProduct {+ f1: testProduct(value: { _0: "abc", _1: 4235, _2: true }) {+ ...Product+ }+ f2: testProduct(value: { _0: "324523", _1: 3468, _2: false, _3: 0.635 }) {+ ...Product+ }+}++fragment Product on Product {+ _0+ _1+ _2+ _3+}
+ test/Feature/Input/collections/product/ok/response.json view
@@ -0,0 +1,16 @@+{+ "data": {+ "f1": {+ "_0": "abc",+ "_1": 4235,+ "_2": true,+ "_3": null+ },+ "f2": {+ "_0": "324523",+ "_1": 3468,+ "_2": false,+ "_3": 0.635+ }+ }+}
+ test/Feature/Input/collections/seq/query.gql view
@@ -0,0 +1,5 @@+query ValidSeq {+ f1: tesSeq(value: [])+ f2: tesSeq(value: [32])+ f3: tesSeq(value: [32, 235, 6463, 352123])+}
+ test/Feature/Input/collections/seq/response.json view
@@ -0,0 +1,7 @@+{+ "data": {+ "f1": [],+ "f2": [32],+ "f3": [32, 235, 6463, 352123]+ }+}
+ test/Feature/Input/collections/set/invalid/query.gql view
@@ -0,0 +1,5 @@+query FailSet {+ f1: testSet(value: [2, 2])+ f2: testSet(value: [32, 32, 32])+ f3: testSet(value: [32, 235, 235, 6463, 352123])+}
+ test/Feature/Input/collections/set/invalid/response.json view
@@ -0,0 +1,16 @@+{+ "errors": [+ {+ "message": "Failure on Resolving Field \"testSet\": Expected a List without duplicates, found 1 duplicates",+ "locations": [{ "line": 2, "column": 3 }]+ },+ {+ "message": "Failure on Resolving Field \"testSet\": Expected a List without duplicates, found 2 duplicates",+ "locations": [{ "line": 3, "column": 3 }]+ },+ {+ "message": "Failure on Resolving Field \"testSet\": Expected a List without duplicates, found 1 duplicates",+ "locations": [{ "line": 4, "column": 3 }]+ }+ ]+}
+ test/Feature/Input/collections/set/ok/query.gql view
@@ -0,0 +1,5 @@+query ValidSet {+ f1: testSet(value: [])+ f2: testSet(value: [32])+ f3: testSet(value: [32, 235, 6463, 352123])+}
+ test/Feature/Input/collections/set/ok/response.json view
@@ -0,0 +1,7 @@+{+ "data": {+ "f1": [],+ "f2": [32],+ "f3": [32, 235, 6463, 352123]+ }+}
+ test/Feature/Input/collections/tuple/invalid/query.gql view
@@ -0,0 +1,9 @@+query InvalidTuple {+ f1: testTuple(value: [])+ f2: testTuple(value: {})+ f3: testTuple(value: { _0: 2 })+ f4: testTuple(value: { _0: "235" })+ f4: testTuple(value: { _0: "235", _1: "235235" })+ f4: testTuple(value: { _0: "235", _1: false })+ f5: testTuple(value: { _0: "34", _1: 2353 })+}
+ test/Feature/Input/collections/tuple/invalid/response.json view
@@ -0,0 +1,40 @@+{+ "errors": [+ {+ "message": "Argument \"value\" got invalid value. Expected type \"InputPairTextInt!\" found [].",+ "locations": [{ "line": 2, "column": 17 }]+ },+ {+ "message": "Argument \"value\" got invalid value. Undefined Field \"_0\".",+ "locations": [{ "line": 3, "column": 17 }]+ },+ {+ "message": "Argument \"value\" got invalid value. Undefined Field \"_1\".",+ "locations": [{ "line": 3, "column": 17 }]+ },+ {+ "message": "Argument \"value\" got invalid value. Undefined Field \"_1\".",+ "locations": [{ "line": 4, "column": 17 }]+ },+ {+ "message": "Argument \"value\" got invalid value. in field \"_0\": Expected type \"String!\" found 2.",+ "locations": [{ "line": 4, "column": 17 }]+ },+ {+ "message": "Argument \"value\" got invalid value. Undefined Field \"_1\".",+ "locations": [{ "line": 5, "column": 17 }]+ },+ {+ "message": "Argument \"value\" got invalid value. in field \"_1\": Expected type \"Int!\" found \"235235\".",+ "locations": [{ "line": 6, "column": 17 }]+ },+ {+ "message": "Argument \"value\" got invalid value. in field \"_1\": Expected type \"Int!\" found false.",+ "locations": [{ "line": 7, "column": 17 }]+ },+ {+ "message": "Field \"testTuple\" of type \"PairTextInt\" must have a selection of subfields",+ "locations": [{ "line": 8, "column": 3 }]+ }+ ]+}
+ test/Feature/Input/collections/tuple/ok/query.gql view
@@ -0,0 +1,10 @@+query ValidTuple {+ f1: testTuple(value: { _0: "abc", _1: 4235 }) {+ _0+ _1+ }+ f2: testTuple(value: { _0: "324523", _1: 3468 }) {+ _0+ _1+ }+}
+ test/Feature/Input/collections/tuple/ok/response.json view
@@ -0,0 +1,12 @@+{+ "data": {+ "f1": {+ "_0": "abc",+ "_1": 4235+ },+ "f2": {+ "_0": "324523",+ "_1": 3468+ }+ }+}
+ test/Feature/Input/collections/vector/query.gql view
@@ -0,0 +1,5 @@+query ValidSeq {+ f1: testVector(value: [])+ f2: testVector(value: [32])+ f3: testVector(value: [32, 235, 6463, 352123])+}
+ test/Feature/Input/collections/vector/response.json view
@@ -0,0 +1,7 @@+{+ "data": {+ "f1": [],+ "f2": [32],+ "f3": [32, 235, 6463, 352123]+ }+}
test/Spec.hs view
@@ -18,6 +18,7 @@ import qualified Feature.Inference.TypeInference as TypeInference import qualified Feature.Inference.UnionType as UnionType import qualified Feature.Inference.WrappedType as WrappedType+import qualified Feature.Input.Collections as Collections import qualified Feature.Input.DefaultValues as DefaultValues import qualified Feature.Input.Enums as Enums import qualified Feature.Input.Objects as Objects@@ -63,7 +64,8 @@ (Enums.api, "enums"), (Scalars.api, "scalars"), (Objects.api, "objects"),- (DefaultValues.api, "default-values")+ (DefaultValues.api, "default-values"),+ (Collections.api, "collections") ], testFeatures "Collision"
test/Subscription/Case/Publishing.hs view
@@ -70,9 +70,9 @@ ) pure (input, state) -triggerSubsciption ::+triggerSubscription :: IO TestTree-triggerSubsciption = do+triggerSubscription = do (input, state) <- simulateSubscriptions SimulationState {inputs, outputs, store} <- simulatePublish (Event [DEITY] Info {name = "Zeus", age = 1200}) state@@ -102,5 +102,5 @@ testPublishing :: IO TestTree testPublishing = do- trigger <- triggerSubsciption+ trigger <- triggerSubscription return $ testGroup "Publishing" [trigger]