feature: Directives api for SDL
directives api for SDL
GraphQL implementations that support the type system definition language must provide the @deprecated directive if representing deprecated portions of the schema.
https://graphql.github.io/graphql-spec/June2018/#sec-Type-System.Directives
TypeSystemDirectiveLocation: one of
- SCHEMA
- SCALAR
- OBJECT
- FIELD_DEFINITION
- ARGUMENT_DEFINITION
- INTERFACE
- UNION
- ENUM
- ENUM_VALUE
- INPUT_OBJECT
- INPUT_FIELD_DEFINITION
TODO
- [ ] SDL parser supports directive definition
- [ ] morpheus applies this directives to morpheus schema
- [ ] user has api to define directives with plain Haskell, without any TH
apollo api
https://www.apollographql.com/docs/graphql-tools/schema-directives/
To implement a schema directive using SchemaDirectiveVisitor, simply create a subclass of SchemaDirectiveVisitor that overrides one or more of the following visitor methods:
visitSchema(schema: GraphQLSchema)
visitScalar(scalar: GraphQLScalarType)
visitObject(object: GraphQLObjectType)
visitFieldDefinition(field: GraphQLField<any, any>)
visitArgumentDefinition(argument: GraphQLArgument)
visitInterface(iface: GraphQLInterfaceType)
visitUnion(union: GraphQLUnionType)
visitEnum(type: GraphQLEnumType)
visitEnumValue(value: GraphQLEnumValue)
visitInputObject(object: GraphQLInputObjectType)
visitInputFieldDefinition(field: GraphQLInputField)
probable morpheus api
type family ValueBy ( loc :: TypeSystemDirectiveLocation) :: *
type instance FIELD_DEFINITION = DataField
type ...
class TypeSystemDirective (location:: TypeSystemDirectiveLocation ) directive where
applyDSL :: directive -> ValueBy location -> Validation (ValueBy location)
so user can define
data Deprecation = Deprecation { reason :: Maybe Text }
instance TypeSystemDirective (location:: TypeSystemDirectiveLocation ) MyDeprecation where
applyDSL Deprecation { reason } field = field { fieldDeprecationReason = reason }
goal
https://www.apollographql.com/docs/graphql-tools/schema-directives/
const typeDefs = `
directive @rest(url: String) on FIELD_DEFINITION
type Query {
people: [Person] @rest(url: "/api/v1/people")
}`;
class RestDirective extends SchemaDirectiveVisitor {
public visitFieldDefinition(field) {
const { url } = this.args;
field.resolve = () => fetch(url);
}
}
const schema = makeExecutableSchema({
typeDefs,
schemaDirectives: {
rest: RestDirective
}
});
Explore supporting extension fields on AST.
data TypeDefinition (a :: TypeCategory) (s :: Stage) = TypeDefinition
{ ....
typeExtensions :: Maybe JSON.Value
}
deriving (Show, Lift, Eq)
data FieldDefinition (cat :: TypeCategory) (s :: Stage) = FieldDefinition
{ ....
fieldExtensions :: Maybe JSON.Value
}
deriving (Show, Lift, Eq)
https://www.graphql-tools.com/docs/schema-directives/
we can define type class DIRECTIVE_LOCATION to allow specific Locations to Directive resolvers
type family DIRECTIVE_LOCATION a (l :: DIrectiveLocation) :: Bool
for example
type instance DIRECTIVE_LOCATION User 'FIELD = 'True
type instance DIRECTIVE_LOCATION User 'TYPE = 'False
that way we can restrict writing resolver function for TYPE on User
type family DIrRes a (l :: Bool) where
DirRes a 'True = a -> GQLResult a
DirRes a 'False = ()
finally
class GQLDirective a where
mapType :: a -> DirRes TypeDefinition (DIRECTIVE_LOCATION 'TYPE)
mapField :: a -> DirRes FieldDefinition (DIRECTIVE_LOCATION 'FIELD)