func executeOperation(p ExecuteOperationParams) *Result { operationType, err := getOperationRootType(p.ExecutionContext.Schema, p.Operation) if err != nil { return &Result{Errors: gqlerrors.FormatErrors(err)} } fields := collectFields(CollectFieldsParams{ ExeContext: p.ExecutionContext, OperationType: operationType, SelectionSet: p.Operation.GetSelectionSet(), }) executeFieldsParams := ExecuteFieldsParams{ ExecutionContext: p.ExecutionContext, ParentType: operationType, Source: p.Root, Fields: fields, } if p.Operation.GetOperation() == "mutation" { return executeFieldsSerially(executeFieldsParams) } else { return executeFields(executeFieldsParams) } }
func Do(p Params) *Result { source := source.NewSource(&source.Source{ Body: []byte(p.RequestString), Name: "GraphQL request", }) AST, err := parser.Parse(parser.ParseParams{Source: source}) if err != nil { return &Result{ Errors: gqlerrors.FormatErrors(err), } } validationResult := ValidateDocument(&p.Schema, AST, nil) if !validationResult.IsValid { return &Result{ Errors: validationResult.Errors, } } return Execute(ExecuteParams{ Schema: p.Schema, Root: p.RootObject, AST: AST, OperationName: p.OperationName, Args: p.VariableValues, Context: p.Context, }) }
func visitUsingRules(schema *Schema, astDoc *ast.Document, rules []ValidationRuleFn) (errors []gqlerrors.FormattedError) { typeInfo := NewTypeInfo(schema) context := NewValidationContext(schema, astDoc, typeInfo) var visitInstance func(astNode ast.Node, instance *ValidationRuleInstance) visitInstance = func(astNode ast.Node, instance *ValidationRuleInstance) { visitor.Visit(astNode, &visitor.VisitorOptions{ Enter: func(p visitor.VisitFuncParams) (string, interface{}) { var action = visitor.ActionNoChange var result interface{} switch node := p.Node.(type) { case ast.Node: // Collect type information about the current position in the AST. typeInfo.Enter(node) // Do not visit top level fragment definitions if this instance will // visit those fragments inline because it // provided `visitSpreadFragments`. kind := node.GetKind() if kind == kinds.FragmentDefinition && p.Key != nil && instance.VisitSpreadFragments == true { return visitor.ActionSkip, nil } // Get the visitor function from the validation instance, and if it // exists, call it with the visitor arguments. enterFn := visitor.GetVisitFn(instance.VisitorOpts, false, kind) if enterFn != nil { action, result = enterFn(p) } // If the visitor returned an error, log it and do not visit any // deeper nodes. if err, ok := result.(error); ok && err != nil { errors = append(errors, gqlerrors.FormatError(err)) action = visitor.ActionSkip } if err, ok := result.([]error); ok && err != nil { errors = append(errors, gqlerrors.FormatErrors(err...)...) action = visitor.ActionSkip } // If any validation instances provide the flag `visitSpreadFragments` // and this node is a fragment spread, visit the fragment definition // from this point. if action == visitor.ActionNoChange && result == nil && instance.VisitSpreadFragments == true && kind == kinds.FragmentSpread { node, _ := node.(*ast.FragmentSpread) name := node.Name nameVal := "" if name != nil { nameVal = name.Value } fragment := context.Fragment(nameVal) if fragment != nil { visitInstance(fragment, instance) } } // If the result is "false" (ie action === Action.Skip), we're not visiting any descendent nodes, // but need to update typeInfo. if action == visitor.ActionSkip { typeInfo.Leave(node) } } return action, result }, Leave: func(p visitor.VisitFuncParams) (string, interface{}) { var action = visitor.ActionNoChange var result interface{} switch node := p.Node.(type) { case ast.Node: kind := node.GetKind() // Get the visitor function from the validation instance, and if it // exists, call it with the visitor arguments. leaveFn := visitor.GetVisitFn(instance.VisitorOpts, true, kind) if leaveFn != nil { action, result = leaveFn(p) } // If the visitor returned an error, log it and do not visit any // deeper nodes. if err, ok := result.(error); ok && err != nil { errors = append(errors, gqlerrors.FormatError(err)) action = visitor.ActionSkip } if err, ok := result.([]error); ok && err != nil { errors = append(errors, gqlerrors.FormatErrors(err...)...) action = visitor.ActionSkip } // Update typeInfo. typeInfo.Leave(node) } return action, result }, }, nil) } instances := []*ValidationRuleInstance{} for _, rule := range rules { instance := rule(context) instances = append(instances, instance) } for _, instance := range instances { visitInstance(astDoc, instance) } return errors }