private async Task ExtractFieldAsync(ExecutionContext context, IObjectGraphType rootType, object source, Field field, FieldType fieldType, ConcurrentDictionary <string, object> data, IEnumerable <string> path) { context.CancellationToken.ThrowIfCancellationRequested(); var name = field.Alias ?? field.Name; if (data.ContainsKey(name)) { return; } if (!ShouldIncludeNode(context, field.Directives)) { return; } if (CanResolveFromData(field, fieldType)) { var result = ResolveFieldFromData(context, rootType, source, fieldType, field, path); data.TryAdd(name, result); } else { var result = await ResolveFieldAsync(context, rootType, source, field, path); if (result.Skip) { return; } data.TryAdd(name, result.Value); } }
private bool CanResolveFromData(Field field, FieldType type) { if (field == null || type == null) { return(false); } if (type.Arguments != null && type.Arguments.Any()) { return(false); } if (!(type.ResolvedType is ScalarGraphType)) { return(false); } if (type.ResolvedType is NonNullGraphType) { return(false); } return(true); }
/// <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 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, 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); }
private void Field(IGraphType type, Field field, ValidationContext context) { if (type == null) { return; } if (type.IsLeafType()) { if (field.SelectionSet != null && field.SelectionSet.Selections.Any()) { var error = new ValidationError(context.OriginalQuery, "5.2.3", NoSubselectionAllowedMessage(field.Name, context.Print(type)), field.SelectionSet); context.ReportError(error); } } else if(field.SelectionSet == null || !field.SelectionSet.Selections.Any()) { var error = new ValidationError(context.OriginalQuery, "5.2.3", RequiredSubselectionMessage(field.Name, context.Print(type)), field); context.ReportError(error); } }
private IDictionary <string, Field> SubFieldsFor(ExecutionContext context, IGraphType fieldType, Field field) { if (!(fieldType is IObjectGraphType) || !field.SelectionSet.Selections.Any()) { return(null); } var subFields = new Dictionary <string, Field>(); var visitedFragments = new List <string>(); var fields = CollectFields(context, fieldType, field.SelectionSet, subFields, visitedFragments); return(fields); }
public async Task <ResolveFieldResult <object> > ResolveFieldAsync(ExecutionContext context, IObjectGraphType parentType, object source, Field field, IEnumerable <string> path) { context.CancellationToken.ThrowIfCancellationRequested(); var fieldPath = path?.ToList() ?? new List <string>(); var resolveResult = new ResolveFieldResult <object> { Skip = false }; var fieldDefinition = GetFieldDefinition(context.Document, 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; resolveContext.Errors = context.Errors; resolveContext.Path = fieldPath; var subFields = SubFieldsFor(context, fieldDefinition.ResolvedType, field); resolveContext.SubFields = subFields; var resolver = fieldDefinition.Resolver ?? new NameFieldResolver(); var result = resolver.Resolve(resolveContext); if (result is Task) { var task = result as Task; if (task.IsFaulted) { var aggregateException = task.Exception; var exception = aggregateException.InnerExceptions.Count == 1 ? aggregateException.InnerException : aggregateException; return(GenerateError(resolveResult, field, context, exception, fieldPath)); } await task.ConfigureAwait(false); result = task.GetProperyValue("Result"); } resolveResult.Value = await CompleteValueAsync(context, parentType, fieldDefinition.ResolvedType, field, result, fieldPath).ConfigureAwait(false); return(resolveResult); } catch (Exception exc) { return(GenerateError(resolveResult, field, context, exc, path)); } }
public FieldType GetFieldDefinition(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); } return(parentType.Fields.FirstOrDefault(f => f.Name == field.Name)); }
public FieldType GetFieldDefinition(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; } return parentType.Fields.FirstOrDefault(f => f.Name == field.Name); }
protected bool Equals(Field other) { return string.Equals(Name, other.Name) && string.Equals(Alias, other.Alias); }
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 <ResolveFieldResult <object> > ResolveFieldAsync(ExecutionContext context, IObjectGraphType parentType, object source, Field field, IEnumerable <string> path) { context.CancellationToken.ThrowIfCancellationRequested(); var fieldPath = path?.ToList() ?? new List <string>(); var resolveResult = new ResolveFieldResult <object> { Skip = false }; var fieldDefinition = GetFieldDefinition(context.Document, 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 { FieldName = field.Name, FieldAst = field, FieldDefinition = fieldDefinition, ReturnType = fieldDefinition.ResolvedType, ParentType = parentType, Arguments = arguments, Source = source, Schema = context.Schema, Document = context.Document, Fragments = context.Fragments, RootValue = context.RootValue, UserContext = context.UserContext, Operation = context.Operation, Variables = context.Variables, CancellationToken = context.CancellationToken, Metrics = context.Metrics, Errors = context.Errors, Path = fieldPath }; var subFields = SubFieldsFor(context, fieldDefinition.ResolvedType, field); resolveContext.SubFields = subFields; var resolver = fieldDefinition.Resolver ?? new NameFieldResolver(); var result = resolver.Resolve(resolveContext); result = await UnwrapResultAsync(result) .ConfigureAwait(false); resolveResult.Value = await CompleteValueAsync(context, parentType, fieldDefinition.ResolvedType, field, result, fieldPath) .ConfigureAwait(false); return(resolveResult); } catch (Exception exc) { return(GenerateError(resolveResult, field, context, exc, path)); } }
/// <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); }
private ResolveEventStreamResult ResolveEventStream( ExecutionContext context, IObjectGraphType parentType, object source, Field field, IEnumerable <string> path) { context.CancellationToken.ThrowIfCancellationRequested(); var fieldPath = path?.ToList() ?? new List <string>(); var resolveResult = new ResolveEventStreamResult { Skip = false }; if (!(GetFieldDefinition(context.Document, context.Schema, parentType, field) is EventStreamFieldType fieldDefinition)) { resolveResult.Skip = true; return(resolveResult); } var arguments = GetArgumentValues( context.Schema, fieldDefinition.Arguments, field.Arguments, context.Variables); try { var resolveContext = new ResolveEventStreamContext(); 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; resolveContext.Errors = context.Errors; resolveContext.Path = fieldPath; if (fieldDefinition.Subscriber == null) { return(GenerateError(resolveResult, field, context, new InvalidOperationException($"Subscriber not set for field {field.Name}"), fieldPath)); } var result = fieldDefinition.Subscriber.Subscribe(resolveContext); var valueTransformer = result .SelectMany(async value => { var fieldResolveResult = await ResolveFieldAsync(context, parentType, value, field, fieldPath); return(new ExecutionResult { Data = fieldResolveResult.Value }); }) .Catch <ExecutionResult, Exception>(exception => Observable.Return( new ExecutionResult { Errors = new ExecutionErrors { new ExecutionError( $"Could not subscribe to field '{field.Name}' in query '{context.Document.OriginalQuery}'", exception) { Path = path } } })); resolveResult.Value = valueTransformer; return(resolveResult); } catch (Exception exc) { return(GenerateError(resolveResult, field, context, exc, path)); } }
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 <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)); }
/// <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); result.Add(nodeResult); } else { var nodeResult = await CompleteValueAsync(context, parentType, listInfo?.ResolvedType, field, node, currentPath).ConfigureAwait(false); result.Add(nodeResult); } } return(result); }
private FieldType GetFieldDef(ISchema schema, GraphType parentType, Field field) { var name = field.Name; if (name == SchemaIntrospection.SchemaMeta.Name && Equals(schema.Query, parentType)) { return SchemaIntrospection.SchemaMeta; } if (name == SchemaIntrospection.TypeMeta.Name && Equals(schema.Query, parentType)) { return SchemaIntrospection.TypeMeta; } if (name == SchemaIntrospection.TypeNameMeta.Name && (parentType is ObjectGraphType || parentType is InterfaceGraphType || parentType is UnionGraphType)) { return SchemaIntrospection.TypeNameMeta; } if (parentType is ObjectGraphType || parentType is InterfaceGraphType) { return parentType.Fields.FirstOrDefault(x => x.Name == field.Name); } return null; }
protected bool Equals(Field other) { return(string.Equals(Name, other.Name, StringComparison.InvariantCulture) && string.Equals(Alias, other.Alias, StringComparison.InvariantCulture)); }