public static void AddLocation(this ExecutionError error, AbstractNode abstractNode, Document document) { if (abstractNode != null) { if (document != null) { var location = new Location(new Source(document.OriginalQuery), abstractNode.SourceLocation.Start); error.AddLocation(location.Line, location.Column); } else if (abstractNode.SourceLocation.Line > 0 && abstractNode.SourceLocation.Column > 0) { error.AddLocation(abstractNode.SourceLocation.Line, abstractNode.SourceLocation.Column); } } }
/// <summary> /// Resolve simple fields in a performant manor /// </summary> private static object ResolveFieldFromData(ExecutionContext context, IObjectGraphType rootType, object source, FieldType fieldType, Field field, IEnumerable <string> path) { object result = null; try { if (fieldType.Resolver != null) { var rfc = new ResolveFieldContext(context, field, fieldType, source, rootType, null, path); result = fieldType.Resolver.Resolve(rfc); } else { result = NameFieldResolver.Resolve(source, field.Name); } if (result != null) { var scalarType = fieldType.ResolvedType as ScalarGraphType; result = scalarType?.Serialize(result); } } catch (Exception exc) { var error = new ExecutionError($"Error trying to resolve {field.Name}.", exc); error.AddLocation(field, context.Document); error.Path = path.ToList(); context.Errors.Add(error); } return(result); }
public object GetVariableValue(Document document, ISchema schema, VariableDefinition variable, object input) { var type = variable.Type.GraphTypeFromType(schema); if (IsValidValue(schema, type, input)) { if (input == null) { if (variable.DefaultValue != null) { return(ValueFromAst(variable.DefaultValue)); } } var coercedValue = CoerceValue(schema, type, input.AstFromValue(schema, type)); return(coercedValue); } if (input == null) { var error2 = new ExecutionError("Variable '${0}' of required type '{1}' was not provided.".ToFormat(variable.Name, type.Name ?? variable.Type.FullName())); error2.AddLocation(variable, document); throw error2; } var error = new ExecutionError("Variable '${0}' expected value of type '{1}'.".ToFormat(variable.Name, type?.Name ?? variable.Type.FullName())); error.AddLocation(variable, document); throw error; }
public static void AddLocation(this ExecutionError error, Field field) { if (field != null) { error.AddLocation(field.SourceLocation.Line, field.SourceLocation.Column); } }
private ResolveFieldResult <object> GenerateError(ResolveFieldResult <object> resolveResult, Field field, ExecutionContext context, Exception exc) { var error = new ExecutionError("Error trying to resolve {0}.".ToFormat(field.Name), exc); error.AddLocation(field, context.Document); context.Errors.Add(error); resolveResult.Skip = false; return(resolveResult); }
public static async Task <TResult> TryAsyncResolve <TResult>(this IResolveFieldContext context, Func <IResolveFieldContext, Task <TResult> > resolve, Func <ExecutionErrors, Task <TResult> > error = null) { try { return(await resolve(context).ConfigureAwait(false)); } catch (Exception ex) { if (error == null) { var er = new ExecutionError(ex.Message, ex); er.AddLocation(context.FieldAst, context.Document); er.Path = context.Path; context.Errors.Add(er); return(default);
/// <summary> /// Resolve lists in a performant manor /// </summary> private async Task <List <object> > ResolveListFromData(ExecutionContext context, object source, IObjectGraphType parentType, IGraphType graphType, Field field, IEnumerable <string> path) { var result = new List <object>(); var listInfo = graphType as ListGraphType; var subType = listInfo?.ResolvedType as IObjectGraphType; var data = source as IEnumerable; var visitedFragments = new List <string>(); var subFields = CollectFields(context, subType, field.SelectionSet, null, visitedFragments); if (data == null) { var error = new ExecutionError("User error: expected an IEnumerable list though did not find one."); error.AddLocation(field, context.Document); throw error; } var index = 0; foreach (var node in data) { var currentPath = path.Concat(new[] { $"{index++}" }); if (subType != null) { var nodeResult = await ExecuteFieldsAsync(context, subType, node, subFields, currentPath) .ConfigureAwait(false); result.Add(nodeResult); } else { var nodeResult = await CompleteValueAsync(context, parentType, listInfo?.ResolvedType, field, node, currentPath) .ConfigureAwait(false); result.Add(nodeResult); } } return(result); }
/// <summary> /// Resolve simple fields in a performant manor /// </summary> private static async Task <object> ResolveFieldFromDataAsync(ExecutionContext context, IObjectGraphType rootType, object source, FieldType fieldType, Field field, IEnumerable <string> path) { object result = null; try { if (fieldType.Resolver != null) { var rfc = new ResolveFieldContext(context, field, fieldType, source, rootType, null, path); result = fieldType.Resolver.Resolve(rfc); result = await UnwrapResultAsync(result) .ConfigureAwait(false); } else { result = NameFieldResolver.Resolve(source, field.Name); } if (result != null) { var scalarType = fieldType.ResolvedType as ScalarGraphType; result = scalarType?.Serialize(result); } } catch (Exception exc) { var error = new ExecutionError($"Error trying to resolve {field.Name}.", exc); error.AddLocation(field, context.Document); error.Path = path.ToList(); context.Errors.Add(error); // If there was an exception, the value of result cannot be trusted result = null; } return(result); }
public IObjectGraphType GetOperationRootType(Document document, ISchema schema, Operation operation) { IObjectGraphType type; ExecutionError error; switch (operation.OperationType) { case OperationType.Query: type = schema.Query; break; case OperationType.Mutation: type = schema.Mutation; if (type == null) { error = new ExecutionError("Schema is not configured for mutations"); error.AddLocation(operation, document); throw error; } break; case OperationType.Subscription: type = schema.Subscription; if (type == null) { error = new ExecutionError("Schema is not configured for subscriptions"); error.AddLocation(operation, document); throw error; } break; default: error = new ExecutionError("Can only execute queries, mutations and subscriptions."); error.AddLocation(operation, document); throw error; } return(type); }
public FieldType GetFieldDefinition(Document document, ISchema schema, IObjectGraphType parentType, Field field) { if (field.Name == SchemaIntrospection.SchemaMeta.Name && schema.Query == parentType) { return(SchemaIntrospection.SchemaMeta); } if (field.Name == SchemaIntrospection.TypeMeta.Name && schema.Query == parentType) { return(SchemaIntrospection.TypeMeta); } if (field.Name == SchemaIntrospection.TypeNameMeta.Name) { return(SchemaIntrospection.TypeNameMeta); } if (parentType == null) { var error = new ExecutionError($"Schema is not configured correctly to fetch {field.Name}. Are you missing a root type?"); error.AddLocation(field, document); throw error; } return(parentType.Fields.FirstOrDefault(f => f.Name == field.Name)); }
public async Task<object> CompleteValueAsync(ExecutionContext context, IGraphType fieldType, Fields fields, object result) { var field = fields != null ? fields.FirstOrDefault() : null; var fieldName = field != null ? field.Name : null; var nonNullType = fieldType as NonNullGraphType; if (nonNullType != null) { var type = nonNullType.ResolvedType; var completed = await CompleteValueAsync(context, type, fields, result).ConfigureAwait(false); if (completed == null) { var error = new ExecutionError("Cannot return null for non-null type. Field: {0}, Type: {1}!." .ToFormat(fieldName, type.Name)); error.AddLocation(field, context.Document); throw error; } return completed; } if (result == null) { return null; } if (fieldType is ScalarGraphType) { var scalarType = fieldType as ScalarGraphType; var coercedValue = scalarType.Serialize(result); return coercedValue; } if (fieldType is ListGraphType) { var list = result as IEnumerable; if (list == null) { var error = new ExecutionError("User error: expected an IEnumerable list though did not find one."); error.AddLocation(field, context.Document); throw error; } var listType = fieldType as ListGraphType; var itemType = listType.ResolvedType; var results = await list.MapAsync(async item => await CompleteValueAsync(context, itemType, fields, item).ConfigureAwait(false)).ConfigureAwait(false); return results; } var objectType = fieldType as IObjectGraphType; if (fieldType is IAbstractGraphType) { var abstractType = fieldType as IAbstractGraphType; objectType = abstractType.GetObjectType(result); if (objectType != null && !abstractType.IsPossibleType(objectType)) { var error = new ExecutionError( "Runtime Object type \"{0}\" is not a possible type for \"{1}\"" .ToFormat(objectType, abstractType)); error.AddLocation(field, context.Document); throw error; } } if (objectType == null) { return null; } if (objectType.IsTypeOf != null && !objectType.IsTypeOf(result)) { var error = new ExecutionError( "Expected value of type \"{0}\" but got: {1}." .ToFormat(objectType, result)); error.AddLocation(field, context.Document); throw error; } var subFields = new Dictionary<string, Fields>(); var visitedFragments = new List<string>(); fields.Apply(f => { subFields = CollectFields(context, objectType, f.SelectionSet, subFields, visitedFragments); }); return await ExecuteFieldsAsync(context, objectType, result, subFields).ConfigureAwait(false); }
public async Task <object> CompleteValueAsync(ExecutionContext context, IGraphType fieldType, Fields fields, object result) { var field = fields != null?fields.FirstOrDefault() : null; var fieldName = field != null ? field.Name : null; var nonNullType = fieldType as NonNullGraphType; if (nonNullType != null) { var type = nonNullType.ResolvedType; var completed = await CompleteValueAsync(context, type, fields, result).ConfigureAwait(false); if (completed == null) { var error = new ExecutionError("Cannot return null for non-null type. Field: {0}, Type: {1}!." .ToFormat(fieldName, type.Name)); error.AddLocation(field, context.Document); throw error; } return(completed); } if (result == null) { return(null); } if (fieldType is ScalarGraphType) { var scalarType = fieldType as ScalarGraphType; var coercedValue = scalarType.Serialize(result); return(coercedValue); } if (fieldType is ListGraphType) { var list = result as IEnumerable; if (list == null) { var error = new ExecutionError("User error: expected an IEnumerable list though did not find one."); error.AddLocation(field, context.Document); throw error; } var listType = fieldType as ListGraphType; var itemType = listType.ResolvedType; var results = await list.MapAsync(async item => await CompleteValueAsync(context, itemType, fields, item).ConfigureAwait(false)).ConfigureAwait(false); return(results); } var objectType = fieldType as IObjectGraphType; if (fieldType is IAbstractGraphType) { var abstractType = fieldType as IAbstractGraphType; objectType = abstractType.GetObjectType(result); if (objectType != null && !abstractType.IsPossibleType(objectType)) { var error = new ExecutionError( "Runtime Object type \"{0}\" is not a possible type for \"{1}\"" .ToFormat(objectType, abstractType)); error.AddLocation(field, context.Document); throw error; } } if (objectType == null) { return(null); } if (objectType.IsTypeOf != null && !objectType.IsTypeOf(result)) { var error = new ExecutionError( "Expected value of type \"{0}\" but got: {1}." .ToFormat(objectType, result)); error.AddLocation(field, context.Document); throw error; } var subFields = new Dictionary <string, Fields>(); var visitedFragments = new List <string>(); fields.Apply(f => { subFields = CollectFields(context, objectType, f.SelectionSet, subFields, visitedFragments); }); return(await ExecuteFieldsAsync(context, objectType, result, subFields).ConfigureAwait(false)); }
public async Task <object> CompleteValueAsync(ExecutionContext context, IObjectGraphType parentType, IGraphType fieldType, Field field, object result, IEnumerable <string> path) { var fieldName = field?.Name; var nonNullType = fieldType as NonNullGraphType; if (nonNullType != null) { var type = nonNullType.ResolvedType; var completed = await CompleteValueAsync(context, parentType, type, field, result, path).ConfigureAwait(false); if (completed == null) { var error = new ExecutionError("Cannot return null for non-null type. Field: {0}, Type: {1}!." .ToFormat(fieldName, type.Name)); error.AddLocation(field, context.Document); throw error; } return(completed); } if (result == null) { return(null); } if (fieldType is ScalarGraphType) { var scalarType = fieldType as ScalarGraphType; var coercedValue = scalarType.Serialize(result); return(coercedValue); } if (fieldType is ListGraphType) { var list = result as IEnumerable; if (list == null) { var error = new ExecutionError("User error: expected an IEnumerable list though did not find one."); error.AddLocation(field, context.Document); throw error; } var listType = fieldType as ListGraphType; var itemType = listType.ResolvedType; var results = await list .MapAsync(async (index, item) => await CompleteValueAsync(context, parentType, itemType, field, item, path.Concat(new[] { $"{index}" })).ConfigureAwait(false)) .ConfigureAwait(false); return(results); } var objectType = fieldType as IObjectGraphType; if (fieldType is IAbstractGraphType) { var abstractType = fieldType as IAbstractGraphType; objectType = abstractType.GetObjectType(result); if (objectType == null) { var error = new ExecutionError( $"Abstract type {abstractType.Name} must resolve to an Object type at " + $"runtime for field {parentType.Name}.{fieldName} " + $"with value {result}, received 'null'."); error.AddLocation(field, context.Document); throw error; } if (!abstractType.IsPossibleType(objectType)) { var error = new ExecutionError( "Runtime Object type \"{0}\" is not a possible type for \"{1}\"" .ToFormat(objectType, abstractType)); error.AddLocation(field, context.Document); throw error; } } if (objectType == null) { return(null); } if (objectType.IsTypeOf != null && !objectType.IsTypeOf(result)) { var error = new ExecutionError( "Expected value of type \"{0}\" but got: {1}." .ToFormat(objectType, result)); error.AddLocation(field, context.Document); throw error; } var subFields = new Dictionary <string, Field>(); var visitedFragments = new List <string>(); subFields = CollectFields(context, objectType, field?.SelectionSet, subFields, visitedFragments); return(await ExecuteFieldsAsync(context, objectType, result, subFields, path).ConfigureAwait(false)); }
private ResolveFieldResult<object> GenerateError(ResolveFieldResult<object> resolveResult, Field field, ExecutionContext context, Exception exc) { var error = new ExecutionError("Error trying to resolve {0}.".ToFormat(field.Name), exc); error.AddLocation(field, context.Document); context.Errors.Add(error); resolveResult.Skip = false; return resolveResult; }
public async Task <ResolveFieldResult <object> > ResolveField(ExecutionContext context, ObjectGraphType parentType, object source, Fields fields) { context.CancellationToken.ThrowIfCancellationRequested(); var resolveResult = new ResolveFieldResult <object> { Skip = false }; var field = fields.First(); var fieldDefinition = GetFieldDefinition(context.Schema, parentType, field); if (fieldDefinition == null) { resolveResult.Skip = true; return(resolveResult); } var arguments = GetArgumentValues(context.Schema, fieldDefinition.Arguments, field.Arguments, context.Variables); Func <ResolveFieldContext, object> defaultResolve = ctx => ctx.Source != null ? GetProperyValue(ctx.Source, ctx.FieldAst.Name) : null; try { var resolveContext = new ResolveFieldContext(); resolveContext.FieldName = field.Name; resolveContext.FieldAst = field; resolveContext.FieldDefinition = fieldDefinition; resolveContext.ReturnType = context.Schema.FindType(fieldDefinition.Type); resolveContext.ParentType = parentType; resolveContext.Arguments = arguments; resolveContext.Source = source; resolveContext.Schema = context.Schema; resolveContext.Fragments = context.Fragments; resolveContext.RootValue = context.RootValue; resolveContext.Operation = context.Operation; resolveContext.Variables = context.Variables; resolveContext.CancellationToken = context.CancellationToken; var resolve = fieldDefinition.Resolve ?? defaultResolve; var result = resolve(resolveContext); if (result is Task) { var task = result as Task; await task; result = GetProperyValue(task, "Result"); } if (parentType is __Field && result is Type) { result = context.Schema.FindType(result as Type); } resolveResult.Value = await CompleteValue(context, context.Schema.FindType(fieldDefinition.Type), fields, result); return(resolveResult); } catch (Exception exc) { var error = new ExecutionError("Error trying to resolve {0}.".ToFormat(field.Name), exc); error.AddLocation(field.SourceLocation.Line, field.SourceLocation.Column); context.Errors.Add(error); resolveResult.Skip = false; return(resolveResult); } }
public async Task <ResolveFieldResult <object> > ResolveFieldAsync(ExecutionContext context, IObjectGraphType parentType, object source, Fields fields) { context.CancellationToken.ThrowIfCancellationRequested(); var resolveResult = new ResolveFieldResult <object> { Skip = false }; var field = fields.First(); var fieldDefinition = GetFieldDefinition(context.Schema, parentType, field); if (fieldDefinition == null) { resolveResult.Skip = true; return(resolveResult); } var arguments = GetArgumentValues(context.Schema, fieldDefinition.Arguments, field.Arguments, context.Variables); try { var resolveContext = new ResolveFieldContext(); resolveContext.FieldName = field.Name; resolveContext.FieldAst = field; resolveContext.FieldDefinition = fieldDefinition; resolveContext.ReturnType = fieldDefinition.ResolvedType; resolveContext.ParentType = parentType; resolveContext.Arguments = arguments; resolveContext.Source = source; resolveContext.Schema = context.Schema; resolveContext.Document = context.Document; resolveContext.Fragments = context.Fragments; resolveContext.RootValue = context.RootValue; resolveContext.UserContext = context.UserContext; resolveContext.Operation = context.Operation; resolveContext.Variables = context.Variables; resolveContext.CancellationToken = context.CancellationToken; resolveContext.Metrics = context.Metrics; var resolver = fieldDefinition.Resolver ?? new NameFieldResolver(); var result = resolver.Resolve(resolveContext); if (result is Task) { var task = result as Task; await task.ConfigureAwait(false); result = task.GetProperyValue("Result"); } resolveResult.Value = await CompleteValueAsync(context, fieldDefinition.ResolvedType, fields, result).ConfigureAwait(false); return(resolveResult); } catch (Exception exc) { var error = new ExecutionError("Error trying to resolve {0}.".ToFormat(field.Name), exc); error.AddLocation(field, context.Document); context.Errors.Add(error); resolveResult.Skip = false; return(resolveResult); } }
public object GetVariableValue(Document document, ISchema schema, VariableDefinition variable, object input) { var type = variable.Type.GraphTypeFromType(schema); if (IsValidValue(schema, type, input)) { if (input == null) { if (variable.DefaultValue != null) { return ValueFromAst(variable.DefaultValue); } } var coercedValue = CoerceValue(schema, type, input.AstFromValue(schema, type)); return coercedValue; } if (input == null) { var error2 = new ExecutionError("Variable '${0}' of required type '{1}' was not provided.".ToFormat(variable.Name, type.Name ?? variable.Type.FullName())); error2.AddLocation(variable, document); throw error2; } var error = new ExecutionError("Variable '${0}' expected value of type '{1}'.".ToFormat(variable.Name, type?.Name ?? variable.Type.FullName())); error.AddLocation(variable, document); throw error; }
public async Task<ResolveFieldResult<object>> ResolveFieldAsync(ExecutionContext context, IObjectGraphType parentType, object source, Fields fields) { context.CancellationToken.ThrowIfCancellationRequested(); var resolveResult = new ResolveFieldResult<object> { Skip = false }; var field = fields.First(); var fieldDefinition = GetFieldDefinition(context.Schema, parentType, field); if (fieldDefinition == null) { resolveResult.Skip = true; return resolveResult; } var arguments = GetArgumentValues(context.Schema, fieldDefinition.Arguments, field.Arguments, context.Variables); try { var resolveContext = new ResolveFieldContext(); resolveContext.FieldName = field.Name; resolveContext.FieldAst = field; resolveContext.FieldDefinition = fieldDefinition; resolveContext.ReturnType = fieldDefinition.ResolvedType; resolveContext.ParentType = parentType; resolveContext.Arguments = arguments; resolveContext.Source = source; resolveContext.Schema = context.Schema; resolveContext.Document = context.Document; resolveContext.Fragments = context.Fragments; resolveContext.RootValue = context.RootValue; resolveContext.UserContext = context.UserContext; resolveContext.Operation = context.Operation; resolveContext.Variables = context.Variables; resolveContext.CancellationToken = context.CancellationToken; resolveContext.Metrics = context.Metrics; var resolver = fieldDefinition.Resolver ?? new NameFieldResolver(); var result = resolver.Resolve(resolveContext); if (result is Task) { var task = result as Task; await task.ConfigureAwait(false); result = task.GetProperyValue("Result"); } resolveResult.Value = await CompleteValueAsync(context, fieldDefinition.ResolvedType, fields, result).ConfigureAwait(false); return resolveResult; } catch (Exception exc) { var error = new ExecutionError("Error trying to resolve {0}.".ToFormat(field.Name), exc); error.AddLocation(field, context.Document); context.Errors.Add(error); resolveResult.Skip = false; return resolveResult; } }
public IObjectGraphType GetOperationRootType(Document document, ISchema schema, Operation operation) { IObjectGraphType type; ExecutionError error; switch (operation.OperationType) { case OperationType.Query: type = schema.Query; break; case OperationType.Mutation: type = schema.Mutation; if (type == null) { error = new ExecutionError("Schema is not configured for mutations"); error.AddLocation(operation, document); throw error; } break; case OperationType.Subscription: type = schema.Subscription; if (type == null) { error = new ExecutionError("Schema is not configured for subscriptions"); error.AddLocation(operation, document); throw error; } break; default: error = new ExecutionError("Can only execute queries, mutations and subscriptions."); error.AddLocation(operation, document); throw error; } return type; }
public async Task<ResolveFieldResult<object>> ResolveFieldAsync(ExecutionContext context, ObjectGraphType parentType, object source, Fields fields) { context.CancellationToken.ThrowIfCancellationRequested(); var resolveResult = new ResolveFieldResult<object> { Skip = false }; var field = fields.First(); var fieldDefinition = GetFieldDefinition(context.Schema, parentType, field); if (fieldDefinition == null) { resolveResult.Skip = true; return resolveResult; } var arguments = GetArgumentValues(context.Schema, fieldDefinition.Arguments, field.Arguments, context.Variables); Func<ResolveFieldContext, object> defaultResolve = ctx => ctx.Source != null ? GetProperyValue(ctx.Source, ctx.FieldAst.Name) : null; try { var resolveContext = new ResolveFieldContext(); resolveContext.FieldName = field.Name; resolveContext.FieldAst = field; resolveContext.FieldDefinition = fieldDefinition; resolveContext.ReturnType = context.Schema.FindType(fieldDefinition.Type); resolveContext.ParentType = parentType; resolveContext.Arguments = arguments; resolveContext.Source = source; resolveContext.Schema = context.Schema; resolveContext.Fragments = context.Fragments; resolveContext.RootValue = context.RootValue; resolveContext.Operation = context.Operation; resolveContext.Variables = context.Variables; resolveContext.CancellationToken = context.CancellationToken; var resolve = fieldDefinition.Resolve ?? defaultResolve; var result = resolve(resolveContext); if(result is Task) { var task = result as Task; await task.ConfigureAwait(false); result = GetProperyValue(task, "Result"); } if (parentType is __Field && result is Type) { result = context.Schema.FindType(result as Type); } resolveResult.Value = await CompleteValueAsync(context, context.Schema.FindType(fieldDefinition.Type), fields, result).ConfigureAwait(false); return resolveResult; } catch (Exception exc) { var error = new ExecutionError("Error trying to resolve {0}.".ToFormat(field.Name), exc); error.AddLocation(field.SourceLocation.Line, field.SourceLocation.Column); context.Errors.Add(error); resolveResult.Skip = false; return resolveResult; } }