private static Models.Field[] BuildMutationFields(ISchemaProvider schema, CombinedMapping combinedMapping) { var rootFields = new List <Models.Field>(); foreach (var field in schema.GetMutations()) { if (field.Name.StartsWith("__")) { continue; } // Skipping ENUM type if (field.ReturnTypeClr.GetTypeInfo().IsEnum) { continue; } var args = BuildArgs(schema, combinedMapping, field).ToArray(); rootFields.Add(new Models.Field { Name = field.Name, Args = args, IsDeprecated = false, Type = BuildType(schema, field.ReturnTypeClr, field.GetReturnType(schema), combinedMapping), Description = field.Description }); } return(rootFields.ToArray()); }
/// <summary> /// Build INPUT Type to be used by Mutations /// </summary> /// <param name="schema"></param> /// <param name="combinedMapping"></param> /// <remarks> /// Since Types and Inputs cannot have the same name, camelCase the name to prevent duplicates. /// </remarks> /// <returns></returns> private static List <TypeElement> BuildInputTypes(ISchemaProvider schema, CombinedMapping combinedMapping) { var types = new List <TypeElement>(); foreach (ISchemaType schemaType in schema.GetNonContextTypes().Where(s => s.IsInput)) { if (schemaType.Name.StartsWith("__")) { continue; } var inputValues = new List <InputValue>(); foreach (Field field in schemaType.GetFields()) { if (field.Name.StartsWith("__")) { continue; } // Skip any property with special attribute var property = schemaType.ContextType.GetProperty(field.Name); if (property != null && GraphQLIgnoreAttribute.ShouldIgnoreMemberFromInput(property)) { continue; } // Skipping custom fields added to schema if (field.Resolve.NodeType == System.Linq.Expressions.ExpressionType.Call) { continue; } // Skipping ENUM type if (field.ReturnTypeClr.GetTypeInfo().IsEnum) { continue; } inputValues.Add(new InputValue { Name = field.Name, Description = field.Description, Type = BuildType(schema, field.ReturnTypeClr, field.GetReturnType(schema), combinedMapping, true) }); } var typeElement = new TypeElement { Kind = "INPUT_OBJECT", Name = schemaType.Name, Description = schemaType.Description, InputFields = inputValues.ToArray() }; types.Add(typeElement); } return(types); }
private static string FindNamedMapping(Type type, CombinedMapping combinedMapping, string fallback = null) { var mappedType = combinedMapping.GetMappedType(type); if (mappedType != null) { return(mappedType); } if (string.IsNullOrEmpty(fallback)) { return(type.Name); } return(fallback); }
private void SetupIntrospectionTypesAndField() { var allTypeMappings = SchemaGenerator.DefaultTypeMappings.ToDictionary(k => k.Key, v => v.Value); // add the top level __schema field which is made _at runtime_ currently e.g. introspection could be faster foreach (var item in customTypeMappings) { allTypeMappings[item.Key] = item.Value; } var combinedMapping = new CombinedMapping(allTypeMappings, customScalarTypes); // evaluate Fields lazily so we don't end up in endless loop Type<Models.TypeElement>("__Type").ReplaceField("fields", new { includeDeprecated = false }, (t, p) => SchemaIntrospection.BuildFieldsForType(this, combinedMapping, t.Name).Where(f => p.includeDeprecated ? f.IsDeprecated || !f.IsDeprecated : !f.IsDeprecated).ToList(), "Fields available on type"); ReplaceField("__schema", db => SchemaIntrospection.Make(this, combinedMapping), "Introspection of the schema", "__Schema"); ReplaceField("__type", new { name = ArgumentHelper.Required<string>() }, (db, p) => SchemaIntrospection.Make(this, combinedMapping).Types.Where(s => s.Name == p.name).First(), "Query a type by name", "__Type"); }
private static List <TypeElement> BuildQueryTypes(ISchemaProvider schema, CombinedMapping combinedMapping) { var types = new List <TypeElement>(); foreach (var st in schema.GetNonContextTypes().Where(s => !s.IsInput && !s.IsEnum)) { var typeElement = new TypeElement { Kind = "OBJECT", Name = st.Name, Description = st.Description }; types.Add(typeElement); } return(types); }
/// <summary> /// Creates an Introspection schema /// </summary> /// <param name="schema"></param> /// <param name="typeMappings"></param> /// <returns></returns> public static Schema Make(ISchemaProvider schema, CombinedMapping combinedMapping) { var types = new List <TypeElement> { new TypeElement { Description = "The query type, represents all of the entry points into our object graph", Kind = "OBJECT", Name = "Query", OfType = null, }, new TypeElement { Description = "The mutation type, represents all updates we can make to our data", Kind = "OBJECT", Name = "Mutation", OfType = null, }, }; types.AddRange(BuildQueryTypes(schema, combinedMapping)); types.AddRange(BuildInputTypes(schema, combinedMapping)); types.AddRange(BuildEnumTypes(schema, combinedMapping)); types.AddRange(BuildScalarTypes(schema, combinedMapping)); var schemaDescription = new Schema { QueryType = new TypeElement { Name = "Query" }, MutationType = new TypeElement { Name = "Mutation" }, Types = types.OrderBy(x => x.Name).ToList(), Directives = BuildDirectives() }; return(schemaDescription); }
private static List <TypeElement> BuildEnumTypes(ISchemaProvider schema, CombinedMapping combinedMapping) { var types = new List <TypeElement>(); foreach (ISchemaType schemaType in schema.GetNonContextTypes().Where(s => s.IsEnum)) { var typeElement = new TypeElement { Kind = "ENUM", Name = schemaType.Name, Description = schemaType.Description, EnumValues = new Models.EnumValue[] { } }; if (schemaType.Name.StartsWith("__")) { continue; } var enumTypes = new List <Models.EnumValue>(); //filter to ENUM type ONLY! foreach (Field field in schemaType.GetFields()) { enumTypes.Add(new Models.EnumValue { Name = field.Name, Description = field.Description, IsDeprecated = false, DeprecationReason = null }); } typeElement.EnumValues = enumTypes.ToArray(); if (typeElement.EnumValues.Count() > 0) { types.Add(typeElement); } } return(types); }
private static List <InputValue> BuildArgs(ISchemaProvider schema, CombinedMapping combinedMapping, IMethodType field) { var args = new List <InputValue>(); foreach (var arg in field.Arguments) { Type clrType = arg.Value.Type.GetNonNullableType(); var gqlTypeName = clrType.IsEnumerableOrArray() ? clrType.GetEnumerableOrArrayType().Name : clrType.Name; var type = BuildType(schema, clrType, gqlTypeName, combinedMapping, true); args.Add(new InputValue { Name = arg.Key, Type = type, DefaultValue = null, Description = null, }); } return(args); }
/// <summary> /// This is used in a lazy evaluated field as a graph can have circular dependencies /// </summary> /// <param name="schema"></param> /// <param name="combinedMapping"></param> /// <param name="typeName"></param> /// <returns></returns> public static Models.Field[] BuildFieldsForType(ISchemaProvider schema, CombinedMapping combinedMapping, string typeName) { if (typeName == "Query") { return(BuildRootQueryFields(schema, combinedMapping)); } if (typeName == "Mutation") { return(BuildMutationFields(schema, combinedMapping)); } var fieldDescs = new List <Models.Field>(); if (!schema.HasType(typeName)) { return(fieldDescs.ToArray()); } var type = schema.Type(typeName); foreach (var field in type.GetFields()) { if (field.Name.StartsWith("__")) { continue; } fieldDescs.Add(new Models.Field { Args = BuildArgs(schema, combinedMapping, field).ToArray(), DeprecationReason = "", Description = field.Description, IsDeprecated = false, Name = SchemaGenerator.ToCamelCaseStartsLower(field.Name), Type = BuildType(schema, field.ReturnTypeClr, field.GetReturnType(schema), combinedMapping), }); } return(fieldDescs.ToArray()); }
private static IEnumerable <TypeElement> BuildScalarTypes(ISchemaProvider schema, CombinedMapping combinedMapping) { var types = new List <TypeElement>(); foreach (var customScalar in schema.CustomScalarTypes) { var typeElement = new TypeElement { Kind = "SCALAR", Name = customScalar, Description = null, }; types.Add(typeElement); } return(types); }
private static TypeElement BuildType(ISchemaProvider schema, Type clrType, string gqlTypeName, CombinedMapping combinedMapping, bool isInput = false) { // Is collection of objects? var type = new TypeElement(); if (clrType.IsEnumerableOrArray()) { type.Kind = "LIST"; type.Name = null; type.OfType = BuildType(schema, clrType.GetEnumerableOrArrayType(), gqlTypeName, combinedMapping, isInput); } else if (clrType.Name == "EntityQueryType`1") { type.Kind = "SCALAR"; type.Name = "String"; type.OfType = null; } else if (clrType.GetTypeInfo().IsEnum) { type.Kind = "ENUM"; type.Name = FindNamedMapping(clrType, combinedMapping, gqlTypeName); type.OfType = null; } else { // ConvertGqlRequiredOrList below handles NON_NULL by type mappings if (clrType.IsNullableType() || clrType.Name == "RequiredField`1") { clrType = clrType.GetGenericArguments()[0]; } type.Kind = combinedMapping.TypeIsScalar(clrType) ? "SCALAR" : "OBJECT"; type.OfType = null; if (type.Kind == "OBJECT" && isInput) { type.Kind = "INPUT_OBJECT"; } type.Name = FindNamedMapping(clrType, combinedMapping, gqlTypeName); type = ConvertGqlRequiredOrList(type); } if (type.Name != null && type.Name.Contains("float")) { var t = 0; t++; } return(type); }