Releases: morpheusgraphql/morpheus-graphql
morpheus-graphql-0.12.0
morpheus-graphql
Breaking Changes
Package was extracted as:
-
morpheus-graphql-core
: core components like: parser, validator, executor, utils.- Data.Morpheus.Core
- Data.Morpheus.QuasiQuoter
- Data.Morpheus.Error
- Data.Morpheus.Internal.TH
- Data.Morpheus.Internal.Utils
- Data.Morpheus.Types.Internal.Resolving
- Data.Morpheus.Types.Internal.Operation
- Data.Morpheus.Types.Internal.AST
- Data.Morpheus.Types.IO
-
morpheus-graphql-client
: lightweight version of morpheus client without server implementation- Data.Morpheus.Client
-
morpheus-graphql
: morpheus graphql server- Data.Morpheus
- Data.Morpheus.Kind
- Data.Morpheus.Types
- Data.Morpheus.Server
- Data.Morpheus.Document
deprecated:
Res
,IORes
,ResolveQ
: useResolverQ
MutRes
,IOMutRes
,ResolveM
: useResolverM
SubRes
,IOSubRes
,ResolveS
: useResolverS
failRes
: useMonadFail
New Feature
-
Semigroup
support for Resolver -
MonadFail
Support for Resolver -
flexible resolvers:
ResolverO
,ResolverQ
,RwsolverM
,ResolverS
they can handle object and scalar types:-- if we have record and regular Int data Object m = Object { field :: m Int } -- we canwrite -- handes kind : (* -> *) -> * resolveObject :: ResolverO o EVENT IO Object -- is alias to: Resolver o () IO (Object (Resolver o () IO)) -- or -- handes kind : * resolveInt :: ResolverO o EVENT IO Int -- is alias to: Resolver o () IO Int
the resolvers :
ResolverQ
,RwsolverM
,ResolverS
, are like
ResolverO
but withQUERY
,MUTATION
andSUBSCRIPTION
as argument. -
flexible compsed Resolver Type alias:
ComposedResolver
. extendsResolverO
with
parameter(f :: * -> *)
. so that you can compose Resolvers e.g:resolveList :: ComposedResolver o EVENT IO [] Object -- is alias to: Resolver o () IO [Object (Resolver o () IO))] resolveList :: ComposedResolver o EVENT IO Maybe Int -- is alias to: Resolver o () IO (Maybe Int)
-
server supports interfaces (see Readme):
- define interface with Haskell Types (runtime validation):
- define interface with
importGQLDocument
andDSL
(compile time validation):
-
support default directives:
@skip
and@include
-
SelectionTree interface
minor
- fixed subscription sessions, srarting new session does not affects old ones.
- added tests for subscriptions
morpheus-graphql-core
0.12.0 - 21.05.2020
New features
-
parser supports implemnets interfaces seperated with empty spaces
type T implements A , B C & D {
-
introspection can render interfaces
morpheus-graphql-0.11.0
Breaking Changes
-
Client generated enum data constructors are now prefixed with with the type name to avoid name conflicts.
-
for Variant selection inputUnion uses
inputname
insead of__typename
-
in
Data.Morpheus.Server
gqlSocketApp
andgqlSocketMonadIOApp
are replaced withwebSocketsApp
- removed
initGQLState
,GQLState
-
for better control of subscriptions
- replaced instance
interpreter gqlRoot state
with
interpreter gqlRoot
. - added:
Input
,Stream
,httpPubApp
from now on you can define API that can be
used in websockets as well as in http serversapi :: Input api -> Stream api EVENT IO api = interpreter gqlRoot server :: IO () server = do (wsApp, publish) <- webSocketsApp api let httpApp = httpPubApp api publish ... runBoth wsApp httpApp
where
publish :: e -> m ()
websockets and http app do not have to be on the same server.
e.g. you can pass events between servers with webhooks. - replaced instance
-
subscription can select only one top level field (based on the GraphQL specification).
New features
- Instead of rejecting conflicting selections, they are merged (based on the GraphQL specification).
- Support for input lists separated by newlines. thanks @charlescrain
- conflicting variable , fragment ... validation
- issue #411: Aeson
FromJSON
ToJSON
instances forID
minor
- changes to internal types
- fixed validation of apollo websockets requests
morpheus-graphql-0.10.0
Breaking Changes
-
all constructors of
Resolver
:QueryResolver
,MutResolver
,SubResolver
are unexposed. uselift
,publish
orsubscribe
instead.
e.g-- Query Resolver resolveUser :: ResolveQ EVENT IO User resolveUser = lift getDBUser -- Mutation Resolver resolveCreateUser :: ResolveM EVENT IO User resolveCreateUser = do publish [userUpdate] -- publishes event inside mutation lift setDBUser -- Subscription Resolver resolveNewUser :: ResolveS EVENT IO User resolveNewUser = subscribe [USER] $ do pure $ \(Event _ content) -> lift (getDBUserByContent content)
New features
-
exposed
publish
for mutation resolvers, now you can writeresolveCreateUser :: ResolveM EVENT IO User resolveCreateUser = do requireAuthorized publish [userUpdate] liftEither setDBUser
-
exposed
subscribe
for subscription resolvers, now you can writeresolveNewUser :: ResolveS EVENT IO User resolveNewUser = subscribe [USER] $ do requireAuthorized pure userByEvent where userByEvent (Event _ content) = liftEither (getDBUser content)
-
type SubField
will convert your subscription monad to query monad.
SubField (Resolver Subscription Event IO) User
will generate same as
Resolver Subscription Event IO (User ((Resolver QUERY Event IO)))
now if you can define subscription as follows
data Subscription m = Subscription { newUser :: SubField m User }
-
unsafeInternalContext
to get resolver context, use only if it really necessary.
the code depending on it may break even on minor version changes.resolveUser :: ResolveQ EVENT IO User resolveUser = do Context { currentSelection, schema, operation } <- unsafeInternalContext lift (getDBUser currentSelection)
Minor
morpheus-graphql-0.9.1
Changed
- removed dependency
mtl
morpheus-graphql-0.9.0
Added
Fixed
-
liftEither support in MutResolver (#351)
-
selection of
__typename
on object und union objects (#337) -
auto inferece of external types in gql document (#343)
th will generate field
m (Type m)
if type has an argumente.g for this types and DSL
data Type1 = Type1 { ... } type Type2 m = SomeType m data Type3 m = Type2 { bla :: m Text } deriving ...
type Query { field1 : Type1! field2 : Type2! field3 : Type3! }
morpheus generates
data Query m = Query { field1 :: m Type1 field2 :: m (Type2 m) field3 :: m (Type3 m) } deriving ...
now you can combine multiple gql documents:
importDocumentWithNamespace `coreTypes.gql` importDocumentWithNamespace `operations.gql`
Changed
-
support of resolver fields
m type
for the fields without argumentsdata Diety m = Deity { name :: m Text } -- is equal to data Diety m = Deity { name :: () -> m Text }
-
template haskell generates
m type
insead of() -> m type
for fields without argument (#334)data Diety m = Deity { name :: (Arrow () (m Text)), power :: (Arrow () (m (Maybe Text))) } -- changed to data Diety m = Deity { name :: m Text, power :: m (Maybe Text) }
morpheus-graphql-0.8.0
Changed
-
deprecated:
INPUT_OBJECT
,OBJECT
,UNION
,- use
INPUT
instead ofINPUT_OBJECT
- use
deriving(GQLType)
insead ofOBJECT
orUNION
- use
-
only namespaced Unions generate regular graphql Union, other attempts will be wrapped inside an object with constructor name :
e.g:
data Character = CharacterDeity Deity SomeDeity Deity deriving (GQLType)
where
Deity
is Object.
will generateunion CHaracter = Deity | SomeDeity type SomeDeity { _0: Deity }
Added
failRes
for resolver failures- added kind: INPUT , OUTPUT
- Automatic Type Inference (only for Object, Union and Enum)
- More general stateful resolvers which accept instances of MonadIO (Authored by Sebastian Pulido [sebashack])
- Utility to create web-socket applications with custom MonadIO instances (Authored by Sebastian Pulido [sebashack])
data Realm =
Sky
| Sea
| Underworld
deriving (Generic, GQLType)
data Deity = Deity{
fullName:: Text,
realm:: Realm
} deriving (Generic, GQLType)
data Character =
CharacterDeity Deity -- Only <tyconName><conName> should generate direct link
-- RECORDS
| Creature { creatureName :: Text, creatureAge :: Int }
--- Types
| SomeDeity Deity
| CharacterInt Int
| SomeMutli Int Text
--- ENUMS
| Zeus
| Cronus deriving (Generic, GQLType)
will generate schema:
enum Realm {
Sky
Sea
Underworld
}
type Deity {
fullName: String!
realm: Realm!
}
union Character =
Deity
| Creature
| SomeDeity
| CharacterInt
| SomeMutli
| CharacterEnumObject
type Creature {
creatureName: String!
creatureAge: Int!
}
type SomeDeity {
_0: Deity!
}
type CharacterInt {
_0: Int!
}
type SomeMutli {
_0: Int!
_1: String!
}
# enum
type CharacterEnumObject {
enum: CharacterEnum!
}
enum CharacterEnum {
Zeus
Cronus
}
rules:
-
haskell union type with only empty constructors (e.g
Realm
), will generate graphqlenum
-
haskell record without union (e.g
Deity
), will generate graphqlobject
-
namespaced Unions:
CharacterDeity
whereCharacter
is TypeConstructor andDeity
referenced object (not scalar) type: will be generate regular graphql Unionunion Character = Deity | ...
-
for union recrods (
Creature { creatureName :: Text, creatureAge :: Int }
) will be referenced in union type, plus typeCreature
will be added in schema.e.g
union Character = ... | Creature | ... type Creature { creatureName : String! creatureAge: Int! }
-
all empty constructors in union will be summed in type
<tyConName>Enum
(e.gCharacterEnum
), this enum will be wrapped inCharacterEnumObject
and this type will be added to unionCharacter
. as in example above -
there is only types left with form
TypeName Type1 2Type ..
(e.gSomeDeity Deity
,CharacterInt Int
,SomeMutli Int Text
),morpheus will generate objet type from it:
type TypeName { _0: Type1! _1: Type2! ... }
-
Removed
- removed kind: INPUT_UNION
Fixed
- on filed resolver was displayed. unexhausted case exception of graphql error
- support of signed numbers (e.g
-4
) - support of round floats (e.g
1.000
) - validation checks undefined fields on inputObject
- variables are supported inside input values
morpheus-graphql-0.7.1
- bounds supports megaparsec-8.0
morpheus-graphql-0.7.0
Removed
toMorpheusHaskellAPi
fromData.Morpheus.Document
functionality will be migrated inmorpheus-graphql-cli
Changed
-
liftM
toMonadTrans
instance methodlift
-
liftEitherM
toliftEither
-
Resolver operation m event value
->Resolver operation event m value
, monad trans needs that last 2 type arguments are monad and value that why it was necessary -
exposed
Data.Morpheus.Types.Internal.AST
-
Mutation Resolver was changed from
resolver :: () -> ResolveM EVENT IO Address
resolver = MutResolver {
mutEvents = [someEventForSubscription],
mutResolver = lift setDBAddress
}
-- Mutation Wit Event Triggering : sends events to subscription
resolver :: () -> ResolveM EVENT IO Address
resolver = MutResolver \$ do
value <- lift setDBAddress
pure ([someEventForSubscription], value)
-- or
-- Mutation Without Event Triggering
resolver :: () -> ResolveM EVENT IO Address
resolver _args = lift setDBAddress
Added
-
added
parseDSL
toData.Morpheus.Document
-
GraphQL SDL support fully supports descriptions: onTypes, fields , args ...
with (enums, inputObjects , union, object)
for example :""" Description for Type Address """ type Address { """ Description for Field city """ city: String! street( """ Description argument id """ id: ID! ): Int! }
GraphQL SDL
type User { name: String! @deprecated(reason: "some reason") }
will displayed in introspection
introspection.json
{ "data": { "__type": { "fields": [ { "name": "city", "isDeprecated": true, "deprecationReason": "test deprecation field with reason" } ] } } }
-
basic support of directive
@deprecated
onenumValue
and objectfield
, only on introspection -
GraphQL Client deprecation warnings
on type
type Human { humanName: String! lifetime: Lifetime! @deprecated(reason: "some reason") profession: Profession }
compiler output:
warning: Morpheus Client Warning: { "message":"the field \"Human.lifetime\" is deprecated. some reason", "locations":[{"line":24,"column":15}] }
-
new helper resolver types aliases:
- ResolveQ : for Query
- ResolveM : for Mutation
- ResolveS : for Subscription
ResolveM EVENT IO Address
is same asMutRes EVENT IO (Address (MutRes EVENT IO))
is helpfull wenn you want to resolve GraphQL object
Fixed
- added missing Monad instance for Mutation resolver
defineByIntrospectionFile
does not breaks if schema contains interfaces- Morpheus Client supports
Subscription
andMutation
operations
morpheus-graphql-0.6.2
Added
- support of ghc 8.8.1
morpheus-graphql-0.6.0
Removed
-
removed
morpheus
cli for code generating, if you need cli you should use
morpheus-graphql-cli -
example
API
executable is removed from Production build
Added
-
helper functions:
liftEitherM
,liftM
liftM :: m a -> Resolver o m e a liftEitherM :: m (Either String a) -> Resolver o m e a