build(deps): bump github.com/open-policy-agent/opa from 1.6.0 to 1.8.0

Bumps [github.com/open-policy-agent/opa](https://github.com/open-policy-agent/opa) from 1.6.0 to 1.8.0.
- [Release notes](https://github.com/open-policy-agent/opa/releases)
- [Changelog](https://github.com/open-policy-agent/opa/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-policy-agent/opa/compare/v1.6.0...v1.8.0)

---
updated-dependencies:
- dependency-name: github.com/open-policy-agent/opa
  dependency-version: 1.8.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
dependabot[bot]
2025-09-23 10:28:55 +02:00
committed by Ralf Haferkamp
parent 98d773bb9b
commit 76ac20e9e8
419 changed files with 57008 additions and 13314 deletions
+24
View File
@@ -0,0 +1,24 @@
package core
import (
"github.com/vektah/gqlparser/v2/gqlerror"
)
type AddErrFunc func(options ...ErrorOption)
type RuleFunc func(observers *Events, addError AddErrFunc)
type Rule struct {
Name string
RuleFunc RuleFunc
}
// NameSorter sorts Rules by name.
// usage: sort.Sort(core.NameSorter(specifiedRules))
type NameSorter []Rule
func (a NameSorter) Len() int { return len(a) }
func (a NameSorter) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a NameSorter) Less(i, j int) bool { return a[i].Name < a[j].Name }
type ErrorOption func(err *gqlerror.Error)
+154
View File
@@ -0,0 +1,154 @@
package core
import (
"bytes"
"fmt"
"math"
"sort"
"strings"
"github.com/agnivade/levenshtein"
"github.com/vektah/gqlparser/v2/ast"
"github.com/vektah/gqlparser/v2/gqlerror"
)
func Message(msg string, args ...interface{}) ErrorOption {
return func(err *gqlerror.Error) {
err.Message += fmt.Sprintf(msg, args...)
}
}
func At(position *ast.Position) ErrorOption {
return func(err *gqlerror.Error) {
if position == nil {
return
}
err.Locations = append(err.Locations, gqlerror.Location{
Line: position.Line,
Column: position.Column,
})
if position.Src.Name != "" {
err.SetFile(position.Src.Name)
}
}
}
func SuggestListQuoted(prefix string, typed string, suggestions []string) ErrorOption {
suggested := SuggestionList(typed, suggestions)
return func(err *gqlerror.Error) {
if len(suggested) > 0 {
err.Message += " " + prefix + " " + QuotedOrList(suggested...) + "?"
}
}
}
func SuggestListUnquoted(prefix string, typed string, suggestions []string) ErrorOption {
suggested := SuggestionList(typed, suggestions)
return func(err *gqlerror.Error) {
if len(suggested) > 0 {
err.Message += " " + prefix + " " + OrList(suggested...) + "?"
}
}
}
func Suggestf(suggestion string, args ...interface{}) ErrorOption {
return func(err *gqlerror.Error) {
err.Message += " Did you mean " + fmt.Sprintf(suggestion, args...) + "?"
}
}
// Given [ A, B, C ] return '"A", "B", or "C"'.
func QuotedOrList(items ...string) string {
itemsQuoted := make([]string, len(items))
for i, item := range items {
itemsQuoted[i] = `"` + item + `"`
}
return OrList(itemsQuoted...)
}
// Given [ A, B, C ] return 'A, B, or C'.
func OrList(items ...string) string {
var buf bytes.Buffer
if len(items) > 5 {
items = items[:5]
}
if len(items) == 2 {
buf.WriteString(items[0])
buf.WriteString(" or ")
buf.WriteString(items[1])
return buf.String()
}
for i, item := range items {
if i != 0 {
if i == len(items)-1 {
buf.WriteString(", or ")
} else {
buf.WriteString(", ")
}
}
buf.WriteString(item)
}
return buf.String()
}
// Given an invalid input string and a list of valid options, returns a filtered
// list of valid options sorted based on their similarity with the input.
func SuggestionList(input string, options []string) []string {
var results []string
optionsByDistance := map[string]int{}
for _, option := range options {
distance := lexicalDistance(input, option)
threshold := calcThreshold(input)
if distance <= threshold {
results = append(results, option)
optionsByDistance[option] = distance
}
}
sort.Slice(results, func(i, j int) bool {
return optionsByDistance[results[i]] < optionsByDistance[results[j]]
})
return results
}
func calcThreshold(a string) (threshold int) {
// the logic is copied from here
// https://github.com/graphql/graphql-js/blob/47bd8c8897c72d3efc17ecb1599a95cee6bac5e8/src/jsutils/suggestionList.ts#L14
threshold = int(math.Floor(float64(len(a))*0.4) + 1)
if threshold < 1 {
threshold = 1
}
return
}
// Computes the lexical distance between strings A and B.
//
// The "distance" between two strings is given by counting the minimum number
// of edits needed to transform string A into string B. An edit can be an
// insertion, deletion, or substitution of a single character, or a swap of two
// adjacent characters.
//
// Includes a custom alteration from Damerau-Levenshtein to treat case changes
// as a single edit which helps identify mis-cased values with an edit distance
// of 1.
//
// This distance can be useful for detecting typos in input or sorting
func lexicalDistance(a, b string) int {
if a == b {
return 0
}
a = strings.ToLower(a)
b = strings.ToLower(b)
// Any case change counts as a single edit
if a == b {
return 1
}
return levenshtein.ComputeDistance(a, b)
}
@@ -1,4 +1,4 @@
package validator
package core
import (
"context"
-55
View File
@@ -1,55 +0,0 @@
package validator
import (
"fmt"
"github.com/vektah/gqlparser/v2/ast"
"github.com/vektah/gqlparser/v2/gqlerror"
)
type ErrorOption func(err *gqlerror.Error)
func Message(msg string, args ...interface{}) ErrorOption {
return func(err *gqlerror.Error) {
err.Message += fmt.Sprintf(msg, args...)
}
}
func At(position *ast.Position) ErrorOption {
return func(err *gqlerror.Error) {
if position == nil {
return
}
err.Locations = append(err.Locations, gqlerror.Location{
Line: position.Line,
Column: position.Column,
})
if position.Src.Name != "" {
err.SetFile(position.Src.Name)
}
}
}
func SuggestListQuoted(prefix string, typed string, suggestions []string) ErrorOption {
suggested := SuggestionList(typed, suggestions)
return func(err *gqlerror.Error) {
if len(suggested) > 0 {
err.Message += " " + prefix + " " + QuotedOrList(suggested...) + "?"
}
}
}
func SuggestListUnquoted(prefix string, typed string, suggestions []string) ErrorOption {
suggested := SuggestionList(typed, suggestions)
return func(err *gqlerror.Error) {
if len(suggested) > 0 {
err.Message += " " + prefix + " " + OrList(suggested...) + "?"
}
}
}
func Suggestf(suggestion string, args ...interface{}) ErrorOption {
return func(err *gqlerror.Error) {
err.Message += " Did you mean " + fmt.Sprintf(suggestion, args...) + "?"
}
}
-39
View File
@@ -1,39 +0,0 @@
package validator
import "bytes"
// Given [ A, B, C ] return '"A", "B", or "C"'.
func QuotedOrList(items ...string) string {
itemsQuoted := make([]string, len(items))
for i, item := range items {
itemsQuoted[i] = `"` + item + `"`
}
return OrList(itemsQuoted...)
}
// Given [ A, B, C ] return 'A, B, or C'.
func OrList(items ...string) string {
var buf bytes.Buffer
if len(items) > 5 {
items = items[:5]
}
if len(items) == 2 {
buf.WriteString(items[0])
buf.WriteString(" or ")
buf.WriteString(items[1])
return buf.String()
}
for i, item := range items {
if i != 0 {
if i == len(items)-1 {
buf.WriteString(", or ")
} else {
buf.WriteString(", ")
}
}
buf.WriteString(item)
}
return buf.String()
}
@@ -8,7 +8,7 @@ import (
"github.com/vektah/gqlparser/v2/ast"
//nolint:staticcheck // Validator rules each use dot imports for convenience.
. "github.com/vektah/gqlparser/v2/validator"
. "github.com/vektah/gqlparser/v2/validator/core"
)
func ruleFuncFieldsOnCorrectType(observers *Events, addError AddErrFunc, disableSuggestion bool) {
@@ -48,10 +48,6 @@ var FieldsOnCorrectTypeRuleWithoutSuggestions = Rule{
},
}
func init() {
AddRule(FieldsOnCorrectTypeRule.Name, FieldsOnCorrectTypeRule.RuleFunc)
}
// Go through all the implementations of type, as well as the interfaces
// that they implement. If any of those types include the provided field,
// suggest them, sorted by how often the type is referenced, starting
@@ -6,7 +6,7 @@ import (
"github.com/vektah/gqlparser/v2/ast"
//nolint:staticcheck // Validator rules each use dot imports for convenience.
. "github.com/vektah/gqlparser/v2/validator"
. "github.com/vektah/gqlparser/v2/validator/core"
)
var FragmentsOnCompositeTypesRule = Rule{
@@ -40,7 +40,3 @@ var FragmentsOnCompositeTypesRule = Rule{
})
},
}
func init() {
AddRule(FragmentsOnCompositeTypesRule.Name, FragmentsOnCompositeTypesRule.RuleFunc)
}
@@ -4,7 +4,7 @@ import (
"github.com/vektah/gqlparser/v2/ast"
//nolint:staticcheck // Validator rules each use dot imports for convenience.
. "github.com/vektah/gqlparser/v2/validator"
. "github.com/vektah/gqlparser/v2/validator/core"
)
func ruleFuncKnownArgumentNames(observers *Events, addError AddErrFunc, disableSuggestion bool) {
@@ -82,7 +82,3 @@ var KnownArgumentNamesRuleWithoutSuggestions = Rule{
ruleFuncKnownArgumentNames(observers, addError, true)
},
}
func init() {
AddRule(KnownArgumentNamesRule.Name, KnownArgumentNamesRule.RuleFunc)
}
+1 -5
View File
@@ -4,7 +4,7 @@ import (
"github.com/vektah/gqlparser/v2/ast"
//nolint:staticcheck // Validator rules each use dot imports for convenience.
. "github.com/vektah/gqlparser/v2/validator"
. "github.com/vektah/gqlparser/v2/validator/core"
)
var KnownDirectivesRule = Rule{
@@ -48,7 +48,3 @@ var KnownDirectivesRule = Rule{
})
},
}
func init() {
AddRule(KnownDirectivesRule.Name, KnownDirectivesRule.RuleFunc)
}
@@ -4,7 +4,7 @@ import (
"github.com/vektah/gqlparser/v2/ast"
//nolint:staticcheck // Validator rules each use dot imports for convenience.
. "github.com/vektah/gqlparser/v2/validator"
. "github.com/vektah/gqlparser/v2/validator/core"
)
var KnownFragmentNamesRule = Rule{
@@ -20,7 +20,3 @@ var KnownFragmentNamesRule = Rule{
})
},
}
func init() {
AddRule(KnownFragmentNamesRule.Name, KnownFragmentNamesRule.RuleFunc)
}
+1 -5
View File
@@ -6,7 +6,7 @@ import (
"github.com/vektah/gqlparser/v2/ast"
//nolint:staticcheck // Validator rules each use dot imports for convenience.
. "github.com/vektah/gqlparser/v2/validator"
. "github.com/vektah/gqlparser/v2/validator/core"
)
var KnownRootTypeRule = Rule{
@@ -36,7 +36,3 @@ var KnownRootTypeRule = Rule{
})
},
}
func init() {
AddRule(KnownRootTypeRule.Name, KnownRootTypeRule.RuleFunc)
}
+1 -5
View File
@@ -4,7 +4,7 @@ import (
"github.com/vektah/gqlparser/v2/ast"
//nolint:staticcheck // Validator rules each use dot imports for convenience.
. "github.com/vektah/gqlparser/v2/validator"
. "github.com/vektah/gqlparser/v2/validator/core"
)
func ruleFuncKnownTypeNames(observers *Events, addError AddErrFunc, disableSuggestion bool) {
@@ -78,7 +78,3 @@ var KnownTypeNamesRuleWithoutSuggestions = Rule{
ruleFuncKnownTypeNames(observers, addError, true)
},
}
func init() {
AddRule(KnownTypeNamesRule.Name, KnownTypeNamesRule.RuleFunc)
}
@@ -4,7 +4,7 @@ import (
"github.com/vektah/gqlparser/v2/ast"
//nolint:staticcheck // Validator rules each use dot imports for convenience.
. "github.com/vektah/gqlparser/v2/validator"
. "github.com/vektah/gqlparser/v2/validator/core"
)
var LoneAnonymousOperationRule = Rule{
@@ -20,7 +20,3 @@ var LoneAnonymousOperationRule = Rule{
})
},
}
func init() {
AddRule(LoneAnonymousOperationRule.Name, LoneAnonymousOperationRule.RuleFunc)
}
@@ -4,7 +4,7 @@ import (
"github.com/vektah/gqlparser/v2/ast"
//nolint:staticcheck // Validator rules each use dot imports for convenience.
. "github.com/vektah/gqlparser/v2/validator"
. "github.com/vektah/gqlparser/v2/validator/core"
)
const maxListsDepth = 3
@@ -84,7 +84,3 @@ func checkDepthFragmentSpread(fragmentSpread *ast.FragmentSpread, visitedFragmen
defer delete(visitedFragments, fragmentName)
return checkDepthSelectionSet(fragment.SelectionSet, visitedFragments, depth)
}
func init() {
AddRule(MaxIntrospectionDepth.Name, MaxIntrospectionDepth.RuleFunc)
}
@@ -7,7 +7,7 @@ import (
"github.com/vektah/gqlparser/v2/ast"
//nolint:staticcheck // Validator rules each use dot imports for convenience.
. "github.com/vektah/gqlparser/v2/validator"
. "github.com/vektah/gqlparser/v2/validator/core"
)
var NoFragmentCyclesRule = Rule{
@@ -71,10 +71,6 @@ var NoFragmentCyclesRule = Rule{
},
}
func init() {
AddRule(NoFragmentCyclesRule.Name, NoFragmentCyclesRule.RuleFunc)
}
func getFragmentSpreads(node ast.SelectionSet) []*ast.FragmentSpread {
var spreads []*ast.FragmentSpread
@@ -4,7 +4,7 @@ import (
"github.com/vektah/gqlparser/v2/ast"
//nolint:staticcheck // Validator rules each use dot imports for convenience.
. "github.com/vektah/gqlparser/v2/validator"
. "github.com/vektah/gqlparser/v2/validator/core"
)
var NoUndefinedVariablesRule = Rule{
@@ -29,7 +29,3 @@ var NoUndefinedVariablesRule = Rule{
})
},
}
func init() {
AddRule(NoUndefinedVariablesRule.Name, NoUndefinedVariablesRule.RuleFunc)
}
@@ -4,7 +4,7 @@ import (
"github.com/vektah/gqlparser/v2/ast"
//nolint:staticcheck // Validator rules each use dot imports for convenience.
. "github.com/vektah/gqlparser/v2/validator"
. "github.com/vektah/gqlparser/v2/validator/core"
)
var NoUnusedFragmentsRule = Rule{
@@ -30,7 +30,3 @@ var NoUnusedFragmentsRule = Rule{
})
},
}
func init() {
AddRule(NoUnusedFragmentsRule.Name, NoUnusedFragmentsRule.RuleFunc)
}
@@ -4,7 +4,7 @@ import (
"github.com/vektah/gqlparser/v2/ast"
//nolint:staticcheck // Validator rules each use dot imports for convenience.
. "github.com/vektah/gqlparser/v2/validator"
. "github.com/vektah/gqlparser/v2/validator/core"
)
var NoUnusedVariablesRule = Rule{
@@ -31,7 +31,3 @@ var NoUnusedVariablesRule = Rule{
})
},
}
func init() {
AddRule(NoUnusedVariablesRule.Name, NoUnusedVariablesRule.RuleFunc)
}
@@ -8,7 +8,7 @@ import (
"github.com/vektah/gqlparser/v2/ast"
//nolint:staticcheck // Validator rules each use dot imports for convenience.
. "github.com/vektah/gqlparser/v2/validator"
. "github.com/vektah/gqlparser/v2/validator/core"
)
var OverlappingFieldsCanBeMergedRule = Rule{
@@ -108,10 +108,6 @@ var OverlappingFieldsCanBeMergedRule = Rule{
},
}
func init() {
AddRule(OverlappingFieldsCanBeMergedRule.Name, OverlappingFieldsCanBeMergedRule.RuleFunc)
}
type pairSet struct {
data map[string]map[string]bool
}
@@ -4,7 +4,7 @@ import (
"github.com/vektah/gqlparser/v2/ast"
//nolint:staticcheck // Validator rules each use dot imports for convenience.
. "github.com/vektah/gqlparser/v2/validator"
. "github.com/vektah/gqlparser/v2/validator/core"
)
var PossibleFragmentSpreadsRule = Rule{
@@ -68,7 +68,3 @@ var PossibleFragmentSpreadsRule = Rule{
})
},
}
func init() {
AddRule(PossibleFragmentSpreadsRule.Name, PossibleFragmentSpreadsRule.RuleFunc)
}
@@ -3,7 +3,7 @@ package rules
import (
"github.com/vektah/gqlparser/v2/ast"
//nolint:staticcheck // Validator rules each use dot imports for convenience.
. "github.com/vektah/gqlparser/v2/validator"
. "github.com/vektah/gqlparser/v2/validator/core"
)
var ProvidedRequiredArgumentsRule = Rule{
@@ -62,7 +62,3 @@ var ProvidedRequiredArgumentsRule = Rule{
})
},
}
func init() {
AddRule(ProvidedRequiredArgumentsRule.Name, ProvidedRequiredArgumentsRule.RuleFunc)
}
+119
View File
@@ -0,0 +1,119 @@
package rules
import (
"slices"
"github.com/vektah/gqlparser/v2/validator/core"
)
// Rules manages GraphQL validation rules.
type Rules struct {
rules map[string]core.RuleFunc
ruleNameKeys []string // for deterministic order
}
// NewRules creates a Rules instance with the specified rules.
func NewRules(rs ...core.Rule) *Rules {
r := &Rules{
rules: make(map[string]core.RuleFunc),
}
for _, rule := range rs {
r.AddRule(rule.Name, rule.RuleFunc)
}
return r
}
// NewDefaultRules creates a Rules instance containing the default GraphQL validation rule set.
func NewDefaultRules() *Rules {
rules := []core.Rule{
FieldsOnCorrectTypeRule,
FragmentsOnCompositeTypesRule,
KnownArgumentNamesRule,
KnownDirectivesRule,
KnownFragmentNamesRule,
KnownRootTypeRule,
KnownTypeNamesRule,
LoneAnonymousOperationRule,
MaxIntrospectionDepth,
NoFragmentCyclesRule,
NoUndefinedVariablesRule,
NoUnusedFragmentsRule,
NoUnusedVariablesRule,
OverlappingFieldsCanBeMergedRule,
PossibleFragmentSpreadsRule,
ProvidedRequiredArgumentsRule,
ScalarLeafsRule,
SingleFieldSubscriptionsRule,
UniqueArgumentNamesRule,
UniqueDirectivesPerLocationRule,
UniqueFragmentNamesRule,
UniqueInputFieldNamesRule,
UniqueOperationNamesRule,
UniqueVariableNamesRule,
ValuesOfCorrectTypeRule,
VariablesAreInputTypesRule,
VariablesInAllowedPositionRule,
}
r := NewRules(rules...)
return r
}
// AddRule adds a rule with the specified name and rule function to the rule set.
// If a rule with the same name already exists, it will not be added.
func (r *Rules) AddRule(name string, ruleFunc core.RuleFunc) {
if r.rules == nil {
r.rules = make(map[string]core.RuleFunc)
}
if _, exists := r.rules[name]; !exists {
r.rules[name] = ruleFunc
r.ruleNameKeys = append(r.ruleNameKeys, name)
}
}
// GetInner returns the internal rule map.
// If the map is not initialized, it returns an empty map.
func (r *Rules) GetInner() map[string]core.RuleFunc {
if r == nil {
return nil // impossible nonsense, hopefully
}
if r.rules == nil {
return make(map[string]core.RuleFunc)
}
return r.rules
}
// RemoveRule removes a rule with the specified name from the rule set.
// If no rule with the specified name exists, it does nothing.
func (r *Rules) RemoveRule(name string) {
if r == nil {
return // impossible nonsense, hopefully
}
if r.rules != nil {
delete(r.rules, name)
}
if len(r.ruleNameKeys) > 0 {
r.ruleNameKeys = slices.DeleteFunc(r.ruleNameKeys, func(s string) bool {
return s == name // delete the name rule key
})
}
}
// ReplaceRule replaces a rule with the specified name with a new rule function.
// If no rule with the specified name exists, it does nothing.
func (r *Rules) ReplaceRule(name string, ruleFunc core.RuleFunc) {
if r == nil {
return // impossible nonsense, hopefully
}
if r.rules == nil {
r.rules = make(map[string]core.RuleFunc)
}
if _, exists := r.rules[name]; exists {
r.rules[name] = ruleFunc
}
}
+1 -5
View File
@@ -4,7 +4,7 @@ import (
"github.com/vektah/gqlparser/v2/ast"
//nolint:staticcheck // Validator rules each use dot imports for convenience.
. "github.com/vektah/gqlparser/v2/validator"
. "github.com/vektah/gqlparser/v2/validator/core"
)
var ScalarLeafsRule = Rule{
@@ -37,7 +37,3 @@ var ScalarLeafsRule = Rule{
})
},
}
func init() {
AddRule(ScalarLeafsRule.Name, ScalarLeafsRule.RuleFunc)
}
@@ -7,7 +7,7 @@ import (
"github.com/vektah/gqlparser/v2/ast"
//nolint:staticcheck // Validator rules each use dot imports for convenience.
. "github.com/vektah/gqlparser/v2/validator"
. "github.com/vektah/gqlparser/v2/validator/core"
)
var SingleFieldSubscriptionsRule = Rule{
@@ -44,10 +44,6 @@ var SingleFieldSubscriptionsRule = Rule{
},
}
func init() {
AddRule(SingleFieldSubscriptionsRule.Name, SingleFieldSubscriptionsRule.RuleFunc)
}
type topField struct {
name string
position *ast.Position
@@ -4,7 +4,7 @@ import (
"github.com/vektah/gqlparser/v2/ast"
//nolint:staticcheck // Validator rules each use dot imports for convenience.
. "github.com/vektah/gqlparser/v2/validator"
. "github.com/vektah/gqlparser/v2/validator/core"
)
var UniqueArgumentNamesRule = Rule{
@@ -20,10 +20,6 @@ var UniqueArgumentNamesRule = Rule{
},
}
func init() {
AddRule(UniqueArgumentNamesRule.Name, UniqueArgumentNamesRule.RuleFunc)
}
func checkUniqueArgs(args ast.ArgumentList, addError AddErrFunc) {
knownArgNames := map[string]int{}
@@ -4,7 +4,7 @@ import (
"github.com/vektah/gqlparser/v2/ast"
//nolint:staticcheck // Validator rules each use dot imports for convenience.
. "github.com/vektah/gqlparser/v2/validator"
. "github.com/vektah/gqlparser/v2/validator/core"
)
var UniqueDirectivesPerLocationRule = Rule{
@@ -25,7 +25,3 @@ var UniqueDirectivesPerLocationRule = Rule{
})
},
}
func init() {
AddRule(UniqueDirectivesPerLocationRule.Name, UniqueDirectivesPerLocationRule.RuleFunc)
}
@@ -4,7 +4,7 @@ import (
"github.com/vektah/gqlparser/v2/ast"
//nolint:staticcheck // Validator rules each use dot imports for convenience.
. "github.com/vektah/gqlparser/v2/validator"
. "github.com/vektah/gqlparser/v2/validator/core"
)
var UniqueFragmentNamesRule = Rule{
@@ -23,7 +23,3 @@ var UniqueFragmentNamesRule = Rule{
})
},
}
func init() {
AddRule(UniqueFragmentNamesRule.Name, UniqueFragmentNamesRule.RuleFunc)
}
@@ -4,7 +4,7 @@ import (
"github.com/vektah/gqlparser/v2/ast"
//nolint:staticcheck // Validator rules each use dot imports for convenience.
. "github.com/vektah/gqlparser/v2/validator"
. "github.com/vektah/gqlparser/v2/validator/core"
)
var UniqueInputFieldNamesRule = Rule{
@@ -28,7 +28,3 @@ var UniqueInputFieldNamesRule = Rule{
})
},
}
func init() {
AddRule(UniqueInputFieldNamesRule.Name, UniqueInputFieldNamesRule.RuleFunc)
}
@@ -4,7 +4,7 @@ import (
"github.com/vektah/gqlparser/v2/ast"
//nolint:staticcheck // Validator rules each use dot imports for convenience.
. "github.com/vektah/gqlparser/v2/validator"
. "github.com/vektah/gqlparser/v2/validator/core"
)
var UniqueOperationNamesRule = Rule{
@@ -23,7 +23,3 @@ var UniqueOperationNamesRule = Rule{
})
},
}
func init() {
AddRule(UniqueOperationNamesRule.Name, UniqueOperationNamesRule.RuleFunc)
}
@@ -4,7 +4,7 @@ import (
"github.com/vektah/gqlparser/v2/ast"
//nolint:staticcheck // Validator rules each use dot imports for convenience.
. "github.com/vektah/gqlparser/v2/validator"
. "github.com/vektah/gqlparser/v2/validator/core"
)
var UniqueVariableNamesRule = Rule{
@@ -25,7 +25,3 @@ var UniqueVariableNamesRule = Rule{
})
},
}
func init() {
AddRule(UniqueVariableNamesRule.Name, UniqueVariableNamesRule.RuleFunc)
}
@@ -8,7 +8,7 @@ import (
"github.com/vektah/gqlparser/v2/ast"
//nolint:staticcheck // Validator rules each use dot imports for convenience.
. "github.com/vektah/gqlparser/v2/validator"
. "github.com/vektah/gqlparser/v2/validator/core"
)
func ruleFuncValuesOfCorrectType(observers *Events, addError AddErrFunc, disableSuggestion bool) {
@@ -213,10 +213,6 @@ var ValuesOfCorrectTypeRuleWithoutSuggestions = Rule{
},
}
func init() {
AddRule(ValuesOfCorrectTypeRule.Name, ValuesOfCorrectTypeRule.RuleFunc)
}
func unexpectedTypeMessage(addError AddErrFunc, v *ast.Value) {
addError(
unexpectedTypeMessageOnly(v),
@@ -4,7 +4,7 @@ import (
"github.com/vektah/gqlparser/v2/ast"
//nolint:staticcheck // Validator rules each use dot imports for convenience.
. "github.com/vektah/gqlparser/v2/validator"
. "github.com/vektah/gqlparser/v2/validator/core"
)
var VariablesAreInputTypesRule = Rule{
@@ -29,7 +29,3 @@ var VariablesAreInputTypesRule = Rule{
})
},
}
func init() {
AddRule(VariablesAreInputTypesRule.Name, VariablesAreInputTypesRule.RuleFunc)
}
@@ -4,7 +4,7 @@ import (
"github.com/vektah/gqlparser/v2/ast"
//nolint:staticcheck // Validator rules each use dot imports for convenience.
. "github.com/vektah/gqlparser/v2/validator"
. "github.com/vektah/gqlparser/v2/validator/core"
)
var VariablesInAllowedPositionRule = Rule{
@@ -39,7 +39,3 @@ var VariablesInAllowedPositionRule = Rule{
})
},
}
func init() {
AddRule(VariablesInAllowedPositionRule.Name, VariablesInAllowedPositionRule.RuleFunc)
}
-69
View File
@@ -1,69 +0,0 @@
package validator
import (
"math"
"sort"
"strings"
"github.com/agnivade/levenshtein"
)
// Given an invalid input string and a list of valid options, returns a filtered
// list of valid options sorted based on their similarity with the input.
func SuggestionList(input string, options []string) []string {
var results []string
optionsByDistance := map[string]int{}
for _, option := range options {
distance := lexicalDistance(input, option)
threshold := calcThreshold(input)
if distance <= threshold {
results = append(results, option)
optionsByDistance[option] = distance
}
}
sort.Slice(results, func(i, j int) bool {
return optionsByDistance[results[i]] < optionsByDistance[results[j]]
})
return results
}
func calcThreshold(a string) (threshold int) {
// the logic is copied from here
// https://github.com/graphql/graphql-js/blob/47bd8c8897c72d3efc17ecb1599a95cee6bac5e8/src/jsutils/suggestionList.ts#L14
threshold = int(math.Floor(float64(len(a))*0.4) + 1)
if threshold < 1 {
threshold = 1
}
return
}
// Computes the lexical distance between strings A and B.
//
// The "distance" between two strings is given by counting the minimum number
// of edits needed to transform string A into string B. An edit can be an
// insertion, deletion, or substitution of a single character, or a swap of two
// adjacent characters.
//
// Includes a custom alteration from Damerau-Levenshtein to treat case changes
// as a single edit which helps identify mis-cased values with an edit distance
// of 1.
//
// This distance can be useful for detecting typos in input or sorting
func lexicalDistance(a, b string) int {
if a == b {
return 0
}
a = strings.ToLower(a)
b = strings.ToLower(b)
// Any case change counts as a single edit
if a == b {
return 1
}
return levenshtein.ComputeDistance(a, b)
}
+71 -6
View File
@@ -1,22 +1,46 @@
package validator
import (
"sort"
//nolint:staticcheck // bad, yeah
. "github.com/vektah/gqlparser/v2/ast"
"github.com/vektah/gqlparser/v2/gqlerror"
"github.com/vektah/gqlparser/v2/validator/core"
validatorrules "github.com/vektah/gqlparser/v2/validator/rules"
)
type AddErrFunc func(options ...ErrorOption)
type (
AddErrFunc = core.AddErrFunc
RuleFunc = core.RuleFunc
Rule = core.Rule
Events = core.Events
ErrorOption = core.ErrorOption
Walker = core.Walker
)
type RuleFunc func(observers *Events, addError AddErrFunc)
var (
Message = core.Message
QuotedOrList = core.QuotedOrList
OrList = core.OrList
)
type Rule struct {
Name string
RuleFunc RuleFunc
// Walk is an alias for core.Walk
func Walk(schema *Schema, document *QueryDocument, observers *Events) {
core.Walk(schema, document, observers)
}
var specifiedRules []Rule
func init() {
// Initialize specifiedRules with default rules
defaultRules := validatorrules.NewDefaultRules()
for name, ruleFunc := range defaultRules.GetInner() {
specifiedRules = append(specifiedRules, Rule{Name: name, RuleFunc: ruleFunc})
// ensure initial default is in deterministic order
sort.Sort(core.NameSorter(specifiedRules))
}
}
// AddRule adds a rule to the rule set.
// ruleFunc is called once each time `Validate` is executed.
func AddRule(name string, ruleFunc RuleFunc) {
@@ -59,6 +83,7 @@ func ReplaceRule(name string, ruleFunc RuleFunc) {
specifiedRules = result
}
// Deprecated: use ValidateWithRules instead.
func Validate(schema *Schema, doc *QueryDocument, rules ...Rule) gqlerror.List {
if rules == nil {
rules = specifiedRules
@@ -74,7 +99,7 @@ func Validate(schema *Schema, doc *QueryDocument, rules ...Rule) gqlerror.List {
if len(errs) > 0 {
return errs
}
observers := &Events{}
observers := &core.Events{}
for i := range rules {
rule := rules[i]
rule.RuleFunc(observers, func(options ...ErrorOption) {
@@ -91,3 +116,43 @@ func Validate(schema *Schema, doc *QueryDocument, rules ...Rule) gqlerror.List {
Walk(schema, doc, observers)
return errs
}
func ValidateWithRules(schema *Schema, doc *QueryDocument, rules *validatorrules.Rules) gqlerror.List {
if rules == nil {
rules = validatorrules.NewDefaultRules()
}
var errs gqlerror.List
if schema == nil {
errs = append(errs, gqlerror.Errorf("cannot validate as Schema is nil"))
}
if doc == nil {
errs = append(errs, gqlerror.Errorf("cannot validate as QueryDocument is nil"))
}
if len(errs) > 0 {
return errs
}
observers := &core.Events{}
var currentRules []Rule // nolint:prealloc // would require extra local refs for len
for name, ruleFunc := range rules.GetInner() {
currentRules = append(currentRules, Rule{Name: name, RuleFunc: ruleFunc})
// ensure deterministic order evaluation
sort.Sort(core.NameSorter(currentRules))
}
for _, currentRule := range currentRules {
currentRule.RuleFunc(observers, func(options ...ErrorOption) {
err := &gqlerror.Error{
Rule: currentRule.Name,
}
for _, o := range options {
o(err)
}
errs = append(errs, err)
})
}
Walk(schema, doc, observers)
return errs
}