1package graphql
2
3const (
4 // Operations
5 DirectiveLocationQuery = "QUERY"
6 DirectiveLocationMutation = "MUTATION"
7 DirectiveLocationSubscription = "SUBSCRIPTION"
8 DirectiveLocationField = "FIELD"
9 DirectiveLocationFragmentDefinition = "FRAGMENT_DEFINITION"
10 DirectiveLocationFragmentSpread = "FRAGMENT_SPREAD"
11 DirectiveLocationInlineFragment = "INLINE_FRAGMENT"
12
13 // Schema Definitions
14 DirectiveLocationSchema = "SCHEMA"
15 DirectiveLocationScalar = "SCALAR"
16 DirectiveLocationObject = "OBJECT"
17 DirectiveLocationFieldDefinition = "FIELD_DEFINITION"
18 DirectiveLocationArgumentDefinition = "ARGUMENT_DEFINITION"
19 DirectiveLocationInterface = "INTERFACE"
20 DirectiveLocationUnion = "UNION"
21 DirectiveLocationEnum = "ENUM"
22 DirectiveLocationEnumValue = "ENUM_VALUE"
23 DirectiveLocationInputObject = "INPUT_OBJECT"
24 DirectiveLocationInputFieldDefinition = "INPUT_FIELD_DEFINITION"
25)
26
27// DefaultDeprecationReason Constant string used for default reason for a deprecation.
28const DefaultDeprecationReason = "No longer supported"
29
30// SpecifiedRules The full list of specified directives.
31var SpecifiedDirectives = []*Directive{
32 IncludeDirective,
33 SkipDirective,
34 DeprecatedDirective,
35}
36
37// Directive structs are used by the GraphQL runtime as a way of modifying execution
38// behavior. Type system creators will usually not create these directly.
39type Directive struct {
40 Name string `json:"name"`
41 Description string `json:"description"`
42 Locations []string `json:"locations"`
43 Args []*Argument `json:"args"`
44
45 err error
46}
47
48// DirectiveConfig options for creating a new GraphQLDirective
49type DirectiveConfig struct {
50 Name string `json:"name"`
51 Description string `json:"description"`
52 Locations []string `json:"locations"`
53 Args FieldConfigArgument `json:"args"`
54}
55
56func NewDirective(config DirectiveConfig) *Directive {
57 dir := &Directive{}
58
59 // Ensure directive is named
60 err := invariant(config.Name != "", "Directive must be named.")
61 if err != nil {
62 dir.err = err
63 return dir
64 }
65
66 // Ensure directive name is valid
67 err = assertValidName(config.Name)
68 if err != nil {
69 dir.err = err
70 return dir
71 }
72
73 // Ensure locations are provided for directive
74 err = invariant(len(config.Locations) > 0, "Must provide locations for directive.")
75 if err != nil {
76 dir.err = err
77 return dir
78 }
79
80 args := []*Argument{}
81
82 for argName, argConfig := range config.Args {
83 err := assertValidName(argName)
84 if err != nil {
85 dir.err = err
86 return dir
87 }
88 args = append(args, &Argument{
89 PrivateName: argName,
90 PrivateDescription: argConfig.Description,
91 Type: argConfig.Type,
92 DefaultValue: argConfig.DefaultValue,
93 })
94 }
95
96 dir.Name = config.Name
97 dir.Description = config.Description
98 dir.Locations = config.Locations
99 dir.Args = args
100 return dir
101}
102
103// IncludeDirective is used to conditionally include fields or fragments.
104var IncludeDirective = NewDirective(DirectiveConfig{
105 Name: "include",
106 Description: "Directs the executor to include this field or fragment only when " +
107 "the `if` argument is true.",
108 Locations: []string{
109 DirectiveLocationField,
110 DirectiveLocationFragmentSpread,
111 DirectiveLocationInlineFragment,
112 },
113 Args: FieldConfigArgument{
114 "if": &ArgumentConfig{
115 Type: NewNonNull(Boolean),
116 Description: "Included when true.",
117 },
118 },
119})
120
121// SkipDirective Used to conditionally skip (exclude) fields or fragments.
122var SkipDirective = NewDirective(DirectiveConfig{
123 Name: "skip",
124 Description: "Directs the executor to skip this field or fragment when the `if` " +
125 "argument is true.",
126 Args: FieldConfigArgument{
127 "if": &ArgumentConfig{
128 Type: NewNonNull(Boolean),
129 Description: "Skipped when true.",
130 },
131 },
132 Locations: []string{
133 DirectiveLocationField,
134 DirectiveLocationFragmentSpread,
135 DirectiveLocationInlineFragment,
136 },
137})
138
139// DeprecatedDirective Used to declare element of a GraphQL schema as deprecated.
140var DeprecatedDirective = NewDirective(DirectiveConfig{
141 Name: "deprecated",
142 Description: "Marks an element of a GraphQL schema as no longer supported.",
143 Args: FieldConfigArgument{
144 "reason": &ArgumentConfig{
145 Type: String,
146 Description: "Explains why this element was deprecated, usually also including a " +
147 "suggestion for how to access supported similar data. Formatted" +
148 "in [Markdown](https://daringfireball.net/projects/markdown/).",
149 DefaultValue: DefaultDeprecationReason,
150 },
151 },
152 Locations: []string{
153 DirectiveLocationFieldDefinition,
154 DirectiveLocationEnumValue,
155 },
156})