|
1 | 1 | /* |
2 | | -package operation_complexity implements two common algorithms used by GitHub to calculate GraphQL query complexity |
| 2 | +Package operation_complexity implements two common algorithms used by GitHub to calculate |
| 3 | +GraphQL query complexity: |
3 | 4 |
|
4 | | -1. Node count, the maximum number of Nodes a query may return |
5 | | -2. Complexity, the maximum number of Node requests that might be needed to execute the query |
| 5 | + 1. Node count, the maximum number of Nodes a query may return |
| 6 | + 2. Complexity, the maximum number of Node requests that might be needed to execute the query |
6 | 7 |
|
7 | | -OperationComplexityEstimator takes a schema definition and a query and then walks recursively through the query to calculate both variables. |
| 8 | +OperationComplexityEstimator takes a schema definition and a query and then |
| 9 | +walks recursively through the query to calculate both variables. |
8 | 10 |
|
9 | | -The calculation can be influenced by integer arguments on fields that indicate the amount of Nodes returned by a field. |
| 11 | +The calculation can be influenced by integer arguments on fields that indicate |
| 12 | +the number of Nodes returned by a field. |
10 | 13 |
|
11 | | -To help the algorithm understand your schema you could make use of these two directives: |
| 14 | +To help the algorithm understand the schema make use of these two directives: |
12 | 15 |
|
13 | | -- directive @nodeCountMultiply on ARGUMENT_DEFINITION |
14 | | -- directive @nodeCountSkip on FIELD |
| 16 | + - directive @nodeCountMultiply on ARGUMENT_DEFINITION |
| 17 | + - directive @nodeCountSkip on FIELD |
15 | 18 |
|
16 | | -nodeCountMultiply: |
17 | | -Indicates that the Int value the directive is applied on should be used as a Node multiplier |
| 19 | +"nodeCountMultiply" indicates that the Int value the directive is applied on |
| 20 | +should be used as a Node multiplier. |
18 | 21 |
|
19 | | -nodeCountSkip: |
20 | | -Indicates that the algorithm should skip this Node. This is useful to whitelist certain query paths, e.g. for introspection. |
| 22 | +"nodeCountSkip" indicates that the algorithm should skip this Node. |
| 23 | +It can be used to allowlist certain query paths. |
| 24 | +
|
| 25 | +Note: Introspection fields (__schema and __type) are automatically skipped |
| 26 | +from complexity calculations by default. |
21 | 27 | */ |
22 | 28 | package operation_complexity |
23 | 29 |
|
|
45 | 51 | nodeCountSkip = []byte("nodeCountSkip") |
46 | 52 | ) |
47 | 53 |
|
| 54 | +const ( |
| 55 | + skipIntrospection = true |
| 56 | + __schemaLiteral = "__schema" |
| 57 | + __typeLiteral = "__type" |
| 58 | +) |
| 59 | + |
48 | 60 | type OperationComplexityEstimator struct { |
49 | 61 | walker *astvisitor.Walker |
50 | 62 | visitor *complexityVisitor |
@@ -184,12 +196,16 @@ func (c *complexityVisitor) EnterField(ref int) { |
184 | 196 | return |
185 | 197 | } |
186 | 198 |
|
187 | | - if _, exits := c.definition.FieldDefinitionDirectiveByName(definition, nodeCountSkip); exits { |
| 199 | + if _, skip := c.definition.FieldDefinitionDirectiveByName(definition, nodeCountSkip); skip { |
188 | 200 | c.SkipNode() |
189 | 201 | return |
190 | 202 | } |
191 | 203 |
|
192 | 204 | typeName, fieldName, alias := c.extractFieldRelatedNames(ref, definition) |
| 205 | + if skipIntrospection && (fieldName == __schemaLiteral || fieldName == __typeLiteral) { |
| 206 | + c.SkipNode() |
| 207 | + return |
| 208 | + } |
193 | 209 | if c.isRootType(typeName) { |
194 | 210 | c.resetCurrentRootFieldComplexity(typeName, fieldName, alias) |
195 | 211 | } |
|
0 commit comments