@@ -22,15 +22,121 @@ import (
22
22
"github.com/pkg/errors"
23
23
)
24
24
25
- func ParseMutation (mutation string ) (* api.Mutation , error ) {
25
+ // ParseMutation parses a block into a mutation. Returns an object with a mutation or
26
+ // an upsert block with mutation, otherwise returns nil with an error.
27
+ func ParseMutation (mutation string ) (mu * api.Mutation , err error ) {
26
28
lexer := lex .NewLexer (mutation )
27
- lexer .Run (lexInsideMutation )
29
+ lexer .Run (lexIdentifyBlock )
30
+ if err := lexer .ValidateResult (); err != nil {
31
+ return nil , err
32
+ }
33
+
28
34
it := lexer .NewIterator ()
29
- var mu api.Mutation
35
+ if ! it .Next () {
36
+ return nil , errors .Errorf ("Invalid mutation" )
37
+ }
38
+
39
+ item := it .Item ()
40
+ switch item .Typ {
41
+ case itemUpsertBlock :
42
+ if mu , err = ParseUpsertBlock (it ); err != nil {
43
+ return nil , err
44
+ }
45
+ case itemLeftCurl :
46
+ if mu , err = ParseMutationBlock (it ); err != nil {
47
+ return nil , err
48
+ }
49
+ default :
50
+ return nil , errors .Errorf ("Unexpected token: [%s]" , item .Val )
51
+ }
52
+
53
+ // mutations must be enclosed in a single block.
54
+ if it .Next () && it .Item ().Typ != lex .ItemEOF {
55
+ return nil , errors .Errorf ("Unexpected %s after the end of the block" , it .Item ().Val )
56
+ }
57
+
58
+ return mu , nil
59
+ }
30
60
61
+ // ParseUpsertBlock parses the upsert block
62
+ func ParseUpsertBlock (it * lex.ItemIterator ) (* api.Mutation , error ) {
63
+ var mu * api.Mutation
64
+ var queryText string
65
+ var queryFound bool
66
+
67
+ // ===>upsert<=== {...}
31
68
if ! it .Next () {
32
- return nil , errors .New ("Invalid mutation" )
69
+ return nil , errors .Errorf ("Unexpected end of upsert block" )
70
+ }
71
+
72
+ // upsert ===>{<=== ....}
73
+ item := it .Item ()
74
+ if item .Typ != itemLeftCurl {
75
+ return nil , errors .Errorf ("Expected { at the start of block. Got: [%s]" , item .Val )
76
+ }
77
+
78
+ for it .Next () {
79
+ item = it .Item ()
80
+ switch {
81
+ // upsert {... ===>}<===
82
+ case item .Typ == itemRightCurl :
83
+ if mu == nil {
84
+ return nil , errors .Errorf ("Empty mutation block" )
85
+ } else if ! queryFound {
86
+ return nil , errors .Errorf ("Query op not found in upsert block" )
87
+ } else {
88
+ mu .Query = queryText
89
+ return mu , nil
90
+ }
91
+
92
+ // upsert { mutation{...} ===>query<==={...}}
93
+ case item .Typ == itemUpsertBlockOp && item .Val == "query" :
94
+ if queryFound {
95
+ return nil , errors .Errorf ("Multiple query ops inside upsert block" )
96
+ }
97
+ queryFound = true
98
+ if ! it .Next () {
99
+ return nil , errors .Errorf ("Unexpected end of upsert block" )
100
+ }
101
+ item = it .Item ()
102
+ if item .Typ != itemUpsertBlockOpContent {
103
+ return nil , errors .Errorf ("Expecting brace, found '%s'" , item .Val )
104
+ }
105
+ queryText += item .Val
106
+
107
+ // upsert { ===>mutation<=== {...} query{...}}
108
+ case item .Typ == itemUpsertBlockOp && item .Val == "mutation" :
109
+ if ! it .Next () {
110
+ return nil , errors .Errorf ("Unexpected end of upsert block" )
111
+ }
112
+ var err error
113
+ if mu , err = ParseMutationBlock (it ); err != nil {
114
+ return nil , err
115
+ }
116
+
117
+ // upsert { mutation{...} ===>fragment<==={...}}
118
+ case item .Typ == itemUpsertBlockOp && item .Val == "fragment" :
119
+ if ! it .Next () {
120
+ return nil , errors .Errorf ("Unexpected end of upsert block" )
121
+ }
122
+ item = it .Item ()
123
+ if item .Typ != itemUpsertBlockOpContent {
124
+ return nil , errors .Errorf ("Expecting brace, found '%s'" , item .Val )
125
+ }
126
+ queryText += "fragment" + item .Val
127
+
128
+ default :
129
+ return nil , errors .Errorf ("Unexpected token in upsert block [%s]" , item .Val )
130
+ }
33
131
}
132
+
133
+ return nil , errors .Errorf ("Invalid upsert block" )
134
+ }
135
+
136
+ // ParseMutationBlock parses the mutation block
137
+ func ParseMutationBlock (it * lex.ItemIterator ) (* api.Mutation , error ) {
138
+ var mu api.Mutation
139
+
34
140
item := it .Item ()
35
141
if item .Typ != itemLeftCurl {
36
142
return nil , errors .Errorf ("Expected { at the start of block. Got: [%s]" , item .Val )
@@ -42,10 +148,6 @@ func ParseMutation(mutation string) (*api.Mutation, error) {
42
148
continue
43
149
}
44
150
if item .Typ == itemRightCurl {
45
- // mutations must be enclosed in a single block.
46
- if it .Next () && it .Item ().Typ != lex .ItemEOF {
47
- return nil , errors .Errorf ("Unexpected %s after the end of the block." , it .Item ().Val )
48
- }
49
151
return & mu , nil
50
152
}
51
153
if item .Typ == itemMutationOp {
@@ -71,7 +173,7 @@ func parseMutationOp(it *lex.ItemIterator, op string, mu *api.Mutation) error {
71
173
}
72
174
parse = true
73
175
}
74
- if item .Typ == itemMutationContent {
176
+ if item .Typ == itemMutationOpContent {
75
177
if ! parse {
76
178
return errors .Errorf ("Mutation syntax invalid." )
77
179
}
0 commit comments