Exemplo n.º 1
0
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)
	}
}
Exemplo n.º 2
0
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,
	})
}
Exemplo n.º 3
0
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
}