Пример #1
0
        /// <summary>
        /// Register the mutation
        /// </summary>
        /// <param name="provider">The mutation api provider</param>
        /// <param name="apiMutation">The mutation description</param>
        /// <param name="apiRoot">The api root</param>
        /// <param name="typesCreated">The list of created types</param>
        /// <returns>The mutation as merged field </returns>
        private static MergedField RegisterConnectionMutation(
            ApiProvider provider,
            ApiMutation apiMutation,
            MergedApiRoot apiRoot,
            Dictionary <string, MergedType> typesCreated)
        {
            var field          = FindContainer(apiMutation, apiRoot);
            var connectionType = field?.Type as MergedConnectionType;

            if (connectionType == null)
            {
                return(null);
            }

            var errorDescriptionApiType =
                provider.Description.Types.FirstOrDefault(t => t.TypeName == "ErrorDescription") as ApiObjectType;
            MergedType errorDescriptionType = null;

            if (errorDescriptionApiType != null)
            {
                errorDescriptionType = CreateConnectionType(errorDescriptionApiType, provider, typesCreated);
            }

            var returnType = new MergedConnectionMutationResultType(
                connectionType.ElementType,
                apiRoot,
                errorDescriptionType,
                provider);

            typesCreated[returnType.ComplexTypeName] = returnType;

            var inputType = new MergedInputType(apiMutation.Name);

            inputType.AddProvider(
                new FieldProvider {
                Provider = provider, FieldType = new ApiObjectType(apiMutation.Name)
            });
            typesCreated[inputType.ComplexTypeName] = inputType;

            foreach (var apiField in apiMutation.Arguments)
            {
                inputType.Fields.Add(
                    apiField.Name,
                    new MergedField(
                        apiField.Name,
                        CreateMergedType(provider, apiField, null, new List <string>(), true, typesCreated),
                        provider,
                        apiMutation,
                        apiMutation.Flags,
                        description: apiField.Description));
            }

            inputType.Fields["clientMutationId"] = new MergedField(
                "clientMutationId",
                CreateScalarType(EnScalarType.String, typesCreated),
                provider,
                apiMutation);

            var arguments = new Dictionary <string, MergedField>
            {
                {
                    "input",
                    new MergedField(
                        "input",
                        inputType,
                        provider,
                        apiMutation)
                }
            };

            return(new MergedField(
                       apiMutation.Name,
                       returnType,
                       provider,
                       apiMutation,
                       apiMutation.Flags,
                       arguments,
                       apiMutation.Description));
        }
Пример #2
0
        /// <summary>
        /// Creates field from api description
        /// </summary>
        /// <param name="provider">The api provider</param>
        /// <param name="apiField">The api field description</param>
        /// <param name="complexField">The same field merged from previous api descriptions</param>
        /// <param name="path">The list of processed types</param>
        /// <param name="createAsInput">A value indicating that an input type is assembled</param>
        /// <param name="typesCreated">The list of already created types</param>
        /// <returns>The field description</returns>
        private static MergedType CreateMergedType(
            ApiProvider provider,
            ApiField apiField,
            MergedField complexField,
            ICollection <string> path,
            bool createAsInput,
            Dictionary <string, MergedType> typesCreated)
        {
            MergedType createdType;

            if (apiField.ScalarType != EnScalarType.None)
            {
                return(CreateScalarType(apiField.ScalarType, typesCreated));
            }

            var apiType = provider.Description.Types.FirstOrDefault(t => t.TypeName == apiField.TypeName);

            if (apiType == null)
            {
                throw new Exception("type was not found");
            }

            var apiEnumType = apiType as ApiEnumType;

            if (apiEnumType != null)
            {
                return(CreateEnumType(apiEnumType, provider, typesCreated));
            }

            var apiObjectType = (ApiObjectType)apiType;

            if (apiField.Flags.HasFlag(EnFieldFlags.IsConnection))
            {
                var typedArgumentNames =
                    apiField.Arguments.Where(a => a.Flags.HasFlag(EnFieldFlags.IsTypeArgument))
                    .Select(f => f.Name)
                    .ToList();
                return(CreateConnectionType(apiObjectType, provider, typesCreated, typedArgumentNames));
            }

            var objectType = (complexField?.Type as MergedObjectType)?.Clone()
                             ?? (createAsInput
                                     ? new MergedInputType($"{provider.Description.ApiName}_{apiField.TypeName}")
                                     : new MergedObjectType($"{provider.Description.ApiName}_{apiField.TypeName}"));

            objectType.AddProvider(new FieldProvider {
                FieldType = apiObjectType, Provider = provider
            });
            if (complexField != null)
            {
                objectType.Category = MergedObjectType.EnCategory.MultipleApiType;
            }

            if (typesCreated.TryGetValue(objectType.ComplexTypeName, out createdType))
            {
                return(createdType);
            }

            typesCreated[objectType.ComplexTypeName] = objectType;

            MergeFields(
                objectType,
                apiObjectType.Fields,
                provider,
                path.Union(new[] { apiObjectType.TypeName }).ToList(),
                createAsInput,
                typesCreated);

            objectType.Initialize();
            return(objectType);
        }
