private static ResolveFieldResult <object> GetMutationReturnItem(dynamic source, Dictionary <string, Fields> fieldsToUse, int id) { // Get all items and then select one with newly added id ResolveFieldResult <object> value = Task.Run(async() => await ResolveFieldAsync(source, null, fieldsToUse.First().Value, true)).GetAwaiter().GetResult(); var items = value.Value as List <dynamic>; var item = new ResolveFieldResult <object>() { Value = items.First(e => ((dynamic)e).id == id) }; return(item); }
public abstract TOut MutateAndGetPayload(MutationInputs inputs, ResolveFieldResult <object> context);
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; } }
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; }
private static ExpandoObject ResolveMutationFieldAsync(string nameToProcess, dynamic newItem, Fields fields, bool isRoot = false) { if (newItem == null) { newItem = new ExpandoObject(); } var resolveResult = new ResolveFieldResult <object> { Skip = false }; var visitedFragments = new List <string>(); var f = fields.First(); foreach (var arg in f.Arguments) { if (arg.Name == "input") { void HandleChilds(INode node, ExpandoObject exp, bool firstCall = false) { foreach (var child in node.Children) { var oField = child as ObjectField; if (firstCall && oField.Name != nameToProcess) { continue; } var grandChild = child.Children; if (grandChild.Count() == 1 && grandChild.First().Children.Count() == 0) { var valueOject = grandChild.First(); // Grandchild should be some IValue if (valueOject is IValue) { dynamic value; try { value = ((dynamic)valueOject).Value; } catch (Exception) { try { value = ((dynamic)valueOject).Name; } catch (Exception) { value = null; } } ((IDictionary <string, object>)exp)[oField.Name] = value; } else { ((IDictionary <string, object>)exp)[oField.Name] = ((dynamic)grandChild.First()).Value; } } else { if (!firstCall && oField != null) { if (oField.Value is ListValue) { if (((IDictionary <string, object>)exp).ContainsKey(oField.Name) == false) { ((IDictionary <string, object>)exp)[oField.Name] = new List <ExpandoObject>(); } foreach (var c in ((dynamic)oField.Value).Values) { var chidExp = new ExpandoObject(); ((List <ExpandoObject>)((IDictionary <string, object>)exp)[oField.Name]).Add(chidExp); HandleChilds(c, chidExp); } } else { var chidExp = new ExpandoObject(); ((IDictionary <string, object>)exp)[oField.Name] = chidExp; HandleChilds(child, chidExp); } } else { HandleChilds(child, exp); } } } } foreach (var child in arg.Children) { HandleChilds(child, newItem, true); } } } return(newItem); }
private static Dictionary <string, dynamic> ExecuteMutationFields(dynamic source, dynamic target, Dictionary <string, Fields> fields, bool isRoot = false) { return(fields.ToDictionary( pair => GetResponseName(pair), pair => { var allowedActions = new[] { "add", "update", "replace", "delete" }; var fieldsToUse = CollectFields(pair.Value.First().SelectionSet); var collectionName = fieldsToUse.Any() ? fieldsToUse.FirstOrDefault().Key : allowedActions.Aggregate(pair.Value.First().Name, (e, c) => e.Replace(c, "")).ToLower(); var collection = ((IDataStore)source).GetCollection(collectionName); if (pair.Value.First().Name.StartsWith("add")) { var newItem = ResolveMutationFieldAsync(fieldsToUse.First().Key, target, pair.Value, isRoot); var success = collection.InsertOne(newItem); var itemId = ((dynamic)newItem).id; dynamic updateData = success ? new { Method = "POST", Path = $"{collectionName}/{itemId}", Collection = collectionName, ItemId = itemId } : null; ResolveFieldResult <object> item = GetMutationReturnItem(source, fieldsToUse, itemId); return Tuple.Create(item.Value as object, updateData); //return item.Value as object; } else if (pair.Value.First().Name.StartsWith("update")) { dynamic id = GraphQL.GetInputId(pair); ExpandoObject newItem = ResolveMutationFieldAsync("patch", target, pair.Value, isRoot); var success = collection.UpdateOne(e => e.id == id, newItem); dynamic updateData = success ? new { Method = "PATCH", Path = $"{collectionName}/{id}", Collection = collectionName, ItemId = id } : null; ResolveFieldResult <object> item = GetMutationReturnItem(source, fieldsToUse, id); return Tuple.Create(item.Value as object, updateData); //return item.Value as object; } else if (pair.Value.First().Name.StartsWith("replace")) { dynamic id = GraphQL.GetInputId(pair); dynamic newItem = ResolveMutationFieldAsync(collectionName, target, pair.Value, isRoot); // Make sure that new data has id field correctly newItem.id = id; var success = collection.ReplaceOne(e => e.id == id, newItem as ExpandoObject); dynamic updateData = success ? new { Method = "PUT", Path = $"{collectionName}/{id}", Collection = collectionName, ItemId = id } : null; ResolveFieldResult <object> item = GetMutationReturnItem(source, fieldsToUse, id); return Tuple.Create(item.Value as object, updateData); //return item.Value as object; } else if (pair.Value.First().Name.StartsWith("delete")) { dynamic id = GraphQL.GetInputId(pair); var success = collection.DeleteOne(e => e.id == id); dynamic updateData = success ? new { Method = "DELETE", Path = $"{collectionName}/{id}", Collection = collectionName, ItemId = id } : null; var item = new ResolveFieldResult <object> { Value = success }; return Tuple.Create(success, updateData); //return success; } else { return Tuple.Create <dynamic, dynamic>(null, null); } })); }
private static async Task <ResolveFieldResult <object> > ResolveFieldAsync(dynamic source, dynamic target, Fields fields, bool isRoot = false) { if (target == null) { target = new ExpandoObject(); } var resolveResult = new ResolveFieldResult <object> { Skip = false }; var subFields = new Dictionary <string, Fields>(); var visitedFragments = new List <string>(); var f = fields.First(); subFields = CollectFields(f.SelectionSet, subFields, visitedFragments); dynamic result; if (isRoot) { result = new List <object>(); var collection = ((IDataStore)source).GetCollection(f.Name); foreach (var item in collection.AsQueryable()) { if (f.Arguments.Any(a => GetValue(item, a.Name) != ((dynamic)a.Value).Value)) { continue; } dynamic rootObject = new ExpandoObject(); foreach (var i in subFields) { var r = await ResolveFieldAsync(item, rootObject, i.Value); rootObject = r.Value; } if (rootObject != null) { result.Add(rootObject); } } resolveResult.Value = result; return(resolveResult); } else { var newSource = ((IDictionary <string, object>)source).ContainsKey(f.Name) ? ((IDictionary <string, object>)source)[f.Name] : null; var newTarget = target; if (newSource is ExpandoObject && subFields.Count > 0) { if (f.Arguments.Any(a => GetValue(newSource, a.Name) != ((dynamic)a.Value).Value)) { return(resolveResult); } newTarget = new ExpandoObject(); ((IDictionary <string, object>)target)[f.Name] = newTarget; foreach (var i in subFields) { var r = await ResolveFieldAsync(newSource, newTarget, i.Value); } } else if (IsEnumerable(newSource?.GetType()) && subFields.Count > 0) { dynamic newArray = Activator.CreateInstance(newSource.GetType()); ((IDictionary <string, object>)target)[f.Name] = newArray; foreach (var item in newSource as IEnumerable <dynamic> ) { if (f.Arguments.Any(a => GetValue(item, a.Name) != ((dynamic)a.Value).Value)) { continue; } dynamic rootObject = new ExpandoObject(); foreach (var i in subFields) { var r = await ResolveFieldAsync(item, rootObject, i.Value); rootObject = r.Value; } if (rootObject != null) { newArray.Add(rootObject); } } } else { ((IDictionary <string, object>)target)[f.Name] = newSource; } resolveResult.Value = target; 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) => { return 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) { context.Errors.Add(new ExecutionError("Error trying to resolve {0}.".ToFormat(field.Name), exc)); resolveResult.Skip = false; return resolveResult; } }