/// <inheritdoc/> public void Leave(INode node, ValidationContext context) { _ancestorStack.Pop(); if (node is SelectionSet) { _parentTypeStack.Pop(); } else if (node is Field) { _fieldDefStack.Pop(); _typeStack.Pop(); } else if (node is Directive) { _directive = null; } else if (node is Operation || node is FragmentDefinition || node is InlineFragment) { _typeStack.Pop(); } else if (node is VariableDefinition) { _inputTypeStack.Pop(); } else if (node is Argument) { _argument = null; _inputTypeStack.Pop(); } else if (node is ListValue || node is ObjectField) { _inputTypeStack.Pop(); } }
/// <inheritdoc/> public virtual Task <bool> AllowDirective(DirectiveGraphType directive) { if (directive.Introspectable.HasValue) { return(directive.Introspectable.Value ? Allowed : Forbidden); } // If the directive has all its locations of type ExecutableDirectiveLocation, // only then it will be present in the introspection response. foreach (var location in directive.Locations) { if (!( location == DirectiveLocation.Query || location == DirectiveLocation.Mutation || location == DirectiveLocation.Subscription || location == DirectiveLocation.Field || location == DirectiveLocation.FragmentDefinition || location == DirectiveLocation.FragmentSpread || location == DirectiveLocation.InlineFragment)) { return(Forbidden); } } return(Allowed); }
public void InputTypeIsDereferenced_DirectiveArgument(Type referenceType, Type mappedType) { var query = new ObjectGraphType(); query.Field(typeof(StringGraphType), "test"); var schema = new Schema { Query = query }; var directive = new DirectiveGraphType("MyDirective") { Arguments = new QueryArguments { new QueryArgument(referenceType) { Name = "arg" } } }; directive.Locations.Add(DirectiveLocation.Field); schema.Directives.Register(directive); schema.RegisterTypeMapping(typeof(MyClass), typeof(MyClassObjectType)); schema.RegisterTypeMapping(typeof(MyClass), typeof(MyClassInputType)); schema.RegisterTypeMapping(typeof(MappedEnum), typeof(MappedEnumGraphType)); schema.Initialize(); schema.Directives.Find("MyDirective").Arguments.Find("arg").Type.ShouldBe(mappedType); }
public void prints_directive_without_arguments() { var d = new DirectiveGraphType("my", DirectiveLocation.Field, DirectiveLocation.Query); string result = new SchemaPrinter(null).PrintDirective(d); result.ShouldBe("directive @my on FIELD | QUERY"); }
protected virtual DirectiveGraphType ToDirective(GraphQLDirectiveDefinition directiveDef) { var result = new DirectiveGraphType((string)directiveDef.Name.Value) { Description = directiveDef.Description?.Value.ToString() ?? directiveDef.Comment?.Text.ToString(), Repeatable = directiveDef.Repeatable, Arguments = ToQueryArguments(directiveDef.Arguments) }; if (directiveDef.Locations?.Count > 0) // just in case { foreach (var location in directiveDef.Locations) { if (__DirectiveLocation.Instance.Values.FindByName(location.Value)?.Value is DirectiveLocation l) { result.Locations.Add(l); } else { throw new InvalidOperationException($"Directive '{result.Name}' has an unknown directive location '{location.Value}'."); } } } return(result); }
internal Directive(DirectiveGraphType oldDirective, DirectiveGraphType newDirective) { this.oldDirective = oldDirective; this.newDirective = newDirective; this.oldArguments = oldDirective.Arguments; this.newArguments = newDirective.Arguments; }
public void Leave(INode node) { if (node is Operation || node is FragmentDefinition) { _typeStack.Pop(); } if (node is SelectionSet) { _parentTypeStack.Pop(); } if (node is Field) { _fieldDefStack.Pop(); _typeStack.Pop(); } if (node is Directive) { _directive = null; } if (node is Argument) { _argument = null; _inputTypeStack.Pop(); } }
public override void VisitDirective(DirectiveGraphType directive, ISchema schema) { if (directive.Locations.Count == 0) { throw new InvalidOperationException($"Directive '{directive}' must have locations"); } }
/// <summary> /// Initializes a new instance with the specified properties. /// </summary> public KnownArgumentNamesError(ValidationContext context, Argument node, DirectiveGraphType directive) : base(context.OriginalQuery, NUMBER, UnknownDirectiveArgMessage( node.Name, directive.Name, StringUtils.SuggestionList(node.Name, directive.Arguments?.Select(q => q.Name))), node) { }
public string PrintDirective(DirectiveGraphType directive) { var builder = new StringBuilder(); builder.Append(PrintDescription(directive.Description)); builder.AppendLine($"directive @{directive.Name}("); builder.AppendLine(formatDirectiveArguments(directive.Arguments)); builder.Append($") on {formatDirectiveLocationList(directive.Locations)}"); return(builder.ToString().TrimStart()); }
protected virtual DirectiveGraphType ToDirective(GraphQLDirectiveDefinition directiveDef) { var locations = directiveDef.Locations.Select(l => ToDirectiveLocation(l.Value)); var directive = new DirectiveGraphType(directiveDef.Name.Value, locations); var arguments = directiveDef.Arguments.Select(ToArguments); directive.Arguments = new QueryArguments(arguments); return(directive); }
protected virtual DirectiveGraphType ToDirective(GraphQLDirectiveDefinition directiveDef) { var locations = directiveDef.Locations.Select(l => ToDirectiveLocation(l.Value)); var directive = new DirectiveGraphType(directiveDef.Name.Value, locations) { Description = directiveDef.Comment?.Text }; directive.Arguments = ToQueryArguments(directiveDef.Arguments); return(directive); }
private void ValidateDirectiveArgumentsUniqueness(DirectiveGraphType type) { if (type.Arguments?.Count > 0) { foreach (var item in type.Arguments.List.ToLookup(f => f.Name)) { if (item.Count() > 1) { throw new InvalidOperationException($"The argument '{item.Key}' must have a unique name within directive '{type.Name}'; no two directive arguments may share the same name."); } } } }
public string PrintType(IGraphType type) { return(type switch { EnumerationGraphType graphType => PrintEnum(graphType), ScalarGraphType scalarGraphType => PrintScalar(scalarGraphType), IObjectGraphType objectGraphType => PrintObject(objectGraphType), IInterfaceGraphType interfaceGraphType => PrintInterface(interfaceGraphType), UnionGraphType unionGraphType => PrintUnion(unionGraphType), DirectiveGraphType directiveGraphType => PrintDirective(directiveGraphType), //TODO: DirectiveGraphType does not inherit IGraphType IInputObjectGraphType input => PrintInputObject(input), _ => throw new InvalidOperationException($"Unknown GraphType '{type.GetType().Name}' with name '{type.Name}'") });
public void prints_repeatable_directive_with_arguments() { var d = new DirectiveGraphType("my", DirectiveLocation.Field, DirectiveLocation.Query) { Repeatable = true, Arguments = new QueryArguments(new QueryArgument(new IntGraphType()) { Name = "max" }) }; string result = new SchemaPrinter(null).PrintDirective(d); result.ShouldBe(@"directive @my( max: Int ) repeatable on FIELD | QUERY"); }
// See 'Type Validation' section in https://spec.graphql.org/June2018/#sec-Type-System.Directives // Directive types have the potential to be invalid if incorrectly defined. /// <inheritdoc/> public override void VisitDirective(DirectiveGraphType type, ISchema schema) { if (type.Locations.Count == 0) { throw new InvalidOperationException($"Directive '{type.Name}' must have locations"); } // 1. A directive definition must not contain the use of a directive which references itself directly. // TODO: // 2. A directive definition must not contain the use of a directive which references itself indirectly // by referencing a Type or Directive which transitively includes a reference to this directive. // TODO: // 3 if (type.Name.StartsWith("__")) { throw new InvalidOperationException($"The directive '{type.Name}' must not have a name which begins with the __ (two underscores)."); } }
/// <summary> /// Inspects the given type and, in accordance with the rules of this maker, will /// generate a complete set of necessary graph types required to support it. /// </summary> /// <param name="concreteType">The concrete type to incorporate into the schema.</param> /// <returns>GraphTypeCreationResult.</returns> public GraphTypeCreationResult CreateGraphType(Type concreteType) { var formatter = _schema.Configuration.DeclarationOptions.GraphNamingFormatter; var template = GraphQLProviders.TemplateProvider.ParseType(concreteType) as IGraphDirectiveTemplate; if (template == null) { return(null); } var result = new GraphTypeCreationResult(); var directive = new DirectiveGraphType( formatter.FormatFieldName(template.Name), template.Locations, template.ObjectType, template.CreateResolver()) { Description = template.Description, Publish = template.Publish, }; // all arguments are required to have the same signature via validation // can use any method to fill the arg field list var argMaker = new GraphArgumentMaker(_schema); foreach (var argTemplate in template.Arguments) { var argumentResult = argMaker.CreateArgument(argTemplate); directive.Arguments.AddArgument(argumentResult.Argument); result.MergeDependents(argumentResult); } result.GraphType = directive; result.ConcreteType = concreteType; return(result); }
public DirectiveAdded(DirectiveGraphType directive) : base(Criticality.NonBreaking) { this.directive = directive; }
public override void VisitDirective(DirectiveGraphType directive, ISchema schema) => SetDescription(directive);
public override void VisitDirectiveArgumentDefinition(QueryArgument argument, DirectiveGraphType type, ISchema schema) => Replace(argument);
public void Enter(INode node) { _ancestorStack.Push(node); if (node is SelectionSet) { _parentTypeStack.Push(GetLastType()); return; } if (node is Field field) { var parentType = _parentTypeStack.Peek().GetNamedType(); var fieldType = GetFieldDef(_schema, parentType, field); _fieldDefStack.Push(fieldType); var targetType = fieldType?.ResolvedType; _typeStack.Push(targetType); return; } if (node is Directive directive) { _directive = _schema.FindDirective(directive.Name); } if (node is Operation op) { IGraphType type = null; if (op.OperationType == OperationType.Query) { type = _schema.Query; } else if (op.OperationType == OperationType.Mutation) { type = _schema.Mutation; } else if (op.OperationType == OperationType.Subscription) { type = _schema.Subscription; } _typeStack.Push(type); return; } if (node is FragmentDefinition def1) { var type = _schema.FindType(def1.Type.Name); _typeStack.Push(type); return; } if (node is InlineFragment def) { var type = def.Type != null?_schema.FindType(def.Type.Name) : GetLastType(); _typeStack.Push(type); return; } if (node is VariableDefinition varDef) { var inputType = varDef.Type.GraphTypeFromType(_schema); _inputTypeStack.Push(inputType); return; } if (node is Argument argAst) { QueryArgument argDef = null; IGraphType argType = null; var args = GetDirective() != null?GetDirective()?.Arguments : GetFieldDef()?.Arguments; if (args != null) { argDef = args.Find(argAst.Name); argType = argDef?.ResolvedType; } _argument = argDef; _inputTypeStack.Push(argType); } if (node is ListValue) { var type = GetInputType().GetNamedType(); _inputTypeStack.Push(type); } if (node is ObjectField objectField) { var objectType = GetInputType().GetNamedType(); IGraphType fieldType = null; if (objectType is IInputObjectGraphType complexType) { var inputField = complexType.GetField(objectField.Name); fieldType = inputField?.ResolvedType; } _inputTypeStack.Push(fieldType); } }
/// <inheritdoc /> public virtual void VisitDirective(DirectiveGraphType type, ISchema schema) { }
/// <inheritdoc /> public virtual void VisitDirectiveArgumentDefinition(QueryArgument argument, DirectiveGraphType type, ISchema schema) { }
/// <inheritdoc/> public void VisitDirectiveArgumentDefinition(QueryArgument argument, DirectiveGraphType type, ISchema schema) => ValidateAppliedDirectives(argument, schema, DirectiveLocation.ArgumentDefinition);
public DirectiveRemoved(DirectiveGraphType directive) : base(Criticality.Breaking) { this.directive = directive; }
public void Enter(INode node) { _ancestorStack.Push(node); if (node is SelectionSet) { _parentTypeStack.Push(GetLastType()); return; } if (node is Field) { var field = (Field)node; var parentType = _parentTypeStack.Peek().GetNamedType(_schema); var fieldType = GetFieldDef(_schema, parentType, field); _fieldDefStack.Push(fieldType); var targetType = _schema.FindType(fieldType?.Type); _typeStack.Push(targetType); return; } if (node is Directive) { var directive = (Directive)node; _directive = _schema.Directives.SingleOrDefault(x => x.Name == directive.Name); } if (node is Operation) { var op = (Operation)node; IGraphType type = null; if (op.OperationType == OperationType.Query) { type = _schema.Query; } else if (op.OperationType == OperationType.Mutation) { type = _schema.Mutation; } else if (op.OperationType == OperationType.Subscription) { type = _schema.Subscription; } _typeStack.Push(type); return; } if (node is FragmentDefinition) { var def = (FragmentDefinition)node; var type = _schema.FindType(def.Type.Name); _typeStack.Push(type); return; } if (node is InlineFragment) { var def = (InlineFragment)node; var type = def.Type != null?_schema.FindType(def.Type.Name) : GetLastType(); _typeStack.Push(type); return; } if (node is VariableDefinition) { var varDef = (VariableDefinition)node; var inputType = varDef.Type.GraphTypeFromType(_schema); _inputTypeStack.Push(inputType); return; } if (node is Argument) { var argAst = (Argument)node; QueryArgument argDef = null; IGraphType argType = null; var args = GetDirective() != null?GetDirective()?.Arguments : GetFieldDef()?.Arguments; if (args != null) { argDef = args.Find(argAst.Name); argType = _schema.FindType(argDef?.Type); } _argument = argDef; _inputTypeStack.Push(argType); } if (node is ListValue) { var type = GetInputType().GetNamedType(_schema); _inputTypeStack.Push(type); } if (node is ObjectField) { var objectType = GetInputType().GetNamedType(_schema); IGraphType fieldType = null; if (objectType is InputObjectGraphType) { var complexType = objectType as IComplexGraphType; var inputField = complexType.Fields.FirstOrDefault(x => x.Name == ((ObjectField)node).Name); fieldType = inputField != null?_schema.FindType(inputField.Type) : null; } _inputTypeStack.Push(fieldType); } }
/// <inheritdoc/> public void VisitDirective(DirectiveGraphType type, ISchema schema) => ValidateAppliedDirectives(type, schema, null); // no location for directives (yet), see https://github.com/graphql/graphql-spec/issues/818
/// <inheritdoc/> public virtual Task <bool> AllowDirective(DirectiveGraphType directive) => _completed;
/// <inheritdoc/> public override void VisitDirectiveArgumentDefinition(QueryArgument argument, DirectiveGraphType type, ISchema schema) { // 4.1 if (argument.Name.StartsWith("__")) { throw new InvalidOperationException($"The argument '{argument.Name}' of directive '{type.Name}' must not have a name which begins with the __ (two underscores)."); } if (argument.ResolvedType == null) { throw new InvalidOperationException($"The argument '{argument.Name}' of directive '{type.Name}' must have non-null '{nameof(IFieldType.ResolvedType)}' property."); } if (argument.ResolvedType is GraphQLTypeReference) { throw new InvalidOperationException($"The argument '{argument.Name}' of directive '{type.Name}' has '{nameof(GraphQLTypeReference)}' type. This type must be replaced with a reference to the actual GraphQL type before using the reference."); } // 4.2 if (!argument.ResolvedType.IsInputType()) { throw new InvalidOperationException($"The argument '{argument.Name}' of directive '{type.Name}' must be an input type."); } // validate default if (argument.DefaultValue is GraphQLValue value) { argument.DefaultValue = Execution.ExecutionHelper.CoerceValue(argument.ResolvedType, Language.CoreToVanillaConverter.Value(value)).Value; } else if (argument.DefaultValue != null && !argument.ResolvedType.IsValidDefault(argument.DefaultValue)) { throw new InvalidOperationException($"The default value of argument '{argument.Name}' of directive '{type.Name}' is invalid."); } }
public void Enter(INode node) { if (node is Operation) { var op = (Operation)node; GraphType type = null; if (op.OperationType == OperationType.Query) { type = _schema.Query; } else if (op.OperationType == OperationType.Mutation) { type = _schema.Mutation; } else if (op.OperationType == OperationType.Subscription) { } _typeStack.Push(type); return; } if (node is FragmentDefinition) { var def = (FragmentDefinition)node; var type = _schema.FindType(def.Type.Name); _typeStack.Push(type); return; } if (node is SelectionSet) { _parentTypeStack.Push(GetLastType()); return; } if (node is Field) { var field = (Field)node; var parentType = _parentTypeStack.Peek(); var fieldType = GetFieldDef(_schema, parentType, field); _fieldDefStack.Push(fieldType); var targetType = _schema.FindType(fieldType?.Type); _typeStack.Push(targetType); return; } if (node is Directive) { var directive = (Directive)node; _directive = _schema.Directives.SingleOrDefault(x => x.Name == directive.Name); } if (node is Argument) { var argAst = (Argument)node; QueryArgument argDef = null; GraphType argType = null; var args = GetDirective() != null?GetDirective()?.Arguments : GetFieldDef()?.Arguments; if (args != null) { argDef = args.Find(argAst.Name); argType = _schema.FindType(argDef?.Type); } _argument = argDef; _inputTypeStack.Push(argType); } }