UNPKG

4.06 kBMarkdownView Raw
1# Draft specification for GraphQL Schema Decorators
2
3Decorators can be used to modify a GraphQL schema behavior, somewhat similar to directives
4which modify the way a GraphQL server executes a query.
5
6The intent of schema decorators is to make GraphQL schemas more malleable without the need
7for modifying the current spec. Decorators don't enable anything that wasn't possible before,
8but they make some common patterns much more reusable.
9
10Decorators can be used for a variety of purposes:
11* Authorization
12* Argument validation
13* Filtering of results
14* Logging & profiling
15* Error handling
16* Backend connectors
17
18Here is an example of decorators on a schema specified with GraphQL schema language:
19```
20@connector(storage: "mongoDB")
21@id(fields: ["uuid"])
22type Person {
23 uuid: String!
24 name: String!
25
26 @deprecationReason(reason: "Use the 'name' field instead")
27 longName: String
28 friends: [Person]
29}
30
31type RootQuery {
32 @description(text: "find a person by name")
33 findPerson(name: String!)
34
35 @adminOnly
36 @log(type: "adminAccess")
37 allPersons(
38 page: Int = 0
39
40 @validateRange(min: 1, max: 10)
41 numPages: Int = 1
42 ): [Person]
43}
44
45type RootMutation {
46 @requiresAuthentication
47 @log(type: "userAccess")
48 addPerson(
49 @maxLen(100)
50 name: String!
51 ): Int
52
53 @adminOnly
54 @log(type: "adminAccess")
55 removePerson(id: Int!): Boolean
56}
57
58schema {
59 query: RootQuery
60 mutation: RootMutation
61}
62```
63
64In GraphQL schema language, arguments to decorators follow the same spec as arguments to fields.
65
66## What decorators do:
67Decorators can be selectively applied to:
68* The schema
69* A specific type (object type, union, interface, input, scalar)
70* A specific field
71* An argument
72
73Decorators can modify the behavior of the parts of the schema they are applied to. Sometimes that requires modifying other parts of the schema. For instance, the @validateRange decorator modifies the behavior of the containing field's resolve function.
74
75In general, decorators either add, remove or modify an attribute of the thing they wrap. The most common type of decorator (e.g. @adminOnly, @log, @connector) will wrap one or more field's resolve functions to alter the execution behavior of the GraphQL schema, but other decorators (e.g. @description) may add attributes to a type, field or argument. It is also possible for a type decorator to add a field to the type (e.g. @id(fields: ["uuid"]) can add the __id field).
76
77
78## Schema decorator API
79All decorators must extend the SchemaDecorator class and implement the following interfaces:
80
81```
82class SampleTypeDecorator extends SchemaDecorator {
83 const tag = 'sample'; // matches @sample in GraphQL schema language
84 const scope = ['type', 'interface', 'union']; // where this decorator can be applied
85
86 constructor(args, prefix){
87 this.args = args;
88 this.prefix = prefix;
89 }
90
91 getTag(){
92 return this.prefix + tag;
93 }
94
95 isInScope(typeName){
96 return scope.indexOf(typeName) >= 0;
97 }
98
99 // context says what scope this decorator is being applied to
100 apply(wrappedThing, { schema, type, field, context }){
101 // this.args ...
102 // ...
103 }
104
105}
106```
107
108## Applying decorators to a GraphQL-JS schema
109
110Schema decorators can also be applied to a GraphQL-JS schema. Here is an example:
111
112```
113import { Description, DeprecationReason, Validator } from 'graphql-decorators';
114// ... more imports ...
115
116const schema = new GraphQLSchema({
117 query: new GraphQLObjectType({
118 name: 'RootQuery',
119 decorators: [ new Description({ text: 'This is the root query' }) ],
120 fields: () => {
121 getString: {
122 type: GraphQLString,
123 decorators: [ new DeprecationReason({ text: 'This field never did anything useful' })],
124 resolve(root, {str}){ return str; },
125 args: {
126 str: {
127 type: GraphQLString,
128 decorators: [ new Validator({ type: 'length', min: 1, max: 1000 }) ]
129 },
130 },
131 },
132 },
133 }),
134});
135
136```
137
138To apply these decorators, the function `applySchemaDecorators(schema)` from the package `graphql-tools` can be used.
139