Пример #3
0
        /// <summary>
        /// Insert new fields from new provider into current type
        /// </summary>
        /// <param name="parentType">
        /// Field to update
        /// </param>
        /// <param name="apiFields">
        /// The list of subfields from api
        /// </param>
        /// <param name="provider">
        /// The api provider
        /// </param>
        /// <param name="path">
        /// The types names path to avoid circular references.
        /// </param>
        /// <param name="createAsInput">A value indicating that an input type is assembled</param>
        /// <param name="typesCreated">The list of previously created types</param>
        private static void MergeFields(
            MergedObjectType parentType,
            IEnumerable <ApiField> apiFields,
            ApiProvider provider,
            ICollection <string> path,
            bool createAsInput,
            Dictionary <string, MergedType> typesCreated)
        {
            var fields = createAsInput
                             ? apiFields.Where(
                f =>
                f.Flags.HasFlag(EnFieldFlags.CanBeUsedInInput) &&
                f.Arguments.All(a => a.Flags.HasFlag(EnFieldFlags.IsTypeArgument)))
                             : apiFields.Where(f => f.Flags.HasFlag(EnFieldFlags.Queryable));

            foreach (var apiField in fields)
            {
                MergedField complexField;
                if (parentType.Fields.TryGetValue(apiField.Name, out complexField))
                {
                    if (apiField.ScalarType != EnScalarType.None || createAsInput ||
                        apiField.Flags.HasFlag(EnFieldFlags.IsConnection) ||
                        apiField.Flags.HasFlag(EnFieldFlags.IsArray) || !(complexField.Type is MergedObjectType) ||
                        complexField.Arguments.Any() || apiField.Arguments.Any())
                    {
                        // todo: write merge error
                        continue;
                    }
                }

                var flags = apiField.Flags;

                if (createAsInput && flags.HasFlag(EnFieldFlags.IsConnection))
                {
                    flags &= ~EnFieldFlags.IsConnection;
                    flags |= EnFieldFlags.IsArray;
                }

                var cloneField = apiField.Clone();
                cloneField.Flags = flags;

                var fieldType = CreateMergedType(provider, cloneField, complexField, path, createAsInput, typesCreated);

                if (fieldType == null)
                {
                    continue;
                }

                var fieldArguments = new Dictionary <string, MergedField>();

                if (!createAsInput)
                {
                    foreach (var argument in apiField.Arguments)
                    {
                        var fieldArgumentType = CreateMergedType(provider, argument, null, path, true, typesCreated);
                        fieldArguments[argument.Name] = new MergedField(
                            argument.Name,
                            fieldArgumentType,
                            provider,
                            apiField,
                            argument.Flags,
                            description: argument.Description);
                    }
                }

                var description = string.Join(
                    "\n",
                    new[] { complexField?.Description, apiField.Description }.Where(s => !string.IsNullOrWhiteSpace(s)));

                var field = new MergedField(
                    apiField.Name,
                    fieldType,
                    provider,
                    cloneField,
                    flags,
                    fieldArguments,
                    string.IsNullOrWhiteSpace(description) ? null : description);
                if (complexField != null)
                {
                    foreach (var complexFieldProvider in complexField.Providers)
                    {
                        field.AddProvider(
                            complexFieldProvider,
                            complexField.OriginalFields[complexFieldProvider.Description.ApiName]);
                    }
                }

                parentType.Fields[apiField.Name] = field;
            }
        }
Пример #4
0
        /// <summary>
        /// Register the mutation
        /// </summary>
        /// <param name="provider">The mutation api provider</param>
        /// <param name="apiMutation">The mutation description</param>
        /// <param name="apiRoot">The api root</param>
        /// <param name="typesCreated">The list of created types</param>
        /// <returns>The mutation as merged field </returns>
        private static MergedField RegisterUntypedMutation(
            ApiProvider provider,
            ApiMutation apiMutation,
            MergedApiRoot apiRoot,
            Dictionary <string, MergedType> typesCreated)
        {
            var returnType = CreateMergedType(provider, apiMutation, null, new List <string>(), false, typesCreated);

            var inputType = new MergedInputType(apiMutation.Name);

            inputType.AddProvider(
                new FieldProvider {
                Provider = provider, FieldType = new ApiObjectType(apiMutation.Name)
            });
            typesCreated[inputType.ComplexTypeName] = inputType;

            foreach (var apiField in apiMutation.Arguments)
            {
                inputType.Fields.Add(
                    apiField.Name,
                    new MergedField(
                        apiField.Name,
                        CreateMergedType(provider, apiField, null, new List <string>(), true, typesCreated),
                        provider,
                        apiMutation.Clone(),
                        apiMutation.Flags,
                        description: apiField.Description));
            }

            inputType.Fields["clientMutationId"] = new MergedField(
                "clientMutationId",
                CreateScalarType(EnScalarType.String, typesCreated),
                provider,
                apiMutation);

            var arguments = new Dictionary <string, MergedField>
            {
                {
                    "input",
                    new MergedField(
                        "input",
                        inputType,
                        provider,
                        apiMutation)
                }
            };

            var payload = new MergedUntypedMutationResult(returnType, apiRoot, provider, apiMutation);

            typesCreated[payload.ComplexTypeName] = payload;

            var untypedMutation = new MergedField(
                apiMutation.Name,
                payload,
                provider,
                apiMutation,
                apiMutation.Flags,
                arguments,
                apiMutation.Description);

            return(untypedMutation);
        }