/// <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)); }
/// <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); }
/// <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; } }
/// <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); }