Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ Now that your global configuration is set, you can define the cost calculation f
| useMultipliers | Defines if the field's cost depends on the parent multipliers and field's multipliers. | Boolean | true | no |
| complexity | The level of complexity to resolve the current field. <br>If the field needs to call an expensive service to resolve itself, then the complexity should be at a high level but if the field is easy to resolve and not an expensive operation, the complexity should be at a low level. | Object {min: number, max: number} | {min: 1} | no |

### Default multipliers

It's possible to define `multipliers` as an object of the form `{limit: 100}`, where the number is the default value of the "limit" argument, used in cost analysis. This is different from adding a default value to the actual GraphQL argument, because it's only used for cost analysis. If the query happens to return more items, the result is not truncated.

## Defining the Cost Settings via Directives

To define the cost settings of fields for which you want a custom cost calculation, just add a `cost` directive to the concerned fields directly to your GraphQL schema.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "graphql-cost-analysis",
"version": "1.0.3",
"version": "1.1.0-smartdok1",
"description": "Graphql query cost analyzer. Use it to protect your GraphQL servers against DoS attacks, compute data consumption per user and limit it.",
"main": "dist/index.js",
"files": [
Expand Down
37 changes: 34 additions & 3 deletions src/costAnalysis.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import type {
DirectiveNode,
GraphQLNamedType,
ValueNode,
ObjectFieldNode,
ArgumentNode,
SelectionNode
} from 'graphql'
Expand Down Expand Up @@ -209,6 +210,22 @@ export default class CostAnalysis {
}
}

getMultipliersFromObjectNode (
objectNode: $ReadOnlyArray<ObjectFieldNode>,
fieldArgs: { [argument: string]: mixed }
) {
const multipliers = []
objectNode.forEach(field => {
if (field.value.kind === Kind.INT) {
multipliers.push([field.name.value, Number(field.value.value)])
} else {
multipliers.push(field.name.value)
}
})

return this.getMultipliersFromString(multipliers, fieldArgs)
}

getMultipliersFromListNode (
listNode: $ReadOnlyArray<ValueNode>,
fieldArgs: { [argument: string]: mixed }
Expand All @@ -224,19 +241,24 @@ export default class CostAnalysis {
}

getMultipliersFromString (
multipliers: Array<string> = [],
multipliers: Array<string | [string, number]> = [],
fieldArgs: { [argument: string]: mixed }
): Array<number> {
// get arguments values, convert to integer and delete 0 values from list
return multipliers
.map(multiplier => {
let defVal = 0
if (Array.isArray(multiplier)) {
defVal = multiplier[1]
multiplier = multiplier[0]
}
const value = selectn(multiplier, fieldArgs)

// if the argument is an array, the multiplier will be the length of it
if (Array.isArray(value)) {
return value.length
}
return Number(value) || 0
return Number(value) || defVal
})
.filter(multiplier => multiplier !== 0)
}
Expand Down Expand Up @@ -281,7 +303,16 @@ export default class CostAnalysis {
multipliersArg.value.values,
fieldArgs
)
: []
: (
multipliersArg &&
multipliersArg.value &&
multipliersArg.value.kind === Kind.OBJECT
? this.getMultipliersFromObjectNode(
multipliersArg.value.fields,
fieldArgs
)
: []
)

const multiplier: ?number =
multiplierArg && multiplierArg.value.value
Expand Down
2 changes: 1 addition & 1 deletion src/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// @flow
import CostAnalysis from './costAnalysis'
import type { CostAnalysisOptions } from './CostAnalysis'
import type { CostAnalysisOptions } from './costAnalysis'
import type {
ValidationContext
} from 'graphql'
Expand Down