Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
import {
parse,
TypeInfo,
ValidationContext,
visit,
visitWithTypeInfo,
getNamedType,
OperationDefinitionNode,
FieldNode,
GraphQLSchema,
SelectionNode,
DocumentNode,
DefinitionNode,
GraphQLNamedType,
} from 'graphql'
import createCostAnalysis from 'graphql-cost-analysis'
import { GraphQLRequestContext } from 'apollo-server-core'
import { Logger } from 'pino'
interface CostInput {
requestContext: GraphQLRequestContext
schema: GraphQLSchema
}
export class QueryCostAnalyzerService {
errorMessage = 'The query exceeds the maximum cost'
constructor() {}
buildAnalyzer(variables) {
return createCostAnalysis({
maximumCost: 1000, // to be determined
variables: variables,
defaultCost: 1, // let's just blanket cost every field with this value for now
onComplete: cost => {
console.log(`graphql-cost-analysis cost for request was ${cost}`) // in prod we wouldn't have a console log here
},
})
}
// do some graphQL things to calculate the cost
getCost({requestContext, schema}: CostInput ): number {
const typeInfo = new TypeInfo(schema)
if (!requestContext.source) {
return 0
}
const ast = parse(requestContext.source)
const onBudgetExceeded = () => { } // leaving this blank for now
const validationContext = new ValidationContext(
schema,
ast,
typeInfo,
onBudgetExceeded
)
const analysisVisitor = this.buildAnalyzer(
requestContext.request.variables,
)(validationContext)
// Unfortunately not functional approach
// Go through AST and register all costs
visit(ast, visitWithTypeInfo(typeInfo, analysisVisitor))
return analysisVisitor.cost || 0
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment