/// <summary> /// Validates the completed document context to ensure it is "correct" against the specification before generating /// the final document. /// </summary> /// <param name="context">The context containing the parsed sections of a query document..</param> /// <returns><c>true</c> if the rule passes, <c>false</c> otherwise.</returns> public override bool Execute(DocumentConstructionContext context) { var node = (VariableValueNode)context.ActiveNode; var queryOperation = context.FindContextItem <QueryOperation>(); var queryValue = context.FindContextItem <QueryInputValue>() as QueryVariableReferenceInputValue; var variable = queryOperation.Variables[node.Value.ToString()]; variable.MarkAsReferenced(); queryValue?.AssignVariableReference(variable); return(true); }
/// <summary> /// Validates the specified node to ensure it is "correct" in the context of the rule doing the valdiation. /// </summary> /// <param name="context">The validation context encapsulating a <see cref="SyntaxNode" /> that needs to be validated.</param> /// <returns><c>true</c> if the node is valid, <c>false</c> otherwise.</returns> public override bool Execute(DocumentConstructionContext context) { var variable = context.FindContextItem <QueryVariable>(); var kind = variable.GraphType?.Kind ?? TypeKind.NONE; switch (kind) { case TypeKind.SCALAR: case TypeKind.ENUM: case TypeKind.INPUT_OBJECT: return(true); default: var errorName = variable.GraphType?.Name ?? "{null}"; var errorKind = variable.GraphType == null ? string.Empty : ", which is of kind '{variable.GraphType.Kind.ToString()}'"; this.ValidationError( context, $"Invalid Variable Graph Type. The variable named '${variable.Name}' references the graph type " + $"'{errorName}'{errorKind}. Only " + $"{TypeKind.SCALAR.ToString()}, {TypeKind.ENUM.ToString()} and '{TypeKind.INPUT_OBJECT.ToString()}' are allowed for " + "variable declarations."); return(false); } }
/// <summary> /// Validates the specified node to ensure it is "correct" in the context of the rule doing the valdiation. /// </summary> /// <param name="context">The validation context encapsulating a <see cref="SyntaxNode" /> that needs to be validated.</param> /// <returns><c>true</c> if the node is valid, <c>false</c> otherwise.</returns> public override bool Execute(DocumentConstructionContext context) { var fragmnet = context.FindContextItem <QueryFragment>(); if (string.IsNullOrEmpty(fragmnet.TargetGraphTypeName)) { return(true); } // shouldn't be false at this step, but just in case fail out if (fragmnet.GraphType == null) { return(false); } if (!ALLOWED_TYPE_KINDS.Contains(fragmnet.GraphType.Kind)) { this.ValidationError( context, $"The fragment declares a target graph type of '{fragmnet.GraphType.Name}' " + $"of kind '{fragmnet.GraphType.Kind.ToString()}' but " + $"fragments can only target graph types of kind {ALLOWED_TYPE_KIND_STRING}."); return(false); } return(true); }
/// <summary> /// Validates the specified node to ensure it is "correct" in the context of the rule doing the valdiation. /// </summary> /// <param name="context">The validation context encapsulating a <see cref="SyntaxNode" /> that needs to be validated.</param> /// <returns><c>true</c> if the node is valid, <c>false</c> otherwise.</returns> public override bool Execute(DocumentConstructionContext context) { var fragment = context.FindContextItem <QueryFragment>(); // allow inline fragments to not have a target graph type (they inherit their parent's type) if (fragment.TargetGraphTypeName == string.Empty) { this.ValidationError( context, "Invalid Fragment. Fragments must declare a target type using the 'on' keyword."); return(false); } if (context.DocumentContext.Schema.KnownTypes.Contains(fragment.TargetGraphTypeName)) { return(true); } this.ValidationError( context, $"The fragment declares a target type of '{fragment.TargetGraphTypeName}' but no graph type exists " + $"on the target schema by that name."); return(false); }
/// <summary> /// Executes the construction step the specified node to ensure it is "correct" in the context of the rule doing the valdiation. /// </summary> /// <param name="context">The validation context encapsulating a <see cref="SyntaxNode" /> that needs to be validated.</param> /// <returns><c>true</c> if the node is valid, <c>false</c> otherwise.</returns> public override bool Execute(DocumentConstructionContext context) { // at this stage we know thta we've encountered a complexvalue node // we can also garuntee that the active input value on the request is going to be the value container // for that ComplexvalueNode. It is to that container that we are adding a new argument. // // take for instance this sequence: // // field(arg1: {childArg1: "value" childArg2: value} ) // // we are pointing at the argument "arg1" // which is a complexargument type having a value of QueryComplexInputValue which is a container of arguments // it is to that container that we are adding this new argument "childArg1" indicated by this InputItemNode // on the context. // // Note: this operation could be nested N levels deep such as with // field(arg1: { childArg1: {subChildArg1: value, subChildArg1: value} childArg2: 5} ) // the scenario would be valid for: // adding childArg1 or childArg2 to arg1 // adding subChildArg1 or subChildArg2 to childArg1 var node = (InputItemNode)context.ActiveNode; var inputObject = context.FindContextItem <QueryInputValue>() as QueryComplexInputValue; var ownerGraphType = inputObject.OwnerArgument.GraphType as IInputObjectGraphType; var field = ownerGraphType.Fields[node.InputName.ToString()]; var graphType = context.DocumentContext.Schema.KnownTypes.FindGraphType(field); var argument = new QueryInputArgument(node, graphType, field.TypeExpression); context.AddDocumentPart(argument); return(true); }
/// <summary> /// Validates the specified node to ensure it is "correct" in the context of the rule doing the valdiation. /// </summary> /// <param name="context">The validation context encapsulating a <see cref="SyntaxNode" /> that needs to be validated.</param> /// <returns><c>true</c> if the node is valid, <c>false</c> otherwise.</returns> public override bool Execute(DocumentConstructionContext context) { var node = (DirectiveNode)context.ActiveNode; var queryDirective = context.FindContextItem <QueryDirective>(); if (queryDirective == null) { return(false); } var location = node.ParentNode?.DirectiveLocation(); if (!location.HasValue || !queryDirective.Directive.Locations.HasFlag(location)) { var locationName = location.HasValue ? location.Value.ToString() : "unknown"; var allowedLocations = queryDirective.Directive.Locations.GetIndividualFlags <DirectiveLocation>(); var allowedString = string.Join(", ", allowedLocations.Select(x => x.ToString())); this.ValidationError( context, $"Invalid directive location. Attempted use of '{queryDirective.Directive.Name}' at location '{locationName}'. " + $"Allowed Locations: {allowedString}"); } return(true); }
/// <summary> /// Executes the construction step the specified node to ensure it is "correct" in the context of the rule doing the valdiation. /// </summary> /// <param name="context">The validation context encapsulating a <see cref="SyntaxNode" /> that needs to be validated.</param> /// <returns><c>true</c> if the node is valid, <c>false</c> otherwise.</returns> public override bool Execute(DocumentConstructionContext context) { var variable = context.FindContextItem <QueryVariable>(); var graphType = context.DocumentContext.Schema.KnownTypes.FindGraphType(variable.TypeExpression.TypeName); variable.AttachGraphType(graphType); return(true); }
/// <summary> /// Executes the construction step the specified node to ensure it is "correct" in the context of the rule doing the valdiation. /// </summary> /// <param name="context">The validation context encapsulating a <see cref="SyntaxNode" /> that needs to be validated.</param> /// <returns><c>true</c> if the node is valid, <c>false</c> otherwise.</returns> public override bool Execute(DocumentConstructionContext context) { var node = (InputItemNode)context.ActiveNode; var argument = context.FindContextItem <QueryInputArgument>(); var complexValue = context.FindContextItem <QueryInputValue>() as QueryComplexInputValue; if (complexValue.Arguments.ContainsKey(node.InputName.ToString())) { this.ValidationError( context, $"Fields on input objects must be unique. The supplied value for argument '{argument.Name}' " + $"defines '{node.InputName.ToString()}' more than once."); return(false); } return(true); }
/// <summary> /// Executes the construction step the specified node to ensure it is "correct" in the context of the rule doing the valdiation. /// </summary> /// <param name="context">The validation context encapsulating a <see cref="SyntaxNode" /> that needs to be validated.</param> /// <returns><c>true</c> if the node is valid, <c>false</c> otherwise.</returns> public override bool Execute(DocumentConstructionContext context) { var node = (InputItemNode)context.ActiveNode; var queryDirective = context.FindContextItem <QueryDirective>(); var fieldArg = queryDirective.Directive.Arguments[node.InputName.ToString()]; var graphType = context.DocumentContext.Schema.KnownTypes.FindGraphType(fieldArg.TypeExpression.TypeName); var argument = new QueryInputArgument(node, graphType, fieldArg.TypeExpression); context.AddDocumentPart(argument); return(true); }
/// <summary> /// Validates the specified node to ensure it is "correct" in the context of the rule doing the valdiation. /// </summary> /// <param name="context">The validation context encapsulating a <see cref="SyntaxNode" /> that needs to be validated.</param> /// <returns><c>true</c> if the node is valid, <c>false</c> otherwise.</returns> public override bool Execute(DocumentConstructionContext context) { var node = (FieldNode)context.ActiveNode; var newField = context.FindContextItem <FieldSelection>(); // do a fast lookup before enumerating the field selection to determine // if there would even be a name collision. if (!context.SelectionSet.ContainsAlias(node.FieldAlias)) { return(true); } var isValid = true; var existingFields = context.SelectionSet.FindFieldsOfAlias(node.FieldAlias); foreach (var existingField in existingFields) { // we may iterate through the field we are adding, it can exist with itself // just skip it if (existingField == newField) { continue; } // fields with the same name in a given context // but targeting non-intersecting types can safely co-exist // in the same selection set. if (this.CanCoExist(context.DocumentContext.Schema, context.SelectionSet, existingField, newField)) { continue; } // fields that could cause a name collision for a type // must be mergable (i.e. have the same shape/signature). if (this.AreSameShape(existingField, newField)) { continue; } this.ValidationError( context, $"The selection set already contains a field with a name or alias of '{newField.Node.FieldAlias.ToString()}'. " + "An attempt was made to add another field with the same name or alias to the selection set but with a different " + "return graph type or input arguments. Fields with the same output name must have identicial signatures " + "within a single selection set."); isValid = false; } return(isValid); }
/// <summary> /// Validates the specified node to ensure it is "correct" in the context of the rule doing the valdiation. /// </summary> /// <param name="context">The validation context encapsulating a <see cref="SyntaxNode" /> that needs to be validated.</param> /// <returns><c>true</c> if the node is valid, <c>false</c> otherwise.</returns> public override bool Execute(DocumentConstructionContext context) { var node = (InputItemNode)context.ActiveNode; var directive = context.FindContextItem <QueryDirective>(); if (directive.Arguments.ContainsKey(node.InputName)) { this.ValidationError( context, $"The directive '{directive.Name}' already contains an input argument named '{node.InputName.ToString()}'. Input arguments " + "must be unique per directive instance."); return(false); } return(true); }
/// <summary> /// Validates the specified node to ensure it is "correct" in the context of the rule doing the valdiation. /// </summary> /// <param name="context">The validation context encapsulating a <see cref="SyntaxNode" /> that needs to be validated.</param> /// <returns><c>true</c> if the node is valid, <c>false</c> otherwise.</returns> public override bool Execute(DocumentConstructionContext context) { var node = (InputItemNode)context.ActiveNode; var fieldSelection = context.FindContextItem <FieldSelection>(); if (!fieldSelection.Field.Arguments.ContainsKey(node.InputName.ToString())) { this.ValidationError( context, $"The field '{fieldSelection.Name}' does not define an input argument named '{node.InputName.ToString()}'. Input arguments " + $"must be defined on the field in the target schema."); return(false); } return(true); }
/// <summary> /// Validates the specified node to ensure it is "correct" in the context of the rule doing the valdiation. /// </summary> /// <param name="context">The validation context encapsulating a <see cref="SyntaxNode" /> that needs to be validated.</param> /// <returns><c>true</c> if the node is valid, <c>false</c> otherwise.</returns> public override bool Execute(DocumentConstructionContext context) { var node = (InputItemNode)context.ActiveNode; var fieldSelection = context.FindContextItem <FieldSelection>(); if (fieldSelection.Arguments.ContainsKey(node.InputName)) { this.ValidationError( context, $"The field '{fieldSelection.Name}' already contains an input argument named '{node.InputName.ToString()}'. Input arguments " + $"must be unique per field instance."); return(false); } return(true); }
/// <summary> /// Validates the specified node to ensure it is "correct" in the context of the rule doing the valdiation. /// </summary> /// <param name="context">The validation context encapsulating a <see cref="SyntaxNode" /> that needs to be validated.</param> /// <returns><c>true</c> if the node is valid, <c>false</c> otherwise.</returns> public override bool Execute(DocumentConstructionContext context) { var queryVariable = context.FindContextItem <QueryVariable>(); if (!queryVariable.TypeExpression.IsValid) { this.ValidationError( context, "Unknown Graph Type. Could not determine the graph type expression of the variable " + $"named '{queryVariable.Name}'. Double check that your variable declaration is correct."); return(false); } return(true); }
/// <summary> /// Validates the specified node to ensure it is "correct" in the context of the rule doing the valdiation. /// </summary> /// <param name="context">The validation context encapsulating a <see cref="SyntaxNode" /> that needs to be validated.</param> /// <returns><c>true</c> if the node is valid, <c>false</c> otherwise.</returns> public override bool Execute(DocumentConstructionContext context) { var node = (InputItemNode)context.ActiveNode; var queryDirective = context.FindContextItem <QueryDirective>(); if (!queryDirective.Directive.Arguments.ContainsKey(node.InputName.ToString())) { this.ValidationError( context, $"The directive '{queryDirective.Name}' does not define an input argument named '{node.InputName.ToString()}'. " + $"Input arguments must be defined on the directive in the target schema."); return(false); } return(true); }
/// <summary> /// Validates the specified node to ensure it is "correct" in the context of the rule doing the valdiation. /// </summary> /// <param name="context">The validation context encapsulating a <see cref="SyntaxNode" /> that needs to be validated.</param> /// <returns><c>true</c> if the node is valid, <c>false</c> otherwise.</returns> public override bool Execute(DocumentConstructionContext context) { var field = context.FindContextItem <FieldSelection>(); if (field.GraphType.Kind.IsLeafKind() && context.ActiveNode.Children.Any <FieldCollectionNode>()) { this.ValidationError( context, $"The graph type '{field.GraphType.Name}' is of kind '{field.GraphType.Kind.ToString()}'. It cannot declare a fieldset " + "to return."); return(false); } return(true); }
/// <summary> /// Validates the specified node to ensure it is "correct" in the context of the rule doing the valdiation. /// </summary> /// <param name="context">The validation context encapsulating a <see cref="SyntaxNode" /> that needs to be validated.</param> /// <returns><c>true</c> if the node is valid, <c>false</c> otherwise.</returns> public override bool Execute(DocumentConstructionContext context) { var queryFragment = context.FindContextItem <QueryFragment>(); // ensure that the named fragment's target type (if there is one) exists in the schema nad assign it to the query // fragment object if it doesnt exist mark this fragment as failed var graphtype = context.DocumentContext.Schema.KnownTypes.FindGraphType(queryFragment.TargetGraphTypeName); if (graphtype == null) { return(false); } queryFragment.GraphType = graphtype; context.DocumentScope?.RestrictFieldsToGraphType(queryFragment.GraphType); return(true); }
/// <summary> /// Executes the construction step the specified node to ensure it is "correct" in the context of the rule doing the valdiation. /// </summary> /// <param name="context">The validation context encapsulating a <see cref="SyntaxNode" /> that needs to be validated.</param> /// <returns><c>true</c> if the node is valid, <c>false</c> otherwise.</returns> public override bool Execute(DocumentConstructionContext context) { var node = (InputItemNode)context.ActiveNode; var argument = context.FindContextItem <QueryInputArgument>(); // represents a field on a complex object argument // ensures that the field exists in the graphtype of the argument if (!(argument.GraphType is IInputObjectGraphType inputGraphType) || !inputGraphType.Fields.ContainsKey(node.InputName.ToString())) { this.ValidationError( context, $"The {argument.GraphType.Kind.ToString()} type '{argument.GraphType.Name}' does not define a field named '{node.InputName.ToString()}'."); return(false); } return(true); }
/// <summary> /// Validates the completed document context to ensure it is "correct" against the specification before generating /// the final document. /// </summary> /// <param name="context">The context containing the parsed sections of a query document..</param> /// <returns><c>true</c> if the rule passes, <c>false</c> otherwise.</returns> public override bool Execute(DocumentConstructionContext context) { var node = (VariableValueNode)context.ActiveNode; var queryOperation = context.FindContextItem <QueryOperation>(); var variableName = node.Value.ToString(); if (queryOperation.Variables == null || !queryOperation.Variables.ContainsKey(variableName)) { this.ValidationError( context, $"The variable named '${variableName}' is not declared for the current operation."); return(false); } return(true); }
/// <summary> /// Validates the specified node to ensure it is "correct" in the context of the rule doing the valdiation. /// </summary> /// <param name="context">The validation context encapsulating a <see cref="SyntaxNode" /> that needs to be validated.</param> /// <returns><c>true</c> if the node is valid, <c>false</c> otherwise.</returns> public override bool Execute(DocumentConstructionContext context) { var queryDirective = context.FindContextItem <QueryDirective>(); if (context.DocumentScope.Directives.Count(x => x.Directive.Name == queryDirective.Directive.Name && x.Directive.Locations.HasFlag(queryDirective.Location)) > 1) { this.ValidationError( context, $"The directive '{queryDirective.Name}' is already defined in this location. Directives must be unique per " + "instantiated location (e.g. once per field, once per input argument etc.)."); return(false); } return(true); }
/// <summary> /// Validates the specified node to ensure it is "correct" in the context of the rule doing the valdiation. /// </summary> /// <param name="context">The validation context encapsulating a <see cref="SyntaxNode" /> that needs to be validated.</param> /// <returns><c>true</c> if the node is valid, <c>false</c> otherwise.</returns> public override bool Execute(DocumentConstructionContext context) { var variable = context.FindContextItem <QueryVariable>(); var graphType = context.DocumentContext.Schema.KnownTypes.FindGraphType(variable.TypeExpression.TypeName); if (graphType == null) { this.ValidationError( context, $"Unknown Variable Graph Type. The variable named '{variable?.Name}' declares " + $"itself as a graph type of '{variable.TypeExpression}' but that graph type does not " + "exist in the schema."); return(false); } return(true); }
/// <summary> /// Validates the specified node to ensure it is "correct" in the context of the rule doing the valdiation. /// </summary> /// <param name="context">The validation context encapsulating a <see cref="SyntaxNode" /> that needs to be validated.</param> /// <returns><c>true</c> if the node is valid, <c>false</c> otherwise.</returns> public override bool Execute(DocumentConstructionContext context) { var node = (VariableNode)context.ActiveNode; var operation = context.FindContextItem <QueryOperation>(); if (operation?.Variables != null) { if (operation.Variables.ContainsKey(node.Name.ToString())) { this.ValidationError( context, $"Duplicate Variable Name. The variable named '{node.Name.ToString()}' must be unique " + "in its contained operation. Ensure that all variable names, per operation, are unique (case-sensitive)."); return(false); } } return(true); }
/// <summary> /// Determines whether this instance can process the given context. The rule will have no effect on the node if it cannot /// process it. /// </summary> /// <param name="context">The context that may be acted upon.</param> /// <returns><c>true</c> if this instance can validate the specified node; otherwise, <c>false</c>.</returns> public override bool ShouldExecute(DocumentConstructionContext context) { return(base.ShouldExecute(context) && context.FindContextItem <QueryOperation>().OperationType == GraphCollection.Subscription); }
/// <summary> /// Determines whether this instance can process the given context. The rule will have no effect on the input argument if it cannot /// process it. /// </summary> /// <param name="context">The context that may be acted upon.</param> /// <returns><c>true</c> if this instance can validate the specified input argument; otherwise, <c>false</c>.</returns> public override bool ShouldExecute(DocumentConstructionContext context) { return(base.ShouldExecute(context) && context.ActiveNode.ParentNode?.ParentNode is ComplexValueNode && context.FindContextItem <QueryInputValue>() is QueryComplexInputValue); }
/// <summary> /// Determines whether this instance can process the given context. The rule will have no effect on the node if it cannot /// process it. /// </summary> /// <param name="context">The context that may be acted upon.</param> /// <returns><c>true</c> if this instance can validate the specified node; otherwise, <c>false</c>.</returns> public override bool ShouldExecute(DocumentConstructionContext context) { return(base.ShouldExecute(context) && context.FindContextItem <QueryInputValue>() is QueryVariableReferenceInputValue); }