-
Notifications
You must be signed in to change notification settings - Fork 0
/
operation.go
121 lines (106 loc) · 2.66 KB
/
operation.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package graphql
import (
"errors"
"fmt"
"strings"
)
type OperationType int
const (
Query OperationType = iota // query – a read‐only fetch.
Mutation // mutation – a write followed by a fetch.
Subscription // subscription – a long‐lived request that fetches data in response to source events.
)
func (o OperationType) String() string {
switch o {
case Query:
return "query"
case Mutation:
return "mutation"
case Subscription:
return "subscription"
default:
panic("invalid operation")
}
}
func (o OperationType) MarshalJSON() ([]byte, error) {
switch o {
case Query:
return []byte(`"query"`), nil
case Mutation:
return []byte(`"mutation"`), nil
case Subscription:
return []byte(`"subscription"`), nil
default:
return nil, errors.New("invalid operation")
}
}
type Operation struct {
OperationType OperationType `json:"type"`
Name string `json:"name"` // optional
VariableDefinitions VariableDefinitions `json:"variable_definitions,omitempty"`
Directives Directives `json:"directives,omitempty"`
SelectionSet SelectionSet `json:"selection_set"`
}
func (op *Operation) String() string {
vals := []string{
op.OperationType.String(),
op.Name,
op.VariableDefinitions.String(),
op.Directives.String(),
op.SelectionSet.String(),
}
return strings.Join(vals, " ")
}
func (p *Parser) parseOperation() error {
var err error
// parse an operation
if err = p.skipSpaces(); err != nil {
return err
}
// default value
op := &Operation{OperationType: Query}
if p.isName() {
opName := p.readName()
switch strings.ToLower(opName) {
case "query":
op.OperationType = Query
case "mutation":
op.OperationType = Mutation
case "subscription":
op.OperationType = Subscription
case "fragment":
// go to fragment reading
return p.readFragment()
default:
return fmt.Errorf("invalid operation %s", opName)
}
if p.isName() {
// read actual operation name
op.Name = p.readName()
}
}
if p.cur() == '(' {
op.VariableDefinitions, err = p.parseVariableDefinitions()
if err != nil {
return err
}
}
op.Directives, err = p.parseDirectives()
if err != nil {
return err
}
if p.cur() != '{' {
return fmt.Errorf("invalid operation, unexpected token %c", p.cur())
}
sl, err := p.parseSelectionSet()
if err != nil {
return fmt.Errorf("in %s %s: %w", op.OperationType, op.Name, err)
}
op.SelectionSet = sl
// add operation to p.doc
if _, ok := p.doc.Operations[op.Name]; ok {
return fmt.Errorf("duplicate operation name %s", op.Name)
}
p.doc.Operations[op.Name] = op
return nil
}