@@ -47,61 +47,61 @@ func NewClient(url string, httpClient Doer) *Client {
4747// Query executes a single GraphQL query request,
4848// with a query derived from q, populating the response into it.
4949// q should be a pointer to struct that corresponds to the GraphQL schema.
50- func (c * Client ) Query (ctx context.Context , q interface {} , variables map [string ]interface {} , options ... Option ) error {
50+ func (c * Client ) Query (ctx context.Context , q any , variables map [string ]any , options ... Option ) error {
5151 return c .do (ctx , queryOperation , q , variables , options ... )
5252}
5353
5454// NamedQuery executes a single GraphQL query request, with operation name
5555//
5656// Deprecated: this is the shortcut of Query method, with NewOperationName option
57- func (c * Client ) NamedQuery (ctx context.Context , name string , q interface {} , variables map [string ]interface {} , options ... Option ) error {
57+ func (c * Client ) NamedQuery (ctx context.Context , name string , q any , variables map [string ]any , options ... Option ) error {
5858 return c .do (ctx , queryOperation , q , variables , append (options , OperationName (name ))... )
5959}
6060
6161// Mutate executes a single GraphQL mutation request,
6262// with a mutation derived from m, populating the response into it.
6363// m should be a pointer to struct that corresponds to the GraphQL schema.
64- func (c * Client ) Mutate (ctx context.Context , m interface {} , variables map [string ]interface {} , options ... Option ) error {
64+ func (c * Client ) Mutate (ctx context.Context , m any , variables map [string ]any , options ... Option ) error {
6565 return c .do (ctx , mutationOperation , m , variables , options ... )
6666}
6767
6868// NamedMutate executes a single GraphQL mutation request, with operation name
6969//
7070// Deprecated: this is the shortcut of Mutate method, with NewOperationName option
71- func (c * Client ) NamedMutate (ctx context.Context , name string , m interface {} , variables map [string ]interface {} , options ... Option ) error {
71+ func (c * Client ) NamedMutate (ctx context.Context , name string , m any , variables map [string ]any , options ... Option ) error {
7272 return c .do (ctx , mutationOperation , m , variables , append (options , OperationName (name ))... )
7373}
7474
7575// Query executes a single GraphQL query request,
7676// with a query derived from q, populating the response into it.
7777// q should be a pointer to struct that corresponds to the GraphQL schema.
7878// return raw bytes message.
79- func (c * Client ) QueryRaw (ctx context.Context , q interface {} , variables map [string ]interface {} , options ... Option ) ([]byte , error ) {
79+ func (c * Client ) QueryRaw (ctx context.Context , q any , variables map [string ]any , options ... Option ) ([]byte , error ) {
8080 return c .doRaw (ctx , queryOperation , q , variables , options ... )
8181}
8282
8383// NamedQueryRaw executes a single GraphQL query request, with operation name
8484// return raw bytes message.
85- func (c * Client ) NamedQueryRaw (ctx context.Context , name string , q interface {} , variables map [string ]interface {} , options ... Option ) ([]byte , error ) {
85+ func (c * Client ) NamedQueryRaw (ctx context.Context , name string , q any , variables map [string ]any , options ... Option ) ([]byte , error ) {
8686 return c .doRaw (ctx , queryOperation , q , variables , append (options , OperationName (name ))... )
8787}
8888
8989// MutateRaw executes a single GraphQL mutation request,
9090// with a mutation derived from m, populating the response into it.
9191// m should be a pointer to struct that corresponds to the GraphQL schema.
9292// return raw bytes message.
93- func (c * Client ) MutateRaw (ctx context.Context , m interface {} , variables map [string ]interface {} , options ... Option ) ([]byte , error ) {
93+ func (c * Client ) MutateRaw (ctx context.Context , m any , variables map [string ]any , options ... Option ) ([]byte , error ) {
9494 return c .doRaw (ctx , mutationOperation , m , variables , options ... )
9595}
9696
9797// NamedMutateRaw executes a single GraphQL mutation request, with operation name
9898// return raw bytes message.
99- func (c * Client ) NamedMutateRaw (ctx context.Context , name string , m interface {} , variables map [string ]interface {} , options ... Option ) ([]byte , error ) {
99+ func (c * Client ) NamedMutateRaw (ctx context.Context , name string , m any , variables map [string ]any , options ... Option ) ([]byte , error ) {
100100 return c .doRaw (ctx , mutationOperation , m , variables , append (options , OperationName (name ))... )
101101}
102102
103- // buildAndRequest the common method that builds and send graphql request
104- func (c * Client ) buildAndRequest ( ctx context. Context , op operationType , v interface {} , variables map [string ]interface {} , options ... Option ) ([] byte , * http. Response , io. Reader , Errors ) {
103+ // buildQueryAndOptions the common method to build query and options
104+ func (c * Client ) buildQueryAndOptions ( op operationType , v any , variables map [string ]any , options ... Option ) (string , * constructOptionsOutput , error ) {
105105 var query string
106106 var err error
107107 var optionOutput * constructOptionsOutput
@@ -110,18 +110,18 @@ func (c *Client) buildAndRequest(ctx context.Context, op operationType, v interf
110110 query , optionOutput , err = constructQuery (v , variables , options ... )
111111 case mutationOperation :
112112 query , optionOutput , err = constructMutation (v , variables , options ... )
113+ default :
114+ err = fmt .Errorf ("invalid operation type: %v" , op )
113115 }
114116
115117 if err != nil {
116- return nil , nil , nil , Errors {newError (ErrGraphQLEncode , err )}
118+ return "" , nil , Errors {newError (ErrGraphQLEncode , err )}
117119 }
118-
119- data , _ , resp , respBuf , errs := c .request (ctx , query , variables , optionOutput )
120- return data , resp , respBuf , errs
120+ return query , optionOutput , nil
121121}
122122
123123// Request the common method that send graphql request
124- func (c * Client ) request (ctx context.Context , query string , variables map [string ]interface {} , options * constructOptionsOutput ) ([]byte , []byte , * http.Response , io.Reader , Errors ) {
124+ func (c * Client ) request (ctx context.Context , query string , variables map [string ]any , options * constructOptionsOutput ) ([]byte , []byte , * http.Response , io.Reader , Errors ) {
125125 in := GraphQLRequestPayload {
126126 Query : query ,
127127 Variables : variables ,
@@ -248,35 +248,45 @@ func (c *Client) request(ctx context.Context, query string, variables map[string
248248
249249// do executes a single GraphQL operation.
250250// return raw message and error
251- func (c * Client ) doRaw (ctx context.Context , op operationType , v interface {}, variables map [string ]interface {}, options ... Option ) ([]byte , error ) {
252- data , _ , _ , err := c .buildAndRequest (ctx , op , v , variables , options ... )
253- if len (err ) > 0 {
254- return data , err
251+ func (c * Client ) doRaw (ctx context.Context , op operationType , v any , variables map [string ]any , options ... Option ) ([]byte , error ) {
252+ query , optionsOutput , err := c .buildQueryAndOptions (op , v , variables , options ... )
253+ if err != nil {
254+ return nil , err
255+ }
256+ data , _ , _ , _ , errs := c .request (ctx , query , variables , optionsOutput )
257+ if len (errs ) > 0 {
258+ return data , errs
255259 }
260+
256261 return data , nil
257262}
258263
259264// do executes a single GraphQL operation and unmarshal json.
260- func (c * Client ) do (ctx context.Context , op operationType , v interface {}, variables map [string ]interface {}, options ... Option ) error {
261- data , resp , respBuf , errs := c .buildAndRequest (ctx , op , v , variables , options ... )
262- return c .processResponse (v , data , resp , respBuf , errs )
265+ func (c * Client ) do (ctx context.Context , op operationType , v any , variables map [string ]any , options ... Option ) error {
266+ query , optionsOutput , err := c .buildQueryAndOptions (op , v , variables , options ... )
267+ if err != nil {
268+ return err
269+ }
270+ data , extData , resp , respBuf , errs := c .request (ctx , query , variables , optionsOutput )
271+
272+ return c .processResponse (v , data , optionsOutput .extensions , extData , resp , respBuf , errs )
263273}
264274
265275// Executes a pre-built query and unmarshals the response into v. Unlike the Query method you have to specify in the query the
266276// fields that you want to receive as they are not inferred from v. This method is useful if you need to build the query dynamically.
267- func (c * Client ) Exec (ctx context.Context , query string , v interface {} , variables map [string ]interface {} , options ... Option ) error {
277+ func (c * Client ) Exec (ctx context.Context , query string , v any , variables map [string ]any , options ... Option ) error {
268278 optionsOutput , err := constructOptions (options )
269279 if err != nil {
270280 return err
271281 }
272282
273- data , _ , resp , respBuf , errs := c .request (ctx , query , variables , optionsOutput )
274- return c .processResponse (v , data , resp , respBuf , errs )
283+ data , extData , resp , respBuf , errs := c .request (ctx , query , variables , optionsOutput )
284+ return c .processResponse (v , data , optionsOutput . extensions , extData , resp , respBuf , errs )
275285}
276286
277287// Executes a pre-built query and returns the raw json message. Unlike the Query method you have to specify in the query the
278288// fields that you want to receive as they are not inferred from the interface. This method is useful if you need to build the query dynamically.
279- func (c * Client ) ExecRaw (ctx context.Context , query string , variables map [string ]interface {} , options ... Option ) ([]byte , error ) {
289+ func (c * Client ) ExecRaw (ctx context.Context , query string , variables map [string ]any , options ... Option ) ([]byte , error ) {
280290 optionsOutput , err := constructOptions (options )
281291 if err != nil {
282292 return nil , err
@@ -289,10 +299,10 @@ func (c *Client) ExecRaw(ctx context.Context, query string, variables map[string
289299 return data , nil
290300}
291301
292- // Executes a pre-built query and returns the raw json message and a map with extensions (values also as raw json objects). Unlike the
302+ // ExecRawWithExtensions execute a pre-built query and returns the raw json message and a map with extensions (values also as raw json objects). Unlike the
293303// Query method you have to specify in the query the fields that you want to receive as they are not inferred from the interface. This method
294304// is useful if you need to build the query dynamically.
295- func (c * Client ) ExecRawWithExtensions (ctx context.Context , query string , variables map [string ]interface {} , options ... Option ) ([]byte , []byte , error ) {
305+ func (c * Client ) ExecRawWithExtensions (ctx context.Context , query string , variables map [string ]any , options ... Option ) ([]byte , []byte , error ) {
296306 optionsOutput , err := constructOptions (options )
297307 if err != nil {
298308 return nil , nil , err
@@ -305,7 +315,7 @@ func (c *Client) ExecRawWithExtensions(ctx context.Context, query string, variab
305315 return data , ext , nil
306316}
307317
308- func (c * Client ) processResponse (v interface {} , data []byte , resp * http.Response , respBuf io.Reader , errs Errors ) error {
318+ func (c * Client ) processResponse (v any , data [] byte , extensions any , rawExtensions []byte , resp * http.Response , respBuf io.Reader , errs Errors ) error {
309319 if len (data ) > 0 {
310320 err := jsonutil .UnmarshalGraphQL (data , v )
311321 if err != nil {
@@ -317,6 +327,14 @@ func (c *Client) processResponse(v interface{}, data []byte, resp *http.Response
317327 }
318328 }
319329
330+ if len (rawExtensions ) > 0 && extensions != nil {
331+ err := json .Unmarshal (rawExtensions , extensions )
332+ if err != nil {
333+ we := newError (ErrGraphQLExtensionsDecode , err )
334+ errs = append (errs , we )
335+ }
336+ }
337+
320338 if len (errs ) > 0 {
321339 return errs
322340 }
@@ -352,13 +370,13 @@ func (c *Client) WithDebug(debug bool) *Client {
352370type Errors []Error
353371
354372type Error struct {
355- Message string `json:"message"`
356- Extensions map [string ]interface {} `json:"extensions"`
373+ Message string `json:"message"`
374+ Extensions map [string ]any `json:"extensions"`
357375 Locations []struct {
358376 Line int `json:"line"`
359377 Column int `json:"column"`
360378 } `json:"locations"`
361- Path []interface {} `json:"path"`
379+ Path []any `json:"path"`
362380 err error
363381}
364382
@@ -390,22 +408,22 @@ func (e Errors) Unwrap() []error {
390408 return errs
391409}
392410
393- func (e Error ) getInternalExtension () map [string ]interface {} {
411+ func (e Error ) getInternalExtension () map [string ]any {
394412 if e .Extensions == nil {
395- return make (map [string ]interface {} )
413+ return make (map [string ]any )
396414 }
397415
398416 if ex , ok := e .Extensions ["internal" ]; ok {
399- return ex .(map [string ]interface {} )
417+ return ex .(map [string ]any )
400418 }
401419
402- return make (map [string ]interface {} )
420+ return make (map [string ]any )
403421}
404422
405423func newError (code string , err error ) Error {
406424 return Error {
407425 Message : err .Error (),
408- Extensions : map [string ]interface {} {
426+ Extensions : map [string ]any {
409427 "code" : code ,
410428 },
411429 err : err ,
@@ -435,31 +453,35 @@ func (e Error) withRequest(req *http.Request, bodyReader io.Reader) Error {
435453 if err != nil {
436454 internal ["error" ] = err
437455 } else {
438- internal ["request" ] = map [string ]interface {} {
456+ internal ["request" ] = map [string ]any {
439457 "headers" : req .Header ,
440458 "body" : string (bodyBytes ),
441459 }
442460 }
443461
444462 if e .Extensions == nil {
445- e .Extensions = make (map [string ]interface {} )
463+ e .Extensions = make (map [string ]any )
446464 }
447465 e .Extensions ["internal" ] = internal
448466 return e
449467}
450468
451469func (e Error ) withResponse (res * http.Response , bodyReader io.Reader ) Error {
452470 internal := e .getInternalExtension ()
453- bodyBytes , err := io .ReadAll (bodyReader )
454- if err != nil {
455- internal ["error" ] = err
456- } else {
457- internal ["response" ] = map [string ]interface {}{
458- "headers" : res .Header ,
459- "body" : string (bodyBytes ),
460- }
471+
472+ response := map [string ]any {
473+ "headers" : res .Header ,
461474 }
462475
476+ if bodyReader != nil {
477+ bodyBytes , err := io .ReadAll (bodyReader )
478+ if err != nil {
479+ internal ["error" ] = err
480+ } else {
481+ response ["body" ] = string (bodyBytes )
482+ }
483+ }
484+ internal ["response" ] = response
463485 e .Extensions ["internal" ] = internal
464486 return e
465487}
@@ -470,7 +492,7 @@ func (e Error) withResponse(res *http.Response, bodyReader io.Reader) Error {
470492// The implementation is created on top of the JSON tokenizer available
471493// in "encoding/json".Decoder.
472494// This function is re-exported from the internal package
473- func UnmarshalGraphQL (data []byte , v interface {} ) error {
495+ func UnmarshalGraphQL (data []byte , v any ) error {
474496 return jsonutil .UnmarshalGraphQL (data , v )
475497}
476498
@@ -481,9 +503,10 @@ const (
481503 mutationOperation
482504 // subscriptionOperation // Unused.
483505
484- ErrRequestError = "request_error"
485- ErrJsonEncode = "json_encode_error"
486- ErrJsonDecode = "json_decode_error"
487- ErrGraphQLEncode = "graphql_encode_error"
488- ErrGraphQLDecode = "graphql_decode_error"
506+ ErrRequestError = "request_error"
507+ ErrJsonEncode = "json_encode_error"
508+ ErrJsonDecode = "json_decode_error"
509+ ErrGraphQLEncode = "graphql_encode_error"
510+ ErrGraphQLDecode = "graphql_decode_error"
511+ ErrGraphQLExtensionsDecode = "graphql_extensions_decode_error"
489512)
0 commit comments