/// <summary> /// Provided two composite types, determine if they "overlap". Two composite /// types overlap when the Sets of possible concrete types for each intersect. /// /// This is often used to determine if a fragment of a given type could possibly /// be visited in a context of another type. /// /// This function is commutative. /// </summary> public static bool DoTypesOverlap(this ISchema schema, GraphType typeA, GraphType typeB) { if (typeA.Equals(typeB)) { return(true); } var a = typeA as GraphQLAbstractType; var b = typeB as GraphQLAbstractType; if (a != null) { if (b != null) { return(a.PossibleTypes.Any(type => b.IsPossibleType(type))); } return(a.IsPossibleType(typeB)); } if (b != null) { return(b.IsPossibleType(typeA)); } return(false); }
public Dictionary <string, Fields> CollectFields(ExecutionContext context, GraphType type, Selections selections, Dictionary <string, Fields> fields) { if (fields == null) { fields = new Dictionary <string, Fields>(); } selections.Apply(selection => { if (selection.Field != null) { if (!ShouldIncludeNode(context, selection.Field.Directives)) { return; } var name = selection.Field.Alias ?? selection.Field.Name; if (!fields.ContainsKey(name)) { fields[name] = new Fields(); } fields[name].Add(selection.Field); } else if (selection.Fragment != null) { if (selection.Fragment is FragmentSpread) { var spread = selection.Fragment as FragmentSpread; if (!ShouldIncludeNode(context, spread.Directives)) { return; } var fragment = context.Fragments.FindDefinition(spread.Name); if (!ShouldIncludeNode(context, fragment.Directives) || !DoesFragmentConditionMatch(context, fragment, type)) { return; } CollectFields(context, type, fragment.Selections, fields); } else if (selection.Fragment is InlineFragment) { var inline = selection.Fragment as InlineFragment; if (!ShouldIncludeNode(context, inline.Directives) || !DoesFragmentConditionMatch(context, inline, type)) { return; } CollectFields(context, type, inline.Selections, fields); } } }); return(fields); }
public static bool IsInputType(this GraphType type, ISchema schema) { var namedType = type.GetNamedType(schema); return(namedType is ScalarGraphType || namedType is EnumerationGraphType || namedType is InputObjectGraphType); }
public NonNullGraphType(GraphType type) { if (type.GetType() == typeof(NonNullGraphType)) { throw new ArgumentException("Cannot nest NonNull inside NonNull.", "type"); } Type = type; }
public IValue AstFromValue(ISchema schema, object value, GraphType type) { if (type is NonNullGraphType) { var nonnull = (NonNullGraphType)type; return(AstFromValue(schema, value, schema.FindType(nonnull.Type))); } if (value is Dictionary <string, object> ) { var dict = (Dictionary <string, object>)value; var fields = dict .Select(pair => new ObjectField(pair.Key, AstFromValue(schema, pair.Value, null))) .ToList(); return(new ObjectValue(fields)); } if (!(value is string) && value is IEnumerable) { GraphType itemType = null; var listType = type as ListGraphType; if (listType != null) { itemType = schema.FindType(listType.Type); } var list = (IEnumerable)value; var values = list.Map(item => AstFromValue(schema, item, itemType)); return(new ListValue(values)); } if (value is bool) { return(new BooleanValue((bool)value)); } if (value is int) { return(new IntValue((int)value)); } if (value is long) { return(new LongValue((long)value)); } if (value is double) { return(new FloatValue((double)value)); } return(new StringValue(value?.ToString())); }
public bool IsValidValue(ISchema schema, GraphType type, object input) { if (type is NonNullGraphType) { if (input == null) { return(false); } return(IsValidValue(schema, schema.FindType(((NonNullGraphType)type).Type), input)); } if (input == null) { return(true); } if (type is ListGraphType) { var listType = (ListGraphType)type; var listItemType = schema.FindType(listType.Type); var list = input as IEnumerable; return(list != null && !(input is string) ? list.All(item => IsValidValue(schema, listItemType, item)) : IsValidValue(schema, listItemType, input)); } if (type is ObjectGraphType || type is InputObjectGraphType) { var dict = input as Dictionary <string, object>; if (dict == null) { return(false); } // ensure every provided field is defined if (type is InputObjectGraphType && dict.Keys.Any(key => type.Fields.FirstOrDefault(field => field.Name == key) == null)) { return(false); } return(type.Fields.All(field => IsValidValue(schema, schema.FindType(field.Type), dict.ContainsKey(field.Name) ? dict[field.Name] : null))); } if (type is ScalarGraphType) { var scalar = (ScalarGraphType)type; return(scalar.Coerce(input) != null); } return(false); }
/// <summary> /// Provided a type and a super type, return true if the first type is either /// equal or a subset of the second super type (covariant). /// </summary> public static bool IsSubtypeOf(this GraphType maybeSubType, GraphType superType, ISchema schema) { if (maybeSubType.Equals(superType)) { return(true); } // If superType is non-null, maybeSubType must also be nullable. if (superType is NonNullGraphType) { if (maybeSubType is NonNullGraphType) { var sub = (NonNullGraphType)maybeSubType; var sup = (NonNullGraphType)superType; return(IsSubtypeOf(schema.FindType(sub.Type), schema.FindType(sup.Type), schema)); } return(false); } else if (maybeSubType is NonNullGraphType) { var sub = (NonNullGraphType)maybeSubType; return(IsSubtypeOf(schema.FindType(sub.Type), superType, schema)); } // If superType type is a list, maybeSubType type must also be a list. if (superType is ListGraphType) { if (maybeSubType is ListGraphType) { var sub = (ListGraphType)maybeSubType; var sup = (ListGraphType)superType; return(IsSubtypeOf(schema.FindType(sub.Type), schema.FindType(sup.Type), schema)); } return(false); } else if (maybeSubType is ListGraphType) { // If superType is not a list, maybeSubType must also be not a list. return(false); } // If superType type is an abstract type, maybeSubType type may be a currently // possible object type. if (superType is GraphQLAbstractType && maybeSubType is ObjectGraphType) { return(((GraphQLAbstractType)superType).IsPossibleType(maybeSubType)); } return(false); }
private void CollectTypes(GraphType type, GraphTypesLookup lookup) { if (type == null) { return; } lookup[type.Name] = type; type.Fields.Apply(field => { CollectTypes(field.Type, lookup); }); }
// TODO: combine duplication with CoerceValue public object CoerceValueAst(Schema schema, GraphType type, object input, Variables variables) { if (type is NonNullGraphType) { var nonNull = type as NonNullGraphType; return(CoerceValueAst(schema, schema.FindType(nonNull.Type), input, variables)); } if (input == null) { return(null); } if (input is Variable) { return(variables != null ? variables.ValueFor(((Variable)input).Name) : null); } if (type is ListGraphType) { var listType = type as ListGraphType; var list = input as IEnumerable; return(list != null ? list.Map(item => CoerceValueAst(schema, listType, item, variables)) : new[] { input }); } if (type is ObjectGraphType) { var objType = type as ObjectGraphType; var obj = new Dictionary <string, object>(); var dict = (Dictionary <string, object>)input; objType.Fields.Apply(field => { var fieldValue = CoerceValueAst(schema, schema.FindType(field.Type), dict[field.Name], variables); obj[field.Name] = fieldValue ?? field.DefaultValue; }); } if (type is ScalarGraphType) { var scalarType = type as ScalarGraphType; return(scalarType.Coerce(input)); } return(input); }
public GraphType this[string typeName] { get { GraphType result = null; if (_types.ContainsKey(typeName)) { result = _types[typeName]; } return(result); } set { _types[typeName] = value; } }
public static GraphType GetNamedType(this GraphType type, ISchema schema) { GraphType unmodifiedType = type; if (type is NonNullGraphType) { var nonNull = (NonNullGraphType)type; return(GetNamedType(schema.FindType(nonNull.Type), schema)); } if (type is ListGraphType) { var list = (ListGraphType)type; return(GetNamedType(schema.FindType(list.Type), schema)); } return(unmodifiedType); }
public bool IsValidValue(Schema schema, GraphType type, object input) { if (type is NonNullGraphType) { if (input == null) { return(false); } return(IsValidValue(schema, schema.FindType(((NonNullGraphType)type).Type), input)); } if (input == null) { return(true); } if (type is ListGraphType) { var listType = (ListGraphType)type; var list = input as IEnumerable; return(list != null ? list.All(item => IsValidValue(schema, type, item)) : IsValidValue(schema, listType, input)); } if (type is ObjectGraphType) { var dict = input as Dictionary <string, object>; return(dict != null && type.Fields.All(field => IsValidValue(schema, schema.FindType(field.Type), dict[field.Name]))); } if (type is ScalarGraphType) { var scalar = (ScalarGraphType)type; return(scalar.Coerce(input) != null); } return(false); }
public Dictionary <string, Fields> CollectFields(ExecutionContext context, GraphType type, Selections selections, Dictionary <string, Fields> fields) { if (fields == null) { fields = new Dictionary <string, Fields>(); } selections.Apply(selection => { if (selection.Field != null) { var name = selection.Field.Alias ?? selection.Field.Name; if (!fields.ContainsKey(name)) { fields[name] = new Fields(); } fields[name].Add(selection.Field); } }); return(fields); }
public object CoerceValue(GraphType type, object input) { if (type is NonNullGraphType) { var nonNull = type as NonNullGraphType; return(CoerceValue(nonNull.Type, input)); } if (type is ListGraphType) { var listType = type as ListGraphType; var list = input as IEnumerable; return(list != null ? list.Map(item => CoerceValue(listType, item)) : new[] { input }); } if (type is ObjectGraphType) { var objType = type as ObjectGraphType; var obj = new Dictionary <string, object>(); objType.Fields.Apply(field => { var dict = (Dictionary <string, object>)input; var fieldValue = CoerceValue(field.Type, dict[field.Name]); obj[field.Name] = fieldValue ?? field.DefaultValue; }); } if (type is ScalarGraphType) { var scalarType = type as ScalarGraphType; return(scalarType.Coerce(input)); } return(null); }
public async Task <object> CompleteValue(ExecutionContext context, GraphType fieldType, Fields fields, object result) { if (fieldType is NonNullGraphType) { var nonNullType = fieldType as NonNullGraphType; var completed = await CompleteValue(context, context.Schema.FindType(nonNullType.Type), fields, result); if (completed == null) { throw new ExecutionError("Cannot return null for non-null type. Field: {0}".ToFormat(nonNullType.Name)); } return(completed); } if (result == null) { return(null); } if (fieldType is ScalarGraphType) { var scalarType = fieldType as ScalarGraphType; var coercedValue = scalarType.Coerce(result); return(coercedValue); } if (fieldType is ListGraphType) { var list = result as IEnumerable; if (list == null) { throw new ExecutionError("User error: expected an IEnumerable list though did not find one."); } var listType = fieldType as ListGraphType; var itemType = context.Schema.FindType(listType.Type); var results = await list.MapAsync(async item => { return(await CompleteValue(context, itemType, fields, item)); }); return(results); } var objectType = fieldType as ObjectGraphType; if (fieldType is InterfaceGraphType) { var interfaceType = fieldType as InterfaceGraphType; objectType = interfaceType.ResolveType(result); } if (objectType == null) { return(null); } var subFields = new Dictionary <string, Fields>(); fields.Apply(field => { subFields = CollectFields(context, objectType, field.Selections, subFields); }); return(await ExecuteFields(context, objectType, result, subFields)); }
public static IEnumerable <string> IsValidLiteralValue(this GraphType type, IValue valueAst, ISchema schema) { if (type is NonNullGraphType) { var nonNull = (NonNullGraphType)type; var ofType = schema.FindType(nonNull.Type); if (valueAst == null) { if (ofType != null) { return(new[] { $"Expected \"{ofType.Name}!\", found null." }); } return(new[] { "Expected non-null value, found null" }); } return(IsValidLiteralValue(ofType, valueAst, schema)); } if (valueAst == null) { return(new string[] {}); } // This function only tests literals, and assumes variables will provide // values of the correct type. if (valueAst is VariableReference) { return(new string[] {}); } if (type is ListGraphType) { var list = (ListGraphType)type; var ofType = schema.FindType(list.Type); if (valueAst is ListValue) { var index = 0; return(((ListValue)valueAst).Values.Aggregate(new string[] {}, (acc, value) => { var errors = IsValidLiteralValue(ofType, value, schema); var result = acc.Concat(errors.Map(err => $"In element #{index}: {err}")).ToArray(); index++; return result; })); } return(IsValidLiteralValue(ofType, valueAst, schema)); } if (type is InputObjectGraphType) { if (!(valueAst is ObjectValue)) { return(new[] { $"Expected \"{type.Name}\", found not an object." }); } var inputType = (InputObjectGraphType)type; var fields = inputType.Fields.ToList(); var fieldAsts = ((ObjectValue)valueAst).ObjectFields.ToList(); var errors = new List <string>(); // ensure every provided field is defined fieldAsts.Apply(providedFieldAst => { var found = fields.FirstOrDefault(x => x.Name == providedFieldAst.Name); if (found == null) { errors.Add($"In field \"{providedFieldAst.Name}\": Unknown field."); } }); // ensure every defined field is valid fields.Apply(field => { var fieldAst = fieldAsts.FirstOrDefault(x => x.Name == field.Name); var result = IsValidLiteralValue(schema.FindType(field.Type), fieldAst?.Value, schema); errors.AddRange(result.Map(err => $"In field \"{field.Name}\": {err}")); }); return(errors); } var scalar = (ScalarGraphType)type; var parseResult = scalar.ParseLiteral(valueAst); if (parseResult == null) { return(new [] { $"Expected type \"{type.Name}\", found {AstPrinter.Print(valueAst)}." }); } return(new string[] {}); }
public object CoerceValueAst(GraphType type, object input) { return(input); }
public static bool IsCompositeType(this GraphType type) { return(type is ObjectGraphType || type is InterfaceGraphType || type is UnionGraphType); }
public bool DoesFragmentConditionMatch(ExecutionContext context, IHaveFragmentType fragment, GraphType type) { if (string.IsNullOrWhiteSpace(fragment.Type)) { return(true); } var conditionalType = context.Schema.FindType(fragment.Type); if (conditionalType == null) { return(false); } if (conditionalType.Equals(type)) { return(true); } if (conditionalType is GraphQLAbstractType) { var abstractType = (GraphQLAbstractType)conditionalType; return(abstractType.IsPossibleType(type)); } return(false); }
public bool IsValidValue(ISchema schema, GraphType type, IType astType, object input) { if (type is NonNullGraphType) { if (input == null) { return(false); } var nonNullType = schema.FindType(((NonNullGraphType)type).Type); if (nonNullType is ScalarGraphType) { var val = ValueFromScalar((ScalarGraphType)nonNullType, input); return(val != null); } return(IsValidValue(schema, nonNullType, astType, input)); } if (astType is NonNullType) { if (input == null) { return(false); } if (type is ScalarGraphType) { var val = ValueFromScalar((ScalarGraphType)type, input); return(val != null); } } if (input == null) { return(true); } if (input is StringValue) { var stringVal = (StringValue)input; if (stringVal.Value == null) { return(true); } } if (type is ListGraphType) { var listType = (ListGraphType)type; var listItemType = schema.FindType(listType.Type); var list = input as IEnumerable; if (list != null && !(input is string)) { return(list.All(item => IsValidValue(schema, listItemType, astType, item))); } var listValue = input as ListValue; if (listValue != null) { return(listValue.Values.All(item => IsValidValue(schema, listItemType, astType, item))); } return(IsValidValue(schema, listItemType, astType, input)); } if (type is ObjectGraphType || type is InputObjectGraphType) { var dict = input as ObjectValue; if (dict == null) { return(false); } // ensure every provided field is defined if (type is InputObjectGraphType && dict.FieldNames.Any(key => type.Fields.FirstOrDefault(field => field.Name == key) == null)) { return(false); } return(type.Fields.All(field => IsValidValue( schema, schema.FindType(field.Type), astType, dict.Field(field.Name)?.Value))); } if (type is ScalarGraphType) { var scalar = (ScalarGraphType)type; var value = ValueFromScalar(scalar, input); return(value != null); } return(false); }
public object CoerceValue(ISchema schema, GraphType type, IValue input, Variables variables = null) { if (type is NonNullGraphType) { var nonNull = type as NonNullGraphType; return(CoerceValue(schema, schema.FindType(nonNull.Type), input, variables)); } if (input == null) { return(null); } var variable = input as VariableReference; if (variable != null) { return(variables != null ? variables.ValueFor(variable.Name) : null); } if (type is ListGraphType) { var listType = type as ListGraphType; var listItemType = schema.FindType(listType.Type); var list = input as ListValue; return(list != null ? list.Values.Map(item => CoerceValue(schema, listItemType, item, variables)).ToArray() : new[] { CoerceValue(schema, listItemType, input, variables) }); } if (type is ObjectGraphType || type is InputObjectGraphType) { var obj = new Dictionary <string, object>(); var objectValue = input as ObjectValue; if (objectValue == null) { return(null); } type.Fields.Apply(field => { var objectField = objectValue.Field(field.Name); if (objectField != null) { var fieldValue = CoerceValue(schema, schema.FindType(field.Type), objectField.Value, variables); fieldValue = fieldValue ?? field.DefaultValue; obj[field.Name] = fieldValue; } }); return(obj); } if (type is ScalarGraphType) { var scalarType = type as ScalarGraphType; return(scalarType.ParseLiteral(input)); } return(null); }
public async Task <object> CompleteValue(ExecutionContext context, GraphType fieldType, Fields fields, object result) { var nonNullType = fieldType as NonNullGraphType; if (nonNullType != null) { var type = context.Schema.FindType(nonNullType.Type); var completed = await CompleteValue(context, type, fields, result); if (completed == null) { var field = fields != null?fields.FirstOrDefault() : null; var fieldName = field != null ? field.Name : null; throw new ExecutionError("Cannot return null for non-null type. Field: {0}, Type: {1}!." .ToFormat(fieldName, type.Name)); } return(completed); } if (result == null) { return(null); } if (fieldType is ScalarGraphType) { var scalarType = fieldType as ScalarGraphType; var coercedValue = scalarType.Coerce(result); return(coercedValue); } if (fieldType is ListGraphType) { var list = result as IEnumerable; if (list == null) { throw new ExecutionError("User error: expected an IEnumerable list though did not find one."); } var listType = fieldType as ListGraphType; var itemType = context.Schema.FindType(listType.Type); var results = await list.MapAsync(async item => { return(await CompleteValue(context, itemType, fields, item)); }); return(results); } var objectType = fieldType as ObjectGraphType; if (fieldType is GraphQLAbstractType) { var abstractType = fieldType as GraphQLAbstractType; objectType = abstractType.GetObjectType(result); if (objectType != null && !abstractType.IsPossibleType(objectType)) { throw new ExecutionError( "Runtime Object type \"{0}\" is not a possible type for \"{1}\"" .ToFormat(objectType, abstractType)); } } if (objectType == null) { return(null); } if (objectType.IsTypeOf != null && !objectType.IsTypeOf(result)) { throw new ExecutionError( "Expected value of type \"{0}\" but got: {1}." .ToFormat(objectType, result)); } var subFields = new Dictionary <string, Fields>(); var visitedFragments = new List <string>(); fields.Apply(field => { subFields = CollectFields(context, objectType, field.Selections, subFields, visitedFragments); }); return(await ExecuteFields(context, objectType, result, subFields)); }
public Dictionary <string, Fields> CollectFields( ExecutionContext context, GraphType specificType, SelectionSet selectionSet, Dictionary <string, Fields> fields, List <string> visitedFragmentNames) { if (fields == null) { fields = new Dictionary <string, Fields>(); } selectionSet.Selections.Apply(selection => { if (selection is Field) { var field = (Field)selection; if (!ShouldIncludeNode(context, field.Directives)) { return; } var name = field.Alias ?? field.Name; if (!fields.ContainsKey(name)) { fields[name] = new Fields(); } fields[name].Add(field); } else if (selection is FragmentSpread) { var spread = (FragmentSpread)selection; if (visitedFragmentNames.Contains(spread.Name) || !ShouldIncludeNode(context, spread.Directives)) { return; } visitedFragmentNames.Add(spread.Name); var fragment = context.Fragments.FindDefinition(spread.Name); if (fragment == null || !ShouldIncludeNode(context, fragment.Directives) || !DoesFragmentConditionMatch(context, fragment.Type.Name, specificType)) { return; } CollectFields(context, specificType, fragment.SelectionSet, fields, visitedFragmentNames); } else if (selection is InlineFragment) { var inline = (InlineFragment)selection; if (!ShouldIncludeNode(context, inline.Directives) || !DoesFragmentConditionMatch(context, inline.Type.Name, specificType)) { return; } CollectFields(context, specificType, inline.SelectionSet, fields, visitedFragmentNames); } }); return(fields); }
public bool DoesFragmentConditionMatch(ExecutionContext context, IHaveFragmentType fragment, GraphType type) { var conditionalType = context.Schema.FindType(fragment.Type); if (conditionalType == type) { return(true); } if (conditionalType is InterfaceGraphType) { var interfaceType = (InterfaceGraphType)conditionalType; var hasInterfaces = type as IImplementInterfaces; if (hasInterfaces != null) { var interfaces = context.Schema.FindTypes(hasInterfaces.Interfaces); return(interfaceType.IsPossibleType(interfaces)); } } return(false); }
public object CoerceValue(ISchema schema, GraphType type, object input, Variables variables = null) { if (type is NonNullGraphType) { var nonNull = type as NonNullGraphType; return(CoerceValue(schema, schema.FindType(nonNull.Type), input, variables)); } if (input == null) { return(null); } var variable = input as Variable; if (variable != null) { return(variables != null ? variables.ValueFor(variable.Name) : null); } if (type is ListGraphType) { var listType = type as ListGraphType; var listItemType = schema.FindType(listType.Type); var list = input as IEnumerable; return(list != null && !(input is string) ? list.Map(item => CoerceValue(schema, listItemType, item, variables)).ToArray() : new[] { CoerceValue(schema, listItemType, input, variables) }); } if (type is ObjectGraphType || type is InputObjectGraphType) { var obj = new Dictionary <string, object>(); if (input is KeyValuePair <string, object> ) { var kvp = (KeyValuePair <string, object>)input; input = new Dictionary <string, object> { { kvp.Key, kvp.Value } }; } var kvps = input as IEnumerable <KeyValuePair <string, object> >; if (kvps != null) { input = kvps.ToDictionary(kvp => kvp.Key, kvp => kvp.Value); } var dict = input as Dictionary <string, object>; if (dict == null) { return(null); } type.Fields.Apply(field => { object inputValue; if (dict.TryGetValue(field.Name, out inputValue)) { var fieldValue = CoerceValue(schema, schema.FindType(field.Type), inputValue, variables); obj[field.Name] = fieldValue ?? field.DefaultValue; } }); return(obj); } if (type is ScalarGraphType) { var scalarType = type as ScalarGraphType; return(scalarType.Coerce(input)); } return(input); }