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);
        }
示例#2
0
 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;
            }
        }