forked from graphql-go/graphql
-
Notifications
You must be signed in to change notification settings - Fork 0
/
directives.go
113 lines (100 loc) · 3.04 KB
/
directives.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package graphql
const (
DirectiveLocationQuery = "QUERY"
DirectiveLocationMutation = "MUTATION"
DirectiveLocationSubscription = "SUBSCRIPTION"
DirectiveLocationField = "FIELD"
DirectiveLocationFragmentDefinition = "FRAGMENT_DEFINITION"
DirectiveLocationFragmentSpread = "FRAGMENT_SPREAD"
DirectiveLocationInlineFragment = "INLINE_FRAGMENT"
)
// Directive structs are used by the GraphQL runtime as a way of modifying execution
// behavior. Type system creators will usually not create these directly.
type Directive struct {
Name string `json:"name"`
Description string `json:"description"`
Locations []string `json:"locations"`
Args []*Argument `json:"args"`
err error
}
// DirectiveConfig options for creating a new GraphQLDirective
type DirectiveConfig struct {
Name string `json:"name"`
Description string `json:"description"`
Locations []string `json:"locations"`
Args FieldConfigArgument `json:"args"`
}
func NewDirective(config DirectiveConfig) *Directive {
dir := &Directive{}
// Ensure directive is named
err := invariant(config.Name != "", "Directive must be named.")
if err != nil {
dir.err = err
return dir
}
// Ensure directive name is valid
err = assertValidName(config.Name)
if err != nil {
dir.err = err
return dir
}
// Ensure locations are provided for directive
err = invariant(len(config.Locations) > 0, "Must provide locations for directive.")
if err != nil {
dir.err = err
return dir
}
args := []*Argument{}
for argName, argConfig := range config.Args {
err := assertValidName(argName)
if err != nil {
dir.err = err
return dir
}
args = append(args, &Argument{
PrivateName: argName,
PrivateDescription: argConfig.Description,
Type: argConfig.Type,
DefaultValue: argConfig.DefaultValue,
})
}
dir.Name = config.Name
dir.Description = config.Description
dir.Locations = config.Locations
dir.Args = args
return dir
}
// IncludeDirective is used to conditionally include fields or fragments
var IncludeDirective = NewDirective(DirectiveConfig{
Name: "include",
Description: "Directs the executor to include this field or fragment only when " +
"the `if` argument is true.",
Locations: []string{
DirectiveLocationField,
DirectiveLocationFragmentSpread,
DirectiveLocationInlineFragment,
},
Args: FieldConfigArgument{
"if": &ArgumentConfig{
Type: NewNonNull(Boolean),
Description: "Included when true.",
},
},
})
// SkipDirective Used to conditionally skip (exclude) fields or fragments
var SkipDirective = NewDirective(DirectiveConfig{
Name: "skip",
Description: "Directs the executor to skip this field or fragment when the `if` " +
"argument is true.",
Args: FieldConfigArgument{
"if": &ArgumentConfig{
Type: NewNonNull(Boolean),
Description: "Skipped when true.",
},
},
Locations: []string{
DirectiveLocationField,
DirectiveLocationFragmentSpread,
DirectiveLocationInlineFragment,
},
})