File tree Expand file tree Collapse file tree 6 files changed +158
-2
lines changed
examples/custom-directives Expand file tree Collapse file tree 6 files changed +158
-2
lines changed Original file line number Diff line number Diff line change
1
+ # custom-directive
2
+
3
+ This directory contains a simple GraphQL with custom directives example based on ` graphql-yoga ` .
4
+
5
+ ## Get started
6
+
7
+ ** Clone the repository:**
8
+
9
+ ``` sh
10
+ git clone https://github.com/graphcool/graphql-yoga/
11
+ cd graphql-yoga/examples/custom-directives
12
+ ```
13
+
14
+ ** Install dependencies and run the app:**
15
+
16
+ ``` sh
17
+ yarn install # or npm install
18
+ yarn start # or npm start
19
+ ```
20
+
21
+ ## Testing
22
+
23
+ Open your browser at [ http://localhost:4000 ] ( http://localhost:4000 ) and start sending queries.
24
+
25
+ ** Query ` hello ` :**
26
+
27
+ ``` graphql
28
+ query {
29
+ hello
30
+ }
31
+ ```
32
+
33
+ The server returns the following response:
34
+
35
+ ``` json
36
+ {
37
+ "data" : {
38
+ "hello" : " HELLO WORD"
39
+ }
40
+ }
41
+ ```
42
+
43
+ Note that the original ` Hello Word ` output from the resolver is now in upper case due to our custom ` @upper ` directive.
44
+
45
+ ** Query ` secret ` (with role set as ` admin ` ):**
46
+ ``` graphql
47
+ query {
48
+ secret
49
+ }
50
+ ```
51
+
52
+ The server returns the following response:
53
+
54
+ ``` json
55
+ {
56
+ "data" : {
57
+ "secret" : " This is very secret"
58
+ }
59
+ }
60
+ ```
61
+
62
+
63
+ ** Query ` secret ` (with role set as ` user ` ):**
64
+
65
+ Go to ` index.js:45 ` , change ` admin ` by ` user ` and reload the server.
66
+
67
+ ``` graphql
68
+ query {
69
+ secret
70
+ }
71
+ ```
72
+
73
+ The server returns the following response:
74
+
75
+ ``` json
76
+ {
77
+ "data" : {
78
+ "secret" : null
79
+ },
80
+ "errors" : [
81
+ {
82
+ "message" : " You are not authorized. Expected roles: admin" ,
83
+ "locations" : [
84
+ {
85
+ "line" : 1 ,
86
+ "column" : 2
87
+ }
88
+ ],
89
+ "path" : [
90
+ " secret"
91
+ ]
92
+ }
93
+ ]
94
+ }
95
+ ```
Original file line number Diff line number Diff line change
1
+ const { GraphQLServer } = require ( "graphql-yoga" ) ;
2
+
3
+ const typeDefs = `
4
+ directive @upper on FIELD_DEFINITION
5
+ directive @auth(roles: [String]) on FIELD_DEFINITION
6
+
7
+ type Query {
8
+ hello: String! @upper
9
+ secret: String @auth(roles: ["admin"])
10
+ }
11
+ ` ;
12
+
13
+ const directiveResolvers = {
14
+ upper ( next , src , args , context ) {
15
+ return next ( ) . then ( str => str . toUpperCase ( ) ) ;
16
+ } ,
17
+ auth ( next , src , args , context ) {
18
+ const { roles } = context ; // We asume has roles of current user in context;
19
+ const expectedRoles = args . roles || [ ] ;
20
+ if (
21
+ expectedRoles . length === 0 || expectedRoles . some ( r => roles . includes ( r ) )
22
+ ) {
23
+ // Call next to continues process resolver.
24
+ return next ( ) ;
25
+ }
26
+
27
+ // We has two options here. throw an error or return null (if field is nullable).
28
+ throw new Error (
29
+ `You are not authorized. Expected roles: ${ expectedRoles . join ( ", " ) } `
30
+ ) ;
31
+ }
32
+ } ;
33
+
34
+ const resolvers = {
35
+ Query : {
36
+ hello : ( ) => `Hello World` ,
37
+ secret : ( ) => `This is very secret`
38
+ }
39
+ } ;
40
+
41
+ const server = new GraphQLServer ( {
42
+ typeDefs,
43
+ resolvers,
44
+ directiveResolvers,
45
+ context : ( ) => ( { roles : [ "admin" ] } )
46
+ } ) ;
47
+
48
+ server . start ( ( ) => console . log ( "Server is running on localhost:4000" ) ) ;
Original file line number Diff line number Diff line change
1
+ {
2
+ "scripts" : {
3
+ "start" : " node ."
4
+ },
5
+ "dependencies" : {
6
+ "graphql-yoga" : " 1.2.0"
7
+ }
8
+ }
Original file line number Diff line number Diff line change @@ -53,7 +53,7 @@ export class GraphQLServer {
53
53
if ( props . schema ) {
54
54
this . executableSchema = props . schema
55
55
} else if ( props . typeDefs && props . resolvers ) {
56
- let { typeDefs, resolvers } = props
56
+ let { directiveResolvers , typeDefs, resolvers } = props
57
57
58
58
// read from .graphql file if path provided
59
59
if ( typeDefs . endsWith ( 'graphql' ) ) {
@@ -70,6 +70,7 @@ export class GraphQLServer {
70
70
? { Upload : GraphQLUpload }
71
71
: { }
72
72
this . executableSchema = makeExecutableSchema ( {
73
+ directiveResolvers,
73
74
typeDefs,
74
75
resolvers : {
75
76
...uploadMixin ,
Original file line number Diff line number Diff line change @@ -26,7 +26,7 @@ export class GraphQLServerLambda {
26
26
if ( props . schema ) {
27
27
this . executableSchema = props . schema
28
28
} else if ( props . typeDefs && props . resolvers ) {
29
- let { typeDefs, resolvers } = props
29
+ let { directiveResolvers , typeDefs, resolvers } = props
30
30
31
31
// read from .graphql file if path provided
32
32
if ( typeDefs . endsWith ( 'graphql' ) ) {
@@ -42,6 +42,7 @@ export class GraphQLServerLambda {
42
42
}
43
43
44
44
this . executableSchema = makeExecutableSchema ( {
45
+ directiveResolvers,
45
46
typeDefs,
46
47
resolvers,
47
48
} )
Original file line number Diff line number Diff line change 8
8
GraphQLTypeResolver ,
9
9
ValidationContext ,
10
10
} from 'graphql'
11
+ import { IDirectiveResolvers } from 'graphql-tools/dist/Interfaces'
11
12
import { SubscriptionOptions } from 'graphql-subscriptions/dist/subscriptions-manager'
12
13
import { LogFunction } from 'apollo-server-core'
13
14
@@ -68,13 +69,15 @@ export interface Options extends ApolloServerOptions {
68
69
}
69
70
70
71
export interface Props {
72
+ directiveResolvers ?: IDirectiveResolvers < any , any >
71
73
typeDefs ?: string
72
74
resolvers ?: IResolvers
73
75
schema ?: GraphQLSchema
74
76
context ?: Context | ContextCallback
75
77
}
76
78
77
79
export interface LambdaProps {
80
+ directiveResolvers ?: IDirectiveResolvers < any , any >
78
81
typeDefs ?: string
79
82
resolvers ?: IResolvers
80
83
schema ?: GraphQLSchema
You can’t perform that action at this time.
0 commit comments