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);
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); } } }
private ResolveFieldResult <object> GenerateError( ResolveFieldResult <object> resolveResult, Field field, ExecutionContext context, Exception exc, IEnumerable <string> path) { var error = new ExecutionError("Error trying to resolve {0}.".ToFormat(field.Name), exc); error.AddLocation(field, context.Document); error.Path = path; context.Errors.Add(error); resolveResult.Skip = false; return(resolveResult); }
/// <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); }
private void WriteErrorExtensions(ExecutionError error, JsonWriter writer, JsonSerializer serializer) { if (string.IsNullOrWhiteSpace(error.Code) && (error.Data == null || error.Data.Count == 0)) { return; } writer.WritePropertyName("extensions"); writer.WriteStartObject(); if (!string.IsNullOrWhiteSpace(error.Code)) { writer.WritePropertyName("code"); serializer.Serialize(writer, error.Code); } if (error.HasCodes) { writer.WritePropertyName("codes"); writer.WriteStartArray(); error.Codes.Apply(code => serializer.Serialize(writer, code)); writer.WriteEndArray(); } if (error.Data?.Count > 0) { writer.WritePropertyName("data"); writer.WriteStartObject(); error.DataAsDictionary.Apply(entry => { writer.WritePropertyName(entry.Key); serializer.Serialize(writer, entry.Value); }); writer.WriteEndObject(); } writer.WriteEndObject(); }
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 override void Add(ExecutionError error) => throw new NotSupportedException();
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)); }
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 <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 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); } }
/// <summary> /// Adds the specified error to <see cref="Errors"/>. /// </summary> /// <returns>Reference to this.</returns> public ExecutionResult AddError(ExecutionError error) { (Errors ??= new ExecutionErrors()).Add(error); return(this); }