diff --git a/graphql.go b/graphql.go index 00f8ded..7fe1ed7 100644 --- a/graphql.go +++ b/graphql.go @@ -104,26 +104,32 @@ func (c *Client) NamedMutateRaw(ctx context.Context, name string, m interface{}, func (c *Client) buildAndRequest(ctx context.Context, op operationType, v interface{}, variables map[string]interface{}, options ...Option) ([]byte, *http.Response, io.Reader, Errors) { var query string var err error + var optionOutput *constructOptionsOutput switch op { case queryOperation: - query, err = ConstructQuery(v, variables, options...) + query, optionOutput, err = constructQuery(v, variables, options...) case mutationOperation: - query, err = ConstructMutation(v, variables, options...) + query, optionOutput, err = constructMutation(v, variables, options...) } if err != nil { return nil, nil, nil, Errors{newError(ErrGraphQLEncode, err)} } - return c.request(ctx, query, variables, options...) + return c.request(ctx, query, variables, optionOutput) } // Request the common method that send graphql request -func (c *Client) request(ctx context.Context, query string, variables map[string]interface{}, options ...Option) ([]byte, *http.Response, io.Reader, Errors) { +func (c *Client) request(ctx context.Context, query string, variables map[string]interface{}, options *constructOptionsOutput) ([]byte, *http.Response, io.Reader, Errors) { in := GraphQLRequestPayload{ Query: query, Variables: variables, } + + if options != nil { + in.OperationName = options.operationName + } + var buf bytes.Buffer err := json.NewEncoder(&buf).Encode(in) if err != nil { @@ -249,14 +255,24 @@ func (c *Client) do(ctx context.Context, op operationType, v interface{}, variab // Executes a pre-built query and unmarshals the response into v. Unlike the Query method you have to specify in the query the // 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. func (c *Client) Exec(ctx context.Context, query string, v interface{}, variables map[string]interface{}, options ...Option) error { - data, resp, respBuf, errs := c.request(ctx, query, variables, options...) + optionsOutput, err := constructOptions(options) + if err != nil { + return err + } + + data, resp, respBuf, errs := c.request(ctx, query, variables, optionsOutput) return c.processResponse(v, data, resp, respBuf, errs) } // Executes a pre-built query and returns the raw json message. Unlike the 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 is useful if you need to build the query dynamically. func (c *Client) ExecRaw(ctx context.Context, query string, variables map[string]interface{}, options ...Option) ([]byte, error) { - data, _, _, errs := c.request(ctx, query, variables, options...) + optionsOutput, err := constructOptions(options) + if err != nil { + return nil, err + } + + data, _, _, errs := c.request(ctx, query, variables, optionsOutput) if len(errs) > 0 { return data, errs } diff --git a/query.go b/query.go index 65748b0..1ee9d7c 100644 --- a/query.go +++ b/query.go @@ -43,48 +43,68 @@ func constructOptions(options []Option) (*constructOptionsOutput, error) { return output, nil } -// ConstructQuery build GraphQL query string from struct and variables -func ConstructQuery(v interface{}, variables map[string]interface{}, options ...Option) (string, error) { +func constructQuery(v interface{}, variables map[string]interface{}, options ...Option) (string, *constructOptionsOutput, error) { query, err := query(v) if err != nil { - return "", err + return "", nil, err } optionsOutput, err := constructOptions(options) if err != nil { - return "", err + return "", nil, err } if len(variables) > 0 { - return fmt.Sprintf("query %s(%s)%s%s", optionsOutput.operationName, queryArguments(variables), optionsOutput.OperationDirectivesString(), query), nil + return fmt.Sprintf("query %s(%s)%s%s", optionsOutput.operationName, queryArguments(variables), optionsOutput.OperationDirectivesString(), query), optionsOutput, nil } if optionsOutput.operationName == "" && len(optionsOutput.operationDirectives) == 0 { - return query, nil + return query, optionsOutput, nil } - return fmt.Sprintf("query %s%s%s", optionsOutput.operationName, optionsOutput.OperationDirectivesString(), query), nil + return fmt.Sprintf("query %s%s%s", optionsOutput.operationName, optionsOutput.OperationDirectivesString(), query), optionsOutput, nil } -// ConstructQuery build GraphQL mutation string from struct and variables -func ConstructMutation(v interface{}, variables map[string]interface{}, options ...Option) (string, error) { - query, err := query(v) +// ConstructQuery build GraphQL query string from struct and variables +func ConstructQuery(v interface{}, variables map[string]interface{}, options ...Option) (string, error) { + query, _, err := constructQuery(v, variables, options...) if err != nil { return "", err } + + return query, err +} + +func constructMutation(v interface{}, variables map[string]interface{}, options ...Option) (string, *constructOptionsOutput, error) { + query, err := query(v) + if err != nil { + return "", nil, err + } + optionsOutput, err := constructOptions(options) if err != nil { - return "", err + return "", nil, err } + if len(variables) > 0 { - return fmt.Sprintf("mutation %s(%s)%s%s", optionsOutput.operationName, queryArguments(variables), optionsOutput.OperationDirectivesString(), query), nil + return fmt.Sprintf("mutation %s(%s)%s%s", optionsOutput.operationName, queryArguments(variables), optionsOutput.OperationDirectivesString(), query), optionsOutput, nil } if optionsOutput.operationName == "" && len(optionsOutput.operationDirectives) == 0 { - return "mutation" + query, nil + return "mutation" + query, optionsOutput, nil + } + + return fmt.Sprintf("mutation %s%s%s", optionsOutput.operationName, optionsOutput.OperationDirectivesString(), query), optionsOutput, nil +} + +// ConstructMutation build GraphQL mutation string from struct and variables +func ConstructMutation(v interface{}, variables map[string]interface{}, options ...Option) (string, error) { + query, _, err := constructMutation(v, variables, options...) + if err != nil { + return "", err } - return fmt.Sprintf("mutation %s%s%s", optionsOutput.operationName, optionsOutput.OperationDirectivesString(), query), nil + return query, err } // ConstructSubscription build GraphQL subscription string from struct and variables