pax_global_header00006660000000000000000000000064143066310420014511gustar00rootroot0000000000000052 comment=eae2341861b4421718a4007ff1d2e13f85d65e50 gqlparser-2.5.1/000077500000000000000000000000001430663104200135165ustar00rootroot00000000000000gqlparser-2.5.1/.circleci/000077500000000000000000000000001430663104200153515ustar00rootroot00000000000000gqlparser-2.5.1/.circleci/config.yml000066400000000000000000000007251430663104200173450ustar00rootroot00000000000000version: 2 jobs: build: docker: - image: golang:1.16 working_directory: /gqlparser steps: - checkout - run: > go get -u github.com/mattn/goveralls - run: go test -race ./... - run: go test -coverprofile=/tmp/coverage.out -coverpkg=./... ./... - run: goveralls -coverprofile=/tmp/coverage.out -service=circle-ci -repotoken=$COVERALLS_TOKEN - run: go test -count 25 ./... # check for flakey test ordering gqlparser-2.5.1/.gitignore000066400000000000000000000001201430663104200154770ustar00rootroot00000000000000/vendor /validator/imported/node_modules /validator/imported/graphql-js .idea/ gqlparser-2.5.1/LICENSE000066400000000000000000000020351430663104200145230ustar00rootroot00000000000000Copyright (c) 2018 Adam Scarr Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.gqlparser-2.5.1/ast/000077500000000000000000000000001430663104200143055ustar00rootroot00000000000000gqlparser-2.5.1/ast/argmap.go000066400000000000000000000013611430663104200161040ustar00rootroot00000000000000package ast func arg2map(defs ArgumentDefinitionList, args ArgumentList, vars map[string]interface{}) map[string]interface{} { result := map[string]interface{}{} var err error for _, argDef := range defs { var val interface{} var hasValue bool if argValue := args.ForName(argDef.Name); argValue != nil { if argValue.Value.Kind == Variable { val, hasValue = vars[argValue.Value.Raw] } else { val, err = argValue.Value.Value(vars) if err != nil { panic(err) } hasValue = true } } if !hasValue && argDef.DefaultValue != nil { val, err = argDef.DefaultValue.Value(vars) if err != nil { panic(err) } hasValue = true } if hasValue { result[argDef.Name] = val } } return result } gqlparser-2.5.1/ast/argmap_test.go000066400000000000000000000042131430663104200171420ustar00rootroot00000000000000package ast import ( "testing" "github.com/stretchr/testify/require" ) func TestArg2Map(t *testing.T) { defs := ArgumentDefinitionList{ {Name: "A", Type: NamedType("String", nil), DefaultValue: &Value{Kind: StringValue, Raw: "defaultA"}}, {Name: "B", Type: NamedType("String", nil)}, } t.Run("defaults", func(t *testing.T) { args := arg2map(defs, ArgumentList{}, nil) require.Equal(t, "defaultA", args["A"]) require.NotContains(t, args, "B") }) t.Run("values", func(t *testing.T) { args := arg2map(defs, ArgumentList{ {Name: "A", Value: &Value{Kind: StringValue, Raw: "valA"}}, {Name: "B", Value: &Value{Kind: StringValue, Raw: "valB"}}, }, nil) require.Equal(t, "valA", args["A"]) require.Equal(t, "valB", args["B"]) }) t.Run("nulls", func(t *testing.T) { args := arg2map(defs, ArgumentList{ {Name: "A", Value: &Value{Kind: NullValue}}, {Name: "B", Value: &Value{Kind: NullValue}}, }, nil) require.Equal(t, nil, args["A"]) require.Equal(t, nil, args["B"]) require.Contains(t, args, "A") require.Contains(t, args, "B") }) t.Run("undefined variables", func(t *testing.T) { args := arg2map(defs, ArgumentList{ {Name: "A", Value: &Value{Kind: Variable, Raw: "VarA"}}, {Name: "B", Value: &Value{Kind: Variable, Raw: "VarB"}}, }, map[string]interface{}{}) require.Equal(t, "defaultA", args["A"]) require.NotContains(t, args, "B") }) t.Run("nil variables", func(t *testing.T) { args := arg2map(defs, ArgumentList{ {Name: "A", Value: &Value{Kind: Variable, Raw: "VarA"}}, {Name: "B", Value: &Value{Kind: Variable, Raw: "VarB"}}, }, map[string]interface{}{ "VarA": nil, "VarB": nil, }) require.Equal(t, nil, args["A"]) require.Equal(t, nil, args["B"]) require.Contains(t, args, "A") require.Contains(t, args, "B") }) t.Run("defined variables", func(t *testing.T) { args := arg2map(defs, ArgumentList{ {Name: "A", Value: &Value{Kind: Variable, Raw: "VarA"}}, {Name: "B", Value: &Value{Kind: Variable, Raw: "VarB"}}, }, map[string]interface{}{ "VarA": "varvalA", "VarB": "varvalB", }) require.Equal(t, "varvalA", args["A"]) require.Equal(t, "varvalB", args["B"]) }) } gqlparser-2.5.1/ast/collections.go000066400000000000000000000050571430663104200171610ustar00rootroot00000000000000package ast type FieldList []*FieldDefinition func (l FieldList) ForName(name string) *FieldDefinition { for _, it := range l { if it.Name == name { return it } } return nil } type EnumValueList []*EnumValueDefinition func (l EnumValueList) ForName(name string) *EnumValueDefinition { for _, it := range l { if it.Name == name { return it } } return nil } type DirectiveList []*Directive func (l DirectiveList) ForName(name string) *Directive { for _, it := range l { if it.Name == name { return it } } return nil } func (l DirectiveList) ForNames(name string) []*Directive { resp := []*Directive{} for _, it := range l { if it.Name == name { resp = append(resp, it) } } return resp } type OperationList []*OperationDefinition func (l OperationList) ForName(name string) *OperationDefinition { if name == "" && len(l) == 1 { return l[0] } for _, it := range l { if it.Name == name { return it } } return nil } type FragmentDefinitionList []*FragmentDefinition func (l FragmentDefinitionList) ForName(name string) *FragmentDefinition { for _, it := range l { if it.Name == name { return it } } return nil } type VariableDefinitionList []*VariableDefinition func (l VariableDefinitionList) ForName(name string) *VariableDefinition { for _, it := range l { if it.Variable == name { return it } } return nil } type ArgumentList []*Argument func (l ArgumentList) ForName(name string) *Argument { for _, it := range l { if it.Name == name { return it } } return nil } type ArgumentDefinitionList []*ArgumentDefinition func (l ArgumentDefinitionList) ForName(name string) *ArgumentDefinition { for _, it := range l { if it.Name == name { return it } } return nil } type SchemaDefinitionList []*SchemaDefinition type DirectiveDefinitionList []*DirectiveDefinition func (l DirectiveDefinitionList) ForName(name string) *DirectiveDefinition { for _, it := range l { if it.Name == name { return it } } return nil } type DefinitionList []*Definition func (l DefinitionList) ForName(name string) *Definition { for _, it := range l { if it.Name == name { return it } } return nil } type OperationTypeDefinitionList []*OperationTypeDefinition func (l OperationTypeDefinitionList) ForType(name string) *OperationTypeDefinition { for _, it := range l { if it.Type == name { return it } } return nil } type ChildValueList []*ChildValue func (v ChildValueList) ForName(name string) *Value { for _, f := range v { if f.Name == name { return f.Value } } return nil } gqlparser-2.5.1/ast/decode.go000066400000000000000000000106131430663104200160600ustar00rootroot00000000000000package ast import ( "encoding/json" ) func UnmarshalSelectionSet(b []byte) (SelectionSet, error) { var tmp []json.RawMessage if err := json.Unmarshal(b, &tmp); err != nil { return nil, err } var result = make([]Selection, 0) for _, item := range tmp { var field Field if err := json.Unmarshal(item, &field); err == nil { result = append(result, &field) continue } var fragmentSpread FragmentSpread if err := json.Unmarshal(item, &fragmentSpread); err == nil { result = append(result, &fragmentSpread) continue } var inlineFragment InlineFragment if err := json.Unmarshal(item, &inlineFragment); err == nil { result = append(result, &inlineFragment) continue } } return result, nil } func (f *FragmentDefinition) UnmarshalJSON(b []byte) error { var tmp map[string]json.RawMessage if err := json.Unmarshal(b, &tmp); err != nil { return err } for k := range tmp { switch k { case "Name": err := json.Unmarshal(tmp[k], &f.Name) if err != nil { return err } case "VariableDefinition": err := json.Unmarshal(tmp[k], &f.VariableDefinition) if err != nil { return err } case "TypeCondition": err := json.Unmarshal(tmp[k], &f.TypeCondition) if err != nil { return err } case "Directives": err := json.Unmarshal(tmp[k], &f.Directives) if err != nil { return err } case "SelectionSet": ss, err := UnmarshalSelectionSet(tmp[k]) if err != nil { return err } f.SelectionSet = ss case "Definition": err := json.Unmarshal(tmp[k], &f.Definition) if err != nil { return err } case "Position": err := json.Unmarshal(tmp[k], &f.Position) if err != nil { return err } } } return nil } func (f *InlineFragment) UnmarshalJSON(b []byte) error { var tmp map[string]json.RawMessage if err := json.Unmarshal(b, &tmp); err != nil { return err } for k := range tmp { switch k { case "TypeCondition": err := json.Unmarshal(tmp[k], &f.TypeCondition) if err != nil { return err } case "Directives": err := json.Unmarshal(tmp[k], &f.Directives) if err != nil { return err } case "SelectionSet": ss, err := UnmarshalSelectionSet(tmp[k]) if err != nil { return err } f.SelectionSet = ss case "ObjectDefinition": err := json.Unmarshal(tmp[k], &f.ObjectDefinition) if err != nil { return err } case "Position": err := json.Unmarshal(tmp[k], &f.Position) if err != nil { return err } } } return nil } func (f *OperationDefinition) UnmarshalJSON(b []byte) error { var tmp map[string]json.RawMessage if err := json.Unmarshal(b, &tmp); err != nil { return err } for k := range tmp { switch k { case "Operation": err := json.Unmarshal(tmp[k], &f.Operation) if err != nil { return err } case "Name": err := json.Unmarshal(tmp[k], &f.Name) if err != nil { return err } case "VariableDefinitions": err := json.Unmarshal(tmp[k], &f.VariableDefinitions) if err != nil { return err } case "Directives": err := json.Unmarshal(tmp[k], &f.Directives) if err != nil { return err } case "SelectionSet": ss, err := UnmarshalSelectionSet(tmp[k]) if err != nil { return err } f.SelectionSet = ss case "Position": err := json.Unmarshal(tmp[k], &f.Position) if err != nil { return err } } } return nil } func (f *Field) UnmarshalJSON(b []byte) error { var tmp map[string]json.RawMessage if err := json.Unmarshal(b, &tmp); err != nil { return err } for k := range tmp { switch k { case "Alias": err := json.Unmarshal(tmp[k], &f.Alias) if err != nil { return err } case "Name": err := json.Unmarshal(tmp[k], &f.Name) if err != nil { return err } case "Arguments": err := json.Unmarshal(tmp[k], &f.Arguments) if err != nil { return err } case "Directives": err := json.Unmarshal(tmp[k], &f.Directives) if err != nil { return err } case "SelectionSet": ss, err := UnmarshalSelectionSet(tmp[k]) if err != nil { return err } f.SelectionSet = ss case "Position": err := json.Unmarshal(tmp[k], &f.Position) if err != nil { return err } case "Definition": err := json.Unmarshal(tmp[k], &f.Definition) if err != nil { return err } case "ObjectDefinition": err := json.Unmarshal(tmp[k], &f.ObjectDefinition) if err != nil { return err } } } return nil } gqlparser-2.5.1/ast/definition.go000066400000000000000000000046011430663104200167650ustar00rootroot00000000000000package ast type DefinitionKind string const ( Scalar DefinitionKind = "SCALAR" Object DefinitionKind = "OBJECT" Interface DefinitionKind = "INTERFACE" Union DefinitionKind = "UNION" Enum DefinitionKind = "ENUM" InputObject DefinitionKind = "INPUT_OBJECT" ) // Definition is the core type definition object, it includes all of the definable types // but does *not* cover schema or directives. // // @vektah: Javascript implementation has different types for all of these, but they are // more similar than different and don't define any behaviour. I think this style of // "some hot" struct works better, at least for go. // // Type extensions are also represented by this same struct. type Definition struct { Kind DefinitionKind Description string Name string Directives DirectiveList Interfaces []string // object and input object Fields FieldList // object and input object Types []string // union EnumValues EnumValueList // enum Position *Position `dump:"-"` BuiltIn bool `dump:"-"` } func (d *Definition) IsLeafType() bool { return d.Kind == Enum || d.Kind == Scalar } func (d *Definition) IsAbstractType() bool { return d.Kind == Interface || d.Kind == Union } func (d *Definition) IsCompositeType() bool { return d.Kind == Object || d.Kind == Interface || d.Kind == Union } func (d *Definition) IsInputType() bool { return d.Kind == Scalar || d.Kind == Enum || d.Kind == InputObject } func (d *Definition) OneOf(types ...string) bool { for _, t := range types { if d.Name == t { return true } } return false } type FieldDefinition struct { Description string Name string Arguments ArgumentDefinitionList // only for objects DefaultValue *Value // only for input objects Type *Type Directives DirectiveList Position *Position `dump:"-"` } type ArgumentDefinition struct { Description string Name string DefaultValue *Value Type *Type Directives DirectiveList Position *Position `dump:"-"` } type EnumValueDefinition struct { Description string Name string Directives DirectiveList Position *Position `dump:"-"` } type DirectiveDefinition struct { Description string Name string Arguments ArgumentDefinitionList Locations []DirectiveLocation IsRepeatable bool Position *Position `dump:"-"` } gqlparser-2.5.1/ast/directive.go000066400000000000000000000032071430663104200166140ustar00rootroot00000000000000package ast type DirectiveLocation string const ( // Executable LocationQuery DirectiveLocation = `QUERY` LocationMutation DirectiveLocation = `MUTATION` LocationSubscription DirectiveLocation = `SUBSCRIPTION` LocationField DirectiveLocation = `FIELD` LocationFragmentDefinition DirectiveLocation = `FRAGMENT_DEFINITION` LocationFragmentSpread DirectiveLocation = `FRAGMENT_SPREAD` LocationInlineFragment DirectiveLocation = `INLINE_FRAGMENT` // Type System LocationSchema DirectiveLocation = `SCHEMA` LocationScalar DirectiveLocation = `SCALAR` LocationObject DirectiveLocation = `OBJECT` LocationFieldDefinition DirectiveLocation = `FIELD_DEFINITION` LocationArgumentDefinition DirectiveLocation = `ARGUMENT_DEFINITION` LocationInterface DirectiveLocation = `INTERFACE` LocationUnion DirectiveLocation = `UNION` LocationEnum DirectiveLocation = `ENUM` LocationEnumValue DirectiveLocation = `ENUM_VALUE` LocationInputObject DirectiveLocation = `INPUT_OBJECT` LocationInputFieldDefinition DirectiveLocation = `INPUT_FIELD_DEFINITION` LocationVariableDefinition DirectiveLocation = `VARIABLE_DEFINITION` ) type Directive struct { Name string Arguments ArgumentList Position *Position `dump:"-"` // Requires validation ParentDefinition *Definition Definition *DirectiveDefinition Location DirectiveLocation } func (d *Directive) ArgumentMap(vars map[string]interface{}) map[string]interface{} { return arg2map(d.Definition.Arguments, d.Arguments, vars) } gqlparser-2.5.1/ast/document.go000066400000000000000000000042121430663104200164510ustar00rootroot00000000000000package ast type QueryDocument struct { Operations OperationList Fragments FragmentDefinitionList Position *Position `dump:"-"` } type SchemaDocument struct { Schema SchemaDefinitionList SchemaExtension SchemaDefinitionList Directives DirectiveDefinitionList Definitions DefinitionList Extensions DefinitionList Position *Position `dump:"-"` } func (d *SchemaDocument) Merge(other *SchemaDocument) { d.Schema = append(d.Schema, other.Schema...) d.SchemaExtension = append(d.SchemaExtension, other.SchemaExtension...) d.Directives = append(d.Directives, other.Directives...) d.Definitions = append(d.Definitions, other.Definitions...) d.Extensions = append(d.Extensions, other.Extensions...) } type Schema struct { Query *Definition Mutation *Definition Subscription *Definition Types map[string]*Definition Directives map[string]*DirectiveDefinition PossibleTypes map[string][]*Definition Implements map[string][]*Definition Description string } // AddTypes is the helper to add types definition to the schema func (s *Schema) AddTypes(defs ...*Definition) { if s.Types == nil { s.Types = make(map[string]*Definition) } for _, def := range defs { s.Types[def.Name] = def } } func (s *Schema) AddPossibleType(name string, def *Definition) { s.PossibleTypes[name] = append(s.PossibleTypes[name], def) } // GetPossibleTypes will enumerate all the definitions for a given interface or union func (s *Schema) GetPossibleTypes(def *Definition) []*Definition { return s.PossibleTypes[def.Name] } func (s *Schema) AddImplements(name string, iface *Definition) { s.Implements[name] = append(s.Implements[name], iface) } // GetImplements returns all the interface and union definitions that the given definition satisfies func (s *Schema) GetImplements(def *Definition) []*Definition { return s.Implements[def.Name] } type SchemaDefinition struct { Description string Directives DirectiveList OperationTypes OperationTypeDefinitionList Position *Position `dump:"-"` } type OperationTypeDefinition struct { Operation Operation Type string Position *Position `dump:"-"` } gqlparser-2.5.1/ast/document_test.go000066400000000000000000000043541430663104200175170ustar00rootroot00000000000000package ast_test import ( "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" . "github.com/vektah/gqlparser/v2/ast" "github.com/vektah/gqlparser/v2/parser" ) func TestQueryDocMethods(t *testing.T) { doc, err := parser.ParseQuery(&Source{Input: ` query Bob { foo { ...Frag } } fragment Frag on Foo { bar } `}) require.Nil(t, err) t.Run("GetOperation", func(t *testing.T) { require.EqualValues(t, "Bob", doc.Operations.ForName("Bob").Name) require.Nil(t, doc.Operations.ForName("Alice")) }) t.Run("GetFragment", func(t *testing.T) { require.EqualValues(t, "Frag", doc.Fragments.ForName("Frag").Name) require.Nil(t, doc.Fragments.ForName("Alice")) }) } func TestNamedTypeCompatability(t *testing.T) { assert.True(t, NamedType("A", nil).IsCompatible(NamedType("A", nil))) assert.False(t, NamedType("A", nil).IsCompatible(NamedType("B", nil))) assert.True(t, ListType(NamedType("A", nil), nil).IsCompatible(ListType(NamedType("A", nil), nil))) assert.False(t, ListType(NamedType("A", nil), nil).IsCompatible(ListType(NamedType("B", nil), nil))) assert.False(t, ListType(NamedType("A", nil), nil).IsCompatible(ListType(NamedType("B", nil), nil))) assert.True(t, ListType(NamedType("A", nil), nil).IsCompatible(ListType(NamedType("A", nil), nil))) assert.False(t, ListType(NamedType("A", nil), nil).IsCompatible(ListType(NamedType("B", nil), nil))) assert.False(t, ListType(NamedType("A", nil), nil).IsCompatible(ListType(NamedType("B", nil), nil))) assert.True(t, NonNullNamedType("A", nil).IsCompatible(NamedType("A", nil))) assert.False(t, NamedType("A", nil).IsCompatible(NonNullNamedType("A", nil))) assert.True(t, NonNullListType(NamedType("String", nil), nil).IsCompatible(NonNullListType(NamedType("String", nil), nil))) assert.True(t, NonNullListType(NamedType("String", nil), nil).IsCompatible(ListType(NamedType("String", nil), nil))) assert.False(t, ListType(NamedType("String", nil), nil).IsCompatible(NonNullListType(NamedType("String", nil), nil))) assert.True(t, ListType(NonNullNamedType("String", nil), nil).IsCompatible(ListType(NamedType("String", nil), nil))) assert.False(t, ListType(NamedType("String", nil), nil).IsCompatible(ListType(NonNullNamedType("String", nil), nil))) } gqlparser-2.5.1/ast/dumper.go000066400000000000000000000057061430663104200161400ustar00rootroot00000000000000package ast import ( "bytes" "fmt" "reflect" "strconv" "strings" ) // Dump turns ast into a stable string format for assertions in tests func Dump(i interface{}) string { v := reflect.ValueOf(i) d := dumper{Buffer: &bytes.Buffer{}} d.dump(v) return d.String() } type dumper struct { *bytes.Buffer indent int } type Dumpable interface { Dump() string } func (d *dumper) dump(v reflect.Value) { if dumpable, isDumpable := v.Interface().(Dumpable); isDumpable { d.WriteString(dumpable.Dump()) return } switch v.Kind() { case reflect.Bool: if v.Bool() { d.WriteString("true") } else { d.WriteString("false") } case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: d.WriteString(fmt.Sprintf("%d", v.Int())) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: d.WriteString(fmt.Sprintf("%d", v.Uint())) case reflect.Float32, reflect.Float64: d.WriteString(fmt.Sprintf("%.2f", v.Float())) case reflect.String: if v.Type().Name() != "string" { d.WriteString(v.Type().Name() + "(" + strconv.Quote(v.String()) + ")") } else { d.WriteString(strconv.Quote(v.String())) } case reflect.Array, reflect.Slice: d.dumpArray(v) case reflect.Interface, reflect.Ptr: d.dumpPtr(v) case reflect.Struct: d.dumpStruct(v) default: panic(fmt.Errorf("unsupported kind: %s\n buf: %s", v.Kind().String(), d.String())) } } func (d *dumper) writeIndent() { d.Buffer.WriteString(strings.Repeat(" ", d.indent)) } func (d *dumper) nl() { d.Buffer.WriteByte('\n') d.writeIndent() } func typeName(t reflect.Type) string { if t.Kind() == reflect.Ptr { return typeName(t.Elem()) } return t.Name() } func (d *dumper) dumpArray(v reflect.Value) { d.WriteString("[" + typeName(v.Type().Elem()) + "]") for i := 0; i < v.Len(); i++ { d.nl() d.WriteString("- ") d.indent++ d.dump(v.Index(i)) d.indent-- } } func (d *dumper) dumpStruct(v reflect.Value) { d.WriteString("<" + v.Type().Name() + ">") d.indent++ typ := v.Type() for i := 0; i < v.NumField(); i++ { f := v.Field(i) if typ.Field(i).Tag.Get("dump") == "-" { continue } if isZero(f) { continue } d.nl() d.WriteString(typ.Field(i).Name) d.WriteString(": ") d.dump(v.Field(i)) } d.indent-- } func isZero(v reflect.Value) bool { switch v.Kind() { case reflect.Ptr, reflect.Interface: return v.IsNil() case reflect.Func, reflect.Map: return v.IsNil() case reflect.Array, reflect.Slice: if v.IsNil() { return true } z := true for i := 0; i < v.Len(); i++ { z = z && isZero(v.Index(i)) } return z case reflect.Struct: z := true for i := 0; i < v.NumField(); i++ { z = z && isZero(v.Field(i)) } return z case reflect.String: return v.String() == "" } // Compare other types directly: return reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type())) } func (d *dumper) dumpPtr(v reflect.Value) { if v.IsNil() { d.WriteString("nil") return } d.dump(v.Elem()) } gqlparser-2.5.1/ast/dumper_test.go000066400000000000000000000011001430663104200171570ustar00rootroot00000000000000package ast import ( "fmt" "testing" "github.com/andreyvit/diff" "github.com/stretchr/testify/require" ) func TestDump(t *testing.T) { res := Dump(SchemaDefinition{ Directives: []*Directive{ { Name: "foo", Arguments: []*Argument{{Name: "bar"}}, }, {Arguments: []*Argument{}}, }, }) expected := ` Directives: [Directive] - Name: "foo" Arguments: [Argument] - Name: "bar" - ` fmt.Println(diff.LineDiff(expected, res)) require.Equal(t, expected, res) } gqlparser-2.5.1/ast/fragment.go000066400000000000000000000014161430663104200164410ustar00rootroot00000000000000package ast type FragmentSpread struct { Name string Directives DirectiveList // Require validation ObjectDefinition *Definition Definition *FragmentDefinition Position *Position `dump:"-"` } type InlineFragment struct { TypeCondition string Directives DirectiveList SelectionSet SelectionSet // Require validation ObjectDefinition *Definition Position *Position `dump:"-"` } type FragmentDefinition struct { Name string // Note: fragment variable definitions are experimental and may be changed // or removed in the future. VariableDefinition VariableDefinitionList TypeCondition string Directives DirectiveList SelectionSet SelectionSet // Require validation Definition *Definition Position *Position `dump:"-"` } gqlparser-2.5.1/ast/operation.go000066400000000000000000000012071430663104200166340ustar00rootroot00000000000000package ast type Operation string const ( Query Operation = "query" Mutation Operation = "mutation" Subscription Operation = "subscription" ) type OperationDefinition struct { Operation Operation Name string VariableDefinitions VariableDefinitionList Directives DirectiveList SelectionSet SelectionSet Position *Position `dump:"-"` } type VariableDefinition struct { Variable string Type *Type DefaultValue *Value Directives DirectiveList Position *Position `dump:"-"` // Requires validation Definition *Definition Used bool `dump:"-"` } gqlparser-2.5.1/ast/path.go000066400000000000000000000022371430663104200155740ustar00rootroot00000000000000package ast import ( "bytes" "encoding/json" "fmt" ) var _ json.Unmarshaler = (*Path)(nil) type Path []PathElement type PathElement interface { isPathElement() } var _ PathElement = PathIndex(0) var _ PathElement = PathName("") func (path Path) String() string { var str bytes.Buffer for i, v := range path { switch v := v.(type) { case PathIndex: str.WriteString(fmt.Sprintf("[%d]", v)) case PathName: if i != 0 { str.WriteByte('.') } str.WriteString(string(v)) default: panic(fmt.Sprintf("unknown type: %T", v)) } } return str.String() } func (path *Path) UnmarshalJSON(b []byte) error { var vs []interface{} err := json.Unmarshal(b, &vs) if err != nil { return err } *path = make([]PathElement, 0, len(vs)) for _, v := range vs { switch v := v.(type) { case string: *path = append(*path, PathName(v)) case int: *path = append(*path, PathIndex(v)) case float64: *path = append(*path, PathIndex(int(v))) default: return fmt.Errorf("unknown path element type: %T", v) } } return nil } type PathIndex int func (_ PathIndex) isPathElement() {} type PathName string func (_ PathName) isPathElement() {} gqlparser-2.5.1/ast/path_test.go000066400000000000000000000032421430663104200166300ustar00rootroot00000000000000package ast import ( "encoding/json" "testing" "github.com/stretchr/testify/require" ) func TestPath_String(t *testing.T) { type Spec struct { Value Path Expected string } specs := []*Spec{ { Value: Path{PathName("a"), PathIndex(2), PathName("c")}, Expected: "a[2].c", }, { Value: Path{}, Expected: ``, }, { Value: Path{PathIndex(1), PathName("b")}, Expected: `[1].b`, }, } for _, spec := range specs { t.Run(spec.Value.String(), func(t *testing.T) { require.Equal(t, spec.Expected, spec.Value.String()) }) } } func TestPath_MarshalJSON(t *testing.T) { type Spec struct { Value Path Expected string } specs := []*Spec{ { Value: Path{PathName("a"), PathIndex(2), PathName("c")}, Expected: `["a",2,"c"]`, }, { Value: Path{}, Expected: `[]`, }, { Value: Path{PathIndex(1), PathName("b")}, Expected: `[1,"b"]`, }, } for _, spec := range specs { t.Run(spec.Value.String(), func(t *testing.T) { b, err := json.Marshal(spec.Value) require.Nil(t, err) require.Equal(t, spec.Expected, string(b)) }) } } func TestPath_UnmarshalJSON(t *testing.T) { type Spec struct { Value string Expected Path } specs := []*Spec{ { Value: `["a",2,"c"]`, Expected: Path{PathName("a"), PathIndex(2), PathName("c")}, }, { Value: `[]`, Expected: Path{}, }, { Value: `[1,"b"]`, Expected: Path{PathIndex(1), PathName("b")}, }, } for _, spec := range specs { t.Run(spec.Value, func(t *testing.T) { var path Path err := json.Unmarshal([]byte(spec.Value), &path) require.Nil(t, err) require.Equal(t, spec.Expected, path) }) } } gqlparser-2.5.1/ast/selection.go000066400000000000000000000016721430663104200166270ustar00rootroot00000000000000package ast type SelectionSet []Selection type Selection interface { isSelection() GetPosition() *Position } func (*Field) isSelection() {} func (*FragmentSpread) isSelection() {} func (*InlineFragment) isSelection() {} func (s *Field) GetPosition() *Position { return s.Position } func (s *FragmentSpread) GetPosition() *Position { return s.Position } func (s *InlineFragment) GetPosition() *Position { return s.Position } type Field struct { Alias string Name string Arguments ArgumentList Directives DirectiveList SelectionSet SelectionSet Position *Position `dump:"-"` // Require validation Definition *FieldDefinition ObjectDefinition *Definition } type Argument struct { Name string Value *Value Position *Position `dump:"-"` } func (f *Field) ArgumentMap(vars map[string]interface{}) map[string]interface{} { return arg2map(f.Definition.Arguments, f.Arguments, vars) } gqlparser-2.5.1/ast/source.go000066400000000000000000000012101430663104200161260ustar00rootroot00000000000000package ast // Source covers a single *.graphql file type Source struct { // Name is the filename of the source Name string // Input is the actual contents of the source file Input string // BuiltIn indicate whether the source is a part of the specification BuiltIn bool } type Position struct { Start int // The starting position, in runes, of this token in the input. End int // The end position, in runes, of this token in the input. Line int // The line number at the start of this item. Column int // The column number at the start of this item. Src *Source // The source document this token belongs to } gqlparser-2.5.1/ast/type.go000066400000000000000000000022721430663104200156200ustar00rootroot00000000000000package ast func NonNullNamedType(named string, pos *Position) *Type { return &Type{NamedType: named, NonNull: true, Position: pos} } func NamedType(named string, pos *Position) *Type { return &Type{NamedType: named, NonNull: false, Position: pos} } func NonNullListType(elem *Type, pos *Position) *Type { return &Type{Elem: elem, NonNull: true, Position: pos} } func ListType(elem *Type, pos *Position) *Type { return &Type{Elem: elem, NonNull: false, Position: pos} } type Type struct { NamedType string Elem *Type NonNull bool Position *Position `dump:"-"` } func (t *Type) Name() string { if t.NamedType != "" { return t.NamedType } return t.Elem.Name() } func (t *Type) String() string { nn := "" if t.NonNull { nn = "!" } if t.NamedType != "" { return t.NamedType + nn } return "[" + t.Elem.String() + "]" + nn } func (t *Type) IsCompatible(other *Type) bool { if t.NamedType != other.NamedType { return false } if t.Elem != nil && other.Elem == nil { return false } if t.Elem != nil && !t.Elem.IsCompatible(other.Elem) { return false } if other.NonNull { return t.NonNull } return true } func (v *Type) Dump() string { return v.String() } gqlparser-2.5.1/ast/value.go000066400000000000000000000045521430663104200157560ustar00rootroot00000000000000package ast import ( "fmt" "strconv" "strings" ) type ValueKind int const ( Variable ValueKind = iota IntValue FloatValue StringValue BlockValue BooleanValue NullValue EnumValue ListValue ObjectValue ) type Value struct { Raw string Children ChildValueList Kind ValueKind Position *Position `dump:"-"` // Require validation Definition *Definition VariableDefinition *VariableDefinition ExpectedType *Type } type ChildValue struct { Name string Value *Value Position *Position `dump:"-"` } func (v *Value) Value(vars map[string]interface{}) (interface{}, error) { if v == nil { return nil, nil } switch v.Kind { case Variable: if value, ok := vars[v.Raw]; ok { return value, nil } if v.VariableDefinition != nil && v.VariableDefinition.DefaultValue != nil { return v.VariableDefinition.DefaultValue.Value(vars) } return nil, nil case IntValue: return strconv.ParseInt(v.Raw, 10, 64) case FloatValue: return strconv.ParseFloat(v.Raw, 64) case StringValue, BlockValue, EnumValue: return v.Raw, nil case BooleanValue: return strconv.ParseBool(v.Raw) case NullValue: return nil, nil case ListValue: var val []interface{} for _, elem := range v.Children { elemVal, err := elem.Value.Value(vars) if err != nil { return val, err } val = append(val, elemVal) } return val, nil case ObjectValue: val := map[string]interface{}{} for _, elem := range v.Children { elemVal, err := elem.Value.Value(vars) if err != nil { return val, err } val[elem.Name] = elemVal } return val, nil default: panic(fmt.Errorf("unknown value kind %d", v.Kind)) } } func (v *Value) String() string { if v == nil { return "" } switch v.Kind { case Variable: return "$" + v.Raw case IntValue, FloatValue, EnumValue, BooleanValue, NullValue: return v.Raw case StringValue, BlockValue: return strconv.Quote(v.Raw) case ListValue: var val []string for _, elem := range v.Children { val = append(val, elem.Value.String()) } return "[" + strings.Join(val, ",") + "]" case ObjectValue: var val []string for _, elem := range v.Children { val = append(val, elem.Name+":"+elem.Value.String()) } return "{" + strings.Join(val, ",") + "}" default: panic(fmt.Errorf("unknown value kind %d", v.Kind)) } } func (v *Value) Dump() string { return v.String() } gqlparser-2.5.1/bin/000077500000000000000000000000001430663104200142665ustar00rootroot00000000000000gqlparser-2.5.1/bin/release000077500000000000000000000010311430663104200156270ustar00rootroot00000000000000#!/bin/bash set -eu if ! [ $# -eq 1 ] ; then echo "usage: ./bin/release [version]" exit 1 fi VERSION=$1 if ! git diff-index --quiet HEAD -- ; then echo "uncommited changes on HEAD, aborting" exit 1 fi if [[ ${VERSION:0:1} != "v" ]] ; then echo "version strings must start with v" exit 1 fi git fetch origin git checkout origin/master git tag -a $VERSION -m $VERSION git push origin $VERSION git push origin HEAD:master echo "Now go write some release notes! https://github.com/vektah/gqlparser/releases" gqlparser-2.5.1/formatter/000077500000000000000000000000001430663104200155215ustar00rootroot00000000000000gqlparser-2.5.1/formatter/formatter.go000066400000000000000000000321441430663104200200570ustar00rootroot00000000000000package formatter import ( "fmt" "io" "sort" "strings" "github.com/vektah/gqlparser/v2/ast" ) type Formatter interface { FormatSchema(schema *ast.Schema) FormatSchemaDocument(doc *ast.SchemaDocument) FormatQueryDocument(doc *ast.QueryDocument) } type FormatterOption func(*formatter) func WithIndent(indent string) FormatterOption { return func(f *formatter) { f.indent = indent } } func NewFormatter(w io.Writer, options ...FormatterOption) Formatter { f := &formatter{ indent: "\t", writer: w, } for _, opt := range options { opt(f) } return f } type formatter struct { writer io.Writer indent string indentSize int emitBuiltin bool padNext bool lineHead bool } func (f *formatter) writeString(s string) { _, _ = f.writer.Write([]byte(s)) } func (f *formatter) writeIndent() *formatter { if f.lineHead { f.writeString(strings.Repeat(f.indent, f.indentSize)) } f.lineHead = false f.padNext = false return f } func (f *formatter) WriteNewline() *formatter { f.writeString("\n") f.lineHead = true f.padNext = false return f } func (f *formatter) WriteWord(word string) *formatter { if f.lineHead { f.writeIndent() } if f.padNext { f.writeString(" ") } f.writeString(strings.TrimSpace(word)) f.padNext = true return f } func (f *formatter) WriteString(s string) *formatter { if f.lineHead { f.writeIndent() } if f.padNext { f.writeString(" ") } f.writeString(s) f.padNext = false return f } func (f *formatter) WriteDescription(s string) *formatter { if s == "" { return f } f.WriteString(`"""`) if ss := strings.Split(s, "\n"); len(ss) > 1 { f.WriteNewline() for _, s := range ss { f.WriteString(s).WriteNewline() } } else { f.WriteString(s) } f.WriteString(`"""`).WriteNewline() return f } func (f *formatter) IncrementIndent() { f.indentSize++ } func (f *formatter) DecrementIndent() { f.indentSize-- } func (f *formatter) NoPadding() *formatter { f.padNext = false return f } func (f *formatter) NeedPadding() *formatter { f.padNext = true return f } func (f *formatter) FormatSchema(schema *ast.Schema) { if schema == nil { return } var inSchema bool startSchema := func() { if !inSchema { inSchema = true f.WriteWord("schema").WriteString("{").WriteNewline() f.IncrementIndent() } } if schema.Query != nil && schema.Query.Name != "Query" { startSchema() f.WriteWord("query").NoPadding().WriteString(":").NeedPadding() f.WriteWord(schema.Query.Name).WriteNewline() } if schema.Mutation != nil && schema.Mutation.Name != "Mutation" { startSchema() f.WriteWord("mutation").NoPadding().WriteString(":").NeedPadding() f.WriteWord(schema.Mutation.Name).WriteNewline() } if schema.Subscription != nil && schema.Subscription.Name != "Subscription" { startSchema() f.WriteWord("subscription").NoPadding().WriteString(":").NeedPadding() f.WriteWord(schema.Subscription.Name).WriteNewline() } if inSchema { f.DecrementIndent() f.WriteString("}").WriteNewline() } directiveNames := make([]string, 0, len(schema.Directives)) for name := range schema.Directives { directiveNames = append(directiveNames, name) } sort.Strings(directiveNames) for _, name := range directiveNames { f.FormatDirectiveDefinition(schema.Directives[name]) } typeNames := make([]string, 0, len(schema.Types)) for name := range schema.Types { typeNames = append(typeNames, name) } sort.Strings(typeNames) for _, name := range typeNames { f.FormatDefinition(schema.Types[name], false) } } func (f *formatter) FormatSchemaDocument(doc *ast.SchemaDocument) { // TODO emit by position based order if doc == nil { return } f.FormatSchemaDefinitionList(doc.Schema, false) f.FormatSchemaDefinitionList(doc.SchemaExtension, true) f.FormatDirectiveDefinitionList(doc.Directives) f.FormatDefinitionList(doc.Definitions, false) f.FormatDefinitionList(doc.Extensions, true) } func (f *formatter) FormatQueryDocument(doc *ast.QueryDocument) { // TODO emit by position based order if doc == nil { return } f.FormatOperationList(doc.Operations) f.FormatFragmentDefinitionList(doc.Fragments) } func (f *formatter) FormatSchemaDefinitionList(lists ast.SchemaDefinitionList, extension bool) { if len(lists) == 0 { return } if extension { f.WriteWord("extend") } f.WriteWord("schema").WriteString("{").WriteNewline() f.IncrementIndent() for _, def := range lists { f.FormatSchemaDefinition(def) } f.DecrementIndent() f.WriteString("}").WriteNewline() } func (f *formatter) FormatSchemaDefinition(def *ast.SchemaDefinition) { f.WriteDescription(def.Description) f.FormatDirectiveList(def.Directives) f.FormatOperationTypeDefinitionList(def.OperationTypes) } func (f *formatter) FormatOperationTypeDefinitionList(lists ast.OperationTypeDefinitionList) { for _, def := range lists { f.FormatOperationTypeDefinition(def) } } func (f *formatter) FormatOperationTypeDefinition(def *ast.OperationTypeDefinition) { f.WriteWord(string(def.Operation)).NoPadding().WriteString(":").NeedPadding() f.WriteWord(def.Type) f.WriteNewline() } func (f *formatter) FormatFieldList(fieldList ast.FieldList) { if len(fieldList) == 0 { return } f.WriteString("{").WriteNewline() f.IncrementIndent() for _, field := range fieldList { f.FormatFieldDefinition(field) } f.DecrementIndent() f.WriteString("}") } func (f *formatter) FormatFieldDefinition(field *ast.FieldDefinition) { if !f.emitBuiltin && strings.HasPrefix(field.Name, "__") { return } f.WriteDescription(field.Description) f.WriteWord(field.Name).NoPadding() f.FormatArgumentDefinitionList(field.Arguments) f.NoPadding().WriteString(":").NeedPadding() f.FormatType(field.Type) if field.DefaultValue != nil { f.WriteWord("=") f.FormatValue(field.DefaultValue) } f.FormatDirectiveList(field.Directives) f.WriteNewline() } func (f *formatter) FormatArgumentDefinitionList(lists ast.ArgumentDefinitionList) { if len(lists) == 0 { return } f.WriteString("(") for idx, arg := range lists { f.FormatArgumentDefinition(arg) // Skip emitting (insignificant) comma in case it is the // last argument, or we printed a new line in its definition. if idx != len(lists)-1 && arg.Description == "" { f.NoPadding().WriteWord(",") } } f.NoPadding().WriteString(")").NeedPadding() } func (f *formatter) FormatArgumentDefinition(def *ast.ArgumentDefinition) { if def.Description != "" { f.WriteNewline().IncrementIndent() f.WriteDescription(def.Description) } f.WriteWord(def.Name).NoPadding().WriteString(":").NeedPadding() f.FormatType(def.Type) if def.DefaultValue != nil { f.WriteWord("=") f.FormatValue(def.DefaultValue) } f.NeedPadding().FormatDirectiveList(def.Directives) if def.Description != "" { f.DecrementIndent() f.WriteNewline() } } func (f *formatter) FormatDirectiveLocation(location ast.DirectiveLocation) { f.WriteWord(string(location)) } func (f *formatter) FormatDirectiveDefinitionList(lists ast.DirectiveDefinitionList) { if len(lists) == 0 { return } for _, dec := range lists { f.FormatDirectiveDefinition(dec) } } func (f *formatter) FormatDirectiveDefinition(def *ast.DirectiveDefinition) { if !f.emitBuiltin { if def.Position.Src.BuiltIn { return } } f.WriteDescription(def.Description) f.WriteWord("directive").WriteString("@").WriteWord(def.Name) if len(def.Arguments) != 0 { f.NoPadding() f.FormatArgumentDefinitionList(def.Arguments) } if len(def.Locations) != 0 { f.WriteWord("on") for idx, dirLoc := range def.Locations { f.FormatDirectiveLocation(dirLoc) if idx != len(def.Locations)-1 { f.WriteWord("|") } } } f.WriteNewline() } func (f *formatter) FormatDefinitionList(lists ast.DefinitionList, extend bool) { if len(lists) == 0 { return } for _, dec := range lists { f.FormatDefinition(dec, extend) } } func (f *formatter) FormatDefinition(def *ast.Definition, extend bool) { if !f.emitBuiltin && def.BuiltIn { return } f.WriteDescription(def.Description) if extend { f.WriteWord("extend") } switch def.Kind { case ast.Scalar: f.WriteWord("scalar").WriteWord(def.Name) case ast.Object: f.WriteWord("type").WriteWord(def.Name) case ast.Interface: f.WriteWord("interface").WriteWord(def.Name) case ast.Union: f.WriteWord("union").WriteWord(def.Name) case ast.Enum: f.WriteWord("enum").WriteWord(def.Name) case ast.InputObject: f.WriteWord("input").WriteWord(def.Name) } if len(def.Interfaces) != 0 { f.WriteWord("implements").WriteWord(strings.Join(def.Interfaces, " & ")) } f.FormatDirectiveList(def.Directives) if len(def.Types) != 0 { f.WriteWord("=").WriteWord(strings.Join(def.Types, " | ")) } f.FormatFieldList(def.Fields) f.FormatEnumValueList(def.EnumValues) f.WriteNewline() } func (f *formatter) FormatEnumValueList(lists ast.EnumValueList) { if len(lists) == 0 { return } f.WriteString("{").WriteNewline() f.IncrementIndent() for _, v := range lists { f.FormatEnumValueDefinition(v) } f.DecrementIndent() f.WriteString("}") } func (f *formatter) FormatEnumValueDefinition(def *ast.EnumValueDefinition) { f.WriteDescription(def.Description) f.WriteWord(def.Name) f.FormatDirectiveList(def.Directives) f.WriteNewline() } func (f *formatter) FormatOperationList(lists ast.OperationList) { for _, def := range lists { f.FormatOperationDefinition(def) } } func (f *formatter) FormatOperationDefinition(def *ast.OperationDefinition) { f.WriteWord(string(def.Operation)) if def.Name != "" { f.WriteWord(def.Name) } f.FormatVariableDefinitionList(def.VariableDefinitions) f.FormatDirectiveList(def.Directives) if len(def.SelectionSet) != 0 { f.FormatSelectionSet(def.SelectionSet) f.WriteNewline() } } func (f *formatter) FormatDirectiveList(lists ast.DirectiveList) { if len(lists) == 0 { return } for _, dir := range lists { f.FormatDirective(dir) } } func (f *formatter) FormatDirective(dir *ast.Directive) { f.WriteString("@").WriteWord(dir.Name) f.FormatArgumentList(dir.Arguments) } func (f *formatter) FormatArgumentList(lists ast.ArgumentList) { if len(lists) == 0 { return } f.NoPadding().WriteString("(") for idx, arg := range lists { f.FormatArgument(arg) if idx != len(lists)-1 { f.NoPadding().WriteWord(",") } } f.WriteString(")").NeedPadding() } func (f *formatter) FormatArgument(arg *ast.Argument) { f.WriteWord(arg.Name).NoPadding().WriteString(":").NeedPadding() f.WriteString(arg.Value.String()) } func (f *formatter) FormatFragmentDefinitionList(lists ast.FragmentDefinitionList) { for _, def := range lists { f.FormatFragmentDefinition(def) } } func (f *formatter) FormatFragmentDefinition(def *ast.FragmentDefinition) { f.WriteWord("fragment").WriteWord(def.Name) f.FormatVariableDefinitionList(def.VariableDefinition) f.WriteWord("on").WriteWord(def.TypeCondition) f.FormatDirectiveList(def.Directives) if len(def.SelectionSet) != 0 { f.FormatSelectionSet(def.SelectionSet) f.WriteNewline() } } func (f *formatter) FormatVariableDefinitionList(lists ast.VariableDefinitionList) { if len(lists) == 0 { return } f.WriteString("(") for idx, def := range lists { f.FormatVariableDefinition(def) if idx != len(lists)-1 { f.NoPadding().WriteWord(",") } } f.NoPadding().WriteString(")").NeedPadding() } func (f *formatter) FormatVariableDefinition(def *ast.VariableDefinition) { f.WriteString("$").WriteWord(def.Variable).NoPadding().WriteString(":").NeedPadding() f.FormatType(def.Type) if def.DefaultValue != nil { f.WriteWord("=") f.FormatValue(def.DefaultValue) } // TODO https://github.com/vektah/gqlparser/v2/issues/102 // VariableDefinition : Variable : Type DefaultValue? Directives[Const]? } func (f *formatter) FormatSelectionSet(sets ast.SelectionSet) { if len(sets) == 0 { return } f.WriteString("{").WriteNewline() f.IncrementIndent() for _, sel := range sets { f.FormatSelection(sel) } f.DecrementIndent() f.WriteString("}") } func (f *formatter) FormatSelection(selection ast.Selection) { switch v := selection.(type) { case *ast.Field: f.FormatField(v) case *ast.FragmentSpread: f.FormatFragmentSpread(v) case *ast.InlineFragment: f.FormatInlineFragment(v) default: panic(fmt.Errorf("unknown Selection type: %T", selection)) } f.WriteNewline() } func (f *formatter) FormatField(field *ast.Field) { if field.Alias != "" && field.Alias != field.Name { f.WriteWord(field.Alias).NoPadding().WriteString(":").NeedPadding() } f.WriteWord(field.Name) if len(field.Arguments) != 0 { f.NoPadding() f.FormatArgumentList(field.Arguments) f.NeedPadding() } f.FormatDirectiveList(field.Directives) f.FormatSelectionSet(field.SelectionSet) } func (f *formatter) FormatFragmentSpread(spread *ast.FragmentSpread) { f.WriteWord("...").WriteWord(spread.Name) f.FormatDirectiveList(spread.Directives) } func (f *formatter) FormatInlineFragment(inline *ast.InlineFragment) { f.WriteWord("...") if inline.TypeCondition != "" { f.WriteWord("on").WriteWord(inline.TypeCondition) } f.FormatDirectiveList(inline.Directives) f.FormatSelectionSet(inline.SelectionSet) } func (f *formatter) FormatType(t *ast.Type) { f.WriteWord(t.String()) } func (f *formatter) FormatValue(value *ast.Value) { f.WriteString(value.String()) } gqlparser-2.5.1/formatter/formatter_test.go000066400000000000000000000113511430663104200211130ustar00rootroot00000000000000package formatter_test import ( "bytes" "flag" "os" "path" "testing" "unicode/utf8" "github.com/stretchr/testify/assert" "github.com/vektah/gqlparser/v2" "github.com/vektah/gqlparser/v2/ast" "github.com/vektah/gqlparser/v2/formatter" "github.com/vektah/gqlparser/v2/parser" ) var update = flag.Bool("u", false, "update golden files") func TestFormatter_FormatSchema(t *testing.T) { const testSourceDir = "./testdata/source/schema" const testBaselineDir = "./testdata/baseline/FormatSchema" executeGoldenTesting(t, &goldenConfig{ SourceDir: testSourceDir, BaselineFileName: func(cfg *goldenConfig, f os.DirEntry) string { return path.Join(testBaselineDir, f.Name()) }, Run: func(t *testing.T, cfg *goldenConfig, f os.DirEntry) []byte { // load stuff schema, gqlErr := gqlparser.LoadSchema(&ast.Source{ Name: f.Name(), Input: mustReadFile(path.Join(testSourceDir, f.Name())), }) if gqlErr != nil { t.Fatal(gqlErr) } // exec format var buf bytes.Buffer formatter.NewFormatter(&buf).FormatSchema(schema) // validity check _, gqlErr = gqlparser.LoadSchema(&ast.Source{ Name: f.Name(), Input: buf.String(), }) if gqlErr != nil { t.Log(buf.String()) t.Fatal(gqlErr) } return buf.Bytes() }, }) } func TestFormatter_FormatSchemaDocument(t *testing.T) { const testSourceDir = "./testdata/source/schema" const testBaselineDir = "./testdata/baseline/FormatSchemaDocument" executeGoldenTesting(t, &goldenConfig{ SourceDir: testSourceDir, BaselineFileName: func(cfg *goldenConfig, f os.DirEntry) string { return path.Join(testBaselineDir, f.Name()) }, Run: func(t *testing.T, cfg *goldenConfig, f os.DirEntry) []byte { // load stuff doc, gqlErr := parser.ParseSchema(&ast.Source{ Name: f.Name(), Input: mustReadFile(path.Join(testSourceDir, f.Name())), }) if gqlErr != nil { t.Fatal(gqlErr) } // exec format var buf bytes.Buffer formatter.NewFormatter(&buf).FormatSchemaDocument(doc) // validity check _, gqlErr = parser.ParseSchema(&ast.Source{ Name: f.Name(), Input: buf.String(), }) if gqlErr != nil { t.Log(buf.String()) t.Fatal(gqlErr) } return buf.Bytes() }, }) } func TestFormatter_FormatQueryDocument(t *testing.T) { const testSourceDir = "./testdata/source/query" const testBaselineDir = "./testdata/baseline/FormatQueryDocument" executeGoldenTesting(t, &goldenConfig{ SourceDir: testSourceDir, BaselineFileName: func(cfg *goldenConfig, f os.DirEntry) string { return path.Join(testBaselineDir, f.Name()) }, Run: func(t *testing.T, cfg *goldenConfig, f os.DirEntry) []byte { // load stuff doc, gqlErr := parser.ParseQuery(&ast.Source{ Name: f.Name(), Input: mustReadFile(path.Join(testSourceDir, f.Name())), }) if gqlErr != nil { t.Fatal(gqlErr) } // exec format var buf bytes.Buffer formatter.NewFormatter(&buf).FormatQueryDocument(doc) // validity check _, gqlErr = parser.ParseQuery(&ast.Source{ Name: f.Name(), Input: buf.String(), }) if gqlErr != nil { t.Log(buf.String()) t.Fatal(gqlErr) } return buf.Bytes() }, }) } type goldenConfig struct { SourceDir string IsTarget func(f os.FileInfo) bool BaselineFileName func(cfg *goldenConfig, f os.DirEntry) string Run func(t *testing.T, cfg *goldenConfig, f os.DirEntry) []byte } func executeGoldenTesting(t *testing.T, cfg *goldenConfig) { t.Helper() if cfg.IsTarget == nil { cfg.IsTarget = func(f os.FileInfo) bool { return !f.IsDir() } } if cfg.BaselineFileName == nil { t.Fatal("BaselineFileName function is required") } if cfg.Run == nil { t.Fatal("Run function is required") } fs, err := os.ReadDir(cfg.SourceDir) if err != nil { t.Fatal(fs) } for _, f := range fs { if f.IsDir() { continue } f := f t.Run(f.Name(), func(t *testing.T) { result := cfg.Run(t, cfg, f) expectedFilePath := cfg.BaselineFileName(cfg, f) if *update { err := os.Remove(expectedFilePath) if err != nil && !os.IsNotExist(err) { t.Fatal(err) } } expected, err := os.ReadFile(expectedFilePath) if os.IsNotExist(err) { err = os.MkdirAll(path.Dir(expectedFilePath), 0755) if err != nil { t.Fatal(err) } err = os.WriteFile(expectedFilePath, result, 0444) if err != nil { t.Fatal(err) } return } else if err != nil { t.Fatal(err) } if bytes.Equal(expected, result) { return } if utf8.Valid(expected) { assert.Equalf(t, string(expected), string(result), "if you want to accept new result. use -u option") } }) } } func mustReadFile(name string) string { src, err := os.ReadFile(name) if err != nil { panic(err) } return string(src) } gqlparser-2.5.1/formatter/testdata/000077500000000000000000000000001430663104200173325ustar00rootroot00000000000000gqlparser-2.5.1/formatter/testdata/baseline/000077500000000000000000000000001430663104200211145ustar00rootroot00000000000000gqlparser-2.5.1/formatter/testdata/baseline/FormatQueryDocument/000077500000000000000000000000001430663104200250715ustar00rootroot00000000000000gqlparser-2.5.1/formatter/testdata/baseline/FormatQueryDocument/basic.graphql000066400000000000000000000001461430663104200275330ustar00rootroot00000000000000query FooBarQuery ($after: String!) { fizzList(first: 100, after: $after) { nodes { id } } } gqlparser-2.5.1/formatter/testdata/baseline/FormatQueryDocument/field.graphql000066400000000000000000000000241430663104200275300ustar00rootroot00000000000000query { bar: foo } gqlparser-2.5.1/formatter/testdata/baseline/FormatQueryDocument/fragment.graphql000066400000000000000000000003261430663104200302550ustar00rootroot00000000000000query FooBarQuery ($after: String!) { fizzList(first: 100, after: $after) { nodes { id ... FooFragment ... on Foo { id } ... { id } name } } } fragment FooFragment on Foo { id } gqlparser-2.5.1/formatter/testdata/baseline/FormatQueryDocument/variable.graphql000066400000000000000000000001711430663104200302350ustar00rootroot00000000000000query ($first: Int = 30, $after: String!) { searchCats(first: $first, after: $after) { nodes { id name } } } gqlparser-2.5.1/formatter/testdata/baseline/FormatSchema/000077500000000000000000000000001430663104200234655ustar00rootroot00000000000000gqlparser-2.5.1/formatter/testdata/baseline/FormatSchema/definition.graphql000066400000000000000000000004041430663104200271730ustar00rootroot00000000000000scalar Cat0 type Cat1 { name: String } interface Cat2 { name: String } union Cat3 = Cat3_0 | Cat3_1 | Cat3_2 type Cat3_0 { name: String } type Cat3_1 { name: String } type Cat3_2 { name: String } enum Cat4 { NFC MAINECOON } input Cat5 { name: String } gqlparser-2.5.1/formatter/testdata/baseline/FormatSchema/description.graphql000066400000000000000000000001551430663104200273710ustar00rootroot00000000000000""" Cat is best kawaii animal in the world. meow! """ type Cat { """Shiny brillian name.""" name: String } gqlparser-2.5.1/formatter/testdata/baseline/FormatSchema/directive.graphql000066400000000000000000000000411430663104200270160ustar00rootroot00000000000000directive @foo on FIELD | OBJECT gqlparser-2.5.1/formatter/testdata/baseline/FormatSchema/directive_locations.graphql000066400000000000000000000003271430663104200311000ustar00rootroot00000000000000directive @foo on OBJECT | UNION | ENUM enum ConnectionStatus @foo { ONLINE OFFLINE ERROR } interface Named { name: String! } type Person implements Named @foo { name: String! } union PersonUnion @foo = Person gqlparser-2.5.1/formatter/testdata/baseline/FormatSchema/extensions.graphql000066400000000000000000000005441430663104200272470ustar00rootroot00000000000000directive @extends on OBJECT directive @key(fields: String!) on OBJECT | INTERFACE directive @permission(permission: String!) on FIELD_DEFINITION type Dog { name: String! owner: Person! @permission(permission: "admin") } type Person @key(fields: "name") { name: String! } type Query @extends { dogs: [Dog!]! } type Subscription { dogEvents: [Dog!]! } gqlparser-2.5.1/formatter/testdata/baseline/FormatSchema/field_definition.graphql000066400000000000000000000000611430663104200303350ustar00rootroot00000000000000input CatInput { food: String = "fish & meat" } gqlparser-2.5.1/formatter/testdata/baseline/FormatSchema/schema.graphql000066400000000000000000000010661430663104200263100ustar00rootroot00000000000000schema { query: TopQuery mutation: TopMutation subscription: TopSubscription } type TopMutation { noop: Boolean noop2( """noop2 foo bar""" arg: String ): Boolean noop3( """noop3 foo bar""" arg: String ): Boolean } type TopQuery { noop: Boolean noop2( """noop2 foo bar""" arg: String ): Boolean noop3( """noop3 foo bar""" arg: String ): Boolean } type TopSubscription { noop: Boolean noop2( """noop2 foo bar""" arg: String ): Boolean noop3( """noop3 foo bar""" arg1: String """noop3 foo bar""" arg2: String ): Boolean } gqlparser-2.5.1/formatter/testdata/baseline/FormatSchema/swapi.graphql000066400000000000000000000031641430663104200261740ustar00rootroot00000000000000interface Character { id: ID! name: String! friends: [Character] friendsConnection(first: Int, after: ID): FriendsConnection! appearsIn: [Episode]! } input ColorInput { red: Int! green: Int! blue: Int! } type Droid implements Character { id: ID! name: String! friends: [Character] friendsConnection(first: Int, after: ID): FriendsConnection! appearsIn: [Episode]! primaryFunction: String } enum Episode { NEWHOPE EMPIRE JEDI } type FriendsConnection { totalCount: Int edges: [FriendsEdge] friends: [Character] pageInfo: PageInfo! } type FriendsEdge { cursor: ID! node: Character } type Human implements Character { id: ID! name: String! homePlanet: String height(unit: LengthUnit = METER): Float mass: Float friends: [Character] friendsConnection(first: Int, after: ID): FriendsConnection! appearsIn: [Episode]! starships: [Starship] } enum LengthUnit { METER FOOT } type Mutation { createReview(episode: Episode, review: ReviewInput!): Review } type PageInfo { startCursor: ID endCursor: ID hasNextPage: Boolean! } type Query { hero(episode: Episode): Character reviews(episode: Episode!): [Review] search(text: String): [SearchResult] character(id: ID!): Character droid(id: ID!): Droid human(id: ID!): Human starship(id: ID!): Starship } type Review { episode: Episode stars: Int! commentary: String } input ReviewInput { stars: Int! commentary: String favorite_color: ColorInput } union SearchResult = Human | Droid | Starship type Starship { id: ID! name: String! length(unit: LengthUnit = METER): Float coordinates: [[Float!]!] } type Subscription { reviewAdded(episode: Episode): Review } gqlparser-2.5.1/formatter/testdata/baseline/FormatSchemaDocument/000077500000000000000000000000001430663104200251645ustar00rootroot00000000000000gqlparser-2.5.1/formatter/testdata/baseline/FormatSchemaDocument/definition.graphql000066400000000000000000000004041430663104200306720ustar00rootroot00000000000000scalar Cat0 type Cat1 { name: String } interface Cat2 { name: String } type Cat3_0 { name: String } type Cat3_1 { name: String } type Cat3_2 { name: String } union Cat3 = Cat3_0 | Cat3_1 | Cat3_2 enum Cat4 { NFC MAINECOON } input Cat5 { name: String } gqlparser-2.5.1/formatter/testdata/baseline/FormatSchemaDocument/description.graphql000066400000000000000000000001551430663104200310700ustar00rootroot00000000000000""" Cat is best kawaii animal in the world. meow! """ type Cat { """Shiny brillian name.""" name: String } gqlparser-2.5.1/formatter/testdata/baseline/FormatSchemaDocument/directive.graphql000066400000000000000000000000411430663104200305150ustar00rootroot00000000000000directive @foo on FIELD | OBJECT gqlparser-2.5.1/formatter/testdata/baseline/FormatSchemaDocument/directive_locations.graphql000066400000000000000000000003271430663104200325770ustar00rootroot00000000000000directive @foo on OBJECT | UNION | ENUM interface Named { name: String! } type Person implements Named @foo { name: String! } enum ConnectionStatus @foo { ONLINE OFFLINE ERROR } union PersonUnion @foo = Person gqlparser-2.5.1/formatter/testdata/baseline/FormatSchemaDocument/extensions.graphql000066400000000000000000000006771430663104200307550ustar00rootroot00000000000000schema { query: Query } extend schema { subscription: Subscription } directive @permission(permission: String!) on FIELD_DEFINITION directive @extends on OBJECT directive @key(fields: String!) on OBJECT | INTERFACE type Query @extends { dogs: [Dog!]! } type Subscription { dogEvents: [Dog!]! } type Dog { name: String! } type Person @key(fields: "name") { name: String! } extend type Dog { owner: Person! @permission(permission: "admin") } gqlparser-2.5.1/formatter/testdata/baseline/FormatSchemaDocument/field_definition.graphql000066400000000000000000000000611430663104200320340ustar00rootroot00000000000000input CatInput { food: String = "fish & meat" } gqlparser-2.5.1/formatter/testdata/baseline/FormatSchemaDocument/schema.graphql000066400000000000000000000010661430663104200300070ustar00rootroot00000000000000schema { query: TopQuery mutation: TopMutation subscription: TopSubscription } type TopMutation { noop: Boolean noop2( """noop2 foo bar""" arg: String ): Boolean noop3( """noop3 foo bar""" arg: String ): Boolean } type TopQuery { noop: Boolean noop2( """noop2 foo bar""" arg: String ): Boolean noop3( """noop3 foo bar""" arg: String ): Boolean } type TopSubscription { noop: Boolean noop2( """noop2 foo bar""" arg: String ): Boolean noop3( """noop3 foo bar""" arg1: String """noop3 foo bar""" arg2: String ): Boolean } gqlparser-2.5.1/formatter/testdata/baseline/FormatSchemaDocument/swapi.graphql000066400000000000000000000032751430663104200276760ustar00rootroot00000000000000schema { query: Query mutation: Mutation subscription: Subscription } type Query { hero(episode: Episode): Character reviews(episode: Episode!): [Review] search(text: String): [SearchResult] character(id: ID!): Character droid(id: ID!): Droid human(id: ID!): Human starship(id: ID!): Starship } type Mutation { createReview(episode: Episode, review: ReviewInput!): Review } type Subscription { reviewAdded(episode: Episode): Review } enum Episode { NEWHOPE EMPIRE JEDI } interface Character { id: ID! name: String! friends: [Character] friendsConnection(first: Int, after: ID): FriendsConnection! appearsIn: [Episode]! } enum LengthUnit { METER FOOT } type Human implements Character { id: ID! name: String! homePlanet: String height(unit: LengthUnit = METER): Float mass: Float friends: [Character] friendsConnection(first: Int, after: ID): FriendsConnection! appearsIn: [Episode]! starships: [Starship] } type Droid implements Character { id: ID! name: String! friends: [Character] friendsConnection(first: Int, after: ID): FriendsConnection! appearsIn: [Episode]! primaryFunction: String } type FriendsConnection { totalCount: Int edges: [FriendsEdge] friends: [Character] pageInfo: PageInfo! } type FriendsEdge { cursor: ID! node: Character } type PageInfo { startCursor: ID endCursor: ID hasNextPage: Boolean! } type Review { episode: Episode stars: Int! commentary: String } input ReviewInput { stars: Int! commentary: String favorite_color: ColorInput } input ColorInput { red: Int! green: Int! blue: Int! } type Starship { id: ID! name: String! length(unit: LengthUnit = METER): Float coordinates: [[Float!]!] } union SearchResult = Human | Droid | Starship gqlparser-2.5.1/formatter/testdata/source/000077500000000000000000000000001430663104200206325ustar00rootroot00000000000000gqlparser-2.5.1/formatter/testdata/source/query/000077500000000000000000000000001430663104200217775ustar00rootroot00000000000000gqlparser-2.5.1/formatter/testdata/source/query/basic.graphql000066400000000000000000000002011430663104200244310ustar00rootroot00000000000000query FooBarQuery ($after: String!) { fizzList(first: 100, after: $after) { nodes { id } } } gqlparser-2.5.1/formatter/testdata/source/query/field.graphql000066400000000000000000000000211430663104200244330ustar00rootroot00000000000000{ bar: foo } gqlparser-2.5.1/formatter/testdata/source/query/fragment.graphql000066400000000000000000000005031430663104200251600ustar00rootroot00000000000000query FooBarQuery ($after: String!) { fizzList(first: 100, after: $after) { nodes { id ... FooFragment ... on Foo { id } ... { id } name } } } fragment FooFragment on Foo { id } gqlparser-2.5.1/formatter/testdata/source/query/variable.graphql000066400000000000000000000002351430663104200251440ustar00rootroot00000000000000query ($first: Int = 30, $after: String!) { searchCats(first: $first, after: $after) { nodes { id name } } } gqlparser-2.5.1/formatter/testdata/source/schema/000077500000000000000000000000001430663104200220725ustar00rootroot00000000000000gqlparser-2.5.1/formatter/testdata/source/schema/definition.graphql000066400000000000000000000004311430663104200256000ustar00rootroot00000000000000scalar Cat0 type Cat1 { name: String } interface Cat2 { name: String } type Cat3_0 { name: String } type Cat3_1 { name: String } type Cat3_2 { name: String } union Cat3 = Cat3_0|Cat3_1|Cat3_2 enum Cat4 { NFC MAINECOON } input Cat5 { name: String } gqlparser-2.5.1/formatter/testdata/source/schema/description.graphql000066400000000000000000000001631430663104200257750ustar00rootroot00000000000000""" Cat is best kawaii animal in the world. meow! """ type Cat { """Shiny brillian name.""" name: String } gqlparser-2.5.1/formatter/testdata/source/schema/directive.graphql000066400000000000000000000000371430663104200254300ustar00rootroot00000000000000directive @foo on FIELD|OBJECT gqlparser-2.5.1/formatter/testdata/source/schema/directive_locations.graphql000066400000000000000000000003271430663104200275050ustar00rootroot00000000000000directive @foo on OBJECT | UNION | ENUM interface Named { name: String! } type Person implements Named @foo { name: String! } enum ConnectionStatus @foo { ONLINE OFFLINE ERROR } union PersonUnion @foo = Person gqlparser-2.5.1/formatter/testdata/source/schema/extensions.graphql000066400000000000000000000007321430663104200256530ustar00rootroot00000000000000schema { query: Query } extend schema { subscription: Subscription } type Query @extends { dogs: [Dog!]! } type Subscription { dogEvents: [Dog!]! } type Dog { name: String! } type Person @key(fields: "name") { name: String! } extend type Dog { owner: Person! @permission(permission: "admin") } directive @permission(permission: String!) on FIELD_DEFINITION directive @extends on OBJECT directive @key(fields: String!) on OBJECT | INTERFACEgqlparser-2.5.1/formatter/testdata/source/schema/field_definition.graphql000066400000000000000000000000641430663104200267450ustar00rootroot00000000000000input CatInput { food: String = "fish & meat" } gqlparser-2.5.1/formatter/testdata/source/schema/schema.graphql000066400000000000000000000013031430663104200247070ustar00rootroot00000000000000schema { query: TopQuery mutation: TopMutation subscription: TopSubscription } type TopMutation { noop: Boolean noop2(""" noop2 foo bar """ arg: String ): Boolean noop3("noop3 foo bar" arg: String ): Boolean } type TopQuery { noop: Boolean noop2(""" noop2 foo bar """ arg: String ): Boolean noop3( "noop3 foo bar" arg: String ): Boolean } type TopSubscription { noop: Boolean noop2( """noop2 foo bar""" arg: String ): Boolean noop3( "noop3 foo bar" arg1: String "noop3 foo bar" arg2: String ): Boolean } gqlparser-2.5.1/formatter/testdata/source/schema/swapi.graphql000066400000000000000000000105531430663104200246010ustar00rootroot00000000000000schema { query: Query mutation: Mutation subscription: Subscription } # The query type, represents all of the entry points into our object graph type Query { hero(episode: Episode): Character reviews(episode: Episode!): [Review] search(text: String): [SearchResult] character(id: ID!): Character droid(id: ID!): Droid human(id: ID!): Human starship(id: ID!): Starship } # The mutation type, represents all updates we can make to our data type Mutation { createReview(episode: Episode, review: ReviewInput!): Review } # The subscription type, represents all subscriptions we can make to our data type Subscription { reviewAdded(episode: Episode): Review } # The episodes in the Star Wars trilogy enum Episode { # Star Wars Episode IV: A New Hope, released in 1977. NEWHOPE # Star Wars Episode V: The Empire Strikes Back, released in 1980. EMPIRE # Star Wars Episode VI: Return of the Jedi, released in 1983. JEDI } # A character from the Star Wars universe interface Character { # The ID of the character id: ID! # The name of the character name: String! # The friends of the character, or an empty list if they have none friends: [Character] # The friends of the character exposed as a connection with edges friendsConnection(first: Int, after: ID): FriendsConnection! # The movies this character appears in appearsIn: [Episode]! } # Units of height enum LengthUnit { # The standard unit around the world METER # Primarily used in the United States FOOT } # A humanoid creature from the Star Wars universe type Human implements Character { # The ID of the human id: ID! # What this human calls themselves name: String! # The home planet of the human, or null if unknown homePlanet: String # Height in the preferred unit, default is meters height(unit: LengthUnit = METER): Float # Mass in kilograms, or null if unknown mass: Float # This human's friends, or an empty list if they have none friends: [Character] # The friends of the human exposed as a connection with edges friendsConnection(first: Int, after: ID): FriendsConnection! # The movies this human appears in appearsIn: [Episode]! # A list of starships this person has piloted, or an empty list if none starships: [Starship] } # An autonomous mechanical character in the Star Wars universe type Droid implements Character { # The ID of the droid id: ID! # What others call this droid name: String! # This droid's friends, or an empty list if they have none friends: [Character] # The friends of the droid exposed as a connection with edges friendsConnection(first: Int, after: ID): FriendsConnection! # The movies this droid appears in appearsIn: [Episode]! # This droid's primary function primaryFunction: String } # A connection object for a character's friends type FriendsConnection { # The total number of friends totalCount: Int # The edges for each of the character's friends. edges: [FriendsEdge] # A list of the friends, as a convenience when edges are not needed. friends: [Character] # Information for paginating this connection pageInfo: PageInfo! } # An edge object for a character's friends type FriendsEdge { # A cursor used for pagination cursor: ID! # The character represented by this friendship edge node: Character } # Information for paginating this connection type PageInfo { startCursor: ID endCursor: ID hasNextPage: Boolean! } # Represents a review for a movie type Review { # The movie episode: Episode # The number of stars this review gave, 1-5 stars: Int! # Comment about the movie commentary: String } # The input object sent when someone is creating a new review input ReviewInput { # 0-5 stars stars: Int! # Comment about the movie, optional commentary: String # Favorite color, optional favorite_color: ColorInput } # The input object sent when passing in a color input ColorInput { red: Int! green: Int! blue: Int! } type Starship { # The ID of the starship id: ID! # The name of the starship name: String! # Length of the starship, along the longest axis length(unit: LengthUnit = METER): Float coordinates: [[Float!]!] } union SearchResult = Human | Droid | Starshipgqlparser-2.5.1/go.mod000066400000000000000000000004141430663104200146230ustar00rootroot00000000000000module github.com/vektah/gqlparser/v2 go 1.16 require ( github.com/agnivade/levenshtein v1.0.1 github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 github.com/sergi/go-diff v1.1.0 // indirect github.com/stretchr/testify v1.4.0 gopkg.in/yaml.v2 v2.2.8 ) gqlparser-2.5.1/go.sum000066400000000000000000000043621430663104200146560ustar00rootroot00000000000000github.com/agnivade/levenshtein v1.0.1 h1:3oJU7J3FGFmyhn8KHjmVaZCN5hxTr7GxgRue+sxIXdQ= github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gqlparser-2.5.1/gqlerror/000077500000000000000000000000001430663104200153535ustar00rootroot00000000000000gqlparser-2.5.1/gqlerror/error.go000066400000000000000000000054461430663104200170440ustar00rootroot00000000000000package gqlerror import ( "bytes" "errors" "fmt" "strconv" "github.com/vektah/gqlparser/v2/ast" ) // Error is the standard graphql error type described in https://facebook.github.io/graphql/draft/#sec-Errors type Error struct { err error `json:"-"` Message string `json:"message"` Path ast.Path `json:"path,omitempty"` Locations []Location `json:"locations,omitempty"` Extensions map[string]interface{} `json:"extensions,omitempty"` Rule string `json:"-"` } func (err *Error) SetFile(file string) { if file == "" { return } if err.Extensions == nil { err.Extensions = map[string]interface{}{} } err.Extensions["file"] = file } type Location struct { Line int `json:"line,omitempty"` Column int `json:"column,omitempty"` } type List []*Error func (err *Error) Error() string { var res bytes.Buffer if err == nil { return "" } filename, _ := err.Extensions["file"].(string) if filename == "" { filename = "input" } res.WriteString(filename) if len(err.Locations) > 0 { res.WriteByte(':') res.WriteString(strconv.Itoa(err.Locations[0].Line)) } res.WriteString(": ") if ps := err.pathString(); ps != "" { res.WriteString(ps) res.WriteByte(' ') } res.WriteString(err.Message) return res.String() } func (err Error) pathString() string { return err.Path.String() } func (err Error) Unwrap() error { return err.err } func (errs List) Error() string { var buf bytes.Buffer for _, err := range errs { buf.WriteString(err.Error()) buf.WriteByte('\n') } return buf.String() } func (errs List) Is(target error) bool { for _, err := range errs { if errors.Is(err, target) { return true } } return false } func (errs List) As(target interface{}) bool { for _, err := range errs { if errors.As(err, target) { return true } } return false } func WrapPath(path ast.Path, err error) *Error { return &Error{ err: err, Message: err.Error(), Path: path, } } func Errorf(message string, args ...interface{}) *Error { return &Error{ Message: fmt.Sprintf(message, args...), } } func ErrorPathf(path ast.Path, message string, args ...interface{}) *Error { return &Error{ Message: fmt.Sprintf(message, args...), Path: path, } } func ErrorPosf(pos *ast.Position, message string, args ...interface{}) *Error { return ErrorLocf( pos.Src.Name, pos.Line, pos.Column, message, args..., ) } func ErrorLocf(file string, line int, col int, message string, args ...interface{}) *Error { var extensions map[string]interface{} if file != "" { extensions = map[string]interface{}{"file": file} } return &Error{ Message: fmt.Sprintf(message, args...), Extensions: extensions, Locations: []Location{ {Line: line, Column: col}, }, } } gqlparser-2.5.1/gqlerror/error_test.go000066400000000000000000000014231430663104200200720ustar00rootroot00000000000000package gqlerror import ( "testing" "github.com/stretchr/testify/require" "github.com/vektah/gqlparser/v2/ast" ) func TestErrorFormatting(t *testing.T) { t.Run("without filename", func(t *testing.T) { err := ErrorLocf("", 66, 2, "kabloom") require.Equal(t, `input:66: kabloom`, err.Error()) require.Equal(t, nil, err.Extensions["file"]) }) t.Run("with filename", func(t *testing.T) { err := ErrorLocf("schema.graphql", 66, 2, "kabloom") require.Equal(t, `schema.graphql:66: kabloom`, err.Error()) require.Equal(t, "schema.graphql", err.Extensions["file"]) }) t.Run("with path", func(t *testing.T) { err := ErrorPathf(ast.Path{ast.PathName("a"), ast.PathIndex(1), ast.PathName("b")}, "kabloom") require.Equal(t, `input: a[1].b kabloom`, err.Error()) }) } gqlparser-2.5.1/gqlparser.go000066400000000000000000000020541430663104200160460ustar00rootroot00000000000000package gqlparser import ( "github.com/vektah/gqlparser/v2/ast" "github.com/vektah/gqlparser/v2/gqlerror" "github.com/vektah/gqlparser/v2/parser" "github.com/vektah/gqlparser/v2/validator" _ "github.com/vektah/gqlparser/v2/validator/rules" ) func LoadSchema(str ...*ast.Source) (*ast.Schema, error) { return validator.LoadSchema(append([]*ast.Source{validator.Prelude}, str...)...) } func MustLoadSchema(str ...*ast.Source) *ast.Schema { s, err := validator.LoadSchema(append([]*ast.Source{validator.Prelude}, str...)...) if err != nil { panic(err) } return s } func LoadQuery(schema *ast.Schema, str string) (*ast.QueryDocument, gqlerror.List) { query, err := parser.ParseQuery(&ast.Source{Input: str}) if err != nil { gqlErr := err.(*gqlerror.Error) return nil, gqlerror.List{gqlErr} } errs := validator.Validate(schema, query) if errs != nil { return nil, errs } return query, nil } func MustLoadQuery(schema *ast.Schema, str string) *ast.QueryDocument { q, err := LoadQuery(schema, str) if err != nil { panic(err) } return q } gqlparser-2.5.1/lexer/000077500000000000000000000000001430663104200146355ustar00rootroot00000000000000gqlparser-2.5.1/lexer/blockstring.go000066400000000000000000000024021430663104200175030ustar00rootroot00000000000000package lexer import ( "math" "strings" ) // blockStringValue produces the value of a block string from its parsed raw value, similar to // Coffeescript's block string, Python's docstring trim or Ruby's strip_heredoc. // // This implements the GraphQL spec's BlockStringValue() static algorithm. func blockStringValue(raw string) string { lines := strings.Split(raw, "\n") commonIndent := math.MaxInt32 for _, line := range lines { indent := leadingWhitespace(line) if indent < len(line) && indent < commonIndent { commonIndent = indent if commonIndent == 0 { break } } } if commonIndent != math.MaxInt32 && len(lines) > 0 { for i := 1; i < len(lines); i++ { if len(lines[i]) < commonIndent { lines[i] = "" } else { lines[i] = lines[i][commonIndent:] } } } start := 0 end := len(lines) for start < end && leadingWhitespace(lines[start]) == math.MaxInt32 { start++ } for start < end && leadingWhitespace(lines[end-1]) == math.MaxInt32 { end-- } return strings.Join(lines[start:end], "\n") } func leadingWhitespace(str string) int { for i, r := range str { if r != ' ' && r != '\t' { return i } } // this line is made up entirely of whitespace, its leading whitespace doesnt count. return math.MaxInt32 } gqlparser-2.5.1/lexer/blockstring_test.go000066400000000000000000000022051430663104200205430ustar00rootroot00000000000000package lexer import ( "testing" "github.com/stretchr/testify/require" ) func TestBlockStringValue(t *testing.T) { t.Run("removes uniform indentation from a string", func(t *testing.T) { result := blockStringValue(` Hello, World! Yours, GraphQL.`) require.Equal(t, "Hello,\n World!\n\nYours,\n GraphQL.", result) }) t.Run("removes empty leading and trailing lines", func(t *testing.T) { result := blockStringValue(` Hello, World! Yours, GraphQL. `) require.Equal(t, "Hello,\n World!\n\nYours,\n GraphQL.", result) }) t.Run("removes blank and trailing newlines", func(t *testing.T) { result := blockStringValue(` Hello, World! Yours, GraphQL. `) require.Equal(t, "Hello,\n World!\n\nYours,\n GraphQL.", result) }) t.Run("does not alter trailing spaces", func(t *testing.T) { result := blockStringValue(` Hello, World! Yours, GraphQL. `) require.Equal(t, "Hello, \n World! \n \nYours, \n GraphQL. ", result) }) } gqlparser-2.5.1/lexer/lexer.go000066400000000000000000000262511430663104200163110ustar00rootroot00000000000000package lexer import ( "bytes" "unicode/utf8" "github.com/vektah/gqlparser/v2/ast" "github.com/vektah/gqlparser/v2/gqlerror" ) // Lexer turns graphql request and schema strings into tokens type Lexer struct { *ast.Source // An offset into the string in bytes start int // An offset into the string in runes startRunes int // An offset into the string in bytes end int // An offset into the string in runes endRunes int // the current line number line int // An offset into the string in rune lineStartRunes int } func New(src *ast.Source) Lexer { return Lexer{ Source: src, line: 1, } } // take one rune from input and advance end func (s *Lexer) peek() (rune, int) { return utf8.DecodeRuneInString(s.Input[s.end:]) } func (s *Lexer) makeToken(kind Type) (Token, error) { return s.makeValueToken(kind, s.Input[s.start:s.end]) } func (s *Lexer) makeValueToken(kind Type, value string) (Token, error) { return Token{ Kind: kind, Value: value, Pos: ast.Position{ Start: s.startRunes, End: s.endRunes, Line: s.line, Column: s.startRunes - s.lineStartRunes + 1, Src: s.Source, }, }, nil } func (s *Lexer) makeError(format string, args ...interface{}) (Token, error) { column := s.endRunes - s.lineStartRunes + 1 return Token{ Kind: Invalid, Pos: ast.Position{ Start: s.startRunes, End: s.endRunes, Line: s.line, Column: column, Src: s.Source, }, }, gqlerror.ErrorLocf(s.Source.Name, s.line, column, format, args...) } // ReadToken gets the next token from the source starting at the given position. // // This skips over whitespace and comments until it finds the next lexable // token, then lexes punctuators immediately or calls the appropriate helper // function for more complicated tokens. func (s *Lexer) ReadToken() (token Token, err error) { s.ws() s.start = s.end s.startRunes = s.endRunes if s.end >= len(s.Input) { return s.makeToken(EOF) } r := s.Input[s.start] s.end++ s.endRunes++ switch r { case '!': return s.makeValueToken(Bang, "") case '$': return s.makeValueToken(Dollar, "") case '&': return s.makeValueToken(Amp, "") case '(': return s.makeValueToken(ParenL, "") case ')': return s.makeValueToken(ParenR, "") case '.': if len(s.Input) > s.start+2 && s.Input[s.start:s.start+3] == "..." { s.end += 2 s.endRunes += 2 return s.makeValueToken(Spread, "") } case ':': return s.makeValueToken(Colon, "") case '=': return s.makeValueToken(Equals, "") case '@': return s.makeValueToken(At, "") case '[': return s.makeValueToken(BracketL, "") case ']': return s.makeValueToken(BracketR, "") case '{': return s.makeValueToken(BraceL, "") case '}': return s.makeValueToken(BraceR, "") case '|': return s.makeValueToken(Pipe, "") case '#': s.readComment() return s.ReadToken() case '_', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z': return s.readName() case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': return s.readNumber() case '"': if len(s.Input) > s.start+2 && s.Input[s.start:s.start+3] == `"""` { return s.readBlockString() } return s.readString() } s.end-- s.endRunes-- if r < 0x0020 && r != 0x0009 && r != 0x000a && r != 0x000d { return s.makeError(`Cannot contain the invalid character "\u%04d"`, r) } if r == '\'' { return s.makeError(`Unexpected single quote character ('), did you mean to use a double quote (")?`) } return s.makeError(`Cannot parse the unexpected character "%s".`, string(r)) } // ws reads from body starting at startPosition until it finds a non-whitespace // or commented character, and updates the token end to include all whitespace func (s *Lexer) ws() { for s.end < len(s.Input) { switch s.Input[s.end] { case '\t', ' ', ',': s.end++ s.endRunes++ case '\n': s.end++ s.endRunes++ s.line++ s.lineStartRunes = s.endRunes case '\r': s.end++ s.endRunes++ s.line++ s.lineStartRunes = s.endRunes // skip the following newline if its there if s.end < len(s.Input) && s.Input[s.end] == '\n' { s.end++ s.endRunes++ } // byte order mark, given ws is hot path we aren't relying on the unicode package here. case 0xef: if s.end+2 < len(s.Input) && s.Input[s.end+1] == 0xBB && s.Input[s.end+2] == 0xBF { s.end += 3 s.endRunes++ } else { return } default: return } } } // readComment from the input // // #[\u0009\u0020-\uFFFF]* func (s *Lexer) readComment() (Token, error) { for s.end < len(s.Input) { r, w := s.peek() // SourceCharacter but not LineTerminator if r > 0x001f || r == '\t' { s.end += w s.endRunes++ } else { break } } return s.makeToken(Comment) } // readNumber from the input, either a float // or an int depending on whether a decimal point appears. // // Int: -?(0|[1-9][0-9]*) // Float: -?(0|[1-9][0-9]*)(\.[0-9]+)?((E|e)(+|-)?[0-9]+)? func (s *Lexer) readNumber() (Token, error) { float := false // backup to the first digit s.end-- s.endRunes-- s.acceptByte('-') if s.acceptByte('0') { if consumed := s.acceptDigits(); consumed != 0 { s.end -= consumed s.endRunes -= consumed return s.makeError("Invalid number, unexpected digit after 0: %s.", s.describeNext()) } } else { if consumed := s.acceptDigits(); consumed == 0 { return s.makeError("Invalid number, expected digit but got: %s.", s.describeNext()) } } if s.acceptByte('.') { float = true if consumed := s.acceptDigits(); consumed == 0 { return s.makeError("Invalid number, expected digit but got: %s.", s.describeNext()) } } if s.acceptByte('e', 'E') { float = true s.acceptByte('-', '+') if consumed := s.acceptDigits(); consumed == 0 { return s.makeError("Invalid number, expected digit but got: %s.", s.describeNext()) } } if float { return s.makeToken(Float) } else { return s.makeToken(Int) } } // acceptByte if it matches any of given bytes, returning true if it found anything func (s *Lexer) acceptByte(bytes ...uint8) bool { if s.end >= len(s.Input) { return false } for _, accepted := range bytes { if s.Input[s.end] == accepted { s.end++ s.endRunes++ return true } } return false } // acceptDigits from the input, returning the number of digits it found func (s *Lexer) acceptDigits() int { consumed := 0 for s.end < len(s.Input) && s.Input[s.end] >= '0' && s.Input[s.end] <= '9' { s.end++ s.endRunes++ consumed++ } return consumed } // describeNext peeks at the input and returns a human readable string. This should will alloc // and should only be used in errors func (s *Lexer) describeNext() string { if s.end < len(s.Input) { return `"` + string(s.Input[s.end]) + `"` } return "" } // readString from the input // // "([^"\\\u000A\u000D]|(\\(u[0-9a-fA-F]{4}|["\\/bfnrt])))*" func (s *Lexer) readString() (Token, error) { inputLen := len(s.Input) // this buffer is lazily created only if there are escape characters. var buf *bytes.Buffer // skip the opening quote s.start++ s.startRunes++ for s.end < inputLen { r := s.Input[s.end] if r == '\n' || r == '\r' { break } if r < 0x0020 && r != '\t' { return s.makeError(`Invalid character within String: "\u%04d".`, r) } switch r { default: var char = rune(r) var w = 1 // skip unicode overhead if we are in the ascii range if r >= 127 { char, w = utf8.DecodeRuneInString(s.Input[s.end:]) } s.end += w s.endRunes++ if buf != nil { buf.WriteRune(char) } case '"': t, err := s.makeToken(String) // the token should not include the quotes in its value, but should cover them in its position t.Pos.Start-- t.Pos.End++ if buf != nil { t.Value = buf.String() } // skip the close quote s.end++ s.endRunes++ return t, err case '\\': if s.end+1 >= inputLen { s.end++ s.endRunes++ return s.makeError(`Invalid character escape sequence.`) } if buf == nil { buf = bytes.NewBufferString(s.Input[s.start:s.end]) } escape := s.Input[s.end+1] if escape == 'u' { if s.end+6 >= inputLen { s.end++ s.endRunes++ return s.makeError("Invalid character escape sequence: \\%s.", s.Input[s.end:]) } r, ok := unhex(s.Input[s.end+2 : s.end+6]) if !ok { s.end++ s.endRunes++ return s.makeError("Invalid character escape sequence: \\%s.", s.Input[s.end:s.end+5]) } buf.WriteRune(r) s.end += 6 s.endRunes += 6 } else { switch escape { case '"', '/', '\\': buf.WriteByte(escape) case 'b': buf.WriteByte('\b') case 'f': buf.WriteByte('\f') case 'n': buf.WriteByte('\n') case 'r': buf.WriteByte('\r') case 't': buf.WriteByte('\t') default: s.end += 1 s.endRunes += 1 return s.makeError("Invalid character escape sequence: \\%s.", string(escape)) } s.end += 2 s.endRunes += 2 } } } return s.makeError("Unterminated string.") } // readBlockString from the input // // """("?"?(\\"""|\\(?!=""")|[^"\\]))*""" func (s *Lexer) readBlockString() (Token, error) { inputLen := len(s.Input) var buf bytes.Buffer // skip the opening quote s.start += 3 s.startRunes += 3 s.end += 2 s.endRunes += 2 for s.end < inputLen { r := s.Input[s.end] // Closing triple quote (""") if r == '"' && s.end+3 <= inputLen && s.Input[s.end:s.end+3] == `"""` { t, err := s.makeValueToken(BlockString, blockStringValue(buf.String())) // the token should not include the quotes in its value, but should cover them in its position t.Pos.Start -= 3 t.Pos.End += 3 // skip the close quote s.end += 3 s.endRunes += 3 return t, err } // SourceCharacter if r < 0x0020 && r != '\t' && r != '\n' && r != '\r' { return s.makeError(`Invalid character within String: "\u%04d".`, r) } if r == '\\' && s.end+4 <= inputLen && s.Input[s.end:s.end+4] == `\"""` { buf.WriteString(`"""`) s.end += 4 s.endRunes += 4 } else if r == '\r' { if s.end+1 < inputLen && s.Input[s.end+1] == '\n' { s.end++ s.endRunes++ } buf.WriteByte('\n') s.end++ s.endRunes++ s.line++ s.lineStartRunes = s.endRunes } else { var char = rune(r) var w = 1 // skip unicode overhead if we are in the ascii range if r >= 127 { char, w = utf8.DecodeRuneInString(s.Input[s.end:]) } s.end += w s.endRunes++ buf.WriteRune(char) if r == '\n' { s.line++ s.lineStartRunes = s.endRunes } } } return s.makeError("Unterminated string.") } func unhex(b string) (v rune, ok bool) { for _, c := range b { v <<= 4 switch { case '0' <= c && c <= '9': v |= c - '0' case 'a' <= c && c <= 'f': v |= c - 'a' + 10 case 'A' <= c && c <= 'F': v |= c - 'A' + 10 default: return 0, false } } return v, true } // readName from the input // // [_A-Za-z][_0-9A-Za-z]* func (s *Lexer) readName() (Token, error) { for s.end < len(s.Input) { r, w := s.peek() if (r >= '0' && r <= '9') || (r >= 'A' && r <= 'Z') || (r >= 'a' && r <= 'z') || r == '_' { s.end += w s.endRunes++ } else { break } } return s.makeToken(Name) } gqlparser-2.5.1/lexer/lexer_test.go000066400000000000000000000014321430663104200173420ustar00rootroot00000000000000package lexer import ( "github.com/vektah/gqlparser/v2/gqlerror" "testing" "github.com/vektah/gqlparser/v2/ast" "github.com/vektah/gqlparser/v2/parser/testrunner" ) func TestLexer(t *testing.T) { testrunner.Test(t, "lexer_test.yml", func(t *testing.T, input string) testrunner.Spec { l := New(&ast.Source{Input: input, Name: "spec"}) ret := testrunner.Spec{} for { tok, err := l.ReadToken() if err != nil { ret.Error = err.(*gqlerror.Error) break } if tok.Kind == EOF { break } ret.Tokens = append(ret.Tokens, testrunner.Token{ Kind: tok.Kind.Name(), Value: tok.Value, Line: tok.Pos.Line, Column: tok.Pos.Column, Start: tok.Pos.Start, End: tok.Pos.End, Src: tok.Pos.Src.Name, }) } return ret }) } gqlparser-2.5.1/lexer/lexer_test.yml000066400000000000000000000331241430663104200175410ustar00rootroot00000000000000encoding: - name: disallows uncommon control characters input: "\u0007" error: message: 'Cannot contain the invalid character "\u0007"' locations: [{line: 1, column: 1}] - name: accepts BOM header input: "\uFEFF foo" tokens: - kind: NAME start: 2 end: 5 value: 'foo' simple tokens: - name: records line and column input: "\n \r\n \r foo\n" tokens: - kind: NAME start: 8 end: 11 line: 4 column: 3 value: 'foo' - name: skips whitespace input: "\n\n foo\n\n\n" tokens: - kind: NAME start: 6 end: 9 value: 'foo' - name: skips comments input: "\n #comment\n foo#comment\n" tokens: - kind: NAME start: 18 end: 21 value: 'foo' - name: skips commas input: ",,,foo,,," tokens: - kind: NAME start: 3 end: 6 value: 'foo' - name: errors respect whitespace input: "\n\n ?\n\n\n" error: message: 'Cannot parse the unexpected character "?".' locations: [{line: 3, column: 5}] string: | Syntax Error: Cannot parse the unexpected character "?". GraphQL request (3:5) 2: 3: ? ^ 4: - name: lex reports useful information for dashes in names input: "a-b" error: message: 'Invalid number, expected digit but got: "b".' locations: [{ line: 1, column: 3 }] tokens: - kind: Name start: 0 end: 1 value: a lexes strings: - name: basic input: '"simple"' tokens: - kind: STRING start: 0 end: 8 value: 'simple' - name: whitespace input: '" white space "' tokens: - kind: STRING start: 0 end: 15 value: ' white space ' - name: quote input: '"quote \""' tokens: - kind: STRING start: 0 end: 10 value: 'quote "' - name: escaped input: '"escaped \n\r\b\t\f"' tokens: - kind: STRING start: 0 end: 20 value: "escaped \n\r\b\t\f" - name: slashes input: '"slashes \\ \/"' tokens: - kind: STRING start: 0 end: 15 value: 'slashes \ /' - name: unicode input: '"unicode \u1234\u5678\u90AB\uCDEF"' tokens: - kind: STRING start: 0 end: 34 value: "unicode \u1234\u5678\u90AB\uCDEF" lex reports useful string errors: - name: unterminated input: '"' error: message: "Unterminated string." locations: [{ line: 1, column: 2 }] - name: no end quote input: '"no end quote' error: message: 'Unterminated string.' locations: [{ line: 1, column: 14 }] - name: single quotes input: "'single quotes'" error: message: "Unexpected single quote character ('), did you mean to use a double quote (\")?" locations: [{ line: 1, column: 1 }] - name: control characters input: "\"contains unescaped \u0007 control char\"" error: message: 'Invalid character within String: "\u0007".' locations: [{ line: 1, column: 21 }] - name: null byte input: "\"null-byte is not \u0000 end of file\"" error: message: 'Invalid character within String: "\u0000".' locations: [{ line: 1, column: 19 }] - name: unterminated newline input: "\"multi\nline\"" error: message: 'Unterminated string.' locations: [{line: 1, column: 7 }] - name: unterminated carriage return input: "\"multi\rline\"" error: message: 'Unterminated string.' locations: [{ line: 1, column: 7 }] - name: bad escape character input: '"bad \z esc"' error: message: 'Invalid character escape sequence: \z.' locations: [{ line: 1, column: 7 }] - name: hex escape sequence input: '"bad \x esc"' error: message: 'Invalid character escape sequence: \x.' locations: [{ line: 1, column: 7 }] - name: short escape sequence input: '"bad \u1 esc"' error: message: 'Invalid character escape sequence: \u1 es.' locations: [{ line: 1, column: 7 }] - name: invalid escape sequence 1 input: '"bad \u0XX1 esc"' error: message: 'Invalid character escape sequence: \u0XX1.' locations: [{ line: 1, column: 7 }] - name: invalid escape sequence 2 input: '"bad \uXXXX esc"' error: message: 'Invalid character escape sequence: \uXXXX.' locations: [{ line: 1, column: 7 }] - name: invalid escape sequence 3 input: '"bad \uFXXX esc"' error: message: 'Invalid character escape sequence: \uFXXX.' locations: [{ line: 1, column: 7 }] - name: invalid character escape sequence input: '"bad \uXXXF esc"' error: message: 'Invalid character escape sequence: \uXXXF.' locations: [{ line: 1, column: 7 }] lexes block strings: - name: simple input: '"""simple"""' tokens: - kind: BLOCK_STRING start: 0 end: 12 value: 'simple' - name: white space input: '""" white space """' tokens: - kind: BLOCK_STRING start: 0 end: 19 value: ' white space ' - name: contains quote input: '"""contains " quote"""' tokens: - kind: BLOCK_STRING start: 0 end: 22 value: 'contains " quote' - name: contains triplequote input: "\"\"\"contains \\\"\"\" triplequote\"\"\"" tokens: - kind: BLOCK_STRING start: 0 end: 31 value: 'contains """ triplequote' - name: multi line input: "\"\"\"multi\nline\"\"\"" tokens: - kind: BLOCK_STRING start: 0 end: 16 value: "multi\nline" - name: multi line normalized input: "\"\"\"multi\rline\r\nnormalized\"\"\"" tokens: - kind: BLOCK_STRING start: 0 end: 28 value: "multi\nline\nnormalized" - name: unescaped input: '"""unescaped \n\r\b\t\f\u1234"""' tokens: - kind: BLOCK_STRING start: 0 end: 32 value: 'unescaped \n\r\b\t\f\u1234' - name: slashes input: '"""slashes \\ \/"""' tokens: - kind: BLOCK_STRING start: 0 end: 19 value: 'slashes \\ \/' - name: multiple lines input: | """ spans multiple lines """ tokens: - kind: BLOCK_STRING start: 0 end: 36 value: "spans\n multiple\n lines" - name: records correct line and column after block string input: | """ some description """ foo tokens: - kind: BLOCK_STRING value: "some\ndescription" - kind: NAME start: 27 end: 30 line: 6 column: 5 value: 'foo' lex reports useful block string errors: - name: unterminated string input: '"""' error: message: "Unterminated string." locations: [{ line: 1, column: 4 }] - name: unescaped control characters input: "\"\"\"contains unescaped \u0007 control char\"\"\"" error: message: 'Invalid character within String: "\u0007".' locations: [{ line: 1, column: 23 }] - name: null byte input: "\"\"\"null-byte is not \u0000 end of file\"\"\"" error: message: 'Invalid character within String: "\u0000".' locations: [{ line: 1, column: 21 }] lexes numbers: - name: integer input: "4" tokens: - kind: INT start: 0 end: 1 value: '4' - name: float input: "4.123" tokens: - kind: FLOAT start: 0 end: 5 value: '4.123' - name: negative input: "-4" tokens: - kind: INT start: 0 end: 2 value: '-4' - name: nine input: "9" tokens: - kind: INT start: 0 end: 1 value: '9' - name: zero input: "0" tokens: - kind: INT start: 0 end: 1 value: '0' - name: negative float input: "-4.123" tokens: - kind: FLOAT start: 0 end: 6 value: '-4.123' - name: float leading zero input: "0.123" tokens: - kind: FLOAT start: 0 end: 5 value: '0.123' - name: exponent whole input: "123e4" tokens: - kind: FLOAT start: 0 end: 5 value: '123e4' - name: exponent uppercase input: "123E4" tokens: - kind: FLOAT start: 0 end: 5 value: '123E4' - name: exponent negative power input: "123e-4" tokens: - kind: FLOAT start: 0 end: 6 value: '123e-4' - name: exponent positive power input: "123e+4" tokens: - kind: FLOAT start: 0 end: 6 value: '123e+4' - name: exponent negative base input: "-1.123e4" tokens: - kind: FLOAT start: 0 end: 8 value: '-1.123e4' - name: exponent negative base upper input: "-1.123E4" tokens: - kind: FLOAT start: 0 end: 8 value: '-1.123E4' - name: exponent negative base negative power input: "-1.123e-4" tokens: - kind: FLOAT start: 0 end: 9 value: '-1.123e-4' - name: exponent negative base positive power input: "-1.123e+4" tokens: - kind: FLOAT start: 0 end: 9 value: '-1.123e+4' - name: exponent negative base large power input: "-1.123e4567" tokens: - kind: FLOAT start: 0 end: 11 value: '-1.123e4567' lex reports useful number errors: - name: zero input: "00" error: message: 'Invalid number, unexpected digit after 0: "0".' locations: [{ line: 1, column: 2 }] - name: positive input: "+1" error: message: 'Cannot parse the unexpected character "+".' locations: [{ line: 1, column: 1 }] - name: trailing dot input: "1." error: message: 'Invalid number, expected digit but got: .' locations: [{ line: 1, column: 3 }] - name: traililng dot exponent input: "1.e1" error: message: 'Invalid number, expected digit but got: "e".' locations: [{ line: 1, column: 3 }] - name: missing leading zero input: ".123" error: message: 'Cannot parse the unexpected character ".".' locations: [{ line: 1, column: 1 }] - name: characters input: "1.A" error: message: 'Invalid number, expected digit but got: "A".' locations: [{ line: 1, column: 3 }] - name: negative characters input: "-A" error: message: 'Invalid number, expected digit but got: "A".' locations: [{ line: 1, column: 2 }] - name: missing exponent input: '1.0e' error: message: 'Invalid number, expected digit but got: .' locations: [{ line: 1, column: 5 }] - name: character exponent input: "1.0eA" error: message: 'Invalid number, expected digit but got: "A".' locations: [{ line: 1, column: 5 }] lexes punctuation: - name: bang input: "!" tokens: - kind: BANG start: 0 end: 1 value: undefined - name: dollar input: "$" tokens: - kind: DOLLAR start: 0 end: 1 value: undefined - name: open paren input: "(" tokens: - kind: PAREN_L start: 0 end: 1 value: undefined - name: close paren input: ")" tokens: - kind: PAREN_R start: 0 end: 1 value: undefined - name: spread input: "..." tokens: - kind: SPREAD start: 0 end: 3 value: undefined - name: colon input: ":" tokens: - kind: COLON start: 0 end: 1 value: undefined - name: equals input: "=" tokens: - kind: EQUALS start: 0 end: 1 value: undefined - name: at input: "@" tokens: - kind: AT start: 0 end: 1 value: undefined - name: open bracket input: "[" tokens: - kind: BRACKET_L start: 0 end: 1 value: undefined - name: close bracket input: "]" tokens: - kind: BRACKET_R start: 0 end: 1 value: undefined - name: open brace input: "{" tokens: - kind: BRACE_L start: 0 end: 1 value: undefined - name: close brace input: "}" tokens: - kind: BRACE_R start: 0 end: 1 value: undefined - name: pipe input: "|" tokens: - kind: PIPE start: 0 end: 1 value: undefined lex reports useful unknown character error: - name: not a spread input: ".." error: message: 'Cannot parse the unexpected character ".".' locations: [{ line: 1, column: 1 }] - name: question mark input: "?" error: message: 'Cannot parse the unexpected character "?".' message: 'Cannot parse the unexpected character "?".' locations: [{ line: 1, column: 1 }] - name: unicode 203 input: "\u203B" error: message: 'Cannot parse the unexpected character "â".' locations: [{ line: 1, column: 1 }] - name: unicode 200 input: "\u200b" error: message: 'Cannot parse the unexpected character "â".' locations: [{ line: 1, column: 1 }] gqlparser-2.5.1/lexer/token.go000066400000000000000000000041671430663104200163140ustar00rootroot00000000000000package lexer import ( "strconv" "github.com/vektah/gqlparser/v2/ast" ) const ( Invalid Type = iota EOF Bang Dollar Amp ParenL ParenR Spread Colon Equals At BracketL BracketR BraceL BraceR Pipe Name Int Float String BlockString Comment ) func (t Type) Name() string { switch t { case Invalid: return "Invalid" case EOF: return "EOF" case Bang: return "Bang" case Dollar: return "Dollar" case Amp: return "Amp" case ParenL: return "ParenL" case ParenR: return "ParenR" case Spread: return "Spread" case Colon: return "Colon" case Equals: return "Equals" case At: return "At" case BracketL: return "BracketL" case BracketR: return "BracketR" case BraceL: return "BraceL" case BraceR: return "BraceR" case Pipe: return "Pipe" case Name: return "Name" case Int: return "Int" case Float: return "Float" case String: return "String" case BlockString: return "BlockString" case Comment: return "Comment" } return "Unknown " + strconv.Itoa(int(t)) } func (t Type) String() string { switch t { case Invalid: return "" case EOF: return "" case Bang: return "!" case Dollar: return "$" case Amp: return "&" case ParenL: return "(" case ParenR: return ")" case Spread: return "..." case Colon: return ":" case Equals: return "=" case At: return "@" case BracketL: return "[" case BracketR: return "]" case BraceL: return "{" case BraceR: return "}" case Pipe: return "|" case Name: return "Name" case Int: return "Int" case Float: return "Float" case String: return "String" case BlockString: return "BlockString" case Comment: return "Comment" } return "Unknown " + strconv.Itoa(int(t)) } // Kind represents a type of token. The types are predefined as constants. type Type int type Token struct { Kind Type // The token type. Value string // The literal value consumed. Pos ast.Position // The file and line this token was read from } func (t Token) String() string { if t.Value != "" { return t.Kind.String() + " " + strconv.Quote(t.Value) } return t.Kind.String() } gqlparser-2.5.1/parser/000077500000000000000000000000001430663104200150125ustar00rootroot00000000000000gqlparser-2.5.1/parser/parser.go000066400000000000000000000044241430663104200166410ustar00rootroot00000000000000package parser import ( "strconv" "github.com/vektah/gqlparser/v2/ast" "github.com/vektah/gqlparser/v2/gqlerror" "github.com/vektah/gqlparser/v2/lexer" ) type parser struct { lexer lexer.Lexer err error peeked bool peekToken lexer.Token peekError error prev lexer.Token } func (p *parser) peekPos() *ast.Position { if p.err != nil { return nil } peek := p.peek() return &peek.Pos } func (p *parser) peek() lexer.Token { if p.err != nil { return p.prev } if !p.peeked { p.peekToken, p.peekError = p.lexer.ReadToken() p.peeked = true } return p.peekToken } func (p *parser) error(tok lexer.Token, format string, args ...interface{}) { if p.err != nil { return } p.err = gqlerror.ErrorLocf(tok.Pos.Src.Name, tok.Pos.Line, tok.Pos.Column, format, args...) } func (p *parser) next() lexer.Token { if p.err != nil { return p.prev } if p.peeked { p.peeked = false p.prev, p.err = p.peekToken, p.peekError } else { p.prev, p.err = p.lexer.ReadToken() } return p.prev } func (p *parser) expectKeyword(value string) lexer.Token { tok := p.peek() if tok.Kind == lexer.Name && tok.Value == value { return p.next() } p.error(tok, "Expected %s, found %s", strconv.Quote(value), tok.String()) return tok } func (p *parser) expect(kind lexer.Type) lexer.Token { tok := p.peek() if tok.Kind == kind { return p.next() } p.error(tok, "Expected %s, found %s", kind, tok.Kind.String()) return tok } func (p *parser) skip(kind lexer.Type) bool { if p.err != nil { return false } tok := p.peek() if tok.Kind != kind { return false } p.next() return true } func (p *parser) unexpectedError() { p.unexpectedToken(p.peek()) } func (p *parser) unexpectedToken(tok lexer.Token) { p.error(tok, "Unexpected %s", tok.String()) } func (p *parser) many(start lexer.Type, end lexer.Type, cb func()) { hasDef := p.skip(start) if !hasDef { return } for p.peek().Kind != end && p.err == nil { cb() } p.next() } func (p *parser) some(start lexer.Type, end lexer.Type, cb func()) { hasDef := p.skip(start) if !hasDef { return } called := false for p.peek().Kind != end && p.err == nil { called = true cb() } if !called { p.error(p.peek(), "expected at least one definition, found %s", p.peek().Kind.String()) return } p.next() } gqlparser-2.5.1/parser/parser_test.go000066400000000000000000000105401430663104200176740ustar00rootroot00000000000000package parser import ( "testing" "github.com/stretchr/testify/require" "github.com/vektah/gqlparser/v2/ast" "github.com/vektah/gqlparser/v2/lexer" ) func TestParserUtils(t *testing.T) { t.Run("test lookaround", func(t *testing.T) { p := newParser("asdf 1.0 turtles") require.Equal(t, "asdf", p.peek().Value) require.Equal(t, "asdf", p.expectKeyword("asdf").Value) require.Equal(t, "asdf", p.prev.Value) require.Nil(t, p.err) require.Equal(t, "1.0", p.peek().Value) require.Equal(t, "1.0", p.peek().Value) require.Equal(t, "1.0", p.expect(lexer.Float).Value) require.Equal(t, "1.0", p.prev.Value) require.Nil(t, p.err) require.True(t, p.skip(lexer.Name)) require.Nil(t, p.err) require.Equal(t, lexer.EOF, p.peek().Kind) require.Nil(t, p.err) }) t.Run("test many", func(t *testing.T) { t.Run("can read array", func(t *testing.T) { p := newParser("[a b c d]") var arr []string p.many(lexer.BracketL, lexer.BracketR, func() { arr = append(arr, p.next().Value) }) require.Nil(t, p.err) require.Equal(t, []string{"a", "b", "c", "d"}, arr) require.Equal(t, lexer.EOF, p.peek().Kind) require.Nil(t, p.err) }) t.Run("return if open is not found", func(t *testing.T) { p := newParser("turtles are happy") p.many(lexer.BracketL, lexer.BracketR, func() { t.Error("cb should not be called") }) require.Nil(t, p.err) require.Equal(t, "turtles", p.next().Value) }) t.Run("will stop on error", func(t *testing.T) { p := newParser("[a b c d]") var arr []string p.many(lexer.BracketL, lexer.BracketR, func() { arr = append(arr, p.next().Value) if len(arr) == 2 { p.error(p.peek(), "boom") } }) require.EqualError(t, p.err, "input.graphql:1: boom") require.Equal(t, []string{"a", "b"}, arr) }) }) t.Run("test some", func(t *testing.T) { t.Run("can read array", func(t *testing.T) { p := newParser("[a b c d]") var arr []string p.some(lexer.BracketL, lexer.BracketR, func() { arr = append(arr, p.next().Value) }) require.Nil(t, p.err) require.Equal(t, []string{"a", "b", "c", "d"}, arr) require.Equal(t, lexer.EOF, p.peek().Kind) require.Nil(t, p.err) }) t.Run("can't read empty array", func(t *testing.T) { p := newParser("[]") var arr []string p.some(lexer.BracketL, lexer.BracketR, func() { arr = append(arr, p.next().Value) }) require.EqualError(t, p.err, "input.graphql:1: expected at least one definition, found ]") require.Equal(t, []string(nil), arr) require.NotEqual(t, lexer.EOF, p.peek().Kind) }) t.Run("return if open is not found", func(t *testing.T) { p := newParser("turtles are happy") p.some(lexer.BracketL, lexer.BracketR, func() { t.Error("cb should not be called") }) require.Nil(t, p.err) require.Equal(t, "turtles", p.next().Value) }) t.Run("will stop on error", func(t *testing.T) { p := newParser("[a b c d]") var arr []string p.some(lexer.BracketL, lexer.BracketR, func() { arr = append(arr, p.next().Value) if len(arr) == 2 { p.error(p.peek(), "boom") } }) require.EqualError(t, p.err, "input.graphql:1: boom") require.Equal(t, []string{"a", "b"}, arr) }) }) t.Run("test errors", func(t *testing.T) { p := newParser("foo bar") p.next() p.error(p.peek(), "test error") p.error(p.peek(), "secondary error") require.EqualError(t, p.err, "input.graphql:1: test error") require.Equal(t, "foo", p.peek().Value) require.Equal(t, "foo", p.next().Value) require.Equal(t, "foo", p.peek().Value) }) t.Run("unexpected error", func(t *testing.T) { p := newParser("1 3") p.unexpectedError() require.EqualError(t, p.err, "input.graphql:1: Unexpected Int \"1\"") }) t.Run("unexpected error", func(t *testing.T) { p := newParser("1 3") p.unexpectedToken(p.next()) require.EqualError(t, p.err, "input.graphql:1: Unexpected Int \"1\"") }) t.Run("expect error", func(t *testing.T) { p := newParser("foo bar") p.expect(lexer.Float) require.EqualError(t, p.err, "input.graphql:1: Expected Float, found Name") }) t.Run("expectKeyword error", func(t *testing.T) { p := newParser("foo bar") p.expectKeyword("baz") require.EqualError(t, p.err, "input.graphql:1: Expected \"baz\", found Name \"foo\"") }) } func newParser(input string) parser { return parser{lexer: lexer.New(&ast.Source{Input: input, Name: "input.graphql"})} } gqlparser-2.5.1/parser/query.go000066400000000000000000000165211430663104200165130ustar00rootroot00000000000000package parser import ( "github.com/vektah/gqlparser/v2/lexer" . "github.com/vektah/gqlparser/v2/ast" ) func ParseQuery(source *Source) (*QueryDocument, error) { p := parser{ lexer: lexer.New(source), } return p.parseQueryDocument(), p.err } func (p *parser) parseQueryDocument() *QueryDocument { var doc QueryDocument for p.peek().Kind != lexer.EOF { if p.err != nil { return &doc } doc.Position = p.peekPos() switch p.peek().Kind { case lexer.Name: switch p.peek().Value { case "query", "mutation", "subscription": doc.Operations = append(doc.Operations, p.parseOperationDefinition()) case "fragment": doc.Fragments = append(doc.Fragments, p.parseFragmentDefinition()) default: p.unexpectedError() } case lexer.BraceL: doc.Operations = append(doc.Operations, p.parseOperationDefinition()) default: p.unexpectedError() } } return &doc } func (p *parser) parseOperationDefinition() *OperationDefinition { if p.peek().Kind == lexer.BraceL { return &OperationDefinition{ Position: p.peekPos(), Operation: Query, SelectionSet: p.parseRequiredSelectionSet(), } } var od OperationDefinition od.Position = p.peekPos() od.Operation = p.parseOperationType() if p.peek().Kind == lexer.Name { od.Name = p.next().Value } od.VariableDefinitions = p.parseVariableDefinitions() od.Directives = p.parseDirectives(false) od.SelectionSet = p.parseRequiredSelectionSet() return &od } func (p *parser) parseOperationType() Operation { tok := p.next() switch tok.Value { case "query": return Query case "mutation": return Mutation case "subscription": return Subscription } p.unexpectedToken(tok) return "" } func (p *parser) parseVariableDefinitions() VariableDefinitionList { var defs []*VariableDefinition p.many(lexer.ParenL, lexer.ParenR, func() { defs = append(defs, p.parseVariableDefinition()) }) return defs } func (p *parser) parseVariableDefinition() *VariableDefinition { var def VariableDefinition def.Position = p.peekPos() def.Variable = p.parseVariable() p.expect(lexer.Colon) def.Type = p.parseTypeReference() if p.skip(lexer.Equals) { def.DefaultValue = p.parseValueLiteral(true) } def.Directives = p.parseDirectives(false) return &def } func (p *parser) parseVariable() string { p.expect(lexer.Dollar) return p.parseName() } func (p *parser) parseOptionalSelectionSet() SelectionSet { var selections []Selection p.some(lexer.BraceL, lexer.BraceR, func() { selections = append(selections, p.parseSelection()) }) return SelectionSet(selections) } func (p *parser) parseRequiredSelectionSet() SelectionSet { if p.peek().Kind != lexer.BraceL { p.error(p.peek(), "Expected %s, found %s", lexer.BraceL, p.peek().Kind.String()) return nil } var selections []Selection p.some(lexer.BraceL, lexer.BraceR, func() { selections = append(selections, p.parseSelection()) }) return SelectionSet(selections) } func (p *parser) parseSelection() Selection { if p.peek().Kind == lexer.Spread { return p.parseFragment() } return p.parseField() } func (p *parser) parseField() *Field { var field Field field.Position = p.peekPos() field.Alias = p.parseName() if p.skip(lexer.Colon) { field.Name = p.parseName() } else { field.Name = field.Alias } field.Arguments = p.parseArguments(false) field.Directives = p.parseDirectives(false) if p.peek().Kind == lexer.BraceL { field.SelectionSet = p.parseOptionalSelectionSet() } return &field } func (p *parser) parseArguments(isConst bool) ArgumentList { var arguments ArgumentList p.many(lexer.ParenL, lexer.ParenR, func() { arguments = append(arguments, p.parseArgument(isConst)) }) return arguments } func (p *parser) parseArgument(isConst bool) *Argument { arg := Argument{} arg.Position = p.peekPos() arg.Name = p.parseName() p.expect(lexer.Colon) arg.Value = p.parseValueLiteral(isConst) return &arg } func (p *parser) parseFragment() Selection { p.expect(lexer.Spread) if peek := p.peek(); peek.Kind == lexer.Name && peek.Value != "on" { return &FragmentSpread{ Position: p.peekPos(), Name: p.parseFragmentName(), Directives: p.parseDirectives(false), } } var def InlineFragment def.Position = p.peekPos() if p.peek().Value == "on" { p.next() // "on" def.TypeCondition = p.parseName() } def.Directives = p.parseDirectives(false) def.SelectionSet = p.parseRequiredSelectionSet() return &def } func (p *parser) parseFragmentDefinition() *FragmentDefinition { var def FragmentDefinition def.Position = p.peekPos() p.expectKeyword("fragment") def.Name = p.parseFragmentName() def.VariableDefinition = p.parseVariableDefinitions() p.expectKeyword("on") def.TypeCondition = p.parseName() def.Directives = p.parseDirectives(false) def.SelectionSet = p.parseRequiredSelectionSet() return &def } func (p *parser) parseFragmentName() string { if p.peek().Value == "on" { p.unexpectedError() return "" } return p.parseName() } func (p *parser) parseValueLiteral(isConst bool) *Value { token := p.peek() var kind ValueKind switch token.Kind { case lexer.BracketL: return p.parseList(isConst) case lexer.BraceL: return p.parseObject(isConst) case lexer.Dollar: if isConst { p.unexpectedError() return nil } return &Value{Position: &token.Pos, Raw: p.parseVariable(), Kind: Variable} case lexer.Int: kind = IntValue case lexer.Float: kind = FloatValue case lexer.String: kind = StringValue case lexer.BlockString: kind = BlockValue case lexer.Name: switch token.Value { case "true", "false": kind = BooleanValue case "null": kind = NullValue default: kind = EnumValue } default: p.unexpectedError() return nil } p.next() return &Value{Position: &token.Pos, Raw: token.Value, Kind: kind} } func (p *parser) parseList(isConst bool) *Value { var values ChildValueList pos := p.peekPos() p.many(lexer.BracketL, lexer.BracketR, func() { values = append(values, &ChildValue{Value: p.parseValueLiteral(isConst)}) }) return &Value{Children: values, Kind: ListValue, Position: pos} } func (p *parser) parseObject(isConst bool) *Value { var fields ChildValueList pos := p.peekPos() p.many(lexer.BraceL, lexer.BraceR, func() { fields = append(fields, p.parseObjectField(isConst)) }) return &Value{Children: fields, Kind: ObjectValue, Position: pos} } func (p *parser) parseObjectField(isConst bool) *ChildValue { field := ChildValue{} field.Position = p.peekPos() field.Name = p.parseName() p.expect(lexer.Colon) field.Value = p.parseValueLiteral(isConst) return &field } func (p *parser) parseDirectives(isConst bool) []*Directive { var directives []*Directive for p.peek().Kind == lexer.At { if p.err != nil { break } directives = append(directives, p.parseDirective(isConst)) } return directives } func (p *parser) parseDirective(isConst bool) *Directive { p.expect(lexer.At) return &Directive{ Position: p.peekPos(), Name: p.parseName(), Arguments: p.parseArguments(isConst), } } func (p *parser) parseTypeReference() *Type { var typ Type if p.skip(lexer.BracketL) { typ.Position = p.peekPos() typ.Elem = p.parseTypeReference() p.expect(lexer.BracketR) } else { typ.Position = p.peekPos() typ.NamedType = p.parseName() } if p.skip(lexer.Bang) { typ.NonNull = true } return &typ } func (p *parser) parseName() string { token := p.expect(lexer.Name) return token.Value } gqlparser-2.5.1/parser/query_test.go000066400000000000000000000010621430663104200175440ustar00rootroot00000000000000package parser import ( "github.com/vektah/gqlparser/v2/gqlerror" "testing" "github.com/vektah/gqlparser/v2/ast" "github.com/vektah/gqlparser/v2/parser/testrunner" ) func TestQueryDocument(t *testing.T) { testrunner.Test(t, "query_test.yml", func(t *testing.T, input string) testrunner.Spec { doc, err := ParseQuery(&ast.Source{Input: input, Name: "spec"}) if err != nil { gqlErr := err.(*gqlerror.Error) return testrunner.Spec{ Error: gqlErr, AST: ast.Dump(doc), } } return testrunner.Spec{ AST: ast.Dump(doc), } }) } gqlparser-2.5.1/parser/query_test.yml000066400000000000000000000373741430663104200177570ustar00rootroot00000000000000parser provides useful errors: - name: unclosed paren input: '{' error: message: "Expected Name, found " locations: [{line: 1, column: 2}] - name: missing on in fragment input: | { ...MissingOn } fragment MissingOn Type error: message: 'Expected "on", found Name "Type"' locations: [{ line: 2, column: 20 }] - name: missing name after alias input: '{ field: {} }' error: message: "Expected Name, found {" locations: [{ line: 1, column: 10 }] - name: not an operation input: 'notanoperation Foo { field }' error: message: 'Unexpected Name "notanoperation"' locations: [{ line: 1, column: 1 }] - name: a wild splat appears input: '...' error: message: 'Unexpected ...' locations: [{ line: 1, column: 1}] variables: - name: are allowed in args input: '{ field(complex: { a: { b: [ $var ] } }) }' - name: are not allowed in default args input: 'query Foo($x: Complex = { a: { b: [ $var ] } }) { field }' error: message: 'Unexpected $' locations: [{ line: 1, column: 37 }] - name: can have directives input: 'query ($withDirective: String @first @second, $withoutDirective: String) { f }' ast: | Operations: [OperationDefinition] - Operation: Operation("query") VariableDefinitions: [VariableDefinition] - Variable: "withDirective" Type: String Directives: [Directive] - Name: "first" - Name: "second" - Variable: "withoutDirective" Type: String SelectionSet: [Selection] - Alias: "f" Name: "f" fragments: - name: can not be named 'on' input: 'fragment on on on { on }' error: message: 'Unexpected Name "on"' locations: [{ line: 1, column: 10 }] - name: can not spread fragments called 'on' input: '{ ...on }' error: message: 'Expected Name, found }' locations: [{ line: 1, column: 9 }] encoding: - name: multibyte characters are supported input: | # This comment has a ਊ multi-byte character. { field(arg: "Has a ਊ multi-byte character.") } ast: | Operations: [OperationDefinition] - Operation: Operation("query") SelectionSet: [Selection] - Alias: "field" Name: "field" Arguments: [Argument] - Name: "arg" Value: "Has a ਊ multi-byte character." keywords are allowed anywhere a name is: - name: on input: | query on { ... a ... on on { field } } fragment a on Type { on(on: $on) @on(on: on) } - name: subscription input: | query subscription { ... subscription ... on subscription { field } } fragment subscription on Type { subscription(subscription: $subscription) @subscription(subscription: subscription) } - name: true input: | query true { ... true ... on true { field } } fragment true on Type { true(true: $true) @true(true: true) } operations: - name: anonymous mutation input: 'mutation { mutationField }' - name: named mutation input: 'mutation Foo { mutationField }' - name: anonymous subscription input: 'subscription { subscriptionField }' - name: named subscription input: 'subscription Foo { subscriptionField }' ast: - name: simple query input: | { node(id: 4) { id, name } } ast: | Operations: [OperationDefinition] - Operation: Operation("query") SelectionSet: [Selection] - Alias: "node" Name: "node" Arguments: [Argument] - Name: "id" Value: 4 SelectionSet: [Selection] - Alias: "id" Name: "id" - Alias: "name" Name: "name" - name: nameless query with no variables input: | query { node { id } } ast: | Operations: [OperationDefinition] - Operation: Operation("query") SelectionSet: [Selection] - Alias: "node" Name: "node" SelectionSet: [Selection] - Alias: "id" Name: "id" - name: fragment defined variables input: 'fragment a($v: Boolean = false) on t { f(v: $v) }' ast: | Fragments: [FragmentDefinition] - Name: "a" VariableDefinition: [VariableDefinition] - Variable: "v" Type: Boolean DefaultValue: false TypeCondition: "t" SelectionSet: [Selection] - Alias: "f" Name: "f" Arguments: [Argument] - Name: "v" Value: $v values: - name: null input: '{ f(id: null) }' ast: | Operations: [OperationDefinition] - Operation: Operation("query") SelectionSet: [Selection] - Alias: "f" Name: "f" Arguments: [Argument] - Name: "id" Value: null - name: strings input: '{ f(long: """long""", short: "short") } ' ast: | Operations: [OperationDefinition] - Operation: Operation("query") SelectionSet: [Selection] - Alias: "f" Name: "f" Arguments: [Argument] - Name: "long" Value: "long" - Name: "short" Value: "short" - name: list input: '{ f(id: [1,2]) }' ast: | Operations: [OperationDefinition] - Operation: Operation("query") SelectionSet: [Selection] - Alias: "f" Name: "f" Arguments: [Argument] - Name: "id" Value: [1,2] types: - name: common types input: 'query ($string: String, $int: Int, $arr: [Arr], $notnull: [Arr!]!) { f }' ast: | Operations: [OperationDefinition] - Operation: Operation("query") VariableDefinitions: [VariableDefinition] - Variable: "string" Type: String - Variable: "int" Type: Int - Variable: "arr" Type: [Arr] - Variable: "notnull" Type: [Arr!]! SelectionSet: [Selection] - Alias: "f" Name: "f" large queries: - name: kitchen sink input: | # Copyright (c) 2015-present, Facebook, Inc. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. query queryName($foo: ComplexType, $site: Site = MOBILE) { whoever123is: node(id: [123, 456]) { id , ... on User @defer { field2 { id , alias: field1(first:10, after:$foo,) @include(if: $foo) { id, ...frag } } } ... @skip(unless: $foo) { id } ... { id } } } mutation likeStory { like(story: 123) @defer { story { id } } } subscription StoryLikeSubscription($input: StoryLikeSubscribeInput) { storyLikeSubscribe(input: $input) { story { likers { count } likeSentence { text } } } } fragment frag on Friend { foo(size: $size, bar: $b, obj: {key: "value", block: """ block string uses \""" """}) } { unnamed(truthy: true, falsey: false, nullish: null), query } ast: | Operations: [OperationDefinition] - Operation: Operation("query") Name: "queryName" VariableDefinitions: [VariableDefinition] - Variable: "foo" Type: ComplexType - Variable: "site" Type: Site DefaultValue: MOBILE SelectionSet: [Selection] - Alias: "whoever123is" Name: "node" Arguments: [Argument] - Name: "id" Value: [123,456] SelectionSet: [Selection] - Alias: "id" Name: "id" - TypeCondition: "User" Directives: [Directive] - Name: "defer" SelectionSet: [Selection] - Alias: "field2" Name: "field2" SelectionSet: [Selection] - Alias: "id" Name: "id" - Alias: "alias" Name: "field1" Arguments: [Argument] - Name: "first" Value: 10 - Name: "after" Value: $foo Directives: [Directive] - Name: "include" Arguments: [Argument] - Name: "if" Value: $foo SelectionSet: [Selection] - Alias: "id" Name: "id" - Name: "frag" - Directives: [Directive] - Name: "skip" Arguments: [Argument] - Name: "unless" Value: $foo SelectionSet: [Selection] - Alias: "id" Name: "id" - SelectionSet: [Selection] - Alias: "id" Name: "id" - Operation: Operation("mutation") Name: "likeStory" SelectionSet: [Selection] - Alias: "like" Name: "like" Arguments: [Argument] - Name: "story" Value: 123 Directives: [Directive] - Name: "defer" SelectionSet: [Selection] - Alias: "story" Name: "story" SelectionSet: [Selection] - Alias: "id" Name: "id" - Operation: Operation("subscription") Name: "StoryLikeSubscription" VariableDefinitions: [VariableDefinition] - Variable: "input" Type: StoryLikeSubscribeInput SelectionSet: [Selection] - Alias: "storyLikeSubscribe" Name: "storyLikeSubscribe" Arguments: [Argument] - Name: "input" Value: $input SelectionSet: [Selection] - Alias: "story" Name: "story" SelectionSet: [Selection] - Alias: "likers" Name: "likers" SelectionSet: [Selection] - Alias: "count" Name: "count" - Alias: "likeSentence" Name: "likeSentence" SelectionSet: [Selection] - Alias: "text" Name: "text" - Operation: Operation("query") SelectionSet: [Selection] - Alias: "unnamed" Name: "unnamed" Arguments: [Argument] - Name: "truthy" Value: true - Name: "falsey" Value: false - Name: "nullish" Value: null - Alias: "query" Name: "query" Fragments: [FragmentDefinition] - Name: "frag" TypeCondition: "Friend" SelectionSet: [Selection] - Alias: "foo" Name: "foo" Arguments: [Argument] - Name: "size" Value: $size - Name: "bar" Value: $b - Name: "obj" Value: {key:"value",block:"block string uses \"\"\""} fuzzer: - name: 01 input: '{__typename{...}}' error: message: 'Expected {, found }' locations: [{ line: 1, column: 16 }] - name: 02 input: '{...{__typename{...{}}}}' error: message: 'expected at least one definition, found }' locations: [{ line: 1, column: 21 }] gqlparser-2.5.1/parser/schema.go000066400000000000000000000315231430663104200166050ustar00rootroot00000000000000package parser import ( . "github.com/vektah/gqlparser/v2/ast" "github.com/vektah/gqlparser/v2/lexer" ) func ParseSchema(source *Source) (*SchemaDocument, error) { p := parser{ lexer: lexer.New(source), } ast, err := p.parseSchemaDocument(), p.err if err != nil { return nil, err } for _, def := range ast.Definitions { def.BuiltIn = source.BuiltIn } for _, def := range ast.Extensions { def.BuiltIn = source.BuiltIn } return ast, nil } func ParseSchemas(inputs ...*Source) (*SchemaDocument, error) { ast := &SchemaDocument{} for _, input := range inputs { inputAst, err := ParseSchema(input) if err != nil { return nil, err } ast.Merge(inputAst) } return ast, nil } func (p *parser) parseSchemaDocument() *SchemaDocument { var doc SchemaDocument doc.Position = p.peekPos() for p.peek().Kind != lexer.EOF { if p.err != nil { return nil } var description string if p.peek().Kind == lexer.BlockString || p.peek().Kind == lexer.String { description = p.parseDescription() } if p.peek().Kind != lexer.Name { p.unexpectedError() break } switch p.peek().Value { case "scalar", "type", "interface", "union", "enum", "input": doc.Definitions = append(doc.Definitions, p.parseTypeSystemDefinition(description)) case "schema": doc.Schema = append(doc.Schema, p.parseSchemaDefinition(description)) case "directive": doc.Directives = append(doc.Directives, p.parseDirectiveDefinition(description)) case "extend": if description != "" { p.unexpectedToken(p.prev) } p.parseTypeSystemExtension(&doc) default: p.unexpectedError() return nil } } return &doc } func (p *parser) parseDescription() string { token := p.peek() if token.Kind != lexer.BlockString && token.Kind != lexer.String { return "" } return p.next().Value } func (p *parser) parseTypeSystemDefinition(description string) *Definition { tok := p.peek() if tok.Kind != lexer.Name { p.unexpectedError() return nil } switch tok.Value { case "scalar": return p.parseScalarTypeDefinition(description) case "type": return p.parseObjectTypeDefinition(description) case "interface": return p.parseInterfaceTypeDefinition(description) case "union": return p.parseUnionTypeDefinition(description) case "enum": return p.parseEnumTypeDefinition(description) case "input": return p.parseInputObjectTypeDefinition(description) default: p.unexpectedError() return nil } } func (p *parser) parseSchemaDefinition(description string) *SchemaDefinition { p.expectKeyword("schema") def := SchemaDefinition{Description: description} def.Position = p.peekPos() def.Description = description def.Directives = p.parseDirectives(true) p.some(lexer.BraceL, lexer.BraceR, func() { def.OperationTypes = append(def.OperationTypes, p.parseOperationTypeDefinition()) }) return &def } func (p *parser) parseOperationTypeDefinition() *OperationTypeDefinition { var op OperationTypeDefinition op.Position = p.peekPos() op.Operation = p.parseOperationType() p.expect(lexer.Colon) op.Type = p.parseName() return &op } func (p *parser) parseScalarTypeDefinition(description string) *Definition { p.expectKeyword("scalar") var def Definition def.Position = p.peekPos() def.Kind = Scalar def.Description = description def.Name = p.parseName() def.Directives = p.parseDirectives(true) return &def } func (p *parser) parseObjectTypeDefinition(description string) *Definition { p.expectKeyword("type") var def Definition def.Position = p.peekPos() def.Kind = Object def.Description = description def.Name = p.parseName() def.Interfaces = p.parseImplementsInterfaces() def.Directives = p.parseDirectives(true) def.Fields = p.parseFieldsDefinition() return &def } func (p *parser) parseImplementsInterfaces() []string { var types []string if p.peek().Value == "implements" { p.next() // optional leading ampersand p.skip(lexer.Amp) types = append(types, p.parseName()) for p.skip(lexer.Amp) && p.err == nil { types = append(types, p.parseName()) } } return types } func (p *parser) parseFieldsDefinition() FieldList { var defs FieldList p.some(lexer.BraceL, lexer.BraceR, func() { defs = append(defs, p.parseFieldDefinition()) }) return defs } func (p *parser) parseFieldDefinition() *FieldDefinition { var def FieldDefinition def.Position = p.peekPos() def.Description = p.parseDescription() def.Name = p.parseName() def.Arguments = p.parseArgumentDefs() p.expect(lexer.Colon) def.Type = p.parseTypeReference() def.Directives = p.parseDirectives(true) return &def } func (p *parser) parseArgumentDefs() ArgumentDefinitionList { var args ArgumentDefinitionList p.some(lexer.ParenL, lexer.ParenR, func() { args = append(args, p.parseArgumentDef()) }) return args } func (p *parser) parseArgumentDef() *ArgumentDefinition { var def ArgumentDefinition def.Position = p.peekPos() def.Description = p.parseDescription() def.Name = p.parseName() p.expect(lexer.Colon) def.Type = p.parseTypeReference() if p.skip(lexer.Equals) { def.DefaultValue = p.parseValueLiteral(true) } def.Directives = p.parseDirectives(true) return &def } func (p *parser) parseInputValueDef() *FieldDefinition { var def FieldDefinition def.Position = p.peekPos() def.Description = p.parseDescription() def.Name = p.parseName() p.expect(lexer.Colon) def.Type = p.parseTypeReference() if p.skip(lexer.Equals) { def.DefaultValue = p.parseValueLiteral(true) } def.Directives = p.parseDirectives(true) return &def } func (p *parser) parseInterfaceTypeDefinition(description string) *Definition { p.expectKeyword("interface") var def Definition def.Position = p.peekPos() def.Kind = Interface def.Description = description def.Name = p.parseName() def.Interfaces = p.parseImplementsInterfaces() def.Directives = p.parseDirectives(true) def.Fields = p.parseFieldsDefinition() return &def } func (p *parser) parseUnionTypeDefinition(description string) *Definition { p.expectKeyword("union") var def Definition def.Position = p.peekPos() def.Kind = Union def.Description = description def.Name = p.parseName() def.Directives = p.parseDirectives(true) def.Types = p.parseUnionMemberTypes() return &def } func (p *parser) parseUnionMemberTypes() []string { var types []string if p.skip(lexer.Equals) { // optional leading pipe p.skip(lexer.Pipe) types = append(types, p.parseName()) for p.skip(lexer.Pipe) && p.err == nil { types = append(types, p.parseName()) } } return types } func (p *parser) parseEnumTypeDefinition(description string) *Definition { p.expectKeyword("enum") var def Definition def.Position = p.peekPos() def.Kind = Enum def.Description = description def.Name = p.parseName() def.Directives = p.parseDirectives(true) def.EnumValues = p.parseEnumValuesDefinition() return &def } func (p *parser) parseEnumValuesDefinition() EnumValueList { var values EnumValueList p.some(lexer.BraceL, lexer.BraceR, func() { values = append(values, p.parseEnumValueDefinition()) }) return values } func (p *parser) parseEnumValueDefinition() *EnumValueDefinition { return &EnumValueDefinition{ Position: p.peekPos(), Description: p.parseDescription(), Name: p.parseName(), Directives: p.parseDirectives(true), } } func (p *parser) parseInputObjectTypeDefinition(description string) *Definition { p.expectKeyword("input") var def Definition def.Position = p.peekPos() def.Kind = InputObject def.Description = description def.Name = p.parseName() def.Directives = p.parseDirectives(true) def.Fields = p.parseInputFieldsDefinition() return &def } func (p *parser) parseInputFieldsDefinition() FieldList { var values FieldList p.some(lexer.BraceL, lexer.BraceR, func() { values = append(values, p.parseInputValueDef()) }) return values } func (p *parser) parseTypeSystemExtension(doc *SchemaDocument) { p.expectKeyword("extend") switch p.peek().Value { case "schema": doc.SchemaExtension = append(doc.SchemaExtension, p.parseSchemaExtension()) case "scalar": doc.Extensions = append(doc.Extensions, p.parseScalarTypeExtension()) case "type": doc.Extensions = append(doc.Extensions, p.parseObjectTypeExtension()) case "interface": doc.Extensions = append(doc.Extensions, p.parseInterfaceTypeExtension()) case "union": doc.Extensions = append(doc.Extensions, p.parseUnionTypeExtension()) case "enum": doc.Extensions = append(doc.Extensions, p.parseEnumTypeExtension()) case "input": doc.Extensions = append(doc.Extensions, p.parseInputObjectTypeExtension()) default: p.unexpectedError() } } func (p *parser) parseSchemaExtension() *SchemaDefinition { p.expectKeyword("schema") var def SchemaDefinition def.Position = p.peekPos() def.Directives = p.parseDirectives(true) p.some(lexer.BraceL, lexer.BraceR, func() { def.OperationTypes = append(def.OperationTypes, p.parseOperationTypeDefinition()) }) if len(def.Directives) == 0 && len(def.OperationTypes) == 0 { p.unexpectedError() } return &def } func (p *parser) parseScalarTypeExtension() *Definition { p.expectKeyword("scalar") var def Definition def.Position = p.peekPos() def.Kind = Scalar def.Name = p.parseName() def.Directives = p.parseDirectives(true) if len(def.Directives) == 0 { p.unexpectedError() } return &def } func (p *parser) parseObjectTypeExtension() *Definition { p.expectKeyword("type") var def Definition def.Position = p.peekPos() def.Kind = Object def.Name = p.parseName() def.Interfaces = p.parseImplementsInterfaces() def.Directives = p.parseDirectives(true) def.Fields = p.parseFieldsDefinition() if len(def.Interfaces) == 0 && len(def.Directives) == 0 && len(def.Fields) == 0 { p.unexpectedError() } return &def } func (p *parser) parseInterfaceTypeExtension() *Definition { p.expectKeyword("interface") var def Definition def.Position = p.peekPos() def.Kind = Interface def.Name = p.parseName() def.Directives = p.parseDirectives(true) def.Fields = p.parseFieldsDefinition() if len(def.Directives) == 0 && len(def.Fields) == 0 { p.unexpectedError() } return &def } func (p *parser) parseUnionTypeExtension() *Definition { p.expectKeyword("union") var def Definition def.Position = p.peekPos() def.Kind = Union def.Name = p.parseName() def.Directives = p.parseDirectives(true) def.Types = p.parseUnionMemberTypes() if len(def.Directives) == 0 && len(def.Types) == 0 { p.unexpectedError() } return &def } func (p *parser) parseEnumTypeExtension() *Definition { p.expectKeyword("enum") var def Definition def.Position = p.peekPos() def.Kind = Enum def.Name = p.parseName() def.Directives = p.parseDirectives(true) def.EnumValues = p.parseEnumValuesDefinition() if len(def.Directives) == 0 && len(def.EnumValues) == 0 { p.unexpectedError() } return &def } func (p *parser) parseInputObjectTypeExtension() *Definition { p.expectKeyword("input") var def Definition def.Position = p.peekPos() def.Kind = InputObject def.Name = p.parseName() def.Directives = p.parseDirectives(false) def.Fields = p.parseInputFieldsDefinition() if len(def.Directives) == 0 && len(def.Fields) == 0 { p.unexpectedError() } return &def } func (p *parser) parseDirectiveDefinition(description string) *DirectiveDefinition { p.expectKeyword("directive") p.expect(lexer.At) var def DirectiveDefinition def.Position = p.peekPos() def.Description = description def.Name = p.parseName() def.Arguments = p.parseArgumentDefs() if peek := p.peek(); peek.Kind == lexer.Name && peek.Value == "repeatable" { def.IsRepeatable = true p.skip(lexer.Name) } p.expectKeyword("on") def.Locations = p.parseDirectiveLocations() return &def } func (p *parser) parseDirectiveLocations() []DirectiveLocation { p.skip(lexer.Pipe) locations := []DirectiveLocation{p.parseDirectiveLocation()} for p.skip(lexer.Pipe) && p.err == nil { locations = append(locations, p.parseDirectiveLocation()) } return locations } func (p *parser) parseDirectiveLocation() DirectiveLocation { name := p.expect(lexer.Name) switch name.Value { case `QUERY`: return LocationQuery case `MUTATION`: return LocationMutation case `SUBSCRIPTION`: return LocationSubscription case `FIELD`: return LocationField case `FRAGMENT_DEFINITION`: return LocationFragmentDefinition case `FRAGMENT_SPREAD`: return LocationFragmentSpread case `INLINE_FRAGMENT`: return LocationInlineFragment case `VARIABLE_DEFINITION`: return LocationVariableDefinition case `SCHEMA`: return LocationSchema case `SCALAR`: return LocationScalar case `OBJECT`: return LocationObject case `FIELD_DEFINITION`: return LocationFieldDefinition case `ARGUMENT_DEFINITION`: return LocationArgumentDefinition case `INTERFACE`: return LocationInterface case `UNION`: return LocationUnion case `ENUM`: return LocationEnum case `ENUM_VALUE`: return LocationEnumValue case `INPUT_OBJECT`: return LocationInputObject case `INPUT_FIELD_DEFINITION`: return LocationInputFieldDefinition } p.unexpectedToken(name) return "" } gqlparser-2.5.1/parser/schema_test.go000066400000000000000000000022661430663104200176460ustar00rootroot00000000000000package parser import ( "github.com/stretchr/testify/assert" "github.com/vektah/gqlparser/v2/gqlerror" "testing" "github.com/vektah/gqlparser/v2/ast" "github.com/vektah/gqlparser/v2/parser/testrunner" ) func TestSchemaDocument(t *testing.T) { testrunner.Test(t, "schema_test.yml", func(t *testing.T, input string) testrunner.Spec { doc, err := ParseSchema(&ast.Source{Input: input, Name: "spec"}) if err != nil { return testrunner.Spec{ Error: err.(*gqlerror.Error), AST: ast.Dump(doc), } } return testrunner.Spec{ AST: ast.Dump(doc), } }) } func TestTypePosition(t *testing.T) { t.Run("type line number with no bang", func(t *testing.T) { schema, parseErr := ParseSchema(&ast.Source{ Input: `type query { me: User } `, }) assert.Nil(t, parseErr) assert.Equal(t, 2, schema.Definitions.ForName("query").Fields.ForName("me").Type.Position.Line) }) t.Run("type line number with bang", func(t *testing.T) { schema, parseErr := ParseSchema(&ast.Source{ Input: `type query { me: User! } `, }) assert.Nil(t, parseErr) assert.Equal(t, 2, schema.Definitions.ForName("query").Fields.ForName("me").Type.Position.Line) }) } gqlparser-2.5.1/parser/schema_test.yml000066400000000000000000000424331430663104200200420ustar00rootroot00000000000000object types: - name: simple input: | type Hello { world: String } ast: | Definitions: [Definition] - Kind: DefinitionKind("OBJECT") Name: "Hello" Fields: [FieldDefinition] - Name: "world" Type: String - name: with description input: | "Description" type Hello { world: String } ast: | Definitions: [Definition] - Kind: DefinitionKind("OBJECT") Description: "Description" Name: "Hello" Fields: [FieldDefinition] - Name: "world" Type: String - name: with block description input: | """ Description """ # Even with comments between them type Hello { world: String } ast: | Definitions: [Definition] - Kind: DefinitionKind("OBJECT") Description: "Description" Name: "Hello" Fields: [FieldDefinition] - Name: "world" Type: String - name: with field arg input: | type Hello { world(flag: Boolean): String } ast: | Definitions: [Definition] - Kind: DefinitionKind("OBJECT") Name: "Hello" Fields: [FieldDefinition] - Name: "world" Arguments: [ArgumentDefinition] - Name: "flag" Type: Boolean Type: String - name: with field arg and default value input: | type Hello { world(flag: Boolean = true): String } ast: | Definitions: [Definition] - Kind: DefinitionKind("OBJECT") Name: "Hello" Fields: [FieldDefinition] - Name: "world" Arguments: [ArgumentDefinition] - Name: "flag" DefaultValue: true Type: Boolean Type: String - name: with field list arg input: | type Hello { world(things: [String]): String } ast: | Definitions: [Definition] - Kind: DefinitionKind("OBJECT") Name: "Hello" Fields: [FieldDefinition] - Name: "world" Arguments: [ArgumentDefinition] - Name: "things" Type: [String] Type: String - name: with two args input: | type Hello { world(argOne: Boolean, argTwo: Int): String } ast: | Definitions: [Definition] - Kind: DefinitionKind("OBJECT") Name: "Hello" Fields: [FieldDefinition] - Name: "world" Arguments: [ArgumentDefinition] - Name: "argOne" Type: Boolean - Name: "argTwo" Type: Int Type: String - name: must define one or more fields input: | type Hello {} error: message: "expected at least one definition, found }" locations: [{ line: 1, column: 13 }] type extensions: - name: Object extension input: | extend type Hello { world: String } ast: | Extensions: [Definition] - Kind: DefinitionKind("OBJECT") Name: "Hello" Fields: [FieldDefinition] - Name: "world" Type: String - name: without any fields input: "extend type Hello implements Greeting" ast: | Extensions: [Definition] - Kind: DefinitionKind("OBJECT") Name: "Hello" Interfaces: [string] - "Greeting" - name: without fields twice input: | extend type Hello implements Greeting extend type Hello implements SecondGreeting ast: | Extensions: [Definition] - Kind: DefinitionKind("OBJECT") Name: "Hello" Interfaces: [string] - "Greeting" - Kind: DefinitionKind("OBJECT") Name: "Hello" Interfaces: [string] - "SecondGreeting" - name: without anything errors input: "extend type Hello" error: message: "Unexpected " locations: [{ line: 1, column: 18 }] - name: can have descriptions # hmm, this might not be spec compliant... input: | "Description" extend type Hello { world: String } error: message: 'Unexpected String "Description"' locations: [{ line: 1, column: 2 }] - name: can not have descriptions on types input: | extend "Description" type Hello { world: String } error: message: Unexpected String "Description" locations: [{ line: 1, column: 9 }] - name: all can have directives input: | extend scalar Foo @deprecated extend type Foo @deprecated extend interface Foo @deprecated extend union Foo @deprecated extend enum Foo @deprecated extend input Foo @deprecated ast: | Extensions: [Definition] - Kind: DefinitionKind("SCALAR") Name: "Foo" Directives: [Directive] - Name: "deprecated" - Kind: DefinitionKind("OBJECT") Name: "Foo" Directives: [Directive] - Name: "deprecated" - Kind: DefinitionKind("INTERFACE") Name: "Foo" Directives: [Directive] - Name: "deprecated" - Kind: DefinitionKind("UNION") Name: "Foo" Directives: [Directive] - Name: "deprecated" - Kind: DefinitionKind("ENUM") Name: "Foo" Directives: [Directive] - Name: "deprecated" - Kind: DefinitionKind("INPUT_OBJECT") Name: "Foo" Directives: [Directive] - Name: "deprecated" schema definition: - name: simple input: | schema { query: Query } ast: | Schema: [SchemaDefinition] - OperationTypes: [OperationTypeDefinition] - Operation: Operation("query") Type: "Query" schema extensions: - name: simple input: | extend schema { mutation: Mutation } ast: | SchemaExtension: [SchemaDefinition] - OperationTypes: [OperationTypeDefinition] - Operation: Operation("mutation") Type: "Mutation" - name: directive only input: "extend schema @directive" ast: | SchemaExtension: [SchemaDefinition] - Directives: [Directive] - Name: "directive" - name: without anything errors input: "extend schema" error: message: "Unexpected " locations: [{ line: 1, column: 14}] inheritance: - name: single input: "type Hello implements World { field: String }" ast: | Definitions: [Definition] - Kind: DefinitionKind("OBJECT") Name: "Hello" Interfaces: [string] - "World" Fields: [FieldDefinition] - Name: "field" Type: String - name: multi input: "type Hello implements Wo & rld { field: String }" ast: | Definitions: [Definition] - Kind: DefinitionKind("OBJECT") Name: "Hello" Interfaces: [string] - "Wo" - "rld" Fields: [FieldDefinition] - Name: "field" Type: String - name: multi with leading amp input: "type Hello implements & Wo & rld { field: String }" ast: | Definitions: [Definition] - Kind: DefinitionKind("OBJECT") Name: "Hello" Interfaces: [string] - "Wo" - "rld" Fields: [FieldDefinition] - Name: "field" Type: String enums: - name: single value input: "enum Hello { WORLD }" ast: | Definitions: [Definition] - Kind: DefinitionKind("ENUM") Name: "Hello" EnumValues: [EnumValueDefinition] - Name: "WORLD" - name: double value input: "enum Hello { WO, RLD }" ast: | Definitions: [Definition] - Kind: DefinitionKind("ENUM") Name: "Hello" EnumValues: [EnumValueDefinition] - Name: "WO" - Name: "RLD" - name: must define one or more unique enum values input: | enum Hello {} error: message: "expected at least one definition, found }" locations: [{ line: 1, column: 13 }] interface: - name: simple input: | interface Hello { world: String } ast: | Definitions: [Definition] - Kind: DefinitionKind("INTERFACE") Name: "Hello" Fields: [FieldDefinition] - Name: "world" Type: String - name: must define one or more fields input: | interface Hello {} error: message: "expected at least one definition, found }" locations: [{ line: 1, column: 18 }] - name: may define intermediate interfaces input: | interface IA { id: ID! } interface IIA implements IA { id: ID! } type A implements IIA { id: ID! } ast: | Definitions: [Definition] - Kind: DefinitionKind("INTERFACE") Name: "IA" Fields: [FieldDefinition] - Name: "id" Type: ID! - Kind: DefinitionKind("INTERFACE") Name: "IIA" Interfaces: [string] - "IA" Fields: [FieldDefinition] - Name: "id" Type: ID! - Kind: DefinitionKind("OBJECT") Name: "A" Interfaces: [string] - "IIA" Fields: [FieldDefinition] - Name: "id" Type: ID! unions: - name: simple input: "union Hello = World" ast: | Definitions: [Definition] - Kind: DefinitionKind("UNION") Name: "Hello" Types: [string] - "World" - name: with two types input: "union Hello = Wo | Rld" ast: | Definitions: [Definition] - Kind: DefinitionKind("UNION") Name: "Hello" Types: [string] - "Wo" - "Rld" - name: with leading pipe input: "union Hello = | Wo | Rld" ast: | Definitions: [Definition] - Kind: DefinitionKind("UNION") Name: "Hello" Types: [string] - "Wo" - "Rld" - name: cant be empty input: "union Hello = || Wo | Rld" error: message: "Expected Name, found |" locations: [{ line: 1, column: 16 }] - name: cant double pipe input: "union Hello = Wo || Rld" error: message: "Expected Name, found |" locations: [{ line: 1, column: 19 }] - name: cant have trailing pipe input: "union Hello = | Wo | Rld |" error: message: "Expected Name, found " locations: [{ line: 1, column: 27 }] scalar: - name: simple input: "scalar Hello" ast: | Definitions: [Definition] - Kind: DefinitionKind("SCALAR") Name: "Hello" input object: - name: simple input: | input Hello { world: String } ast: | Definitions: [Definition] - Kind: DefinitionKind("INPUT_OBJECT") Name: "Hello" Fields: [FieldDefinition] - Name: "world" Type: String - name: can not have args input: | input Hello { world(foo: Int): String } error: message: "Expected :, found (" locations: [{ line: 2, column: 8 }] - name: must define one or more input fields input: | input Hello {} error: message: "expected at least one definition, found }" locations: [{ line: 1, column: 14 }] directives: - name: simple input: directive @foo on FIELD ast: | Directives: [DirectiveDefinition] - Name: "foo" Locations: [DirectiveLocation] - DirectiveLocation("FIELD") IsRepeatable: false - name: executable input: | directive @onQuery on QUERY directive @onMutation on MUTATION directive @onSubscription on SUBSCRIPTION directive @onField on FIELD directive @onFragmentDefinition on FRAGMENT_DEFINITION directive @onFragmentSpread on FRAGMENT_SPREAD directive @onInlineFragment on INLINE_FRAGMENT directive @onVariableDefinition on VARIABLE_DEFINITION ast: | Directives: [DirectiveDefinition] - Name: "onQuery" Locations: [DirectiveLocation] - DirectiveLocation("QUERY") IsRepeatable: false - Name: "onMutation" Locations: [DirectiveLocation] - DirectiveLocation("MUTATION") IsRepeatable: false - Name: "onSubscription" Locations: [DirectiveLocation] - DirectiveLocation("SUBSCRIPTION") IsRepeatable: false - Name: "onField" Locations: [DirectiveLocation] - DirectiveLocation("FIELD") IsRepeatable: false - Name: "onFragmentDefinition" Locations: [DirectiveLocation] - DirectiveLocation("FRAGMENT_DEFINITION") IsRepeatable: false - Name: "onFragmentSpread" Locations: [DirectiveLocation] - DirectiveLocation("FRAGMENT_SPREAD") IsRepeatable: false - Name: "onInlineFragment" Locations: [DirectiveLocation] - DirectiveLocation("INLINE_FRAGMENT") IsRepeatable: false - Name: "onVariableDefinition" Locations: [DirectiveLocation] - DirectiveLocation("VARIABLE_DEFINITION") IsRepeatable: false - name: repeatable input: directive @foo repeatable on FIELD ast: | Directives: [DirectiveDefinition] - Name: "foo" Locations: [DirectiveLocation] - DirectiveLocation("FIELD") IsRepeatable: true - name: invalid location input: "directive @foo on FIELD | INCORRECT_LOCATION" error: message: 'Unexpected Name "INCORRECT_LOCATION"' locations: [{ line: 1, column: 27 }] fuzzer: - name: 1 input: "type o{d(g:[" error: message: 'Expected Name, found ' locations: [{ line: 1, column: 13 }] - name: 2 input: "\"\"\"\r" error: message: 'Unexpected ' locations: [{ line: 2, column: 1 }] gqlparser-2.5.1/parser/testrunner/000077500000000000000000000000001430663104200172235ustar00rootroot00000000000000gqlparser-2.5.1/parser/testrunner/runner.go000066400000000000000000000075641430663104200210770ustar00rootroot00000000000000package testrunner import ( "os" "strconv" "strings" "testing" "github.com/andreyvit/diff" "github.com/vektah/gqlparser/v2/gqlerror" "gopkg.in/yaml.v2" ) type Features map[string][]Spec type Spec struct { Name string Input string Error *gqlerror.Error Tokens []Token AST string } type Token struct { Kind string Value string Start int End int Line int Column int Src string } func (t Token) String() string { return t.Kind + " " + strconv.Quote(t.Value) } func Test(t *testing.T, filename string, f func(t *testing.T, input string) Spec) { b, err := os.ReadFile(filename) if err != nil { panic(err) } var tests Features err = yaml.Unmarshal(b, &tests) if err != nil { t.Errorf("unable to load %s: %s", filename, err.Error()) return } for name, specs := range tests { t.Run(name, func(t *testing.T) { for _, spec := range specs { t.Run(spec.Name, func(t *testing.T) { result := f(t, spec.Input) if spec.Error == nil { if result.Error != nil { gqlErr := err.(*gqlerror.Error) t.Errorf("unexpected error %s", gqlErr.Message) } } else if result.Error == nil { t.Errorf("expected error but got none") } else { if result.Error.Message != spec.Error.Message { t.Errorf("wrong error returned\nexpected: %s\ngot: %s", spec.Error.Message, result.Error.Message) } if result.Error.Locations[0].Column != spec.Error.Locations[0].Column || result.Error.Locations[0].Line != spec.Error.Locations[0].Line { t.Errorf( "wrong error location:\nexpected: line %d column %d\ngot: line %d column %d", spec.Error.Locations[0].Line, spec.Error.Locations[0].Column, result.Error.Locations[0].Line, result.Error.Locations[0].Column, ) } } if len(spec.Tokens) != len(result.Tokens) { var tokensStr []string for _, t := range result.Tokens { tokensStr = append(tokensStr, t.String()) } t.Errorf("token count mismatch, got: \n%s", strings.Join(tokensStr, "\n")) } else { for i, tok := range result.Tokens { expected := spec.Tokens[i] if !strings.EqualFold(strings.Replace(expected.Kind, "_", "", -1), tok.Kind) { t.Errorf("token[%d].kind should be %s, was %s", i, expected.Kind, tok.Kind) } if expected.Value != "undefined" && expected.Value != tok.Value { t.Errorf("token[%d].value incorrect\nexpected: %s\ngot: %s", i, strconv.Quote(expected.Value), strconv.Quote(tok.Value)) } if expected.Start != 0 && expected.Start != tok.Start { t.Errorf("token[%d].start should be %d, was %d", i, expected.Start, tok.Start) } if expected.End != 0 && expected.End != tok.End { t.Errorf("token[%d].end should be %d, was %d", i, expected.End, tok.End) } if expected.Line != 0 && expected.Line != tok.Line { t.Errorf("token[%d].line should be %d, was %d", i, expected.Line, tok.Line) } if expected.Column != 0 && expected.Column != tok.Column { t.Errorf("token[%d].column should be %d, was %d", i, expected.Column, tok.Column) } if tok.Src != "spec" { t.Errorf("token[%d].source.name should be spec, was %s", i, strconv.Quote(tok.Src)) } } } spec.AST = strings.TrimSpace(spec.AST) result.AST = strings.TrimSpace(result.AST) if spec.AST != "" && spec.AST != result.AST { diff := diff.LineDiff(spec.AST, result.AST) if diff != "" { t.Errorf("AST mismatch:\n%s", diff) } } if t.Failed() { t.Logf("input: %s", strconv.Quote(spec.Input)) if result.Error != nil { t.Logf("error: %s", result.Error.Message) } t.Log("tokens: ") for _, tok := range result.Tokens { t.Logf(" - %s", tok.String()) } t.Logf(" - ") } }) } }) } } gqlparser-2.5.1/readme.md000066400000000000000000000027161430663104200153030ustar00rootroot00000000000000gqlparser [![CircleCI](https://badgen.net/circleci/github/vektah/gqlparser/master)](https://circleci.com/gh/vektah/gqlparser) [![Go Report Card](https://goreportcard.com/badge/github.com/vektah/gqlparser/v2)](https://goreportcard.com/report/github.com/vektah/gqlparser/v2) [![Coverage Status](https://badgen.net/coveralls/c/github/vektah/gqlparser)](https://coveralls.io/github/vektah/gqlparser?branch=master) === This is a parser for graphql, written to mirror the graphql-js reference implementation as closely while remaining idiomatic and easy to use. spec target: June 2018 (Schema definition language, block strings as descriptions, error paths & extension) This parser is used by [gqlgen](https://github.com/99designs/gqlgen), and it should be reasonably stable. Guiding principles: - maintainability: It should be easy to stay up to date with the spec - well tested: It shouldn't need a graphql server to validate itself. Changes to this repo should be self contained. - server agnostic: It should be usable by any of the graphql server implementations, and any graphql client tooling. - idiomatic & stable api: It should follow go best practices, especially around forwards compatibility. - fast: Where it doesn't impact on the above it should be fast. Avoid unnecessary allocs in hot paths. - close to reference: Where it doesn't impact on the above, it should stay close to the [graphql/graphql-js](https://github.com/graphql/graphql-js) reference implementation. gqlparser-2.5.1/validator/000077500000000000000000000000001430663104200155035ustar00rootroot00000000000000gqlparser-2.5.1/validator/error.go000066400000000000000000000025231430663104200171650ustar00rootroot00000000000000package 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...) + "?" } } gqlparser-2.5.1/validator/imported/000077500000000000000000000000001430663104200173265ustar00rootroot00000000000000gqlparser-2.5.1/validator/imported/LICENSE000066400000000000000000000031441430663104200203350ustar00rootroot00000000000000The files in this testdata directory are derived from the graphql-js project: https://github.com/graphql/graphql-js BSD License For GraphQL software Copyright (c) 2015, Facebook, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name Facebook nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.gqlparser-2.5.1/validator/imported/babel.config.json000066400000000000000000000002141430663104200225270ustar00rootroot00000000000000{ "plugins": ["@babel/plugin-transform-typescript"], "presets": [ "@babel/preset-env", "@babel/preset-flow" ] } gqlparser-2.5.1/validator/imported/deviations.yml000066400000000000000000000027121430663104200222200ustar00rootroot00000000000000- rule: 'ExecutableDefinitionsRule/.*' skip: "These are impossible to generate because the parser is split between Query and Schema" - rule: 'FieldsOnCorrectType/Defined on implementors but not on interface' errors: - message: Cannot query field "nickname" on type "Pet". Did you mean to use an inline fragment on "Cat" or "Dog"? locations: - {line: 3, column: 9} - rule: 'KnownDirectivesRule/within schema language/with misplaced directives' skip: "When the syntax of schema is mixed in query, parser can't consume schema syntax and ignore it" - rule: 'KnownTypeNamesRule/ignores type definitions' skip: "When the syntax of schema is mixed in query, parser can't consume schema syntax and ignore it" - rule: 'OverlappingFieldsCanBeMergedRule/return types must be unambiguous/reports correctly when a non-exclusive follows an exclusive' skip: "Spec issue? scalar is not exists on SomeBox" - rule: 'ValuesOfCorrectTypeRule/.*custom scalar.*' skip: "Custom scalars are a runtime feature, maybe they dont belong in here?" - rule: 'NoDeprecatedCustomRule/.*' skip: "This rule is optional and is not part of the Validation section of the GraphQL Specification" - rule: 'NoSchemaIntrospectionCustomRule/.*' skip: "This rule is optional and is not part of the Validation section of the GraphQL Specification" - rule: 'KnownTypeNamesRule/references to standard scalars that are missing in schema' skip: "standard scalars must be exists in schema"gqlparser-2.5.1/validator/imported/export.js000066400000000000000000000101371430663104200212070ustar00rootroot00000000000000import fs from "fs"; import Module from "module"; import { testSchema } from "./graphql-js/src/validation/__tests__/harness"; import { printSchema } from "./graphql-js/src/utilities"; import yaml from "js-yaml"; let schemas = []; function registerSchema(schema) { for (let i = 0; i < schemas.length; i++) { if (schemas[i] === schema) { return i; } } schemas.push(schema); return schemas.length - 1; } function resultProxy(start, base = {}) { const funcWithPath = (path) => { const f = () => {}; f.path = path; return f; }; let handler = { get: function (obj, prop) { if (base[prop]) { return base[prop]; } return new Proxy(funcWithPath(`${obj.path}.${prop}`), handler); }, }; return new Proxy(funcWithPath(start), handler); } // replace empty lines with the normal amount of whitespace // so that yaml correctly preserves the whitespace function normalizeWs(rawString) { const lines = rawString.split(/\r\n|[\n\r]/g); let commonIndent = 1000000; for (let i = 1; i < lines.length; i++) { const line = lines[i]; if (!line.trim()) { continue; } const indent = line.search(/\S/); if (indent < commonIndent) { commonIndent = indent; } } for (let i = 1; i < lines.length; i++) { if (lines[i].length < commonIndent) { lines[i] = " ".repeat(commonIndent); } } return lines.join("\n"); } const harness = { testSchema, expectValidationErrorsWithSchema(schema, rule, queryStr) { return resultProxy("expectValidationErrorsWithSchema", { toDeepEqual(expected) { tests.push({ name: names.slice(1).join("/"), rule: rule.name.replace(/Rule$/, ""), schema: registerSchema(schema), query: normalizeWs(queryStr), errors: expected, }); }, }); }, expectValidationErrors(rule, queryStr) { return harness.expectValidationErrorsWithSchema(testSchema, rule, queryStr); }, expectSDLValidationErrors(schema, rule, sdlStr) { return resultProxy("expectSDLValidationErrors", { toDeepEqual(expected) { // ignore now... // console.warn(rule.name, sdlStr, JSON.stringify(expected, null, 2)); }, }); }, }; let tests = []; let names = []; const fakeModules = { mocha: { describe(name, f) { names.push(name); f(); names.pop(); }, it(name, f) { names.push(name); f(); names.pop(); }, }, chai: { expect(it) { const expect = { get to() { return expect; }, get have() { return expect; }, get nested() { return expect; }, equal(value) { // currently ignored, we know all we need to add an assertion here. }, property(path, value) { // currently ignored, we know all we need to add an assertion here. }, }; return expect; }, }, "./harness": harness, }; const originalLoader = Module._load; Module._load = function (request, parent, isMain) { return fakeModules[request] || originalLoader(request, parent, isMain); }; fs.readdirSync("./graphql-js/src/validation/__tests__").forEach((file) => { if (!file.endsWith("-test.ts")) { return; } if (file === "validation-test.ts") { return; } require(`./graphql-js/src/validation/__tests__/${file}`); let dump = yaml.dump(tests, { skipInvalid: true, flowLevel: 5, noRefs: true, lineWidth: 1000, }); fs.writeFileSync(`./spec/${file.replace("-test.ts", ".spec.yml")}`, dump); tests = []; }); let schemaList = schemas.map((s) => printSchema(s)); schemaList[0] += ` # injected becuase upstream spec is missing some types extend type QueryRoot { field: T f1: Type f2: Type f3: Type } type Type { a: String b: String c: String } type T { a: String b: String c: String d: String y: String deepField: T deeperField: T }`; let dump = yaml.dump(schemaList, { skipInvalid: true, flowLevel: 5, noRefs: true, lineWidth: 1000, }); fs.writeFileSync("./spec/schemas.yml", dump); gqlparser-2.5.1/validator/imported/export.sh000077500000000000000000000015331430663104200212100ustar00rootroot00000000000000#!/bin/bash REPO_DIR=./graphql-js EXPORTER_ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd "$EXPORTER_ROOT" || exit GIT_REF=origin/main if [[ -f "$EXPORTER_ROOT/graphql-js-commit.log" ]] ; then GIT_REF=$(cat "$EXPORTER_ROOT/graphql-js-commit.log") fi echo $GIT_REF if [[ -d "$REPO_DIR" ]] ; then echo "fetching graphql-js with ${GIT_REF}" cd "$REPO_DIR" || exit git fetch origin master git checkout "$GIT_REF" git reset --hard else echo "cloning graphql-js with ${GIT_REF}" git clone --no-tags --single-branch -- https://github.com/graphql/graphql-js $REPO_DIR cd "$REPO_DIR" || exit git checkout "$GIT_REF" fi git rev-parse HEAD > $EXPORTER_ROOT/graphql-js-commit.log cd "$EXPORTER_ROOT" || exit echo "installing js dependencies" npm ci echo "exporting tests" npx babel-node -x ".ts,.js" ./export.js gqlparser-2.5.1/validator/imported/graphql-js-commit.log000066400000000000000000000000511430663104200233630ustar00rootroot00000000000000f597c694339b7c488f05496806e404659f6ff955 gqlparser-2.5.1/validator/imported/package-lock.json000066400000000000000000006707211430663104200225570ustar00rootroot00000000000000{ "name": "imported", "lockfileVersion": 2, "requires": true, "packages": { "": { "dependencies": { "@babel/cli": "^7.16.8", "@babel/core": "^7.16.12", "@babel/node": "^7.16.8", "@babel/plugin-transform-typescript": "^7.16.8", "@babel/preset-env": "^7.16.11", "@babel/preset-flow": "^7.16.7", "chai": "^4.3.6", "iterall": "^1.3.0", "js-yaml": "^4.0.0" }, "devDependencies": { "prettier": "^2.5.1" } }, "node_modules/@babel/cli": { "version": "7.16.8", "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.16.8.tgz", "integrity": "sha512-FTKBbxyk5TclXOGmwYyqelqP5IF6hMxaeJskd85jbR5jBfYlwqgwAbJwnixi1ZBbTqKfFuAA95mdmUFeSRwyJA==", "dependencies": { "commander": "^4.0.1", "convert-source-map": "^1.1.0", "fs-readdir-recursive": "^1.1.0", "glob": "^7.0.0", "make-dir": "^2.1.0", "slash": "^2.0.0", "source-map": "^0.5.0" }, "bin": { "babel": "bin/babel.js", "babel-external-helpers": "bin/babel-external-helpers.js" }, "engines": { "node": ">=6.9.0" }, "optionalDependencies": { "@nicolo-ribaudo/chokidar-2": "2.1.8-no-fsevents.3", "chokidar": "^3.4.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/code-frame": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", "dependencies": { "@babel/highlight": "^7.16.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { "version": "7.16.8", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.16.8.tgz", "integrity": "sha512-m7OkX0IdKLKPpBlJtF561YJal5y/jyI5fNfWbPxh2D/nbzzGI4qRyrD8xO2jB24u7l+5I2a43scCG2IrfjC50Q==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { "version": "7.16.12", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.16.12.tgz", "integrity": "sha512-dK5PtG1uiN2ikk++5OzSYsitZKny4wOCD0nrO4TqnW4BVBTQ2NGS3NgilvT/TEyxTST7LNyWV/T4tXDoD3fOgg==", "dependencies": { "@babel/code-frame": "^7.16.7", "@babel/generator": "^7.16.8", "@babel/helper-compilation-targets": "^7.16.7", "@babel/helper-module-transforms": "^7.16.7", "@babel/helpers": "^7.16.7", "@babel/parser": "^7.16.12", "@babel/template": "^7.16.7", "@babel/traverse": "^7.16.10", "@babel/types": "^7.16.8", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.1.2", "semver": "^6.3.0", "source-map": "^0.5.0" }, "engines": { "node": ">=6.9.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/babel" } }, "node_modules/@babel/generator": { "version": "7.16.8", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.16.8.tgz", "integrity": "sha512-1ojZwE9+lOXzcWdWmO6TbUzDfqLD39CmEhN8+2cX9XkDo5yW1OpgfejfliysR2AWLpMamTiOiAp/mtroaymhpw==", "dependencies": { "@babel/types": "^7.16.8", "jsesc": "^2.5.1", "source-map": "^0.5.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-annotate-as-pure": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz", "integrity": "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==", "dependencies": { "@babel/types": "^7.16.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz", "integrity": "sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA==", "dependencies": { "@babel/helper-explode-assignable-expression": "^7.16.7", "@babel/types": "^7.16.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz", "integrity": "sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA==", "dependencies": { "@babel/compat-data": "^7.16.4", "@babel/helper-validator-option": "^7.16.7", "browserslist": "^4.17.5", "semver": "^6.3.0" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-create-class-features-plugin": { "version": "7.16.10", "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.16.10.tgz", "integrity": "sha512-wDeej0pu3WN/ffTxMNCPW5UCiOav8IcLRxSIyp/9+IF2xJUM9h/OYjg0IJLHaL6F8oU8kqMz9nc1vryXhMsgXg==", "dependencies": { "@babel/helper-annotate-as-pure": "^7.16.7", "@babel/helper-environment-visitor": "^7.16.7", "@babel/helper-function-name": "^7.16.7", "@babel/helper-member-expression-to-functions": "^7.16.7", "@babel/helper-optimise-call-expression": "^7.16.7", "@babel/helper-replace-supers": "^7.16.7", "@babel/helper-split-export-declaration": "^7.16.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-create-regexp-features-plugin": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.16.7.tgz", "integrity": "sha512-fk5A6ymfp+O5+p2yCkXAu5Kyj6v0xh0RBeNcAkYUMDvvAAoxvSKXn+Jb37t/yWFiQVDFK1ELpUTD8/aLhCPu+g==", "dependencies": { "@babel/helper-annotate-as-pure": "^7.16.7", "regexpu-core": "^4.7.1" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-define-polyfill-provider": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz", "integrity": "sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==", "dependencies": { "@babel/helper-compilation-targets": "^7.13.0", "@babel/helper-module-imports": "^7.12.13", "@babel/helper-plugin-utils": "^7.13.0", "@babel/traverse": "^7.13.0", "debug": "^4.1.1", "lodash.debounce": "^4.0.8", "resolve": "^1.14.2", "semver": "^6.1.2" }, "peerDependencies": { "@babel/core": "^7.4.0-0" } }, "node_modules/@babel/helper-environment-visitor": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz", "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==", "dependencies": { "@babel/types": "^7.16.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-explode-assignable-expression": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz", "integrity": "sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ==", "dependencies": { "@babel/types": "^7.16.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz", "integrity": "sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA==", "dependencies": { "@babel/helper-get-function-arity": "^7.16.7", "@babel/template": "^7.16.7", "@babel/types": "^7.16.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-get-function-arity": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz", "integrity": "sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==", "dependencies": { "@babel/types": "^7.16.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-hoist-variables": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", "dependencies": { "@babel/types": "^7.16.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-member-expression-to-functions": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.7.tgz", "integrity": "sha512-VtJ/65tYiU/6AbMTDwyoXGPKHgTsfRarivm+YbB5uAzKUyuPjgZSgAFeG87FCigc7KNHu2Pegh1XIT3lXjvz3Q==", "dependencies": { "@babel/types": "^7.16.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", "dependencies": { "@babel/types": "^7.16.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.16.7.tgz", "integrity": "sha512-gaqtLDxJEFCeQbYp9aLAefjhkKdjKcdh6DB7jniIGU3Pz52WAmP268zK0VgPz9hUNkMSYeH976K2/Y6yPadpng==", "dependencies": { "@babel/helper-environment-visitor": "^7.16.7", "@babel/helper-module-imports": "^7.16.7", "@babel/helper-simple-access": "^7.16.7", "@babel/helper-split-export-declaration": "^7.16.7", "@babel/helper-validator-identifier": "^7.16.7", "@babel/template": "^7.16.7", "@babel/traverse": "^7.16.7", "@babel/types": "^7.16.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-optimise-call-expression": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz", "integrity": "sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w==", "dependencies": { "@babel/types": "^7.16.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz", "integrity": "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-remap-async-to-generator": { "version": "7.16.8", "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.8.tgz", "integrity": "sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw==", "dependencies": { "@babel/helper-annotate-as-pure": "^7.16.7", "@babel/helper-wrap-function": "^7.16.8", "@babel/types": "^7.16.8" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-replace-supers": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz", "integrity": "sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw==", "dependencies": { "@babel/helper-environment-visitor": "^7.16.7", "@babel/helper-member-expression-to-functions": "^7.16.7", "@babel/helper-optimise-call-expression": "^7.16.7", "@babel/traverse": "^7.16.7", "@babel/types": "^7.16.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-simple-access": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz", "integrity": "sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g==", "dependencies": { "@babel/types": "^7.16.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { "version": "7.16.0", "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz", "integrity": "sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw==", "dependencies": { "@babel/types": "^7.16.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-split-export-declaration": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", "dependencies": { "@babel/types": "^7.16.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-wrap-function": { "version": "7.16.8", "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.16.8.tgz", "integrity": "sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw==", "dependencies": { "@babel/helper-function-name": "^7.16.7", "@babel/template": "^7.16.7", "@babel/traverse": "^7.16.8", "@babel/types": "^7.16.8" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.16.7.tgz", "integrity": "sha512-9ZDoqtfY7AuEOt3cxchfii6C7GDyyMBffktR5B2jvWv8u2+efwvpnVKXMWzNehqy68tKgAfSwfdw/lWpthS2bw==", "dependencies": { "@babel/template": "^7.16.7", "@babel/traverse": "^7.16.7", "@babel/types": "^7.16.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { "version": "7.16.10", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", "dependencies": { "@babel/helper-validator-identifier": "^7.16.7", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/node": { "version": "7.16.8", "resolved": "https://registry.npmjs.org/@babel/node/-/node-7.16.8.tgz", "integrity": "sha512-V2dopEtPUL4LD+e8UtMIZB6BbsmMsS/7E1ZAvWNINzBfi7Cf3X9MLCpzHVZT4HeeF1lQl72IRtqqVt2RUImwyA==", "dependencies": { "@babel/register": "^7.16.8", "commander": "^4.0.1", "core-js": "^3.20.2", "node-environment-flags": "^1.0.5", "regenerator-runtime": "^0.13.4", "v8flags": "^3.1.1" }, "bin": { "babel-node": "bin/babel-node.js" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/parser": { "version": "7.16.12", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.12.tgz", "integrity": "sha512-VfaV15po8RiZssrkPweyvbGVSe4x2y+aciFCgn0n0/SJMR22cwofRV1mtnJQYcSB1wUTaA/X1LnA3es66MCO5A==", "bin": { "parser": "bin/babel-parser.js" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.7.tgz", "integrity": "sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg==", "dependencies": { "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.7.tgz", "integrity": "sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw==", "dependencies": { "@babel/helper-plugin-utils": "^7.16.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", "@babel/plugin-proposal-optional-chaining": "^7.16.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.13.0" } }, "node_modules/@babel/plugin-proposal-async-generator-functions": { "version": "7.16.8", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.8.tgz", "integrity": "sha512-71YHIvMuiuqWJQkebWJtdhQTfd4Q4mF76q2IX37uZPkG9+olBxsX+rH1vkhFto4UeJZ9dPY2s+mDvhDm1u2BGQ==", "dependencies": { "@babel/helper-plugin-utils": "^7.16.7", "@babel/helper-remap-async-to-generator": "^7.16.8", "@babel/plugin-syntax-async-generators": "^7.8.4" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-proposal-class-properties": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz", "integrity": "sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww==", "dependencies": { "@babel/helper-create-class-features-plugin": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-proposal-class-static-block": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.16.7.tgz", "integrity": "sha512-dgqJJrcZoG/4CkMopzhPJjGxsIe9A8RlkQLnL/Vhhx8AA9ZuaRwGSlscSh42hazc7WSrya/IK7mTeoF0DP9tEw==", "dependencies": { "@babel/helper-create-class-features-plugin": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-class-static-block": "^7.14.5" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.12.0" } }, "node_modules/@babel/plugin-proposal-dynamic-import": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz", "integrity": "sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg==", "dependencies": { "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-dynamic-import": "^7.8.3" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-proposal-export-namespace-from": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz", "integrity": "sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA==", "dependencies": { "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-export-namespace-from": "^7.8.3" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-proposal-json-strings": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.7.tgz", "integrity": "sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ==", "dependencies": { "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-json-strings": "^7.8.3" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-proposal-logical-assignment-operators": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz", "integrity": "sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg==", "dependencies": { "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz", "integrity": "sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ==", "dependencies": { "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-proposal-numeric-separator": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz", "integrity": "sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw==", "dependencies": { "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-numeric-separator": "^7.10.4" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-proposal-object-rest-spread": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.16.7.tgz", "integrity": "sha512-3O0Y4+dw94HA86qSg9IHfyPktgR7q3gpNVAeiKQd+8jBKFaU5NQS1Yatgo4wY+UFNuLjvxcSmzcsHqrhgTyBUA==", "dependencies": { "@babel/compat-data": "^7.16.4", "@babel/helper-compilation-targets": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", "@babel/plugin-transform-parameters": "^7.16.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-proposal-optional-catch-binding": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz", "integrity": "sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA==", "dependencies": { "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-proposal-optional-chaining": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz", "integrity": "sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA==", "dependencies": { "@babel/helper-plugin-utils": "^7.16.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", "@babel/plugin-syntax-optional-chaining": "^7.8.3" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-proposal-private-methods": { "version": "7.16.11", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz", "integrity": "sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw==", "dependencies": { "@babel/helper-create-class-features-plugin": "^7.16.10", "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-proposal-private-property-in-object": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz", "integrity": "sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ==", "dependencies": { "@babel/helper-annotate-as-pure": "^7.16.7", "@babel/helper-create-class-features-plugin": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-private-property-in-object": "^7.14.5" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-proposal-unicode-property-regex": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.7.tgz", "integrity": "sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg==", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=4" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-syntax-async-generators": { "version": "7.8.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-syntax-class-properties": { "version": "7.12.13", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", "dependencies": { "@babel/helper-plugin-utils": "^7.12.13" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-syntax-class-static-block": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-syntax-dynamic-import": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-syntax-export-namespace-from": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", "dependencies": { "@babel/helper-plugin-utils": "^7.8.3" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-syntax-flow": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.16.7.tgz", "integrity": "sha512-UDo3YGQO0jH6ytzVwgSLv9i/CzMcUjbKenL67dTrAZPPv6GFAtDhe6jqnvmoKzC/7htNTohhos+onPtDMqJwaQ==", "dependencies": { "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-syntax-json-strings": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-syntax-logical-assignment-operators": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-syntax-numeric-separator": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-syntax-object-rest-spread": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-syntax-optional-catch-binding": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-syntax-optional-chaining": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-syntax-private-property-in-object": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-syntax-top-level-await": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-syntax-typescript": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.7.tgz", "integrity": "sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A==", "dependencies": { "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-arrow-functions": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz", "integrity": "sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ==", "dependencies": { "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-async-to-generator": { "version": "7.16.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.8.tgz", "integrity": "sha512-MtmUmTJQHCnyJVrScNzNlofQJ3dLFuobYn3mwOTKHnSCMtbNsqvF71GQmJfFjdrXSsAA7iysFmYWw4bXZ20hOg==", "dependencies": { "@babel/helper-module-imports": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7", "@babel/helper-remap-async-to-generator": "^7.16.8" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-block-scoped-functions": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz", "integrity": "sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg==", "dependencies": { "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-block-scoping": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz", "integrity": "sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ==", "dependencies": { "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-classes": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz", "integrity": "sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ==", "dependencies": { "@babel/helper-annotate-as-pure": "^7.16.7", "@babel/helper-environment-visitor": "^7.16.7", "@babel/helper-function-name": "^7.16.7", "@babel/helper-optimise-call-expression": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7", "@babel/helper-replace-supers": "^7.16.7", "@babel/helper-split-export-declaration": "^7.16.7", "globals": "^11.1.0" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-computed-properties": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz", "integrity": "sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw==", "dependencies": { "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-destructuring": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.16.7.tgz", "integrity": "sha512-VqAwhTHBnu5xBVDCvrvqJbtLUa++qZaWC0Fgr2mqokBlulZARGyIvZDoqbPlPaKImQ9dKAcCzbv+ul//uqu70A==", "dependencies": { "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-dotall-regex": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz", "integrity": "sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ==", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-duplicate-keys": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.7.tgz", "integrity": "sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw==", "dependencies": { "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-exponentiation-operator": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz", "integrity": "sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA==", "dependencies": { "@babel/helper-builder-binary-assignment-operator-visitor": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-flow-strip-types": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.16.7.tgz", "integrity": "sha512-mzmCq3cNsDpZZu9FADYYyfZJIOrSONmHcop2XEKPdBNMa4PDC4eEvcOvzZaCNcjKu72v0XQlA5y1g58aLRXdYg==", "dependencies": { "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-flow": "^7.16.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-for-of": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz", "integrity": "sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg==", "dependencies": { "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-function-name": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz", "integrity": "sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA==", "dependencies": { "@babel/helper-compilation-targets": "^7.16.7", "@babel/helper-function-name": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-literals": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz", "integrity": "sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ==", "dependencies": { "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-member-expression-literals": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz", "integrity": "sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw==", "dependencies": { "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-modules-amd": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.7.tgz", "integrity": "sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g==", "dependencies": { "@babel/helper-module-transforms": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7", "babel-plugin-dynamic-import-node": "^2.3.3" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-modules-commonjs": { "version": "7.16.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.8.tgz", "integrity": "sha512-oflKPvsLT2+uKQopesJt3ApiaIS2HW+hzHFcwRNtyDGieAeC/dIHZX8buJQ2J2X1rxGPy4eRcUijm3qcSPjYcA==", "dependencies": { "@babel/helper-module-transforms": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7", "@babel/helper-simple-access": "^7.16.7", "babel-plugin-dynamic-import-node": "^2.3.3" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-modules-systemjs": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.7.tgz", "integrity": "sha512-DuK5E3k+QQmnOqBR9UkusByy5WZWGRxfzV529s9nPra1GE7olmxfqO2FHobEOYSPIjPBTr4p66YDcjQnt8cBmw==", "dependencies": { "@babel/helper-hoist-variables": "^7.16.7", "@babel/helper-module-transforms": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7", "@babel/helper-validator-identifier": "^7.16.7", "babel-plugin-dynamic-import-node": "^2.3.3" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-modules-umd": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.7.tgz", "integrity": "sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ==", "dependencies": { "@babel/helper-module-transforms": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { "version": "7.16.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.8.tgz", "integrity": "sha512-j3Jw+n5PvpmhRR+mrgIh04puSANCk/T/UA3m3P1MjJkhlK906+ApHhDIqBQDdOgL/r1UYpz4GNclTXxyZrYGSw==", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.16.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "node_modules/@babel/plugin-transform-new-target": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.7.tgz", "integrity": "sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg==", "dependencies": { "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-object-super": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz", "integrity": "sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw==", "dependencies": { "@babel/helper-plugin-utils": "^7.16.7", "@babel/helper-replace-supers": "^7.16.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-parameters": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz", "integrity": "sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw==", "dependencies": { "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-property-literals": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz", "integrity": "sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw==", "dependencies": { "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-regenerator": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz", "integrity": "sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q==", "dependencies": { "regenerator-transform": "^0.14.2" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-reserved-words": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.7.tgz", "integrity": "sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg==", "dependencies": { "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-shorthand-properties": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz", "integrity": "sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg==", "dependencies": { "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-spread": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz", "integrity": "sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg==", "dependencies": { "@babel/helper-plugin-utils": "^7.16.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-sticky-regex": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz", "integrity": "sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw==", "dependencies": { "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-template-literals": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz", "integrity": "sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA==", "dependencies": { "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-typeof-symbol": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.7.tgz", "integrity": "sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ==", "dependencies": { "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-typescript": { "version": "7.16.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.16.8.tgz", "integrity": "sha512-bHdQ9k7YpBDO2d0NVfkj51DpQcvwIzIusJ7mEUaMlbZq3Kt/U47j24inXZHQ5MDiYpCs+oZiwnXyKedE8+q7AQ==", "dependencies": { "@babel/helper-create-class-features-plugin": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-typescript": "^7.16.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-unicode-escapes": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz", "integrity": "sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q==", "dependencies": { "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-unicode-regex": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz", "integrity": "sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q==", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/preset-env": { "version": "7.16.11", "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.16.11.tgz", "integrity": "sha512-qcmWG8R7ZW6WBRPZK//y+E3Cli151B20W1Rv7ln27vuPaXU/8TKms6jFdiJtF7UDTxcrb7mZd88tAeK9LjdT8g==", "dependencies": { "@babel/compat-data": "^7.16.8", "@babel/helper-compilation-targets": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7", "@babel/helper-validator-option": "^7.16.7", "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.16.7", "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.16.7", "@babel/plugin-proposal-async-generator-functions": "^7.16.8", "@babel/plugin-proposal-class-properties": "^7.16.7", "@babel/plugin-proposal-class-static-block": "^7.16.7", "@babel/plugin-proposal-dynamic-import": "^7.16.7", "@babel/plugin-proposal-export-namespace-from": "^7.16.7", "@babel/plugin-proposal-json-strings": "^7.16.7", "@babel/plugin-proposal-logical-assignment-operators": "^7.16.7", "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.7", "@babel/plugin-proposal-numeric-separator": "^7.16.7", "@babel/plugin-proposal-object-rest-spread": "^7.16.7", "@babel/plugin-proposal-optional-catch-binding": "^7.16.7", "@babel/plugin-proposal-optional-chaining": "^7.16.7", "@babel/plugin-proposal-private-methods": "^7.16.11", "@babel/plugin-proposal-private-property-in-object": "^7.16.7", "@babel/plugin-proposal-unicode-property-regex": "^7.16.7", "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-class-properties": "^7.12.13", "@babel/plugin-syntax-class-static-block": "^7.14.5", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-namespace-from": "^7.8.3", "@babel/plugin-syntax-json-strings": "^7.8.3", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", "@babel/plugin-syntax-numeric-separator": "^7.10.4", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-syntax-private-property-in-object": "^7.14.5", "@babel/plugin-syntax-top-level-await": "^7.14.5", "@babel/plugin-transform-arrow-functions": "^7.16.7", "@babel/plugin-transform-async-to-generator": "^7.16.8", "@babel/plugin-transform-block-scoped-functions": "^7.16.7", "@babel/plugin-transform-block-scoping": "^7.16.7", "@babel/plugin-transform-classes": "^7.16.7", "@babel/plugin-transform-computed-properties": "^7.16.7", "@babel/plugin-transform-destructuring": "^7.16.7", "@babel/plugin-transform-dotall-regex": "^7.16.7", "@babel/plugin-transform-duplicate-keys": "^7.16.7", "@babel/plugin-transform-exponentiation-operator": "^7.16.7", "@babel/plugin-transform-for-of": "^7.16.7", "@babel/plugin-transform-function-name": "^7.16.7", "@babel/plugin-transform-literals": "^7.16.7", "@babel/plugin-transform-member-expression-literals": "^7.16.7", "@babel/plugin-transform-modules-amd": "^7.16.7", "@babel/plugin-transform-modules-commonjs": "^7.16.8", "@babel/plugin-transform-modules-systemjs": "^7.16.7", "@babel/plugin-transform-modules-umd": "^7.16.7", "@babel/plugin-transform-named-capturing-groups-regex": "^7.16.8", "@babel/plugin-transform-new-target": "^7.16.7", "@babel/plugin-transform-object-super": "^7.16.7", "@babel/plugin-transform-parameters": "^7.16.7", "@babel/plugin-transform-property-literals": "^7.16.7", "@babel/plugin-transform-regenerator": "^7.16.7", "@babel/plugin-transform-reserved-words": "^7.16.7", "@babel/plugin-transform-shorthand-properties": "^7.16.7", "@babel/plugin-transform-spread": "^7.16.7", "@babel/plugin-transform-sticky-regex": "^7.16.7", "@babel/plugin-transform-template-literals": "^7.16.7", "@babel/plugin-transform-typeof-symbol": "^7.16.7", "@babel/plugin-transform-unicode-escapes": "^7.16.7", "@babel/plugin-transform-unicode-regex": "^7.16.7", "@babel/preset-modules": "^0.1.5", "@babel/types": "^7.16.8", "babel-plugin-polyfill-corejs2": "^0.3.0", "babel-plugin-polyfill-corejs3": "^0.5.0", "babel-plugin-polyfill-regenerator": "^0.3.0", "core-js-compat": "^3.20.2", "semver": "^6.3.0" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/preset-flow": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.16.7.tgz", "integrity": "sha512-6ceP7IyZdUYQ3wUVqyRSQXztd1YmFHWI4Xv11MIqAlE4WqxBSd/FZ61V9k+TS5Gd4mkHOtQtPp9ymRpxH4y1Ug==", "dependencies": { "@babel/helper-plugin-utils": "^7.16.7", "@babel/helper-validator-option": "^7.16.7", "@babel/plugin-transform-flow-strip-types": "^7.16.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/preset-modules": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", "@babel/plugin-transform-dotall-regex": "^7.4.4", "@babel/types": "^7.4.4", "esutils": "^2.0.2" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/register": { "version": "7.16.9", "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.16.9.tgz", "integrity": "sha512-jJ72wcghdRIlENfvALcyODhNoGE5j75cYHdC+aQMh6cU/P86tiiXTp9XYZct1UxUMo/4+BgQRyNZEGx0KWGS+g==", "dependencies": { "clone-deep": "^4.0.1", "find-cache-dir": "^2.0.0", "make-dir": "^2.1.0", "pirates": "^4.0.0", "source-map-support": "^0.5.16" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/runtime": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.7.tgz", "integrity": "sha512-9E9FJowqAsytyOY6LG+1KuueckRL+aQW+mKvXRXnuFGyRAyepJPmEo9vgMfXUA6O9u3IeEdv9MAkppFcaQwogQ==", "dependencies": { "regenerator-runtime": "^0.13.4" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/template": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", "dependencies": { "@babel/code-frame": "^7.16.7", "@babel/parser": "^7.16.7", "@babel/types": "^7.16.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { "version": "7.16.10", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.16.10.tgz", "integrity": "sha512-yzuaYXoRJBGMlBhsMJoUW7G1UmSb/eXr/JHYM/MsOJgavJibLwASijW7oXBdw3NQ6T0bW7Ty5P/VarOs9cHmqw==", "dependencies": { "@babel/code-frame": "^7.16.7", "@babel/generator": "^7.16.8", "@babel/helper-environment-visitor": "^7.16.7", "@babel/helper-function-name": "^7.16.7", "@babel/helper-hoist-variables": "^7.16.7", "@babel/helper-split-export-declaration": "^7.16.7", "@babel/parser": "^7.16.10", "@babel/types": "^7.16.8", "debug": "^4.1.0", "globals": "^11.1.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/types": { "version": "7.16.8", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.16.8.tgz", "integrity": "sha512-smN2DQc5s4M7fntyjGtyIPbRJv6wW4rU/94fmYJ7PKQuZkC0qGMHXJbg6sNGt12JmVr4k5YaptI/XtiLJBnmIg==", "dependencies": { "@babel/helper-validator-identifier": "^7.16.7", "to-fast-properties": "^2.0.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@nicolo-ribaudo/chokidar-2": { "version": "2.1.8-no-fsevents.3", "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz", "integrity": "sha512-s88O1aVtXftvp5bCPB7WnmXc5IwOZZ7YPuwNPt+GtOOXpPvad1LfbmjYv+qII7zP6RU2QGnqve27dnLycEnyEQ==", "optional": true }, "node_modules/ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dependencies": { "color-convert": "^1.9.0" }, "engines": { "node": ">=4" } }, "node_modules/anymatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", "optional": true, "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" }, "engines": { "node": ">= 8" } }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", "engines": { "node": "*" } }, "node_modules/babel-plugin-dynamic-import-node": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", "dependencies": { "object.assign": "^4.1.0" } }, "node_modules/babel-plugin-polyfill-corejs2": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz", "integrity": "sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w==", "dependencies": { "@babel/compat-data": "^7.13.11", "@babel/helper-define-polyfill-provider": "^0.3.1", "semver": "^6.1.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/babel-plugin-polyfill-corejs3": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.1.tgz", "integrity": "sha512-TihqEe4sQcb/QcPJvxe94/9RZuLQuF1+To4WqQcRvc+3J3gLCPIPgDKzGLG6zmQLfH3nn25heRuDNkS2KR4I8A==", "dependencies": { "@babel/helper-define-polyfill-provider": "^0.3.1", "core-js-compat": "^3.20.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/babel-plugin-polyfill-regenerator": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz", "integrity": "sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==", "dependencies": { "@babel/helper-define-polyfill-provider": "^0.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "optional": true, "engines": { "node": ">=8" } }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "node_modules/braces": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "optional": true, "dependencies": { "fill-range": "^7.0.1" }, "engines": { "node": ">=8" } }, "node_modules/browserslist": { "version": "4.19.1", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.1.tgz", "integrity": "sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A==", "dependencies": { "caniuse-lite": "^1.0.30001286", "electron-to-chromium": "^1.4.17", "escalade": "^3.1.1", "node-releases": "^2.0.1", "picocolors": "^1.0.0" }, "bin": { "browserslist": "cli.js" }, "engines": { "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/browserslist" } }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, "node_modules/call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", "dependencies": { "function-bind": "^1.1.1", "get-intrinsic": "^1.0.2" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/caniuse-lite": { "version": "1.0.30001304", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001304.tgz", "integrity": "sha512-bdsfZd6K6ap87AGqSHJP/s1V+U6Z5lyrcbBu3ovbCCf8cSYpwTtGrCBObMpJqwxfTbLW6YTIdbb1jEeTelcpYQ==", "funding": { "type": "opencollective", "url": "https://opencollective.com/browserslist" } }, "node_modules/chai": { "version": "4.3.6", "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", "dependencies": { "assertion-error": "^1.1.0", "check-error": "^1.0.2", "deep-eql": "^3.0.1", "get-func-name": "^2.0.0", "loupe": "^2.3.1", "pathval": "^1.1.1", "type-detect": "^4.0.5" }, "engines": { "node": ">=4" } }, "node_modules/chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" }, "engines": { "node": ">=4" } }, "node_modules/check-error": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", "engines": { "node": "*" } }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "funding": [ { "type": "individual", "url": "https://paulmillr.com/funding/" } ], "optional": true, "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "engines": { "node": ">= 8.10.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "node_modules/clone-deep": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", "dependencies": { "is-plain-object": "^2.0.4", "kind-of": "^6.0.2", "shallow-clone": "^3.0.0" }, "engines": { "node": ">=6" } }, "node_modules/color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dependencies": { "color-name": "1.1.3" } }, "node_modules/color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "node_modules/commander": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", "engines": { "node": ">= 6" } }, "node_modules/commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "node_modules/convert-source-map": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", "dependencies": { "safe-buffer": "~5.1.1" } }, "node_modules/core-js": { "version": "3.20.3", "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.20.3.tgz", "integrity": "sha512-vVl8j8ph6tRS3B8qir40H7yw7voy17xL0piAjlbBUsH7WIfzoedL/ZOr1OV9FyZQLWXsayOJyV4tnRyXR85/ag==", "hasInstallScript": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/core-js" } }, "node_modules/core-js-compat": { "version": "3.20.3", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.20.3.tgz", "integrity": "sha512-c8M5h0IkNZ+I92QhIpuSijOxGAcj3lgpsWdkCqmUTZNwidujF4r3pi6x1DCN+Vcs5qTS2XWWMfWSuCqyupX8gw==", "dependencies": { "browserslist": "^4.19.1", "semver": "7.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/core-js" } }, "node_modules/core-js-compat/node_modules/semver": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", "bin": { "semver": "bin/semver.js" } }, "node_modules/debug": { "version": "4.3.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", "dependencies": { "ms": "2.1.2" }, "engines": { "node": ">=6.0" }, "peerDependenciesMeta": { "supports-color": { "optional": true } } }, "node_modules/deep-eql": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", "dependencies": { "type-detect": "^4.0.0" }, "engines": { "node": ">=0.12" } }, "node_modules/define-properties": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", "dependencies": { "object-keys": "^1.0.12" }, "engines": { "node": ">= 0.4" } }, "node_modules/electron-to-chromium": { "version": "1.4.57", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.57.tgz", "integrity": "sha512-FNC+P5K1n6pF+M0zIK+gFCoXcJhhzDViL3DRIGy2Fv5PohuSES1JHR7T+GlwxSxlzx4yYbsuzCZvHxcBSRCIOw==" }, "node_modules/es-abstract": { "version": "1.19.1", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz", "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==", "dependencies": { "call-bind": "^1.0.2", "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", "get-intrinsic": "^1.1.1", "get-symbol-description": "^1.0.0", "has": "^1.0.3", "has-symbols": "^1.0.2", "internal-slot": "^1.0.3", "is-callable": "^1.2.4", "is-negative-zero": "^2.0.1", "is-regex": "^1.1.4", "is-shared-array-buffer": "^1.0.1", "is-string": "^1.0.7", "is-weakref": "^1.0.1", "object-inspect": "^1.11.0", "object-keys": "^1.1.1", "object.assign": "^4.1.2", "string.prototype.trimend": "^1.0.4", "string.prototype.trimstart": "^1.0.4", "unbox-primitive": "^1.0.1" }, "engines": { "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/es-to-primitive": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", "dependencies": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", "is-symbol": "^1.0.2" }, "engines": { "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "engines": { "node": ">=6" } }, "node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "engines": { "node": ">=0.8.0" } }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "engines": { "node": ">=0.10.0" } }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "optional": true, "dependencies": { "to-regex-range": "^5.0.1" }, "engines": { "node": ">=8" } }, "node_modules/find-cache-dir": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", "dependencies": { "commondir": "^1.0.1", "make-dir": "^2.0.0", "pkg-dir": "^3.0.0" }, "engines": { "node": ">=6" } }, "node_modules/find-up": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "dependencies": { "locate-path": "^3.0.0" }, "engines": { "node": ">=6" } }, "node_modules/fs-readdir-recursive": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==" }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "node_modules/fsevents": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "hasInstallScript": true, "optional": true, "os": [ "darwin" ], "engines": { "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "engines": { "node": ">=6.9.0" } }, "node_modules/get-func-name": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", "engines": { "node": "*" } }, "node_modules/get-intrinsic": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", "dependencies": { "function-bind": "^1.1.1", "has": "^1.0.3", "has-symbols": "^1.0.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/get-symbol-description": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.1.1" }, "engines": { "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.0.4", "once": "^1.3.0", "path-is-absolute": "^1.0.0" }, "engines": { "node": "*" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "optional": true, "dependencies": { "is-glob": "^4.0.1" }, "engines": { "node": ">= 6" } }, "node_modules/globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "engines": { "node": ">=4" } }, "node_modules/has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dependencies": { "function-bind": "^1.1.1" }, "engines": { "node": ">= 0.4.0" } }, "node_modules/has-bigints": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "engines": { "node": ">=4" } }, "node_modules/has-symbols": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", "engines": { "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-tostringtag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", "dependencies": { "has-symbols": "^1.0.2" }, "engines": { "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/homedir-polyfill": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", "dependencies": { "parse-passwd": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "node_modules/internal-slot": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", "dependencies": { "get-intrinsic": "^1.1.0", "has": "^1.0.3", "side-channel": "^1.0.4" }, "engines": { "node": ">= 0.4" } }, "node_modules/is-bigint": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", "dependencies": { "has-bigints": "^1.0.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "optional": true, "dependencies": { "binary-extensions": "^2.0.0" }, "engines": { "node": ">=8" } }, "node_modules/is-boolean-object": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" }, "engines": { "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-callable": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", "engines": { "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-core-module": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", "dependencies": { "has": "^1.0.3" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-date-object": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", "dependencies": { "has-tostringtag": "^1.0.0" }, "engines": { "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "optional": true, "engines": { "node": ">=0.10.0" } }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "optional": true, "dependencies": { "is-extglob": "^2.1.1" }, "engines": { "node": ">=0.10.0" } }, "node_modules/is-negative-zero": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", "engines": { "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "optional": true, "engines": { "node": ">=0.12.0" } }, "node_modules/is-number-object": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", "dependencies": { "has-tostringtag": "^1.0.0" }, "engines": { "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dependencies": { "isobject": "^3.0.1" }, "engines": { "node": ">=0.10.0" } }, "node_modules/is-regex": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" }, "engines": { "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-shared-array-buffer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz", "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-string": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", "dependencies": { "has-tostringtag": "^1.0.0" }, "engines": { "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-symbol": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", "dependencies": { "has-symbols": "^1.0.2" }, "engines": { "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-weakref": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", "dependencies": { "call-bind": "^1.0.2" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "engines": { "node": ">=0.10.0" } }, "node_modules/iterall": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.3.0.tgz", "integrity": "sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg==" }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "bin": { "jsesc": "bin/jsesc" }, "engines": { "node": ">=4" } }, "node_modules/json5": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", "dependencies": { "minimist": "^1.2.5" }, "bin": { "json5": "lib/cli.js" }, "engines": { "node": ">=6" } }, "node_modules/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "engines": { "node": ">=0.10.0" } }, "node_modules/locate-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "dependencies": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" }, "engines": { "node": ">=6" } }, "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" }, "node_modules/loupe": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.1.tgz", "integrity": "sha512-EN1D3jyVmaX4tnajVlfbREU4axL647hLec1h/PXAb8CPDMJiYitcWF2UeLVNttRqaIqQs4x+mRvXf+d+TlDrCA==", "dependencies": { "get-func-name": "^2.0.0" } }, "node_modules/make-dir": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", "dependencies": { "pify": "^4.0.1", "semver": "^5.6.0" }, "engines": { "node": ">=6" } }, "node_modules/make-dir/node_modules/semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "bin": { "semver": "bin/semver" } }, "node_modules/minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dependencies": { "brace-expansion": "^1.1.7" }, "engines": { "node": "*" } }, "node_modules/minimist": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/node-environment-flags": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz", "integrity": "sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw==", "dependencies": { "object.getownpropertydescriptors": "^2.0.3", "semver": "^5.7.0" } }, "node_modules/node-environment-flags/node_modules/semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "bin": { "semver": "bin/semver" } }, "node_modules/node-releases": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.1.tgz", "integrity": "sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==" }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "optional": true, "engines": { "node": ">=0.10.0" } }, "node_modules/object-inspect": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "engines": { "node": ">= 0.4" } }, "node_modules/object.assign": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", "dependencies": { "call-bind": "^1.0.0", "define-properties": "^1.1.3", "has-symbols": "^1.0.1", "object-keys": "^1.1.1" }, "engines": { "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/object.getownpropertydescriptors": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.3.tgz", "integrity": "sha512-VdDoCwvJI4QdC6ndjpqFmoL3/+HxffFBbcJzKi5hwLLqqx3mdbedRpfZDdK0SrOSauj8X4GzBvnDZl4vTN7dOw==", "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.3", "es-abstract": "^1.19.1" }, "engines": { "node": ">= 0.8" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dependencies": { "wrappy": "1" } }, "node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dependencies": { "p-try": "^2.0.0" }, "engines": { "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-locate": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "dependencies": { "p-limit": "^2.0.0" }, "engines": { "node": ">=6" } }, "node_modules/p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "engines": { "node": ">=6" } }, "node_modules/parse-passwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", "engines": { "node": ">=0.10.0" } }, "node_modules/path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", "engines": { "node": ">=4" } }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "engines": { "node": ">=0.10.0" } }, "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "node_modules/pathval": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", "engines": { "node": "*" } }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "optional": true, "engines": { "node": ">=8.6" }, "funding": { "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/pify": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", "engines": { "node": ">=6" } }, "node_modules/pirates": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", "engines": { "node": ">= 6" } }, "node_modules/pkg-dir": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", "dependencies": { "find-up": "^3.0.0" }, "engines": { "node": ">=6" } }, "node_modules/prettier": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz", "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==", "dev": true, "bin": { "prettier": "bin-prettier.js" }, "engines": { "node": ">=10.13.0" } }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "optional": true, "dependencies": { "picomatch": "^2.2.1" }, "engines": { "node": ">=8.10.0" } }, "node_modules/regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" }, "node_modules/regenerate-unicode-properties": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-9.0.0.tgz", "integrity": "sha512-3E12UeNSPfjrgwjkR81m5J7Aw/T55Tu7nUyZVQYCKEOs+2dkxEY+DpPtZzO4YruuiPb7NkYLVcyJC4+zCbk5pA==", "dependencies": { "regenerate": "^1.4.2" }, "engines": { "node": ">=4" } }, "node_modules/regenerator-runtime": { "version": "0.13.9", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" }, "node_modules/regenerator-transform": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", "dependencies": { "@babel/runtime": "^7.8.4" } }, "node_modules/regexpu-core": { "version": "4.8.0", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.8.0.tgz", "integrity": "sha512-1F6bYsoYiz6is+oz70NWur2Vlh9KWtswuRuzJOfeYUrfPX2o8n74AnUVaOGDbUqVGO9fNHu48/pjJO4sNVwsOg==", "dependencies": { "regenerate": "^1.4.2", "regenerate-unicode-properties": "^9.0.0", "regjsgen": "^0.5.2", "regjsparser": "^0.7.0", "unicode-match-property-ecmascript": "^2.0.0", "unicode-match-property-value-ecmascript": "^2.0.0" }, "engines": { "node": ">=4" } }, "node_modules/regjsgen": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==" }, "node_modules/regjsparser": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.7.0.tgz", "integrity": "sha512-A4pcaORqmNMDVwUjWoTzuhwMGpP+NykpfqAsEgI1FSH/EzC7lrN5TMd+kN8YCovX+jMpu8eaqXgXPCa0g8FQNQ==", "dependencies": { "jsesc": "~0.5.0" }, "bin": { "regjsparser": "bin/parser" } }, "node_modules/regjsparser/node_modules/jsesc": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", "bin": { "jsesc": "bin/jsesc" } }, "node_modules/resolve": { "version": "1.22.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", "dependencies": { "is-core-module": "^2.8.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "node_modules/semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "bin": { "semver": "bin/semver.js" } }, "node_modules/shallow-clone": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", "dependencies": { "kind-of": "^6.0.2" }, "engines": { "node": ">=8" } }, "node_modules/side-channel": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", "dependencies": { "call-bind": "^1.0.0", "get-intrinsic": "^1.0.2", "object-inspect": "^1.9.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/slash": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", "engines": { "node": ">=6" } }, "node_modules/source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "engines": { "node": ">=0.10.0" } }, "node_modules/source-map-support": { "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "node_modules/source-map-support/node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "engines": { "node": ">=0.10.0" } }, "node_modules/string.prototype.trimend": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.3" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trimstart": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.3" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dependencies": { "has-flag": "^3.0.0" }, "engines": { "node": ">=4" } }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "engines": { "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", "engines": { "node": ">=4" } }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "optional": true, "dependencies": { "is-number": "^7.0.0" }, "engines": { "node": ">=8.0" } }, "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "engines": { "node": ">=4" } }, "node_modules/unbox-primitive": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", "dependencies": { "function-bind": "^1.1.1", "has-bigints": "^1.0.1", "has-symbols": "^1.0.2", "which-boxed-primitive": "^1.0.2" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", "engines": { "node": ">=4" } }, "node_modules/unicode-match-property-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", "dependencies": { "unicode-canonical-property-names-ecmascript": "^2.0.0", "unicode-property-aliases-ecmascript": "^2.0.0" }, "engines": { "node": ">=4" } }, "node_modules/unicode-match-property-value-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz", "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==", "engines": { "node": ">=4" } }, "node_modules/unicode-property-aliases-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz", "integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==", "engines": { "node": ">=4" } }, "node_modules/v8flags": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", "dependencies": { "homedir-polyfill": "^1.0.1" }, "engines": { "node": ">= 0.10" } }, "node_modules/which-boxed-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", "dependencies": { "is-bigint": "^1.0.1", "is-boolean-object": "^1.1.0", "is-number-object": "^1.0.4", "is-string": "^1.0.5", "is-symbol": "^1.0.3" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" } }, "dependencies": { "@babel/cli": { "version": "7.16.8", "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.16.8.tgz", "integrity": "sha512-FTKBbxyk5TclXOGmwYyqelqP5IF6hMxaeJskd85jbR5jBfYlwqgwAbJwnixi1ZBbTqKfFuAA95mdmUFeSRwyJA==", "requires": { "@nicolo-ribaudo/chokidar-2": "2.1.8-no-fsevents.3", "chokidar": "^3.4.0", "commander": "^4.0.1", "convert-source-map": "^1.1.0", "fs-readdir-recursive": "^1.1.0", "glob": "^7.0.0", "make-dir": "^2.1.0", "slash": "^2.0.0", "source-map": "^0.5.0" } }, "@babel/code-frame": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", "requires": { "@babel/highlight": "^7.16.7" } }, "@babel/compat-data": { "version": "7.16.8", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.16.8.tgz", "integrity": "sha512-m7OkX0IdKLKPpBlJtF561YJal5y/jyI5fNfWbPxh2D/nbzzGI4qRyrD8xO2jB24u7l+5I2a43scCG2IrfjC50Q==" }, "@babel/core": { "version": "7.16.12", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.16.12.tgz", "integrity": "sha512-dK5PtG1uiN2ikk++5OzSYsitZKny4wOCD0nrO4TqnW4BVBTQ2NGS3NgilvT/TEyxTST7LNyWV/T4tXDoD3fOgg==", "requires": { "@babel/code-frame": "^7.16.7", "@babel/generator": "^7.16.8", "@babel/helper-compilation-targets": "^7.16.7", "@babel/helper-module-transforms": "^7.16.7", "@babel/helpers": "^7.16.7", "@babel/parser": "^7.16.12", "@babel/template": "^7.16.7", "@babel/traverse": "^7.16.10", "@babel/types": "^7.16.8", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.1.2", "semver": "^6.3.0", "source-map": "^0.5.0" } }, "@babel/generator": { "version": "7.16.8", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.16.8.tgz", "integrity": "sha512-1ojZwE9+lOXzcWdWmO6TbUzDfqLD39CmEhN8+2cX9XkDo5yW1OpgfejfliysR2AWLpMamTiOiAp/mtroaymhpw==", "requires": { "@babel/types": "^7.16.8", "jsesc": "^2.5.1", "source-map": "^0.5.0" } }, "@babel/helper-annotate-as-pure": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz", "integrity": "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==", "requires": { "@babel/types": "^7.16.7" } }, "@babel/helper-builder-binary-assignment-operator-visitor": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz", "integrity": "sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA==", "requires": { "@babel/helper-explode-assignable-expression": "^7.16.7", "@babel/types": "^7.16.7" } }, "@babel/helper-compilation-targets": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz", "integrity": "sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA==", "requires": { "@babel/compat-data": "^7.16.4", "@babel/helper-validator-option": "^7.16.7", "browserslist": "^4.17.5", "semver": "^6.3.0" } }, "@babel/helper-create-class-features-plugin": { "version": "7.16.10", "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.16.10.tgz", "integrity": "sha512-wDeej0pu3WN/ffTxMNCPW5UCiOav8IcLRxSIyp/9+IF2xJUM9h/OYjg0IJLHaL6F8oU8kqMz9nc1vryXhMsgXg==", "requires": { "@babel/helper-annotate-as-pure": "^7.16.7", "@babel/helper-environment-visitor": "^7.16.7", "@babel/helper-function-name": "^7.16.7", "@babel/helper-member-expression-to-functions": "^7.16.7", "@babel/helper-optimise-call-expression": "^7.16.7", "@babel/helper-replace-supers": "^7.16.7", "@babel/helper-split-export-declaration": "^7.16.7" } }, "@babel/helper-create-regexp-features-plugin": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.16.7.tgz", "integrity": "sha512-fk5A6ymfp+O5+p2yCkXAu5Kyj6v0xh0RBeNcAkYUMDvvAAoxvSKXn+Jb37t/yWFiQVDFK1ELpUTD8/aLhCPu+g==", "requires": { "@babel/helper-annotate-as-pure": "^7.16.7", "regexpu-core": "^4.7.1" } }, "@babel/helper-define-polyfill-provider": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz", "integrity": "sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==", "requires": { "@babel/helper-compilation-targets": "^7.13.0", "@babel/helper-module-imports": "^7.12.13", "@babel/helper-plugin-utils": "^7.13.0", "@babel/traverse": "^7.13.0", "debug": "^4.1.1", "lodash.debounce": "^4.0.8", "resolve": "^1.14.2", "semver": "^6.1.2" } }, "@babel/helper-environment-visitor": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz", "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==", "requires": { "@babel/types": "^7.16.7" } }, "@babel/helper-explode-assignable-expression": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz", "integrity": "sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ==", "requires": { "@babel/types": "^7.16.7" } }, "@babel/helper-function-name": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz", "integrity": "sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA==", "requires": { "@babel/helper-get-function-arity": "^7.16.7", "@babel/template": "^7.16.7", "@babel/types": "^7.16.7" } }, "@babel/helper-get-function-arity": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz", "integrity": "sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==", "requires": { "@babel/types": "^7.16.7" } }, "@babel/helper-hoist-variables": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", "requires": { "@babel/types": "^7.16.7" } }, "@babel/helper-member-expression-to-functions": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.7.tgz", "integrity": "sha512-VtJ/65tYiU/6AbMTDwyoXGPKHgTsfRarivm+YbB5uAzKUyuPjgZSgAFeG87FCigc7KNHu2Pegh1XIT3lXjvz3Q==", "requires": { "@babel/types": "^7.16.7" } }, "@babel/helper-module-imports": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", "requires": { "@babel/types": "^7.16.7" } }, "@babel/helper-module-transforms": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.16.7.tgz", "integrity": "sha512-gaqtLDxJEFCeQbYp9aLAefjhkKdjKcdh6DB7jniIGU3Pz52WAmP268zK0VgPz9hUNkMSYeH976K2/Y6yPadpng==", "requires": { "@babel/helper-environment-visitor": "^7.16.7", "@babel/helper-module-imports": "^7.16.7", "@babel/helper-simple-access": "^7.16.7", "@babel/helper-split-export-declaration": "^7.16.7", "@babel/helper-validator-identifier": "^7.16.7", "@babel/template": "^7.16.7", "@babel/traverse": "^7.16.7", "@babel/types": "^7.16.7" } }, "@babel/helper-optimise-call-expression": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz", "integrity": "sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w==", "requires": { "@babel/types": "^7.16.7" } }, "@babel/helper-plugin-utils": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz", "integrity": "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==" }, "@babel/helper-remap-async-to-generator": { "version": "7.16.8", "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.8.tgz", "integrity": "sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw==", "requires": { "@babel/helper-annotate-as-pure": "^7.16.7", "@babel/helper-wrap-function": "^7.16.8", "@babel/types": "^7.16.8" } }, "@babel/helper-replace-supers": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz", "integrity": "sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw==", "requires": { "@babel/helper-environment-visitor": "^7.16.7", "@babel/helper-member-expression-to-functions": "^7.16.7", "@babel/helper-optimise-call-expression": "^7.16.7", "@babel/traverse": "^7.16.7", "@babel/types": "^7.16.7" } }, "@babel/helper-simple-access": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz", "integrity": "sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g==", "requires": { "@babel/types": "^7.16.7" } }, "@babel/helper-skip-transparent-expression-wrappers": { "version": "7.16.0", "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz", "integrity": "sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw==", "requires": { "@babel/types": "^7.16.0" } }, "@babel/helper-split-export-declaration": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", "requires": { "@babel/types": "^7.16.7" } }, "@babel/helper-validator-identifier": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==" }, "@babel/helper-validator-option": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==" }, "@babel/helper-wrap-function": { "version": "7.16.8", "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.16.8.tgz", "integrity": "sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw==", "requires": { "@babel/helper-function-name": "^7.16.7", "@babel/template": "^7.16.7", "@babel/traverse": "^7.16.8", "@babel/types": "^7.16.8" } }, "@babel/helpers": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.16.7.tgz", "integrity": "sha512-9ZDoqtfY7AuEOt3cxchfii6C7GDyyMBffktR5B2jvWv8u2+efwvpnVKXMWzNehqy68tKgAfSwfdw/lWpthS2bw==", "requires": { "@babel/template": "^7.16.7", "@babel/traverse": "^7.16.7", "@babel/types": "^7.16.7" } }, "@babel/highlight": { "version": "7.16.10", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", "requires": { "@babel/helper-validator-identifier": "^7.16.7", "chalk": "^2.0.0", "js-tokens": "^4.0.0" } }, "@babel/node": { "version": "7.16.8", "resolved": "https://registry.npmjs.org/@babel/node/-/node-7.16.8.tgz", "integrity": "sha512-V2dopEtPUL4LD+e8UtMIZB6BbsmMsS/7E1ZAvWNINzBfi7Cf3X9MLCpzHVZT4HeeF1lQl72IRtqqVt2RUImwyA==", "requires": { "@babel/register": "^7.16.8", "commander": "^4.0.1", "core-js": "^3.20.2", "node-environment-flags": "^1.0.5", "regenerator-runtime": "^0.13.4", "v8flags": "^3.1.1" } }, "@babel/parser": { "version": "7.16.12", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.12.tgz", "integrity": "sha512-VfaV15po8RiZssrkPweyvbGVSe4x2y+aciFCgn0n0/SJMR22cwofRV1mtnJQYcSB1wUTaA/X1LnA3es66MCO5A==" }, "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.7.tgz", "integrity": "sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg==", "requires": { "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.7.tgz", "integrity": "sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw==", "requires": { "@babel/helper-plugin-utils": "^7.16.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", "@babel/plugin-proposal-optional-chaining": "^7.16.7" } }, "@babel/plugin-proposal-async-generator-functions": { "version": "7.16.8", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.8.tgz", "integrity": "sha512-71YHIvMuiuqWJQkebWJtdhQTfd4Q4mF76q2IX37uZPkG9+olBxsX+rH1vkhFto4UeJZ9dPY2s+mDvhDm1u2BGQ==", "requires": { "@babel/helper-plugin-utils": "^7.16.7", "@babel/helper-remap-async-to-generator": "^7.16.8", "@babel/plugin-syntax-async-generators": "^7.8.4" } }, "@babel/plugin-proposal-class-properties": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz", "integrity": "sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww==", "requires": { "@babel/helper-create-class-features-plugin": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-proposal-class-static-block": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.16.7.tgz", "integrity": "sha512-dgqJJrcZoG/4CkMopzhPJjGxsIe9A8RlkQLnL/Vhhx8AA9ZuaRwGSlscSh42hazc7WSrya/IK7mTeoF0DP9tEw==", "requires": { "@babel/helper-create-class-features-plugin": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-class-static-block": "^7.14.5" } }, "@babel/plugin-proposal-dynamic-import": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz", "integrity": "sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg==", "requires": { "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-dynamic-import": "^7.8.3" } }, "@babel/plugin-proposal-export-namespace-from": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz", "integrity": "sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA==", "requires": { "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-export-namespace-from": "^7.8.3" } }, "@babel/plugin-proposal-json-strings": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.7.tgz", "integrity": "sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ==", "requires": { "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-json-strings": "^7.8.3" } }, "@babel/plugin-proposal-logical-assignment-operators": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz", "integrity": "sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg==", "requires": { "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" } }, "@babel/plugin-proposal-nullish-coalescing-operator": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz", "integrity": "sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ==", "requires": { "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" } }, "@babel/plugin-proposal-numeric-separator": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz", "integrity": "sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw==", "requires": { "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-numeric-separator": "^7.10.4" } }, "@babel/plugin-proposal-object-rest-spread": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.16.7.tgz", "integrity": "sha512-3O0Y4+dw94HA86qSg9IHfyPktgR7q3gpNVAeiKQd+8jBKFaU5NQS1Yatgo4wY+UFNuLjvxcSmzcsHqrhgTyBUA==", "requires": { "@babel/compat-data": "^7.16.4", "@babel/helper-compilation-targets": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", "@babel/plugin-transform-parameters": "^7.16.7" } }, "@babel/plugin-proposal-optional-catch-binding": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz", "integrity": "sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA==", "requires": { "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" } }, "@babel/plugin-proposal-optional-chaining": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz", "integrity": "sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA==", "requires": { "@babel/helper-plugin-utils": "^7.16.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", "@babel/plugin-syntax-optional-chaining": "^7.8.3" } }, "@babel/plugin-proposal-private-methods": { "version": "7.16.11", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz", "integrity": "sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw==", "requires": { "@babel/helper-create-class-features-plugin": "^7.16.10", "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-proposal-private-property-in-object": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz", "integrity": "sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ==", "requires": { "@babel/helper-annotate-as-pure": "^7.16.7", "@babel/helper-create-class-features-plugin": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-private-property-in-object": "^7.14.5" } }, "@babel/plugin-proposal-unicode-property-regex": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.7.tgz", "integrity": "sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg==", "requires": { "@babel/helper-create-regexp-features-plugin": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-syntax-async-generators": { "version": "7.8.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", "requires": { "@babel/helper-plugin-utils": "^7.8.0" } }, "@babel/plugin-syntax-class-properties": { "version": "7.12.13", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", "requires": { "@babel/helper-plugin-utils": "^7.12.13" } }, "@babel/plugin-syntax-class-static-block": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", "requires": { "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-syntax-dynamic-import": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", "requires": { "@babel/helper-plugin-utils": "^7.8.0" } }, "@babel/plugin-syntax-export-namespace-from": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", "requires": { "@babel/helper-plugin-utils": "^7.8.3" } }, "@babel/plugin-syntax-flow": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.16.7.tgz", "integrity": "sha512-UDo3YGQO0jH6ytzVwgSLv9i/CzMcUjbKenL67dTrAZPPv6GFAtDhe6jqnvmoKzC/7htNTohhos+onPtDMqJwaQ==", "requires": { "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-syntax-json-strings": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", "requires": { "@babel/helper-plugin-utils": "^7.8.0" } }, "@babel/plugin-syntax-logical-assignment-operators": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", "requires": { "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-syntax-nullish-coalescing-operator": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", "requires": { "@babel/helper-plugin-utils": "^7.8.0" } }, "@babel/plugin-syntax-numeric-separator": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", "requires": { "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-syntax-object-rest-spread": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", "requires": { "@babel/helper-plugin-utils": "^7.8.0" } }, "@babel/plugin-syntax-optional-catch-binding": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", "requires": { "@babel/helper-plugin-utils": "^7.8.0" } }, "@babel/plugin-syntax-optional-chaining": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", "requires": { "@babel/helper-plugin-utils": "^7.8.0" } }, "@babel/plugin-syntax-private-property-in-object": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", "requires": { "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-syntax-top-level-await": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", "requires": { "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/plugin-syntax-typescript": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.7.tgz", "integrity": "sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A==", "requires": { "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-arrow-functions": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz", "integrity": "sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ==", "requires": { "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-async-to-generator": { "version": "7.16.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.8.tgz", "integrity": "sha512-MtmUmTJQHCnyJVrScNzNlofQJ3dLFuobYn3mwOTKHnSCMtbNsqvF71GQmJfFjdrXSsAA7iysFmYWw4bXZ20hOg==", "requires": { "@babel/helper-module-imports": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7", "@babel/helper-remap-async-to-generator": "^7.16.8" } }, "@babel/plugin-transform-block-scoped-functions": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz", "integrity": "sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg==", "requires": { "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-block-scoping": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz", "integrity": "sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ==", "requires": { "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-classes": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz", "integrity": "sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ==", "requires": { "@babel/helper-annotate-as-pure": "^7.16.7", "@babel/helper-environment-visitor": "^7.16.7", "@babel/helper-function-name": "^7.16.7", "@babel/helper-optimise-call-expression": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7", "@babel/helper-replace-supers": "^7.16.7", "@babel/helper-split-export-declaration": "^7.16.7", "globals": "^11.1.0" } }, "@babel/plugin-transform-computed-properties": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz", "integrity": "sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw==", "requires": { "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-destructuring": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.16.7.tgz", "integrity": "sha512-VqAwhTHBnu5xBVDCvrvqJbtLUa++qZaWC0Fgr2mqokBlulZARGyIvZDoqbPlPaKImQ9dKAcCzbv+ul//uqu70A==", "requires": { "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-dotall-regex": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz", "integrity": "sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ==", "requires": { "@babel/helper-create-regexp-features-plugin": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-duplicate-keys": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.7.tgz", "integrity": "sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw==", "requires": { "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-exponentiation-operator": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz", "integrity": "sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA==", "requires": { "@babel/helper-builder-binary-assignment-operator-visitor": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-flow-strip-types": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.16.7.tgz", "integrity": "sha512-mzmCq3cNsDpZZu9FADYYyfZJIOrSONmHcop2XEKPdBNMa4PDC4eEvcOvzZaCNcjKu72v0XQlA5y1g58aLRXdYg==", "requires": { "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-flow": "^7.16.7" } }, "@babel/plugin-transform-for-of": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz", "integrity": "sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg==", "requires": { "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-function-name": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz", "integrity": "sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA==", "requires": { "@babel/helper-compilation-targets": "^7.16.7", "@babel/helper-function-name": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-literals": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz", "integrity": "sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ==", "requires": { "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-member-expression-literals": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz", "integrity": "sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw==", "requires": { "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-modules-amd": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.7.tgz", "integrity": "sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g==", "requires": { "@babel/helper-module-transforms": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7", "babel-plugin-dynamic-import-node": "^2.3.3" } }, "@babel/plugin-transform-modules-commonjs": { "version": "7.16.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.8.tgz", "integrity": "sha512-oflKPvsLT2+uKQopesJt3ApiaIS2HW+hzHFcwRNtyDGieAeC/dIHZX8buJQ2J2X1rxGPy4eRcUijm3qcSPjYcA==", "requires": { "@babel/helper-module-transforms": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7", "@babel/helper-simple-access": "^7.16.7", "babel-plugin-dynamic-import-node": "^2.3.3" } }, "@babel/plugin-transform-modules-systemjs": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.7.tgz", "integrity": "sha512-DuK5E3k+QQmnOqBR9UkusByy5WZWGRxfzV529s9nPra1GE7olmxfqO2FHobEOYSPIjPBTr4p66YDcjQnt8cBmw==", "requires": { "@babel/helper-hoist-variables": "^7.16.7", "@babel/helper-module-transforms": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7", "@babel/helper-validator-identifier": "^7.16.7", "babel-plugin-dynamic-import-node": "^2.3.3" } }, "@babel/plugin-transform-modules-umd": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.7.tgz", "integrity": "sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ==", "requires": { "@babel/helper-module-transforms": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-named-capturing-groups-regex": { "version": "7.16.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.8.tgz", "integrity": "sha512-j3Jw+n5PvpmhRR+mrgIh04puSANCk/T/UA3m3P1MjJkhlK906+ApHhDIqBQDdOgL/r1UYpz4GNclTXxyZrYGSw==", "requires": { "@babel/helper-create-regexp-features-plugin": "^7.16.7" } }, "@babel/plugin-transform-new-target": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.7.tgz", "integrity": "sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg==", "requires": { "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-object-super": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz", "integrity": "sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw==", "requires": { "@babel/helper-plugin-utils": "^7.16.7", "@babel/helper-replace-supers": "^7.16.7" } }, "@babel/plugin-transform-parameters": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz", "integrity": "sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw==", "requires": { "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-property-literals": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz", "integrity": "sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw==", "requires": { "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-regenerator": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz", "integrity": "sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q==", "requires": { "regenerator-transform": "^0.14.2" } }, "@babel/plugin-transform-reserved-words": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.7.tgz", "integrity": "sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg==", "requires": { "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-shorthand-properties": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz", "integrity": "sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg==", "requires": { "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-spread": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz", "integrity": "sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg==", "requires": { "@babel/helper-plugin-utils": "^7.16.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0" } }, "@babel/plugin-transform-sticky-regex": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz", "integrity": "sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw==", "requires": { "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-template-literals": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz", "integrity": "sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA==", "requires": { "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-typeof-symbol": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.7.tgz", "integrity": "sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ==", "requires": { "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-typescript": { "version": "7.16.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.16.8.tgz", "integrity": "sha512-bHdQ9k7YpBDO2d0NVfkj51DpQcvwIzIusJ7mEUaMlbZq3Kt/U47j24inXZHQ5MDiYpCs+oZiwnXyKedE8+q7AQ==", "requires": { "@babel/helper-create-class-features-plugin": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7", "@babel/plugin-syntax-typescript": "^7.16.7" } }, "@babel/plugin-transform-unicode-escapes": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz", "integrity": "sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q==", "requires": { "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/plugin-transform-unicode-regex": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz", "integrity": "sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q==", "requires": { "@babel/helper-create-regexp-features-plugin": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7" } }, "@babel/preset-env": { "version": "7.16.11", "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.16.11.tgz", "integrity": "sha512-qcmWG8R7ZW6WBRPZK//y+E3Cli151B20W1Rv7ln27vuPaXU/8TKms6jFdiJtF7UDTxcrb7mZd88tAeK9LjdT8g==", "requires": { "@babel/compat-data": "^7.16.8", "@babel/helper-compilation-targets": "^7.16.7", "@babel/helper-plugin-utils": "^7.16.7", "@babel/helper-validator-option": "^7.16.7", "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.16.7", "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.16.7", "@babel/plugin-proposal-async-generator-functions": "^7.16.8", "@babel/plugin-proposal-class-properties": "^7.16.7", "@babel/plugin-proposal-class-static-block": "^7.16.7", "@babel/plugin-proposal-dynamic-import": "^7.16.7", "@babel/plugin-proposal-export-namespace-from": "^7.16.7", "@babel/plugin-proposal-json-strings": "^7.16.7", "@babel/plugin-proposal-logical-assignment-operators": "^7.16.7", "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.7", "@babel/plugin-proposal-numeric-separator": "^7.16.7", "@babel/plugin-proposal-object-rest-spread": "^7.16.7", "@babel/plugin-proposal-optional-catch-binding": "^7.16.7", "@babel/plugin-proposal-optional-chaining": "^7.16.7", "@babel/plugin-proposal-private-methods": "^7.16.11", "@babel/plugin-proposal-private-property-in-object": "^7.16.7", "@babel/plugin-proposal-unicode-property-regex": "^7.16.7", "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-class-properties": "^7.12.13", "@babel/plugin-syntax-class-static-block": "^7.14.5", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-namespace-from": "^7.8.3", "@babel/plugin-syntax-json-strings": "^7.8.3", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", "@babel/plugin-syntax-numeric-separator": "^7.10.4", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-syntax-private-property-in-object": "^7.14.5", "@babel/plugin-syntax-top-level-await": "^7.14.5", "@babel/plugin-transform-arrow-functions": "^7.16.7", "@babel/plugin-transform-async-to-generator": "^7.16.8", "@babel/plugin-transform-block-scoped-functions": "^7.16.7", "@babel/plugin-transform-block-scoping": "^7.16.7", "@babel/plugin-transform-classes": "^7.16.7", "@babel/plugin-transform-computed-properties": "^7.16.7", "@babel/plugin-transform-destructuring": "^7.16.7", "@babel/plugin-transform-dotall-regex": "^7.16.7", "@babel/plugin-transform-duplicate-keys": "^7.16.7", "@babel/plugin-transform-exponentiation-operator": "^7.16.7", "@babel/plugin-transform-for-of": "^7.16.7", "@babel/plugin-transform-function-name": "^7.16.7", "@babel/plugin-transform-literals": "^7.16.7", "@babel/plugin-transform-member-expression-literals": "^7.16.7", "@babel/plugin-transform-modules-amd": "^7.16.7", "@babel/plugin-transform-modules-commonjs": "^7.16.8", "@babel/plugin-transform-modules-systemjs": "^7.16.7", "@babel/plugin-transform-modules-umd": "^7.16.7", "@babel/plugin-transform-named-capturing-groups-regex": "^7.16.8", "@babel/plugin-transform-new-target": "^7.16.7", "@babel/plugin-transform-object-super": "^7.16.7", "@babel/plugin-transform-parameters": "^7.16.7", "@babel/plugin-transform-property-literals": "^7.16.7", "@babel/plugin-transform-regenerator": "^7.16.7", "@babel/plugin-transform-reserved-words": "^7.16.7", "@babel/plugin-transform-shorthand-properties": "^7.16.7", "@babel/plugin-transform-spread": "^7.16.7", "@babel/plugin-transform-sticky-regex": "^7.16.7", "@babel/plugin-transform-template-literals": "^7.16.7", "@babel/plugin-transform-typeof-symbol": "^7.16.7", "@babel/plugin-transform-unicode-escapes": "^7.16.7", "@babel/plugin-transform-unicode-regex": "^7.16.7", "@babel/preset-modules": "^0.1.5", "@babel/types": "^7.16.8", "babel-plugin-polyfill-corejs2": "^0.3.0", "babel-plugin-polyfill-corejs3": "^0.5.0", "babel-plugin-polyfill-regenerator": "^0.3.0", "core-js-compat": "^3.20.2", "semver": "^6.3.0" } }, "@babel/preset-flow": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.16.7.tgz", "integrity": "sha512-6ceP7IyZdUYQ3wUVqyRSQXztd1YmFHWI4Xv11MIqAlE4WqxBSd/FZ61V9k+TS5Gd4mkHOtQtPp9ymRpxH4y1Ug==", "requires": { "@babel/helper-plugin-utils": "^7.16.7", "@babel/helper-validator-option": "^7.16.7", "@babel/plugin-transform-flow-strip-types": "^7.16.7" } }, "@babel/preset-modules": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", "requires": { "@babel/helper-plugin-utils": "^7.0.0", "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", "@babel/plugin-transform-dotall-regex": "^7.4.4", "@babel/types": "^7.4.4", "esutils": "^2.0.2" } }, "@babel/register": { "version": "7.16.9", "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.16.9.tgz", "integrity": "sha512-jJ72wcghdRIlENfvALcyODhNoGE5j75cYHdC+aQMh6cU/P86tiiXTp9XYZct1UxUMo/4+BgQRyNZEGx0KWGS+g==", "requires": { "clone-deep": "^4.0.1", "find-cache-dir": "^2.0.0", "make-dir": "^2.1.0", "pirates": "^4.0.0", "source-map-support": "^0.5.16" } }, "@babel/runtime": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.7.tgz", "integrity": "sha512-9E9FJowqAsytyOY6LG+1KuueckRL+aQW+mKvXRXnuFGyRAyepJPmEo9vgMfXUA6O9u3IeEdv9MAkppFcaQwogQ==", "requires": { "regenerator-runtime": "^0.13.4" } }, "@babel/template": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", "requires": { "@babel/code-frame": "^7.16.7", "@babel/parser": "^7.16.7", "@babel/types": "^7.16.7" } }, "@babel/traverse": { "version": "7.16.10", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.16.10.tgz", "integrity": "sha512-yzuaYXoRJBGMlBhsMJoUW7G1UmSb/eXr/JHYM/MsOJgavJibLwASijW7oXBdw3NQ6T0bW7Ty5P/VarOs9cHmqw==", "requires": { "@babel/code-frame": "^7.16.7", "@babel/generator": "^7.16.8", "@babel/helper-environment-visitor": "^7.16.7", "@babel/helper-function-name": "^7.16.7", "@babel/helper-hoist-variables": "^7.16.7", "@babel/helper-split-export-declaration": "^7.16.7", "@babel/parser": "^7.16.10", "@babel/types": "^7.16.8", "debug": "^4.1.0", "globals": "^11.1.0" } }, "@babel/types": { "version": "7.16.8", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.16.8.tgz", "integrity": "sha512-smN2DQc5s4M7fntyjGtyIPbRJv6wW4rU/94fmYJ7PKQuZkC0qGMHXJbg6sNGt12JmVr4k5YaptI/XtiLJBnmIg==", "requires": { "@babel/helper-validator-identifier": "^7.16.7", "to-fast-properties": "^2.0.0" } }, "@nicolo-ribaudo/chokidar-2": { "version": "2.1.8-no-fsevents.3", "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz", "integrity": "sha512-s88O1aVtXftvp5bCPB7WnmXc5IwOZZ7YPuwNPt+GtOOXpPvad1LfbmjYv+qII7zP6RU2QGnqve27dnLycEnyEQ==", "optional": true }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "requires": { "color-convert": "^1.9.0" } }, "anymatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", "optional": true, "requires": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==" }, "babel-plugin-dynamic-import-node": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", "requires": { "object.assign": "^4.1.0" } }, "babel-plugin-polyfill-corejs2": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz", "integrity": "sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w==", "requires": { "@babel/compat-data": "^7.13.11", "@babel/helper-define-polyfill-provider": "^0.3.1", "semver": "^6.1.1" } }, "babel-plugin-polyfill-corejs3": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.1.tgz", "integrity": "sha512-TihqEe4sQcb/QcPJvxe94/9RZuLQuF1+To4WqQcRvc+3J3gLCPIPgDKzGLG6zmQLfH3nn25heRuDNkS2KR4I8A==", "requires": { "@babel/helper-define-polyfill-provider": "^0.3.1", "core-js-compat": "^3.20.0" } }, "babel-plugin-polyfill-regenerator": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz", "integrity": "sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==", "requires": { "@babel/helper-define-polyfill-provider": "^0.3.1" } }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "optional": true }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "braces": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "optional": true, "requires": { "fill-range": "^7.0.1" } }, "browserslist": { "version": "4.19.1", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.1.tgz", "integrity": "sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A==", "requires": { "caniuse-lite": "^1.0.30001286", "electron-to-chromium": "^1.4.17", "escalade": "^3.1.1", "node-releases": "^2.0.1", "picocolors": "^1.0.0" } }, "buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, "call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", "requires": { "function-bind": "^1.1.1", "get-intrinsic": "^1.0.2" } }, "caniuse-lite": { "version": "1.0.30001304", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001304.tgz", "integrity": "sha512-bdsfZd6K6ap87AGqSHJP/s1V+U6Z5lyrcbBu3ovbCCf8cSYpwTtGrCBObMpJqwxfTbLW6YTIdbb1jEeTelcpYQ==" }, "chai": { "version": "4.3.6", "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", "requires": { "assertion-error": "^1.1.0", "check-error": "^1.0.2", "deep-eql": "^3.0.1", "get-func-name": "^2.0.0", "loupe": "^2.3.1", "pathval": "^1.1.1", "type-detect": "^4.0.5" } }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "check-error": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=" }, "chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "optional": true, "requires": { "anymatch": "~3.1.2", "braces": "~3.0.2", "fsevents": "~2.3.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" } }, "clone-deep": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", "requires": { "is-plain-object": "^2.0.4", "kind-of": "^6.0.2", "shallow-clone": "^3.0.0" } }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "requires": { "color-name": "1.1.3" } }, "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "commander": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==" }, "commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "convert-source-map": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", "requires": { "safe-buffer": "~5.1.1" } }, "core-js": { "version": "3.20.3", "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.20.3.tgz", "integrity": "sha512-vVl8j8ph6tRS3B8qir40H7yw7voy17xL0piAjlbBUsH7WIfzoedL/ZOr1OV9FyZQLWXsayOJyV4tnRyXR85/ag==" }, "core-js-compat": { "version": "3.20.3", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.20.3.tgz", "integrity": "sha512-c8M5h0IkNZ+I92QhIpuSijOxGAcj3lgpsWdkCqmUTZNwidujF4r3pi6x1DCN+Vcs5qTS2XWWMfWSuCqyupX8gw==", "requires": { "browserslist": "^4.19.1", "semver": "7.0.0" }, "dependencies": { "semver": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==" } } }, "debug": { "version": "4.3.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", "requires": { "ms": "2.1.2" } }, "deep-eql": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", "requires": { "type-detect": "^4.0.0" } }, "define-properties": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", "requires": { "object-keys": "^1.0.12" } }, "electron-to-chromium": { "version": "1.4.57", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.57.tgz", "integrity": "sha512-FNC+P5K1n6pF+M0zIK+gFCoXcJhhzDViL3DRIGy2Fv5PohuSES1JHR7T+GlwxSxlzx4yYbsuzCZvHxcBSRCIOw==" }, "es-abstract": { "version": "1.19.1", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz", "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==", "requires": { "call-bind": "^1.0.2", "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", "get-intrinsic": "^1.1.1", "get-symbol-description": "^1.0.0", "has": "^1.0.3", "has-symbols": "^1.0.2", "internal-slot": "^1.0.3", "is-callable": "^1.2.4", "is-negative-zero": "^2.0.1", "is-regex": "^1.1.4", "is-shared-array-buffer": "^1.0.1", "is-string": "^1.0.7", "is-weakref": "^1.0.1", "object-inspect": "^1.11.0", "object-keys": "^1.1.1", "object.assign": "^4.1.2", "string.prototype.trimend": "^1.0.4", "string.prototype.trimstart": "^1.0.4", "unbox-primitive": "^1.0.1" } }, "es-to-primitive": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", "requires": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", "is-symbol": "^1.0.2" } }, "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "optional": true, "requires": { "to-regex-range": "^5.0.1" } }, "find-cache-dir": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", "requires": { "commondir": "^1.0.1", "make-dir": "^2.0.0", "pkg-dir": "^3.0.0" } }, "find-up": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "requires": { "locate-path": "^3.0.0" } }, "fs-readdir-recursive": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==" }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "optional": true }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" }, "get-func-name": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=" }, "get-intrinsic": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", "requires": { "function-bind": "^1.1.1", "has": "^1.0.3", "has-symbols": "^1.0.1" } }, "get-symbol-description": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", "requires": { "call-bind": "^1.0.2", "get-intrinsic": "^1.1.1" } }, "glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.0.4", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "optional": true, "requires": { "is-glob": "^4.0.1" } }, "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "requires": { "function-bind": "^1.1.1" } }, "has-bigints": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==" }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, "has-symbols": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" }, "has-tostringtag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", "requires": { "has-symbols": "^1.0.2" } }, "homedir-polyfill": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", "requires": { "parse-passwd": "^1.0.0" } }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "requires": { "once": "^1.3.0", "wrappy": "1" } }, "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "internal-slot": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", "requires": { "get-intrinsic": "^1.1.0", "has": "^1.0.3", "side-channel": "^1.0.4" } }, "is-bigint": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", "requires": { "has-bigints": "^1.0.1" } }, "is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "optional": true, "requires": { "binary-extensions": "^2.0.0" } }, "is-boolean-object": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", "requires": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" } }, "is-callable": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==" }, "is-core-module": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", "requires": { "has": "^1.0.3" } }, "is-date-object": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", "requires": { "has-tostringtag": "^1.0.0" } }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "optional": true }, "is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "optional": true, "requires": { "is-extglob": "^2.1.1" } }, "is-negative-zero": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==" }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "optional": true }, "is-number-object": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", "requires": { "has-tostringtag": "^1.0.0" } }, "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "requires": { "isobject": "^3.0.1" } }, "is-regex": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "requires": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" } }, "is-shared-array-buffer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz", "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==" }, "is-string": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", "requires": { "has-tostringtag": "^1.0.0" } }, "is-symbol": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", "requires": { "has-symbols": "^1.0.2" } }, "is-weakref": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", "requires": { "call-bind": "^1.0.2" } }, "isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" }, "iterall": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.3.0.tgz", "integrity": "sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg==" }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "requires": { "argparse": "^2.0.1" } }, "jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" }, "json5": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", "requires": { "minimist": "^1.2.5" } }, "kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" }, "locate-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "requires": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" } }, "lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" }, "loupe": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.1.tgz", "integrity": "sha512-EN1D3jyVmaX4tnajVlfbREU4axL647hLec1h/PXAb8CPDMJiYitcWF2UeLVNttRqaIqQs4x+mRvXf+d+TlDrCA==", "requires": { "get-func-name": "^2.0.0" } }, "make-dir": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", "requires": { "pify": "^4.0.1", "semver": "^5.6.0" }, "dependencies": { "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" } } }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node-environment-flags": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz", "integrity": "sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw==", "requires": { "object.getownpropertydescriptors": "^2.0.3", "semver": "^5.7.0" }, "dependencies": { "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" } } }, "node-releases": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.1.tgz", "integrity": "sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==" }, "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "optional": true }, "object-inspect": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==" }, "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" }, "object.assign": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", "requires": { "call-bind": "^1.0.0", "define-properties": "^1.1.3", "has-symbols": "^1.0.1", "object-keys": "^1.1.1" } }, "object.getownpropertydescriptors": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.3.tgz", "integrity": "sha512-VdDoCwvJI4QdC6ndjpqFmoL3/+HxffFBbcJzKi5hwLLqqx3mdbedRpfZDdK0SrOSauj8X4GzBvnDZl4vTN7dOw==", "requires": { "call-bind": "^1.0.2", "define-properties": "^1.1.3", "es-abstract": "^1.19.1" } }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "requires": { "wrappy": "1" } }, "p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "requires": { "p-try": "^2.0.0" } }, "p-locate": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "requires": { "p-limit": "^2.0.0" } }, "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" }, "parse-passwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=" }, "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, "path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "pathval": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==" }, "picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, "picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "optional": true }, "pify": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" }, "pirates": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==" }, "pkg-dir": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", "requires": { "find-up": "^3.0.0" } }, "prettier": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz", "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==", "dev": true }, "readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "optional": true, "requires": { "picomatch": "^2.2.1" } }, "regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" }, "regenerate-unicode-properties": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-9.0.0.tgz", "integrity": "sha512-3E12UeNSPfjrgwjkR81m5J7Aw/T55Tu7nUyZVQYCKEOs+2dkxEY+DpPtZzO4YruuiPb7NkYLVcyJC4+zCbk5pA==", "requires": { "regenerate": "^1.4.2" } }, "regenerator-runtime": { "version": "0.13.9", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" }, "regenerator-transform": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", "requires": { "@babel/runtime": "^7.8.4" } }, "regexpu-core": { "version": "4.8.0", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.8.0.tgz", "integrity": "sha512-1F6bYsoYiz6is+oz70NWur2Vlh9KWtswuRuzJOfeYUrfPX2o8n74AnUVaOGDbUqVGO9fNHu48/pjJO4sNVwsOg==", "requires": { "regenerate": "^1.4.2", "regenerate-unicode-properties": "^9.0.0", "regjsgen": "^0.5.2", "regjsparser": "^0.7.0", "unicode-match-property-ecmascript": "^2.0.0", "unicode-match-property-value-ecmascript": "^2.0.0" } }, "regjsgen": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==" }, "regjsparser": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.7.0.tgz", "integrity": "sha512-A4pcaORqmNMDVwUjWoTzuhwMGpP+NykpfqAsEgI1FSH/EzC7lrN5TMd+kN8YCovX+jMpu8eaqXgXPCa0g8FQNQ==", "requires": { "jsesc": "~0.5.0" }, "dependencies": { "jsesc": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=" } } }, "resolve": { "version": "1.22.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", "requires": { "is-core-module": "^2.8.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" } }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" }, "shallow-clone": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", "requires": { "kind-of": "^6.0.2" } }, "side-channel": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", "requires": { "call-bind": "^1.0.0", "get-intrinsic": "^1.0.2", "object-inspect": "^1.9.0" } }, "slash": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==" }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" }, "source-map-support": { "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" }, "dependencies": { "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" } } }, "string.prototype.trimend": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", "requires": { "call-bind": "^1.0.2", "define-properties": "^1.1.3" } }, "string.prototype.trimstart": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", "requires": { "call-bind": "^1.0.2", "define-properties": "^1.1.3" } }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "requires": { "has-flag": "^3.0.0" } }, "supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" }, "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "optional": true, "requires": { "is-number": "^7.0.0" } }, "type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" }, "unbox-primitive": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", "requires": { "function-bind": "^1.1.1", "has-bigints": "^1.0.1", "has-symbols": "^1.0.2", "which-boxed-primitive": "^1.0.2" } }, "unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==" }, "unicode-match-property-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", "requires": { "unicode-canonical-property-names-ecmascript": "^2.0.0", "unicode-property-aliases-ecmascript": "^2.0.0" } }, "unicode-match-property-value-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz", "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==" }, "unicode-property-aliases-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz", "integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==" }, "v8flags": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", "requires": { "homedir-polyfill": "^1.0.1" } }, "which-boxed-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", "requires": { "is-bigint": "^1.0.1", "is-boolean-object": "^1.1.0", "is-number-object": "^1.0.4", "is-string": "^1.0.5", "is-symbol": "^1.0.3" } }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" } } } gqlparser-2.5.1/validator/imported/package.json000066400000000000000000000006451430663104200216210ustar00rootroot00000000000000{ "scripts": { "fmt": "prettier -w '*.js'" }, "dependencies": { "@babel/cli": "^7.16.8", "@babel/core": "^7.16.12", "@babel/node": "^7.16.8", "@babel/plugin-transform-typescript": "^7.16.8", "@babel/preset-env": "^7.16.11", "@babel/preset-flow": "^7.16.7", "chai": "^4.3.6", "iterall": "^1.3.0", "js-yaml": "^4.0.0" }, "devDependencies": { "prettier": "^2.5.1" } } gqlparser-2.5.1/validator/imported/readme.md000066400000000000000000000005371430663104200211120ustar00rootroot00000000000000# graphql.js spec importer These specs have been generated from the testsuite in [graphql/graph-js](https://github.com/graphql/graphql-js). Direct modifications should not be made, instead take a look at the exporter. ```shell script # update to latest $ rm graphql-js-commit.log && ./export.sh # re-generate with known revision $ ./export.sh ``` gqlparser-2.5.1/validator/imported/spec/000077500000000000000000000000001430663104200202605ustar00rootroot00000000000000gqlparser-2.5.1/validator/imported/spec/ExecutableDefinitionsRule.spec.yml000066400000000000000000000030641430663104200270440ustar00rootroot00000000000000- name: with only operation rule: ExecutableDefinitions schema: 0 query: |2- query Foo { dog { name } } errors: [] - name: with operation and fragment rule: ExecutableDefinitions schema: 0 query: |2- query Foo { dog { name ...Frag } } fragment Frag on Dog { name } errors: [] - name: with type definition rule: ExecutableDefinitions schema: 0 query: |2- query Foo { dog { name } } type Cow { name: String } extend type Dog { color: String } errors: - message: The "Cow" definition is not executable. locations: - {line: 8, column: 7} - message: The "Dog" definition is not executable. locations: - {line: 12, column: 7} - name: with schema definition rule: ExecutableDefinitions schema: 0 query: |2- schema { query: Query } type Query { test: String } extend schema @directive errors: - message: The schema definition is not executable. locations: - {line: 2, column: 7} - message: The "Query" definition is not executable. locations: - {line: 6, column: 7} - message: The schema definition is not executable. locations: - {line: 10, column: 7} gqlparser-2.5.1/validator/imported/spec/FieldsOnCorrectTypeRule.spec.yml000066400000000000000000000130561430663104200264600ustar00rootroot00000000000000- name: Object field selection rule: FieldsOnCorrectType schema: 1 query: |2- fragment objectFieldSelection on Dog { __typename name } errors: [] - name: Aliased object field selection rule: FieldsOnCorrectType schema: 1 query: |2- fragment aliasedObjectFieldSelection on Dog { tn : __typename otherName : name } errors: [] - name: Interface field selection rule: FieldsOnCorrectType schema: 1 query: |2- fragment interfaceFieldSelection on Pet { __typename name } errors: [] - name: Aliased interface field selection rule: FieldsOnCorrectType schema: 1 query: |2- fragment interfaceFieldSelection on Pet { otherName : name } errors: [] - name: Lying alias selection rule: FieldsOnCorrectType schema: 1 query: |2- fragment lyingAliasSelection on Dog { name : nickname } errors: [] - name: Ignores fields on unknown type rule: FieldsOnCorrectType schema: 1 query: |2- fragment unknownSelection on UnknownType { unknownField } errors: [] - name: reports errors when type is known again rule: FieldsOnCorrectType schema: 1 query: |2- fragment typeKnownAgain on Pet { unknown_pet_field { ... on Cat { unknown_cat_field } } } errors: - message: Cannot query field "unknown_pet_field" on type "Pet". locations: - {line: 3, column: 9} - message: Cannot query field "unknown_cat_field" on type "Cat". locations: - {line: 5, column: 13} - name: Field not defined on fragment rule: FieldsOnCorrectType schema: 1 query: |2- fragment fieldNotDefined on Dog { meowVolume } errors: - message: Cannot query field "meowVolume" on type "Dog". Did you mean "barkVolume"? locations: - {line: 3, column: 9} - name: Ignores deeply unknown field rule: FieldsOnCorrectType schema: 1 query: |2- fragment deepFieldNotDefined on Dog { unknown_field { deeper_unknown_field } } errors: - message: Cannot query field "unknown_field" on type "Dog". locations: - {line: 3, column: 9} - name: Sub-field not defined rule: FieldsOnCorrectType schema: 1 query: |2- fragment subFieldNotDefined on Human { pets { unknown_field } } errors: - message: Cannot query field "unknown_field" on type "Pet". locations: - {line: 4, column: 11} - name: Field not defined on inline fragment rule: FieldsOnCorrectType schema: 1 query: |2- fragment fieldNotDefined on Pet { ... on Dog { meowVolume } } errors: - message: Cannot query field "meowVolume" on type "Dog". Did you mean "barkVolume"? locations: - {line: 4, column: 11} - name: Aliased field target not defined rule: FieldsOnCorrectType schema: 1 query: |2- fragment aliasedFieldTargetNotDefined on Dog { volume : mooVolume } errors: - message: Cannot query field "mooVolume" on type "Dog". Did you mean "barkVolume"? locations: - {line: 3, column: 9} - name: Aliased lying field target not defined rule: FieldsOnCorrectType schema: 1 query: |2- fragment aliasedLyingFieldTargetNotDefined on Dog { barkVolume : kawVolume } errors: - message: Cannot query field "kawVolume" on type "Dog". Did you mean "barkVolume"? locations: - {line: 3, column: 9} - name: Not defined on interface rule: FieldsOnCorrectType schema: 1 query: |2- fragment notDefinedOnInterface on Pet { tailLength } errors: - message: Cannot query field "tailLength" on type "Pet". locations: - {line: 3, column: 9} - name: Defined on implementors but not on interface rule: FieldsOnCorrectType schema: 1 query: |2- fragment definedOnImplementorsButNotInterface on Pet { nickname } errors: - message: Cannot query field "nickname" on type "Pet". Did you mean to use an inline fragment on "Cat" or "Dog"? locations: - {line: 3, column: 9} - name: Meta field selection on union rule: FieldsOnCorrectType schema: 1 query: |2- fragment directFieldSelectionOnUnion on CatOrDog { __typename } errors: [] - name: Direct field selection on union rule: FieldsOnCorrectType schema: 1 query: |2- fragment directFieldSelectionOnUnion on CatOrDog { directField } errors: - message: Cannot query field "directField" on type "CatOrDog". locations: - {line: 3, column: 9} - name: Defined on implementors queried on union rule: FieldsOnCorrectType schema: 1 query: |2- fragment definedOnImplementorsQueriedOnUnion on CatOrDog { name } errors: - message: Cannot query field "name" on type "CatOrDog". Did you mean to use an inline fragment on "Pet", "Cat", or "Dog"? locations: - {line: 3, column: 9} - name: valid field in inline fragment rule: FieldsOnCorrectType schema: 1 query: |2- fragment objectFieldSelection on Pet { ... on Dog { name } ... { name } } errors: [] gqlparser-2.5.1/validator/imported/spec/FragmentsOnCompositeTypesRule.spec.yml000066400000000000000000000050721430663104200277230ustar00rootroot00000000000000- name: object is valid fragment type rule: FragmentsOnCompositeTypes schema: 0 query: |2- fragment validFragment on Dog { barks } errors: [] - name: interface is valid fragment type rule: FragmentsOnCompositeTypes schema: 0 query: |2- fragment validFragment on Pet { name } errors: [] - name: object is valid inline fragment type rule: FragmentsOnCompositeTypes schema: 0 query: |2- fragment validFragment on Pet { ... on Dog { barks } } errors: [] - name: interface is valid inline fragment type rule: FragmentsOnCompositeTypes schema: 0 query: |2- fragment validFragment on Mammal { ... on Canine { name } } errors: [] - name: inline fragment without type is valid rule: FragmentsOnCompositeTypes schema: 0 query: |2- fragment validFragment on Pet { ... { name } } errors: [] - name: union is valid fragment type rule: FragmentsOnCompositeTypes schema: 0 query: |2- fragment validFragment on CatOrDog { __typename } errors: [] - name: scalar is invalid fragment type rule: FragmentsOnCompositeTypes schema: 0 query: |2- fragment scalarFragment on Boolean { bad } errors: - message: Fragment "scalarFragment" cannot condition on non composite type "Boolean". locations: - {line: 2, column: 34} - name: enum is invalid fragment type rule: FragmentsOnCompositeTypes schema: 0 query: |2- fragment scalarFragment on FurColor { bad } errors: - message: Fragment "scalarFragment" cannot condition on non composite type "FurColor". locations: - {line: 2, column: 34} - name: input object is invalid fragment type rule: FragmentsOnCompositeTypes schema: 0 query: |2- fragment inputFragment on ComplexInput { stringField } errors: - message: Fragment "inputFragment" cannot condition on non composite type "ComplexInput". locations: - {line: 2, column: 33} - name: scalar is invalid inline fragment type rule: FragmentsOnCompositeTypes schema: 0 query: |2- fragment invalidFragment on Pet { ... on String { barks } } errors: - message: Fragment cannot condition on non composite type "String". locations: - {line: 3, column: 16} gqlparser-2.5.1/validator/imported/spec/KnownArgumentNamesRule.spec.yml000066400000000000000000000103451430663104200263520ustar00rootroot00000000000000- name: single arg is known rule: KnownArgumentNames schema: 0 query: |2- fragment argOnRequiredArg on Dog { doesKnowCommand(dogCommand: SIT) } errors: [] - name: multiple args are known rule: KnownArgumentNames schema: 0 query: |2- fragment multipleArgs on ComplicatedArgs { multipleReqs(req1: 1, req2: 2) } errors: [] - name: ignores args of unknown fields rule: KnownArgumentNames schema: 0 query: |2- fragment argOnUnknownField on Dog { unknownField(unknownArg: SIT) } errors: [] - name: multiple args in reverse order are known rule: KnownArgumentNames schema: 0 query: |2- fragment multipleArgsReverseOrder on ComplicatedArgs { multipleReqs(req2: 2, req1: 1) } errors: [] - name: no args on optional arg rule: KnownArgumentNames schema: 0 query: |2- fragment noArgOnOptionalArg on Dog { isHouseTrained } errors: [] - name: args are known deeply rule: KnownArgumentNames schema: 0 query: |2- { dog { doesKnowCommand(dogCommand: SIT) } human { pet { ... on Dog { doesKnowCommand(dogCommand: SIT) } } } } errors: [] - name: directive args are known rule: KnownArgumentNames schema: 0 query: |2- { dog @skip(if: true) } errors: [] - name: field args are invalid rule: KnownArgumentNames schema: 0 query: |2- { dog @skip(unless: true) } errors: - message: Unknown argument "unless" on directive "@skip". locations: - {line: 3, column: 19} - name: directive without args is valid rule: KnownArgumentNames schema: 0 query: |2- { dog @onField } errors: [] - name: arg passed to directive without arg is reported rule: KnownArgumentNames schema: 0 query: |2- { dog @onField(if: true) } errors: - message: Unknown argument "if" on directive "@onField". locations: - {line: 3, column: 22} - name: misspelled directive args are reported rule: KnownArgumentNames schema: 0 query: |2- { dog @skip(iff: true) } errors: - message: Unknown argument "iff" on directive "@skip". Did you mean "if"? locations: - {line: 3, column: 19} - name: invalid arg name rule: KnownArgumentNames schema: 0 query: |2- fragment invalidArgName on Dog { doesKnowCommand(unknown: true) } errors: - message: Unknown argument "unknown" on field "Dog.doesKnowCommand". locations: - {line: 3, column: 25} - name: misspelled arg name is reported rule: KnownArgumentNames schema: 0 query: |2- fragment invalidArgName on Dog { doesKnowCommand(DogCommand: true) } errors: - message: Unknown argument "DogCommand" on field "Dog.doesKnowCommand". Did you mean "dogCommand"? locations: - {line: 3, column: 25} - name: unknown args amongst known args rule: KnownArgumentNames schema: 0 query: |2- fragment oneGoodArgOneInvalidArg on Dog { doesKnowCommand(whoKnows: 1, dogCommand: SIT, unknown: true) } errors: - message: Unknown argument "whoKnows" on field "Dog.doesKnowCommand". locations: - {line: 3, column: 25} - message: Unknown argument "unknown" on field "Dog.doesKnowCommand". locations: - {line: 3, column: 55} - name: unknown args deeply rule: KnownArgumentNames schema: 0 query: |2- { dog { doesKnowCommand(unknown: true) } human { pet { ... on Dog { doesKnowCommand(unknown: true) } } } } errors: - message: Unknown argument "unknown" on field "Dog.doesKnowCommand". locations: - {line: 4, column: 27} - message: Unknown argument "unknown" on field "Dog.doesKnowCommand". locations: - {line: 9, column: 31} gqlparser-2.5.1/validator/imported/spec/KnownDirectivesRule.spec.yml000066400000000000000000000076601430663104200257130ustar00rootroot00000000000000- name: with no directives rule: KnownDirectives schema: 2 query: |2- query Foo { name ...Frag } fragment Frag on Dog { name } errors: [] - name: with standard directives rule: KnownDirectives schema: 2 query: |2- { human @skip(if: false) { name pets { ... on Dog @include(if: true) { name } } } } errors: [] - name: with unknown directive rule: KnownDirectives schema: 2 query: |2- { human @unknown(directive: "value") { name } } errors: - message: Unknown directive "@unknown". locations: - {line: 3, column: 15} - name: with many unknown directives rule: KnownDirectives schema: 2 query: |2- { __typename @unknown human @unknown { name pets @unknown { name } } } errors: - message: Unknown directive "@unknown". locations: - {line: 3, column: 20} - message: Unknown directive "@unknown". locations: - {line: 4, column: 15} - message: Unknown directive "@unknown". locations: - {line: 6, column: 16} - name: with well placed directives rule: KnownDirectives schema: 2 query: |2- query ($var: Boolean @onVariableDefinition) @onQuery { human @onField { ...Frag @onFragmentSpread ... @onInlineFragment { name @onField } } } mutation @onMutation { someField @onField } subscription @onSubscription { someField @onField } fragment Frag on Human @onFragmentDefinition { name @onField } errors: [] - name: with misplaced directives rule: KnownDirectives schema: 2 query: |2- query ($var: Boolean @onQuery) @onMutation { human @onQuery { ...Frag @onQuery ... @onQuery { name @onQuery } } } mutation @onQuery { someField @onQuery } subscription @onQuery { someField @onQuery } fragment Frag on Human @onQuery { name @onQuery } errors: - message: Directive "@onQuery" may not be used on VARIABLE_DEFINITION. locations: - {line: 2, column: 28} - message: Directive "@onMutation" may not be used on QUERY. locations: - {line: 2, column: 38} - message: Directive "@onQuery" may not be used on FIELD. locations: - {line: 3, column: 15} - message: Directive "@onQuery" may not be used on FRAGMENT_SPREAD. locations: - {line: 4, column: 19} - message: Directive "@onQuery" may not be used on INLINE_FRAGMENT. locations: - {line: 5, column: 15} - message: Directive "@onQuery" may not be used on FIELD. locations: - {line: 6, column: 18} - message: Directive "@onQuery" may not be used on MUTATION. locations: - {line: 11, column: 16} - message: Directive "@onQuery" may not be used on FIELD. locations: - {column: 19, line: 12} - message: Directive "@onQuery" may not be used on SUBSCRIPTION. locations: - {column: 20, line: 15} - message: Directive "@onQuery" may not be used on FIELD. locations: - {column: 19, line: 16} - message: Directive "@onQuery" may not be used on FRAGMENT_DEFINITION. locations: - {column: 30, line: 19} - message: Directive "@onQuery" may not be used on FIELD. locations: - {column: 14, line: 20} gqlparser-2.5.1/validator/imported/spec/KnownFragmentNamesRule.spec.yml000066400000000000000000000023711430663104200263330ustar00rootroot00000000000000- name: known fragment names are valid rule: KnownFragmentNames schema: 0 query: |2- { human(id: 4) { ...HumanFields1 ... on Human { ...HumanFields2 } ... { name } } } fragment HumanFields1 on Human { name ...HumanFields3 } fragment HumanFields2 on Human { name } fragment HumanFields3 on Human { name } errors: [] - name: unknown fragment names are invalid rule: KnownFragmentNames schema: 0 query: |2- { human(id: 4) { ...UnknownFragment1 ... on Human { ...UnknownFragment2 } } } fragment HumanFields on Human { name ...UnknownFragment3 } errors: - message: Unknown fragment "UnknownFragment1". locations: - {line: 4, column: 14} - message: Unknown fragment "UnknownFragment2". locations: - {line: 6, column: 16} - message: Unknown fragment "UnknownFragment3". locations: - {line: 12, column: 12} gqlparser-2.5.1/validator/imported/spec/KnownTypeNamesRule.spec.yml000066400000000000000000000030141430663104200255040ustar00rootroot00000000000000- name: known type names are valid rule: KnownTypeNames schema: 0 query: |2- query Foo( $var: String $required: [Int!]! $introspectionType: __EnumValue ) { user(id: 4) { pets { ... on Pet { name }, ...PetFields, ... { name } } } } fragment PetFields on Pet { name } errors: [] - name: unknown type names are invalid rule: KnownTypeNames schema: 0 query: |2- query Foo($var: [JumbledUpLetters!]!) { user(id: 4) { name pets { ... on Badger { name }, ...PetFields } } } fragment PetFields on Peat { name } errors: - message: Unknown type "JumbledUpLetters". locations: - {line: 2, column: 24} - message: Unknown type "Badger". locations: - {line: 5, column: 25} - message: Unknown type "Peat". Did you mean "Pet" or "Cat"? locations: - {line: 8, column: 29} - name: references to standard scalars that are missing in schema rule: KnownTypeNames schema: 3 query: |2- query ($id: ID, $float: Float, $int: Int) { __typename } errors: - message: Unknown type "ID". locations: - {line: 2, column: 19} - message: Unknown type "Float". locations: - {line: 2, column: 31} - message: Unknown type "Int". locations: - {line: 2, column: 44} gqlparser-2.5.1/validator/imported/spec/LoneAnonymousOperationRule.spec.yml000066400000000000000000000034531430663104200272600ustar00rootroot00000000000000- name: no operations rule: LoneAnonymousOperation schema: 0 query: |2- fragment fragA on Type { field } errors: [] - name: one anon operation rule: LoneAnonymousOperation schema: 0 query: |2- { field } errors: [] - name: multiple named operations rule: LoneAnonymousOperation schema: 0 query: |2- query Foo { field } query Bar { field } errors: [] - name: anon operation with fragment rule: LoneAnonymousOperation schema: 0 query: |2- { ...Foo } fragment Foo on Type { field } errors: [] - name: multiple anon operations rule: LoneAnonymousOperation schema: 0 query: |2- { fieldA } { fieldB } errors: - message: This anonymous operation must be the only defined operation. locations: - {line: 2, column: 7} - message: This anonymous operation must be the only defined operation. locations: - {line: 5, column: 7} - name: anon operation with a mutation rule: LoneAnonymousOperation schema: 0 query: |2- { fieldA } mutation Foo { fieldB } errors: - message: This anonymous operation must be the only defined operation. locations: - {line: 2, column: 7} - name: anon operation with a subscription rule: LoneAnonymousOperation schema: 0 query: |2- { fieldA } subscription Foo { fieldB } errors: - message: This anonymous operation must be the only defined operation. locations: - {line: 2, column: 7} gqlparser-2.5.1/validator/imported/spec/LoneSchemaDefinitionRule.spec.yml000066400000000000000000000000031430663104200266040ustar00rootroot00000000000000[] gqlparser-2.5.1/validator/imported/spec/NoDeprecatedCustomRule.spec.yml000066400000000000000000000126311430663104200263170ustar00rootroot00000000000000- name: no deprecated fields/ignores fields that are not deprecated rule: NoDeprecatedCustom schema: 4 query: |2- { normalField } errors: [] - name: no deprecated fields/ignores unknown fields rule: NoDeprecatedCustom schema: 4 query: |2- { unknownField } fragment UnknownFragment on UnknownType { deprecatedField } errors: [] - name: no deprecated fields/reports error when a deprecated field is selected rule: NoDeprecatedCustom schema: 4 query: |2- { deprecatedField } fragment QueryFragment on Query { deprecatedField } errors: - message: The field Query.deprecatedField is deprecated. Some field reason. locations: - {line: 3, column: 11} - message: The field Query.deprecatedField is deprecated. Some field reason. locations: - {line: 7, column: 11} - name: no deprecated arguments on fields/ignores arguments that are not deprecated rule: NoDeprecatedCustom schema: 5 query: |2- { normalField(normalArg: "") } errors: [] - name: no deprecated arguments on fields/ignores unknown arguments rule: NoDeprecatedCustom schema: 5 query: |2- { someField(unknownArg: "") unknownField(deprecatedArg: "") } errors: [] - name: no deprecated arguments on fields/reports error when a deprecated argument is used rule: NoDeprecatedCustom schema: 5 query: |2- { someField(deprecatedArg: "") } errors: - message: Field "Query.someField" argument "deprecatedArg" is deprecated. Some arg reason. locations: - {line: 3, column: 21} - name: no deprecated arguments on directives/ignores arguments that are not deprecated rule: NoDeprecatedCustom schema: 6 query: |2- { someField @someDirective(normalArg: "") } errors: [] - name: no deprecated arguments on directives/ignores unknown arguments rule: NoDeprecatedCustom schema: 6 query: |2- { someField @someDirective(unknownArg: "") someField @unknownDirective(deprecatedArg: "") } errors: [] - name: no deprecated arguments on directives/reports error when a deprecated argument is used rule: NoDeprecatedCustom schema: 6 query: |2- { someField @someDirective(deprecatedArg: "") } errors: - message: Directive "@someDirective" argument "deprecatedArg" is deprecated. Some arg reason. locations: - {line: 3, column: 36} - name: no deprecated input fields/ignores input fields that are not deprecated rule: NoDeprecatedCustom schema: 7 query: |2- { someField( someArg: { normalField: "" } ) @someDirective(someArg: { normalField: "" }) } errors: [] - name: no deprecated input fields/ignores unknown input fields rule: NoDeprecatedCustom schema: 7 query: |2- { someField( someArg: { unknownField: "" } ) someField( unknownArg: { unknownField: "" } ) unknownField( unknownArg: { unknownField: "" } ) } errors: [] - name: no deprecated input fields/reports error when a deprecated input field is used rule: NoDeprecatedCustom schema: 7 query: |2- { someField( someArg: { deprecatedField: "" } ) @someDirective(someArg: { deprecatedField: "" }) } errors: - message: The input field InputType.deprecatedField is deprecated. Some input field reason. locations: - {line: 4, column: 24} - message: The input field InputType.deprecatedField is deprecated. Some input field reason. locations: - {line: 5, column: 39} - name: no deprecated enum values/ignores enum values that are not deprecated rule: NoDeprecatedCustom schema: 8 query: |2- { normalField(enumArg: NORMAL_VALUE) } errors: [] - name: no deprecated enum values/ignores unknown enum values rule: NoDeprecatedCustom schema: 8 query: |2- query ( $unknownValue: EnumType = UNKNOWN_VALUE $unknownType: UnknownType = UNKNOWN_VALUE ) { someField(enumArg: UNKNOWN_VALUE) someField(unknownArg: UNKNOWN_VALUE) unknownField(unknownArg: UNKNOWN_VALUE) } fragment SomeFragment on Query { someField(enumArg: UNKNOWN_VALUE) } errors: [] - name: no deprecated enum values/reports error when a deprecated enum value is used rule: NoDeprecatedCustom schema: 8 query: |2- query ( $variable: EnumType = DEPRECATED_VALUE ) { someField(enumArg: DEPRECATED_VALUE) } errors: - message: The enum value "EnumType.DEPRECATED_VALUE" is deprecated. Some enum reason. locations: - {line: 3, column: 33} - message: The enum value "EnumType.DEPRECATED_VALUE" is deprecated. Some enum reason. locations: - {line: 5, column: 30} gqlparser-2.5.1/validator/imported/spec/NoFragmentCyclesRule.spec.yml000066400000000000000000000140631430663104200257730ustar00rootroot00000000000000- name: single reference is valid rule: NoFragmentCycles schema: 0 query: |2- fragment fragA on Dog { ...fragB } fragment fragB on Dog { name } errors: [] - name: spreading twice is not circular rule: NoFragmentCycles schema: 0 query: |2- fragment fragA on Dog { ...fragB, ...fragB } fragment fragB on Dog { name } errors: [] - name: spreading twice indirectly is not circular rule: NoFragmentCycles schema: 0 query: |2- fragment fragA on Dog { ...fragB, ...fragC } fragment fragB on Dog { ...fragC } fragment fragC on Dog { name } errors: [] - name: double spread within abstract types rule: NoFragmentCycles schema: 0 query: |2- fragment nameFragment on Pet { ... on Dog { name } ... on Cat { name } } fragment spreadsInAnon on Pet { ... on Dog { ...nameFragment } ... on Cat { ...nameFragment } } errors: [] - name: does not false positive on unknown fragment rule: NoFragmentCycles schema: 0 query: |2- fragment nameFragment on Pet { ...UnknownFragment } errors: [] - name: spreading recursively within field fails rule: NoFragmentCycles schema: 0 query: |2- fragment fragA on Human { relatives { ...fragA } }, errors: - message: Cannot spread fragment "fragA" within itself. locations: - {line: 2, column: 45} - name: no spreading itself directly rule: NoFragmentCycles schema: 0 query: |2- fragment fragA on Dog { ...fragA } errors: - message: Cannot spread fragment "fragA" within itself. locations: - {line: 2, column: 31} - name: no spreading itself directly within inline fragment rule: NoFragmentCycles schema: 0 query: |2- fragment fragA on Pet { ... on Dog { ...fragA } } errors: - message: Cannot spread fragment "fragA" within itself. locations: - {line: 4, column: 11} - name: no spreading itself indirectly rule: NoFragmentCycles schema: 0 query: |2- fragment fragA on Dog { ...fragB } fragment fragB on Dog { ...fragA } errors: - message: Cannot spread fragment "fragA" within itself via "fragB". locations: - {line: 2, column: 31} - {line: 3, column: 31} - name: no spreading itself indirectly reports opposite order rule: NoFragmentCycles schema: 0 query: |2- fragment fragB on Dog { ...fragA } fragment fragA on Dog { ...fragB } errors: - message: Cannot spread fragment "fragB" within itself via "fragA". locations: - {line: 2, column: 31} - {line: 3, column: 31} - name: no spreading itself indirectly within inline fragment rule: NoFragmentCycles schema: 0 query: |2- fragment fragA on Pet { ... on Dog { ...fragB } } fragment fragB on Pet { ... on Dog { ...fragA } } errors: - message: Cannot spread fragment "fragA" within itself via "fragB". locations: - {line: 4, column: 11} - {line: 9, column: 11} - name: no spreading itself deeply rule: NoFragmentCycles schema: 0 query: |2- fragment fragA on Dog { ...fragB } fragment fragB on Dog { ...fragC } fragment fragC on Dog { ...fragO } fragment fragX on Dog { ...fragY } fragment fragY on Dog { ...fragZ } fragment fragZ on Dog { ...fragO } fragment fragO on Dog { ...fragP } fragment fragP on Dog { ...fragA, ...fragX } errors: - message: Cannot spread fragment "fragA" within itself via "fragB", "fragC", "fragO", "fragP". locations: - {line: 2, column: 31} - {line: 3, column: 31} - {line: 4, column: 31} - {line: 8, column: 31} - {line: 9, column: 31} - message: Cannot spread fragment "fragO" within itself via "fragP", "fragX", "fragY", "fragZ". locations: - {line: 8, column: 31} - {line: 9, column: 41} - {line: 5, column: 31} - {line: 6, column: 31} - {line: 7, column: 31} - name: no spreading itself deeply two paths rule: NoFragmentCycles schema: 0 query: |2- fragment fragA on Dog { ...fragB, ...fragC } fragment fragB on Dog { ...fragA } fragment fragC on Dog { ...fragA } errors: - message: Cannot spread fragment "fragA" within itself via "fragB". locations: - {line: 2, column: 31} - {line: 3, column: 31} - message: Cannot spread fragment "fragA" within itself via "fragC". locations: - {line: 2, column: 41} - {line: 4, column: 31} - name: no spreading itself deeply two paths -- alt traverse order rule: NoFragmentCycles schema: 0 query: |2- fragment fragA on Dog { ...fragC } fragment fragB on Dog { ...fragC } fragment fragC on Dog { ...fragA, ...fragB } errors: - message: Cannot spread fragment "fragA" within itself via "fragC". locations: - {line: 2, column: 31} - {line: 4, column: 31} - message: Cannot spread fragment "fragC" within itself via "fragB". locations: - {line: 4, column: 41} - {line: 3, column: 31} - name: no spreading itself deeply and immediately rule: NoFragmentCycles schema: 0 query: |2- fragment fragA on Dog { ...fragB } fragment fragB on Dog { ...fragB, ...fragC } fragment fragC on Dog { ...fragA, ...fragB } errors: - message: Cannot spread fragment "fragB" within itself. locations: - {line: 3, column: 31} - message: Cannot spread fragment "fragA" within itself via "fragB", "fragC". locations: - {line: 2, column: 31} - {line: 3, column: 41} - {line: 4, column: 31} - message: Cannot spread fragment "fragB" within itself via "fragC". locations: - {line: 3, column: 41} - {line: 4, column: 41} gqlparser-2.5.1/validator/imported/spec/NoSchemaIntrospectionCustomRule.spec.yml000066400000000000000000000052201430663104200302340ustar00rootroot00000000000000- name: ignores valid fields including __typename rule: NoSchemaIntrospectionCustom schema: 9 query: |2- { someQuery { __typename someField } } errors: [] - name: ignores fields not in the schema rule: NoSchemaIntrospectionCustom schema: 9 query: |2- { __introspect } errors: [] - name: reports error when a field with an introspection type is requested rule: NoSchemaIntrospectionCustom schema: 9 query: |2- { __schema { queryType { name } } } errors: - message: GraphQL introspection has been disabled, but the requested query contained the field "__schema". locations: - {line: 3, column: 9} - message: GraphQL introspection has been disabled, but the requested query contained the field "queryType". locations: - {line: 4, column: 11} - name: reports error when a field with an introspection type is requested and aliased rule: NoSchemaIntrospectionCustom schema: 9 query: |2- { s: __schema { queryType { name } } } errors: - message: GraphQL introspection has been disabled, but the requested query contained the field "__schema". locations: - {line: 3, column: 9} - message: GraphQL introspection has been disabled, but the requested query contained the field "queryType". locations: - {line: 4, column: 11} - name: reports error when using a fragment with a field with an introspection type rule: NoSchemaIntrospectionCustom schema: 9 query: |2- { ...QueryFragment } fragment QueryFragment on Query { __schema { queryType { name } } } errors: - message: GraphQL introspection has been disabled, but the requested query contained the field "__schema". locations: - {line: 7, column: 9} - message: GraphQL introspection has been disabled, but the requested query contained the field "queryType". locations: - {line: 8, column: 11} - name: reports error for non-standard introspection fields rule: NoSchemaIntrospectionCustom schema: 9 query: |2- { someQuery { introspectionField } } errors: - message: GraphQL introspection has been disabled, but the requested query contained the field "introspectionField". locations: - {line: 4, column: 11} gqlparser-2.5.1/validator/imported/spec/NoUndefinedVariablesRule.spec.yml000066400000000000000000000207231430663104200266170ustar00rootroot00000000000000- name: all variables defined rule: NoUndefinedVariables schema: 0 query: |2- query Foo($a: String, $b: String, $c: String) { field(a: $a, b: $b, c: $c) } errors: [] - name: all variables deeply defined rule: NoUndefinedVariables schema: 0 query: |2- query Foo($a: String, $b: String, $c: String) { field(a: $a) { field(b: $b) { field(c: $c) } } } errors: [] - name: all variables deeply in inline fragments defined rule: NoUndefinedVariables schema: 0 query: |2- query Foo($a: String, $b: String, $c: String) { ... on Type { field(a: $a) { field(b: $b) { ... on Type { field(c: $c) } } } } } errors: [] - name: all variables in fragments deeply defined rule: NoUndefinedVariables schema: 0 query: |2- query Foo($a: String, $b: String, $c: String) { ...FragA } fragment FragA on Type { field(a: $a) { ...FragB } } fragment FragB on Type { field(b: $b) { ...FragC } } fragment FragC on Type { field(c: $c) } errors: [] - name: variable within single fragment defined in multiple operations rule: NoUndefinedVariables schema: 0 query: |2- query Foo($a: String) { ...FragA } query Bar($a: String) { ...FragA } fragment FragA on Type { field(a: $a) } errors: [] - name: variable within fragments defined in operations rule: NoUndefinedVariables schema: 0 query: |2- query Foo($a: String) { ...FragA } query Bar($b: String) { ...FragB } fragment FragA on Type { field(a: $a) } fragment FragB on Type { field(b: $b) } errors: [] - name: variable within recursive fragment defined rule: NoUndefinedVariables schema: 0 query: |2- query Foo($a: String) { ...FragA } fragment FragA on Type { field(a: $a) { ...FragA } } errors: [] - name: variable not defined rule: NoUndefinedVariables schema: 0 query: |2- query Foo($a: String, $b: String, $c: String) { field(a: $a, b: $b, c: $c, d: $d) } errors: - message: Variable "$d" is not defined by operation "Foo". locations: - {line: 3, column: 39} - {line: 2, column: 7} - name: variable not defined by un-named query rule: NoUndefinedVariables schema: 0 query: |2- { field(a: $a) } errors: - message: Variable "$a" is not defined. locations: - {line: 3, column: 18} - {line: 2, column: 7} - name: multiple variables not defined rule: NoUndefinedVariables schema: 0 query: |2- query Foo($b: String) { field(a: $a, b: $b, c: $c) } errors: - message: Variable "$a" is not defined by operation "Foo". locations: - {line: 3, column: 18} - {line: 2, column: 7} - message: Variable "$c" is not defined by operation "Foo". locations: - {line: 3, column: 32} - {line: 2, column: 7} - name: variable in fragment not defined by un-named query rule: NoUndefinedVariables schema: 0 query: |2- { ...FragA } fragment FragA on Type { field(a: $a) } errors: - message: Variable "$a" is not defined. locations: - {line: 6, column: 18} - {line: 2, column: 7} - name: variable in fragment not defined by operation rule: NoUndefinedVariables schema: 0 query: |2- query Foo($a: String, $b: String) { ...FragA } fragment FragA on Type { field(a: $a) { ...FragB } } fragment FragB on Type { field(b: $b) { ...FragC } } fragment FragC on Type { field(c: $c) } errors: - message: Variable "$c" is not defined by operation "Foo". locations: - {line: 16, column: 18} - {line: 2, column: 7} - name: multiple variables in fragments not defined rule: NoUndefinedVariables schema: 0 query: |2- query Foo($b: String) { ...FragA } fragment FragA on Type { field(a: $a) { ...FragB } } fragment FragB on Type { field(b: $b) { ...FragC } } fragment FragC on Type { field(c: $c) } errors: - message: Variable "$a" is not defined by operation "Foo". locations: - {line: 6, column: 18} - {line: 2, column: 7} - message: Variable "$c" is not defined by operation "Foo". locations: - {line: 16, column: 18} - {line: 2, column: 7} - name: single variable in fragment not defined by multiple operations rule: NoUndefinedVariables schema: 0 query: |2- query Foo($a: String) { ...FragAB } query Bar($a: String) { ...FragAB } fragment FragAB on Type { field(a: $a, b: $b) } errors: - message: Variable "$b" is not defined by operation "Foo". locations: - {line: 9, column: 25} - {line: 2, column: 7} - message: Variable "$b" is not defined by operation "Bar". locations: - {line: 9, column: 25} - {line: 5, column: 7} - name: variables in fragment not defined by multiple operations rule: NoUndefinedVariables schema: 0 query: |2- query Foo($b: String) { ...FragAB } query Bar($a: String) { ...FragAB } fragment FragAB on Type { field(a: $a, b: $b) } errors: - message: Variable "$a" is not defined by operation "Foo". locations: - {line: 9, column: 18} - {line: 2, column: 7} - message: Variable "$b" is not defined by operation "Bar". locations: - {line: 9, column: 25} - {line: 5, column: 7} - name: variable in fragment used by other operation rule: NoUndefinedVariables schema: 0 query: |2- query Foo($b: String) { ...FragA } query Bar($a: String) { ...FragB } fragment FragA on Type { field(a: $a) } fragment FragB on Type { field(b: $b) } errors: - message: Variable "$a" is not defined by operation "Foo". locations: - {line: 9, column: 18} - {line: 2, column: 7} - message: Variable "$b" is not defined by operation "Bar". locations: - {line: 12, column: 18} - {line: 5, column: 7} - name: multiple undefined variables produce multiple errors rule: NoUndefinedVariables schema: 0 query: |2- query Foo($b: String) { ...FragAB } query Bar($a: String) { ...FragAB } fragment FragAB on Type { field1(a: $a, b: $b) ...FragC field3(a: $a, b: $b) } fragment FragC on Type { field2(c: $c) } errors: - message: Variable "$a" is not defined by operation "Foo". locations: - {line: 9, column: 19} - {line: 2, column: 7} - message: Variable "$a" is not defined by operation "Foo". locations: - {line: 11, column: 19} - {line: 2, column: 7} - message: Variable "$c" is not defined by operation "Foo". locations: - {line: 14, column: 19} - {line: 2, column: 7} - message: Variable "$b" is not defined by operation "Bar". locations: - {line: 9, column: 26} - {line: 5, column: 7} - message: Variable "$b" is not defined by operation "Bar". locations: - {line: 11, column: 26} - {line: 5, column: 7} - message: Variable "$c" is not defined by operation "Bar". locations: - {line: 14, column: 19} - {line: 5, column: 7} gqlparser-2.5.1/validator/imported/spec/NoUnusedFragmentsRule.spec.yml000066400000000000000000000063221430663104200261760ustar00rootroot00000000000000- name: all fragment names are used rule: NoUnusedFragments schema: 0 query: |2- { human(id: 4) { ...HumanFields1 ... on Human { ...HumanFields2 } } } fragment HumanFields1 on Human { name ...HumanFields3 } fragment HumanFields2 on Human { name } fragment HumanFields3 on Human { name } errors: [] - name: all fragment names are used by multiple operations rule: NoUnusedFragments schema: 0 query: |2- query Foo { human(id: 4) { ...HumanFields1 } } query Bar { human(id: 4) { ...HumanFields2 } } fragment HumanFields1 on Human { name ...HumanFields3 } fragment HumanFields2 on Human { name } fragment HumanFields3 on Human { name } errors: [] - name: contains unknown fragments rule: NoUnusedFragments schema: 0 query: |2- query Foo { human(id: 4) { ...HumanFields1 } } query Bar { human(id: 4) { ...HumanFields2 } } fragment HumanFields1 on Human { name ...HumanFields3 } fragment HumanFields2 on Human { name } fragment HumanFields3 on Human { name } fragment Unused1 on Human { name } fragment Unused2 on Human { name } errors: - message: Fragment "Unused1" is never used. locations: - {line: 22, column: 7} - message: Fragment "Unused2" is never used. locations: - {line: 25, column: 7} - name: contains unknown fragments with ref cycle rule: NoUnusedFragments schema: 0 query: |2- query Foo { human(id: 4) { ...HumanFields1 } } query Bar { human(id: 4) { ...HumanFields2 } } fragment HumanFields1 on Human { name ...HumanFields3 } fragment HumanFields2 on Human { name } fragment HumanFields3 on Human { name } fragment Unused1 on Human { name ...Unused2 } fragment Unused2 on Human { name ...Unused1 } errors: - message: Fragment "Unused1" is never used. locations: - {line: 22, column: 7} - message: Fragment "Unused2" is never used. locations: - {line: 26, column: 7} - name: contains unknown and undef fragments rule: NoUnusedFragments schema: 0 query: |2- query Foo { human(id: 4) { ...bar } } fragment foo on Human { name } errors: - message: Fragment "foo" is never used. locations: - {line: 7, column: 7} gqlparser-2.5.1/validator/imported/spec/NoUnusedVariablesRule.spec.yml000066400000000000000000000120171430663104200261560ustar00rootroot00000000000000- name: uses all variables rule: NoUnusedVariables schema: 0 query: |2- query ($a: String, $b: String, $c: String) { field(a: $a, b: $b, c: $c) } errors: [] - name: uses all variables deeply rule: NoUnusedVariables schema: 0 query: |2- query Foo($a: String, $b: String, $c: String) { field(a: $a) { field(b: $b) { field(c: $c) } } } errors: [] - name: uses all variables deeply in inline fragments rule: NoUnusedVariables schema: 0 query: |2- query Foo($a: String, $b: String, $c: String) { ... on Type { field(a: $a) { field(b: $b) { ... on Type { field(c: $c) } } } } } errors: [] - name: uses all variables in fragments rule: NoUnusedVariables schema: 0 query: |2- query Foo($a: String, $b: String, $c: String) { ...FragA } fragment FragA on Type { field(a: $a) { ...FragB } } fragment FragB on Type { field(b: $b) { ...FragC } } fragment FragC on Type { field(c: $c) } errors: [] - name: variable used by fragment in multiple operations rule: NoUnusedVariables schema: 0 query: |2- query Foo($a: String) { ...FragA } query Bar($b: String) { ...FragB } fragment FragA on Type { field(a: $a) } fragment FragB on Type { field(b: $b) } errors: [] - name: variable used by recursive fragment rule: NoUnusedVariables schema: 0 query: |2- query Foo($a: String) { ...FragA } fragment FragA on Type { field(a: $a) { ...FragA } } errors: [] - name: variable not used rule: NoUnusedVariables schema: 0 query: |2- query ($a: String, $b: String, $c: String) { field(a: $a, b: $b) } errors: - message: Variable "$c" is never used. locations: - {line: 2, column: 38} - name: multiple variables not used rule: NoUnusedVariables schema: 0 query: |2- query Foo($a: String, $b: String, $c: String) { field(b: $b) } errors: - message: Variable "$a" is never used in operation "Foo". locations: - {line: 2, column: 17} - message: Variable "$c" is never used in operation "Foo". locations: - {line: 2, column: 41} - name: variable not used in fragments rule: NoUnusedVariables schema: 0 query: |2- query Foo($a: String, $b: String, $c: String) { ...FragA } fragment FragA on Type { field(a: $a) { ...FragB } } fragment FragB on Type { field(b: $b) { ...FragC } } fragment FragC on Type { field } errors: - message: Variable "$c" is never used in operation "Foo". locations: - {line: 2, column: 41} - name: multiple variables not used in fragments rule: NoUnusedVariables schema: 0 query: |2- query Foo($a: String, $b: String, $c: String) { ...FragA } fragment FragA on Type { field { ...FragB } } fragment FragB on Type { field(b: $b) { ...FragC } } fragment FragC on Type { field } errors: - message: Variable "$a" is never used in operation "Foo". locations: - {line: 2, column: 17} - message: Variable "$c" is never used in operation "Foo". locations: - {line: 2, column: 41} - name: variable not used by unreferenced fragment rule: NoUnusedVariables schema: 0 query: |2- query Foo($b: String) { ...FragA } fragment FragA on Type { field(a: $a) } fragment FragB on Type { field(b: $b) } errors: - message: Variable "$b" is never used in operation "Foo". locations: - {line: 2, column: 17} - name: variable not used by fragment used by other operation rule: NoUnusedVariables schema: 0 query: |2- query Foo($b: String) { ...FragA } query Bar($a: String) { ...FragB } fragment FragA on Type { field(a: $a) } fragment FragB on Type { field(b: $b) } errors: - message: Variable "$b" is never used in operation "Foo". locations: - {line: 2, column: 17} - message: Variable "$a" is never used in operation "Bar". locations: - {line: 5, column: 17} gqlparser-2.5.1/validator/imported/spec/OverlappingFieldsCanBeMergedRule.spec.yml000066400000000000000000000610621430663104200302230ustar00rootroot00000000000000- name: unique fields rule: OverlappingFieldsCanBeMerged schema: 0 query: |2- fragment uniqueFields on Dog { name nickname } errors: [] - name: identical fields rule: OverlappingFieldsCanBeMerged schema: 0 query: |2- fragment mergeIdenticalFields on Dog { name name } errors: [] - name: identical fields with identical args rule: OverlappingFieldsCanBeMerged schema: 0 query: |2- fragment mergeIdenticalFieldsWithIdenticalArgs on Dog { doesKnowCommand(dogCommand: SIT) doesKnowCommand(dogCommand: SIT) } errors: [] - name: identical fields with identical directives rule: OverlappingFieldsCanBeMerged schema: 0 query: |2- fragment mergeSameFieldsWithSameDirectives on Dog { name @include(if: true) name @include(if: true) } errors: [] - name: different args with different aliases rule: OverlappingFieldsCanBeMerged schema: 0 query: |2- fragment differentArgsWithDifferentAliases on Dog { knowsSit: doesKnowCommand(dogCommand: SIT) knowsDown: doesKnowCommand(dogCommand: DOWN) } errors: [] - name: different directives with different aliases rule: OverlappingFieldsCanBeMerged schema: 0 query: |2- fragment differentDirectivesWithDifferentAliases on Dog { nameIfTrue: name @include(if: true) nameIfFalse: name @include(if: false) } errors: [] - name: different skip/include directives accepted rule: OverlappingFieldsCanBeMerged schema: 0 query: |2- fragment differentDirectivesWithDifferentAliases on Dog { name @include(if: true) name @include(if: false) } errors: [] - name: Same aliases with different field targets rule: OverlappingFieldsCanBeMerged schema: 0 query: |2- fragment sameAliasesWithDifferentFieldTargets on Dog { fido: name fido: nickname } errors: - message: Fields "fido" conflict because "name" and "nickname" are different fields. Use different aliases on the fields to fetch both if this was intentional. locations: - {line: 3, column: 9} - {line: 4, column: 9} - name: Same aliases allowed on non-overlapping fields rule: OverlappingFieldsCanBeMerged schema: 0 query: |2- fragment sameAliasesWithDifferentFieldTargets on Pet { ... on Dog { name } ... on Cat { name: nickname } } errors: [] - name: Alias masking direct field access rule: OverlappingFieldsCanBeMerged schema: 0 query: |2- fragment aliasMaskingDirectFieldAccess on Dog { name: nickname name } errors: - message: Fields "name" conflict because "nickname" and "name" are different fields. Use different aliases on the fields to fetch both if this was intentional. locations: - {line: 3, column: 9} - {line: 4, column: 9} - name: different args, second adds an argument rule: OverlappingFieldsCanBeMerged schema: 0 query: |2- fragment conflictingArgs on Dog { doesKnowCommand doesKnowCommand(dogCommand: HEEL) } errors: - message: Fields "doesKnowCommand" conflict because they have differing arguments. Use different aliases on the fields to fetch both if this was intentional. locations: - {line: 3, column: 9} - {line: 4, column: 9} - name: different args, second missing an argument rule: OverlappingFieldsCanBeMerged schema: 0 query: |2- fragment conflictingArgs on Dog { doesKnowCommand(dogCommand: SIT) doesKnowCommand } errors: - message: Fields "doesKnowCommand" conflict because they have differing arguments. Use different aliases on the fields to fetch both if this was intentional. locations: - {line: 3, column: 9} - {line: 4, column: 9} - name: conflicting arg values rule: OverlappingFieldsCanBeMerged schema: 0 query: |2- fragment conflictingArgs on Dog { doesKnowCommand(dogCommand: SIT) doesKnowCommand(dogCommand: HEEL) } errors: - message: Fields "doesKnowCommand" conflict because they have differing arguments. Use different aliases on the fields to fetch both if this was intentional. locations: - {line: 3, column: 9} - {line: 4, column: 9} - name: conflicting arg names rule: OverlappingFieldsCanBeMerged schema: 0 query: |2- fragment conflictingArgs on Dog { isAtLocation(x: 0) isAtLocation(y: 0) } errors: - message: Fields "isAtLocation" conflict because they have differing arguments. Use different aliases on the fields to fetch both if this was intentional. locations: - {line: 3, column: 9} - {line: 4, column: 9} - name: allows different args where no conflict is possible rule: OverlappingFieldsCanBeMerged schema: 0 query: |2- fragment conflictingArgs on Pet { ... on Dog { name(surname: true) } ... on Cat { name } } errors: [] - name: allows different order of args rule: OverlappingFieldsCanBeMerged schema: 10 query: |2- { someField(a: null, b: null) someField(b: null, a: null) } errors: [] - name: allows different order of input object fields in arg values rule: OverlappingFieldsCanBeMerged schema: 11 query: |2- { someField(arg: { a: null, b: null }) someField(arg: { b: null, a: null }) } errors: [] - name: encounters conflict in fragments rule: OverlappingFieldsCanBeMerged schema: 0 query: |2- { ...A ...B } fragment A on Type { x: a } fragment B on Type { x: b } errors: - message: Fields "x" conflict because "a" and "b" are different fields. Use different aliases on the fields to fetch both if this was intentional. locations: - {line: 7, column: 9} - {line: 10, column: 9} - name: reports each conflict once rule: OverlappingFieldsCanBeMerged schema: 0 query: |2- { f1 { ...A ...B } f2 { ...B ...A } f3 { ...A ...B x: c } } fragment A on Type { x: a } fragment B on Type { x: b } errors: - message: Fields "x" conflict because "a" and "b" are different fields. Use different aliases on the fields to fetch both if this was intentional. locations: - {line: 18, column: 9} - {line: 21, column: 9} - message: Fields "x" conflict because "c" and "a" are different fields. Use different aliases on the fields to fetch both if this was intentional. locations: - {line: 14, column: 11} - {line: 18, column: 9} - message: Fields "x" conflict because "c" and "b" are different fields. Use different aliases on the fields to fetch both if this was intentional. locations: - {line: 14, column: 11} - {line: 21, column: 9} - name: deep conflict rule: OverlappingFieldsCanBeMerged schema: 0 query: |2- { field { x: a }, field { x: b } } errors: - message: Fields "field" conflict because subfields "x" conflict because "a" and "b" are different fields. Use different aliases on the fields to fetch both if this was intentional. locations: - {line: 3, column: 9} - {line: 4, column: 11} - {line: 6, column: 9} - {line: 7, column: 11} - name: deep conflict with multiple issues rule: OverlappingFieldsCanBeMerged schema: 0 query: |2- { field { x: a y: c }, field { x: b y: d } } errors: - message: Fields "field" conflict because subfields "x" conflict because "a" and "b" are different fields and subfields "y" conflict because "c" and "d" are different fields. Use different aliases on the fields to fetch both if this was intentional. locations: - {line: 3, column: 9} - {line: 4, column: 11} - {line: 5, column: 11} - {line: 7, column: 9} - {line: 8, column: 11} - {line: 9, column: 11} - name: very deep conflict rule: OverlappingFieldsCanBeMerged schema: 0 query: |2- { field { deepField { x: a } }, field { deepField { x: b } } } errors: - message: Fields "field" conflict because subfields "deepField" conflict because subfields "x" conflict because "a" and "b" are different fields. Use different aliases on the fields to fetch both if this was intentional. locations: - {line: 3, column: 9} - {line: 4, column: 11} - {line: 5, column: 13} - {line: 8, column: 9} - {line: 9, column: 11} - {line: 10, column: 13} - name: reports deep conflict to nearest common ancestor rule: OverlappingFieldsCanBeMerged schema: 0 query: |2- { field { deepField { x: a } deepField { x: b } }, field { deepField { y } } } errors: - message: Fields "deepField" conflict because subfields "x" conflict because "a" and "b" are different fields. Use different aliases on the fields to fetch both if this was intentional. locations: - {line: 4, column: 11} - {line: 5, column: 13} - {line: 7, column: 11} - {line: 8, column: 13} - name: reports deep conflict to nearest common ancestor in fragments rule: OverlappingFieldsCanBeMerged schema: 0 query: |2- { field { ...F } field { ...F } } fragment F on T { deepField { deeperField { x: a } deeperField { x: b } }, deepField { deeperField { y } } } errors: - message: Fields "deeperField" conflict because subfields "x" conflict because "a" and "b" are different fields. Use different aliases on the fields to fetch both if this was intentional. locations: - {line: 12, column: 11} - {line: 13, column: 13} - {line: 15, column: 11} - {line: 16, column: 13} - name: reports deep conflict in nested fragments rule: OverlappingFieldsCanBeMerged schema: 0 query: |2- { field { ...F } field { ...I } } fragment F on T { x: a ...G } fragment G on T { y: c } fragment I on T { y: d ...J } fragment J on T { x: b } errors: - message: Fields "field" conflict because subfields "x" conflict because "a" and "b" are different fields and subfields "y" conflict because "c" and "d" are different fields. Use different aliases on the fields to fetch both if this was intentional. locations: - {line: 3, column: 9} - {line: 11, column: 9} - {line: 15, column: 9} - {line: 6, column: 9} - {line: 22, column: 9} - {line: 18, column: 9} - name: ignores unknown fragments rule: OverlappingFieldsCanBeMerged schema: 0 query: |2- { field ...Unknown ...Known } fragment Known on T { field ...OtherUnknown } errors: [] - name: return types must be unambiguous/conflicting return types which potentially overlap rule: OverlappingFieldsCanBeMerged schema: 12 query: |2- { someBox { ...on IntBox { scalar } ...on NonNullStringBox1 { scalar } } } errors: - message: Fields "scalar" conflict because they return conflicting types "Int" and "String!". Use different aliases on the fields to fetch both if this was intentional. locations: - {line: 5, column: 17} - {line: 8, column: 17} - name: return types must be unambiguous/compatible return shapes on different return types rule: OverlappingFieldsCanBeMerged schema: 12 query: |2- { someBox { ... on SomeBox { deepBox { unrelatedField } } ... on StringBox { deepBox { unrelatedField } } } } errors: [] - name: return types must be unambiguous/disallows differing return types despite no overlap rule: OverlappingFieldsCanBeMerged schema: 12 query: |2- { someBox { ... on IntBox { scalar } ... on StringBox { scalar } } } errors: - message: Fields "scalar" conflict because they return conflicting types "Int" and "String". Use different aliases on the fields to fetch both if this was intentional. locations: - {line: 5, column: 17} - {line: 8, column: 17} - name: return types must be unambiguous/reports correctly when a non-exclusive follows an exclusive rule: OverlappingFieldsCanBeMerged schema: 12 query: |2- { someBox { ... on IntBox { deepBox { ...X } } } someBox { ... on StringBox { deepBox { ...Y } } } memoed: someBox { ... on IntBox { deepBox { ...X } } } memoed: someBox { ... on StringBox { deepBox { ...Y } } } other: someBox { ...X } other: someBox { ...Y } } fragment X on SomeBox { scalar } fragment Y on SomeBox { scalar: unrelatedField } errors: - message: Fields "other" conflict because subfields "scalar" conflict because "scalar" and "unrelatedField" are different fields. Use different aliases on the fields to fetch both if this was intentional. locations: - {line: 31, column: 13} - {line: 39, column: 13} - {line: 34, column: 13} - {line: 42, column: 13} - name: return types must be unambiguous/disallows differing return type nullability despite no overlap rule: OverlappingFieldsCanBeMerged schema: 12 query: |2- { someBox { ... on NonNullStringBox1 { scalar } ... on StringBox { scalar } } } errors: - message: Fields "scalar" conflict because they return conflicting types "String!" and "String". Use different aliases on the fields to fetch both if this was intentional. locations: - {line: 5, column: 17} - {line: 8, column: 17} - name: return types must be unambiguous/disallows differing return type list despite no overlap rule: OverlappingFieldsCanBeMerged schema: 12 query: |2- { someBox { ... on IntBox { box: listStringBox { scalar } } ... on StringBox { box: stringBox { scalar } } } } errors: - message: Fields "box" conflict because they return conflicting types "[StringBox]" and "StringBox". Use different aliases on the fields to fetch both if this was intentional. locations: - {line: 5, column: 17} - {line: 10, column: 17} - name: return types must be unambiguous/disallows differing return type list despite no overlap rule: OverlappingFieldsCanBeMerged schema: 12 query: |2- { someBox { ... on IntBox { box: stringBox { scalar } } ... on StringBox { box: listStringBox { scalar } } } } errors: - message: Fields "box" conflict because they return conflicting types "StringBox" and "[StringBox]". Use different aliases on the fields to fetch both if this was intentional. locations: - {line: 5, column: 17} - {line: 10, column: 17} - name: return types must be unambiguous/disallows differing subfields rule: OverlappingFieldsCanBeMerged schema: 12 query: |2- { someBox { ... on IntBox { box: stringBox { val: scalar val: unrelatedField } } ... on StringBox { box: stringBox { val: scalar } } } } errors: - message: Fields "val" conflict because "scalar" and "unrelatedField" are different fields. Use different aliases on the fields to fetch both if this was intentional. locations: - {line: 6, column: 19} - {line: 7, column: 19} - name: return types must be unambiguous/disallows differing deep return types despite no overlap rule: OverlappingFieldsCanBeMerged schema: 12 query: |2- { someBox { ... on IntBox { box: stringBox { scalar } } ... on StringBox { box: intBox { scalar } } } } errors: - message: Fields "box" conflict because subfields "scalar" conflict because they return conflicting types "String" and "Int". Use different aliases on the fields to fetch both if this was intentional. locations: - {line: 5, column: 17} - {line: 6, column: 19} - {line: 10, column: 17} - {line: 11, column: 19} - name: return types must be unambiguous/allows non-conflicting overlapping types rule: OverlappingFieldsCanBeMerged schema: 12 query: |2- { someBox { ... on IntBox { scalar: unrelatedField } ... on StringBox { scalar } } } errors: [] - name: return types must be unambiguous/same wrapped scalar return types rule: OverlappingFieldsCanBeMerged schema: 12 query: |2- { someBox { ...on NonNullStringBox1 { scalar } ...on NonNullStringBox2 { scalar } } } errors: [] - name: return types must be unambiguous/allows inline fragments without type condition rule: OverlappingFieldsCanBeMerged schema: 12 query: |2- { a ... { a } } errors: [] - name: return types must be unambiguous/compares deep types including list rule: OverlappingFieldsCanBeMerged schema: 12 query: |2- { connection { ...edgeID edges { node { id: name } } } } fragment edgeID on Connection { edges { node { id } } } errors: - message: Fields "edges" conflict because subfields "node" conflict because subfields "id" conflict because "name" and "id" are different fields. Use different aliases on the fields to fetch both if this was intentional. locations: - {line: 5, column: 15} - {line: 6, column: 17} - {line: 7, column: 19} - {line: 14, column: 13} - {line: 15, column: 15} - {line: 16, column: 17} - name: return types must be unambiguous/ignores unknown types rule: OverlappingFieldsCanBeMerged schema: 12 query: |2- { someBox { ...on UnknownType { scalar } ...on NonNullStringBox2 { scalar } } } errors: [] - name: return types must be unambiguous/works for field names that are JS keywords rule: OverlappingFieldsCanBeMerged schema: 13 query: |2- { foo { constructor } } errors: [] - name: does not infinite loop on recursive fragment rule: OverlappingFieldsCanBeMerged schema: 0 query: |2- { ...fragA } fragment fragA on Human { name, relatives { name, ...fragA } } errors: [] - name: does not infinite loop on immediately recursive fragment rule: OverlappingFieldsCanBeMerged schema: 0 query: |2- { ...fragA } fragment fragA on Human { name, ...fragA } errors: [] - name: does not infinite loop on recursive fragment with a field named after fragment rule: OverlappingFieldsCanBeMerged schema: 0 query: |2- { ...fragA fragA } fragment fragA on Query { ...fragA } errors: [] - name: finds invalid cases even with field named after fragment rule: OverlappingFieldsCanBeMerged schema: 0 query: |2- { fragA ...fragA } fragment fragA on Type { fragA: b } errors: - message: Fields "fragA" conflict because "fragA" and "b" are different fields. Use different aliases on the fields to fetch both if this was intentional. locations: - {line: 3, column: 9} - {line: 8, column: 9} - name: does not infinite loop on transitively recursive fragment rule: OverlappingFieldsCanBeMerged schema: 0 query: |2- { ...fragA fragB } fragment fragA on Human { name, ...fragB } fragment fragB on Human { name, ...fragC } fragment fragC on Human { name, ...fragA } errors: [] - name: finds invalid case even with immediately recursive fragment rule: OverlappingFieldsCanBeMerged schema: 0 query: |2- fragment sameAliasesWithDifferentFieldTargets on Dog { ...sameAliasesWithDifferentFieldTargets fido: name fido: nickname } errors: - message: Fields "fido" conflict because "name" and "nickname" are different fields. Use different aliases on the fields to fetch both if this was intentional. locations: - {line: 4, column: 9} - {line: 5, column: 9} gqlparser-2.5.1/validator/imported/spec/PossibleFragmentSpreadsRule.spec.yml000066400000000000000000000167601430663104200273640ustar00rootroot00000000000000- name: of the same object rule: PossibleFragmentSpreads schema: 14 query: |2- fragment objectWithinObject on Dog { ...dogFragment } fragment dogFragment on Dog { barkVolume } errors: [] - name: of the same object with inline fragment rule: PossibleFragmentSpreads schema: 14 query: |2- fragment objectWithinObjectAnon on Dog { ... on Dog { barkVolume } } errors: [] - name: object into an implemented interface rule: PossibleFragmentSpreads schema: 14 query: |2- fragment objectWithinInterface on Pet { ...dogFragment } fragment dogFragment on Dog { barkVolume } errors: [] - name: object into containing union rule: PossibleFragmentSpreads schema: 14 query: |2- fragment objectWithinUnion on CatOrDog { ...dogFragment } fragment dogFragment on Dog { barkVolume } errors: [] - name: union into contained object rule: PossibleFragmentSpreads schema: 14 query: |2- fragment unionWithinObject on Dog { ...catOrDogFragment } fragment catOrDogFragment on CatOrDog { __typename } errors: [] - name: union into overlapping interface rule: PossibleFragmentSpreads schema: 14 query: |2- fragment unionWithinInterface on Pet { ...catOrDogFragment } fragment catOrDogFragment on CatOrDog { __typename } errors: [] - name: union into overlapping union rule: PossibleFragmentSpreads schema: 14 query: |2- fragment unionWithinUnion on DogOrHuman { ...catOrDogFragment } fragment catOrDogFragment on CatOrDog { __typename } errors: [] - name: interface into implemented object rule: PossibleFragmentSpreads schema: 14 query: |2- fragment interfaceWithinObject on Dog { ...petFragment } fragment petFragment on Pet { name } errors: [] - name: interface into overlapping interface rule: PossibleFragmentSpreads schema: 14 query: |2- fragment interfaceWithinInterface on Pet { ...beingFragment } fragment beingFragment on Being { name } errors: [] - name: interface into overlapping interface in inline fragment rule: PossibleFragmentSpreads schema: 14 query: |2- fragment interfaceWithinInterface on Pet { ... on Being { name } } errors: [] - name: interface into overlapping union rule: PossibleFragmentSpreads schema: 14 query: |2- fragment interfaceWithinUnion on CatOrDog { ...petFragment } fragment petFragment on Pet { name } errors: [] - name: ignores incorrect type (caught by FragmentsOnCompositeTypesRule) rule: PossibleFragmentSpreads schema: 14 query: |2- fragment petFragment on Pet { ...badInADifferentWay } fragment badInADifferentWay on String { name } errors: [] - name: ignores unknown fragments (caught by KnownFragmentNamesRule) rule: PossibleFragmentSpreads schema: 14 query: |2- fragment petFragment on Pet { ...UnknownFragment } errors: [] - name: different object into object rule: PossibleFragmentSpreads schema: 14 query: |2- fragment invalidObjectWithinObject on Cat { ...dogFragment } fragment dogFragment on Dog { barkVolume } errors: - message: Fragment "dogFragment" cannot be spread here as objects of type "Cat" can never be of type "Dog". locations: - {line: 2, column: 51} - name: different object into object in inline fragment rule: PossibleFragmentSpreads schema: 14 query: |2- fragment invalidObjectWithinObjectAnon on Cat { ... on Dog { barkVolume } } errors: - message: Fragment cannot be spread here as objects of type "Cat" can never be of type "Dog". locations: - {line: 3, column: 9} - name: object into not implementing interface rule: PossibleFragmentSpreads schema: 14 query: |2- fragment invalidObjectWithinInterface on Pet { ...humanFragment } fragment humanFragment on Human { pets { name } } errors: - message: Fragment "humanFragment" cannot be spread here as objects of type "Pet" can never be of type "Human". locations: - {line: 2, column: 54} - name: object into not containing union rule: PossibleFragmentSpreads schema: 14 query: |2- fragment invalidObjectWithinUnion on CatOrDog { ...humanFragment } fragment humanFragment on Human { pets { name } } errors: - message: Fragment "humanFragment" cannot be spread here as objects of type "CatOrDog" can never be of type "Human". locations: - {line: 2, column: 55} - name: union into not contained object rule: PossibleFragmentSpreads schema: 14 query: |2- fragment invalidUnionWithinObject on Human { ...catOrDogFragment } fragment catOrDogFragment on CatOrDog { __typename } errors: - message: Fragment "catOrDogFragment" cannot be spread here as objects of type "Human" can never be of type "CatOrDog". locations: - {line: 2, column: 52} - name: union into non overlapping interface rule: PossibleFragmentSpreads schema: 14 query: |2- fragment invalidUnionWithinInterface on Pet { ...humanOrAlienFragment } fragment humanOrAlienFragment on HumanOrAlien { __typename } errors: - message: Fragment "humanOrAlienFragment" cannot be spread here as objects of type "Pet" can never be of type "HumanOrAlien". locations: - {line: 2, column: 53} - name: union into non overlapping union rule: PossibleFragmentSpreads schema: 14 query: |2- fragment invalidUnionWithinUnion on CatOrDog { ...humanOrAlienFragment } fragment humanOrAlienFragment on HumanOrAlien { __typename } errors: - message: Fragment "humanOrAlienFragment" cannot be spread here as objects of type "CatOrDog" can never be of type "HumanOrAlien". locations: - {line: 2, column: 54} - name: interface into non implementing object rule: PossibleFragmentSpreads schema: 14 query: |2- fragment invalidInterfaceWithinObject on Cat { ...intelligentFragment } fragment intelligentFragment on Intelligent { iq } errors: - message: Fragment "intelligentFragment" cannot be spread here as objects of type "Cat" can never be of type "Intelligent". locations: - {line: 2, column: 54} - name: interface into non overlapping interface rule: PossibleFragmentSpreads schema: 14 query: |2- fragment invalidInterfaceWithinInterface on Pet { ...intelligentFragment } fragment intelligentFragment on Intelligent { iq } errors: - message: Fragment "intelligentFragment" cannot be spread here as objects of type "Pet" can never be of type "Intelligent". locations: - {line: 3, column: 9} - name: interface into non overlapping interface in inline fragment rule: PossibleFragmentSpreads schema: 14 query: |2- fragment invalidInterfaceWithinInterfaceAnon on Pet { ...on Intelligent { iq } } errors: - message: Fragment cannot be spread here as objects of type "Pet" can never be of type "Intelligent". locations: - {line: 3, column: 9} - name: interface into non overlapping union rule: PossibleFragmentSpreads schema: 14 query: |2- fragment invalidInterfaceWithinUnion on HumanOrAlien { ...petFragment } fragment petFragment on Pet { name } errors: - message: Fragment "petFragment" cannot be spread here as objects of type "HumanOrAlien" can never be of type "Pet". locations: - {line: 2, column: 62} gqlparser-2.5.1/validator/imported/spec/PossibleTypeExtensionsRule.spec.yml000066400000000000000000000000031430663104200272570ustar00rootroot00000000000000[] gqlparser-2.5.1/validator/imported/spec/ProvidedRequiredArgumentsRule.spec.yml000066400000000000000000000125431430663104200277340ustar00rootroot00000000000000- name: ignores unknown arguments rule: ProvidedRequiredArguments schema: 0 query: |2- { dog { isHouseTrained(unknownArgument: true) } } errors: [] - name: Valid non-nullable value/Arg on optional arg rule: ProvidedRequiredArguments schema: 0 query: |2- { dog { isHouseTrained(atOtherHomes: true) } } errors: [] - name: Valid non-nullable value/No Arg on optional arg rule: ProvidedRequiredArguments schema: 0 query: |2- { dog { isHouseTrained } } errors: [] - name: Valid non-nullable value/No arg on non-null field with default rule: ProvidedRequiredArguments schema: 0 query: |2- { complicatedArgs { nonNullFieldWithDefault } } errors: [] - name: Valid non-nullable value/Multiple args rule: ProvidedRequiredArguments schema: 0 query: |2- { complicatedArgs { multipleReqs(req1: 1, req2: 2) } } errors: [] - name: Valid non-nullable value/Multiple args reverse order rule: ProvidedRequiredArguments schema: 0 query: |2- { complicatedArgs { multipleReqs(req2: 2, req1: 1) } } errors: [] - name: Valid non-nullable value/No args on multiple optional rule: ProvidedRequiredArguments schema: 0 query: |2- { complicatedArgs { multipleOpts } } errors: [] - name: Valid non-nullable value/One arg on multiple optional rule: ProvidedRequiredArguments schema: 0 query: |2- { complicatedArgs { multipleOpts(opt1: 1) } } errors: [] - name: Valid non-nullable value/Second arg on multiple optional rule: ProvidedRequiredArguments schema: 0 query: |2- { complicatedArgs { multipleOpts(opt2: 1) } } errors: [] - name: Valid non-nullable value/Multiple required args on mixedList rule: ProvidedRequiredArguments schema: 0 query: |2- { complicatedArgs { multipleOptAndReq(req1: 3, req2: 4) } } errors: [] - name: Valid non-nullable value/Multiple required and one optional arg on mixedList rule: ProvidedRequiredArguments schema: 0 query: |2- { complicatedArgs { multipleOptAndReq(req1: 3, req2: 4, opt1: 5) } } errors: [] - name: Valid non-nullable value/All required and optional args on mixedList rule: ProvidedRequiredArguments schema: 0 query: |2- { complicatedArgs { multipleOptAndReq(req1: 3, req2: 4, opt1: 5, opt2: 6) } } errors: [] - name: Invalid non-nullable value/Missing one non-nullable argument rule: ProvidedRequiredArguments schema: 0 query: |2- { complicatedArgs { multipleReqs(req2: 2) } } errors: - message: Field "multipleReqs" argument "req1" of type "Int!" is required, but it was not provided. locations: - {line: 4, column: 13} - name: Invalid non-nullable value/Missing multiple non-nullable arguments rule: ProvidedRequiredArguments schema: 0 query: |2- { complicatedArgs { multipleReqs } } errors: - message: Field "multipleReqs" argument "req1" of type "Int!" is required, but it was not provided. locations: - {line: 4, column: 13} - message: Field "multipleReqs" argument "req2" of type "Int!" is required, but it was not provided. locations: - {line: 4, column: 13} - name: Invalid non-nullable value/Incorrect value and missing argument rule: ProvidedRequiredArguments schema: 0 query: |2- { complicatedArgs { multipleReqs(req1: "one") } } errors: - message: Field "multipleReqs" argument "req2" of type "Int!" is required, but it was not provided. locations: - {line: 4, column: 13} - name: Directive arguments/ignores unknown directives rule: ProvidedRequiredArguments schema: 0 query: |2- { dog @unknown } errors: [] - name: Directive arguments/with directives of valid types rule: ProvidedRequiredArguments schema: 0 query: |2- { dog @include(if: true) { name } human @skip(if: false) { name } } errors: [] - name: Directive arguments/with directive with missing types rule: ProvidedRequiredArguments schema: 0 query: |2- { dog @include { name @skip } } errors: - message: Directive "@include" argument "if" of type "Boolean!" is required, but it was not provided. locations: - {line: 3, column: 15} - message: Directive "@skip" argument "if" of type "Boolean!" is required, but it was not provided. locations: - {line: 4, column: 18} gqlparser-2.5.1/validator/imported/spec/ScalarLeafsRule.spec.yml000066400000000000000000000056051430663104200247520ustar00rootroot00000000000000- name: valid scalar selection rule: ScalarLeafs schema: 0 query: |2- fragment scalarSelection on Dog { barks } errors: [] - name: object type missing selection rule: ScalarLeafs schema: 0 query: |2- query directQueryOnObjectWithoutSubFields { human } errors: - message: Field "human" of type "Human" must have a selection of subfields. Did you mean "human { ... }"? locations: - {line: 3, column: 9} - name: interface type missing selection rule: ScalarLeafs schema: 0 query: |2- { human { pets } } errors: - message: Field "pets" of type "[Pet]" must have a selection of subfields. Did you mean "pets { ... }"? locations: - {line: 3, column: 17} - name: valid scalar selection with args rule: ScalarLeafs schema: 0 query: |2- fragment scalarSelectionWithArgs on Dog { doesKnowCommand(dogCommand: SIT) } errors: [] - name: scalar selection not allowed on Boolean rule: ScalarLeafs schema: 0 query: |2- fragment scalarSelectionsNotAllowedOnBoolean on Dog { barks { sinceWhen } } errors: - message: Field "barks" must not have a selection since type "Boolean" has no subfields. locations: - {line: 3, column: 15} - name: scalar selection not allowed on Enum rule: ScalarLeafs schema: 0 query: |2- fragment scalarSelectionsNotAllowedOnEnum on Cat { furColor { inHexDec } } errors: - message: Field "furColor" must not have a selection since type "FurColor" has no subfields. locations: - {line: 3, column: 18} - name: scalar selection not allowed with args rule: ScalarLeafs schema: 0 query: |2- fragment scalarSelectionsNotAllowedWithArgs on Dog { doesKnowCommand(dogCommand: SIT) { sinceWhen } } errors: - message: Field "doesKnowCommand" must not have a selection since type "Boolean" has no subfields. locations: - {line: 3, column: 42} - name: Scalar selection not allowed with directives rule: ScalarLeafs schema: 0 query: |2- fragment scalarSelectionsNotAllowedWithDirectives on Dog { name @include(if: true) { isAlsoHumanName } } errors: - message: Field "name" must not have a selection since type "String" has no subfields. locations: - {line: 3, column: 33} - name: Scalar selection not allowed with directives and args rule: ScalarLeafs schema: 0 query: |2- fragment scalarSelectionsNotAllowedWithDirectivesAndArgs on Dog { doesKnowCommand(dogCommand: SIT) @include(if: true) { sinceWhen } } errors: - message: Field "doesKnowCommand" must not have a selection since type "Boolean" has no subfields. locations: - {line: 3, column: 61} gqlparser-2.5.1/validator/imported/spec/SingleFieldSubscriptionsRule.spec.yml000066400000000000000000000140111430663104200275360ustar00rootroot00000000000000- name: valid subscription rule: SingleFieldSubscriptions schema: 15 query: |2- subscription ImportantEmails { importantEmails } errors: [] - name: valid subscription with fragment rule: SingleFieldSubscriptions schema: 15 query: |2- subscription sub { ...newMessageFields } fragment newMessageFields on SubscriptionRoot { newMessage { body sender } } errors: [] - name: valid subscription with fragment and field rule: SingleFieldSubscriptions schema: 15 query: |2- subscription sub { newMessage { body } ...newMessageFields } fragment newMessageFields on SubscriptionRoot { newMessage { body sender } } errors: [] - name: fails with more than one root field rule: SingleFieldSubscriptions schema: 15 query: |2- subscription ImportantEmails { importantEmails notImportantEmails } errors: - message: Subscription "ImportantEmails" must select only one top level field. locations: - {line: 4, column: 9} - name: fails with more than one root field including introspection rule: SingleFieldSubscriptions schema: 15 query: |2- subscription ImportantEmails { importantEmails __typename } errors: - message: Subscription "ImportantEmails" must select only one top level field. locations: - {line: 4, column: 9} - message: Subscription "ImportantEmails" must not select an introspection top level field. locations: - {line: 4, column: 9} - name: fails with more than one root field including aliased introspection via fragment rule: SingleFieldSubscriptions schema: 15 query: |2- subscription ImportantEmails { importantEmails ...Introspection } fragment Introspection on SubscriptionRoot { typename: __typename } errors: - message: Subscription "ImportantEmails" must select only one top level field. locations: - {line: 7, column: 9} - message: Subscription "ImportantEmails" must not select an introspection top level field. locations: - {line: 7, column: 9} - name: fails with many more than one root field rule: SingleFieldSubscriptions schema: 15 query: |2- subscription ImportantEmails { importantEmails notImportantEmails spamEmails } errors: - message: Subscription "ImportantEmails" must select only one top level field. locations: - {line: 4, column: 9} - {line: 5, column: 9} - name: fails with many more than one root field via fragments rule: SingleFieldSubscriptions schema: 15 query: |2- subscription ImportantEmails { importantEmails ... { more: moreImportantEmails } ...NotImportantEmails } fragment NotImportantEmails on SubscriptionRoot { notImportantEmails deleted: deletedEmails ...SpamEmails } fragment SpamEmails on SubscriptionRoot { spamEmails } errors: - message: Subscription "ImportantEmails" must select only one top level field. locations: - {line: 5, column: 11} - {line: 10, column: 9} - {line: 11, column: 9} - {line: 15, column: 9} - name: does not infinite loop on recursive fragments rule: SingleFieldSubscriptions schema: 15 query: |2- subscription NoInfiniteLoop { ...A } fragment A on SubscriptionRoot { ...A } errors: [] - name: fails with many more than one root field via fragments (anonymous) rule: SingleFieldSubscriptions schema: 15 query: |2- subscription { importantEmails ... { more: moreImportantEmails ...NotImportantEmails } ...NotImportantEmails } fragment NotImportantEmails on SubscriptionRoot { notImportantEmails deleted: deletedEmails ... { ... { archivedEmails } } ...SpamEmails } fragment SpamEmails on SubscriptionRoot { spamEmails ...NonExistentFragment } errors: - message: Anonymous Subscription must select only one top level field. locations: - {line: 5, column: 11} - {line: 11, column: 9} - {line: 12, column: 9} - {line: 15, column: 13} - {line: 21, column: 9} - name: fails with more than one root field in anonymous subscriptions rule: SingleFieldSubscriptions schema: 15 query: |2- subscription { importantEmails notImportantEmails } errors: - message: Anonymous Subscription must select only one top level field. locations: - {line: 4, column: 9} - name: fails with introspection field rule: SingleFieldSubscriptions schema: 15 query: |2- subscription ImportantEmails { __typename } errors: - message: Subscription "ImportantEmails" must not select an introspection top level field. locations: - {line: 3, column: 9} - name: fails with introspection field in anonymous subscription rule: SingleFieldSubscriptions schema: 15 query: |2- subscription { __typename } errors: - message: Anonymous Subscription must not select an introspection top level field. locations: - {line: 3, column: 9} - name: skips if not subscription type rule: SingleFieldSubscriptions schema: 16 query: |2- subscription { __typename } errors: [] gqlparser-2.5.1/validator/imported/spec/UniqueArgumentDefinitionNamesRule.spec.yml000066400000000000000000000000031430663104200305230ustar00rootroot00000000000000[] gqlparser-2.5.1/validator/imported/spec/UniqueArgumentNamesRule.spec.yml000066400000000000000000000056451430663104200265330ustar00rootroot00000000000000- name: no arguments on field rule: UniqueArgumentNames schema: 0 query: |2- { field } errors: [] - name: no arguments on directive rule: UniqueArgumentNames schema: 0 query: |2- { field @directive } errors: [] - name: argument on field rule: UniqueArgumentNames schema: 0 query: |2- { field(arg: "value") } errors: [] - name: argument on directive rule: UniqueArgumentNames schema: 0 query: |2- { field @directive(arg: "value") } errors: [] - name: same argument on two fields rule: UniqueArgumentNames schema: 0 query: |2- { one: field(arg: "value") two: field(arg: "value") } errors: [] - name: same argument on field and directive rule: UniqueArgumentNames schema: 0 query: |2- { field(arg: "value") @directive(arg: "value") } errors: [] - name: same argument on two directives rule: UniqueArgumentNames schema: 0 query: |2- { field @directive1(arg: "value") @directive2(arg: "value") } errors: [] - name: multiple field arguments rule: UniqueArgumentNames schema: 0 query: |2- { field(arg1: "value", arg2: "value", arg3: "value") } errors: [] - name: multiple directive arguments rule: UniqueArgumentNames schema: 0 query: |2- { field @directive(arg1: "value", arg2: "value", arg3: "value") } errors: [] - name: duplicate field arguments rule: UniqueArgumentNames schema: 0 query: |2- { field(arg1: "value", arg1: "value") } errors: - message: There can be only one argument named "arg1". locations: - {line: 3, column: 15} - {line: 3, column: 30} - name: many duplicate field arguments rule: UniqueArgumentNames schema: 0 query: |2- { field(arg1: "value", arg1: "value", arg1: "value") } errors: - message: There can be only one argument named "arg1". locations: - {line: 3, column: 15} - {line: 3, column: 30} - {line: 3, column: 45} - name: duplicate directive arguments rule: UniqueArgumentNames schema: 0 query: |2- { field @directive(arg1: "value", arg1: "value") } errors: - message: There can be only one argument named "arg1". locations: - {line: 3, column: 26} - {line: 3, column: 41} - name: many duplicate directive arguments rule: UniqueArgumentNames schema: 0 query: |2- { field @directive(arg1: "value", arg1: "value", arg1: "value") } errors: - message: There can be only one argument named "arg1". locations: - {line: 3, column: 26} - {line: 3, column: 41} - {line: 3, column: 56} gqlparser-2.5.1/validator/imported/spec/UniqueDirectiveNamesRule.spec.yml000066400000000000000000000000031430663104200266460ustar00rootroot00000000000000[] gqlparser-2.5.1/validator/imported/spec/UniqueDirectivesPerLocationRule.spec.yml000066400000000000000000000070631430663104200302220ustar00rootroot00000000000000- name: no directives rule: UniqueDirectivesPerLocation schema: 17 query: |2- fragment Test on Type { field } errors: [] - name: unique directives in different locations rule: UniqueDirectivesPerLocation schema: 17 query: |2- fragment Test on Type @directiveA { field @directiveB } errors: [] - name: unique directives in same locations rule: UniqueDirectivesPerLocation schema: 17 query: |2- fragment Test on Type @directiveA @directiveB { field @directiveA @directiveB } errors: [] - name: same directives in different locations rule: UniqueDirectivesPerLocation schema: 17 query: |2- fragment Test on Type @directiveA { field @directiveA } errors: [] - name: same directives in similar locations rule: UniqueDirectivesPerLocation schema: 17 query: |2- fragment Test on Type { field @directive field @directive } errors: [] - name: repeatable directives in same location rule: UniqueDirectivesPerLocation schema: 17 query: |2- fragment Test on Type @repeatable @repeatable { field @repeatable @repeatable } errors: [] - name: unknown directives must be ignored rule: UniqueDirectivesPerLocation schema: 17 query: |2- type Test @unknown @unknown { field: String! @unknown @unknown } extend type Test @unknown { anotherField: String! } errors: [] - name: duplicate directives in one location rule: UniqueDirectivesPerLocation schema: 17 query: |2- fragment Test on Type { field @directive @directive } errors: - message: The directive "@directive" can only be used once at this location. locations: - {line: 3, column: 15} - {line: 3, column: 26} - name: many duplicate directives in one location rule: UniqueDirectivesPerLocation schema: 17 query: |2- fragment Test on Type { field @directive @directive @directive } errors: - message: The directive "@directive" can only be used once at this location. locations: - {line: 3, column: 15} - {line: 3, column: 26} - message: The directive "@directive" can only be used once at this location. locations: - {line: 3, column: 15} - {line: 3, column: 37} - name: different duplicate directives in one location rule: UniqueDirectivesPerLocation schema: 17 query: |2- fragment Test on Type { field @directiveA @directiveB @directiveA @directiveB } errors: - message: The directive "@directiveA" can only be used once at this location. locations: - {line: 3, column: 15} - {line: 3, column: 39} - message: The directive "@directiveB" can only be used once at this location. locations: - {line: 3, column: 27} - {line: 3, column: 51} - name: duplicate directives in many locations rule: UniqueDirectivesPerLocation schema: 17 query: |2- fragment Test on Type @directive @directive { field @directive @directive } errors: - message: The directive "@directive" can only be used once at this location. locations: - {line: 2, column: 29} - {line: 2, column: 40} - message: The directive "@directive" can only be used once at this location. locations: - {line: 3, column: 15} - {line: 3, column: 26} gqlparser-2.5.1/validator/imported/spec/UniqueEnumValueNamesRule.spec.yml000066400000000000000000000000031430663104200266310ustar00rootroot00000000000000[] gqlparser-2.5.1/validator/imported/spec/UniqueFieldDefinitionNamesRule.spec.yml000066400000000000000000000000031430663104200277640ustar00rootroot00000000000000[] gqlparser-2.5.1/validator/imported/spec/UniqueFragmentNamesRule.spec.yml000066400000000000000000000037401430663104200265060ustar00rootroot00000000000000- name: no fragments rule: UniqueFragmentNames schema: 0 query: |2- { field } errors: [] - name: one fragment rule: UniqueFragmentNames schema: 0 query: |2- { ...fragA } fragment fragA on Type { field } errors: [] - name: many fragments rule: UniqueFragmentNames schema: 0 query: |2- { ...fragA ...fragB ...fragC } fragment fragA on Type { fieldA } fragment fragB on Type { fieldB } fragment fragC on Type { fieldC } errors: [] - name: inline fragments are always unique rule: UniqueFragmentNames schema: 0 query: |2- { ...on Type { fieldA } ...on Type { fieldB } } errors: [] - name: fragment and operation named the same rule: UniqueFragmentNames schema: 0 query: |2- query Foo { ...Foo } fragment Foo on Type { field } errors: [] - name: fragments named the same rule: UniqueFragmentNames schema: 0 query: |2- { ...fragA } fragment fragA on Type { fieldA } fragment fragA on Type { fieldB } errors: - message: There can be only one fragment named "fragA". locations: - {line: 5, column: 16} - {line: 8, column: 16} - name: fragments named the same without being referenced rule: UniqueFragmentNames schema: 0 query: |2- fragment fragA on Type { fieldA } fragment fragA on Type { fieldB } errors: - message: There can be only one fragment named "fragA". locations: - {line: 2, column: 16} - {line: 5, column: 16} gqlparser-2.5.1/validator/imported/spec/UniqueInputFieldNamesRule.spec.yml000066400000000000000000000037651430663104200270150ustar00rootroot00000000000000- name: input object with fields rule: UniqueInputFieldNames schema: 0 query: |2- { field(arg: { f: true }) } errors: [] - name: same input object within two args rule: UniqueInputFieldNames schema: 0 query: |2- { field(arg1: { f: true }, arg2: { f: true }) } errors: [] - name: multiple input object fields rule: UniqueInputFieldNames schema: 0 query: |2- { field(arg: { f1: "value", f2: "value", f3: "value" }) } errors: [] - name: allows for nested input objects with similar fields rule: UniqueInputFieldNames schema: 0 query: |2- { field(arg: { deep: { deep: { id: 1 } id: 1 } id: 1 }) } errors: [] - name: duplicate input object fields rule: UniqueInputFieldNames schema: 0 query: |2- { field(arg: { f1: "value", f1: "value" }) } errors: - message: There can be only one input field named "f1". locations: - {line: 3, column: 22} - {line: 3, column: 35} - name: many duplicate input object fields rule: UniqueInputFieldNames schema: 0 query: |2- { field(arg: { f1: "value", f1: "value", f1: "value" }) } errors: - message: There can be only one input field named "f1". locations: - {line: 3, column: 22} - {line: 3, column: 35} - message: There can be only one input field named "f1". locations: - {line: 3, column: 22} - {line: 3, column: 48} - name: nested duplicate input object fields rule: UniqueInputFieldNames schema: 0 query: |2- { field(arg: { f1: {f2: "value", f2: "value" }}) } errors: - message: There can be only one input field named "f2". locations: - {line: 3, column: 27} - {line: 3, column: 40} gqlparser-2.5.1/validator/imported/spec/UniqueOperationNamesRule.spec.yml000066400000000000000000000044101430663104200266760ustar00rootroot00000000000000- name: no operations rule: UniqueOperationNames schema: 0 query: |2- fragment fragA on Type { field } errors: [] - name: one anon operation rule: UniqueOperationNames schema: 0 query: |2- { field } errors: [] - name: one named operation rule: UniqueOperationNames schema: 0 query: |2- query Foo { field } errors: [] - name: multiple operations rule: UniqueOperationNames schema: 0 query: |2- query Foo { field } query Bar { field } errors: [] - name: multiple operations of different types rule: UniqueOperationNames schema: 0 query: |2- query Foo { field } mutation Bar { field } subscription Baz { field } errors: [] - name: fragment and operation named the same rule: UniqueOperationNames schema: 0 query: |2- query Foo { ...Foo } fragment Foo on Type { field } errors: [] - name: multiple operations of same name rule: UniqueOperationNames schema: 0 query: |2- query Foo { fieldA } query Foo { fieldB } errors: - message: There can be only one operation named "Foo". locations: - {line: 2, column: 13} - {line: 5, column: 13} - name: multiple ops of same name of different types (mutation) rule: UniqueOperationNames schema: 0 query: |2- query Foo { fieldA } mutation Foo { fieldB } errors: - message: There can be only one operation named "Foo". locations: - {line: 2, column: 13} - {line: 5, column: 16} - name: multiple ops of same name of different types (subscription) rule: UniqueOperationNames schema: 0 query: |2- query Foo { fieldA } subscription Foo { fieldB } errors: - message: There can be only one operation named "Foo". locations: - {line: 2, column: 13} - {line: 5, column: 20} gqlparser-2.5.1/validator/imported/spec/UniqueOperationTypesRule.spec.yml000066400000000000000000000000031430663104200267310ustar00rootroot00000000000000[] gqlparser-2.5.1/validator/imported/spec/UniqueTypeNamesRule.spec.yml000066400000000000000000000000031430663104200256510ustar00rootroot00000000000000[] gqlparser-2.5.1/validator/imported/spec/UniqueVariableNamesRule.spec.yml000066400000000000000000000016311430663104200264650ustar00rootroot00000000000000- name: unique variable names rule: UniqueVariableNames schema: 0 query: |2- query A($x: Int, $y: String) { __typename } query B($x: String, $y: Int) { __typename } errors: [] - name: duplicate variable names rule: UniqueVariableNames schema: 0 query: |2- query A($x: Int, $x: Int, $x: String) { __typename } query B($x: String, $x: Int) { __typename } query C($x: Int, $x: Int) { __typename } errors: - message: There can be only one variable named "$x". locations: - {line: 2, column: 16} - {line: 2, column: 25} - {line: 2, column: 34} - message: There can be only one variable named "$x". locations: - {line: 3, column: 16} - {line: 3, column: 28} - message: There can be only one variable named "$x". locations: - {line: 4, column: 16} - {line: 4, column: 25} gqlparser-2.5.1/validator/imported/spec/ValidationContext.spec.yml000066400000000000000000000000031430663104200253640ustar00rootroot00000000000000[] gqlparser-2.5.1/validator/imported/spec/ValuesOfCorrectTypeRule.spec.yml000066400000000000000000000632731430663104200265070ustar00rootroot00000000000000- name: Valid values/Good int value rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { intArgField(intArg: 2) } } errors: [] - name: Valid values/Good negative int value rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { intArgField(intArg: -2) } } errors: [] - name: Valid values/Good boolean value rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { booleanArgField(booleanArg: true) } } errors: [] - name: Valid values/Good string value rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { stringArgField(stringArg: "foo") } } errors: [] - name: Valid values/Good float value rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { floatArgField(floatArg: 1.1) } } errors: [] - name: Valid values/Good negative float value rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { floatArgField(floatArg: -1.1) } } errors: [] - name: Valid values/Int into Float rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { floatArgField(floatArg: 1) } } errors: [] - name: Valid values/Int into ID rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { idArgField(idArg: 1) } } errors: [] - name: Valid values/String into ID rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { idArgField(idArg: "someIdString") } } errors: [] - name: Valid values/Good enum value rule: ValuesOfCorrectType schema: 0 query: |2- { dog { doesKnowCommand(dogCommand: SIT) } } errors: [] - name: Valid values/Enum with undefined value rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { enumArgField(enumArg: UNKNOWN) } } errors: [] - name: Valid values/Enum with null value rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { enumArgField(enumArg: NO_FUR) } } errors: [] - name: Valid values/null into nullable type rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { intArgField(intArg: null) } } errors: [] - name: Valid values/null into nullable type rule: ValuesOfCorrectType schema: 0 query: |2- { dog(a: null, b: null, c:{ requiredField: true, intField: null }) { name } } errors: [] - name: Invalid String values/Int into String rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { stringArgField(stringArg: 1) } } errors: - message: 'String cannot represent a non string value: 1' locations: - {line: 4, column: 39} - name: Invalid String values/Float into String rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { stringArgField(stringArg: 1.0) } } errors: - message: 'String cannot represent a non string value: 1.0' locations: - {line: 4, column: 39} - name: Invalid String values/Boolean into String rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { stringArgField(stringArg: true) } } errors: - message: 'String cannot represent a non string value: true' locations: - {line: 4, column: 39} - name: Invalid String values/Unquoted String into String rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { stringArgField(stringArg: BAR) } } errors: - message: 'String cannot represent a non string value: BAR' locations: - {line: 4, column: 39} - name: Invalid Int values/String into Int rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { intArgField(intArg: "3") } } errors: - message: 'Int cannot represent non-integer value: "3"' locations: - {line: 4, column: 33} - name: Invalid Int values/Big Int into Int rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { intArgField(intArg: 829384293849283498239482938) } } errors: - message: 'Int cannot represent non 32-bit signed integer value: 829384293849283498239482938' locations: - {line: 4, column: 33} - name: Invalid Int values/Unquoted String into Int rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { intArgField(intArg: FOO) } } errors: - message: 'Int cannot represent non-integer value: FOO' locations: - {line: 4, column: 33} - name: Invalid Int values/Simple Float into Int rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { intArgField(intArg: 3.0) } } errors: - message: 'Int cannot represent non-integer value: 3.0' locations: - {line: 4, column: 33} - name: Invalid Int values/Float into Int rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { intArgField(intArg: 3.333) } } errors: - message: 'Int cannot represent non-integer value: 3.333' locations: - {line: 4, column: 33} - name: Invalid Float values/String into Float rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { floatArgField(floatArg: "3.333") } } errors: - message: 'Float cannot represent non numeric value: "3.333"' locations: - {line: 4, column: 37} - name: Invalid Float values/Boolean into Float rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { floatArgField(floatArg: true) } } errors: - message: 'Float cannot represent non numeric value: true' locations: - {line: 4, column: 37} - name: Invalid Float values/Unquoted into Float rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { floatArgField(floatArg: FOO) } } errors: - message: 'Float cannot represent non numeric value: FOO' locations: - {line: 4, column: 37} - name: Invalid Boolean value/Int into Boolean rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { booleanArgField(booleanArg: 2) } } errors: - message: 'Boolean cannot represent a non boolean value: 2' locations: - {line: 4, column: 41} - name: Invalid Boolean value/Float into Boolean rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { booleanArgField(booleanArg: 1.0) } } errors: - message: 'Boolean cannot represent a non boolean value: 1.0' locations: - {line: 4, column: 41} - name: Invalid Boolean value/String into Boolean rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { booleanArgField(booleanArg: "true") } } errors: - message: 'Boolean cannot represent a non boolean value: "true"' locations: - {line: 4, column: 41} - name: Invalid Boolean value/Unquoted into Boolean rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { booleanArgField(booleanArg: TRUE) } } errors: - message: 'Boolean cannot represent a non boolean value: TRUE' locations: - {line: 4, column: 41} - name: Invalid ID value/Float into ID rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { idArgField(idArg: 1.0) } } errors: - message: 'ID cannot represent a non-string and non-integer value: 1.0' locations: - {line: 4, column: 31} - name: Invalid ID value/Boolean into ID rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { idArgField(idArg: true) } } errors: - message: 'ID cannot represent a non-string and non-integer value: true' locations: - {line: 4, column: 31} - name: Invalid ID value/Unquoted into ID rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { idArgField(idArg: SOMETHING) } } errors: - message: 'ID cannot represent a non-string and non-integer value: SOMETHING' locations: - {line: 4, column: 31} - name: Invalid Enum value/Int into Enum rule: ValuesOfCorrectType schema: 0 query: |2- { dog { doesKnowCommand(dogCommand: 2) } } errors: - message: 'Enum "DogCommand" cannot represent non-enum value: 2.' locations: - {line: 4, column: 41} - name: Invalid Enum value/Float into Enum rule: ValuesOfCorrectType schema: 0 query: |2- { dog { doesKnowCommand(dogCommand: 1.0) } } errors: - message: 'Enum "DogCommand" cannot represent non-enum value: 1.0.' locations: - {line: 4, column: 41} - name: Invalid Enum value/String into Enum rule: ValuesOfCorrectType schema: 0 query: |2- { dog { doesKnowCommand(dogCommand: "SIT") } } errors: - message: 'Enum "DogCommand" cannot represent non-enum value: "SIT". Did you mean the enum value "SIT"?' locations: - {line: 4, column: 41} - name: Invalid Enum value/Boolean into Enum rule: ValuesOfCorrectType schema: 0 query: |2- { dog { doesKnowCommand(dogCommand: true) } } errors: - message: 'Enum "DogCommand" cannot represent non-enum value: true.' locations: - {line: 4, column: 41} - name: Invalid Enum value/Unknown Enum Value into Enum rule: ValuesOfCorrectType schema: 0 query: |2- { dog { doesKnowCommand(dogCommand: JUGGLE) } } errors: - message: Value "JUGGLE" does not exist in "DogCommand" enum. locations: - {line: 4, column: 41} - name: Invalid Enum value/Different case Enum Value into Enum rule: ValuesOfCorrectType schema: 0 query: |2- { dog { doesKnowCommand(dogCommand: sit) } } errors: - message: Value "sit" does not exist in "DogCommand" enum. Did you mean the enum value "SIT"? locations: - {line: 4, column: 41} - name: Valid List value/Good list value rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { stringListArgField(stringListArg: ["one", null, "two"]) } } errors: [] - name: Valid List value/Empty list value rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { stringListArgField(stringListArg: []) } } errors: [] - name: Valid List value/Null value rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { stringListArgField(stringListArg: null) } } errors: [] - name: Valid List value/Single value into List rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { stringListArgField(stringListArg: "one") } } errors: [] - name: Invalid List value/Incorrect item type rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { stringListArgField(stringListArg: ["one", 2]) } } errors: - message: 'String cannot represent a non string value: 2' locations: - {line: 4, column: 55} - name: Invalid List value/Single value of incorrect type rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { stringListArgField(stringListArg: 1) } } errors: - message: 'String cannot represent a non string value: 1' locations: - {line: 4, column: 47} - name: Valid non-nullable value/Arg on optional arg rule: ValuesOfCorrectType schema: 0 query: |2- { dog { isHouseTrained(atOtherHomes: true) } } errors: [] - name: Valid non-nullable value/No Arg on optional arg rule: ValuesOfCorrectType schema: 0 query: |2- { dog { isHouseTrained } } errors: [] - name: Valid non-nullable value/Multiple args rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { multipleReqs(req1: 1, req2: 2) } } errors: [] - name: Valid non-nullable value/Multiple args reverse order rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { multipleReqs(req2: 2, req1: 1) } } errors: [] - name: Valid non-nullable value/No args on multiple optional rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { multipleOpts } } errors: [] - name: Valid non-nullable value/One arg on multiple optional rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { multipleOpts(opt1: 1) } } errors: [] - name: Valid non-nullable value/Second arg on multiple optional rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { multipleOpts(opt2: 1) } } errors: [] - name: Valid non-nullable value/Multiple required args on mixedList rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { multipleOptAndReq(req1: 3, req2: 4) } } errors: [] - name: Valid non-nullable value/Multiple required and one optional arg on mixedList rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { multipleOptAndReq(req1: 3, req2: 4, opt1: 5) } } errors: [] - name: Valid non-nullable value/All required and optional args on mixedList rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { multipleOptAndReq(req1: 3, req2: 4, opt1: 5, opt2: 6) } } errors: [] - name: Invalid non-nullable value/Incorrect value type rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { multipleReqs(req2: "two", req1: "one") } } errors: - message: 'Int cannot represent non-integer value: "two"' locations: - {line: 4, column: 32} - message: 'Int cannot represent non-integer value: "one"' locations: - {line: 4, column: 45} - name: Invalid non-nullable value/Incorrect value and missing argument (ProvidedRequiredArgumentsRule) rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { multipleReqs(req1: "one") } } errors: - message: 'Int cannot represent non-integer value: "one"' locations: - {line: 4, column: 32} - name: Invalid non-nullable value/Null value rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { multipleReqs(req1: null) } } errors: - message: Expected value of type "Int!", found null. locations: - {line: 4, column: 32} - name: Valid input object value/Optional arg, despite required field in type rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { complexArgField } } errors: [] - name: Valid input object value/Partial object, only required rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { complexArgField(complexArg: { requiredField: true }) } } errors: [] - name: Valid input object value/Partial object, required field can be falsy rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { complexArgField(complexArg: { requiredField: false }) } } errors: [] - name: Valid input object value/Partial object, including required rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { complexArgField(complexArg: { requiredField: true, intField: 4 }) } } errors: [] - name: Valid input object value/Full object rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { complexArgField(complexArg: { requiredField: true, intField: 4, stringField: "foo", booleanField: false, stringListField: ["one", "two"] }) } } errors: [] - name: Valid input object value/Full object with fields in different order rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { complexArgField(complexArg: { stringListField: ["one", "two"], booleanField: false, requiredField: true, stringField: "foo", intField: 4, }) } } errors: [] - name: Invalid input object value/Partial object, missing required rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { complexArgField(complexArg: { intField: 4 }) } } errors: - message: Field "ComplexInput.requiredField" of required type "Boolean!" was not provided. locations: - {line: 4, column: 41} - name: Invalid input object value/Partial object, invalid field type rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { complexArgField(complexArg: { stringListField: ["one", 2], requiredField: true, }) } } errors: - message: 'String cannot represent a non string value: 2' locations: - {line: 5, column: 40} - name: Invalid input object value/Partial object, null to non-null field rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { complexArgField(complexArg: { requiredField: true, nonNullField: null, }) } } errors: - message: Expected value of type "Boolean!", found null. locations: - {line: 6, column: 29} - name: Invalid input object value/Partial object, unknown field arg rule: ValuesOfCorrectType schema: 0 query: |2- { complicatedArgs { complexArgField(complexArg: { requiredField: true, invalidField: "value" }) } } errors: - message: Field "invalidField" is not defined by type "ComplexInput". Did you mean "intField"? locations: - {line: 6, column: 15} - name: Invalid input object value/reports error for custom scalar that returns undefined rule: ValuesOfCorrectType schema: 18 query: '{ invalidArg(arg: 123) }' errors: - message: Expected value of type "CustomScalar", found 123. locations: - {line: 1, column: 19} - name: Invalid input object value/allows custom scalar to accept complex literals rule: ValuesOfCorrectType schema: 19 query: |2- { test1: anyArg(arg: 123) test2: anyArg(arg: "abc") test3: anyArg(arg: [123, "abc"]) test4: anyArg(arg: {deep: [123, "abc"]}) } errors: [] - name: Directive arguments/with directives of valid types rule: ValuesOfCorrectType schema: 0 query: |2- { dog @include(if: true) { name } human @skip(if: false) { name } } errors: [] - name: Directive arguments/with directive with incorrect types rule: ValuesOfCorrectType schema: 0 query: |2- { dog @include(if: "yes") { name @skip(if: ENUM) } } errors: - message: 'Boolean cannot represent a non boolean value: "yes"' locations: - {line: 3, column: 28} - message: 'Boolean cannot represent a non boolean value: ENUM' locations: - {line: 4, column: 28} - name: Variable default values/variables with valid default values rule: ValuesOfCorrectType schema: 0 query: |2- query WithDefaultValues( $a: Int = 1, $b: String = "ok", $c: ComplexInput = { requiredField: true, intField: 3 } $d: Int! = 123 ) { dog { name } } errors: [] - name: Variable default values/variables with valid default null values rule: ValuesOfCorrectType schema: 0 query: |2- query WithDefaultValues( $a: Int = null, $b: String = null, $c: ComplexInput = { requiredField: true, intField: null } ) { dog { name } } errors: [] - name: Variable default values/variables with invalid default null values rule: ValuesOfCorrectType schema: 0 query: |2- query WithDefaultValues( $a: Int! = null, $b: String! = null, $c: ComplexInput = { requiredField: null, intField: null } ) { dog { name } } errors: - message: Expected value of type "Int!", found null. locations: - {line: 3, column: 22} - message: Expected value of type "String!", found null. locations: - {line: 4, column: 25} - message: Expected value of type "Boolean!", found null. locations: - {line: 5, column: 47} - name: Variable default values/variables with invalid default values rule: ValuesOfCorrectType schema: 0 query: |2- query InvalidDefaultValues( $a: Int = "one", $b: String = 4, $c: ComplexInput = "NotVeryComplex" ) { dog { name } } errors: - message: 'Int cannot represent non-integer value: "one"' locations: - {line: 3, column: 21} - message: 'String cannot represent a non string value: 4' locations: - {line: 4, column: 24} - message: Expected value of type "ComplexInput", found "NotVeryComplex". locations: - {line: 5, column: 30} - name: Variable default values/variables with complex invalid default values rule: ValuesOfCorrectType schema: 0 query: |2- query WithDefaultValues( $a: ComplexInput = { requiredField: 123, intField: "abc" } ) { dog { name } } errors: - message: 'Boolean cannot represent a non boolean value: 123' locations: - {line: 3, column: 47} - message: 'Int cannot represent non-integer value: "abc"' locations: - {line: 3, column: 62} - name: Variable default values/complex variables missing required field rule: ValuesOfCorrectType schema: 0 query: |2- query MissingRequiredField($a: ComplexInput = {intField: 3}) { dog { name } } errors: - message: Field "ComplexInput.requiredField" of required type "Boolean!" was not provided. locations: - {line: 2, column: 55} - name: Variable default values/list variables with invalid item rule: ValuesOfCorrectType schema: 0 query: |2- query InvalidItem($a: [String] = ["one", 2]) { dog { name } } errors: - message: 'String cannot represent a non string value: 2' locations: - {line: 2, column: 50} gqlparser-2.5.1/validator/imported/spec/VariablesAreInputTypesRule.spec.yml000066400000000000000000000017211430663104200271720ustar00rootroot00000000000000- name: unknown types are ignored rule: VariablesAreInputTypes schema: 0 query: |2- query Foo($a: Unknown, $b: [[Unknown!]]!) { field(a: $a, b: $b) } errors: [] - name: input types are valid rule: VariablesAreInputTypes schema: 0 query: |2- query Foo($a: String, $b: [Boolean!]!, $c: ComplexInput) { field(a: $a, b: $b, c: $c) } errors: [] - name: output types are invalid rule: VariablesAreInputTypes schema: 0 query: |2- query Foo($a: Dog, $b: [[CatOrDog!]]!, $c: Pet) { field(a: $a, b: $b, c: $c) } errors: - locations: - {line: 2, column: 21} message: Variable "$a" cannot be non-input type "Dog". - locations: - {line: 2, column: 30} message: Variable "$b" cannot be non-input type "[[CatOrDog!]]!". - locations: - {line: 2, column: 50} message: Variable "$c" cannot be non-input type "Pet". gqlparser-2.5.1/validator/imported/spec/VariablesInAllowedPositionRule.spec.yml000066400000000000000000000215001430663104200300160ustar00rootroot00000000000000- name: Boolean => Boolean rule: VariablesInAllowedPosition schema: 0 query: |2- query Query($booleanArg: Boolean) { complicatedArgs { booleanArgField(booleanArg: $booleanArg) } } errors: [] - name: Boolean => Boolean within fragment rule: VariablesInAllowedPosition schema: 0 query: |2- fragment booleanArgFrag on ComplicatedArgs { booleanArgField(booleanArg: $booleanArg) } query Query($booleanArg: Boolean) { complicatedArgs { ...booleanArgFrag } } errors: [] - name: Boolean => Boolean within fragment rule: VariablesInAllowedPosition schema: 0 query: |2- query Query($booleanArg: Boolean) { complicatedArgs { ...booleanArgFrag } } fragment booleanArgFrag on ComplicatedArgs { booleanArgField(booleanArg: $booleanArg) } errors: [] - name: Boolean! => Boolean rule: VariablesInAllowedPosition schema: 0 query: |2- query Query($nonNullBooleanArg: Boolean!) { complicatedArgs { booleanArgField(booleanArg: $nonNullBooleanArg) } } errors: [] - name: Boolean! => Boolean within fragment rule: VariablesInAllowedPosition schema: 0 query: |2- fragment booleanArgFrag on ComplicatedArgs { booleanArgField(booleanArg: $nonNullBooleanArg) } query Query($nonNullBooleanArg: Boolean!) { complicatedArgs { ...booleanArgFrag } } errors: [] - name: '[String] => [String]' rule: VariablesInAllowedPosition schema: 0 query: |2- query Query($stringListVar: [String]) { complicatedArgs { stringListArgField(stringListArg: $stringListVar) } } errors: [] - name: '[String!] => [String]' rule: VariablesInAllowedPosition schema: 0 query: |2- query Query($stringListVar: [String!]) { complicatedArgs { stringListArgField(stringListArg: $stringListVar) } } errors: [] - name: String => [String] in item position rule: VariablesInAllowedPosition schema: 0 query: |2- query Query($stringVar: String) { complicatedArgs { stringListArgField(stringListArg: [$stringVar]) } } errors: [] - name: String! => [String] in item position rule: VariablesInAllowedPosition schema: 0 query: |2- query Query($stringVar: String!) { complicatedArgs { stringListArgField(stringListArg: [$stringVar]) } } errors: [] - name: ComplexInput => ComplexInput rule: VariablesInAllowedPosition schema: 0 query: |2- query Query($complexVar: ComplexInput) { complicatedArgs { complexArgField(complexArg: $complexVar) } } errors: [] - name: ComplexInput => ComplexInput in field position rule: VariablesInAllowedPosition schema: 0 query: |2- query Query($boolVar: Boolean = false) { complicatedArgs { complexArgField(complexArg: {requiredArg: $boolVar}) } } errors: [] - name: Boolean! => Boolean! in directive rule: VariablesInAllowedPosition schema: 0 query: |2- query Query($boolVar: Boolean!) { dog @include(if: $boolVar) } errors: [] - name: Int => Int! rule: VariablesInAllowedPosition schema: 0 query: |2- query Query($intArg: Int) { complicatedArgs { nonNullIntArgField(nonNullIntArg: $intArg) } } errors: - message: Variable "$intArg" of type "Int" used in position expecting type "Int!". locations: - {line: 2, column: 19} - {line: 4, column: 45} - name: Int => Int! within fragment rule: VariablesInAllowedPosition schema: 0 query: |2- fragment nonNullIntArgFieldFrag on ComplicatedArgs { nonNullIntArgField(nonNullIntArg: $intArg) } query Query($intArg: Int) { complicatedArgs { ...nonNullIntArgFieldFrag } } errors: - message: Variable "$intArg" of type "Int" used in position expecting type "Int!". locations: - {line: 6, column: 19} - {line: 3, column: 43} - name: Int => Int! within nested fragment rule: VariablesInAllowedPosition schema: 0 query: |2- fragment outerFrag on ComplicatedArgs { ...nonNullIntArgFieldFrag } fragment nonNullIntArgFieldFrag on ComplicatedArgs { nonNullIntArgField(nonNullIntArg: $intArg) } query Query($intArg: Int) { complicatedArgs { ...outerFrag } } errors: - message: Variable "$intArg" of type "Int" used in position expecting type "Int!". locations: - {line: 10, column: 19} - {line: 7, column: 43} - name: String over Boolean rule: VariablesInAllowedPosition schema: 0 query: |2- query Query($stringVar: String) { complicatedArgs { booleanArgField(booleanArg: $stringVar) } } errors: - message: Variable "$stringVar" of type "String" used in position expecting type "Boolean". locations: - {line: 2, column: 19} - {line: 4, column: 39} - name: String => [String] rule: VariablesInAllowedPosition schema: 0 query: |2- query Query($stringVar: String) { complicatedArgs { stringListArgField(stringListArg: $stringVar) } } errors: - message: Variable "$stringVar" of type "String" used in position expecting type "[String]". locations: - {line: 2, column: 19} - {line: 4, column: 45} - name: Boolean => Boolean! in directive rule: VariablesInAllowedPosition schema: 0 query: |2- query Query($boolVar: Boolean) { dog @include(if: $boolVar) } errors: - message: Variable "$boolVar" of type "Boolean" used in position expecting type "Boolean!". locations: - {line: 2, column: 19} - {line: 3, column: 26} - name: String => Boolean! in directive rule: VariablesInAllowedPosition schema: 0 query: |2- query Query($stringVar: String) { dog @include(if: $stringVar) } errors: - message: Variable "$stringVar" of type "String" used in position expecting type "Boolean!". locations: - {line: 2, column: 19} - {line: 3, column: 26} - name: '[String] => [String!]' rule: VariablesInAllowedPosition schema: 0 query: |2- query Query($stringListVar: [String]) { complicatedArgs { stringListNonNullArgField(stringListNonNullArg: $stringListVar) } } errors: - message: Variable "$stringListVar" of type "[String]" used in position expecting type "[String!]". locations: - {line: 2, column: 19} - {line: 5, column: 59} - name: Allows optional (nullable) variables with default values/Int => Int! fails when variable provides null default value rule: VariablesInAllowedPosition schema: 0 query: |2- query Query($intVar: Int = null) { complicatedArgs { nonNullIntArgField(nonNullIntArg: $intVar) } } errors: - message: Variable "$intVar" of type "Int" used in position expecting type "Int!". locations: - {line: 2, column: 21} - {line: 4, column: 47} - name: Allows optional (nullable) variables with default values/Int => Int! when variable provides non-null default value rule: VariablesInAllowedPosition schema: 0 query: |2- query Query($intVar: Int = 1) { complicatedArgs { nonNullIntArgField(nonNullIntArg: $intVar) } } errors: [] - name: Allows optional (nullable) variables with default values/Int => Int! when optional argument provides default value rule: VariablesInAllowedPosition schema: 0 query: |2- query Query($intVar: Int) { complicatedArgs { nonNullFieldWithDefault(nonNullIntArg: $intVar) } } errors: [] - name: Allows optional (nullable) variables with default values/Boolean => Boolean! in directive with default value with option rule: VariablesInAllowedPosition schema: 0 query: |2- query Query($boolVar: Boolean = false) { dog @include(if: $boolVar) } errors: [] gqlparser-2.5.1/validator/imported/spec/schemas.yml000066400000000000000000000217371430663104200224400ustar00rootroot00000000000000- |- schema { query: QueryRoot } directive @onField on FIELD interface Mammal { mother: Mammal father: Mammal } interface Pet { name(surname: Boolean): String } interface Canine implements Mammal { name(surname: Boolean): String mother: Canine father: Canine } enum DogCommand { SIT HEEL DOWN } type Dog implements Pet & Mammal & Canine { name(surname: Boolean): String nickname: String barkVolume: Int barks: Boolean doesKnowCommand(dogCommand: DogCommand): Boolean isHouseTrained(atOtherHomes: Boolean = true): Boolean isAtLocation(x: Int, y: Int): Boolean mother: Dog father: Dog } type Cat implements Pet { name(surname: Boolean): String nickname: String meows: Boolean meowsVolume: Int furColor: FurColor } union CatOrDog = Cat | Dog type Human { name(surname: Boolean): String pets: [Pet] relatives: [Human] } enum FurColor { BROWN BLACK TAN SPOTTED NO_FUR UNKNOWN } input ComplexInput { requiredField: Boolean! nonNullField: Boolean! = false intField: Int stringField: String booleanField: Boolean stringListField: [String] } type ComplicatedArgs { intArgField(intArg: Int): String nonNullIntArgField(nonNullIntArg: Int!): String stringArgField(stringArg: String): String booleanArgField(booleanArg: Boolean): String enumArgField(enumArg: FurColor): String floatArgField(floatArg: Float): String idArgField(idArg: ID): String stringListArgField(stringListArg: [String]): String stringListNonNullArgField(stringListNonNullArg: [String!]): String complexArgField(complexArg: ComplexInput): String multipleReqs(req1: Int!, req2: Int!): String nonNullFieldWithDefault(arg: Int! = 0): String multipleOpts(opt1: Int = 0, opt2: Int = 0): String multipleOptAndReq(req1: Int!, req2: Int!, opt1: Int = 0, opt2: Int = 0): String } type QueryRoot { human(id: ID): Human dog: Dog cat: Cat pet: Pet catOrDog: CatOrDog complicatedArgs: ComplicatedArgs } # injected becuase upstream spec is missing some types extend type QueryRoot { field: T f1: Type f2: Type f3: Type } type Type { a: String b: String c: String } type T { a: String b: String c: String d: String y: String deepField: T deeperField: T } - |- interface Pet { name: String } type Dog implements Pet { name: String nickname: String barkVolume: Int } type Cat implements Pet { name: String nickname: String meowVolume: Int } union CatOrDog = Cat | Dog type Human { name: String pets: [Pet] } type Query { human: Human } - |- directive @onQuery on QUERY directive @onMutation on MUTATION directive @onSubscription on SUBSCRIPTION directive @onField on FIELD directive @onFragmentDefinition on FRAGMENT_DEFINITION directive @onFragmentSpread on FRAGMENT_SPREAD directive @onInlineFragment on INLINE_FRAGMENT directive @onVariableDefinition on VARIABLE_DEFINITION type Query { dummy: String } - |- type Query { foo: String } - |- type Query { normalField: String deprecatedField: String @deprecated(reason: "Some field reason.") } - |- type Query { someField(normalArg: String, deprecatedArg: String @deprecated(reason: "Some arg reason.")): String } - |- directive @someDirective(normalArg: String, deprecatedArg: String @deprecated(reason: "Some arg reason.")) on FIELD type Query { someField: String } - |- directive @someDirective(someArg: InputType) on FIELD input InputType { normalField: String deprecatedField: String @deprecated(reason: "Some input field reason.") } type Query { someField(someArg: InputType): String } - |- enum EnumType { NORMAL_VALUE DEPRECATED_VALUE @deprecated(reason: "Some enum reason.") } type Query { someField(enumArg: EnumType): String } - |- type Query { someQuery: SomeType } type SomeType { someField: String introspectionField: __EnumValue } - |- type Query { someField(a: String, b: String): String } - |- input SomeInput { a: String b: String } type Query { someField(arg: SomeInput): String } - |- interface SomeBox { deepBox: SomeBox unrelatedField: String } type StringBox implements SomeBox { scalar: String deepBox: StringBox unrelatedField: String listStringBox: [StringBox] stringBox: StringBox intBox: IntBox } type IntBox implements SomeBox { scalar: Int deepBox: IntBox unrelatedField: String listStringBox: [StringBox] stringBox: StringBox intBox: IntBox } interface NonNullStringBox1 { scalar: String! } type NonNullStringBox1Impl implements SomeBox & NonNullStringBox1 { scalar: String! unrelatedField: String deepBox: SomeBox } interface NonNullStringBox2 { scalar: String! } type NonNullStringBox2Impl implements SomeBox & NonNullStringBox2 { scalar: String! unrelatedField: String deepBox: SomeBox } type Connection { edges: [Edge] } type Edge { node: Node } type Node { id: ID name: String } type Query { someBox: SomeBox connection: Connection } - |- type Foo { constructor: String } type Query { foo: Foo } - |- interface Being { name: String } interface Pet implements Being { name: String } type Dog implements Being & Pet { name: String barkVolume: Int } type Cat implements Being & Pet { name: String meowVolume: Int } union CatOrDog = Cat | Dog interface Intelligent { iq: Int } type Human implements Being & Intelligent { name: String pets: [Pet] iq: Int } type Alien implements Being & Intelligent { name: String iq: Int } union DogOrHuman = Dog | Human union HumanOrAlien = Human | Alien type Query { catOrDog: CatOrDog dogOrHuman: DogOrHuman humanOrAlien: HumanOrAlien } - |- schema { query: QueryRoot subscription: SubscriptionRoot } type Message { body: String sender: String } type SubscriptionRoot { importantEmails: [String] notImportantEmails: [String] moreImportantEmails: [String] spamEmails: [String] deletedEmails: [String] newMessage: Message } type QueryRoot { dummy: String } - |- type Query { dummy: String } - |- schema { query: QueryRoot } directive @onField on FIELD directive @directive on FIELD | FRAGMENT_DEFINITION directive @directiveA on FIELD | FRAGMENT_DEFINITION directive @directiveB on FIELD | FRAGMENT_DEFINITION directive @repeatable repeatable on FIELD | FRAGMENT_DEFINITION interface Mammal { mother: Mammal father: Mammal } interface Pet { name(surname: Boolean): String } interface Canine implements Mammal { name(surname: Boolean): String mother: Canine father: Canine } enum DogCommand { SIT HEEL DOWN } type Dog implements Pet & Mammal & Canine { name(surname: Boolean): String nickname: String barkVolume: Int barks: Boolean doesKnowCommand(dogCommand: DogCommand): Boolean isHouseTrained(atOtherHomes: Boolean = true): Boolean isAtLocation(x: Int, y: Int): Boolean mother: Dog father: Dog } type Cat implements Pet { name(surname: Boolean): String nickname: String meows: Boolean meowsVolume: Int furColor: FurColor } union CatOrDog = Cat | Dog type Human { name(surname: Boolean): String pets: [Pet] relatives: [Human] } enum FurColor { BROWN BLACK TAN SPOTTED NO_FUR UNKNOWN } input ComplexInput { requiredField: Boolean! nonNullField: Boolean! = false intField: Int stringField: String booleanField: Boolean stringListField: [String] } type ComplicatedArgs { intArgField(intArg: Int): String nonNullIntArgField(nonNullIntArg: Int!): String stringArgField(stringArg: String): String booleanArgField(booleanArg: Boolean): String enumArgField(enumArg: FurColor): String floatArgField(floatArg: Float): String idArgField(idArg: ID): String stringListArgField(stringListArg: [String]): String stringListNonNullArgField(stringListNonNullArg: [String!]): String complexArgField(complexArg: ComplexInput): String multipleReqs(req1: Int!, req2: Int!): String nonNullFieldWithDefault(arg: Int! = 0): String multipleOpts(opt1: Int = 0, opt2: Int = 0): String multipleOptAndReq(req1: Int!, req2: Int!, opt1: Int = 0, opt2: Int = 0): String } type QueryRoot { human(id: ID): Human dog: Dog cat: Cat pet: Pet catOrDog: CatOrDog complicatedArgs: ComplicatedArgs } - |- type Query { invalidArg(arg: CustomScalar): String } scalar CustomScalar - |- type Query { anyArg(arg: Any): String } scalar Any - "" gqlparser-2.5.1/validator/imported/tests.json000066400000000000000000005645321430663104200214020ustar00rootroot00000000000000 { "schemas": [ "schema {\n query: QueryRoot\n}\n\ndirective @onQuery on QUERY\n\ndirective @onMutation on MUTATION\n\ndirective @onSubscription on SUBSCRIPTION\n\ndirective @onField on FIELD\n\ndirective @onFragmentDefinition on FRAGMENT_DEFINITION\n\ndirective @onFragmentSpread on FRAGMENT_SPREAD\n\ndirective @onInlineFragment on INLINE_FRAGMENT\n\ndirective @onSchema on SCHEMA\n\ndirective @onScalar on SCALAR\n\ndirective @onObject on OBJECT\n\ndirective @onFieldDefinition on FIELD_DEFINITION\n\ndirective @onArgumentDefinition on ARGUMENT_DEFINITION\n\ndirective @onInterface on INTERFACE\n\ndirective @onUnion on UNION\n\ndirective @onEnum on ENUM\n\ndirective @onEnumValue on ENUM_VALUE\n\ndirective @onInputObject on INPUT_OBJECT\n\ndirective @onInputFieldDefinition on INPUT_FIELD_DEFINITION\n\ntype Alien implements Being & Intelligent {\n iq: Int\n name(surname: Boolean): String\n numEyes: Int\n}\n\nscalar Any\n\ninterface Being {\n name(surname: Boolean): String\n}\n\ninterface Canine {\n name(surname: Boolean): String\n}\n\ntype Cat implements Being & Pet {\n name(surname: Boolean): String\n nickname: String\n meows: Boolean\n meowVolume: Int\n furColor: FurColor\n}\n\nunion CatOrDog = Dog | Cat\n\ninput ComplexInput {\n requiredField: Boolean!\n nonNullField: Boolean! = false\n intField: Int\n stringField: String\n booleanField: Boolean\n stringListField: [String]\n}\n\ntype ComplicatedArgs {\n intArgField(intArg: Int): String\n nonNullIntArgField(nonNullIntArg: Int!): String\n stringArgField(stringArg: String): String\n booleanArgField(booleanArg: Boolean): String\n enumArgField(enumArg: FurColor): String\n floatArgField(floatArg: Float): String\n idArgField(idArg: ID): String\n stringListArgField(stringListArg: [String]): String\n stringListNonNullArgField(stringListNonNullArg: [String!]): String\n complexArgField(complexArg: ComplexInput): String\n multipleReqs(req1: Int!, req2: Int!): String\n nonNullFieldWithDefault(arg: Int! = 0): String\n multipleOpts(opt1: Int = 0, opt2: Int = 0): String\n multipleOptAndReq(req1: Int!, req2: Int!, opt1: Int = 0, opt2: Int = 0): String\n}\n\ntype Dog implements Being & Pet & Canine {\n name(surname: Boolean): String\n nickname: String\n barkVolume: Int\n barks: Boolean\n doesKnowCommand(dogCommand: DogCommand): Boolean\n isHousetrained(atOtherHomes: Boolean = true): Boolean\n isAtLocation(x: Int, y: Int): Boolean\n}\n\nenum DogCommand {\n SIT\n HEEL\n DOWN\n}\n\nunion DogOrHuman = Dog | Human\n\nenum FurColor {\n BROWN\n BLACK\n TAN\n SPOTTED\n NO_FUR\n UNKNOWN\n}\n\ntype Human implements Being & Intelligent {\n name(surname: Boolean): String\n pets: [Pet]\n relatives: [Human]\n iq: Int\n}\n\nunion HumanOrAlien = Human | Alien\n\ninterface Intelligent {\n iq: Int\n}\n\nscalar Invalid\n\ninterface Pet {\n name(surname: Boolean): String\n}\n\ntype QueryRoot {\n human(id: ID): Human\n alien: Alien\n dog: Dog\n cat: Cat\n pet: Pet\n catOrDog: CatOrDog\n dogOrHuman: DogOrHuman\n humanOrAlien: HumanOrAlien\n complicatedArgs: ComplicatedArgs\n invalidArg(arg: Invalid): String\n anyArg(arg: Any): String\n}\n", "schema {\n query: QueryRoot\n}\n\ntype Connection {\n edges: [Edge]\n}\n\ntype Edge {\n node: Node\n}\n\ntype IntBox implements SomeBox {\n scalar: Int\n deepBox: IntBox\n unrelatedField: String\n listStringBox: [StringBox]\n stringBox: StringBox\n intBox: IntBox\n}\n\ntype Node {\n id: ID\n name: String\n}\n\ninterface NonNullStringBox1 {\n scalar: String!\n}\n\ntype NonNullStringBox1Impl implements SomeBox & NonNullStringBox1 {\n scalar: String!\n unrelatedField: String\n deepBox: SomeBox\n}\n\ninterface NonNullStringBox2 {\n scalar: String!\n}\n\ntype NonNullStringBox2Impl implements SomeBox & NonNullStringBox2 {\n scalar: String!\n unrelatedField: String\n deepBox: SomeBox\n}\n\ntype QueryRoot {\n someBox: SomeBox\n connection: Connection\n}\n\ninterface SomeBox {\n deepBox: SomeBox\n unrelatedField: String\n}\n\ntype StringBox implements SomeBox {\n scalar: String\n deepBox: StringBox\n unrelatedField: String\n listStringBox: [StringBox]\n stringBox: StringBox\n intBox: IntBox\n}\n", "type Foo {\n constructor: String\n}\n\ntype Query {\n foo: Foo\n}\n" ], "tests": [ { "name": "Validate: Executable definitions/with only operation", "rule": "ExecutableDefinitions", "schema": 0, "query": "\n query Foo {\n dog {\n name\n }\n }\n ", "errors": [] }, { "name": "Validate: Executable definitions/with operation and fragment", "rule": "ExecutableDefinitions", "schema": 0, "query": "\n query Foo {\n dog {\n name\n ...Frag\n }\n }\n\n fragment Frag on Dog {\n name\n }\n ", "errors": [] }, { "name": "Validate: Executable definitions/with type definition", "rule": "ExecutableDefinitions", "schema": 0, "query": "\n query Foo {\n dog {\n name\n }\n }\n\n type Cow {\n name: String\n }\n\n extend type Dog {\n color: String\n }\n ", "errors": [ { "message": "The Cow definition is not executable.", "locations": [ { "line": 8, "column": 7 } ] }, { "message": "The Dog definition is not executable.", "locations": [ { "line": 12, "column": 7 } ] } ] }, { "name": "Validate: Executable definitions/with schema definition", "rule": "ExecutableDefinitions", "schema": 0, "query": "\n schema {\n query: Query\n }\n\n type Query {\n test: String\n }\n\n extend schema @directive\n ", "errors": [ { "message": "The schema definition is not executable.", "locations": [ { "line": 2, "column": 7 } ] }, { "message": "The Query definition is not executable.", "locations": [ { "line": 6, "column": 7 } ] }, { "message": "The schema definition is not executable.", "locations": [ { "line": 10, "column": 7 } ] } ] }, { "name": "Validate: Fields on correct type/Object field selection", "rule": "FieldsOnCorrectType", "schema": 0, "query": "\n fragment objectFieldSelection on Dog {\n __typename\n name\n }\n ", "errors": [] }, { "name": "Validate: Fields on correct type/Aliased object field selection", "rule": "FieldsOnCorrectType", "schema": 0, "query": "\n fragment aliasedObjectFieldSelection on Dog {\n tn : __typename\n otherName : name\n }\n ", "errors": [] }, { "name": "Validate: Fields on correct type/Interface field selection", "rule": "FieldsOnCorrectType", "schema": 0, "query": "\n fragment interfaceFieldSelection on Pet {\n __typename\n name\n }\n ", "errors": [] }, { "name": "Validate: Fields on correct type/Aliased interface field selection", "rule": "FieldsOnCorrectType", "schema": 0, "query": "\n fragment interfaceFieldSelection on Pet {\n otherName : name\n }\n ", "errors": [] }, { "name": "Validate: Fields on correct type/Lying alias selection", "rule": "FieldsOnCorrectType", "schema": 0, "query": "\n fragment lyingAliasSelection on Dog {\n name : nickname\n }\n ", "errors": [] }, { "name": "Validate: Fields on correct type/Ignores fields on unknown type", "rule": "FieldsOnCorrectType", "schema": 0, "query": "\n fragment unknownSelection on UnknownType {\n unknownField\n }\n ", "errors": [] }, { "name": "Validate: Fields on correct type/reports errors when type is known again", "rule": "FieldsOnCorrectType", "schema": 0, "query": "\n fragment typeKnownAgain on Pet {\n unknown_pet_field {\n ... on Cat {\n unknown_cat_field\n }\n }\n }", "errors": [ { "message": "Cannot query field \"unknown_pet_field\" on type \"Pet\".", "locations": [ { "line": 3, "column": 9 } ] }, { "message": "Cannot query field \"unknown_cat_field\" on type \"Cat\".", "locations": [ { "line": 5, "column": 13 } ] } ] }, { "name": "Validate: Fields on correct type/Field not defined on fragment", "rule": "FieldsOnCorrectType", "schema": 0, "query": "\n fragment fieldNotDefined on Dog {\n meowVolume\n }", "errors": [ { "message": "Cannot query field \"meowVolume\" on type \"Dog\". Did you mean \"barkVolume\"?", "locations": [ { "line": 3, "column": 9 } ] } ] }, { "name": "Validate: Fields on correct type/Ignores deeply unknown field", "rule": "FieldsOnCorrectType", "schema": 0, "query": "\n fragment deepFieldNotDefined on Dog {\n unknown_field {\n deeper_unknown_field\n }\n }", "errors": [ { "message": "Cannot query field \"unknown_field\" on type \"Dog\".", "locations": [ { "line": 3, "column": 9 } ] } ] }, { "name": "Validate: Fields on correct type/Sub-field not defined", "rule": "FieldsOnCorrectType", "schema": 0, "query": "\n fragment subFieldNotDefined on Human {\n pets {\n unknown_field\n }\n }", "errors": [ { "message": "Cannot query field \"unknown_field\" on type \"Pet\".", "locations": [ { "line": 4, "column": 11 } ] } ] }, { "name": "Validate: Fields on correct type/Field not defined on inline fragment", "rule": "FieldsOnCorrectType", "schema": 0, "query": "\n fragment fieldNotDefined on Pet {\n ... on Dog {\n meowVolume\n }\n }", "errors": [ { "message": "Cannot query field \"meowVolume\" on type \"Dog\". Did you mean \"barkVolume\"?", "locations": [ { "line": 4, "column": 11 } ] } ] }, { "name": "Validate: Fields on correct type/Aliased field target not defined", "rule": "FieldsOnCorrectType", "schema": 0, "query": "\n fragment aliasedFieldTargetNotDefined on Dog {\n volume : mooVolume\n }", "errors": [ { "message": "Cannot query field \"mooVolume\" on type \"Dog\". Did you mean \"barkVolume\"?", "locations": [ { "line": 3, "column": 9 } ] } ] }, { "name": "Validate: Fields on correct type/Aliased lying field target not defined", "rule": "FieldsOnCorrectType", "schema": 0, "query": "\n fragment aliasedLyingFieldTargetNotDefined on Dog {\n barkVolume : kawVolume\n }", "errors": [ { "message": "Cannot query field \"kawVolume\" on type \"Dog\". Did you mean \"barkVolume\"?", "locations": [ { "line": 3, "column": 9 } ] } ] }, { "name": "Validate: Fields on correct type/Not defined on interface", "rule": "FieldsOnCorrectType", "schema": 0, "query": "\n fragment notDefinedOnInterface on Pet {\n tailLength\n }", "errors": [ { "message": "Cannot query field \"tailLength\" on type \"Pet\".", "locations": [ { "line": 3, "column": 9 } ] } ] }, { "name": "Validate: Fields on correct type/Defined on implementors but not on interface", "rule": "FieldsOnCorrectType", "schema": 0, "query": "\n fragment definedOnImplementorsButNotInterface on Pet {\n nickname\n }", "errors": [ { "message": "Cannot query field \"nickname\" on type \"Pet\".", "locations": [ { "line": 3, "column": 9 } ] } ] }, { "name": "Validate: Fields on correct type/Meta field selection on union", "rule": "FieldsOnCorrectType", "schema": 0, "query": "\n fragment directFieldSelectionOnUnion on CatOrDog {\n __typename\n }", "errors": [] }, { "name": "Validate: Fields on correct type/Direct field selection on union", "rule": "FieldsOnCorrectType", "schema": 0, "query": "\n fragment directFieldSelectionOnUnion on CatOrDog {\n directField\n }", "errors": [ { "message": "Cannot query field \"directField\" on type \"CatOrDog\".", "locations": [ { "line": 3, "column": 9 } ] } ] }, { "name": "Validate: Fields on correct type/Defined on implementors queried on union", "rule": "FieldsOnCorrectType", "schema": 0, "query": "\n fragment definedOnImplementorsQueriedOnUnion on CatOrDog {\n name\n }", "errors": [ { "message": "Cannot query field \"name\" on type \"CatOrDog\".", "locations": [ { "line": 3, "column": 9 } ] } ] }, { "name": "Validate: Fields on correct type/valid field in inline fragment", "rule": "FieldsOnCorrectType", "schema": 0, "query": "\n fragment objectFieldSelection on Pet {\n ... on Dog {\n name\n }\n ... {\n name\n }\n }\n ", "errors": [] }, { "name": "Validate: Fragments on composite types/object is valid fragment type", "rule": "FragmentsOnCompositeTypes", "schema": 0, "query": "\n fragment validFragment on Dog {\n barks\n }\n ", "errors": [] }, { "name": "Validate: Fragments on composite types/interface is valid fragment type", "rule": "FragmentsOnCompositeTypes", "schema": 0, "query": "\n fragment validFragment on Pet {\n name\n }\n ", "errors": [] }, { "name": "Validate: Fragments on composite types/object is valid inline fragment type", "rule": "FragmentsOnCompositeTypes", "schema": 0, "query": "\n fragment validFragment on Pet {\n ... on Dog {\n barks\n }\n }\n ", "errors": [] }, { "name": "Validate: Fragments on composite types/inline fragment without type is valid", "rule": "FragmentsOnCompositeTypes", "schema": 0, "query": "\n fragment validFragment on Pet {\n ... {\n name\n }\n }\n ", "errors": [] }, { "name": "Validate: Fragments on composite types/union is valid fragment type", "rule": "FragmentsOnCompositeTypes", "schema": 0, "query": "\n fragment validFragment on CatOrDog {\n __typename\n }\n ", "errors": [] }, { "name": "Validate: Fragments on composite types/scalar is invalid fragment type", "rule": "FragmentsOnCompositeTypes", "schema": 0, "query": "\n fragment scalarFragment on Boolean {\n bad\n }\n ", "errors": [ { "message": "Fragment \"scalarFragment\" cannot condition on non composite type \"Boolean\".", "locations": [ { "line": 2, "column": 34 } ] } ] }, { "name": "Validate: Fragments on composite types/enum is invalid fragment type", "rule": "FragmentsOnCompositeTypes", "schema": 0, "query": "\n fragment scalarFragment on FurColor {\n bad\n }\n ", "errors": [ { "message": "Fragment \"scalarFragment\" cannot condition on non composite type \"FurColor\".", "locations": [ { "line": 2, "column": 34 } ] } ] }, { "name": "Validate: Fragments on composite types/input object is invalid fragment type", "rule": "FragmentsOnCompositeTypes", "schema": 0, "query": "\n fragment inputFragment on ComplexInput {\n stringField\n }\n ", "errors": [ { "message": "Fragment \"inputFragment\" cannot condition on non composite type \"ComplexInput\".", "locations": [ { "line": 2, "column": 33 } ] } ] }, { "name": "Validate: Fragments on composite types/scalar is invalid inline fragment type", "rule": "FragmentsOnCompositeTypes", "schema": 0, "query": "\n fragment invalidFragment on Pet {\n ... on String {\n barks\n }\n }\n ", "errors": [ { "message": "Fragment cannot condition on non composite type \"String\".", "locations": [ { "line": 3, "column": 16 } ] } ] }, { "name": "Validate: Known argument names/single arg is known", "rule": "KnownArgumentNames", "schema": 0, "query": "\n fragment argOnRequiredArg on Dog {\n doesKnowCommand(dogCommand: SIT)\n }\n ", "errors": [] }, { "name": "Validate: Known argument names/multiple args are known", "rule": "KnownArgumentNames", "schema": 0, "query": "\n fragment multipleArgs on ComplicatedArgs {\n multipleReqs(req1: 1, req2: 2)\n }\n ", "errors": [] }, { "name": "Validate: Known argument names/ignores args of unknown fields", "rule": "KnownArgumentNames", "schema": 0, "query": "\n fragment argOnUnknownField on Dog {\n unknownField(unknownArg: SIT)\n }\n ", "errors": [] }, { "name": "Validate: Known argument names/multiple args in reverse order are known", "rule": "KnownArgumentNames", "schema": 0, "query": "\n fragment multipleArgsReverseOrder on ComplicatedArgs {\n multipleReqs(req2: 2, req1: 1)\n }\n ", "errors": [] }, { "name": "Validate: Known argument names/no args on optional arg", "rule": "KnownArgumentNames", "schema": 0, "query": "\n fragment noArgOnOptionalArg on Dog {\n isHousetrained\n }\n ", "errors": [] }, { "name": "Validate: Known argument names/args are known deeply", "rule": "KnownArgumentNames", "schema": 0, "query": "\n {\n dog {\n doesKnowCommand(dogCommand: SIT)\n }\n human {\n pet {\n ... on Dog {\n doesKnowCommand(dogCommand: SIT)\n }\n }\n }\n }\n ", "errors": [] }, { "name": "Validate: Known argument names/directive args are known", "rule": "KnownArgumentNames", "schema": 0, "query": "\n {\n dog @skip(if: true)\n }\n ", "errors": [] }, { "name": "Validate: Known argument names/undirective args are invalid", "rule": "KnownArgumentNames", "schema": 0, "query": "\n {\n dog @skip(unless: true)\n }\n ", "errors": [ { "message": "Unknown argument \"unless\" on directive \"@skip\".", "locations": [ { "line": 3, "column": 19 } ] } ] }, { "name": "Validate: Known argument names/misspelled directive args are reported", "rule": "KnownArgumentNames", "schema": 0, "query": "\n {\n dog @skip(iff: true)\n }\n ", "errors": [ { "message": "Unknown argument \"iff\" on directive \"@skip\". Did you mean \"if\"?", "locations": [ { "line": 3, "column": 19 } ] } ] }, { "name": "Validate: Known argument names/invalid arg name", "rule": "KnownArgumentNames", "schema": 0, "query": "\n fragment invalidArgName on Dog {\n doesKnowCommand(unknown: true)\n }\n ", "errors": [ { "message": "Unknown argument \"unknown\" on field \"doesKnowCommand\" of type \"Dog\".", "locations": [ { "line": 3, "column": 25 } ] } ] }, { "name": "Validate: Known argument names/misspelled arg name is reported", "rule": "KnownArgumentNames", "schema": 0, "query": "\n fragment invalidArgName on Dog {\n doesKnowCommand(dogcommand: true)\n }\n ", "errors": [ { "message": "Unknown argument \"dogcommand\" on field \"doesKnowCommand\" of type \"Dog\". Did you mean \"dogCommand\"?", "locations": [ { "line": 3, "column": 25 } ] } ] }, { "name": "Validate: Known argument names/unknown args amongst known args", "rule": "KnownArgumentNames", "schema": 0, "query": "\n fragment oneGoodArgOneInvalidArg on Dog {\n doesKnowCommand(whoknows: 1, dogCommand: SIT, unknown: true)\n }\n ", "errors": [ { "message": "Unknown argument \"whoknows\" on field \"doesKnowCommand\" of type \"Dog\".", "locations": [ { "line": 3, "column": 25 } ] }, { "message": "Unknown argument \"unknown\" on field \"doesKnowCommand\" of type \"Dog\".", "locations": [ { "line": 3, "column": 55 } ] } ] }, { "name": "Validate: Known argument names/unknown args deeply", "rule": "KnownArgumentNames", "schema": 0, "query": "\n {\n dog {\n doesKnowCommand(unknown: true)\n }\n human {\n pet {\n ... on Dog {\n doesKnowCommand(unknown: true)\n }\n }\n }\n }\n ", "errors": [ { "message": "Unknown argument \"unknown\" on field \"doesKnowCommand\" of type \"Dog\".", "locations": [ { "line": 4, "column": 27 } ] }, { "message": "Unknown argument \"unknown\" on field \"doesKnowCommand\" of type \"Dog\".", "locations": [ { "line": 9, "column": 31 } ] } ] }, { "name": "Validate: Known directives/with no directives", "rule": "KnownDirectives", "schema": 0, "query": "\n query Foo {\n name\n ...Frag\n }\n\n fragment Frag on Dog {\n name\n }\n ", "errors": [] }, { "name": "Validate: Known directives/with known directives", "rule": "KnownDirectives", "schema": 0, "query": "\n {\n dog @include(if: true) {\n name\n }\n human @skip(if: false) {\n name\n }\n }\n ", "errors": [] }, { "name": "Validate: Known directives/with unknown directive", "rule": "KnownDirectives", "schema": 0, "query": "\n {\n dog @unknown(directive: \"value\") {\n name\n }\n }\n ", "errors": [ { "message": "Unknown directive \"unknown\".", "locations": [ { "line": 3, "column": 13 } ] } ] }, { "name": "Validate: Known directives/with many unknown directives", "rule": "KnownDirectives", "schema": 0, "query": "\n {\n dog @unknown(directive: \"value\") {\n name\n }\n human @unknown(directive: \"value\") {\n name\n pets @unknown(directive: \"value\") {\n name\n }\n }\n }\n ", "errors": [ { "message": "Unknown directive \"unknown\".", "locations": [ { "line": 3, "column": 13 } ] }, { "message": "Unknown directive \"unknown\".", "locations": [ { "line": 6, "column": 15 } ] }, { "message": "Unknown directive \"unknown\".", "locations": [ { "line": 8, "column": 16 } ] } ] }, { "name": "Validate: Known directives/with well placed directives", "rule": "KnownDirectives", "schema": 0, "query": "\n query Foo @onQuery {\n name @include(if: true)\n ...Frag @include(if: true)\n skippedField @skip(if: true)\n ...SkippedFrag @skip(if: true)\n }\n\n mutation Bar @onMutation {\n someField\n }\n ", "errors": [] }, { "name": "Validate: Known directives/with misplaced directives", "rule": "KnownDirectives", "schema": 0, "query": "\n query Foo @include(if: true) {\n name @onQuery\n ...Frag @onQuery\n }\n\n mutation Bar @onQuery {\n someField\n }\n ", "errors": [ { "message": "Directive \"include\" may not be used on QUERY.", "locations": [ { "line": 2, "column": 17 } ] }, { "message": "Directive \"onQuery\" may not be used on FIELD.", "locations": [ { "line": 3, "column": 14 } ] }, { "message": "Directive \"onQuery\" may not be used on FRAGMENT_SPREAD.", "locations": [ { "line": 4, "column": 17 } ] }, { "message": "Directive \"onQuery\" may not be used on MUTATION.", "locations": [ { "line": 7, "column": 20 } ] } ] }, { "name": "Validate: Known fragment names/known fragment names are valid", "rule": "KnownFragmentNames", "schema": 0, "query": "\n {\n human(id: 4) {\n ...HumanFields1\n ... on Human {\n ...HumanFields2\n }\n ... {\n name\n }\n }\n }\n fragment HumanFields1 on Human {\n name\n ...HumanFields3\n }\n fragment HumanFields2 on Human {\n name\n }\n fragment HumanFields3 on Human {\n name\n }\n ", "errors": [] }, { "name": "Validate: Known fragment names/unknown fragment names are invalid", "rule": "KnownFragmentNames", "schema": 0, "query": "\n {\n human(id: 4) {\n ...UnknownFragment1\n ... on Human {\n ...UnknownFragment2\n }\n }\n }\n fragment HumanFields on Human {\n name\n ...UnknownFragment3\n }\n ", "errors": [ { "message": "Unknown fragment \"UnknownFragment1\".", "locations": [ { "line": 4, "column": 14 } ] }, { "message": "Unknown fragment \"UnknownFragment2\".", "locations": [ { "line": 6, "column": 16 } ] }, { "message": "Unknown fragment \"UnknownFragment3\".", "locations": [ { "line": 12, "column": 12 } ] } ] }, { "name": "Validate: Known type names/known type names are valid", "rule": "KnownTypeNames", "schema": 0, "query": "\n query Foo($var: String, $required: [String!]!) {\n user(id: 4) {\n pets { ... on Pet { name }, ...PetFields, ... { name } }\n }\n }\n fragment PetFields on Pet {\n name\n }\n ", "errors": [] }, { "name": "Validate: Known type names/unknown type names are invalid", "rule": "KnownTypeNames", "schema": 0, "query": "\n query Foo($var: JumbledUpLetters) {\n user(id: 4) {\n name\n pets { ... on Badger { name }, ...PetFields }\n }\n }\n fragment PetFields on Peettt {\n name\n }\n ", "errors": [ { "message": "Unknown type \"JumbledUpLetters\".", "locations": [ { "line": 2, "column": 23 } ] }, { "message": "Unknown type \"Badger\".", "locations": [ { "line": 5, "column": 25 } ] }, { "message": "Unknown type \"Peettt\".", "locations": [ { "line": 8, "column": 29 } ] } ] }, { "name": "Validate: Anonymous operation must be alone/no operations", "rule": "LoneAnonymousOperation", "schema": 0, "query": "\n fragment fragA on Type {\n field\n }\n ", "errors": [] }, { "name": "Validate: Anonymous operation must be alone/one anon operation", "rule": "LoneAnonymousOperation", "schema": 0, "query": "\n {\n field\n }\n ", "errors": [] }, { "name": "Validate: Anonymous operation must be alone/multiple named operations", "rule": "LoneAnonymousOperation", "schema": 0, "query": "\n query Foo {\n field\n }\n\n query Bar {\n field\n }\n ", "errors": [] }, { "name": "Validate: Anonymous operation must be alone/anon operation with fragment", "rule": "LoneAnonymousOperation", "schema": 0, "query": "\n {\n ...Foo\n }\n fragment Foo on Type {\n field\n }\n ", "errors": [] }, { "name": "Validate: Anonymous operation must be alone/multiple anon operations", "rule": "LoneAnonymousOperation", "schema": 0, "query": "\n {\n fieldA\n }\n {\n fieldB\n }\n ", "errors": [ { "message": "This anonymous operation must be the only defined operation.", "locations": [ { "line": 2, "column": 7 } ] }, { "message": "This anonymous operation must be the only defined operation.", "locations": [ { "line": 5, "column": 7 } ] } ] }, { "name": "Validate: Anonymous operation must be alone/anon operation with a mutation", "rule": "LoneAnonymousOperation", "schema": 0, "query": "\n {\n fieldA\n }\n mutation Foo {\n fieldB\n }\n ", "errors": [ { "message": "This anonymous operation must be the only defined operation.", "locations": [ { "line": 2, "column": 7 } ] } ] }, { "name": "Validate: Anonymous operation must be alone/anon operation with a subscription", "rule": "LoneAnonymousOperation", "schema": 0, "query": "\n {\n fieldA\n }\n subscription Foo {\n fieldB\n }\n ", "errors": [ { "message": "This anonymous operation must be the only defined operation.", "locations": [ { "line": 2, "column": 7 } ] } ] }, { "name": "Validate: No circular fragment spreads/single reference is valid", "rule": "NoFragmentCycles", "schema": 0, "query": "\n fragment fragA on Dog { ...fragB }\n fragment fragB on Dog { name }\n ", "errors": [] }, { "name": "Validate: No circular fragment spreads/spreading twice is not circular", "rule": "NoFragmentCycles", "schema": 0, "query": "\n fragment fragA on Dog { ...fragB, ...fragB }\n fragment fragB on Dog { name }\n ", "errors": [] }, { "name": "Validate: No circular fragment spreads/spreading twice indirectly is not circular", "rule": "NoFragmentCycles", "schema": 0, "query": "\n fragment fragA on Dog { ...fragB, ...fragC }\n fragment fragB on Dog { ...fragC }\n fragment fragC on Dog { name }\n ", "errors": [] }, { "name": "Validate: No circular fragment spreads/double spread within abstract types", "rule": "NoFragmentCycles", "schema": 0, "query": "\n fragment nameFragment on Pet {\n ... on Dog { name }\n ... on Cat { name }\n }\n\n fragment spreadsInAnon on Pet {\n ... on Dog { ...nameFragment }\n ... on Cat { ...nameFragment }\n }\n ", "errors": [] }, { "name": "Validate: No circular fragment spreads/does not false positive on unknown fragment", "rule": "NoFragmentCycles", "schema": 0, "query": "\n fragment nameFragment on Pet {\n ...UnknownFragment\n }\n ", "errors": [] }, { "name": "Validate: No circular fragment spreads/spreading recursively within field fails", "rule": "NoFragmentCycles", "schema": 0, "query": "\n fragment fragA on Human { relatives { ...fragA } },\n ", "errors": [ { "message": "Cannot spread fragment \"fragA\" within itself.", "locations": [ { "line": 2, "column": 45 } ] } ] }, { "name": "Validate: No circular fragment spreads/no spreading itself directly", "rule": "NoFragmentCycles", "schema": 0, "query": "\n fragment fragA on Dog { ...fragA }\n ", "errors": [ { "message": "Cannot spread fragment \"fragA\" within itself.", "locations": [ { "line": 2, "column": 31 } ] } ] }, { "name": "Validate: No circular fragment spreads/no spreading itself directly within inline fragment", "rule": "NoFragmentCycles", "schema": 0, "query": "\n fragment fragA on Pet {\n ... on Dog {\n ...fragA\n }\n }\n ", "errors": [ { "message": "Cannot spread fragment \"fragA\" within itself.", "locations": [ { "line": 4, "column": 11 } ] } ] }, { "name": "Validate: No circular fragment spreads/no spreading itself indirectly", "rule": "NoFragmentCycles", "schema": 0, "query": "\n fragment fragA on Dog { ...fragB }\n fragment fragB on Dog { ...fragA }\n ", "errors": [ { "message": "Cannot spread fragment \"fragA\" within itself via fragB.", "locations": [ { "line": 2, "column": 31 }, { "line": 3, "column": 31 } ] } ] }, { "name": "Validate: No circular fragment spreads/no spreading itself indirectly reports opposite order", "rule": "NoFragmentCycles", "schema": 0, "query": "\n fragment fragB on Dog { ...fragA }\n fragment fragA on Dog { ...fragB }\n ", "errors": [ { "message": "Cannot spread fragment \"fragB\" within itself via fragA.", "locations": [ { "line": 2, "column": 31 }, { "line": 3, "column": 31 } ] } ] }, { "name": "Validate: No circular fragment spreads/no spreading itself indirectly within inline fragment", "rule": "NoFragmentCycles", "schema": 0, "query": "\n fragment fragA on Pet {\n ... on Dog {\n ...fragB\n }\n }\n fragment fragB on Pet {\n ... on Dog {\n ...fragA\n }\n }\n ", "errors": [ { "message": "Cannot spread fragment \"fragA\" within itself via fragB.", "locations": [ { "line": 4, "column": 11 }, { "line": 9, "column": 11 } ] } ] }, { "name": "Validate: No circular fragment spreads/no spreading itself deeply", "rule": "NoFragmentCycles", "schema": 0, "query": "\n fragment fragA on Dog { ...fragB }\n fragment fragB on Dog { ...fragC }\n fragment fragC on Dog { ...fragO }\n fragment fragX on Dog { ...fragY }\n fragment fragY on Dog { ...fragZ }\n fragment fragZ on Dog { ...fragO }\n fragment fragO on Dog { ...fragP }\n fragment fragP on Dog { ...fragA, ...fragX }\n ", "errors": [ { "message": "Cannot spread fragment \"fragA\" within itself via fragB, fragC, fragO, fragP.", "locations": [ { "line": 2, "column": 31 }, { "line": 3, "column": 31 }, { "line": 4, "column": 31 }, { "line": 8, "column": 31 }, { "line": 9, "column": 31 } ] }, { "message": "Cannot spread fragment \"fragO\" within itself via fragP, fragX, fragY, fragZ.", "locations": [ { "line": 8, "column": 31 }, { "line": 9, "column": 41 }, { "line": 5, "column": 31 }, { "line": 6, "column": 31 }, { "line": 7, "column": 31 } ] } ] }, { "name": "Validate: No circular fragment spreads/no spreading itself deeply two paths", "rule": "NoFragmentCycles", "schema": 0, "query": "\n fragment fragA on Dog { ...fragB, ...fragC }\n fragment fragB on Dog { ...fragA }\n fragment fragC on Dog { ...fragA }\n ", "errors": [ { "message": "Cannot spread fragment \"fragA\" within itself via fragB.", "locations": [ { "line": 2, "column": 31 }, { "line": 3, "column": 31 } ] }, { "message": "Cannot spread fragment \"fragA\" within itself via fragC.", "locations": [ { "line": 2, "column": 41 }, { "line": 4, "column": 31 } ] } ] }, { "name": "Validate: No circular fragment spreads/no spreading itself deeply two paths -- alt traverse order", "rule": "NoFragmentCycles", "schema": 0, "query": "\n fragment fragA on Dog { ...fragC }\n fragment fragB on Dog { ...fragC }\n fragment fragC on Dog { ...fragA, ...fragB }\n ", "errors": [ { "message": "Cannot spread fragment \"fragA\" within itself via fragC.", "locations": [ { "line": 2, "column": 31 }, { "line": 4, "column": 31 } ] }, { "message": "Cannot spread fragment \"fragC\" within itself via fragB.", "locations": [ { "line": 4, "column": 41 }, { "line": 3, "column": 31 } ] } ] }, { "name": "Validate: No circular fragment spreads/no spreading itself deeply and immediately", "rule": "NoFragmentCycles", "schema": 0, "query": "\n fragment fragA on Dog { ...fragB }\n fragment fragB on Dog { ...fragB, ...fragC }\n fragment fragC on Dog { ...fragA, ...fragB }\n ", "errors": [ { "message": "Cannot spread fragment \"fragB\" within itself.", "locations": [ { "line": 3, "column": 31 } ] }, { "message": "Cannot spread fragment \"fragA\" within itself via fragB, fragC.", "locations": [ { "line": 2, "column": 31 }, { "line": 3, "column": 41 }, { "line": 4, "column": 31 } ] }, { "message": "Cannot spread fragment \"fragB\" within itself via fragC.", "locations": [ { "line": 3, "column": 41 }, { "line": 4, "column": 41 } ] } ] }, { "name": "Validate: No undefined variables/all variables defined", "rule": "NoUndefinedVariables", "schema": 0, "query": "\n query Foo($a: String, $b: String, $c: String) {\n field(a: $a, b: $b, c: $c)\n }\n ", "errors": [] }, { "name": "Validate: No undefined variables/all variables deeply defined", "rule": "NoUndefinedVariables", "schema": 0, "query": "\n query Foo($a: String, $b: String, $c: String) {\n field(a: $a) {\n field(b: $b) {\n field(c: $c)\n }\n }\n }\n ", "errors": [] }, { "name": "Validate: No undefined variables/all variables deeply in inline fragments defined", "rule": "NoUndefinedVariables", "schema": 0, "query": "\n query Foo($a: String, $b: String, $c: String) {\n ... on Type {\n field(a: $a) {\n field(b: $b) {\n ... on Type {\n field(c: $c)\n }\n }\n }\n }\n }\n ", "errors": [] }, { "name": "Validate: No undefined variables/all variables in fragments deeply defined", "rule": "NoUndefinedVariables", "schema": 0, "query": "\n query Foo($a: String, $b: String, $c: String) {\n ...FragA\n }\n fragment FragA on Type {\n field(a: $a) {\n ...FragB\n }\n }\n fragment FragB on Type {\n field(b: $b) {\n ...FragC\n }\n }\n fragment FragC on Type {\n field(c: $c)\n }\n ", "errors": [] }, { "name": "Validate: No undefined variables/variable within single fragment defined in multiple operations", "rule": "NoUndefinedVariables", "schema": 0, "query": "\n query Foo($a: String) {\n ...FragA\n }\n query Bar($a: String) {\n ...FragA\n }\n fragment FragA on Type {\n field(a: $a)\n }\n ", "errors": [] }, { "name": "Validate: No undefined variables/variable within fragments defined in operations", "rule": "NoUndefinedVariables", "schema": 0, "query": "\n query Foo($a: String) {\n ...FragA\n }\n query Bar($b: String) {\n ...FragB\n }\n fragment FragA on Type {\n field(a: $a)\n }\n fragment FragB on Type {\n field(b: $b)\n }\n ", "errors": [] }, { "name": "Validate: No undefined variables/variable within recursive fragment defined", "rule": "NoUndefinedVariables", "schema": 0, "query": "\n query Foo($a: String) {\n ...FragA\n }\n fragment FragA on Type {\n field(a: $a) {\n ...FragA\n }\n }\n ", "errors": [] }, { "name": "Validate: No undefined variables/variable not defined", "rule": "NoUndefinedVariables", "schema": 0, "query": "\n query Foo($a: String, $b: String, $c: String) {\n field(a: $a, b: $b, c: $c, d: $d)\n }\n ", "errors": [ { "message": "Variable \"$d\" is not defined by operation \"Foo\".", "locations": [ { "line": 3, "column": 39 }, { "line": 2, "column": 7 } ] } ] }, { "name": "Validate: No undefined variables/variable not defined by un-named query", "rule": "NoUndefinedVariables", "schema": 0, "query": "\n {\n field(a: $a)\n }\n ", "errors": [ { "message": "Variable \"$a\" is not defined.", "locations": [ { "line": 3, "column": 18 }, { "line": 2, "column": 7 } ] } ] }, { "name": "Validate: No undefined variables/multiple variables not defined", "rule": "NoUndefinedVariables", "schema": 0, "query": "\n query Foo($b: String) {\n field(a: $a, b: $b, c: $c)\n }\n ", "errors": [ { "message": "Variable \"$a\" is not defined by operation \"Foo\".", "locations": [ { "line": 3, "column": 18 }, { "line": 2, "column": 7 } ] }, { "message": "Variable \"$c\" is not defined by operation \"Foo\".", "locations": [ { "line": 3, "column": 32 }, { "line": 2, "column": 7 } ] } ] }, { "name": "Validate: No undefined variables/variable in fragment not defined by un-named query", "rule": "NoUndefinedVariables", "schema": 0, "query": "\n {\n ...FragA\n }\n fragment FragA on Type {\n field(a: $a)\n }\n ", "errors": [ { "message": "Variable \"$a\" is not defined.", "locations": [ { "line": 6, "column": 18 }, { "line": 2, "column": 7 } ] } ] }, { "name": "Validate: No undefined variables/variable in fragment not defined by operation", "rule": "NoUndefinedVariables", "schema": 0, "query": "\n query Foo($a: String, $b: String) {\n ...FragA\n }\n fragment FragA on Type {\n field(a: $a) {\n ...FragB\n }\n }\n fragment FragB on Type {\n field(b: $b) {\n ...FragC\n }\n }\n fragment FragC on Type {\n field(c: $c)\n }\n ", "errors": [ { "message": "Variable \"$c\" is not defined by operation \"Foo\".", "locations": [ { "line": 16, "column": 18 }, { "line": 2, "column": 7 } ] } ] }, { "name": "Validate: No undefined variables/multiple variables in fragments not defined", "rule": "NoUndefinedVariables", "schema": 0, "query": "\n query Foo($b: String) {\n ...FragA\n }\n fragment FragA on Type {\n field(a: $a) {\n ...FragB\n }\n }\n fragment FragB on Type {\n field(b: $b) {\n ...FragC\n }\n }\n fragment FragC on Type {\n field(c: $c)\n }\n ", "errors": [ { "message": "Variable \"$a\" is not defined by operation \"Foo\".", "locations": [ { "line": 6, "column": 18 }, { "line": 2, "column": 7 } ] }, { "message": "Variable \"$c\" is not defined by operation \"Foo\".", "locations": [ { "line": 16, "column": 18 }, { "line": 2, "column": 7 } ] } ] }, { "name": "Validate: No undefined variables/single variable in fragment not defined by multiple operations", "rule": "NoUndefinedVariables", "schema": 0, "query": "\n query Foo($a: String) {\n ...FragAB\n }\n query Bar($a: String) {\n ...FragAB\n }\n fragment FragAB on Type {\n field(a: $a, b: $b)\n }\n ", "errors": [ { "message": "Variable \"$b\" is not defined by operation \"Foo\".", "locations": [ { "line": 9, "column": 25 }, { "line": 2, "column": 7 } ] }, { "message": "Variable \"$b\" is not defined by operation \"Bar\".", "locations": [ { "line": 9, "column": 25 }, { "line": 5, "column": 7 } ] } ] }, { "name": "Validate: No undefined variables/variables in fragment not defined by multiple operations", "rule": "NoUndefinedVariables", "schema": 0, "query": "\n query Foo($b: String) {\n ...FragAB\n }\n query Bar($a: String) {\n ...FragAB\n }\n fragment FragAB on Type {\n field(a: $a, b: $b)\n }\n ", "errors": [ { "message": "Variable \"$a\" is not defined by operation \"Foo\".", "locations": [ { "line": 9, "column": 18 }, { "line": 2, "column": 7 } ] }, { "message": "Variable \"$b\" is not defined by operation \"Bar\".", "locations": [ { "line": 9, "column": 25 }, { "line": 5, "column": 7 } ] } ] }, { "name": "Validate: No undefined variables/variable in fragment used by other operation", "rule": "NoUndefinedVariables", "schema": 0, "query": "\n query Foo($b: String) {\n ...FragA\n }\n query Bar($a: String) {\n ...FragB\n }\n fragment FragA on Type {\n field(a: $a)\n }\n fragment FragB on Type {\n field(b: $b)\n }\n ", "errors": [ { "message": "Variable \"$a\" is not defined by operation \"Foo\".", "locations": [ { "line": 9, "column": 18 }, { "line": 2, "column": 7 } ] }, { "message": "Variable \"$b\" is not defined by operation \"Bar\".", "locations": [ { "line": 12, "column": 18 }, { "line": 5, "column": 7 } ] } ] }, { "name": "Validate: No undefined variables/multiple undefined variables produce multiple errors", "rule": "NoUndefinedVariables", "schema": 0, "query": "\n query Foo($b: String) {\n ...FragAB\n }\n query Bar($a: String) {\n ...FragAB\n }\n fragment FragAB on Type {\n field1(a: $a, b: $b)\n ...FragC\n field3(a: $a, b: $b)\n }\n fragment FragC on Type {\n field2(c: $c)\n }\n ", "errors": [ { "message": "Variable \"$a\" is not defined by operation \"Foo\".", "locations": [ { "line": 9, "column": 19 }, { "line": 2, "column": 7 } ] }, { "message": "Variable \"$a\" is not defined by operation \"Foo\".", "locations": [ { "line": 11, "column": 19 }, { "line": 2, "column": 7 } ] }, { "message": "Variable \"$c\" is not defined by operation \"Foo\".", "locations": [ { "line": 14, "column": 19 }, { "line": 2, "column": 7 } ] }, { "message": "Variable \"$b\" is not defined by operation \"Bar\".", "locations": [ { "line": 9, "column": 26 }, { "line": 5, "column": 7 } ] }, { "message": "Variable \"$b\" is not defined by operation \"Bar\".", "locations": [ { "line": 11, "column": 26 }, { "line": 5, "column": 7 } ] }, { "message": "Variable \"$c\" is not defined by operation \"Bar\".", "locations": [ { "line": 14, "column": 19 }, { "line": 5, "column": 7 } ] } ] }, { "name": "Validate: No unused fragments/all fragment names are used", "rule": "NoUnusedFragments", "schema": 0, "query": "\n {\n human(id: 4) {\n ...HumanFields1\n ... on Human {\n ...HumanFields2\n }\n }\n }\n fragment HumanFields1 on Human {\n name\n ...HumanFields3\n }\n fragment HumanFields2 on Human {\n name\n }\n fragment HumanFields3 on Human {\n name\n }\n ", "errors": [] }, { "name": "Validate: No unused fragments/all fragment names are used by multiple operations", "rule": "NoUnusedFragments", "schema": 0, "query": "\n query Foo {\n human(id: 4) {\n ...HumanFields1\n }\n }\n query Bar {\n human(id: 4) {\n ...HumanFields2\n }\n }\n fragment HumanFields1 on Human {\n name\n ...HumanFields3\n }\n fragment HumanFields2 on Human {\n name\n }\n fragment HumanFields3 on Human {\n name\n }\n ", "errors": [] }, { "name": "Validate: No unused fragments/contains unknown fragments", "rule": "NoUnusedFragments", "schema": 0, "query": "\n query Foo {\n human(id: 4) {\n ...HumanFields1\n }\n }\n query Bar {\n human(id: 4) {\n ...HumanFields2\n }\n }\n fragment HumanFields1 on Human {\n name\n ...HumanFields3\n }\n fragment HumanFields2 on Human {\n name\n }\n fragment HumanFields3 on Human {\n name\n }\n fragment Unused1 on Human {\n name\n }\n fragment Unused2 on Human {\n name\n }\n ", "errors": [ { "message": "Fragment \"Unused1\" is never used.", "locations": [ { "line": 22, "column": 7 } ] }, { "message": "Fragment \"Unused2\" is never used.", "locations": [ { "line": 25, "column": 7 } ] } ] }, { "name": "Validate: No unused fragments/contains unknown fragments with ref cycle", "rule": "NoUnusedFragments", "schema": 0, "query": "\n query Foo {\n human(id: 4) {\n ...HumanFields1\n }\n }\n query Bar {\n human(id: 4) {\n ...HumanFields2\n }\n }\n fragment HumanFields1 on Human {\n name\n ...HumanFields3\n }\n fragment HumanFields2 on Human {\n name\n }\n fragment HumanFields3 on Human {\n name\n }\n fragment Unused1 on Human {\n name\n ...Unused2\n }\n fragment Unused2 on Human {\n name\n ...Unused1\n }\n ", "errors": [ { "message": "Fragment \"Unused1\" is never used.", "locations": [ { "line": 22, "column": 7 } ] }, { "message": "Fragment \"Unused2\" is never used.", "locations": [ { "line": 26, "column": 7 } ] } ] }, { "name": "Validate: No unused fragments/contains unknown and undef fragments", "rule": "NoUnusedFragments", "schema": 0, "query": "\n query Foo {\n human(id: 4) {\n ...bar\n }\n }\n fragment foo on Human {\n name\n }\n ", "errors": [ { "message": "Fragment \"foo\" is never used.", "locations": [ { "line": 7, "column": 7 } ] } ] }, { "name": "Validate: No unused variables/uses all variables", "rule": "NoUnusedVariables", "schema": 0, "query": "\n query ($a: String, $b: String, $c: String) {\n field(a: $a, b: $b, c: $c)\n }\n ", "errors": [] }, { "name": "Validate: No unused variables/uses all variables deeply", "rule": "NoUnusedVariables", "schema": 0, "query": "\n query Foo($a: String, $b: String, $c: String) {\n field(a: $a) {\n field(b: $b) {\n field(c: $c)\n }\n }\n }\n ", "errors": [] }, { "name": "Validate: No unused variables/uses all variables deeply in inline fragments", "rule": "NoUnusedVariables", "schema": 0, "query": "\n query Foo($a: String, $b: String, $c: String) {\n ... on Type {\n field(a: $a) {\n field(b: $b) {\n ... on Type {\n field(c: $c)\n }\n }\n }\n }\n }\n ", "errors": [] }, { "name": "Validate: No unused variables/uses all variables in fragments", "rule": "NoUnusedVariables", "schema": 0, "query": "\n query Foo($a: String, $b: String, $c: String) {\n ...FragA\n }\n fragment FragA on Type {\n field(a: $a) {\n ...FragB\n }\n }\n fragment FragB on Type {\n field(b: $b) {\n ...FragC\n }\n }\n fragment FragC on Type {\n field(c: $c)\n }\n ", "errors": [] }, { "name": "Validate: No unused variables/variable used by fragment in multiple operations", "rule": "NoUnusedVariables", "schema": 0, "query": "\n query Foo($a: String) {\n ...FragA\n }\n query Bar($b: String) {\n ...FragB\n }\n fragment FragA on Type {\n field(a: $a)\n }\n fragment FragB on Type {\n field(b: $b)\n }\n ", "errors": [] }, { "name": "Validate: No unused variables/variable used by recursive fragment", "rule": "NoUnusedVariables", "schema": 0, "query": "\n query Foo($a: String) {\n ...FragA\n }\n fragment FragA on Type {\n field(a: $a) {\n ...FragA\n }\n }\n ", "errors": [] }, { "name": "Validate: No unused variables/variable not used", "rule": "NoUnusedVariables", "schema": 0, "query": "\n query ($a: String, $b: String, $c: String) {\n field(a: $a, b: $b)\n }\n ", "errors": [ { "message": "Variable \"$c\" is never used.", "locations": [ { "line": 2, "column": 38 } ] } ] }, { "name": "Validate: No unused variables/multiple variables not used", "rule": "NoUnusedVariables", "schema": 0, "query": "\n query Foo($a: String, $b: String, $c: String) {\n field(b: $b)\n }\n ", "errors": [ { "message": "Variable \"$a\" is never used in operation \"Foo\".", "locations": [ { "line": 2, "column": 17 } ] }, { "message": "Variable \"$c\" is never used in operation \"Foo\".", "locations": [ { "line": 2, "column": 41 } ] } ] }, { "name": "Validate: No unused variables/variable not used in fragments", "rule": "NoUnusedVariables", "schema": 0, "query": "\n query Foo($a: String, $b: String, $c: String) {\n ...FragA\n }\n fragment FragA on Type {\n field(a: $a) {\n ...FragB\n }\n }\n fragment FragB on Type {\n field(b: $b) {\n ...FragC\n }\n }\n fragment FragC on Type {\n field\n }\n ", "errors": [ { "message": "Variable \"$c\" is never used in operation \"Foo\".", "locations": [ { "line": 2, "column": 41 } ] } ] }, { "name": "Validate: No unused variables/multiple variables not used in fragments", "rule": "NoUnusedVariables", "schema": 0, "query": "\n query Foo($a: String, $b: String, $c: String) {\n ...FragA\n }\n fragment FragA on Type {\n field {\n ...FragB\n }\n }\n fragment FragB on Type {\n field(b: $b) {\n ...FragC\n }\n }\n fragment FragC on Type {\n field\n }\n ", "errors": [ { "message": "Variable \"$a\" is never used in operation \"Foo\".", "locations": [ { "line": 2, "column": 17 } ] }, { "message": "Variable \"$c\" is never used in operation \"Foo\".", "locations": [ { "line": 2, "column": 41 } ] } ] }, { "name": "Validate: No unused variables/variable not used by unreferenced fragment", "rule": "NoUnusedVariables", "schema": 0, "query": "\n query Foo($b: String) {\n ...FragA\n }\n fragment FragA on Type {\n field(a: $a)\n }\n fragment FragB on Type {\n field(b: $b)\n }\n ", "errors": [ { "message": "Variable \"$b\" is never used in operation \"Foo\".", "locations": [ { "line": 2, "column": 17 } ] } ] }, { "name": "Validate: No unused variables/variable not used by fragment used by other operation", "rule": "NoUnusedVariables", "schema": 0, "query": "\n query Foo($b: String) {\n ...FragA\n }\n query Bar($a: String) {\n ...FragB\n }\n fragment FragA on Type {\n field(a: $a)\n }\n fragment FragB on Type {\n field(b: $b)\n }\n ", "errors": [ { "message": "Variable \"$b\" is never used in operation \"Foo\".", "locations": [ { "line": 2, "column": 17 } ] }, { "message": "Variable \"$a\" is never used in operation \"Bar\".", "locations": [ { "line": 5, "column": 17 } ] } ] }, { "name": "Validate: Overlapping fields can be merged/unique fields", "rule": "OverlappingFieldsCanBeMerged", "schema": 0, "query": "\n fragment uniqueFields on Dog {\n name\n nickname\n }\n ", "errors": [] }, { "name": "Validate: Overlapping fields can be merged/identical fields", "rule": "OverlappingFieldsCanBeMerged", "schema": 0, "query": "\n fragment mergeIdenticalFields on Dog {\n name\n name\n }\n ", "errors": [] }, { "name": "Validate: Overlapping fields can be merged/identical fields with identical args", "rule": "OverlappingFieldsCanBeMerged", "schema": 0, "query": "\n fragment mergeIdenticalFieldsWithIdenticalArgs on Dog {\n doesKnowCommand(dogCommand: SIT)\n doesKnowCommand(dogCommand: SIT)\n }\n ", "errors": [] }, { "name": "Validate: Overlapping fields can be merged/identical fields with identical directives", "rule": "OverlappingFieldsCanBeMerged", "schema": 0, "query": "\n fragment mergeSameFieldsWithSameDirectives on Dog {\n name @include(if: true)\n name @include(if: true)\n }\n ", "errors": [] }, { "name": "Validate: Overlapping fields can be merged/different args with different aliases", "rule": "OverlappingFieldsCanBeMerged", "schema": 0, "query": "\n fragment differentArgsWithDifferentAliases on Dog {\n knowsSit: doesKnowCommand(dogCommand: SIT)\n knowsDown: doesKnowCommand(dogCommand: DOWN)\n }\n ", "errors": [] }, { "name": "Validate: Overlapping fields can be merged/different directives with different aliases", "rule": "OverlappingFieldsCanBeMerged", "schema": 0, "query": "\n fragment differentDirectivesWithDifferentAliases on Dog {\n nameIfTrue: name @include(if: true)\n nameIfFalse: name @include(if: false)\n }\n ", "errors": [] }, { "name": "Validate: Overlapping fields can be merged/different skip/include directives accepted", "rule": "OverlappingFieldsCanBeMerged", "schema": 0, "query": "\n fragment differentDirectivesWithDifferentAliases on Dog {\n name @include(if: true)\n name @include(if: false)\n }\n ", "errors": [] }, { "name": "Validate: Overlapping fields can be merged/Same aliases with different field targets", "rule": "OverlappingFieldsCanBeMerged", "schema": 0, "query": "\n fragment sameAliasesWithDifferentFieldTargets on Dog {\n fido: name\n fido: nickname\n }\n ", "errors": [ { "message": "Fields \"fido\" conflict because name and nickname are different fields. Use different aliases on the fields to fetch both if this was intentional.", "locations": [ { "line": 3, "column": 9 }, { "line": 4, "column": 9 } ] } ] }, { "name": "Validate: Overlapping fields can be merged/Same aliases allowed on non-overlapping fields", "rule": "OverlappingFieldsCanBeMerged", "schema": 0, "query": "\n fragment sameAliasesWithDifferentFieldTargets on Pet {\n ... on Dog {\n name\n }\n ... on Cat {\n name: nickname\n }\n }\n ", "errors": [] }, { "name": "Validate: Overlapping fields can be merged/Alias masking direct field access", "rule": "OverlappingFieldsCanBeMerged", "schema": 0, "query": "\n fragment aliasMaskingDirectFieldAccess on Dog {\n name: nickname\n name\n }\n ", "errors": [ { "message": "Fields \"name\" conflict because nickname and name are different fields. Use different aliases on the fields to fetch both if this was intentional.", "locations": [ { "line": 3, "column": 9 }, { "line": 4, "column": 9 } ] } ] }, { "name": "Validate: Overlapping fields can be merged/different args, second adds an argument", "rule": "OverlappingFieldsCanBeMerged", "schema": 0, "query": "\n fragment conflictingArgs on Dog {\n doesKnowCommand\n doesKnowCommand(dogCommand: HEEL)\n }\n ", "errors": [ { "message": "Fields \"doesKnowCommand\" conflict because they have differing arguments. Use different aliases on the fields to fetch both if this was intentional.", "locations": [ { "line": 3, "column": 9 }, { "line": 4, "column": 9 } ] } ] }, { "name": "Validate: Overlapping fields can be merged/different args, second missing an argument", "rule": "OverlappingFieldsCanBeMerged", "schema": 0, "query": "\n fragment conflictingArgs on Dog {\n doesKnowCommand(dogCommand: SIT)\n doesKnowCommand\n }\n ", "errors": [ { "message": "Fields \"doesKnowCommand\" conflict because they have differing arguments. Use different aliases on the fields to fetch both if this was intentional.", "locations": [ { "line": 3, "column": 9 }, { "line": 4, "column": 9 } ] } ] }, { "name": "Validate: Overlapping fields can be merged/conflicting args", "rule": "OverlappingFieldsCanBeMerged", "schema": 0, "query": "\n fragment conflictingArgs on Dog {\n doesKnowCommand(dogCommand: SIT)\n doesKnowCommand(dogCommand: HEEL)\n }\n ", "errors": [ { "message": "Fields \"doesKnowCommand\" conflict because they have differing arguments. Use different aliases on the fields to fetch both if this was intentional.", "locations": [ { "line": 3, "column": 9 }, { "line": 4, "column": 9 } ] } ] }, { "name": "Validate: Overlapping fields can be merged/allows different args where no conflict is possible", "rule": "OverlappingFieldsCanBeMerged", "schema": 0, "query": "\n fragment conflictingArgs on Pet {\n ... on Dog {\n name(surname: true)\n }\n ... on Cat {\n name\n }\n }\n ", "errors": [] }, { "name": "Validate: Overlapping fields can be merged/encounters conflict in fragments", "rule": "OverlappingFieldsCanBeMerged", "schema": 0, "query": "\n {\n ...A\n ...B\n }\n fragment A on Type {\n x: a\n }\n fragment B on Type {\n x: b\n }\n ", "errors": [ { "message": "Fields \"x\" conflict because a and b are different fields. Use different aliases on the fields to fetch both if this was intentional.", "locations": [ { "line": 7, "column": 9 }, { "line": 10, "column": 9 } ] } ] }, { "name": "Validate: Overlapping fields can be merged/reports each conflict once", "rule": "OverlappingFieldsCanBeMerged", "schema": 0, "query": "\n {\n f1 {\n ...A\n ...B\n }\n f2 {\n ...B\n ...A\n }\n f3 {\n ...A\n ...B\n x: c\n }\n }\n fragment A on Type {\n x: a\n }\n fragment B on Type {\n x: b\n }\n ", "errors": [ { "message": "Fields \"x\" conflict because a and b are different fields. Use different aliases on the fields to fetch both if this was intentional.", "locations": [ { "line": 18, "column": 9 }, { "line": 21, "column": 9 } ] }, { "message": "Fields \"x\" conflict because c and a are different fields. Use different aliases on the fields to fetch both if this was intentional.", "locations": [ { "line": 14, "column": 11 }, { "line": 18, "column": 9 } ] }, { "message": "Fields \"x\" conflict because c and b are different fields. Use different aliases on the fields to fetch both if this was intentional.", "locations": [ { "line": 14, "column": 11 }, { "line": 21, "column": 9 } ] } ] }, { "name": "Validate: Overlapping fields can be merged/deep conflict", "rule": "OverlappingFieldsCanBeMerged", "schema": 0, "query": "\n {\n field {\n x: a\n },\n field {\n x: b\n }\n }\n ", "errors": [ { "message": "Fields \"field\" conflict because subfields \"x\" conflict because a and b are different fields. Use different aliases on the fields to fetch both if this was intentional.", "locations": [ { "line": 3, "column": 9 }, { "line": 4, "column": 11 }, { "line": 6, "column": 9 }, { "line": 7, "column": 11 } ] } ] }, { "name": "Validate: Overlapping fields can be merged/deep conflict with multiple issues", "rule": "OverlappingFieldsCanBeMerged", "schema": 0, "query": "\n {\n field {\n x: a\n y: c\n },\n field {\n x: b\n y: d\n }\n }\n ", "errors": [ { "message": "Fields \"field\" conflict because subfields \"x\" conflict because a and b are different fields and subfields \"y\" conflict because c and d are different fields. Use different aliases on the fields to fetch both if this was intentional.", "locations": [ { "line": 3, "column": 9 }, { "line": 4, "column": 11 }, { "line": 5, "column": 11 }, { "line": 7, "column": 9 }, { "line": 8, "column": 11 }, { "line": 9, "column": 11 } ] } ] }, { "name": "Validate: Overlapping fields can be merged/very deep conflict", "rule": "OverlappingFieldsCanBeMerged", "schema": 0, "query": "\n {\n field {\n deepField {\n x: a\n }\n },\n field {\n deepField {\n x: b\n }\n }\n }\n ", "errors": [ { "message": "Fields \"field\" conflict because subfields \"deepField\" conflict because subfields \"x\" conflict because a and b are different fields. Use different aliases on the fields to fetch both if this was intentional.", "locations": [ { "line": 3, "column": 9 }, { "line": 4, "column": 11 }, { "line": 5, "column": 13 }, { "line": 8, "column": 9 }, { "line": 9, "column": 11 }, { "line": 10, "column": 13 } ] } ] }, { "name": "Validate: Overlapping fields can be merged/reports deep conflict to nearest common ancestor", "rule": "OverlappingFieldsCanBeMerged", "schema": 0, "query": "\n {\n field {\n deepField {\n x: a\n }\n deepField {\n x: b\n }\n },\n field {\n deepField {\n y\n }\n }\n }\n ", "errors": [ { "message": "Fields \"deepField\" conflict because subfields \"x\" conflict because a and b are different fields. Use different aliases on the fields to fetch both if this was intentional.", "locations": [ { "line": 4, "column": 11 }, { "line": 5, "column": 13 }, { "line": 7, "column": 11 }, { "line": 8, "column": 13 } ] } ] }, { "name": "Validate: Overlapping fields can be merged/reports deep conflict to nearest common ancestor in fragments", "rule": "OverlappingFieldsCanBeMerged", "schema": 0, "query": "\n {\n field {\n ...F\n }\n field {\n ...F\n }\n }\n fragment F on T {\n deepField {\n deeperField {\n x: a\n }\n deeperField {\n x: b\n }\n },\n deepField {\n deeperField {\n y\n }\n }\n }\n ", "errors": [ { "message": "Fields \"deeperField\" conflict because subfields \"x\" conflict because a and b are different fields. Use different aliases on the fields to fetch both if this was intentional.", "locations": [ { "line": 12, "column": 11 }, { "line": 13, "column": 13 }, { "line": 15, "column": 11 }, { "line": 16, "column": 13 } ] } ] }, { "name": "Validate: Overlapping fields can be merged/reports deep conflict in nested fragments", "rule": "OverlappingFieldsCanBeMerged", "schema": 0, "query": "\n {\n field {\n ...F\n }\n field {\n ...I\n }\n }\n fragment F on T {\n x: a\n ...G\n }\n fragment G on T {\n y: c\n }\n fragment I on T {\n y: d\n ...J\n }\n fragment J on T {\n x: b\n }\n ", "errors": [ { "message": "Fields \"field\" conflict because subfields \"x\" conflict because a and b are different fields and subfields \"y\" conflict because c and d are different fields. Use different aliases on the fields to fetch both if this was intentional.", "locations": [ { "line": 3, "column": 9 }, { "line": 11, "column": 9 }, { "line": 15, "column": 9 }, { "line": 6, "column": 9 }, { "line": 22, "column": 9 }, { "line": 18, "column": 9 } ] } ] }, { "name": "Validate: Overlapping fields can be merged/ignores unknown fragments", "rule": "OverlappingFieldsCanBeMerged", "schema": 0, "query": "\n {\n field\n ...Unknown\n ...Known\n }\n\n fragment Known on T {\n field\n ...OtherUnknown\n }\n ", "errors": [] }, { "name": "Validate: Overlapping fields can be merged/return types must be unambiguous/conflicting return types which potentially overlap", "rule": "OverlappingFieldsCanBeMerged", "schema": 1, "query": "\n {\n someBox {\n ...on IntBox {\n scalar\n }\n ...on NonNullStringBox1 {\n scalar\n }\n }\n }\n ", "errors": [ { "message": "Fields \"scalar\" conflict because they return conflicting types Int and String!. Use different aliases on the fields to fetch both if this was intentional.", "locations": [ { "line": 5, "column": 15 }, { "line": 8, "column": 15 } ] } ] }, { "name": "Validate: Overlapping fields can be merged/return types must be unambiguous/compatible return shapes on different return types", "rule": "OverlappingFieldsCanBeMerged", "schema": 1, "query": "\n {\n someBox {\n ... on SomeBox {\n deepBox {\n unrelatedField\n }\n }\n ... on StringBox {\n deepBox {\n unrelatedField\n }\n }\n }\n }\n ", "errors": [] }, { "name": "Validate: Overlapping fields can be merged/return types must be unambiguous/disallows differing return types despite no overlap", "rule": "OverlappingFieldsCanBeMerged", "schema": 1, "query": "\n {\n someBox {\n ... on IntBox {\n scalar\n }\n ... on StringBox {\n scalar\n }\n }\n }\n ", "errors": [ { "message": "Fields \"scalar\" conflict because they return conflicting types Int and String. Use different aliases on the fields to fetch both if this was intentional.", "locations": [ { "line": 5, "column": 15 }, { "line": 8, "column": 15 } ] } ] }, { "name": "Validate: Overlapping fields can be merged/return types must be unambiguous/disallows differing return type nullability despite no overlap", "rule": "OverlappingFieldsCanBeMerged", "schema": 1, "query": "\n {\n someBox {\n ... on NonNullStringBox1 {\n scalar\n }\n ... on StringBox {\n scalar\n }\n }\n }\n ", "errors": [ { "message": "Fields \"scalar\" conflict because they return conflicting types String! and String. Use different aliases on the fields to fetch both if this was intentional.", "locations": [ { "line": 5, "column": 15 }, { "line": 8, "column": 15 } ] } ] }, { "name": "Validate: Overlapping fields can be merged/return types must be unambiguous/disallows differing return type list despite no overlap", "rule": "OverlappingFieldsCanBeMerged", "schema": 1, "query": "\n {\n someBox {\n ... on IntBox {\n box: listStringBox {\n scalar\n }\n }\n ... on StringBox {\n box: stringBox {\n scalar\n }\n }\n }\n }\n ", "errors": [ { "message": "Fields \"box\" conflict because they return conflicting types [StringBox] and StringBox. Use different aliases on the fields to fetch both if this was intentional.", "locations": [ { "line": 5, "column": 15 }, { "line": 10, "column": 15 } ] } ] }, { "name": "Validate: Overlapping fields can be merged/return types must be unambiguous/disallows differing return type list despite no overlap", "rule": "OverlappingFieldsCanBeMerged", "schema": 1, "query": "\n {\n someBox {\n ... on IntBox {\n box: stringBox {\n scalar\n }\n }\n ... on StringBox {\n box: listStringBox {\n scalar\n }\n }\n }\n }\n ", "errors": [ { "message": "Fields \"box\" conflict because they return conflicting types StringBox and [StringBox]. Use different aliases on the fields to fetch both if this was intentional.", "locations": [ { "line": 5, "column": 15 }, { "line": 10, "column": 15 } ] } ] }, { "name": "Validate: Overlapping fields can be merged/return types must be unambiguous/disallows differing deep return types despite no overlap", "rule": "OverlappingFieldsCanBeMerged", "schema": 1, "query": "\n {\n someBox {\n ... on IntBox {\n box: stringBox {\n scalar\n }\n }\n ... on StringBox {\n box: intBox {\n scalar\n }\n }\n }\n }\n ", "errors": [ { "message": "Fields \"box\" conflict because subfields \"scalar\" conflict because they return conflicting types String and Int. Use different aliases on the fields to fetch both if this was intentional.", "locations": [ { "line": 5, "column": 15 }, { "line": 6, "column": 17 }, { "line": 10, "column": 15 }, { "line": 11, "column": 17 } ] } ] }, { "name": "Validate: Overlapping fields can be merged/return types must be unambiguous/allows non-conflicting overlaping types", "rule": "OverlappingFieldsCanBeMerged", "schema": 1, "query": "\n {\n someBox {\n ... on IntBox {\n scalar: unrelatedField\n }\n ... on StringBox {\n scalar\n }\n }\n }\n ", "errors": [] }, { "name": "Validate: Overlapping fields can be merged/return types must be unambiguous/same wrapped scalar return types", "rule": "OverlappingFieldsCanBeMerged", "schema": 1, "query": "\n {\n someBox {\n ...on NonNullStringBox1 {\n scalar\n }\n ...on NonNullStringBox2 {\n scalar\n }\n }\n }\n ", "errors": [] }, { "name": "Validate: Overlapping fields can be merged/return types must be unambiguous/allows inline typeless fragments", "rule": "OverlappingFieldsCanBeMerged", "schema": 1, "query": "\n {\n a\n ... {\n a\n }\n }\n ", "errors": [] }, { "name": "Validate: Overlapping fields can be merged/return types must be unambiguous/compares deep types including list", "rule": "OverlappingFieldsCanBeMerged", "schema": 1, "query": "\n {\n connection {\n ...edgeID\n edges {\n node {\n id: name\n }\n }\n }\n }\n\n fragment edgeID on Connection {\n edges {\n node {\n id\n }\n }\n }\n ", "errors": [ { "message": "Fields \"edges\" conflict because subfields \"node\" conflict because subfields \"id\" conflict because name and id are different fields. Use different aliases on the fields to fetch both if this was intentional.", "locations": [ { "line": 5, "column": 13 }, { "line": 6, "column": 15 }, { "line": 7, "column": 17 }, { "line": 14, "column": 11 }, { "line": 15, "column": 13 }, { "line": 16, "column": 15 } ] } ] }, { "name": "Validate: Overlapping fields can be merged/return types must be unambiguous/ignores unknown types", "rule": "OverlappingFieldsCanBeMerged", "schema": 1, "query": "\n {\n someBox {\n ...on UnknownType {\n scalar\n }\n ...on NonNullStringBox2 {\n scalar\n }\n }\n }\n ", "errors": [] }, { "name": "Validate: Overlapping fields can be merged/return types must be unambiguous/works for field names that are JS keywords", "rule": "OverlappingFieldsCanBeMerged", "schema": 2, "query": "{\n foo {\n constructor\n }\n }", "errors": [] }, { "name": "Validate: Overlapping fields can be merged/does not infinite loop on recursive fragment", "rule": "OverlappingFieldsCanBeMerged", "schema": 0, "query": "\n fragment fragA on Human { name, relatives { name, ...fragA } }\n ", "errors": [] }, { "name": "Validate: Overlapping fields can be merged/does not infinite loop on immediately recursive fragment", "rule": "OverlappingFieldsCanBeMerged", "schema": 0, "query": "\n fragment fragA on Human { name, ...fragA }\n ", "errors": [] }, { "name": "Validate: Overlapping fields can be merged/does not infinite loop on transitively recursive fragment", "rule": "OverlappingFieldsCanBeMerged", "schema": 0, "query": "\n fragment fragA on Human { name, ...fragB }\n fragment fragB on Human { name, ...fragC }\n fragment fragC on Human { name, ...fragA }\n ", "errors": [] }, { "name": "Validate: Overlapping fields can be merged/finds invalid case even with immediately recursive fragment", "rule": "OverlappingFieldsCanBeMerged", "schema": 0, "query": "\n fragment sameAliasesWithDifferentFieldTargets on Dog {\n ...sameAliasesWithDifferentFieldTargets\n fido: name\n fido: nickname\n }\n ", "errors": [ { "message": "Fields \"fido\" conflict because name and nickname are different fields. Use different aliases on the fields to fetch both if this was intentional.", "locations": [ { "line": 4, "column": 9 }, { "line": 5, "column": 9 } ] } ] }, { "name": "Validate: Possible fragment spreads/of the same object", "rule": "PossibleFragmentSpreads", "schema": 0, "query": "\n fragment objectWithinObject on Dog { ...dogFragment }\n fragment dogFragment on Dog { barkVolume }\n ", "errors": [] }, { "name": "Validate: Possible fragment spreads/of the same object with inline fragment", "rule": "PossibleFragmentSpreads", "schema": 0, "query": "\n fragment objectWithinObjectAnon on Dog { ... on Dog { barkVolume } }\n ", "errors": [] }, { "name": "Validate: Possible fragment spreads/object into an implemented interface", "rule": "PossibleFragmentSpreads", "schema": 0, "query": "\n fragment objectWithinInterface on Pet { ...dogFragment }\n fragment dogFragment on Dog { barkVolume }\n ", "errors": [] }, { "name": "Validate: Possible fragment spreads/object into containing union", "rule": "PossibleFragmentSpreads", "schema": 0, "query": "\n fragment objectWithinUnion on CatOrDog { ...dogFragment }\n fragment dogFragment on Dog { barkVolume }\n ", "errors": [] }, { "name": "Validate: Possible fragment spreads/union into contained object", "rule": "PossibleFragmentSpreads", "schema": 0, "query": "\n fragment unionWithinObject on Dog { ...catOrDogFragment }\n fragment catOrDogFragment on CatOrDog { __typename }\n ", "errors": [] }, { "name": "Validate: Possible fragment spreads/union into overlapping interface", "rule": "PossibleFragmentSpreads", "schema": 0, "query": "\n fragment unionWithinInterface on Pet { ...catOrDogFragment }\n fragment catOrDogFragment on CatOrDog { __typename }\n ", "errors": [] }, { "name": "Validate: Possible fragment spreads/union into overlapping union", "rule": "PossibleFragmentSpreads", "schema": 0, "query": "\n fragment unionWithinUnion on DogOrHuman { ...catOrDogFragment }\n fragment catOrDogFragment on CatOrDog { __typename }\n ", "errors": [] }, { "name": "Validate: Possible fragment spreads/interface into implemented object", "rule": "PossibleFragmentSpreads", "schema": 0, "query": "\n fragment interfaceWithinObject on Dog { ...petFragment }\n fragment petFragment on Pet { name }\n ", "errors": [] }, { "name": "Validate: Possible fragment spreads/interface into overlapping interface", "rule": "PossibleFragmentSpreads", "schema": 0, "query": "\n fragment interfaceWithinInterface on Pet { ...beingFragment }\n fragment beingFragment on Being { name }\n ", "errors": [] }, { "name": "Validate: Possible fragment spreads/interface into overlapping interface in inline fragment", "rule": "PossibleFragmentSpreads", "schema": 0, "query": "\n fragment interfaceWithinInterface on Pet { ... on Being { name } }\n ", "errors": [] }, { "name": "Validate: Possible fragment spreads/interface into overlapping union", "rule": "PossibleFragmentSpreads", "schema": 0, "query": "\n fragment interfaceWithinUnion on CatOrDog { ...petFragment }\n fragment petFragment on Pet { name }\n ", "errors": [] }, { "name": "Validate: Possible fragment spreads/ignores incorrect type (caught by FragmentsOnCompositeTypes)", "rule": "PossibleFragmentSpreads", "schema": 0, "query": "\n fragment petFragment on Pet { ...badInADifferentWay }\n fragment badInADifferentWay on String { name }\n ", "errors": [] }, { "name": "Validate: Possible fragment spreads/different object into object", "rule": "PossibleFragmentSpreads", "schema": 0, "query": "\n fragment invalidObjectWithinObject on Cat { ...dogFragment }\n fragment dogFragment on Dog { barkVolume }\n ", "errors": [ { "message": "Fragment \"dogFragment\" cannot be spread here as objects of type \"Cat\" can never be of type \"Dog\".", "locations": [ { "line": 2, "column": 51 } ] } ] }, { "name": "Validate: Possible fragment spreads/different object into object in inline fragment", "rule": "PossibleFragmentSpreads", "schema": 0, "query": "\n fragment invalidObjectWithinObjectAnon on Cat {\n ... on Dog { barkVolume }\n }\n ", "errors": [ { "message": "Fragment cannot be spread here as objects of type \"Cat\" can never be of type \"Dog\".", "locations": [ { "line": 3, "column": 9 } ] } ] }, { "name": "Validate: Possible fragment spreads/object into not implementing interface", "rule": "PossibleFragmentSpreads", "schema": 0, "query": "\n fragment invalidObjectWithinInterface on Pet { ...humanFragment }\n fragment humanFragment on Human { pets { name } }\n ", "errors": [ { "message": "Fragment \"humanFragment\" cannot be spread here as objects of type \"Pet\" can never be of type \"Human\".", "locations": [ { "line": 2, "column": 54 } ] } ] }, { "name": "Validate: Possible fragment spreads/object into not containing union", "rule": "PossibleFragmentSpreads", "schema": 0, "query": "\n fragment invalidObjectWithinUnion on CatOrDog { ...humanFragment }\n fragment humanFragment on Human { pets { name } }\n ", "errors": [ { "message": "Fragment \"humanFragment\" cannot be spread here as objects of type \"CatOrDog\" can never be of type \"Human\".", "locations": [ { "line": 2, "column": 55 } ] } ] }, { "name": "Validate: Possible fragment spreads/union into not contained object", "rule": "PossibleFragmentSpreads", "schema": 0, "query": "\n fragment invalidUnionWithinObject on Human { ...catOrDogFragment }\n fragment catOrDogFragment on CatOrDog { __typename }\n ", "errors": [ { "message": "Fragment \"catOrDogFragment\" cannot be spread here as objects of type \"Human\" can never be of type \"CatOrDog\".", "locations": [ { "line": 2, "column": 52 } ] } ] }, { "name": "Validate: Possible fragment spreads/union into non overlapping interface", "rule": "PossibleFragmentSpreads", "schema": 0, "query": "\n fragment invalidUnionWithinInterface on Pet { ...humanOrAlienFragment }\n fragment humanOrAlienFragment on HumanOrAlien { __typename }\n ", "errors": [ { "message": "Fragment \"humanOrAlienFragment\" cannot be spread here as objects of type \"Pet\" can never be of type \"HumanOrAlien\".", "locations": [ { "line": 2, "column": 53 } ] } ] }, { "name": "Validate: Possible fragment spreads/union into non overlapping union", "rule": "PossibleFragmentSpreads", "schema": 0, "query": "\n fragment invalidUnionWithinUnion on CatOrDog { ...humanOrAlienFragment }\n fragment humanOrAlienFragment on HumanOrAlien { __typename }\n ", "errors": [ { "message": "Fragment \"humanOrAlienFragment\" cannot be spread here as objects of type \"CatOrDog\" can never be of type \"HumanOrAlien\".", "locations": [ { "line": 2, "column": 54 } ] } ] }, { "name": "Validate: Possible fragment spreads/interface into non implementing object", "rule": "PossibleFragmentSpreads", "schema": 0, "query": "\n fragment invalidInterfaceWithinObject on Cat { ...intelligentFragment }\n fragment intelligentFragment on Intelligent { iq }\n ", "errors": [ { "message": "Fragment \"intelligentFragment\" cannot be spread here as objects of type \"Cat\" can never be of type \"Intelligent\".", "locations": [ { "line": 2, "column": 54 } ] } ] }, { "name": "Validate: Possible fragment spreads/interface into non overlapping interface", "rule": "PossibleFragmentSpreads", "schema": 0, "query": "\n fragment invalidInterfaceWithinInterface on Pet {\n ...intelligentFragment\n }\n fragment intelligentFragment on Intelligent { iq }\n ", "errors": [ { "message": "Fragment \"intelligentFragment\" cannot be spread here as objects of type \"Pet\" can never be of type \"Intelligent\".", "locations": [ { "line": 3, "column": 9 } ] } ] }, { "name": "Validate: Possible fragment spreads/interface into non overlapping interface in inline fragment", "rule": "PossibleFragmentSpreads", "schema": 0, "query": "\n fragment invalidInterfaceWithinInterfaceAnon on Pet {\n ...on Intelligent { iq }\n }\n ", "errors": [ { "message": "Fragment cannot be spread here as objects of type \"Pet\" can never be of type \"Intelligent\".", "locations": [ { "line": 3, "column": 9 } ] } ] }, { "name": "Validate: Possible fragment spreads/interface into non overlapping union", "rule": "PossibleFragmentSpreads", "schema": 0, "query": "\n fragment invalidInterfaceWithinUnion on HumanOrAlien { ...petFragment }\n fragment petFragment on Pet { name }\n ", "errors": [ { "message": "Fragment \"petFragment\" cannot be spread here as objects of type \"HumanOrAlien\" can never be of type \"Pet\".", "locations": [ { "line": 2, "column": 62 } ] } ] }, { "name": "Validate: Provided required arguments/ignores unknown arguments", "rule": "ProvidedRequiredArguments", "schema": 0, "query": "\n {\n dog {\n isHousetrained(unknownArgument: true)\n }\n }\n ", "errors": [] }, { "name": "Validate: Provided required arguments/Valid non-nullable value/Arg on optional arg", "rule": "ProvidedRequiredArguments", "schema": 0, "query": "\n {\n dog {\n isHousetrained(atOtherHomes: true)\n }\n }\n ", "errors": [] }, { "name": "Validate: Provided required arguments/Valid non-nullable value/No Arg on optional arg", "rule": "ProvidedRequiredArguments", "schema": 0, "query": "\n {\n dog {\n isHousetrained\n }\n }\n ", "errors": [] }, { "name": "Validate: Provided required arguments/Valid non-nullable value/No arg on non-null field with default", "rule": "ProvidedRequiredArguments", "schema": 0, "query": "\n {\n complicatedArgs {\n nonNullFieldWithDefault\n }\n }\n ", "errors": [] }, { "name": "Validate: Provided required arguments/Valid non-nullable value/Multiple args", "rule": "ProvidedRequiredArguments", "schema": 0, "query": "\n {\n complicatedArgs {\n multipleReqs(req1: 1, req2: 2)\n }\n }\n ", "errors": [] }, { "name": "Validate: Provided required arguments/Valid non-nullable value/Multiple args reverse order", "rule": "ProvidedRequiredArguments", "schema": 0, "query": "\n {\n complicatedArgs {\n multipleReqs(req2: 2, req1: 1)\n }\n }\n ", "errors": [] }, { "name": "Validate: Provided required arguments/Valid non-nullable value/No args on multiple optional", "rule": "ProvidedRequiredArguments", "schema": 0, "query": "\n {\n complicatedArgs {\n multipleOpts\n }\n }\n ", "errors": [] }, { "name": "Validate: Provided required arguments/Valid non-nullable value/One arg on multiple optional", "rule": "ProvidedRequiredArguments", "schema": 0, "query": "\n {\n complicatedArgs {\n multipleOpts(opt1: 1)\n }\n }\n ", "errors": [] }, { "name": "Validate: Provided required arguments/Valid non-nullable value/Second arg on multiple optional", "rule": "ProvidedRequiredArguments", "schema": 0, "query": "\n {\n complicatedArgs {\n multipleOpts(opt2: 1)\n }\n }\n ", "errors": [] }, { "name": "Validate: Provided required arguments/Valid non-nullable value/Multiple reqs on mixedList", "rule": "ProvidedRequiredArguments", "schema": 0, "query": "\n {\n complicatedArgs {\n multipleOptAndReq(req1: 3, req2: 4)\n }\n }\n ", "errors": [] }, { "name": "Validate: Provided required arguments/Valid non-nullable value/Multiple reqs and one opt on mixedList", "rule": "ProvidedRequiredArguments", "schema": 0, "query": "\n {\n complicatedArgs {\n multipleOptAndReq(req1: 3, req2: 4, opt1: 5)\n }\n }\n ", "errors": [] }, { "name": "Validate: Provided required arguments/Valid non-nullable value/All reqs and opts on mixedList", "rule": "ProvidedRequiredArguments", "schema": 0, "query": "\n {\n complicatedArgs {\n multipleOptAndReq(req1: 3, req2: 4, opt1: 5, opt2: 6)\n }\n }\n ", "errors": [] }, { "name": "Validate: Provided required arguments/Invalid non-nullable value/Missing one non-nullable argument", "rule": "ProvidedRequiredArguments", "schema": 0, "query": "\n {\n complicatedArgs {\n multipleReqs(req2: 2)\n }\n }\n ", "errors": [ { "message": "Field \"multipleReqs\" argument \"req1\" of type \"Int!\" is required but not provided.", "locations": [ { "line": 4, "column": 13 } ] } ] }, { "name": "Validate: Provided required arguments/Invalid non-nullable value/Missing multiple non-nullable arguments", "rule": "ProvidedRequiredArguments", "schema": 0, "query": "\n {\n complicatedArgs {\n multipleReqs\n }\n }\n ", "errors": [ { "message": "Field \"multipleReqs\" argument \"req1\" of type \"Int!\" is required but not provided.", "locations": [ { "line": 4, "column": 13 } ] }, { "message": "Field \"multipleReqs\" argument \"req2\" of type \"Int!\" is required but not provided.", "locations": [ { "line": 4, "column": 13 } ] } ] }, { "name": "Validate: Provided required arguments/Invalid non-nullable value/Incorrect value and missing argument", "rule": "ProvidedRequiredArguments", "schema": 0, "query": "\n {\n complicatedArgs {\n multipleReqs(req1: \"one\")\n }\n }\n ", "errors": [ { "message": "Field \"multipleReqs\" argument \"req2\" of type \"Int!\" is required but not provided.", "locations": [ { "line": 4, "column": 13 } ] } ] }, { "name": "Validate: Provided required arguments/Directive arguments/ignores unknown directives", "rule": "ProvidedRequiredArguments", "schema": 0, "query": "\n {\n dog @unknown\n }\n ", "errors": [] }, { "name": "Validate: Provided required arguments/Directive arguments/with directives of valid types", "rule": "ProvidedRequiredArguments", "schema": 0, "query": "\n {\n dog @include(if: true) {\n name\n }\n human @skip(if: false) {\n name\n }\n }\n ", "errors": [] }, { "name": "Validate: Provided required arguments/Directive arguments/with directive with missing types", "rule": "ProvidedRequiredArguments", "schema": 0, "query": "\n {\n dog @include {\n name @skip\n }\n }\n ", "errors": [ { "message": "Directive \"@include\" argument \"if\" of type \"Boolean!\" is required but not provided.", "locations": [ { "line": 3, "column": 15 } ] }, { "message": "Directive \"@skip\" argument \"if\" of type \"Boolean!\" is required but not provided.", "locations": [ { "line": 4, "column": 18 } ] } ] }, { "name": "Validate: Scalar leafs/valid scalar selection", "rule": "ScalarLeafs", "schema": 0, "query": "\n fragment scalarSelection on Dog {\n barks\n }\n ", "errors": [] }, { "name": "Validate: Scalar leafs/object type missing selection", "rule": "ScalarLeafs", "schema": 0, "query": "\n query directQueryOnObjectWithoutSubFields {\n human\n }\n ", "errors": [ { "message": "Field \"human\" of type \"Human\" must have a selection of subfields. Did you mean \"human { ... }\"?", "locations": [ { "line": 3, "column": 9 } ] } ] }, { "name": "Validate: Scalar leafs/interface type missing selection", "rule": "ScalarLeafs", "schema": 0, "query": "\n {\n human { pets }\n }\n ", "errors": [ { "message": "Field \"pets\" of type \"[Pet]\" must have a selection of subfields. Did you mean \"pets { ... }\"?", "locations": [ { "line": 3, "column": 17 } ] } ] }, { "name": "Validate: Scalar leafs/valid scalar selection with args", "rule": "ScalarLeafs", "schema": 0, "query": "\n fragment scalarSelectionWithArgs on Dog {\n doesKnowCommand(dogCommand: SIT)\n }\n ", "errors": [] }, { "name": "Validate: Scalar leafs/scalar selection not allowed on Boolean", "rule": "ScalarLeafs", "schema": 0, "query": "\n fragment scalarSelectionsNotAllowedOnBoolean on Dog {\n barks { sinceWhen }\n }\n ", "errors": [ { "message": "Field \"barks\" must not have a selection since type \"Boolean\" has no subfields.", "locations": [ { "line": 3, "column": 15 } ] } ] }, { "name": "Validate: Scalar leafs/scalar selection not allowed on Enum", "rule": "ScalarLeafs", "schema": 0, "query": "\n fragment scalarSelectionsNotAllowedOnEnum on Cat {\n furColor { inHexdec }\n }\n ", "errors": [ { "message": "Field \"furColor\" must not have a selection since type \"FurColor\" has no subfields.", "locations": [ { "line": 3, "column": 18 } ] } ] }, { "name": "Validate: Scalar leafs/scalar selection not allowed with args", "rule": "ScalarLeafs", "schema": 0, "query": "\n fragment scalarSelectionsNotAllowedWithArgs on Dog {\n doesKnowCommand(dogCommand: SIT) { sinceWhen }\n }\n ", "errors": [ { "message": "Field \"doesKnowCommand\" must not have a selection since type \"Boolean\" has no subfields.", "locations": [ { "line": 3, "column": 42 } ] } ] }, { "name": "Validate: Scalar leafs/Scalar selection not allowed with directives", "rule": "ScalarLeafs", "schema": 0, "query": "\n fragment scalarSelectionsNotAllowedWithDirectives on Dog {\n name @include(if: true) { isAlsoHumanName }\n }\n ", "errors": [ { "message": "Field \"name\" must not have a selection since type \"String\" has no subfields.", "locations": [ { "line": 3, "column": 33 } ] } ] }, { "name": "Validate: Scalar leafs/Scalar selection not allowed with directives and args", "rule": "ScalarLeafs", "schema": 0, "query": "\n fragment scalarSelectionsNotAllowedWithDirectivesAndArgs on Dog {\n doesKnowCommand(dogCommand: SIT) @include(if: true) { sinceWhen }\n }\n ", "errors": [ { "message": "Field \"doesKnowCommand\" must not have a selection since type \"Boolean\" has no subfields.", "locations": [ { "line": 3, "column": 61 } ] } ] }, { "name": "Validate: Subscriptions with single field/valid subscription", "rule": "SingleFieldSubscriptions", "schema": 0, "query": "\n subscription ImportantEmails {\n importantEmails\n }\n ", "errors": [] }, { "name": "Validate: Subscriptions with single field/fails with more than one root field", "rule": "SingleFieldSubscriptions", "schema": 0, "query": "\n subscription ImportantEmails {\n importantEmails\n notImportantEmails\n }\n ", "errors": [ { "message": "Subscription \"ImportantEmails\" must select only one top level field.", "locations": [ { "line": 4, "column": 9 } ] } ] }, { "name": "Validate: Subscriptions with single field/fails with more than one root field including introspection", "rule": "SingleFieldSubscriptions", "schema": 0, "query": "\n subscription ImportantEmails {\n importantEmails\n __typename\n }\n ", "errors": [ { "message": "Subscription \"ImportantEmails\" must select only one top level field.", "locations": [ { "line": 4, "column": 9 } ] } ] }, { "name": "Validate: Subscriptions with single field/fails with many more than one root field", "rule": "SingleFieldSubscriptions", "schema": 0, "query": "\n subscription ImportantEmails {\n importantEmails\n notImportantEmails\n spamEmails\n }\n ", "errors": [ { "message": "Subscription \"ImportantEmails\" must select only one top level field.", "locations": [ { "line": 4, "column": 9 }, { "line": 5, "column": 9 } ] } ] }, { "name": "Validate: Subscriptions with single field/fails with more than one root field in anonymous subscriptions", "rule": "SingleFieldSubscriptions", "schema": 0, "query": "\n subscription {\n importantEmails\n notImportantEmails\n }\n ", "errors": [ { "message": "Anonymous Subscription must select only one top level field.", "locations": [ { "line": 4, "column": 9 } ] } ] }, { "name": "Validate: Unique argument names/no arguments on field", "rule": "UniqueArgumentNames", "schema": 0, "query": "\n {\n field\n }\n ", "errors": [] }, { "name": "Validate: Unique argument names/no arguments on directive", "rule": "UniqueArgumentNames", "schema": 0, "query": "\n {\n field @directive\n }\n ", "errors": [] }, { "name": "Validate: Unique argument names/argument on field", "rule": "UniqueArgumentNames", "schema": 0, "query": "\n {\n field(arg: \"value\")\n }\n ", "errors": [] }, { "name": "Validate: Unique argument names/argument on directive", "rule": "UniqueArgumentNames", "schema": 0, "query": "\n {\n field @directive(arg: \"value\")\n }\n ", "errors": [] }, { "name": "Validate: Unique argument names/same argument on two fields", "rule": "UniqueArgumentNames", "schema": 0, "query": "\n {\n one: field(arg: \"value\")\n two: field(arg: \"value\")\n }\n ", "errors": [] }, { "name": "Validate: Unique argument names/same argument on field and directive", "rule": "UniqueArgumentNames", "schema": 0, "query": "\n {\n field(arg: \"value\") @directive(arg: \"value\")\n }\n ", "errors": [] }, { "name": "Validate: Unique argument names/same argument on two directives", "rule": "UniqueArgumentNames", "schema": 0, "query": "\n {\n field @directive1(arg: \"value\") @directive2(arg: \"value\")\n }\n ", "errors": [] }, { "name": "Validate: Unique argument names/multiple field arguments", "rule": "UniqueArgumentNames", "schema": 0, "query": "\n {\n field(arg1: \"value\", arg2: \"value\", arg3: \"value\")\n }\n ", "errors": [] }, { "name": "Validate: Unique argument names/multiple directive arguments", "rule": "UniqueArgumentNames", "schema": 0, "query": "\n {\n field @directive(arg1: \"value\", arg2: \"value\", arg3: \"value\")\n }\n ", "errors": [] }, { "name": "Validate: Unique argument names/duplicate field arguments", "rule": "UniqueArgumentNames", "schema": 0, "query": "\n {\n field(arg1: \"value\", arg1: \"value\")\n }\n ", "errors": [ { "message": "There can be only one argument named \"arg1\".", "locations": [ { "line": 3, "column": 15 }, { "line": 3, "column": 30 } ] } ] }, { "name": "Validate: Unique argument names/many duplicate field arguments", "rule": "UniqueArgumentNames", "schema": 0, "query": "\n {\n field(arg1: \"value\", arg1: \"value\", arg1: \"value\")\n }\n ", "errors": [ { "message": "There can be only one argument named \"arg1\".", "locations": [ { "line": 3, "column": 15 }, { "line": 3, "column": 30 } ] }, { "message": "There can be only one argument named \"arg1\".", "locations": [ { "line": 3, "column": 15 }, { "line": 3, "column": 45 } ] } ] }, { "name": "Validate: Unique argument names/duplicate directive arguments", "rule": "UniqueArgumentNames", "schema": 0, "query": "\n {\n field @directive(arg1: \"value\", arg1: \"value\")\n }\n ", "errors": [ { "message": "There can be only one argument named \"arg1\".", "locations": [ { "line": 3, "column": 26 }, { "line": 3, "column": 41 } ] } ] }, { "name": "Validate: Unique argument names/many duplicate directive arguments", "rule": "UniqueArgumentNames", "schema": 0, "query": "\n {\n field @directive(arg1: \"value\", arg1: \"value\", arg1: \"value\")\n }\n ", "errors": [ { "message": "There can be only one argument named \"arg1\".", "locations": [ { "line": 3, "column": 26 }, { "line": 3, "column": 41 } ] }, { "message": "There can be only one argument named \"arg1\".", "locations": [ { "line": 3, "column": 26 }, { "line": 3, "column": 56 } ] } ] }, { "name": "Validate: Directives Are Unique Per Location/no directives", "rule": "UniqueDirectivesPerLocation", "schema": 0, "query": "\n fragment Test on Type {\n field\n }\n ", "errors": [] }, { "name": "Validate: Directives Are Unique Per Location/unique directives in different locations", "rule": "UniqueDirectivesPerLocation", "schema": 0, "query": "\n fragment Test on Type @directiveA {\n field @directiveB\n }\n ", "errors": [] }, { "name": "Validate: Directives Are Unique Per Location/unique directives in same locations", "rule": "UniqueDirectivesPerLocation", "schema": 0, "query": "\n fragment Test on Type @directiveA @directiveB {\n field @directiveA @directiveB\n }\n ", "errors": [] }, { "name": "Validate: Directives Are Unique Per Location/same directives in different locations", "rule": "UniqueDirectivesPerLocation", "schema": 0, "query": "\n fragment Test on Type @directiveA {\n field @directiveA\n }\n ", "errors": [] }, { "name": "Validate: Directives Are Unique Per Location/same directives in similar locations", "rule": "UniqueDirectivesPerLocation", "schema": 0, "query": "\n fragment Test on Type {\n field @directive\n field @directive\n }\n ", "errors": [] }, { "name": "Validate: Directives Are Unique Per Location/duplicate directives in one location", "rule": "UniqueDirectivesPerLocation", "schema": 0, "query": "\n fragment Test on Type {\n field @directive @directive\n }\n ", "errors": [ { "message": "The directive \"directive\" can only be used once at this location.", "locations": [ { "line": 3, "column": 15 }, { "line": 3, "column": 26 } ] } ] }, { "name": "Validate: Directives Are Unique Per Location/many duplicate directives in one location", "rule": "UniqueDirectivesPerLocation", "schema": 0, "query": "\n fragment Test on Type {\n field @directive @directive @directive\n }\n ", "errors": [ { "message": "The directive \"directive\" can only be used once at this location.", "locations": [ { "line": 3, "column": 15 }, { "line": 3, "column": 26 } ] }, { "message": "The directive \"directive\" can only be used once at this location.", "locations": [ { "line": 3, "column": 15 }, { "line": 3, "column": 37 } ] } ] }, { "name": "Validate: Directives Are Unique Per Location/different duplicate directives in one location", "rule": "UniqueDirectivesPerLocation", "schema": 0, "query": "\n fragment Test on Type {\n field @directiveA @directiveB @directiveA @directiveB\n }\n ", "errors": [ { "message": "The directive \"directiveA\" can only be used once at this location.", "locations": [ { "line": 3, "column": 15 }, { "line": 3, "column": 39 } ] }, { "message": "The directive \"directiveB\" can only be used once at this location.", "locations": [ { "line": 3, "column": 27 }, { "line": 3, "column": 51 } ] } ] }, { "name": "Validate: Directives Are Unique Per Location/duplicate directives in many locations", "rule": "UniqueDirectivesPerLocation", "schema": 0, "query": "\n fragment Test on Type @directive @directive {\n field @directive @directive\n }\n ", "errors": [ { "message": "The directive \"directive\" can only be used once at this location.", "locations": [ { "line": 2, "column": 29 }, { "line": 2, "column": 40 } ] }, { "message": "The directive \"directive\" can only be used once at this location.", "locations": [ { "line": 3, "column": 15 }, { "line": 3, "column": 26 } ] } ] }, { "name": "Validate: Unique fragment names/no fragments", "rule": "UniqueFragmentNames", "schema": 0, "query": "\n {\n field\n }\n ", "errors": [] }, { "name": "Validate: Unique fragment names/one fragment", "rule": "UniqueFragmentNames", "schema": 0, "query": "\n {\n ...fragA\n }\n\n fragment fragA on Type {\n field\n }\n ", "errors": [] }, { "name": "Validate: Unique fragment names/many fragments", "rule": "UniqueFragmentNames", "schema": 0, "query": "\n {\n ...fragA\n ...fragB\n ...fragC\n }\n fragment fragA on Type {\n fieldA\n }\n fragment fragB on Type {\n fieldB\n }\n fragment fragC on Type {\n fieldC\n }\n ", "errors": [] }, { "name": "Validate: Unique fragment names/inline fragments are always unique", "rule": "UniqueFragmentNames", "schema": 0, "query": "\n {\n ...on Type {\n fieldA\n }\n ...on Type {\n fieldB\n }\n }\n ", "errors": [] }, { "name": "Validate: Unique fragment names/fragment and operation named the same", "rule": "UniqueFragmentNames", "schema": 0, "query": "\n query Foo {\n ...Foo\n }\n fragment Foo on Type {\n field\n }\n ", "errors": [] }, { "name": "Validate: Unique fragment names/fragments named the same", "rule": "UniqueFragmentNames", "schema": 0, "query": "\n {\n ...fragA\n }\n fragment fragA on Type {\n fieldA\n }\n fragment fragA on Type {\n fieldB\n }\n ", "errors": [ { "message": "There can be only one fragment named \"fragA\".", "locations": [ { "line": 5, "column": 16 }, { "line": 8, "column": 16 } ] } ] }, { "name": "Validate: Unique fragment names/fragments named the same without being referenced", "rule": "UniqueFragmentNames", "schema": 0, "query": "\n fragment fragA on Type {\n fieldA\n }\n fragment fragA on Type {\n fieldB\n }\n ", "errors": [ { "message": "There can be only one fragment named \"fragA\".", "locations": [ { "line": 2, "column": 16 }, { "line": 5, "column": 16 } ] } ] }, { "name": "Validate: Unique input field names/input object with fields", "rule": "UniqueInputFieldNames", "schema": 0, "query": "\n {\n field(arg: { f: true })\n }\n ", "errors": [] }, { "name": "Validate: Unique input field names/same input object within two args", "rule": "UniqueInputFieldNames", "schema": 0, "query": "\n {\n field(arg1: { f: true }, arg2: { f: true })\n }\n ", "errors": [] }, { "name": "Validate: Unique input field names/multiple input object fields", "rule": "UniqueInputFieldNames", "schema": 0, "query": "\n {\n field(arg: { f1: \"value\", f2: \"value\", f3: \"value\" })\n }\n ", "errors": [] }, { "name": "Validate: Unique input field names/allows for nested input objects with similar fields", "rule": "UniqueInputFieldNames", "schema": 0, "query": "\n {\n field(arg: {\n deep: {\n deep: {\n id: 1\n }\n id: 1\n }\n id: 1\n })\n }\n ", "errors": [] }, { "name": "Validate: Unique input field names/duplicate input object fields", "rule": "UniqueInputFieldNames", "schema": 0, "query": "\n {\n field(arg: { f1: \"value\", f1: \"value\" })\n }\n ", "errors": [ { "message": "There can be only one input field named \"f1\".", "locations": [ { "line": 3, "column": 22 }, { "line": 3, "column": 35 } ] } ] }, { "name": "Validate: Unique input field names/many duplicate input object fields", "rule": "UniqueInputFieldNames", "schema": 0, "query": "\n {\n field(arg: { f1: \"value\", f1: \"value\", f1: \"value\" })\n }\n ", "errors": [ { "message": "There can be only one input field named \"f1\".", "locations": [ { "line": 3, "column": 22 }, { "line": 3, "column": 35 } ] }, { "message": "There can be only one input field named \"f1\".", "locations": [ { "line": 3, "column": 22 }, { "line": 3, "column": 48 } ] } ] }, { "name": "Validate: Unique operation names/no operations", "rule": "UniqueOperationNames", "schema": 0, "query": "\n fragment fragA on Type {\n field\n }\n ", "errors": [] }, { "name": "Validate: Unique operation names/one anon operation", "rule": "UniqueOperationNames", "schema": 0, "query": "\n {\n field\n }\n ", "errors": [] }, { "name": "Validate: Unique operation names/one named operation", "rule": "UniqueOperationNames", "schema": 0, "query": "\n query Foo {\n field\n }\n ", "errors": [] }, { "name": "Validate: Unique operation names/multiple operations", "rule": "UniqueOperationNames", "schema": 0, "query": "\n query Foo {\n field\n }\n\n query Bar {\n field\n }\n ", "errors": [] }, { "name": "Validate: Unique operation names/multiple operations of different types", "rule": "UniqueOperationNames", "schema": 0, "query": "\n query Foo {\n field\n }\n\n mutation Bar {\n field\n }\n\n subscription Baz {\n field\n }\n ", "errors": [] }, { "name": "Validate: Unique operation names/fragment and operation named the same", "rule": "UniqueOperationNames", "schema": 0, "query": "\n query Foo {\n ...Foo\n }\n fragment Foo on Type {\n field\n }\n ", "errors": [] }, { "name": "Validate: Unique operation names/multiple operations of same name", "rule": "UniqueOperationNames", "schema": 0, "query": "\n query Foo {\n fieldA\n }\n query Foo {\n fieldB\n }\n ", "errors": [ { "message": "There can be only one operation named \"Foo\".", "locations": [ { "line": 2, "column": 13 }, { "line": 5, "column": 13 } ] } ] }, { "name": "Validate: Unique operation names/multiple ops of same name of different types (mutation)", "rule": "UniqueOperationNames", "schema": 0, "query": "\n query Foo {\n fieldA\n }\n mutation Foo {\n fieldB\n }\n ", "errors": [ { "message": "There can be only one operation named \"Foo\".", "locations": [ { "line": 2, "column": 13 }, { "line": 5, "column": 16 } ] } ] }, { "name": "Validate: Unique operation names/multiple ops of same name of different types (subscription)", "rule": "UniqueOperationNames", "schema": 0, "query": "\n query Foo {\n fieldA\n }\n subscription Foo {\n fieldB\n }\n ", "errors": [ { "message": "There can be only one operation named \"Foo\".", "locations": [ { "line": 2, "column": 13 }, { "line": 5, "column": 20 } ] } ] }, { "name": "Validate: Unique variable names/unique variable names", "rule": "UniqueVariableNames", "schema": 0, "query": "\n query A($x: Int, $y: String) { __typename }\n query B($x: String, $y: Int) { __typename }\n ", "errors": [] }, { "name": "Validate: Unique variable names/duplicate variable names", "rule": "UniqueVariableNames", "schema": 0, "query": "\n query A($x: Int, $x: Int, $x: String) { __typename }\n query B($x: String, $x: Int) { __typename }\n query C($x: Int, $x: Int) { __typename }\n ", "errors": [ { "message": "There can be only one variable named \"x\".", "locations": [ { "line": 2, "column": 16 }, { "line": 2, "column": 25 } ] }, { "message": "There can be only one variable named \"x\".", "locations": [ { "line": 2, "column": 16 }, { "line": 2, "column": 34 } ] }, { "message": "There can be only one variable named \"x\".", "locations": [ { "line": 3, "column": 16 }, { "line": 3, "column": 28 } ] }, { "message": "There can be only one variable named \"x\".", "locations": [ { "line": 4, "column": 16 }, { "line": 4, "column": 25 } ] } ] }, { "name": "Validate: Values of correct type/Valid values/Good int value", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n intArgField(intArg: 2)\n }\n }\n ", "errors": [] }, { "name": "Validate: Values of correct type/Valid values/Good negative int value", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n intArgField(intArg: -2)\n }\n }\n ", "errors": [] }, { "name": "Validate: Values of correct type/Valid values/Good boolean value", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n booleanArgField(booleanArg: true)\n }\n }\n ", "errors": [] }, { "name": "Validate: Values of correct type/Valid values/Good string value", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n stringArgField(stringArg: \"foo\")\n }\n }\n ", "errors": [] }, { "name": "Validate: Values of correct type/Valid values/Good float value", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n floatArgField(floatArg: 1.1)\n }\n }\n ", "errors": [] }, { "name": "Validate: Values of correct type/Valid values/Good negative float value", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n floatArgField(floatArg: -1.1)\n }\n }\n ", "errors": [] }, { "name": "Validate: Values of correct type/Valid values/Int into Float", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n floatArgField(floatArg: 1)\n }\n }\n ", "errors": [] }, { "name": "Validate: Values of correct type/Valid values/Int into ID", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n idArgField(idArg: 1)\n }\n }\n ", "errors": [] }, { "name": "Validate: Values of correct type/Valid values/String into ID", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n idArgField(idArg: \"someIdString\")\n }\n }\n ", "errors": [] }, { "name": "Validate: Values of correct type/Valid values/Good enum value", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n dog {\n doesKnowCommand(dogCommand: SIT)\n }\n }\n ", "errors": [] }, { "name": "Validate: Values of correct type/Valid values/Enum with undefined value", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n enumArgField(enumArg: UNKNOWN)\n }\n }\n ", "errors": [] }, { "name": "Validate: Values of correct type/Valid values/Enum with null value", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n enumArgField(enumArg: NO_FUR)\n }\n }\n ", "errors": [] }, { "name": "Validate: Values of correct type/Valid values/null into nullable type", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n intArgField(intArg: null)\n }\n }\n ", "errors": [] }, { "name": "Validate: Values of correct type/Valid values/null into nullable type", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n dog(a: null, b: null, c:{ requiredField: true, intField: null }) {\n name\n }\n }\n ", "errors": [] }, { "name": "Validate: Values of correct type/Invalid String values/Int into String", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n stringArgField(stringArg: 1)\n }\n }\n ", "errors": [ { "message": "Expected type String, found 1.", "locations": [ { "line": 4, "column": 39 } ] } ] }, { "name": "Validate: Values of correct type/Invalid String values/Float into String", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n stringArgField(stringArg: 1.0)\n }\n }\n ", "errors": [ { "message": "Expected type String, found 1.0.", "locations": [ { "line": 4, "column": 39 } ] } ] }, { "name": "Validate: Values of correct type/Invalid String values/Boolean into String", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n stringArgField(stringArg: true)\n }\n }\n ", "errors": [ { "message": "Expected type String, found true.", "locations": [ { "line": 4, "column": 39 } ] } ] }, { "name": "Validate: Values of correct type/Invalid String values/Unquoted String into String", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n stringArgField(stringArg: BAR)\n }\n }\n ", "errors": [ { "message": "Expected type String, found BAR.", "locations": [ { "line": 4, "column": 39 } ] } ] }, { "name": "Validate: Values of correct type/Invalid Int values/String into Int", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n intArgField(intArg: \"3\")\n }\n }\n ", "errors": [ { "message": "Expected type Int, found \"3\".", "locations": [ { "line": 4, "column": 33 } ] } ] }, { "name": "Validate: Values of correct type/Invalid Int values/Big Int into Int", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n intArgField(intArg: 829384293849283498239482938)\n }\n }\n ", "errors": [ { "message": "Expected type Int, found 829384293849283498239482938.", "locations": [ { "line": 4, "column": 33 } ] } ] }, { "name": "Validate: Values of correct type/Invalid Int values/Unquoted String into Int", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n intArgField(intArg: FOO)\n }\n }\n ", "errors": [ { "message": "Expected type Int, found FOO.", "locations": [ { "line": 4, "column": 33 } ] } ] }, { "name": "Validate: Values of correct type/Invalid Int values/Simple Float into Int", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n intArgField(intArg: 3.0)\n }\n }\n ", "errors": [ { "message": "Expected type Int, found 3.0.", "locations": [ { "line": 4, "column": 33 } ] } ] }, { "name": "Validate: Values of correct type/Invalid Int values/Float into Int", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n intArgField(intArg: 3.333)\n }\n }\n ", "errors": [ { "message": "Expected type Int, found 3.333.", "locations": [ { "line": 4, "column": 33 } ] } ] }, { "name": "Validate: Values of correct type/Invalid Float values/String into Float", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n floatArgField(floatArg: \"3.333\")\n }\n }\n ", "errors": [ { "message": "Expected type Float, found \"3.333\".", "locations": [ { "line": 4, "column": 37 } ] } ] }, { "name": "Validate: Values of correct type/Invalid Float values/Boolean into Float", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n floatArgField(floatArg: true)\n }\n }\n ", "errors": [ { "message": "Expected type Float, found true.", "locations": [ { "line": 4, "column": 37 } ] } ] }, { "name": "Validate: Values of correct type/Invalid Float values/Unquoted into Float", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n floatArgField(floatArg: FOO)\n }\n }\n ", "errors": [ { "message": "Expected type Float, found FOO.", "locations": [ { "line": 4, "column": 37 } ] } ] }, { "name": "Validate: Values of correct type/Invalid Boolean value/Int into Boolean", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n booleanArgField(booleanArg: 2)\n }\n }\n ", "errors": [ { "message": "Expected type Boolean, found 2.", "locations": [ { "line": 4, "column": 41 } ] } ] }, { "name": "Validate: Values of correct type/Invalid Boolean value/Float into Boolean", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n booleanArgField(booleanArg: 1.0)\n }\n }\n ", "errors": [ { "message": "Expected type Boolean, found 1.0.", "locations": [ { "line": 4, "column": 41 } ] } ] }, { "name": "Validate: Values of correct type/Invalid Boolean value/String into Boolean", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n booleanArgField(booleanArg: \"true\")\n }\n }\n ", "errors": [ { "message": "Expected type Boolean, found \"true\".", "locations": [ { "line": 4, "column": 41 } ] } ] }, { "name": "Validate: Values of correct type/Invalid Boolean value/Unquoted into Boolean", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n booleanArgField(booleanArg: TRUE)\n }\n }\n ", "errors": [ { "message": "Expected type Boolean, found TRUE.", "locations": [ { "line": 4, "column": 41 } ] } ] }, { "name": "Validate: Values of correct type/Invalid ID value/Float into ID", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n idArgField(idArg: 1.0)\n }\n }\n ", "errors": [ { "message": "Expected type ID, found 1.0.", "locations": [ { "line": 4, "column": 31 } ] } ] }, { "name": "Validate: Values of correct type/Invalid ID value/Boolean into ID", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n idArgField(idArg: true)\n }\n }\n ", "errors": [ { "message": "Expected type ID, found true.", "locations": [ { "line": 4, "column": 31 } ] } ] }, { "name": "Validate: Values of correct type/Invalid ID value/Unquoted into ID", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n idArgField(idArg: SOMETHING)\n }\n }\n ", "errors": [ { "message": "Expected type ID, found SOMETHING.", "locations": [ { "line": 4, "column": 31 } ] } ] }, { "name": "Validate: Values of correct type/Invalid Enum value/Int into Enum", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n dog {\n doesKnowCommand(dogCommand: 2)\n }\n }\n ", "errors": [ { "message": "Expected type DogCommand, found 2.", "locations": [ { "line": 4, "column": 41 } ] } ] }, { "name": "Validate: Values of correct type/Invalid Enum value/Float into Enum", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n dog {\n doesKnowCommand(dogCommand: 1.0)\n }\n }\n ", "errors": [ { "message": "Expected type DogCommand, found 1.0.", "locations": [ { "line": 4, "column": 41 } ] } ] }, { "name": "Validate: Values of correct type/Invalid Enum value/String into Enum", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n dog {\n doesKnowCommand(dogCommand: \"SIT\")\n }\n }\n ", "errors": [ { "message": "Expected type DogCommand, found \"SIT\"; Did you mean the enum value SIT?", "locations": [ { "line": 4, "column": 41 } ] } ] }, { "name": "Validate: Values of correct type/Invalid Enum value/Boolean into Enum", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n dog {\n doesKnowCommand(dogCommand: true)\n }\n }\n ", "errors": [ { "message": "Expected type DogCommand, found true.", "locations": [ { "line": 4, "column": 41 } ] } ] }, { "name": "Validate: Values of correct type/Invalid Enum value/Unknown Enum Value into Enum", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n dog {\n doesKnowCommand(dogCommand: JUGGLE)\n }\n }\n ", "errors": [ { "message": "Expected type DogCommand, found JUGGLE.", "locations": [ { "line": 4, "column": 41 } ] } ] }, { "name": "Validate: Values of correct type/Invalid Enum value/Different case Enum Value into Enum", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n dog {\n doesKnowCommand(dogCommand: sit)\n }\n }\n ", "errors": [ { "message": "Expected type DogCommand, found sit; Did you mean the enum value SIT?", "locations": [ { "line": 4, "column": 41 } ] } ] }, { "name": "Validate: Values of correct type/Valid List value/Good list value", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n stringListArgField(stringListArg: [\"one\", null, \"two\"])\n }\n }\n ", "errors": [] }, { "name": "Validate: Values of correct type/Valid List value/Empty list value", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n stringListArgField(stringListArg: [])\n }\n }\n ", "errors": [] }, { "name": "Validate: Values of correct type/Valid List value/Null value", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n stringListArgField(stringListArg: null)\n }\n }\n ", "errors": [] }, { "name": "Validate: Values of correct type/Valid List value/Single value into List", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n stringListArgField(stringListArg: \"one\")\n }\n }\n ", "errors": [] }, { "name": "Validate: Values of correct type/Invalid List value/Incorrect item type", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n stringListArgField(stringListArg: [\"one\", 2])\n }\n }\n ", "errors": [ { "message": "Expected type String, found 2.", "locations": [ { "line": 4, "column": 55 } ] } ] }, { "name": "Validate: Values of correct type/Invalid List value/Single value of incorrect type", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n stringListArgField(stringListArg: 1)\n }\n }\n ", "errors": [ { "message": "Expected type [String], found 1.", "locations": [ { "line": 4, "column": 47 } ] } ] }, { "name": "Validate: Values of correct type/Valid non-nullable value/Arg on optional arg", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n dog {\n isHousetrained(atOtherHomes: true)\n }\n }\n ", "errors": [] }, { "name": "Validate: Values of correct type/Valid non-nullable value/No Arg on optional arg", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n dog {\n isHousetrained\n }\n }\n ", "errors": [] }, { "name": "Validate: Values of correct type/Valid non-nullable value/Multiple args", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n multipleReqs(req1: 1, req2: 2)\n }\n }\n ", "errors": [] }, { "name": "Validate: Values of correct type/Valid non-nullable value/Multiple args reverse order", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n multipleReqs(req2: 2, req1: 1)\n }\n }\n ", "errors": [] }, { "name": "Validate: Values of correct type/Valid non-nullable value/No args on multiple optional", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n multipleOpts\n }\n }\n ", "errors": [] }, { "name": "Validate: Values of correct type/Valid non-nullable value/One arg on multiple optional", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n multipleOpts(opt1: 1)\n }\n }\n ", "errors": [] }, { "name": "Validate: Values of correct type/Valid non-nullable value/Second arg on multiple optional", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n multipleOpts(opt2: 1)\n }\n }\n ", "errors": [] }, { "name": "Validate: Values of correct type/Valid non-nullable value/Multiple reqs on mixedList", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n multipleOptAndReq(req1: 3, req2: 4)\n }\n }\n ", "errors": [] }, { "name": "Validate: Values of correct type/Valid non-nullable value/Multiple reqs and one opt on mixedList", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n multipleOptAndReq(req1: 3, req2: 4, opt1: 5)\n }\n }\n ", "errors": [] }, { "name": "Validate: Values of correct type/Valid non-nullable value/All reqs and opts on mixedList", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n multipleOptAndReq(req1: 3, req2: 4, opt1: 5, opt2: 6)\n }\n }\n ", "errors": [] }, { "name": "Validate: Values of correct type/Invalid non-nullable value/Incorrect value type", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n multipleReqs(req2: \"two\", req1: \"one\")\n }\n }\n ", "errors": [ { "message": "Expected type Int!, found \"two\".", "locations": [ { "line": 4, "column": 32 } ] }, { "message": "Expected type Int!, found \"one\".", "locations": [ { "line": 4, "column": 45 } ] } ] }, { "name": "Validate: Values of correct type/Invalid non-nullable value/Incorrect value and missing argument (ProvidedRequiredArguments)", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n multipleReqs(req1: \"one\")\n }\n }\n ", "errors": [ { "message": "Expected type Int!, found \"one\".", "locations": [ { "line": 4, "column": 32 } ] } ] }, { "name": "Validate: Values of correct type/Invalid non-nullable value/Null value", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n multipleReqs(req1: null)\n }\n }\n ", "errors": [ { "message": "Expected type Int!, found null.", "locations": [ { "line": 4, "column": 32 } ] } ] }, { "name": "Validate: Values of correct type/Valid input object value/Optional arg, despite required field in type", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n complexArgField\n }\n }\n ", "errors": [] }, { "name": "Validate: Values of correct type/Valid input object value/Partial object, only required", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n complexArgField(complexArg: { requiredField: true })\n }\n }\n ", "errors": [] }, { "name": "Validate: Values of correct type/Valid input object value/Partial object, required field can be falsey", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n complexArgField(complexArg: { requiredField: false })\n }\n }\n ", "errors": [] }, { "name": "Validate: Values of correct type/Valid input object value/Partial object, including required", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n complexArgField(complexArg: { requiredField: true, intField: 4 })\n }\n }\n ", "errors": [] }, { "name": "Validate: Values of correct type/Valid input object value/Full object", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n complexArgField(complexArg: {\n requiredField: true,\n intField: 4,\n stringField: \"foo\",\n booleanField: false,\n stringListField: [\"one\", \"two\"]\n })\n }\n }\n ", "errors": [] }, { "name": "Validate: Values of correct type/Valid input object value/Full object with fields in different order", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n complexArgField(complexArg: {\n stringListField: [\"one\", \"two\"],\n booleanField: false,\n requiredField: true,\n stringField: \"foo\",\n intField: 4,\n })\n }\n }\n ", "errors": [] }, { "name": "Validate: Values of correct type/Invalid input object value/Partial object, missing required", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n complexArgField(complexArg: { intField: 4 })\n }\n }\n ", "errors": [ { "message": "Field ComplexInput.requiredField of required type Boolean! was not provided.", "locations": [ { "line": 4, "column": 41 } ] } ] }, { "name": "Validate: Values of correct type/Invalid input object value/Partial object, invalid field type", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n complexArgField(complexArg: {\n stringListField: [\"one\", 2],\n requiredField: true,\n })\n }\n }\n ", "errors": [ { "message": "Expected type String, found 2.", "locations": [ { "line": 5, "column": 40 } ] } ] }, { "name": "Validate: Values of correct type/Invalid input object value/Partial object, null to non-null field", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n complexArgField(complexArg: {\n requiredField: true,\n nonNullField: null,\n })\n }\n }\n ", "errors": [ { "message": "Expected type Boolean!, found null.", "locations": [ { "line": 6, "column": 29 } ] } ] }, { "name": "Validate: Values of correct type/Invalid input object value/Partial object, unknown field arg", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n complicatedArgs {\n complexArgField(complexArg: {\n requiredField: true,\n unknownField: \"value\"\n })\n }\n }\n ", "errors": [ { "message": "Field \"unknownField\" is not defined by type ComplexInput; Did you mean nonNullField, intField, or booleanField?", "locations": [ { "line": 6, "column": 15 } ] } ] }, { "name": "Validate: Values of correct type/Invalid input object value/reports original error for custom scalar which throws", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n invalidArg(arg: 123)\n }\n ", "errors": [ { "message": "Expected type Invalid, found 123; Invalid scalar is always invalid: 123", "locations": [ { "line": 3, "column": 27 } ] } ] }, { "name": "Validate: Values of correct type/Invalid input object value/allows custom scalar to accept complex literals", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n test1: anyArg(arg: 123)\n test2: anyArg(arg: \"abc\")\n test3: anyArg(arg: [123, \"abc\"])\n test4: anyArg(arg: {deep: [123, \"abc\"]})\n }\n ", "errors": [] }, { "name": "Validate: Values of correct type/Directive arguments/with directives of valid types", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n dog @include(if: true) {\n name\n }\n human @skip(if: false) {\n name\n }\n }\n ", "errors": [] }, { "name": "Validate: Values of correct type/Directive arguments/with directive with incorrect types", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n {\n dog @include(if: \"yes\") {\n name @skip(if: ENUM)\n }\n }\n ", "errors": [ { "message": "Expected type Boolean!, found \"yes\".", "locations": [ { "line": 3, "column": 28 } ] }, { "message": "Expected type Boolean!, found ENUM.", "locations": [ { "line": 4, "column": 28 } ] } ] }, { "name": "Validate: Values of correct type/Variable default values/variables with valid default values", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n query WithDefaultValues(\n $a: Int = 1,\n $b: String = \"ok\",\n $c: ComplexInput = { requiredField: true, intField: 3 }\n $d: Int! = 123\n ) {\n dog { name }\n }\n ", "errors": [] }, { "name": "Validate: Values of correct type/Variable default values/variables with valid default null values", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n query WithDefaultValues(\n $a: Int = null,\n $b: String = null,\n $c: ComplexInput = { requiredField: true, intField: null }\n ) {\n dog { name }\n }\n ", "errors": [] }, { "name": "Validate: Values of correct type/Variable default values/variables with invalid default null values", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n query WithDefaultValues(\n $a: Int! = null,\n $b: String! = null,\n $c: ComplexInput = { requiredField: null, intField: null }\n ) {\n dog { name }\n }\n ", "errors": [ { "message": "Expected type Int!, found null.", "locations": [ { "line": 3, "column": 22 } ] }, { "message": "Expected type String!, found null.", "locations": [ { "line": 4, "column": 25 } ] }, { "message": "Expected type Boolean!, found null.", "locations": [ { "line": 5, "column": 47 } ] } ] }, { "name": "Validate: Values of correct type/Variable default values/variables with invalid default values", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n query InvalidDefaultValues(\n $a: Int = \"one\",\n $b: String = 4,\n $c: ComplexInput = \"notverycomplex\"\n ) {\n dog { name }\n }\n ", "errors": [ { "message": "Expected type Int, found \"one\".", "locations": [ { "line": 3, "column": 21 } ] }, { "message": "Expected type String, found 4.", "locations": [ { "line": 4, "column": 24 } ] }, { "message": "Expected type ComplexInput, found \"notverycomplex\".", "locations": [ { "line": 5, "column": 30 } ] } ] }, { "name": "Validate: Values of correct type/Variable default values/variables with complex invalid default values", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n query WithDefaultValues(\n $a: ComplexInput = { requiredField: 123, intField: \"abc\" }\n ) {\n dog { name }\n }\n ", "errors": [ { "message": "Expected type Boolean!, found 123.", "locations": [ { "line": 3, "column": 47 } ] }, { "message": "Expected type Int, found \"abc\".", "locations": [ { "line": 3, "column": 62 } ] } ] }, { "name": "Validate: Values of correct type/Variable default values/complex variables missing required field", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n query MissingRequiredField($a: ComplexInput = {intField: 3}) {\n dog { name }\n }\n ", "errors": [ { "message": "Field ComplexInput.requiredField of required type Boolean! was not provided.", "locations": [ { "line": 2, "column": 55 } ] } ] }, { "name": "Validate: Values of correct type/Variable default values/list variables with invalid item", "rule": "ValuesOfCorrectType", "schema": 0, "query": "\n query InvalidItem($a: [String] = [\"one\", 2]) {\n dog { name }\n }\n ", "errors": [ { "message": "Expected type String, found 2.", "locations": [ { "line": 2, "column": 50 } ] } ] }, { "name": "Validate: Variables are input types/input types are valid", "rule": "VariablesAreInputTypes", "schema": 0, "query": "\n query Foo($a: String, $b: [Boolean!]!, $c: ComplexInput) {\n field(a: $a, b: $b, c: $c)\n }\n ", "errors": [] }, { "name": "Validate: Variables are input types/output types are invalid", "rule": "VariablesAreInputTypes", "schema": 0, "query": "\n query Foo($a: Dog, $b: [[CatOrDog!]]!, $c: Pet) {\n field(a: $a, b: $b, c: $c)\n }\n ", "errors": [ { "locations": [ { "line": 2, "column": 21 } ], "message": "Variable \"$a\" cannot be non-input type \"Dog\"." }, { "locations": [ { "line": 2, "column": 30 } ], "message": "Variable \"$b\" cannot be non-input type \"[[CatOrDog!]]!\"." }, { "locations": [ { "line": 2, "column": 50 } ], "message": "Variable \"$c\" cannot be non-input type \"Pet\"." } ] }, { "name": "Validate: Variables are in allowed positions/Boolean => Boolean", "rule": "VariablesInAllowedPosition", "schema": 0, "query": "\n query Query($booleanArg: Boolean)\n {\n complicatedArgs {\n booleanArgField(booleanArg: $booleanArg)\n }\n }\n ", "errors": [] }, { "name": "Validate: Variables are in allowed positions/Boolean => Boolean within fragment", "rule": "VariablesInAllowedPosition", "schema": 0, "query": "\n fragment booleanArgFrag on ComplicatedArgs {\n booleanArgField(booleanArg: $booleanArg)\n }\n query Query($booleanArg: Boolean)\n {\n complicatedArgs {\n ...booleanArgFrag\n }\n }\n ", "errors": [] }, { "name": "Validate: Variables are in allowed positions/Boolean => Boolean within fragment", "rule": "VariablesInAllowedPosition", "schema": 0, "query": "\n query Query($booleanArg: Boolean)\n {\n complicatedArgs {\n ...booleanArgFrag\n }\n }\n fragment booleanArgFrag on ComplicatedArgs {\n booleanArgField(booleanArg: $booleanArg)\n }\n ", "errors": [] }, { "name": "Validate: Variables are in allowed positions/Boolean! => Boolean", "rule": "VariablesInAllowedPosition", "schema": 0, "query": "\n query Query($nonNullBooleanArg: Boolean!)\n {\n complicatedArgs {\n booleanArgField(booleanArg: $nonNullBooleanArg)\n }\n }\n ", "errors": [] }, { "name": "Validate: Variables are in allowed positions/Boolean! => Boolean within fragment", "rule": "VariablesInAllowedPosition", "schema": 0, "query": "\n fragment booleanArgFrag on ComplicatedArgs {\n booleanArgField(booleanArg: $nonNullBooleanArg)\n }\n\n query Query($nonNullBooleanArg: Boolean!)\n {\n complicatedArgs {\n ...booleanArgFrag\n }\n }\n ", "errors": [] }, { "name": "Validate: Variables are in allowed positions/[String] => [String]", "rule": "VariablesInAllowedPosition", "schema": 0, "query": "\n query Query($stringListVar: [String])\n {\n complicatedArgs {\n stringListArgField(stringListArg: $stringListVar)\n }\n }\n ", "errors": [] }, { "name": "Validate: Variables are in allowed positions/[String!] => [String]", "rule": "VariablesInAllowedPosition", "schema": 0, "query": "\n query Query($stringListVar: [String!])\n {\n complicatedArgs {\n stringListArgField(stringListArg: $stringListVar)\n }\n }\n ", "errors": [] }, { "name": "Validate: Variables are in allowed positions/String => [String] in item position", "rule": "VariablesInAllowedPosition", "schema": 0, "query": "\n query Query($stringVar: String)\n {\n complicatedArgs {\n stringListArgField(stringListArg: [$stringVar])\n }\n }\n ", "errors": [] }, { "name": "Validate: Variables are in allowed positions/String! => [String] in item position", "rule": "VariablesInAllowedPosition", "schema": 0, "query": "\n query Query($stringVar: String!)\n {\n complicatedArgs {\n stringListArgField(stringListArg: [$stringVar])\n }\n }\n ", "errors": [] }, { "name": "Validate: Variables are in allowed positions/ComplexInput => ComplexInput", "rule": "VariablesInAllowedPosition", "schema": 0, "query": "\n query Query($complexVar: ComplexInput)\n {\n complicatedArgs {\n complexArgField(complexArg: $complexVar)\n }\n }\n ", "errors": [] }, { "name": "Validate: Variables are in allowed positions/ComplexInput => ComplexInput in field position", "rule": "VariablesInAllowedPosition", "schema": 0, "query": "\n query Query($boolVar: Boolean = false)\n {\n complicatedArgs {\n complexArgField(complexArg: {requiredArg: $boolVar})\n }\n }\n ", "errors": [] }, { "name": "Validate: Variables are in allowed positions/Boolean! => Boolean! in directive", "rule": "VariablesInAllowedPosition", "schema": 0, "query": "\n query Query($boolVar: Boolean!)\n {\n dog @include(if: $boolVar)\n }\n ", "errors": [] }, { "name": "Validate: Variables are in allowed positions/Int => Int!", "rule": "VariablesInAllowedPosition", "schema": 0, "query": "\n query Query($intArg: Int) {\n complicatedArgs {\n nonNullIntArgField(nonNullIntArg: $intArg)\n }\n }\n ", "errors": [ { "message": "Variable \"$intArg\" of type \"Int\" used in position expecting type \"Int!\".", "locations": [ { "line": 2, "column": 19 }, { "line": 4, "column": 45 } ] } ] }, { "name": "Validate: Variables are in allowed positions/Int => Int! within fragment", "rule": "VariablesInAllowedPosition", "schema": 0, "query": "\n fragment nonNullIntArgFieldFrag on ComplicatedArgs {\n nonNullIntArgField(nonNullIntArg: $intArg)\n }\n\n query Query($intArg: Int) {\n complicatedArgs {\n ...nonNullIntArgFieldFrag\n }\n }\n ", "errors": [ { "message": "Variable \"$intArg\" of type \"Int\" used in position expecting type \"Int!\".", "locations": [ { "line": 6, "column": 19 }, { "line": 3, "column": 43 } ] } ] }, { "name": "Validate: Variables are in allowed positions/Int => Int! within nested fragment", "rule": "VariablesInAllowedPosition", "schema": 0, "query": "\n fragment outerFrag on ComplicatedArgs {\n ...nonNullIntArgFieldFrag\n }\n\n fragment nonNullIntArgFieldFrag on ComplicatedArgs {\n nonNullIntArgField(nonNullIntArg: $intArg)\n }\n\n query Query($intArg: Int) {\n complicatedArgs {\n ...outerFrag\n }\n }\n ", "errors": [ { "message": "Variable \"$intArg\" of type \"Int\" used in position expecting type \"Int!\".", "locations": [ { "line": 10, "column": 19 }, { "line": 7, "column": 43 } ] } ] }, { "name": "Validate: Variables are in allowed positions/String over Boolean", "rule": "VariablesInAllowedPosition", "schema": 0, "query": "\n query Query($stringVar: String) {\n complicatedArgs {\n booleanArgField(booleanArg: $stringVar)\n }\n }\n ", "errors": [ { "message": "Variable \"$stringVar\" of type \"String\" used in position expecting type \"Boolean\".", "locations": [ { "line": 2, "column": 19 }, { "line": 4, "column": 39 } ] } ] }, { "name": "Validate: Variables are in allowed positions/String => [String]", "rule": "VariablesInAllowedPosition", "schema": 0, "query": "\n query Query($stringVar: String) {\n complicatedArgs {\n stringListArgField(stringListArg: $stringVar)\n }\n }\n ", "errors": [ { "message": "Variable \"$stringVar\" of type \"String\" used in position expecting type \"[String]\".", "locations": [ { "line": 2, "column": 19 }, { "line": 4, "column": 45 } ] } ] }, { "name": "Validate: Variables are in allowed positions/Boolean => Boolean! in directive", "rule": "VariablesInAllowedPosition", "schema": 0, "query": "\n query Query($boolVar: Boolean) {\n dog @include(if: $boolVar)\n }\n ", "errors": [ { "message": "Variable \"$boolVar\" of type \"Boolean\" used in position expecting type \"Boolean!\".", "locations": [ { "line": 2, "column": 19 }, { "line": 3, "column": 26 } ] } ] }, { "name": "Validate: Variables are in allowed positions/String => Boolean! in directive", "rule": "VariablesInAllowedPosition", "schema": 0, "query": "\n query Query($stringVar: String) {\n dog @include(if: $stringVar)\n }\n ", "errors": [ { "message": "Variable \"$stringVar\" of type \"String\" used in position expecting type \"Boolean!\".", "locations": [ { "line": 2, "column": 19 }, { "line": 3, "column": 26 } ] } ] }, { "name": "Validate: Variables are in allowed positions/[String] => [String!]", "rule": "VariablesInAllowedPosition", "schema": 0, "query": "\n query Query($stringListVar: [String])\n {\n complicatedArgs {\n stringListNonNullArgField(stringListNonNullArg: $stringListVar)\n }\n }\n ", "errors": [ { "message": "Variable \"$stringListVar\" of type \"[String]\" used in position expecting type \"[String!]\".", "locations": [ { "line": 2, "column": 19 }, { "line": 5, "column": 59 } ] } ] }, { "name": "Validate: Variables are in allowed positions/Allows optional (nullable) variables with default values/Int => Int! fails when variable provides null default value", "rule": "VariablesInAllowedPosition", "schema": 0, "query": "\n query Query($intVar: Int = null) {\n complicatedArgs {\n nonNullIntArgField(nonNullIntArg: $intVar)\n }\n }", "errors": [ { "message": "Variable \"$intVar\" of type \"Int\" used in position expecting type \"Int!\".", "locations": [ { "line": 2, "column": 21 }, { "line": 4, "column": 47 } ] } ] }, { "name": "Validate: Variables are in allowed positions/Allows optional (nullable) variables with default values/Int => Int! when variable provides non-null default value", "rule": "VariablesInAllowedPosition", "schema": 0, "query": "\n query Query($intVar: Int = 1) {\n complicatedArgs {\n nonNullIntArgField(nonNullIntArg: $intVar)\n }\n }", "errors": [] }, { "name": "Validate: Variables are in allowed positions/Allows optional (nullable) variables with default values/Int => Int! when optional argument provides default value", "rule": "VariablesInAllowedPosition", "schema": 0, "query": "\n query Query($intVar: Int) {\n complicatedArgs {\n nonNullFieldWithDefault(nonNullIntArg: $intVar)\n }\n }", "errors": [] }, { "name": "Validate: Variables are in allowed positions/Allows optional (nullable) variables with default values/Boolean => Boolean! in directive with default value with option", "rule": "VariablesInAllowedPosition", "schema": 0, "query": "\n query Query($boolVar: Boolean = false) {\n dog @include(if: $boolVar)\n }", "errors": [] } ] }gqlparser-2.5.1/validator/imported_test.go000066400000000000000000000110561430663104200207170ustar00rootroot00000000000000package validator_test import ( "fmt" "os" "path/filepath" "regexp" "sort" "strconv" "strings" "testing" "github.com/stretchr/testify/require" "github.com/vektah/gqlparser/v2" "github.com/vektah/gqlparser/v2/ast" "github.com/vektah/gqlparser/v2/gqlerror" "gopkg.in/yaml.v2" ) type Spec struct { Name string Rule string Schema string Query string Errors gqlerror.List } type Deviation struct { Rule string Errors []*gqlerror.Error Skip string pattern *regexp.Regexp } func TestValidation(t *testing.T) { var rawSchemas []string readYaml("./imported/spec/schemas.yml", &rawSchemas) var deviations []*Deviation readYaml("./imported/deviations.yml", &deviations) for _, d := range deviations { d.pattern = regexp.MustCompile("^" + d.Rule + "$") } var schemas []*ast.Schema for i, schema := range rawSchemas { schema, err := gqlparser.LoadSchema(&ast.Source{Input: schema, Name: fmt.Sprintf("schemas.yml[%d]", i)}) if err != nil { panic(err) } schemas = append(schemas, schema) } err := filepath.Walk("./", func(path string, info os.FileInfo, err error) error { if info.IsDir() || !strings.HasSuffix(path, ".spec.yml") { return nil } runSpec(t, schemas, deviations, path) return nil }) require.NoError(t, err) } func runSpec(t *testing.T, schemas []*ast.Schema, deviations []*Deviation, filename string) { ruleName := strings.TrimSuffix(filepath.Base(filename), ".spec.yml") var specs []Spec readYaml(filename, &specs) t.Run(ruleName, func(t *testing.T) { for _, spec := range specs { if len(spec.Errors) == 0 { spec.Errors = nil } t.Run(spec.Name, func(t *testing.T) { for _, deviation := range deviations { if deviation.pattern.MatchString(ruleName + "/" + spec.Name) { if deviation.Skip != "" { t.Skip(deviation.Skip) } if deviation.Errors != nil { spec.Errors = deviation.Errors } } } // idx := spec.Schema var schema *ast.Schema if idx, err := strconv.Atoi(spec.Schema); err != nil { var gqlErr error schema, gqlErr = gqlparser.LoadSchema(&ast.Source{Input: spec.Schema, Name: spec.Name}) if gqlErr != nil { t.Fatal(err) } } else { schema = schemas[idx] } _, errList := gqlparser.LoadQuery(schema, spec.Query) var finalErrors gqlerror.List for _, err := range errList { // ignore errors from other rules if spec.Rule != "" && err.Rule != spec.Rule { continue } finalErrors = append(finalErrors, err) } for i := range spec.Errors { spec.Errors[i].Rule = spec.Rule // remove inconsistent use of ; spec.Errors[i].Message = strings.Replace(spec.Errors[i].Message, "; Did you mean", ". Did you mean", -1) } sort.Slice(spec.Errors, compareErrors(spec.Errors)) sort.Slice(finalErrors, compareErrors(finalErrors)) if len(finalErrors) != len(spec.Errors) { t.Errorf("wrong number of errors returned\ngot:\n%s\nwant:\n%s", finalErrors.Error(), spec.Errors) } else { for i := range spec.Errors { expected := spec.Errors[i] actual := finalErrors[i] if actual.Rule != spec.Rule { continue } var errLocs []string if expected.Message != actual.Message { errLocs = append(errLocs, "message mismatch") } if len(expected.Locations) > 0 && len(actual.Locations) == 0 { errLocs = append(errLocs, "missing location") } if len(expected.Locations) > 0 && len(actual.Locations) > 0 { found := false for _, loc := range expected.Locations { if actual.Locations[0].Line == loc.Line { found = true break } } if !found { errLocs = append(errLocs, "line") } } if len(errLocs) > 0 { t.Errorf("%s\ngot: %s\nwant: %s", strings.Join(errLocs, ", "), finalErrors[i].Error(), spec.Errors[i].Error()) } } } if t.Failed() { t.Logf("name: '%s'", spec.Name) t.Log("\nquery:", spec.Query) } }) } }) } func compareErrors(errors gqlerror.List) func(i, j int) bool { return func(i, j int) bool { cmp := strings.Compare(errors[i].Message, errors[j].Message) if cmp == 0 && len(errors[i].Locations) > 0 && len(errors[j].Locations) > 0 { return errors[i].Locations[0].Line > errors[j].Locations[0].Line } return cmp < 0 } } func readYaml(filename string, result interface{}) { b, err := os.ReadFile(filename) if err != nil { panic(err) } err = yaml.Unmarshal(b, result) if err != nil { panic(fmt.Errorf("unable to load %s: %s", filename, err.Error())) } } gqlparser-2.5.1/validator/messaging.go000066400000000000000000000013521430663104200200100ustar00rootroot00000000000000package 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() } gqlparser-2.5.1/validator/messaging_test.go000066400000000000000000000014371430663104200210530ustar00rootroot00000000000000package validator import ( "testing" "github.com/stretchr/testify/assert" ) func TestMessaging(t *testing.T) { t.Run("OrList", func(t *testing.T) { assert.Equal(t, "", OrList()) assert.Equal(t, "A", OrList("A")) assert.Equal(t, "A or B", OrList("A", "B")) assert.Equal(t, "A, B, or C", OrList("A", "B", "C")) assert.Equal(t, "A, B, C, or D", OrList("A", "B", "C", "D")) assert.Equal(t, "A, B, C, D, or E", OrList("A", "B", "C", "D", "E", "F")) }) t.Run("QuotedOrList", func(t *testing.T) { assert.Equal(t, ``, QuotedOrList()) assert.Equal(t, `"A"`, QuotedOrList("A")) assert.Equal(t, `"A" or "B"`, QuotedOrList("A", "B")) assert.Equal(t, `"A", "B", or "C"`, QuotedOrList("A", "B", "C")) assert.Equal(t, `"A", "B", "C", or "D"`, QuotedOrList("A", "B", "C", "D")) }) } gqlparser-2.5.1/validator/prelude.go000066400000000000000000000003521430663104200174720ustar00rootroot00000000000000package validator import ( _ "embed" "github.com/vektah/gqlparser/v2/ast" ) //go:embed prelude.graphql var preludeGraphql string var Prelude = &ast.Source{ Name: "prelude.graphql", Input: preludeGraphql, BuiltIn: true, } gqlparser-2.5.1/validator/prelude.graphql000066400000000000000000000076671430663104200205430ustar00rootroot00000000000000# This file defines all the implicitly declared types that are required by the graphql spec. It is implicitly included by calls to LoadSchema "The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1." scalar Int "The `Float` scalar type represents signed double-precision fractional values as specified by [IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point)." scalar Float "The `String`scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text." scalar String "The `Boolean` scalar type represents `true` or `false`." scalar Boolean """The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as "4") or integer (such as 4) input value will be accepted as an ID.""" scalar ID "The @include directive may be provided for fields, fragment spreads, and inline fragments, and allows for conditional inclusion during execution as described by the if argument." directive @include(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT "The @skip directive may be provided for fields, fragment spreads, and inline fragments, and allows for conditional exclusion during execution as described by the if argument." directive @skip(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT "The @deprecated built-in directive is used within the type system definition language to indicate deprecated portions of a GraphQL service's schema, such as deprecated fields on a type, arguments on a field, input fields on an input type, or values of an enum type." directive @deprecated(reason: String = "No longer supported") on FIELD_DEFINITION | ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION | ENUM_VALUE "The @specifiedBy built-in directive is used within the type system definition language to provide a scalar specification URL for specifying the behavior of custom scalar types." directive @specifiedBy(url: String!) on SCALAR type __Schema { description: String types: [__Type!]! queryType: __Type! mutationType: __Type subscriptionType: __Type directives: [__Directive!]! } type __Type { kind: __TypeKind! name: String description: String # must be non-null for OBJECT and INTERFACE, otherwise null. fields(includeDeprecated: Boolean = false): [__Field!] # must be non-null for OBJECT and INTERFACE, otherwise null. interfaces: [__Type!] # must be non-null for INTERFACE and UNION, otherwise null. possibleTypes: [__Type!] # must be non-null for ENUM, otherwise null. enumValues(includeDeprecated: Boolean = false): [__EnumValue!] # must be non-null for INPUT_OBJECT, otherwise null. inputFields: [__InputValue!] # must be non-null for NON_NULL and LIST, otherwise null. ofType: __Type # may be non-null for custom SCALAR, otherwise null. specifiedByURL: String } type __Field { name: String! description: String args: [__InputValue!]! type: __Type! isDeprecated: Boolean! deprecationReason: String } type __InputValue { name: String! description: String type: __Type! defaultValue: String } type __EnumValue { name: String! description: String isDeprecated: Boolean! deprecationReason: String } enum __TypeKind { SCALAR OBJECT INTERFACE UNION ENUM INPUT_OBJECT LIST NON_NULL } type __Directive { name: String! description: String locations: [__DirectiveLocation!]! args: [__InputValue!]! isRepeatable: Boolean! } enum __DirectiveLocation { QUERY MUTATION SUBSCRIPTION FIELD FRAGMENT_DEFINITION FRAGMENT_SPREAD INLINE_FRAGMENT VARIABLE_DEFINITION SCHEMA SCALAR OBJECT FIELD_DEFINITION ARGUMENT_DEFINITION INTERFACE UNION ENUM ENUM_VALUE INPUT_OBJECT INPUT_FIELD_DEFINITION } gqlparser-2.5.1/validator/rules/000077500000000000000000000000001430663104200166355ustar00rootroot00000000000000gqlparser-2.5.1/validator/rules/fields_on_correct_type.go000066400000000000000000000056041430663104200237150ustar00rootroot00000000000000package validator import ( "fmt" "sort" "strings" "github.com/vektah/gqlparser/v2/ast" . "github.com/vektah/gqlparser/v2/validator" ) func init() { AddRule("FieldsOnCorrectType", func(observers *Events, addError AddErrFunc) { observers.OnField(func(walker *Walker, field *ast.Field) { if field.ObjectDefinition == nil || field.Definition != nil { return } message := fmt.Sprintf(`Cannot query field "%s" on type "%s".`, field.Name, field.ObjectDefinition.Name) if suggestedTypeNames := getSuggestedTypeNames(walker, field.ObjectDefinition, field.Name); suggestedTypeNames != nil { message += " Did you mean to use an inline fragment on " + QuotedOrList(suggestedTypeNames...) + "?" } else if suggestedFieldNames := getSuggestedFieldNames(field.ObjectDefinition, field.Name); suggestedFieldNames != nil { message += " Did you mean " + QuotedOrList(suggestedFieldNames...) + "?" } addError( Message(message), At(field.Position), ) }) }) } // Go through all of 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 // with Interfaces. func getSuggestedTypeNames(walker *Walker, parent *ast.Definition, name string) []string { if !parent.IsAbstractType() { return nil } var suggestedObjectTypes []string var suggestedInterfaceTypes []string interfaceUsageCount := map[string]int{} for _, possibleType := range walker.Schema.GetPossibleTypes(parent) { field := possibleType.Fields.ForName(name) if field == nil { continue } suggestedObjectTypes = append(suggestedObjectTypes, possibleType.Name) for _, possibleInterface := range possibleType.Interfaces { interfaceField := walker.Schema.Types[possibleInterface] if interfaceField != nil && interfaceField.Fields.ForName(name) != nil { if interfaceUsageCount[possibleInterface] == 0 { suggestedInterfaceTypes = append(suggestedInterfaceTypes, possibleInterface) } interfaceUsageCount[possibleInterface]++ } } } suggestedTypes := append(suggestedInterfaceTypes, suggestedObjectTypes...) sort.SliceStable(suggestedTypes, func(i, j int) bool { typeA, typeB := suggestedTypes[i], suggestedTypes[j] diff := interfaceUsageCount[typeB] - interfaceUsageCount[typeA] if diff != 0 { return diff < 0 } return strings.Compare(typeA, typeB) < 0 }) return suggestedTypes } // For the field name provided, determine if there are any similar field names // that may be the result of a typo. func getSuggestedFieldNames(parent *ast.Definition, name string) []string { if parent.Kind != ast.Object && parent.Kind != ast.Interface { return nil } var possibleFieldNames []string for _, field := range parent.Fields { possibleFieldNames = append(possibleFieldNames, field.Name) } return SuggestionList(name, possibleFieldNames) } gqlparser-2.5.1/validator/rules/fragments_on_composite_types.go000066400000000000000000000020461430663104200251560ustar00rootroot00000000000000package validator import ( "fmt" "github.com/vektah/gqlparser/v2/ast" . "github.com/vektah/gqlparser/v2/validator" ) func init() { AddRule("FragmentsOnCompositeTypes", func(observers *Events, addError AddErrFunc) { observers.OnInlineFragment(func(walker *Walker, inlineFragment *ast.InlineFragment) { fragmentType := walker.Schema.Types[inlineFragment.TypeCondition] if fragmentType == nil || fragmentType.IsCompositeType() { return } message := fmt.Sprintf(`Fragment cannot condition on non composite type "%s".`, inlineFragment.TypeCondition) addError( Message(message), At(inlineFragment.Position), ) }) observers.OnFragment(func(walker *Walker, fragment *ast.FragmentDefinition) { if fragment.Definition == nil || fragment.TypeCondition == "" || fragment.Definition.IsCompositeType() { return } message := fmt.Sprintf(`Fragment "%s" cannot condition on non composite type "%s".`, fragment.Name, fragment.TypeCondition) addError( Message(message), At(fragment.Position), ) }) }) } gqlparser-2.5.1/validator/rules/known_argument_names.go000066400000000000000000000030521430663104200234050ustar00rootroot00000000000000package validator import ( "github.com/vektah/gqlparser/v2/ast" . "github.com/vektah/gqlparser/v2/validator" ) func init() { AddRule("KnownArgumentNames", func(observers *Events, addError AddErrFunc) { // A GraphQL field is only valid if all supplied arguments are defined by that field. observers.OnField(func(walker *Walker, field *ast.Field) { if field.Definition == nil || field.ObjectDefinition == nil { return } for _, arg := range field.Arguments { def := field.Definition.Arguments.ForName(arg.Name) if def != nil { continue } var suggestions []string for _, argDef := range field.Definition.Arguments { suggestions = append(suggestions, argDef.Name) } addError( Message(`Unknown argument "%s" on field "%s.%s".`, arg.Name, field.ObjectDefinition.Name, field.Name), SuggestListQuoted("Did you mean", arg.Name, suggestions), At(field.Position), ) } }) observers.OnDirective(func(walker *Walker, directive *ast.Directive) { if directive.Definition == nil { return } for _, arg := range directive.Arguments { def := directive.Definition.Arguments.ForName(arg.Name) if def != nil { continue } var suggestions []string for _, argDef := range directive.Definition.Arguments { suggestions = append(suggestions, argDef.Name) } addError( Message(`Unknown argument "%s" on directive "@%s".`, arg.Name, directive.Name), SuggestListQuoted("Did you mean", arg.Name, suggestions), At(directive.Position), ) } }) }) } gqlparser-2.5.1/validator/rules/known_directives.go000066400000000000000000000021351430663104200225420ustar00rootroot00000000000000package validator import ( "github.com/vektah/gqlparser/v2/ast" . "github.com/vektah/gqlparser/v2/validator" ) func init() { AddRule("KnownDirectives", func(observers *Events, addError AddErrFunc) { type mayNotBeUsedDirective struct { Name string Line int Column int } var seen map[mayNotBeUsedDirective]bool = map[mayNotBeUsedDirective]bool{} observers.OnDirective(func(walker *Walker, directive *ast.Directive) { if directive.Definition == nil { addError( Message(`Unknown directive "@%s".`, directive.Name), At(directive.Position), ) return } for _, loc := range directive.Definition.Locations { if loc == directive.Location { return } } // position must be exists if directive.Definition != nil tmp := mayNotBeUsedDirective{ Name: directive.Name, Line: directive.Position.Line, Column: directive.Position.Column, } if !seen[tmp] { addError( Message(`Directive "@%s" may not be used on %s.`, directive.Name, directive.Location), At(directive.Position), ) seen[tmp] = true } }) }) } gqlparser-2.5.1/validator/rules/known_fragment_names.go000066400000000000000000000007231430663104200233700ustar00rootroot00000000000000package validator import ( "github.com/vektah/gqlparser/v2/ast" . "github.com/vektah/gqlparser/v2/validator" ) func init() { AddRule("KnownFragmentNames", func(observers *Events, addError AddErrFunc) { observers.OnFragmentSpread(func(walker *Walker, fragmentSpread *ast.FragmentSpread) { if fragmentSpread.Definition == nil { addError( Message(`Unknown fragment "%s".`, fragmentSpread.Name), At(fragmentSpread.Position), ) } }) }) } gqlparser-2.5.1/validator/rules/known_root_type.go000066400000000000000000000017521430663104200224310ustar00rootroot00000000000000package validator import ( "fmt" "github.com/vektah/gqlparser/v2/ast" . "github.com/vektah/gqlparser/v2/validator" ) func init() { AddRule("KnownRootType", func(observers *Events, addError AddErrFunc) { // A query's root must be a valid type. Surprisingly, this isn't // checked anywhere else! observers.OnOperation(func(walker *Walker, operation *ast.OperationDefinition) { var def *ast.Definition switch operation.Operation { case ast.Query, "": def = walker.Schema.Query case ast.Mutation: def = walker.Schema.Mutation case ast.Subscription: def = walker.Schema.Subscription default: // This shouldn't even parse; if it did we probably need to // update this switch block to add the new operation type. panic(fmt.Sprintf(`got unknown operation type "%s"`, operation.Operation)) } if def == nil { addError( Message(`Schema does not support operation type "%s"`, operation.Operation), At(operation.Position)) } }) }) } gqlparser-2.5.1/validator/rules/known_type_names.go000066400000000000000000000024731430663104200225520ustar00rootroot00000000000000package validator import ( "github.com/vektah/gqlparser/v2/ast" . "github.com/vektah/gqlparser/v2/validator" ) func init() { AddRule("KnownTypeNames", func(observers *Events, addError AddErrFunc) { observers.OnVariable(func(walker *Walker, variable *ast.VariableDefinition) { typeName := variable.Type.Name() typdef := walker.Schema.Types[typeName] if typdef != nil { return } addError( Message(`Unknown type "%s".`, typeName), At(variable.Position), ) }) observers.OnInlineFragment(func(walker *Walker, inlineFragment *ast.InlineFragment) { typedName := inlineFragment.TypeCondition if typedName == "" { return } def := walker.Schema.Types[typedName] if def != nil { return } addError( Message(`Unknown type "%s".`, typedName), At(inlineFragment.Position), ) }) observers.OnFragment(func(walker *Walker, fragment *ast.FragmentDefinition) { typeName := fragment.TypeCondition def := walker.Schema.Types[typeName] if def != nil { return } var possibleTypes []string for _, t := range walker.Schema.Types { possibleTypes = append(possibleTypes, t.Name) } addError( Message(`Unknown type "%s".`, typeName), SuggestListQuoted("Did you mean", typeName, possibleTypes), At(fragment.Position), ) }) }) } gqlparser-2.5.1/validator/rules/lone_anonymous_operation.go000066400000000000000000000007711430663104200243160ustar00rootroot00000000000000package validator import ( "github.com/vektah/gqlparser/v2/ast" . "github.com/vektah/gqlparser/v2/validator" ) func init() { AddRule("LoneAnonymousOperation", func(observers *Events, addError AddErrFunc) { observers.OnOperation(func(walker *Walker, operation *ast.OperationDefinition) { if operation.Name == "" && len(walker.Document.Operations) > 1 { addError( Message(`This anonymous operation must be the only defined operation.`), At(operation.Position), ) } }) }) } gqlparser-2.5.1/validator/rules/no_fragment_cycles.go000066400000000000000000000046011430663104200230260ustar00rootroot00000000000000package validator import ( "fmt" "strings" "github.com/vektah/gqlparser/v2/ast" . "github.com/vektah/gqlparser/v2/validator" ) func init() { AddRule("NoFragmentCycles", func(observers *Events, addError AddErrFunc) { visitedFrags := make(map[string]bool) observers.OnFragment(func(walker *Walker, fragment *ast.FragmentDefinition) { var spreadPath []*ast.FragmentSpread spreadPathIndexByName := make(map[string]int) var recursive func(fragment *ast.FragmentDefinition) recursive = func(fragment *ast.FragmentDefinition) { if visitedFrags[fragment.Name] { return } visitedFrags[fragment.Name] = true spreadNodes := getFragmentSpreads(fragment.SelectionSet) if len(spreadNodes) == 0 { return } spreadPathIndexByName[fragment.Name] = len(spreadPath) for _, spreadNode := range spreadNodes { spreadName := spreadNode.Name cycleIndex, ok := spreadPathIndexByName[spreadName] spreadPath = append(spreadPath, spreadNode) if !ok { spreadFragment := walker.Document.Fragments.ForName(spreadName) if spreadFragment != nil { recursive(spreadFragment) } } else { cyclePath := spreadPath[cycleIndex : len(spreadPath)-1] var fragmentNames []string for _, fs := range cyclePath { fragmentNames = append(fragmentNames, fmt.Sprintf(`"%s"`, fs.Name)) } var via string if len(fragmentNames) != 0 { via = fmt.Sprintf(" via %s", strings.Join(fragmentNames, ", ")) } addError( Message(`Cannot spread fragment "%s" within itself%s.`, spreadName, via), At(spreadNode.Position), ) } spreadPath = spreadPath[:len(spreadPath)-1] } delete(spreadPathIndexByName, fragment.Name) } recursive(fragment) }) }) } func getFragmentSpreads(node ast.SelectionSet) []*ast.FragmentSpread { var spreads []*ast.FragmentSpread setsToVisit := []ast.SelectionSet{node} for len(setsToVisit) != 0 { set := setsToVisit[len(setsToVisit)-1] setsToVisit = setsToVisit[:len(setsToVisit)-1] for _, selection := range set { switch selection := selection.(type) { case *ast.FragmentSpread: spreads = append(spreads, selection) case *ast.Field: setsToVisit = append(setsToVisit, selection.SelectionSet) case *ast.InlineFragment: setsToVisit = append(setsToVisit, selection.SelectionSet) } } } return spreads } gqlparser-2.5.1/validator/rules/no_undefined_variables.go000066400000000000000000000013041430663104200236470ustar00rootroot00000000000000package validator import ( "github.com/vektah/gqlparser/v2/ast" . "github.com/vektah/gqlparser/v2/validator" ) func init() { AddRule("NoUndefinedVariables", func(observers *Events, addError AddErrFunc) { observers.OnValue(func(walker *Walker, value *ast.Value) { if walker.CurrentOperation == nil || value.Kind != ast.Variable || value.VariableDefinition != nil { return } if walker.CurrentOperation.Name != "" { addError( Message(`Variable "%s" is not defined by operation "%s".`, value, walker.CurrentOperation.Name), At(value.Position), ) } else { addError( Message(`Variable "%s" is not defined.`, value), At(value.Position), ) } }) }) } gqlparser-2.5.1/validator/rules/no_unused_fragments.go000066400000000000000000000013431430663104200232320ustar00rootroot00000000000000package validator import ( "github.com/vektah/gqlparser/v2/ast" . "github.com/vektah/gqlparser/v2/validator" ) func init() { AddRule("NoUnusedFragments", func(observers *Events, addError AddErrFunc) { inFragmentDefinition := false fragmentNameUsed := make(map[string]bool) observers.OnFragmentSpread(func(walker *Walker, fragmentSpread *ast.FragmentSpread) { if !inFragmentDefinition { fragmentNameUsed[fragmentSpread.Name] = true } }) observers.OnFragment(func(walker *Walker, fragment *ast.FragmentDefinition) { inFragmentDefinition = true if !fragmentNameUsed[fragment.Name] { addError( Message(`Fragment "%s" is never used.`, fragment.Name), At(fragment.Position), ) } }) }) } gqlparser-2.5.1/validator/rules/no_unused_variables.go000066400000000000000000000013141430663104200232120ustar00rootroot00000000000000package validator import ( "github.com/vektah/gqlparser/v2/ast" . "github.com/vektah/gqlparser/v2/validator" ) func init() { AddRule("NoUnusedVariables", func(observers *Events, addError AddErrFunc) { observers.OnOperation(func(walker *Walker, operation *ast.OperationDefinition) { for _, varDef := range operation.VariableDefinitions { if varDef.Used { continue } if operation.Name != "" { addError( Message(`Variable "$%s" is never used in operation "%s".`, varDef.Variable, operation.Name), At(varDef.Position), ) } else { addError( Message(`Variable "$%s" is never used.`, varDef.Variable), At(varDef.Position), ) } } }) }) } gqlparser-2.5.1/validator/rules/overlapping_fields_can_be_merged.go000066400000000000000000000441711430663104200256610ustar00rootroot00000000000000package validator import ( "bytes" "fmt" "reflect" "github.com/vektah/gqlparser/v2/ast" . "github.com/vektah/gqlparser/v2/validator" ) func init() { AddRule("OverlappingFieldsCanBeMerged", func(observers *Events, addError AddErrFunc) { /** * Algorithm: * * Conflicts occur when two fields exist in a query which will produce the same * response name, but represent differing values, thus creating a conflict. * The algorithm below finds all conflicts via making a series of comparisons * between fields. In order to compare as few fields as possible, this makes * a series of comparisons "within" sets of fields and "between" sets of fields. * * Given any selection set, a collection produces both a set of fields by * also including all inline fragments, as well as a list of fragments * referenced by fragment spreads. * * A) Each selection set represented in the document first compares "within" its * collected set of fields, finding any conflicts between every pair of * overlapping fields. * Note: This is the *only time* that a the fields "within" a set are compared * to each other. After this only fields "between" sets are compared. * * B) Also, if any fragment is referenced in a selection set, then a * comparison is made "between" the original set of fields and the * referenced fragment. * * C) Also, if multiple fragments are referenced, then comparisons * are made "between" each referenced fragment. * * D) When comparing "between" a set of fields and a referenced fragment, first * a comparison is made between each field in the original set of fields and * each field in the the referenced set of fields. * * E) Also, if any fragment is referenced in the referenced selection set, * then a comparison is made "between" the original set of fields and the * referenced fragment (recursively referring to step D). * * F) When comparing "between" two fragments, first a comparison is made between * each field in the first referenced set of fields and each field in the the * second referenced set of fields. * * G) Also, any fragments referenced by the first must be compared to the * second, and any fragments referenced by the second must be compared to the * first (recursively referring to step F). * * H) When comparing two fields, if both have selection sets, then a comparison * is made "between" both selection sets, first comparing the set of fields in * the first selection set with the set of fields in the second. * * I) Also, if any fragment is referenced in either selection set, then a * comparison is made "between" the other set of fields and the * referenced fragment. * * J) Also, if two fragments are referenced in both selection sets, then a * comparison is made "between" the two fragments. * */ m := &overlappingFieldsCanBeMergedManager{ comparedFragmentPairs: pairSet{data: make(map[string]map[string]bool)}, } observers.OnOperation(func(walker *Walker, operation *ast.OperationDefinition) { m.walker = walker conflicts := m.findConflictsWithinSelectionSet(operation.SelectionSet) for _, conflict := range conflicts { conflict.addFieldsConflictMessage(addError) } }) observers.OnField(func(walker *Walker, field *ast.Field) { if walker.CurrentOperation == nil { // When checking both Operation and Fragment, errors are duplicated when processing FragmentDefinition referenced from Operation return } m.walker = walker conflicts := m.findConflictsWithinSelectionSet(field.SelectionSet) for _, conflict := range conflicts { conflict.addFieldsConflictMessage(addError) } }) observers.OnInlineFragment(func(walker *Walker, inlineFragment *ast.InlineFragment) { m.walker = walker conflicts := m.findConflictsWithinSelectionSet(inlineFragment.SelectionSet) for _, conflict := range conflicts { conflict.addFieldsConflictMessage(addError) } }) observers.OnFragment(func(walker *Walker, fragment *ast.FragmentDefinition) { m.walker = walker conflicts := m.findConflictsWithinSelectionSet(fragment.SelectionSet) for _, conflict := range conflicts { conflict.addFieldsConflictMessage(addError) } }) }) } type pairSet struct { data map[string]map[string]bool } func (pairSet *pairSet) Add(a *ast.FragmentSpread, b *ast.FragmentSpread, areMutuallyExclusive bool) { add := func(a *ast.FragmentSpread, b *ast.FragmentSpread) { m := pairSet.data[a.Name] if m == nil { m = make(map[string]bool) pairSet.data[a.Name] = m } m[b.Name] = areMutuallyExclusive } add(a, b) add(b, a) } func (pairSet *pairSet) Has(a *ast.FragmentSpread, b *ast.FragmentSpread, areMutuallyExclusive bool) bool { am, ok := pairSet.data[a.Name] if !ok { return false } result, ok := am[b.Name] if !ok { return false } // areMutuallyExclusive being false is a superset of being true, // hence if we want to know if this PairSet "has" these two with no // exclusivity, we have to ensure it was added as such. if !areMutuallyExclusive { return !result } return true } type sequentialFieldsMap struct { // We can't use map[string][]*ast.Field. because map is not stable... seq []string data map[string][]*ast.Field } type fieldIterateEntry struct { ResponseName string Fields []*ast.Field } func (m *sequentialFieldsMap) Push(responseName string, field *ast.Field) { fields, ok := m.data[responseName] if !ok { m.seq = append(m.seq, responseName) } fields = append(fields, field) m.data[responseName] = fields } func (m *sequentialFieldsMap) Get(responseName string) ([]*ast.Field, bool) { fields, ok := m.data[responseName] return fields, ok } func (m *sequentialFieldsMap) Iterator() [][]*ast.Field { fieldsList := make([][]*ast.Field, 0, len(m.seq)) for _, responseName := range m.seq { fields := m.data[responseName] fieldsList = append(fieldsList, fields) } return fieldsList } func (m *sequentialFieldsMap) KeyValueIterator() []*fieldIterateEntry { fieldEntriesList := make([]*fieldIterateEntry, 0, len(m.seq)) for _, responseName := range m.seq { fields := m.data[responseName] fieldEntriesList = append(fieldEntriesList, &fieldIterateEntry{ ResponseName: responseName, Fields: fields, }) } return fieldEntriesList } type conflictMessageContainer struct { Conflicts []*ConflictMessage } type ConflictMessage struct { Message string ResponseName string Names []string SubMessage []*ConflictMessage Position *ast.Position } func (m *ConflictMessage) String(buf *bytes.Buffer) { if len(m.SubMessage) == 0 { buf.WriteString(m.Message) return } for idx, subMessage := range m.SubMessage { buf.WriteString(`subfields "`) buf.WriteString(subMessage.ResponseName) buf.WriteString(`" conflict because `) subMessage.String(buf) if idx != len(m.SubMessage)-1 { buf.WriteString(" and ") } } } func (m *ConflictMessage) addFieldsConflictMessage(addError AddErrFunc) { var buf bytes.Buffer m.String(&buf) addError( Message(`Fields "%s" conflict because %s. Use different aliases on the fields to fetch both if this was intentional.`, m.ResponseName, buf.String()), At(m.Position), ) } type overlappingFieldsCanBeMergedManager struct { walker *Walker // per walker comparedFragmentPairs pairSet // cachedFieldsAndFragmentNames interface{} // per selectionSet comparedFragments map[string]bool } func (m *overlappingFieldsCanBeMergedManager) findConflictsWithinSelectionSet(selectionSet ast.SelectionSet) []*ConflictMessage { if len(selectionSet) == 0 { return nil } fieldsMap, fragmentSpreads := getFieldsAndFragmentNames(selectionSet) var conflicts conflictMessageContainer // (A) Find find all conflicts "within" the fieldMap of this selection set. // Note: this is the *only place* `collectConflictsWithin` is called. m.collectConflictsWithin(&conflicts, fieldsMap) m.comparedFragments = make(map[string]bool) for idx, fragmentSpreadA := range fragmentSpreads { // (B) Then collect conflicts between these fieldMap and those represented by // each spread fragment name found. m.collectConflictsBetweenFieldsAndFragment(&conflicts, false, fieldsMap, fragmentSpreadA) for _, fragmentSpreadB := range fragmentSpreads[idx+1:] { // (C) Then compare this fragment with all other fragments found in this // selection set to collect conflicts between fragments spread together. // This compares each item in the list of fragment names to every other // item in that same list (except for itself). m.collectConflictsBetweenFragments(&conflicts, false, fragmentSpreadA, fragmentSpreadB) } } return conflicts.Conflicts } func (m *overlappingFieldsCanBeMergedManager) collectConflictsBetweenFieldsAndFragment(conflicts *conflictMessageContainer, areMutuallyExclusive bool, fieldsMap *sequentialFieldsMap, fragmentSpread *ast.FragmentSpread) { if m.comparedFragments[fragmentSpread.Name] { return } m.comparedFragments[fragmentSpread.Name] = true if fragmentSpread.Definition == nil { return } fieldsMapB, fragmentSpreads := getFieldsAndFragmentNames(fragmentSpread.Definition.SelectionSet) // Do not compare a fragment's fieldMap to itself. if reflect.DeepEqual(fieldsMap, fieldsMapB) { return } // (D) First collect any conflicts between the provided collection of fields // and the collection of fields represented by the given fragment. m.collectConflictsBetween(conflicts, areMutuallyExclusive, fieldsMap, fieldsMapB) // (E) Then collect any conflicts between the provided collection of fields // and any fragment names found in the given fragment. baseFragmentSpread := fragmentSpread for _, fragmentSpread := range fragmentSpreads { if fragmentSpread.Name == baseFragmentSpread.Name { continue } m.collectConflictsBetweenFieldsAndFragment(conflicts, areMutuallyExclusive, fieldsMap, fragmentSpread) } } func (m *overlappingFieldsCanBeMergedManager) collectConflictsBetweenFragments(conflicts *conflictMessageContainer, areMutuallyExclusive bool, fragmentSpreadA *ast.FragmentSpread, fragmentSpreadB *ast.FragmentSpread) { var check func(fragmentSpreadA *ast.FragmentSpread, fragmentSpreadB *ast.FragmentSpread) check = func(fragmentSpreadA *ast.FragmentSpread, fragmentSpreadB *ast.FragmentSpread) { if fragmentSpreadA.Name == fragmentSpreadB.Name { return } if m.comparedFragmentPairs.Has(fragmentSpreadA, fragmentSpreadB, areMutuallyExclusive) { return } m.comparedFragmentPairs.Add(fragmentSpreadA, fragmentSpreadB, areMutuallyExclusive) if fragmentSpreadA.Definition == nil { return } if fragmentSpreadB.Definition == nil { return } fieldsMapA, fragmentSpreadsA := getFieldsAndFragmentNames(fragmentSpreadA.Definition.SelectionSet) fieldsMapB, fragmentSpreadsB := getFieldsAndFragmentNames(fragmentSpreadB.Definition.SelectionSet) // (F) First, collect all conflicts between these two collections of fields // (not including any nested fragments). m.collectConflictsBetween(conflicts, areMutuallyExclusive, fieldsMapA, fieldsMapB) // (G) Then collect conflicts between the first fragment and any nested // fragments spread in the second fragment. for _, fragmentSpread := range fragmentSpreadsB { check(fragmentSpreadA, fragmentSpread) } // (G) Then collect conflicts between the second fragment and any nested // fragments spread in the first fragment. for _, fragmentSpread := range fragmentSpreadsA { check(fragmentSpread, fragmentSpreadB) } } check(fragmentSpreadA, fragmentSpreadB) } func (m *overlappingFieldsCanBeMergedManager) findConflictsBetweenSubSelectionSets(areMutuallyExclusive bool, selectionSetA ast.SelectionSet, selectionSetB ast.SelectionSet) *conflictMessageContainer { var conflicts conflictMessageContainer fieldsMapA, fragmentSpreadsA := getFieldsAndFragmentNames(selectionSetA) fieldsMapB, fragmentSpreadsB := getFieldsAndFragmentNames(selectionSetB) // (H) First, collect all conflicts between these two collections of field. m.collectConflictsBetween(&conflicts, areMutuallyExclusive, fieldsMapA, fieldsMapB) // (I) Then collect conflicts between the first collection of fields and // those referenced by each fragment name associated with the second. for _, fragmentSpread := range fragmentSpreadsB { m.comparedFragments = make(map[string]bool) m.collectConflictsBetweenFieldsAndFragment(&conflicts, areMutuallyExclusive, fieldsMapA, fragmentSpread) } // (I) Then collect conflicts between the second collection of fields and // those referenced by each fragment name associated with the first. for _, fragmentSpread := range fragmentSpreadsA { m.comparedFragments = make(map[string]bool) m.collectConflictsBetweenFieldsAndFragment(&conflicts, areMutuallyExclusive, fieldsMapB, fragmentSpread) } // (J) Also collect conflicts between any fragment names by the first and // fragment names by the second. This compares each item in the first set of // names to each item in the second set of names. for _, fragmentSpreadA := range fragmentSpreadsA { for _, fragmentSpreadB := range fragmentSpreadsB { m.collectConflictsBetweenFragments(&conflicts, areMutuallyExclusive, fragmentSpreadA, fragmentSpreadB) } } if len(conflicts.Conflicts) == 0 { return nil } return &conflicts } func (m *overlappingFieldsCanBeMergedManager) collectConflictsWithin(conflicts *conflictMessageContainer, fieldsMap *sequentialFieldsMap) { for _, fields := range fieldsMap.Iterator() { for idx, fieldA := range fields { for _, fieldB := range fields[idx+1:] { conflict := m.findConflict(false, fieldA, fieldB) if conflict != nil { conflicts.Conflicts = append(conflicts.Conflicts, conflict) } } } } } func (m *overlappingFieldsCanBeMergedManager) collectConflictsBetween(conflicts *conflictMessageContainer, parentFieldsAreMutuallyExclusive bool, fieldsMapA *sequentialFieldsMap, fieldsMapB *sequentialFieldsMap) { for _, fieldsEntryA := range fieldsMapA.KeyValueIterator() { fieldsB, ok := fieldsMapB.Get(fieldsEntryA.ResponseName) if !ok { continue } for _, fieldA := range fieldsEntryA.Fields { for _, fieldB := range fieldsB { conflict := m.findConflict(parentFieldsAreMutuallyExclusive, fieldA, fieldB) if conflict != nil { conflicts.Conflicts = append(conflicts.Conflicts, conflict) } } } } } func (m *overlappingFieldsCanBeMergedManager) findConflict(parentFieldsAreMutuallyExclusive bool, fieldA *ast.Field, fieldB *ast.Field) *ConflictMessage { if fieldA.ObjectDefinition == nil || fieldB.ObjectDefinition == nil { return nil } areMutuallyExclusive := parentFieldsAreMutuallyExclusive if !areMutuallyExclusive { tmp := fieldA.ObjectDefinition.Name != fieldB.ObjectDefinition.Name tmp = tmp && fieldA.ObjectDefinition.Kind == ast.Object tmp = tmp && fieldB.ObjectDefinition.Kind == ast.Object tmp = tmp && fieldA.Definition != nil && fieldB.Definition != nil areMutuallyExclusive = tmp } fieldNameA := fieldA.Name if fieldA.Alias != "" { fieldNameA = fieldA.Alias } if !areMutuallyExclusive { // Two aliases must refer to the same field. if fieldA.Name != fieldB.Name { return &ConflictMessage{ ResponseName: fieldNameA, Message: fmt.Sprintf(`"%s" and "%s" are different fields`, fieldA.Name, fieldB.Name), Position: fieldB.Position, } } // Two field calls must have the same arguments. if !sameArguments(fieldA.Arguments, fieldB.Arguments) { return &ConflictMessage{ ResponseName: fieldNameA, Message: "they have differing arguments", Position: fieldB.Position, } } } if fieldA.Definition != nil && fieldB.Definition != nil && doTypesConflict(m.walker, fieldA.Definition.Type, fieldB.Definition.Type) { return &ConflictMessage{ ResponseName: fieldNameA, Message: fmt.Sprintf(`they return conflicting types "%s" and "%s"`, fieldA.Definition.Type.String(), fieldB.Definition.Type.String()), Position: fieldB.Position, } } // Collect and compare sub-fields. Use the same "visited fragment names" list // for both collections so fields in a fragment reference are never // compared to themselves. conflicts := m.findConflictsBetweenSubSelectionSets(areMutuallyExclusive, fieldA.SelectionSet, fieldB.SelectionSet) if conflicts == nil { return nil } return &ConflictMessage{ ResponseName: fieldNameA, SubMessage: conflicts.Conflicts, Position: fieldB.Position, } } func sameArguments(args1 []*ast.Argument, args2 []*ast.Argument) bool { if len(args1) != len(args2) { return false } for _, arg1 := range args1 { var matched bool for _, arg2 := range args2 { if arg1.Name == arg2.Name && sameValue(arg1.Value, arg2.Value) { matched = true break } } if !matched { return false } } return true } func sameValue(value1 *ast.Value, value2 *ast.Value) bool { if value1.Kind != value2.Kind { return false } if value1.Raw != value2.Raw { return false } return true } func doTypesConflict(walker *Walker, type1 *ast.Type, type2 *ast.Type) bool { if type1.Elem != nil { if type2.Elem != nil { return doTypesConflict(walker, type1.Elem, type2.Elem) } return true } if type2.Elem != nil { return true } if type1.NonNull && !type2.NonNull { return true } if !type1.NonNull && type2.NonNull { return true } t1 := walker.Schema.Types[type1.NamedType] t2 := walker.Schema.Types[type2.NamedType] if (t1.Kind == ast.Scalar || t1.Kind == ast.Enum) && (t2.Kind == ast.Scalar || t2.Kind == ast.Enum) { return t1.Name != t2.Name } return false } func getFieldsAndFragmentNames(selectionSet ast.SelectionSet) (*sequentialFieldsMap, []*ast.FragmentSpread) { fieldsMap := sequentialFieldsMap{ data: make(map[string][]*ast.Field), } var fragmentSpreads []*ast.FragmentSpread var walk func(selectionSet ast.SelectionSet) walk = func(selectionSet ast.SelectionSet) { for _, selection := range selectionSet { switch selection := selection.(type) { case *ast.Field: responseName := selection.Name if selection.Alias != "" { responseName = selection.Alias } fieldsMap.Push(responseName, selection) case *ast.InlineFragment: walk(selection.SelectionSet) case *ast.FragmentSpread: fragmentSpreads = append(fragmentSpreads, selection) } } } walk(selectionSet) return &fieldsMap, fragmentSpreads } gqlparser-2.5.1/validator/rules/overlapping_fields_can_be_merged_test.go000066400000000000000000000062371430663104200267210ustar00rootroot00000000000000package validator import ( "testing" "github.com/vektah/gqlparser/v2/ast" ) func Test_sameArguments(t *testing.T) { tests := map[string]struct { args func() (args1, args2 []*ast.Argument) result bool }{ "both argument lists empty": { args: func() (args1 []*ast.Argument, args2 []*ast.Argument) { return nil, nil }, result: true, }, "args 1 empty, args 2 not": { args: func() (args1 []*ast.Argument, args2 []*ast.Argument) { return nil, []*ast.Argument{ { Name: "thing", Value: &ast.Value{Raw: "a thing"}, Position: &ast.Position{}, }, } }, result: false, }, "args 2 empty, args 1 not": { args: func() (args1 []*ast.Argument, args2 []*ast.Argument) { return []*ast.Argument{ { Name: "thing", Value: &ast.Value{Raw: "a thing"}, Position: &ast.Position{}, }, }, nil }, result: false, }, "args 1 mismatches args 2 names": { args: func() (args1 []*ast.Argument, args2 []*ast.Argument) { return []*ast.Argument{ { Name: "thing1", Value: &ast.Value{Raw: "1 thing"}, Position: &ast.Position{}, }, }, []*ast.Argument{ { Name: "thing2", Value: &ast.Value{Raw: "2 thing"}, Position: &ast.Position{}, }, } }, result: false, }, "args 1 mismatches args 2 values": { args: func() (args1 []*ast.Argument, args2 []*ast.Argument) { return []*ast.Argument{ { Name: "thing1", Value: &ast.Value{Raw: "1 thing"}, Position: &ast.Position{}, }, }, []*ast.Argument{ { Name: "thing1", Value: &ast.Value{Raw: "2 thing"}, Position: &ast.Position{}, }, } }, result: false, }, "args 1 matches args 2 names and values": { args: func() (args1 []*ast.Argument, args2 []*ast.Argument) { return []*ast.Argument{ { Name: "thing1", Value: &ast.Value{Raw: "1 thing"}, Position: &ast.Position{}, }, }, []*ast.Argument{ { Name: "thing1", Value: &ast.Value{Raw: "1 thing"}, Position: &ast.Position{}, }, } }, result: true, }, "args 1 matches args 2 names and values where multiple exist in various orders": { args: func() (args1 []*ast.Argument, args2 []*ast.Argument) { return []*ast.Argument{ { Name: "thing1", Value: &ast.Value{Raw: "1 thing"}, Position: &ast.Position{}, }, { Name: "thing2", Value: &ast.Value{Raw: "2 thing"}, Position: &ast.Position{}, }, }, []*ast.Argument{ { Name: "thing1", Value: &ast.Value{Raw: "1 thing"}, Position: &ast.Position{}, }, { Name: "thing2", Value: &ast.Value{Raw: "2 thing"}, Position: &ast.Position{}, }, } }, result: true, }, } for name, tc := range tests { t.Run(name, func(t *testing.T) { args1, args2 := tc.args() resp := sameArguments(args1, args2) if resp != tc.result { t.Fatalf("Expected %t got %t", tc.result, resp) } }) } } gqlparser-2.5.1/validator/rules/possible_fragment_spreads.go000066400000000000000000000037251430663104200244170ustar00rootroot00000000000000package validator import ( "github.com/vektah/gqlparser/v2/ast" . "github.com/vektah/gqlparser/v2/validator" ) func init() { AddRule("PossibleFragmentSpreads", func(observers *Events, addError AddErrFunc) { validate := func(walker *Walker, parentDef *ast.Definition, fragmentName string, emitError func()) { if parentDef == nil { return } var parentDefs []*ast.Definition switch parentDef.Kind { case ast.Object: parentDefs = []*ast.Definition{parentDef} case ast.Interface, ast.Union: parentDefs = walker.Schema.GetPossibleTypes(parentDef) default: return } fragmentDefType := walker.Schema.Types[fragmentName] if fragmentDefType == nil { return } if !fragmentDefType.IsCompositeType() { // checked by FragmentsOnCompositeTypes return } fragmentDefs := walker.Schema.GetPossibleTypes(fragmentDefType) for _, fragmentDef := range fragmentDefs { for _, parentDef := range parentDefs { if parentDef.Name == fragmentDef.Name { return } } } emitError() } observers.OnInlineFragment(func(walker *Walker, inlineFragment *ast.InlineFragment) { validate(walker, inlineFragment.ObjectDefinition, inlineFragment.TypeCondition, func() { addError( Message(`Fragment cannot be spread here as objects of type "%s" can never be of type "%s".`, inlineFragment.ObjectDefinition.Name, inlineFragment.TypeCondition), At(inlineFragment.Position), ) }) }) observers.OnFragmentSpread(func(walker *Walker, fragmentSpread *ast.FragmentSpread) { if fragmentSpread.Definition == nil { return } validate(walker, fragmentSpread.ObjectDefinition, fragmentSpread.Definition.TypeCondition, func() { addError( Message(`Fragment "%s" cannot be spread here as objects of type "%s" can never be of type "%s".`, fragmentSpread.Name, fragmentSpread.ObjectDefinition.Name, fragmentSpread.Definition.TypeCondition), At(fragmentSpread.Position), ) }) }) }) } gqlparser-2.5.1/validator/rules/provided_required_arguments.go000066400000000000000000000026451430663104200247740ustar00rootroot00000000000000package validator import ( "github.com/vektah/gqlparser/v2/ast" . "github.com/vektah/gqlparser/v2/validator" ) func init() { AddRule("ProvidedRequiredArguments", func(observers *Events, addError AddErrFunc) { observers.OnField(func(walker *Walker, field *ast.Field) { if field.Definition == nil { return } argDef: for _, argDef := range field.Definition.Arguments { if !argDef.Type.NonNull { continue } if argDef.DefaultValue != nil { continue } for _, arg := range field.Arguments { if arg.Name == argDef.Name { continue argDef } } addError( Message(`Field "%s" argument "%s" of type "%s" is required, but it was not provided.`, field.Name, argDef.Name, argDef.Type.String()), At(field.Position), ) } }) observers.OnDirective(func(walker *Walker, directive *ast.Directive) { if directive.Definition == nil { return } argDef: for _, argDef := range directive.Definition.Arguments { if !argDef.Type.NonNull { continue } if argDef.DefaultValue != nil { continue } for _, arg := range directive.Arguments { if arg.Name == argDef.Name { continue argDef } } addError( Message(`Directive "@%s" argument "%s" of type "%s" is required, but it was not provided.`, directive.Definition.Name, argDef.Name, argDef.Type.String()), At(directive.Position), ) } }) }) } gqlparser-2.5.1/validator/rules/scalar_leafs.go000066400000000000000000000016501430663104200216050ustar00rootroot00000000000000package validator import ( "github.com/vektah/gqlparser/v2/ast" . "github.com/vektah/gqlparser/v2/validator" ) func init() { AddRule("ScalarLeafs", func(observers *Events, addError AddErrFunc) { observers.OnField(func(walker *Walker, field *ast.Field) { if field.Definition == nil { return } fieldType := walker.Schema.Types[field.Definition.Type.Name()] if fieldType == nil { return } if fieldType.IsLeafType() && len(field.SelectionSet) > 0 { addError( Message(`Field "%s" must not have a selection since type "%s" has no subfields.`, field.Name, fieldType.Name), At(field.Position), ) } if !fieldType.IsLeafType() && len(field.SelectionSet) == 0 { addError( Message(`Field "%s" of type "%s" must have a selection of subfields.`, field.Name, field.Definition.Type.String()), Suggestf(`"%s { ... }"`, field.Name), At(field.Position), ) } }) }) } gqlparser-2.5.1/validator/rules/single_field_subscriptions.go000066400000000000000000000041011430663104200245730ustar00rootroot00000000000000package validator import ( "strconv" "strings" "github.com/vektah/gqlparser/v2/ast" . "github.com/vektah/gqlparser/v2/validator" ) func init() { AddRule("SingleFieldSubscriptions", func(observers *Events, addError AddErrFunc) { observers.OnOperation(func(walker *Walker, operation *ast.OperationDefinition) { if walker.Schema.Subscription == nil || operation.Operation != ast.Subscription { return } fields := retrieveTopFieldNames(operation.SelectionSet) name := "Anonymous Subscription" if operation.Name != "" { name = `Subscription ` + strconv.Quote(operation.Name) } if len(fields) > 1 { addError( Message(`%s must select only one top level field.`, name), At(fields[1].position), ) } for _, field := range fields { if strings.HasPrefix(field.name, "__") { addError( Message(`%s must not select an introspection top level field.`, name), At(field.position), ) } } }) }) } type topField struct { name string position *ast.Position } func retrieveTopFieldNames(selectionSet ast.SelectionSet) []*topField { fields := []*topField{} inFragmentRecursive := map[string]bool{} var walk func(selectionSet ast.SelectionSet) walk = func(selectionSet ast.SelectionSet) { for _, selection := range selectionSet { switch selection := selection.(type) { case *ast.Field: fields = append(fields, &topField{ name: selection.Name, position: selection.GetPosition(), }) case *ast.InlineFragment: walk(selection.SelectionSet) case *ast.FragmentSpread: if selection.Definition == nil { return } fragment := selection.Definition.Name if !inFragmentRecursive[fragment] { inFragmentRecursive[fragment] = true walk(selection.Definition.SelectionSet) } } } } walk(selectionSet) seen := make(map[string]bool, len(fields)) uniquedFields := make([]*topField, 0, len(fields)) for _, field := range fields { if !seen[field.name] { uniquedFields = append(uniquedFields, field) } seen[field.name] = true } return uniquedFields } gqlparser-2.5.1/validator/rules/unique_argument_names.go000066400000000000000000000014021430663104200235540ustar00rootroot00000000000000package validator import ( "github.com/vektah/gqlparser/v2/ast" . "github.com/vektah/gqlparser/v2/validator" ) func init() { AddRule("UniqueArgumentNames", func(observers *Events, addError AddErrFunc) { observers.OnField(func(walker *Walker, field *ast.Field) { checkUniqueArgs(field.Arguments, addError) }) observers.OnDirective(func(walker *Walker, directive *ast.Directive) { checkUniqueArgs(directive.Arguments, addError) }) }) } func checkUniqueArgs(args ast.ArgumentList, addError AddErrFunc) { knownArgNames := map[string]int{} for _, arg := range args { if knownArgNames[arg.Name] == 1 { addError( Message(`There can be only one argument named "%s".`, arg.Name), At(arg.Position), ) } knownArgNames[arg.Name]++ } } gqlparser-2.5.1/validator/rules/unique_directives_per_location.go000066400000000000000000000011241430663104200254470ustar00rootroot00000000000000package validator import ( "github.com/vektah/gqlparser/v2/ast" . "github.com/vektah/gqlparser/v2/validator" ) func init() { AddRule("UniqueDirectivesPerLocation", func(observers *Events, addError AddErrFunc) { observers.OnDirectiveList(func(walker *Walker, directives []*ast.Directive) { seen := map[string]bool{} for _, dir := range directives { if dir.Name != "repeatable" && seen[dir.Name] { addError( Message(`The directive "@%s" can only be used once at this location.`, dir.Name), At(dir.Position), ) } seen[dir.Name] = true } }) }) } gqlparser-2.5.1/validator/rules/unique_fragment_names.go000066400000000000000000000010351430663104200235370ustar00rootroot00000000000000package validator import ( "github.com/vektah/gqlparser/v2/ast" . "github.com/vektah/gqlparser/v2/validator" ) func init() { AddRule("UniqueFragmentNames", func(observers *Events, addError AddErrFunc) { seenFragments := map[string]bool{} observers.OnFragment(func(walker *Walker, fragment *ast.FragmentDefinition) { if seenFragments[fragment.Name] { addError( Message(`There can be only one fragment named "%s".`, fragment.Name), At(fragment.Position), ) } seenFragments[fragment.Name] = true }) }) } gqlparser-2.5.1/validator/rules/unique_input_field_names.go000066400000000000000000000011251430663104200242360ustar00rootroot00000000000000package validator import ( "github.com/vektah/gqlparser/v2/ast" . "github.com/vektah/gqlparser/v2/validator" ) func init() { AddRule("UniqueInputFieldNames", func(observers *Events, addError AddErrFunc) { observers.OnValue(func(walker *Walker, value *ast.Value) { if value.Kind != ast.ObjectValue { return } seen := map[string]bool{} for _, field := range value.Children { if seen[field.Name] { addError( Message(`There can be only one input field named "%s".`, field.Name), At(field.Position), ) } seen[field.Name] = true } }) }) } gqlparser-2.5.1/validator/rules/unique_operation_names.go000066400000000000000000000010131430663104200237300ustar00rootroot00000000000000package validator import ( "github.com/vektah/gqlparser/v2/ast" . "github.com/vektah/gqlparser/v2/validator" ) func init() { AddRule("UniqueOperationNames", func(observers *Events, addError AddErrFunc) { seen := map[string]bool{} observers.OnOperation(func(walker *Walker, operation *ast.OperationDefinition) { if seen[operation.Name] { addError( Message(`There can be only one operation named "%s".`, operation.Name), At(operation.Position), ) } seen[operation.Name] = true }) }) } gqlparser-2.5.1/validator/rules/unique_variable_names.go000066400000000000000000000011641430663104200235240ustar00rootroot00000000000000package validator import ( "github.com/vektah/gqlparser/v2/ast" . "github.com/vektah/gqlparser/v2/validator" ) func init() { AddRule("UniqueVariableNames", func(observers *Events, addError AddErrFunc) { observers.OnOperation(func(walker *Walker, operation *ast.OperationDefinition) { seen := map[string]int{} for _, def := range operation.VariableDefinitions { // add the same error only once per a variable. if seen[def.Variable] == 1 { addError( Message(`There can be only one variable named "$%s".`, def.Variable), At(def.Position), ) } seen[def.Variable]++ } }) }) } gqlparser-2.5.1/validator/rules/values_of_correct_type.go000066400000000000000000000117551430663104200237420ustar00rootroot00000000000000package validator import ( "errors" "fmt" "strconv" "github.com/vektah/gqlparser/v2/ast" . "github.com/vektah/gqlparser/v2/validator" ) func init() { AddRule("ValuesOfCorrectType", func(observers *Events, addError AddErrFunc) { observers.OnValue(func(walker *Walker, value *ast.Value) { if value.Definition == nil || value.ExpectedType == nil { return } if value.Kind == ast.NullValue && value.ExpectedType.NonNull { addError( Message(`Expected value of type "%s", found %s.`, value.ExpectedType.String(), value.String()), At(value.Position), ) } if value.Definition.Kind == ast.Scalar { // Skip custom validating scalars if !value.Definition.OneOf("Int", "Float", "String", "Boolean", "ID") { return } } var possibleEnums []string if value.Definition.Kind == ast.Enum { for _, val := range value.Definition.EnumValues { possibleEnums = append(possibleEnums, val.Name) } } rawVal, err := value.Value(nil) if err != nil { unexpectedTypeMessage(addError, value) } switch value.Kind { case ast.NullValue: return case ast.ListValue: if value.ExpectedType.Elem == nil { unexpectedTypeMessage(addError, value) return } case ast.IntValue: if !value.Definition.OneOf("Int", "Float", "ID") { unexpectedTypeMessage(addError, value) } case ast.FloatValue: if !value.Definition.OneOf("Float") { unexpectedTypeMessage(addError, value) } case ast.StringValue, ast.BlockValue: if value.Definition.Kind == ast.Enum { rawValStr := fmt.Sprint(rawVal) addError( Message(`Enum "%s" cannot represent non-enum value: %s.`, value.ExpectedType.String(), value.String()), SuggestListQuoted("Did you mean the enum value", rawValStr, possibleEnums), At(value.Position), ) } else if !value.Definition.OneOf("String", "ID") { unexpectedTypeMessage(addError, value) } case ast.EnumValue: if value.Definition.Kind != ast.Enum { rawValStr := fmt.Sprint(rawVal) addError( unexpectedTypeMessageOnly(value), SuggestListUnquoted("Did you mean the enum value", rawValStr, possibleEnums), At(value.Position), ) } else if value.Definition.EnumValues.ForName(value.Raw) == nil { rawValStr := fmt.Sprint(rawVal) addError( Message(`Value "%s" does not exist in "%s" enum.`, value.String(), value.ExpectedType.String()), SuggestListQuoted("Did you mean the enum value", rawValStr, possibleEnums), At(value.Position), ) } case ast.BooleanValue: if !value.Definition.OneOf("Boolean") { unexpectedTypeMessage(addError, value) } case ast.ObjectValue: for _, field := range value.Definition.Fields { if field.Type.NonNull { fieldValue := value.Children.ForName(field.Name) if fieldValue == nil && field.DefaultValue == nil { addError( Message(`Field "%s.%s" of required type "%s" was not provided.`, value.Definition.Name, field.Name, field.Type.String()), At(value.Position), ) continue } } } for _, fieldValue := range value.Children { if value.Definition.Fields.ForName(fieldValue.Name) == nil { var suggestions []string for _, fieldValue := range value.Definition.Fields { suggestions = append(suggestions, fieldValue.Name) } addError( Message(`Field "%s" is not defined by type "%s".`, fieldValue.Name, value.Definition.Name), SuggestListQuoted("Did you mean", fieldValue.Name, suggestions), At(fieldValue.Position), ) } } case ast.Variable: return default: panic(fmt.Errorf("unhandled %T", value)) } }) }) } func unexpectedTypeMessage(addError AddErrFunc, v *ast.Value) { addError( unexpectedTypeMessageOnly(v), At(v.Position), ) } func unexpectedTypeMessageOnly(v *ast.Value) ErrorOption { switch v.ExpectedType.String() { case "Int", "Int!": if _, err := strconv.ParseInt(v.Raw, 10, 32); err != nil && errors.Is(err, strconv.ErrRange) { return Message(`Int cannot represent non 32-bit signed integer value: %s`, v.String()) } return Message(`Int cannot represent non-integer value: %s`, v.String()) case "String", "String!", "[String]": return Message(`String cannot represent a non string value: %s`, v.String()) case "Boolean", "Boolean!": return Message(`Boolean cannot represent a non boolean value: %s`, v.String()) case "Float", "Float!": return Message(`Float cannot represent non numeric value: %s`, v.String()) case "ID", "ID!": return Message(`ID cannot represent a non-string and non-integer value: %s`, v.String()) //case "Enum": // return Message(`Enum "%s" cannot represent non-enum value: %s`, v.ExpectedType.String(), v.String()) default: if v.Definition.Kind == ast.Enum { return Message(`Enum "%s" cannot represent non-enum value: %s.`, v.ExpectedType.String(), v.String()) } return Message(`Expected value of type "%s", found %s.`, v.ExpectedType.String(), v.String()) } } gqlparser-2.5.1/validator/rules/variables_are_input_types.go000066400000000000000000000011721430663104200244270ustar00rootroot00000000000000package validator import ( "github.com/vektah/gqlparser/v2/ast" . "github.com/vektah/gqlparser/v2/validator" ) func init() { AddRule("VariablesAreInputTypes", func(observers *Events, addError AddErrFunc) { observers.OnOperation(func(walker *Walker, operation *ast.OperationDefinition) { for _, def := range operation.VariableDefinitions { if def.Definition == nil { continue } if !def.Definition.IsInputType() { addError( Message( `Variable "$%s" cannot be non-input type "%s".`, def.Variable, def.Type.String(), ), At(def.Position), ) } } }) }) } gqlparser-2.5.1/validator/rules/variables_in_allowed_position.go000066400000000000000000000020241430663104200252530ustar00rootroot00000000000000package validator import ( "github.com/vektah/gqlparser/v2/ast" . "github.com/vektah/gqlparser/v2/validator" ) func init() { AddRule("VariablesInAllowedPosition", func(observers *Events, addError AddErrFunc) { observers.OnValue(func(walker *Walker, value *ast.Value) { if value.Kind != ast.Variable || value.ExpectedType == nil || value.VariableDefinition == nil || walker.CurrentOperation == nil { return } tmp := *value.ExpectedType // todo: move me into walk // If there is a default non nullable types can be null if value.VariableDefinition.DefaultValue != nil && value.VariableDefinition.DefaultValue.Kind != ast.NullValue { if value.ExpectedType.NonNull { tmp.NonNull = false } } if !value.VariableDefinition.Type.IsCompatible(&tmp) { addError( Message( `Variable "%s" of type "%s" used in position expecting type "%s".`, value, value.VariableDefinition.Type.String(), value.ExpectedType.String(), ), At(value.Position), ) } }) }) } gqlparser-2.5.1/validator/schema.go000066400000000000000000000366311430663104200173030ustar00rootroot00000000000000package validator import ( "sort" "strconv" "strings" . "github.com/vektah/gqlparser/v2/ast" "github.com/vektah/gqlparser/v2/gqlerror" "github.com/vektah/gqlparser/v2/parser" ) func LoadSchema(inputs ...*Source) (*Schema, error) { ast, err := parser.ParseSchemas(inputs...) if err != nil { return nil, err } return ValidateSchemaDocument(ast) } func ValidateSchemaDocument(ast *SchemaDocument) (*Schema, error) { schema := Schema{ Types: map[string]*Definition{}, Directives: map[string]*DirectiveDefinition{}, PossibleTypes: map[string][]*Definition{}, Implements: map[string][]*Definition{}, } for i, def := range ast.Definitions { if schema.Types[def.Name] != nil { return nil, gqlerror.ErrorPosf(def.Position, "Cannot redeclare type %s.", def.Name) } schema.Types[def.Name] = ast.Definitions[i] } defs := append(DefinitionList{}, ast.Definitions...) for _, ext := range ast.Extensions { def := schema.Types[ext.Name] if def == nil { schema.Types[ext.Name] = &Definition{ Kind: ext.Kind, Name: ext.Name, Position: ext.Position, } def = schema.Types[ext.Name] defs = append(defs, def) } if def.Kind != ext.Kind { return nil, gqlerror.ErrorPosf(ext.Position, "Cannot extend type %s because the base type is a %s, not %s.", ext.Name, def.Kind, ext.Kind) } def.Directives = append(def.Directives, ext.Directives...) def.Interfaces = append(def.Interfaces, ext.Interfaces...) def.Fields = append(def.Fields, ext.Fields...) def.Types = append(def.Types, ext.Types...) def.EnumValues = append(def.EnumValues, ext.EnumValues...) } for _, def := range defs { switch def.Kind { case Union: for _, t := range def.Types { schema.AddPossibleType(def.Name, schema.Types[t]) schema.AddImplements(t, def) } case InputObject, Object: for _, intf := range def.Interfaces { schema.AddPossibleType(intf, def) schema.AddImplements(def.Name, schema.Types[intf]) } schema.AddPossibleType(def.Name, def) case Interface: for _, intf := range def.Interfaces { schema.AddPossibleType(intf, def) schema.AddImplements(def.Name, schema.Types[intf]) } } } for i, dir := range ast.Directives { if schema.Directives[dir.Name] != nil { // While the spec says SDL must not (§3.5) explicitly define builtin // scalars, it may (§3.13) define builtin directives. Here we check for // that, and reject doubly-defined directives otherwise. switch dir.Name { case "include", "skip", "deprecated", "specifiedBy": // the builtins // In principle here we might want to validate that the // directives are the same. But they might not be, if the // server has an older spec than we do. (Plus, validating this // is a lot of work.) So we just keep the first one we saw. // That's an arbitrary choice, but in theory the only way it // fails is if the server is using features newer than this // version of gqlparser, in which case they're in trouble // anyway. default: return nil, gqlerror.ErrorPosf(dir.Position, "Cannot redeclare directive %s.", dir.Name) } } schema.Directives[dir.Name] = ast.Directives[i] } if len(ast.Schema) > 1 { return nil, gqlerror.ErrorPosf(ast.Schema[1].Position, "Cannot have multiple schema entry points, consider schema extensions instead.") } if len(ast.Schema) == 1 { schema.Description = ast.Schema[0].Description for _, entrypoint := range ast.Schema[0].OperationTypes { def := schema.Types[entrypoint.Type] if def == nil { return nil, gqlerror.ErrorPosf(entrypoint.Position, "Schema root %s refers to a type %s that does not exist.", entrypoint.Operation, entrypoint.Type) } switch entrypoint.Operation { case Query: schema.Query = def case Mutation: schema.Mutation = def case Subscription: schema.Subscription = def } } } for _, ext := range ast.SchemaExtension { for _, entrypoint := range ext.OperationTypes { def := schema.Types[entrypoint.Type] if def == nil { return nil, gqlerror.ErrorPosf(entrypoint.Position, "Schema root %s refers to a type %s that does not exist.", entrypoint.Operation, entrypoint.Type) } switch entrypoint.Operation { case Query: schema.Query = def case Mutation: schema.Mutation = def case Subscription: schema.Subscription = def } } } if err := validateTypeDefinitions(&schema); err != nil { return nil, err } if err := validateDirectiveDefinitions(&schema); err != nil { return nil, err } // Inferred root operation type names should be performed only when a `schema` directive is // **not** provided, when it is, `Mutation` and `Subscription` becomes valid types and are not // assigned as a root operation on the schema. if len(ast.Schema) == 0 { if schema.Query == nil && schema.Types["Query"] != nil { schema.Query = schema.Types["Query"] } if schema.Mutation == nil && schema.Types["Mutation"] != nil { schema.Mutation = schema.Types["Mutation"] } if schema.Subscription == nil && schema.Types["Subscription"] != nil { schema.Subscription = schema.Types["Subscription"] } } if schema.Query != nil { schema.Query.Fields = append( schema.Query.Fields, &FieldDefinition{ Name: "__schema", Type: NonNullNamedType("__Schema", nil), }, &FieldDefinition{ Name: "__type", Type: NamedType("__Type", nil), Arguments: ArgumentDefinitionList{ {Name: "name", Type: NonNullNamedType("String", nil)}, }, }, ) } return &schema, nil } func validateTypeDefinitions(schema *Schema) *gqlerror.Error { types := make([]string, 0, len(schema.Types)) for typ := range schema.Types { types = append(types, typ) } sort.Strings(types) for _, typ := range types { err := validateDefinition(schema, schema.Types[typ]) if err != nil { return err } } return nil } func validateDirectiveDefinitions(schema *Schema) *gqlerror.Error { directives := make([]string, 0, len(schema.Directives)) for directive := range schema.Directives { directives = append(directives, directive) } sort.Strings(directives) for _, directive := range directives { err := validateDirective(schema, schema.Directives[directive]) if err != nil { return err } } return nil } func validateDirective(schema *Schema, def *DirectiveDefinition) *gqlerror.Error { if err := validateName(def.Position, def.Name); err != nil { // now, GraphQL spec doesn't have reserved directive name return err } return validateArgs(schema, def.Arguments, def) } func validateDefinition(schema *Schema, def *Definition) *gqlerror.Error { for _, field := range def.Fields { if err := validateName(field.Position, field.Name); err != nil { // now, GraphQL spec doesn't have reserved field name return err } if err := validateTypeRef(schema, field.Type); err != nil { return err } if err := validateArgs(schema, field.Arguments, nil); err != nil { return err } wantDirLocation := LocationFieldDefinition if def.Kind == InputObject { wantDirLocation = LocationInputFieldDefinition } if err := validateDirectives(schema, field.Directives, wantDirLocation, nil); err != nil { return err } } for _, typ := range def.Types { typDef := schema.Types[typ] if typDef == nil { return gqlerror.ErrorPosf(def.Position, "Undefined type %s.", strconv.Quote(typ)) } if !isValidKind(typDef.Kind, Object) { return gqlerror.ErrorPosf(def.Position, "%s type %s must be %s.", def.Kind, strconv.Quote(typ), kindList(Object)) } } for _, intf := range def.Interfaces { if err := validateImplements(schema, def, intf); err != nil { return err } } switch def.Kind { case Object, Interface: if len(def.Fields) == 0 { return gqlerror.ErrorPosf(def.Position, "%s %s: must define one or more fields.", def.Kind, def.Name) } for _, field := range def.Fields { if typ, ok := schema.Types[field.Type.Name()]; ok { if !isValidKind(typ.Kind, Scalar, Object, Interface, Union, Enum) { return gqlerror.ErrorPosf(field.Position, "%s %s: field must be one of %s.", def.Kind, def.Name, kindList(Scalar, Object, Interface, Union, Enum)) } } } case Enum: if len(def.EnumValues) == 0 { return gqlerror.ErrorPosf(def.Position, "%s %s: must define one or more unique enum values.", def.Kind, def.Name) } for _, value := range def.EnumValues { for _, nonEnum := range [3]string{"true", "false", "null"} { if value.Name == nonEnum { return gqlerror.ErrorPosf(def.Position, "%s %s: non-enum value %s.", def.Kind, def.Name, value.Name) } } } case InputObject: if len(def.Fields) == 0 { return gqlerror.ErrorPosf(def.Position, "%s %s: must define one or more input fields.", def.Kind, def.Name) } for _, field := range def.Fields { if typ, ok := schema.Types[field.Type.Name()]; ok { if !isValidKind(typ.Kind, Scalar, Enum, InputObject) { return gqlerror.ErrorPosf(field.Position, "%s %s: field must be one of %s.", typ.Kind, field.Name, kindList(Scalar, Enum, InputObject)) } } } } for idx, field1 := range def.Fields { for _, field2 := range def.Fields[idx+1:] { if field1.Name == field2.Name { return gqlerror.ErrorPosf(field2.Position, "Field %s.%s can only be defined once.", def.Name, field2.Name) } } } if !def.BuiltIn { // GraphQL spec has reserved type names a lot! err := validateName(def.Position, def.Name) if err != nil { return err } } return validateDirectives(schema, def.Directives, DirectiveLocation(def.Kind), nil) } func validateTypeRef(schema *Schema, typ *Type) *gqlerror.Error { if schema.Types[typ.Name()] == nil { return gqlerror.ErrorPosf(typ.Position, "Undefined type %s.", typ.Name()) } return nil } func validateArgs(schema *Schema, args ArgumentDefinitionList, currentDirective *DirectiveDefinition) *gqlerror.Error { for _, arg := range args { if err := validateName(arg.Position, arg.Name); err != nil { // now, GraphQL spec doesn't have reserved argument name return err } if err := validateTypeRef(schema, arg.Type); err != nil { return err } def := schema.Types[arg.Type.Name()] if !def.IsInputType() { return gqlerror.ErrorPosf( arg.Position, "cannot use %s as argument %s because %s is not a valid input type", arg.Type.String(), arg.Name, def.Kind, ) } if err := validateDirectives(schema, arg.Directives, LocationArgumentDefinition, currentDirective); err != nil { return err } } return nil } func validateDirectives(schema *Schema, dirs DirectiveList, location DirectiveLocation, currentDirective *DirectiveDefinition) *gqlerror.Error { for _, dir := range dirs { if err := validateName(dir.Position, dir.Name); err != nil { // now, GraphQL spec doesn't have reserved directive name return err } if currentDirective != nil && dir.Name == currentDirective.Name { return gqlerror.ErrorPosf(dir.Position, "Directive %s cannot refer to itself.", currentDirective.Name) } if schema.Directives[dir.Name] == nil { return gqlerror.ErrorPosf(dir.Position, "Undefined directive %s.", dir.Name) } validKind := false for _, dirLocation := range schema.Directives[dir.Name].Locations { if dirLocation == location { validKind = true break } } if !validKind { return gqlerror.ErrorPosf(dir.Position, "Directive %s is not applicable on %s.", dir.Name, location) } dir.Definition = schema.Directives[dir.Name] } return nil } func validateImplements(schema *Schema, def *Definition, intfName string) *gqlerror.Error { // see validation rules at the bottom of // https://facebook.github.io/graphql/October2021/#sec-Objects intf := schema.Types[intfName] if intf == nil { return gqlerror.ErrorPosf(def.Position, "Undefined type %s.", strconv.Quote(intfName)) } if intf.Kind != Interface { return gqlerror.ErrorPosf(def.Position, "%s is a non interface type %s.", strconv.Quote(intfName), intf.Kind) } for _, requiredField := range intf.Fields { foundField := def.Fields.ForName(requiredField.Name) if foundField == nil { return gqlerror.ErrorPosf(def.Position, `For %s to implement %s it must have a field called %s.`, def.Name, intf.Name, requiredField.Name, ) } if !isCovariant(schema, requiredField.Type, foundField.Type) { return gqlerror.ErrorPosf(foundField.Position, `For %s to implement %s the field %s must have type %s.`, def.Name, intf.Name, requiredField.Name, requiredField.Type.String(), ) } for _, requiredArg := range requiredField.Arguments { foundArg := foundField.Arguments.ForName(requiredArg.Name) if foundArg == nil { return gqlerror.ErrorPosf(foundField.Position, `For %s to implement %s the field %s must have the same arguments but it is missing %s.`, def.Name, intf.Name, requiredField.Name, requiredArg.Name, ) } if !requiredArg.Type.IsCompatible(foundArg.Type) { return gqlerror.ErrorPosf(foundArg.Position, `For %s to implement %s the field %s must have the same arguments but %s has the wrong type.`, def.Name, intf.Name, requiredField.Name, requiredArg.Name, ) } } for _, foundArgs := range foundField.Arguments { if requiredField.Arguments.ForName(foundArgs.Name) == nil && foundArgs.Type.NonNull && foundArgs.DefaultValue == nil { return gqlerror.ErrorPosf(foundArgs.Position, `For %s to implement %s any additional arguments on %s must be optional or have a default value but %s is required.`, def.Name, intf.Name, foundField.Name, foundArgs.Name, ) } } } return validateTypeImplementsAncestors(schema, def, intfName) } // validateTypeImplementsAncestors // https://github.com/graphql/graphql-js/blob/47bd8c8897c72d3efc17ecb1599a95cee6bac5e8/src/type/validate.ts#L428 func validateTypeImplementsAncestors(schema *Schema, def *Definition, intfName string) *gqlerror.Error { intf := schema.Types[intfName] if intf == nil { return gqlerror.ErrorPosf(def.Position, "Undefined type %s.", strconv.Quote(intfName)) } for _, transitive := range intf.Interfaces { if !containsString(def.Interfaces, transitive) { if transitive == def.Name { return gqlerror.ErrorPosf(def.Position, `Type %s cannot implement %s because it would create a circular reference.`, def.Name, intfName, ) } return gqlerror.ErrorPosf(def.Position, `Type %s must implement %s because it is implemented by %s.`, def.Name, transitive, intfName, ) } } return nil } func containsString(slice []string, want string) bool { for _, str := range slice { if want == str { return true } } return false } func isCovariant(schema *Schema, required *Type, actual *Type) bool { if required.NonNull && !actual.NonNull { return false } if required.NamedType != "" { if required.NamedType == actual.NamedType { return true } for _, pt := range schema.PossibleTypes[required.NamedType] { if pt.Name == actual.NamedType { return true } } return false } if required.Elem != nil && actual.Elem == nil { return false } return isCovariant(schema, required.Elem, actual.Elem) } func validateName(pos *Position, name string) *gqlerror.Error { if strings.HasPrefix(name, "__") { return gqlerror.ErrorPosf(pos, `Name "%s" must not begin with "__", which is reserved by GraphQL introspection.`, name) } return nil } func isValidKind(kind DefinitionKind, valid ...DefinitionKind) bool { for _, k := range valid { if kind == k { return true } } return false } func kindList(kinds ...DefinitionKind) string { s := make([]string, len(kinds)) for i, k := range kinds { s[i] = string(k) } return strings.Join(s, ", ") } gqlparser-2.5.1/validator/schema_test.go000066400000000000000000000075511430663104200203410ustar00rootroot00000000000000package validator import ( "github.com/vektah/gqlparser/v2/gqlerror" "os" "testing" "github.com/stretchr/testify/require" "github.com/vektah/gqlparser/v2/ast" "github.com/vektah/gqlparser/v2/parser/testrunner" ) func TestLoadSchema(t *testing.T) { t.Run("prelude", func(t *testing.T) { s, err := LoadSchema(Prelude) require.Nil(t, err) boolDef := s.Types["Boolean"] require.Equal(t, "Boolean", boolDef.Name) require.Equal(t, ast.Scalar, boolDef.Kind) require.Equal(t, "The `Boolean` scalar type represents `true` or `false`.", boolDef.Description) }) t.Run("swapi", func(t *testing.T) { file, err := os.ReadFile("testdata/swapi.graphql") require.Nil(t, err) s, err := LoadSchema(Prelude, &ast.Source{Input: string(file), Name: "TestLoadSchema"}) require.Nil(t, err) require.Equal(t, "Query", s.Query.Name) require.Equal(t, "hero", s.Query.Fields[0].Name) require.Equal(t, "Human", s.Types["Human"].Name) require.Equal(t, "Subscription", s.Subscription.Name) require.Equal(t, "reviewAdded", s.Subscription.Fields[0].Name) possibleCharacters := s.GetPossibleTypes(s.Types["Character"]) require.Len(t, possibleCharacters, 2) require.Equal(t, "Human", possibleCharacters[0].Name) require.Equal(t, "Droid", possibleCharacters[1].Name) implements := s.GetImplements(s.Types["Droid"]) require.Len(t, implements, 2) require.Equal(t, "Character", implements[0].Name) // interface require.Equal(t, "SearchResult", implements[1].Name) // union }) t.Run("default root operation type names", func(t *testing.T) { file, err := os.ReadFile("testdata/default_root_operation_type_names.graphql") require.Nil(t, err) s, err := LoadSchema(Prelude, &ast.Source{Input: string(file), Name: "TestLoadSchema"}) require.Nil(t, err) require.Nil(t, s.Mutation) require.Nil(t, s.Subscription) require.Equal(t, "Mutation", s.Types["Mutation"].Name) require.Equal(t, "Subscription", s.Types["Subscription"].Name) }) t.Run("type extensions", func(t *testing.T) { file, err := os.ReadFile("testdata/extensions.graphql") require.Nil(t, err) s, err := LoadSchema(Prelude, &ast.Source{Input: string(file), Name: "TestLoadSchema"}) require.Nil(t, err) require.Equal(t, "Subscription", s.Subscription.Name) require.Equal(t, "dogEvents", s.Subscription.Fields[0].Name) require.Equal(t, "owner", s.Types["Dog"].Fields[1].Name) directives := s.Types["Person"].Directives require.Len(t, directives, 2) wantArgs := []string{"sushi", "tempura"} for i, directive := range directives { require.Equal(t, "favorite", directive.Name) require.True(t, directive.Definition.IsRepeatable) for _, arg := range directive.Arguments { require.Equal(t, wantArgs[i], arg.Value.Raw) } } }) t.Run("interfaces", func(t *testing.T) { file, err := os.ReadFile("testdata/interfaces.graphql") require.Nil(t, err) s, err := LoadSchema(Prelude, &ast.Source{Input: string(file), Name: "interfaces"}) require.Nil(t, err) implements := s.GetImplements(s.Types["Canine"]) require.Len(t, implements, 1) require.Equal(t, "Mammal", implements[0].Name) possibleTypes := s.GetPossibleTypes(s.Types["Mammal"]) require.Len(t, possibleTypes, 1) require.Equal(t, "Canine", possibleTypes[0].Name) }) testrunner.Test(t, "./schema_test.yml", func(t *testing.T, input string) testrunner.Spec { _, err := LoadSchema(Prelude, &ast.Source{Input: input}) if err != nil { return testrunner.Spec{ Error: err.(*gqlerror.Error), } } return testrunner.Spec{} }) } func TestSchemaDescription(t *testing.T) { s, err := LoadSchema(Prelude, &ast.Source{Name: "graph/schema.graphqls", Input: ` """ A simple GraphQL schema which is well described. """ schema { query: Query } type Query { entity: String } `, BuiltIn: false}) require.Nil(t, err) want := "A simple GraphQL schema which is well described." require.Equal(t, want, s.Description) } gqlparser-2.5.1/validator/schema_test.yml000066400000000000000000000410401430663104200205240ustar00rootroot00000000000000types: - name: cannot be redeclared input: | type A { name: String } type A { name: String } error: message: "Cannot redeclare type A." locations: [{line: 4, column: 6}] - name: cannot be duplicated field at same definition 1 input: | type A { name: String name: String } error: message: "Field A.name can only be defined once." locations: [{line: 3, column: 3}] - name: cannot be duplicated field at same definition 2 input: | type A { name: String } extend type A { name: String } error: message: "Field A.name can only be defined once." locations: [{line: 5, column: 3}] - name: cannot be duplicated field at same definition 3 input: | type A { name: String } extend type A { age: Int age: Int } error: message: "Field A.age can only be defined once." locations: [{line: 6, column: 3}] object types: - name: must define one or more fields input: | directive @D on OBJECT # This pattern rejected by parser # type InvalidObject1 {} type InvalidObject2 @D type ValidObject { id: ID } extend type ValidObject @D extend type ValidObject { b: Int } error: message: 'OBJECT InvalidObject2: must define one or more fields.' locations: [{line: 6, column: 6}] - name: check reserved names on type name input: | type __FooBar { id: ID } error: message: 'Name "__FooBar" must not begin with "__", which is reserved by GraphQL introspection.' locations: [{line: 1, column: 6}] - name: check reserved names on type field input: | type FooBar { __id: ID } error: message: 'Name "__id" must not begin with "__", which is reserved by GraphQL introspection.' locations: [{line: 2, column: 3}] - name: check reserved names on type field argument input: | type FooBar { foo(__bar: ID): ID } error: message: 'Name "__bar" must not begin with "__", which is reserved by GraphQL introspection.' locations: [{line: 2, column: 7}] - name: must not allow input object as field type input: | input Input { id: ID } type Query { input: Input! } error: message: 'OBJECT Query: field must be one of SCALAR, OBJECT, INTERFACE, UNION, ENUM.' locations: [{line: 5, column: 3}] interfaces: - name: must exist input: | type Thing implements Object { id: ID! } type Query { Things: [Thing!]! } error: message: 'Undefined type "Object".' locations: [{line: 1, column: 6}] - name: must be an interface input: | type Thing implements Object { id: ID! } type Query { Things: [Thing!]! } type Object { name: String } error: message: '"Object" is a non interface type OBJECT.' locations: [{line: 1, column: 6}] - name: must define one or more fields input: | directive @D on INTERFACE # This pattern rejected by parser # interface InvalidInterface1 {} interface InvalidInterface2 @D interface ValidInterface { id: ID } extend interface ValidInterface @D extend interface ValidInterface { b: Int } error: message: 'INTERFACE InvalidInterface2: must define one or more fields.' locations: [{line: 6, column: 11}] - name: check reserved names on type name input: | interface __FooBar { id: ID } error: message: 'Name "__FooBar" must not begin with "__", which is reserved by GraphQL introspection.' locations: [{line: 1, column: 11}] - name: must not allow input object as field type input: | input Input { id: ID } type Query { foo: Foo! } interface Foo { input: Input! } error: message: 'INTERFACE Foo: field must be one of SCALAR, OBJECT, INTERFACE, UNION, ENUM.' locations: [{line: 8, column: 3}] - name: must have all fields from interface input: | type Bar implements BarInterface { someField: Int! } interface BarInterface { id: ID! } error: message: 'For Bar to implement BarInterface it must have a field called id.' locations: [{line: 1, column: 6}] - name: must have same type of fields input: | type Bar implements BarInterface { id: Int! } interface BarInterface { id: ID! } error: message: 'For Bar to implement BarInterface the field id must have type ID!.' locations: [{line: 2, column: 5}] - name: must have all required arguments input: | type Bar implements BarInterface { id: ID! } interface BarInterface { id(ff: Int!): ID! } error: message: 'For Bar to implement BarInterface the field id must have the same arguments but it is missing ff.' locations: [{line: 2, column: 5}] - name: must have same argument types input: | type Bar implements BarInterface { id(ff: ID!): ID! } interface BarInterface { id(ff: Int!): ID! } error: message: 'For Bar to implement BarInterface the field id must have the same arguments but ff has the wrong type.' locations: [{line: 2, column: 8}] - name: may defined additional nullable arguments input: | type Bar implements BarInterface { id(opt: Int): ID! } interface BarInterface { id: ID! } - name: may defined additional required arguments with defaults input: | type Bar implements BarInterface { id(opt: Int! = 1): ID! } interface BarInterface { id: ID! } - name: must not define additional required arguments without defaults input: | type Bar implements BarInterface { id(opt: Int!): ID! } interface BarInterface { id: ID! } error: message: 'For Bar to implement BarInterface any additional arguments on id must be optional or have a default value but opt is required.' locations: [{line: 2, column: 8}] - name: can have covariant argument types input: | union U = A|B type A { name: String } type B { name: String } type Bar implements BarInterface { f: A! } interface BarInterface { f: U! } - name: may define intermediate interfaces input: | interface IA { id: ID! } interface IIA implements IA { id: ID! } type A implements IIA & IA { id: ID! } - name: Type Foo must implement Baz because it is implemented by Bar input: | interface Baz { baz: String } interface Bar implements Baz { bar: String baz: String } type Foo implements Bar { foo: String bar: String baz: String } error: message: 'Type Foo must implement Baz because it is implemented by Bar.' locations: [{line: 10, column: 6}] - name: circular reference error input: | interface Circular1 implements Circular2 { id: ID! } interface Circular2 implements Circular1 { id: ID! } error: message: 'Type Circular1 cannot implement Circular2 because it would create a circular reference.' locations: [{line: 1, column: 11}] inputs: - name: must define one or more input fields input: | directive @D on INPUT_OBJECT # This pattern rejected by parser # input InvalidInput1 {} input InvalidInput2 @D input ValidInput { id: ID } extend input ValidInput @D extend input ValidInput { b: Int } error: message: 'INPUT_OBJECT InvalidInput2: must define one or more input fields.' locations: [{line: 6, column: 7}] - name: check reserved names on type name input: | input __FooBar { id: ID } error: message: 'Name "__FooBar" must not begin with "__", which is reserved by GraphQL introspection.' locations: [{line: 1, column: 7}] - name: fields cannot be Objects input: | type Object { id: ID } input Foo { a: Object! } error: message: 'OBJECT a: field must be one of SCALAR, ENUM, INPUT_OBJECT.' locations: [{line: 2, column: 13}] - name: fields cannot be Interfaces input: | interface Interface { id: ID! } input Foo { a: Interface! } error: message: 'INTERFACE a: field must be one of SCALAR, ENUM, INPUT_OBJECT.' locations: [{line: 2, column: 13}] - name: fields cannot be Unions input: | type Object { id: ID } union Union = Object input Foo { a: Union! } error: message: 'UNION a: field must be one of SCALAR, ENUM, INPUT_OBJECT.' locations: [{line: 3, column: 13}] args: - name: Valid arg types input: | input Input { id: ID } enum Enum { A } scalar Scalar type Query { f(a: Input, b: Scalar, c: Enum): Boolean! } - name: Objects not allowed input: | type Object { id: ID } type Query { f(a: Object): Boolean! } error: message: 'cannot use Object as argument a because OBJECT is not a valid input type' locations: [{line: 2, column: 16}] - name: Union not allowed input: | type Object { id: ID } union Union = Object type Query { f(a: Union): Boolean! } error: message: 'cannot use Union as argument a because UNION is not a valid input type' locations: [{line: 3, column: 16}] - name: Interface not allowed input: | interface Interface { id: ID } type Query { f(a: Interface): Boolean! } error: message: 'cannot use Interface as argument a because INTERFACE is not a valid input type' locations: [{line: 2, column: 16}] enums: - name: must define one or more unique enum values input: | directive @D on ENUM # This pattern rejected by parser # enum InvalidEmum1 {} enum InvalidEnum2 @D enum ValidEnum { FOO } extend enum ValidEnum @D extend enum ValidEnum { BAR } error: message: 'ENUM InvalidEnum2: must define one or more unique enum values.' locations: [{line: 6, column: 6}] - name: check reserved names on type name input: | enum __FooBar { A B } error: message: 'Name "__FooBar" must not begin with "__", which is reserved by GraphQL introspection.' locations: [{line: 1, column: 6}] unions: - name: union types must be defined input: | union Foo = Bar | Baz type Bar { id: ID } error: message: "Undefined type \"Baz\"." locations: [{line: 1, column: 7}] - name: union types must be objects input: | union Foo = Baz interface Baz { id: ID } error: message: "UNION type \"Baz\" must be OBJECT." locations: [{line: 1, column: 7}] - name: unions of pure type extensions are valid input: | type Review { body: String! author: User! @provides(fields: "username") product: Product! } extend type User @key(fields: "id") { id: ID! @external reviews: [Review] } extend type Product @key(fields: "upc") { upc: String! @external reviews: [Review] } union Foo = User | Product scalar _Any scalar _FieldSet directive @external on FIELD_DEFINITION directive @requires(fields: _FieldSet!) on FIELD_DEFINITION directive @provides(fields: _FieldSet!) on FIELD_DEFINITION directive @key(fields: _FieldSet!) on OBJECT | INTERFACE directive @extends on OBJECT type extensions: - name: can extend non existant types input: | extend type A { name: String } - name: cannot extend incorret type existant types input: | scalar A extend type A { name: String } error: message: "Cannot extend type A because the base type is a SCALAR, not OBJECT." locations: [{line: 2, column: 13}] directives: - name: cannot redeclare directives input: | directive @A on FIELD_DEFINITION directive @A on FIELD_DEFINITION error: message: "Cannot redeclare directive A." locations: [{line: 2, column: 12}] - name: can redeclare builtin directives input: | directive @skip(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT directive @skip(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT - name: must be declared input: | type User { name: String @foo } error: message: "Undefined directive foo." locations: [{line: 2, column: 17}] - name: cannot be self-referential input: | directive @A(foo: Int! @A) on FIELD_DEFINITION error: message: "Directive A cannot refer to itself." locations: [{line: 1, column: 25}] - name: check reserved names on type name input: | directive @__A on FIELD_DEFINITION error: message: 'Name "__A" must not begin with "__", which is reserved by GraphQL introspection.' locations: [{line: 1, column: 12}] - name: Valid arg types input: | input Input { id: ID } enum Enum { A } scalar Scalar directive @A(a: Input, b: Scalar, c: Enum) on FIELD_DEFINITION - name: Objects not allowed input: | type Object { id: ID } directive @A(a: Object) on FIELD_DEFINITION error: message: 'cannot use Object as argument a because OBJECT is not a valid input type' locations: [{line: 2, column: 14}] - name: Union not allowed input: | type Object { id: ID } union Union = Object directive @A(a: Union) on FIELD_DEFINITION error: message: 'cannot use Union as argument a because UNION is not a valid input type' locations: [{line: 3, column: 14}] - name: Interface not allowed input: | interface Interface { id: ID } directive @A(a: Interface) on FIELD_DEFINITION error: message: 'cannot use Interface as argument a because INTERFACE is not a valid input type' locations: [{line: 2, column: 14}] - name: Invalid location usage not allowed input: | directive @test on FIELD_DEFINITION input I1 @test { f: String } error: message: 'Directive test is not applicable on INPUT_OBJECT.' locations: [{line: 2, column: 11}] - name: Valid location usage input: | directive @testInputField on INPUT_FIELD_DEFINITION directive @testField on FIELD_DEFINITION directive @inp on INPUT_OBJECT input I1 @inp { f: String @testInputField } type P { name: String @testField } interface I { id: ID @testField } entry points: - name: multiple schema entry points input: | schema { query: Query } schema { query: Query } scalar Query error: message: "Cannot have multiple schema entry points, consider schema extensions instead." locations: [{line: 4, column: 8}] - name: Undefined schema entrypoint input: | schema { query: Query } error: message: "Schema root query refers to a type Query that does not exist." locations: [{line: 2, column: 3}] entry point extensions: - name: Undefined schema entrypoint input: | schema { query: Query } scalar Query extend schema { mutation: Mutation } error: message: "Schema root mutation refers to a type Mutation that does not exist." locations: [{line: 6, column: 3}] type references: - name: Field types input: | type User { posts: Post } error: message: "Undefined type Post." locations: [{line: 2, column: 10}] - name: Arg types input: | type User { posts(foo: FooBar): String } error: message: "Undefined type FooBar." locations: [{line: 2, column: 14}] - name: Directive arg types input: | directive @Foo(foo: FooBar) on FIELD_DEFINITION error: message: "Undefined type FooBar." locations: [{line: 1, column: 21}] - name: Invalid enum value input: | enum Enum { true } error: message: "ENUM Enum: non-enum value true." locations: [{line: 1, column: 6}] gqlparser-2.5.1/validator/spec/000077500000000000000000000000001430663104200164355ustar00rootroot00000000000000gqlparser-2.5.1/validator/spec/FragmentsOnCompositeTypes.spec.yml000066400000000000000000000003541430663104200252460ustar00rootroot00000000000000- name: Undefined type assertions schema: 0 query: | fragment c on Float {...c} errors: - message: Fragment "c" cannot condition on non composite type "Float". - message: Cannot spread fragment "c" within itself. gqlparser-2.5.1/validator/spec/Fuzz.spec.yml000066400000000000000000000013361430663104200210520ustar00rootroot00000000000000- name: 01 schema: 0 query: '{r{__typename(s:0)}}' errors: - message: Cannot query field "r" on type "QueryRoot". - name: 02 - infinit loop occured in OverlappingFieldsCanBeMerged rule schema: | type Query { fieldA: A } type A { s: String } query: | { ...F } fragment F on Query { fieldA { s } ...{ ...{ ...F } fieldA { ...notExists } } } errors: # from KnownFragmentNames rule - message: Unknown fragment "notExists". - message: Unknown fragment "notExists". - message: Unknown fragment "notExists". # from NoFragmentCycles rule - message: Cannot spread fragment "F" within itself. gqlparser-2.5.1/validator/spec/KnownRootTypeRule.spec.yml000066400000000000000000000007401430663104200235440ustar00rootroot00000000000000- name: Known root type rule: KnownRootType schema: 0 query: | query { dog { name } } - name: Valid root type but not in schema rule: KnownRootType schema: 0 query: | mutation { dog { name } } errors: - message: Schema does not support operation type "mutation" - name: Valid root type but schema is entirely empty rule: KnownRootType schema: 20 query: | { dog { name } } errors: - message: Schema does not support operation type "query" gqlparser-2.5.1/validator/spec/NonExistantTypes.spec.yml000066400000000000000000000006531430663104200234140ustar00rootroot00000000000000- name: Undefined type assertions schema: 0 query: | query panic{ panic{ ...PanicInput __typename } } fragment PanicInput on Panic { __typename } errors: - message: Unknown type "Panic". Did you mean "Canine"? locations: - {line: 7, column: 7} - message: Cannot query field "panic" on type "QueryRoot". locations: - {line: 2, column: 14} gqlparser-2.5.1/validator/suggestionList.go000066400000000000000000000034631430663104200210630ustar00rootroot00000000000000package 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) } gqlparser-2.5.1/validator/testdata/000077500000000000000000000000001430663104200173145ustar00rootroot00000000000000gqlparser-2.5.1/validator/testdata/default_root_operation_type_names.graphql000066400000000000000000000002621430663104200276670ustar00rootroot00000000000000schema { query: Query } type Query { mutation: Mutation! subscription: Subscription! } type Mutation { name: String! } type Subscription { name: String! } gqlparser-2.5.1/validator/testdata/extensions.graphql000066400000000000000000000007271430663104200231010ustar00rootroot00000000000000schema { query: Query } extend schema { subscription: Subscription } type Query { dogs: [Dog!]! } type Subscription { dogEvents: [Dog!]! } type Dog { name: String! } type Person @favorite(name: "sushi") @favorite(name: "tempura") { name: String! } directive @favorite(name: String!) repeatable on OBJECT extend type Dog { owner: Person! @permission(permission: "admin") } directive @permission(permission: String!) on FIELD_DEFINITION gqlparser-2.5.1/validator/testdata/interfaces.graphql000066400000000000000000000003251430663104200230170ustar00rootroot00000000000000interface Mammal { mother: Mammal father: Mammal } interface Pet { name(surname: Boolean): String } interface Canine implements Mammal { name(surname: Boolean): String mother: Canine father: Canine }gqlparser-2.5.1/validator/testdata/swapi.graphql000066400000000000000000000105531430663104200220230ustar00rootroot00000000000000schema { query: Query mutation: Mutation subscription: Subscription } # The query type, represents all of the entry points into our object graph type Query { hero(episode: Episode): Character reviews(episode: Episode!): [Review] search(text: String): [SearchResult] character(id: ID!): Character droid(id: ID!): Droid human(id: ID!): Human starship(id: ID!): Starship } # The mutation type, represents all updates we can make to our data type Mutation { createReview(episode: Episode, review: ReviewInput!): Review } # The subscription type, represents all subscriptions we can make to our data type Subscription { reviewAdded(episode: Episode): Review } # The episodes in the Star Wars trilogy enum Episode { # Star Wars Episode IV: A New Hope, released in 1977. NEWHOPE # Star Wars Episode V: The Empire Strikes Back, released in 1980. EMPIRE # Star Wars Episode VI: Return of the Jedi, released in 1983. JEDI } # A character from the Star Wars universe interface Character { # The ID of the character id: ID! # The name of the character name: String! # The friends of the character, or an empty list if they have none friends: [Character] # The friends of the character exposed as a connection with edges friendsConnection(first: Int, after: ID): FriendsConnection! # The movies this character appears in appearsIn: [Episode]! } # Units of height enum LengthUnit { # The standard unit around the world METER # Primarily used in the United States FOOT } # A humanoid creature from the Star Wars universe type Human implements Character { # The ID of the human id: ID! # What this human calls themselves name: String! # The home planet of the human, or null if unknown homePlanet: String # Height in the preferred unit, default is meters height(unit: LengthUnit = METER): Float # Mass in kilograms, or null if unknown mass: Float # This human's friends, or an empty list if they have none friends: [Character] # The friends of the human exposed as a connection with edges friendsConnection(first: Int, after: ID): FriendsConnection! # The movies this human appears in appearsIn: [Episode]! # A list of starships this person has piloted, or an empty list if none starships: [Starship] } # An autonomous mechanical character in the Star Wars universe type Droid implements Character { # The ID of the droid id: ID! # What others call this droid name: String! # This droid's friends, or an empty list if they have none friends: [Character] # The friends of the droid exposed as a connection with edges friendsConnection(first: Int, after: ID): FriendsConnection! # The movies this droid appears in appearsIn: [Episode]! # This droid's primary function primaryFunction: String } # A connection object for a character's friends type FriendsConnection { # The total number of friends totalCount: Int # The edges for each of the character's friends. edges: [FriendsEdge] # A list of the friends, as a convenience when edges are not needed. friends: [Character] # Information for paginating this connection pageInfo: PageInfo! } # An edge object for a character's friends type FriendsEdge { # A cursor used for pagination cursor: ID! # The character represented by this friendship edge node: Character } # Information for paginating this connection type PageInfo { startCursor: ID endCursor: ID hasNextPage: Boolean! } # Represents a review for a movie type Review { # The movie episode: Episode # The number of stars this review gave, 1-5 stars: Int! # Comment about the movie commentary: String } # The input object sent when someone is creating a new review input ReviewInput { # 0-5 stars stars: Int! # Comment about the movie, optional commentary: String # Favorite color, optional favorite_color: ColorInput } # The input object sent when passing in a color input ColorInput { red: Int! green: Int! blue: Int! } type Starship { # The ID of the starship id: ID! # The name of the starship name: String! # Length of the starship, along the longest axis length(unit: LengthUnit = METER): Float coordinates: [[Float!]!] } union SearchResult = Human | Droid | Starshipgqlparser-2.5.1/validator/testdata/vars.graphql000066400000000000000000000014501430663104200216470ustar00rootroot00000000000000type Query { optionalIntArg(i: Int): Boolean! intArg(i: Int!): Boolean! stringArg(i: String): Boolean! boolArg(i: Boolean!): Boolean! floatArg(i: Float!): Boolean! idArg(i: ID!): Boolean! scalarArg(i: Custom!): Boolean! structArg(i: InputType!): Boolean! defaultStructArg(i: InputType! = {name: "foo"}): Boolean! arrayArg(i: [InputType!]): Boolean! intArrayArg(i: [Int]): Boolean! stringArrayArg(i: [String]): Boolean! boolArrayArg(i: [Boolean]): Boolean! typeArrayArg(i: [CustomType]): Boolean! } input InputType { name: String! nullName: String nullEmbedded: Embedded enum: Enum defaultName: String! = "defaultFoo" } input Embedded { name: String! } input CustomType { and: [Int!] } enum Enum { A } scalar Custom gqlparser-2.5.1/validator/validator.go000066400000000000000000000015251430663104200200220ustar00rootroot00000000000000package validator import ( . "github.com/vektah/gqlparser/v2/ast" "github.com/vektah/gqlparser/v2/gqlerror" ) type AddErrFunc func(options ...ErrorOption) type ruleFunc func(observers *Events, addError AddErrFunc) type rule struct { name string rule ruleFunc } var rules []rule // addRule to rule set. // f is called once each time `Validate` is executed. func AddRule(name string, f ruleFunc) { rules = append(rules, rule{name: name, rule: f}) } func Validate(schema *Schema, doc *QueryDocument) gqlerror.List { var errs gqlerror.List observers := &Events{} for i := range rules { rule := rules[i] rule.rule(observers, func(options ...ErrorOption) { err := &gqlerror.Error{ Rule: rule.name, } for _, o := range options { o(err) } errs = append(errs, err) }) } Walk(schema, doc, observers) return errs } gqlparser-2.5.1/validator/validator_test.go000066400000000000000000000056051430663104200210640ustar00rootroot00000000000000package validator_test import ( "testing" "github.com/stretchr/testify/require" "github.com/vektah/gqlparser/v2" "github.com/vektah/gqlparser/v2/ast" "github.com/vektah/gqlparser/v2/parser" "github.com/vektah/gqlparser/v2/validator" ) func TestExtendingNonExistantTypes(t *testing.T) { s := gqlparser.MustLoadSchema( &ast.Source{Name: "graph/schema.graphqls", Input: ` extend type User { id: ID! } extend type Product { upc: String! } union _Entity = Product | User extend type Query { entity: _Entity } `, BuiltIn: false}, ) q, err := parser.ParseQuery(&ast.Source{Name: "ff", Input: `{ entity { ... on User { id } } }`}) require.Nil(t, err) require.Nil(t, validator.Validate(s, q)) } func TestValidationRulesAreIndependent(t *testing.T) { s := gqlparser.MustLoadSchema( &ast.Source{Name: "graph/schema.graphqls", Input: ` extend type Query { myAction(myEnum: Locale!): SomeResult! } type SomeResult { id: String } enum Locale { EN LT DE } `, BuiltIn: false}, ) // Validation as a first call q1, err := parser.ParseQuery(&ast.Source{ Name: "SomeOperation", Input: ` query SomeOperation { # Note: Not providing mandatory parameter: (myEnum: Locale!) myAction { id } } `}) require.Nil(t, err) r1 := validator.Validate(s, q1) require.Len(t, r1, 1) const errorString = `SomeOperation:4: Field "myAction" argument "myEnum" of type "Locale!" is required, but it was not provided.` require.EqualError(t, r1[0], errorString) // Some other call that should not affect validator behavior q2, err := parser.ParseQuery(&ast.Source{ Name: "SomeOperation", Input: ` # Note: there is default enum value in variables query SomeOperation ($locale: Locale! = DE) { myAction(myEnum: $locale) { id } } `}) require.Nil(t, err) require.Nil(t, validator.Validate(s, q2)) // Repeating same query and expecting to still return same validation error require.Len(t, r1, 1) require.EqualError(t, r1[0], errorString) } func TestDeprecatingTypes(t *testing.T) { schema := &ast.Source{ Name: "graph/schema.graphqls", Input: ` type DeprecatedType { deprecatedField: String @deprecated newField(deprecatedArg: Int): Boolean } enum DeprecatedEnum { ALPHA @deprecated } `, BuiltIn: false, } _, err := validator.LoadSchema(append([]*ast.Source{validator.Prelude}, schema)...) require.Nil(t, err) } func TestNoUnusedVariables(t *testing.T) { // https://github.com/99designs/gqlgen/issues/2028 t.Run("gqlgen issues #2028", func(t *testing.T) { s := gqlparser.MustLoadSchema( &ast.Source{Name: "graph/schema.graphqls", Input: ` type Query { bar: String! } `, BuiltIn: false}, ) q, err := parser.ParseQuery(&ast.Source{Name: "2028", Input: ` query Foo($flag: Boolean!) { ...Bar } fragment Bar on Query { bar @include(if: $flag) } `}) require.Nil(t, err) require.Nil(t, validator.Validate(s, q)) }) } gqlparser-2.5.1/validator/vars.go000066400000000000000000000155471430663104200170210ustar00rootroot00000000000000package validator import ( "encoding/json" "fmt" "reflect" "strconv" "strings" "github.com/vektah/gqlparser/v2/ast" "github.com/vektah/gqlparser/v2/gqlerror" ) var UnexpectedType = fmt.Errorf("Unexpected Type") // VariableValues coerces and validates variable values func VariableValues(schema *ast.Schema, op *ast.OperationDefinition, variables map[string]interface{}) (map[string]interface{}, error) { coercedVars := map[string]interface{}{} validator := varValidator{ path: ast.Path{ast.PathName("variable")}, schema: schema, } for _, v := range op.VariableDefinitions { validator.path = append(validator.path, ast.PathName(v.Variable)) if !v.Definition.IsInputType() { return nil, gqlerror.ErrorPathf(validator.path, "must an input type") } val, hasValue := variables[v.Variable] if !hasValue { if v.DefaultValue != nil { var err error val, err = v.DefaultValue.Value(nil) if err != nil { return nil, gqlerror.WrapPath(validator.path, err) } hasValue = true } else if v.Type.NonNull { return nil, gqlerror.ErrorPathf(validator.path, "must be defined") } } if hasValue { if val == nil { if v.Type.NonNull { return nil, gqlerror.ErrorPathf(validator.path, "cannot be null") } coercedVars[v.Variable] = nil } else { rv := reflect.ValueOf(val) jsonNumber, isJsonNumber := val.(json.Number) if isJsonNumber { if v.Type.NamedType == "Int" { n, err := jsonNumber.Int64() if err != nil { return nil, gqlerror.ErrorPathf(validator.path, "cannot use value %d as %s", n, v.Type.NamedType) } rv = reflect.ValueOf(n) } else if v.Type.NamedType == "Float" { f, err := jsonNumber.Float64() if err != nil { return nil, gqlerror.ErrorPathf(validator.path, "cannot use value %f as %s", f, v.Type.NamedType) } rv = reflect.ValueOf(f) } } if rv.Kind() == reflect.Ptr || rv.Kind() == reflect.Interface { rv = rv.Elem() } rval, err := validator.validateVarType(v.Type, rv) if err != nil { return nil, err } coercedVars[v.Variable] = rval.Interface() } } validator.path = validator.path[0 : len(validator.path)-1] } return coercedVars, nil } type varValidator struct { path ast.Path schema *ast.Schema } func (v *varValidator) validateVarType(typ *ast.Type, val reflect.Value) (reflect.Value, *gqlerror.Error) { currentPath := v.path resetPath := func() { v.path = currentPath } defer resetPath() if typ.Elem != nil { if val.Kind() != reflect.Slice { // GraphQL spec says that non-null values should be coerced to an array when possible. // Hence if the value is not a slice, we create a slice and add val to it. slc := reflect.MakeSlice(reflect.SliceOf(val.Type()), 0, 0) slc = reflect.Append(slc, val) val = slc } for i := 0; i < val.Len(); i++ { resetPath() v.path = append(v.path, ast.PathIndex(i)) field := val.Index(i) if field.Kind() == reflect.Ptr || field.Kind() == reflect.Interface { if typ.Elem.NonNull && field.IsNil() { return val, gqlerror.ErrorPathf(v.path, "cannot be null") } field = field.Elem() } _, err := v.validateVarType(typ.Elem, field) if err != nil { return val, err } } return val, nil } def := v.schema.Types[typ.NamedType] if def == nil { panic(fmt.Errorf("missing def for %s", typ.NamedType)) } if !typ.NonNull && !val.IsValid() { // If the type is not null and we got a invalid value namely null/nil, then it's valid return val, nil } switch def.Kind { case ast.Enum: kind := val.Type().Kind() if kind != reflect.Int && kind != reflect.Int32 && kind != reflect.Int64 && kind != reflect.String { return val, gqlerror.ErrorPathf(v.path, "enums must be ints or strings") } isValidEnum := false for _, enumVal := range def.EnumValues { if strings.EqualFold(val.String(), enumVal.Name) { isValidEnum = true } } if !isValidEnum { return val, gqlerror.ErrorPathf(v.path, "%s is not a valid %s", val.String(), def.Name) } return val, nil case ast.Scalar: kind := val.Type().Kind() switch typ.NamedType { case "Int": if kind == reflect.Int || kind == reflect.Int32 || kind == reflect.Int64 || kind == reflect.Float32 || kind == reflect.Float64 || IsValidIntString(val, kind) { return val, nil } case "Float": if kind == reflect.Float32 || kind == reflect.Float64 || kind == reflect.Int || kind == reflect.Int32 || kind == reflect.Int64 || IsValidFloatString(val, kind) { return val, nil } case "String": if kind == reflect.String { return val, nil } case "Boolean": if kind == reflect.Bool { return val, nil } case "ID": if kind == reflect.Int || kind == reflect.Int32 || kind == reflect.Int64 || kind == reflect.String { return val, nil } default: // assume custom scalars are ok return val, nil } return val, gqlerror.ErrorPathf(v.path, "cannot use %s as %s", kind.String(), typ.NamedType) case ast.InputObject: if val.Kind() != reflect.Map { return val, gqlerror.ErrorPathf(v.path, "must be a %s", def.Name) } // check for unknown fields for _, name := range val.MapKeys() { val.MapIndex(name) fieldDef := def.Fields.ForName(name.String()) resetPath() v.path = append(v.path, ast.PathName(name.String())) switch { case name.String() == "__typename": continue case fieldDef == nil: return val, gqlerror.ErrorPathf(v.path, "unknown field") } } for _, fieldDef := range def.Fields { resetPath() v.path = append(v.path, ast.PathName(fieldDef.Name)) field := val.MapIndex(reflect.ValueOf(fieldDef.Name)) if !field.IsValid() { if fieldDef.Type.NonNull { if fieldDef.DefaultValue != nil { var err error _, err = fieldDef.DefaultValue.Value(nil) if err == nil { continue } } return val, gqlerror.ErrorPathf(v.path, "must be defined") } continue } if field.Kind() == reflect.Ptr || field.Kind() == reflect.Interface { if fieldDef.Type.NonNull && field.IsNil() { return val, gqlerror.ErrorPathf(v.path, "cannot be null") } //allow null object field and skip it if !fieldDef.Type.NonNull && field.IsNil() { continue } field = field.Elem() } cval, err := v.validateVarType(fieldDef.Type, field) if err != nil { return val, err } val.SetMapIndex(reflect.ValueOf(fieldDef.Name), cval) } default: panic(fmt.Errorf("unsupported type %s", def.Kind)) } return val, nil } func IsValidIntString(val reflect.Value, kind reflect.Kind) bool { if kind != reflect.String { return false } _, e := strconv.ParseInt(fmt.Sprintf("%v", val.Interface()), 10, 64) return e == nil } func IsValidFloatString(val reflect.Value, kind reflect.Kind) bool { if kind != reflect.String { return false } _, e := strconv.ParseFloat(fmt.Sprintf("%v", val.Interface()), 64) return e == nil } gqlparser-2.5.1/validator/vars_test.go000066400000000000000000000326041430663104200200510ustar00rootroot00000000000000package validator_test import ( "os" "testing" "github.com/stretchr/testify/require" "github.com/vektah/gqlparser/v2" "github.com/vektah/gqlparser/v2/ast" "github.com/vektah/gqlparser/v2/validator" ) func TestValidateVars(t *testing.T) { schema := gqlparser.MustLoadSchema(&ast.Source{ Name: "vars.graphql", Input: mustReadFile("./testdata/vars.graphql"), }) t.Run("undefined variable", func(t *testing.T) { t.Run("without default", func(t *testing.T) { q := gqlparser.MustLoadQuery(schema, `query($id: Int!) { intArg(i: $id) }`) _, gerr := validator.VariableValues(schema, q.Operations.ForName(""), nil) require.EqualError(t, gerr, "input: variable.id must be defined") }) t.Run("nil in required value", func(t *testing.T) { q := gqlparser.MustLoadQuery(schema, `query($id: Int!) { intArg(i: $id) }`) _, gerr := validator.VariableValues(schema, q.Operations.ForName(""), map[string]interface{}{ "id": nil, }) require.EqualError(t, gerr, "input: variable.id cannot be null") }) t.Run("with default", func(t *testing.T) { q := gqlparser.MustLoadQuery(schema, `query($id: Int! = 1) { intArg(i: $id) }`) vars, gerr := validator.VariableValues(schema, q.Operations.ForName(""), nil) require.Nil(t, gerr) require.EqualValues(t, 1, vars["id"]) }) t.Run("with union", func(t *testing.T) { q := gqlparser.MustLoadQuery(schema, `query($id: Int! = 1) { intArg(i: $id) }`) vars, gerr := validator.VariableValues(schema, q.Operations.ForName(""), nil) require.Nil(t, gerr) require.EqualValues(t, 1, vars["id"]) }) }) t.Run("input object", func(t *testing.T) { t.Run("non object", func(t *testing.T) { q := gqlparser.MustLoadQuery(schema, `query foo($var: InputType!) { structArg(i: $var) }`) _, gerr := validator.VariableValues(schema, q.Operations.ForName(""), map[string]interface{}{ "var": "hello", }) require.EqualError(t, gerr, "input: variable.var must be a InputType") }) t.Run("defaults", func(t *testing.T) { q := gqlparser.MustLoadQuery(schema, `query foo($var: InputType! = {name: "foo"}) { structArg(i: $var) }`) vars, gerr := validator.VariableValues(schema, q.Operations.ForName(""), nil) require.Nil(t, gerr) require.EqualValues(t, map[string]interface{}{"name": "foo"}, vars["var"]) }) t.Run("valid value", func(t *testing.T) { q := gqlparser.MustLoadQuery(schema, `query foo($var: InputType!) { structArg(i: $var) }`) vars, gerr := validator.VariableValues(schema, q.Operations.ForName(""), map[string]interface{}{ "var": map[string]interface{}{ "name": "foobar", }, }) require.Nil(t, gerr) require.EqualValues(t, map[string]interface{}{"name": "foobar"}, vars["var"]) }) t.Run("null object field", func(t *testing.T) { q := gqlparser.MustLoadQuery(schema, `query foo($var: InputType!) { structArg(i: $var) }`) vars, gerr := validator.VariableValues(schema, q.Operations.ForName(""), map[string]interface{}{ "var": map[string]interface{}{ "name": "foobar", "nullName": nil, }, }) require.Nil(t, gerr) require.EqualValues(t, map[string]interface{}{"name": "foobar", "nullName": nil}, vars["var"]) }) t.Run("missing required values", func(t *testing.T) { q := gqlparser.MustLoadQuery(schema, `query foo($var: InputType!) { structArg(i: $var) }`) _, gerr := validator.VariableValues(schema, q.Operations.ForName(""), map[string]interface{}{ "var": map[string]interface{}{}, }) require.EqualError(t, gerr, "input: variable.var.name must be defined") }) t.Run("null required field", func(t *testing.T) { q := gqlparser.MustLoadQuery(schema, `query foo($var: InputType!) { structArg(i: $var) }`) _, gerr := validator.VariableValues(schema, q.Operations.ForName(""), map[string]interface{}{ "var": map[string]interface{}{ "name": nil, }, }) require.EqualError(t, gerr, "input: variable.var.name cannot be null") }) t.Run("null embedded input object", func(t *testing.T) { q := gqlparser.MustLoadQuery(schema, `query foo($var: InputType!) { structArg(i: $var) }`) _, gerr := validator.VariableValues(schema, q.Operations.ForName(""), map[string]interface{}{ "var": map[string]interface{}{ "name": "foo", "nullEmbedded": nil, }, }) require.Nil(t, gerr) }) t.Run("unknown field", func(t *testing.T) { q := gqlparser.MustLoadQuery(schema, `query foo($var: InputType!) { structArg(i: $var) }`) _, gerr := validator.VariableValues(schema, q.Operations.ForName(""), map[string]interface{}{ "var": map[string]interface{}{ "name": "foobar", "foobard": true, }, }) require.EqualError(t, gerr, "input: variable.var.foobard unknown field") }) t.Run("unknown __typefield", func(t *testing.T) { q := gqlparser.MustLoadQuery(schema, `query foo($var: InputType!) { structArg(i: $var) }`) vars, gerr := validator.VariableValues(schema, q.Operations.ForName(""), map[string]interface{}{ "var": map[string]interface{}{ "name": "foobar", "__typename": "InputType", }, }) require.Nil(t, gerr) require.EqualValues(t, map[string]interface{}{"__typename": "InputType", "name": "foobar"}, vars["var"]) }) t.Run("enum input object", func(t *testing.T) { q := gqlparser.MustLoadQuery(schema, `query foo($var: InputType!) { structArg(i: $var) }`) _, gerr := validator.VariableValues(schema, q.Operations.ForName(""), map[string]interface{}{ "var": map[string]interface{}{ "name": "foobar", "enum": "A", }, }) require.Nil(t, gerr) }) t.Run("unknown enum value input object", func(t *testing.T) { q := gqlparser.MustLoadQuery(schema, `query foo($var: InputType!) { structArg(i: $var) }`) _, gerr := validator.VariableValues(schema, q.Operations.ForName(""), map[string]interface{}{ "var": map[string]interface{}{ "name": "foobar", "enum": "B", }, }) require.EqualError(t, gerr, "input: variable.var.enum B is not a valid Enum") }) }) t.Run("array", func(t *testing.T) { t.Run("non-null object value should be coerced to an array", func(t *testing.T) { q := gqlparser.MustLoadQuery(schema, `query foo($var: [InputType!]) { arrayArg(i: $var) }`) vars, gerr := validator.VariableValues(schema, q.Operations.ForName(""), map[string]interface{}{ "var": map[string]interface{}{"name": "hello"}, }) require.Nil(t, gerr) require.EqualValues(t, []map[string]interface{}{{"name": "hello"}}, vars["var"]) }) t.Run("non-null int value should be coerced to an array", func(t *testing.T) { q := gqlparser.MustLoadQuery(schema, `query foo($var: [Int!]) { intArrayArg(i: $var) }`) vars, gerr := validator.VariableValues(schema, q.Operations.ForName(""), map[string]interface{}{ "var": 5, }) require.Nil(t, gerr) expected := []int{5} require.EqualValues(t, expected, vars["var"]) }) t.Run("non-null int deep value should be coerced to an array", func(t *testing.T) { q := gqlparser.MustLoadQuery(schema, `query foo($var: [CustomType]) { typeArrayArg(i: $var) }`) vars, gerr := validator.VariableValues(schema, q.Operations.ForName(""), map[string]interface{}{ "var": []map[string]interface{}{{"and": 5}}, }) require.Nil(t, gerr) expected := []map[string]interface{}{{"and": []int{5}}} require.EqualValues(t, expected, vars["var"]) }) t.Run("defaults", func(t *testing.T) { q := gqlparser.MustLoadQuery(schema, `query foo($var: [InputType!] = [{name: "foo"}]) { arrayArg(i: $var) }`) vars, gerr := validator.VariableValues(schema, q.Operations.ForName(""), nil) require.Nil(t, gerr) require.EqualValues(t, []interface{}{map[string]interface{}{ "name": "foo", }}, vars["var"]) }) t.Run("valid value", func(t *testing.T) { q := gqlparser.MustLoadQuery(schema, `query foo($var: [InputType!]) { arrayArg(i: $var) }`) vars, gerr := validator.VariableValues(schema, q.Operations.ForName(""), map[string]interface{}{ "var": []interface{}{map[string]interface{}{ "name": "foo", }}, }) require.Nil(t, gerr) require.EqualValues(t, []interface{}{map[string]interface{}{ "name": "foo", }}, vars["var"]) }) t.Run("null element value", func(t *testing.T) { q := gqlparser.MustLoadQuery(schema, `query foo($var: [InputType!]) { arrayArg(i: $var) }`) _, gerr := validator.VariableValues(schema, q.Operations.ForName(""), map[string]interface{}{ "var": []interface{}{nil}, }) require.EqualError(t, gerr, "input: variable.var[0] cannot be null") }) t.Run("missing required values", func(t *testing.T) { q := gqlparser.MustLoadQuery(schema, `query foo($var: [InputType!]) { arrayArg(i: $var) }`) _, gerr := validator.VariableValues(schema, q.Operations.ForName(""), map[string]interface{}{ "var": []interface{}{map[string]interface{}{}}, }) require.EqualError(t, gerr, "input: variable.var[0].name must be defined") }) t.Run("invalid variable paths", func(t *testing.T) { q := gqlparser.MustLoadQuery(schema, `query foo($var1: InputType!, $var2: InputType!) { a:structArg(i: $var1) b:structArg(i: $var2) }`) _, gerr := validator.VariableValues(schema, q.Operations.ForName(""), map[string]interface{}{ "var1": map[string]interface{}{ "name": "foobar", }, "var2": map[string]interface{}{ "nullName": "foobar", }, }) require.EqualError(t, gerr, "input: variable.var2.name must be defined") }) }) t.Run("Scalars", func(t *testing.T) { t.Run("String -> String", func(t *testing.T) { q := gqlparser.MustLoadQuery(schema, `query foo($var: String!) { stringArg(i: $var) }`) vars, gerr := validator.VariableValues(schema, q.Operations.ForName(""), map[string]interface{}{ "var": "asdf", }) require.Nil(t, gerr) require.EqualValues(t, "asdf", vars["var"]) }) t.Run("Int -> String", func(t *testing.T) { q := gqlparser.MustLoadQuery(schema, `query foo($var: String!) { stringArg(i: $var) }`) _, gerr := validator.VariableValues(schema, q.Operations.ForName(""), map[string]interface{}{ "var": 1, }) require.EqualError(t, gerr, "input: variable.var cannot use int as String") }) t.Run("Nil -> String", func(t *testing.T) { q := gqlparser.MustLoadQuery(schema, `query foo($var: String!) { stringArg(i: $var) }`) _, gerr := validator.VariableValues(schema, q.Operations.ForName(""), map[string]interface{}{ "var": nil, }) require.EqualError(t, gerr, "input: variable.var cannot be null") }) t.Run("Undefined -> String!", func(t *testing.T) { q := gqlparser.MustLoadQuery(schema, `query foo($var: String!) { stringArg(i: $var) }`) _, gerr := validator.VariableValues(schema, q.Operations.ForName(""), nil) require.EqualError(t, gerr, "input: variable.var must be defined") }) t.Run("Undefined -> Int", func(t *testing.T) { q := gqlparser.MustLoadQuery(schema, `query foo($var: Int) { optionalIntArg(i: $var) }`) _, gerr := validator.VariableValues(schema, q.Operations.ForName(""), nil) require.Nil(t, gerr) }) t.Run("Json Number -> Int", func(t *testing.T) { q := gqlparser.MustLoadQuery(schema, `query foo($var: Int) { optionalIntArg(i: $var) }`) vars, gerr := validator.VariableValues(schema, q.Operations.ForName(""), map[string]interface{}{ "var": 10, }) require.Nil(t, gerr) require.Equal(t, 10, vars["var"]) }) t.Run("Json Number -> Float", func(t *testing.T) { q := gqlparser.MustLoadQuery(schema, `query foo($var: Float!) { floatArg(i: $var) }`) vars, gerr := validator.VariableValues(schema, q.Operations.ForName(""), map[string]interface{}{ "var": 10.2, }) require.Nil(t, gerr) require.Equal(t, 10.2, vars["var"]) }) t.Run("Nil -> Int", func(t *testing.T) { q := gqlparser.MustLoadQuery(schema, `query foo($var: Int) { optionalIntArg(i: $var) }`) vars, gerr := validator.VariableValues(schema, q.Operations.ForName(""), map[string]interface{}{ "var": nil, }) require.Nil(t, gerr) require.Equal(t, nil, vars["var"]) }) t.Run("Bool -> Int", func(t *testing.T) { q := gqlparser.MustLoadQuery(schema, `query foo($var: Int!) { intArg(i: $var) }`) _, gerr := validator.VariableValues(schema, q.Operations.ForName(""), map[string]interface{}{ "var": true, }) require.EqualError(t, gerr, "input: variable.var cannot use bool as Int") }) }) t.Run("Int Array", func(t *testing.T) { t.Run("Array with null", func(t *testing.T) { q := gqlparser.MustLoadQuery(schema, `query foo($var: [Int]) { intArrayArg(i: $var) }`) a := 1 b := 2 _, gerr := validator.VariableValues(schema, q.Operations.ForName(""), map[string]interface{}{ "var": []*int{&a, &b, nil}, }) require.Nil(t, gerr) }) }) t.Run("String Array", func(t *testing.T) { t.Run("Array with null", func(t *testing.T) { q := gqlparser.MustLoadQuery(schema, `query foo($var: [String]) { stringArrayArg(i: $var) }`) a := "1" b := "2" _, gerr := validator.VariableValues(schema, q.Operations.ForName(""), map[string]interface{}{ "var": []*string{&a, &b, nil}, }) require.Nil(t, gerr) }) }) t.Run("Boolean Array", func(t *testing.T) { t.Run("Array with null", func(t *testing.T) { q := gqlparser.MustLoadQuery(schema, `query foo($var: [Boolean]) { boolArrayArg(i: $var) }`) a := true b := false _, gerr := validator.VariableValues(schema, q.Operations.ForName(""), map[string]interface{}{ "var": []*bool{&a, &b, nil}, }) require.Nil(t, gerr) }) }) } func mustReadFile(name string) string { src, err := os.ReadFile(name) if err != nil { panic(err) } return string(src) } gqlparser-2.5.1/validator/walk.go000066400000000000000000000173761430663104200170060ustar00rootroot00000000000000package validator import ( "context" "fmt" "github.com/vektah/gqlparser/v2/ast" ) type Events struct { operationVisitor []func(walker *Walker, operation *ast.OperationDefinition) field []func(walker *Walker, field *ast.Field) fragment []func(walker *Walker, fragment *ast.FragmentDefinition) inlineFragment []func(walker *Walker, inlineFragment *ast.InlineFragment) fragmentSpread []func(walker *Walker, fragmentSpread *ast.FragmentSpread) directive []func(walker *Walker, directive *ast.Directive) directiveList []func(walker *Walker, directives []*ast.Directive) value []func(walker *Walker, value *ast.Value) variable []func(walker *Walker, variable *ast.VariableDefinition) } func (o *Events) OnOperation(f func(walker *Walker, operation *ast.OperationDefinition)) { o.operationVisitor = append(o.operationVisitor, f) } func (o *Events) OnField(f func(walker *Walker, field *ast.Field)) { o.field = append(o.field, f) } func (o *Events) OnFragment(f func(walker *Walker, fragment *ast.FragmentDefinition)) { o.fragment = append(o.fragment, f) } func (o *Events) OnInlineFragment(f func(walker *Walker, inlineFragment *ast.InlineFragment)) { o.inlineFragment = append(o.inlineFragment, f) } func (o *Events) OnFragmentSpread(f func(walker *Walker, fragmentSpread *ast.FragmentSpread)) { o.fragmentSpread = append(o.fragmentSpread, f) } func (o *Events) OnDirective(f func(walker *Walker, directive *ast.Directive)) { o.directive = append(o.directive, f) } func (o *Events) OnDirectiveList(f func(walker *Walker, directives []*ast.Directive)) { o.directiveList = append(o.directiveList, f) } func (o *Events) OnValue(f func(walker *Walker, value *ast.Value)) { o.value = append(o.value, f) } func (o *Events) OnVariable(f func(walker *Walker, variable *ast.VariableDefinition)) { o.variable = append(o.variable, f) } func Walk(schema *ast.Schema, document *ast.QueryDocument, observers *Events) { w := Walker{ Observers: observers, Schema: schema, Document: document, } w.walk() } type Walker struct { Context context.Context Observers *Events Schema *ast.Schema Document *ast.QueryDocument validatedFragmentSpreads map[string]bool CurrentOperation *ast.OperationDefinition } func (w *Walker) walk() { for _, child := range w.Document.Operations { w.validatedFragmentSpreads = make(map[string]bool) w.walkOperation(child) } for _, child := range w.Document.Fragments { w.validatedFragmentSpreads = make(map[string]bool) w.walkFragment(child) } } func (w *Walker) walkOperation(operation *ast.OperationDefinition) { w.CurrentOperation = operation for _, varDef := range operation.VariableDefinitions { varDef.Definition = w.Schema.Types[varDef.Type.Name()] for _, v := range w.Observers.variable { v(w, varDef) } if varDef.DefaultValue != nil { varDef.DefaultValue.ExpectedType = varDef.Type varDef.DefaultValue.Definition = w.Schema.Types[varDef.Type.Name()] } } var def *ast.Definition var loc ast.DirectiveLocation switch operation.Operation { case ast.Query, "": def = w.Schema.Query loc = ast.LocationQuery case ast.Mutation: def = w.Schema.Mutation loc = ast.LocationMutation case ast.Subscription: def = w.Schema.Subscription loc = ast.LocationSubscription } for _, varDef := range operation.VariableDefinitions { if varDef.DefaultValue != nil { w.walkValue(varDef.DefaultValue) } w.walkDirectives(varDef.Definition, varDef.Directives, ast.LocationVariableDefinition) } w.walkDirectives(def, operation.Directives, loc) w.walkSelectionSet(def, operation.SelectionSet) for _, v := range w.Observers.operationVisitor { v(w, operation) } w.CurrentOperation = nil } func (w *Walker) walkFragment(it *ast.FragmentDefinition) { def := w.Schema.Types[it.TypeCondition] it.Definition = def w.walkDirectives(def, it.Directives, ast.LocationFragmentDefinition) w.walkSelectionSet(def, it.SelectionSet) for _, v := range w.Observers.fragment { v(w, it) } } func (w *Walker) walkDirectives(parentDef *ast.Definition, directives []*ast.Directive, location ast.DirectiveLocation) { for _, dir := range directives { def := w.Schema.Directives[dir.Name] dir.Definition = def dir.ParentDefinition = parentDef dir.Location = location for _, arg := range dir.Arguments { var argDef *ast.ArgumentDefinition if def != nil { argDef = def.Arguments.ForName(arg.Name) } w.walkArgument(argDef, arg) } for _, v := range w.Observers.directive { v(w, dir) } } for _, v := range w.Observers.directiveList { v(w, directives) } } func (w *Walker) walkValue(value *ast.Value) { if value.Kind == ast.Variable && w.CurrentOperation != nil { value.VariableDefinition = w.CurrentOperation.VariableDefinitions.ForName(value.Raw) if value.VariableDefinition != nil { value.VariableDefinition.Used = true } } if value.Kind == ast.ObjectValue { for _, child := range value.Children { if value.Definition != nil { fieldDef := value.Definition.Fields.ForName(child.Name) if fieldDef != nil { child.Value.ExpectedType = fieldDef.Type child.Value.Definition = w.Schema.Types[fieldDef.Type.Name()] } } w.walkValue(child.Value) } } if value.Kind == ast.ListValue { for _, child := range value.Children { if value.ExpectedType != nil && value.ExpectedType.Elem != nil { child.Value.ExpectedType = value.ExpectedType.Elem child.Value.Definition = value.Definition } w.walkValue(child.Value) } } for _, v := range w.Observers.value { v(w, value) } } func (w *Walker) walkArgument(argDef *ast.ArgumentDefinition, arg *ast.Argument) { if argDef != nil { arg.Value.ExpectedType = argDef.Type arg.Value.Definition = w.Schema.Types[argDef.Type.Name()] } w.walkValue(arg.Value) } func (w *Walker) walkSelectionSet(parentDef *ast.Definition, it ast.SelectionSet) { for _, child := range it { w.walkSelection(parentDef, child) } } func (w *Walker) walkSelection(parentDef *ast.Definition, it ast.Selection) { switch it := it.(type) { case *ast.Field: var def *ast.FieldDefinition if it.Name == "__typename" { def = &ast.FieldDefinition{ Name: "__typename", Type: ast.NamedType("String", nil), } } else if parentDef != nil { def = parentDef.Fields.ForName(it.Name) } it.Definition = def it.ObjectDefinition = parentDef var nextParentDef *ast.Definition if def != nil { nextParentDef = w.Schema.Types[def.Type.Name()] } for _, arg := range it.Arguments { var argDef *ast.ArgumentDefinition if def != nil { argDef = def.Arguments.ForName(arg.Name) } w.walkArgument(argDef, arg) } w.walkDirectives(nextParentDef, it.Directives, ast.LocationField) w.walkSelectionSet(nextParentDef, it.SelectionSet) for _, v := range w.Observers.field { v(w, it) } case *ast.InlineFragment: it.ObjectDefinition = parentDef nextParentDef := parentDef if it.TypeCondition != "" { nextParentDef = w.Schema.Types[it.TypeCondition] } w.walkDirectives(nextParentDef, it.Directives, ast.LocationInlineFragment) w.walkSelectionSet(nextParentDef, it.SelectionSet) for _, v := range w.Observers.inlineFragment { v(w, it) } case *ast.FragmentSpread: def := w.Document.Fragments.ForName(it.Name) it.Definition = def it.ObjectDefinition = parentDef var nextParentDef *ast.Definition if def != nil { nextParentDef = w.Schema.Types[def.TypeCondition] } w.walkDirectives(nextParentDef, it.Directives, ast.LocationFragmentSpread) if def != nil && !w.validatedFragmentSpreads[def.Name] { // prevent inifinite recursion w.validatedFragmentSpreads[def.Name] = true w.walkSelectionSet(nextParentDef, def.SelectionSet) } for _, v := range w.Observers.fragmentSpread { v(w, it) } default: panic(fmt.Errorf("unsupported %T", it)) } } gqlparser-2.5.1/validator/walk_test.go000066400000000000000000000025541430663104200200350ustar00rootroot00000000000000package validator import ( "testing" "github.com/stretchr/testify/require" "github.com/vektah/gqlparser/v2/ast" "github.com/vektah/gqlparser/v2/parser" ) func TestWalker(t *testing.T) { schema, err := LoadSchema(Prelude, &ast.Source{Input: "type Query { name: String }\n schema { query: Query }"}) require.Nil(t, err) query, err := parser.ParseQuery(&ast.Source{Input: "{ as: name }"}) require.Nil(t, err) called := false observers := &Events{} observers.OnField(func(walker *Walker, field *ast.Field) { called = true require.Equal(t, "name", field.Name) require.Equal(t, "as", field.Alias) require.Equal(t, "name", field.Definition.Name) require.Equal(t, "Query", field.ObjectDefinition.Name) }) Walk(schema, query, observers) require.True(t, called) } func TestWalkInlineFragment(t *testing.T) { schema, err := LoadSchema(Prelude, &ast.Source{Input: "type Query { name: String }\n schema { query: Query }"}) require.Nil(t, err) query, err := parser.ParseQuery(&ast.Source{Input: "{ ... { name } }"}) require.Nil(t, err) called := false observers := &Events{} observers.OnField(func(walker *Walker, field *ast.Field) { called = true require.Equal(t, "name", field.Name) require.Equal(t, "name", field.Definition.Name) require.Equal(t, "Query", field.ObjectDefinition.Name) }) Walk(schema, query, observers) require.True(t, called) }