func newContext( schema typs.QLSchema, documentAST *lang.Document, rootValue interface{}, rawVariableValues map[string]interface{}, operationName string, ) *_Context { operations := make(map[string]*lang.OperationDefinition) fragments := make(map[string]*lang.FragmentDefinition) for _, statement := range documentAST.Definitions { switch statement := statement.(type) { case *lang.OperationDefinition: name := "" if statement.Name != nil { name = statement.Name.Value } operations[name] = statement case *lang.FragmentDefinition: fragments[statement.Name.Value] = statement default: panic(lang.NewQLError( fmt.Sprintf(`Cannot execute a request containing a %v.`, statement.Kind()), []lang.INode{statement})) } } if operationName != "" && len(operations) != 1 { panic(lang.NewQLError(`Must provide operation name if query contains multiple operations.`, nil)) } if operationName == "" { for name := range operations { operationName = name } } operation, ok := operations[operationName] if !ok { panic(lang.NewQLError( fmt.Sprintf(`Unknown operation named "%v".`, operationName), nil)) } variableValues := GetVariableValues(schema, operation.VariableDefinitions, rawVariableValues) return &_Context{ Schema: schema, Fragments: fragments, RootValue: rootValue, Operation: operation, VariableValues: variableValues, Errors: nil, } }
func getOperationRootType( schema typs.QLSchema, operation *lang.OperationDefinition, ) *typs.QLObject { switch operation.Operation { case lang.OperationQuery: return schema.GetQueryType() case lang.OperationMutation: murationType := schema.GetMutationType() if murationType == nil { panic(lang.NewQLError( "Schema is not configured for mutations", []lang.INode{operation})) } return murationType default: panic(lang.NewQLError( "Can only execute queries and mutation", []lang.INode{operation})) } }
func (c *_Context) completeValue( returnType typs.QLType, fieldASTs []*lang.Field, info typs.QLResolveInfo, result interface{}, ) interface{} { if returnType, ok := returnType.(*typs.QLNonNull); ok { completed := c.completeValue(returnType.OfType, fieldASTs, info, result) if completed == nil { nodes := make([]lang.INode, len(fieldASTs)) for i, node := range fieldASTs { nodes[i] = node } panic(lang.NewQLError( fmt.Sprintf( `Cannot return null for non-nullable field %v.%v.`, info.ParentType, info.FieldName), nodes)) } return completed } v := reflect.ValueOf(result) if result == nil { return nil } v = reflect.Indirect(v) t := v.Type() switch returnType := returnType.(type) { case *typs.QLList: if t.Kind() == reflect.Slice || t.Kind() == reflect.Array { itemType := returnType.OfType list := make([]interface{}, t.NumField()) for i, n := 0, t.NumField(); i < n; i++ { list[i] = c.completeValueCatchingError(itemType, fieldASTs, info, v.Field(i).Interface()) } return list } panic("User Error: expected array of slice, but did not find one.") case *typs.QLScalar: if returnType.Serialize == nil { panic("Missing serialize method on type") } serializedResult := returnType.Serialize(result) if serializedResult == nil { return nil } return serializedResult case *typs.QLEnum: return returnType.Serialize(result) case *typs.QLObject: runtimeType := returnType subFieldASTs := map[string][]*lang.Field{} visitedFragmentNames := map[string]struct{}{} for _, fieldAST := range fieldASTs { selectionSet := fieldAST.SelectionSet if selectionSet != nil { subFieldASTs = c.collectFields(runtimeType, selectionSet, subFieldASTs, visitedFragmentNames) } } return c.executeFields(runtimeType, result, subFieldASTs) case typs.QLAbstractType: panic("not implemented") default: panic("unreachable") } }