sorare/graphql/query.go

101 lines
2.3 KiB
Go

package graphql
import (
"context"
"fmt"
"reflect"
"strings"
"github.com/pkg/errors"
)
type Query[ReturnType any, Params any] struct {
c *Client
gqltype string
containerLayers []string
additionalPayloadParams map[string]interface{}
additionalQueryParams map[string]interface{}
maxPageSize int
}
func NewQuery[ReturnType any, Params any](
c *Client,
gqlType string,
containerLayers []string,
) *Query[ReturnType, Params] {
return &Query[ReturnType, Params]{
c: c,
gqltype: gqlType,
containerLayers: containerLayers,
additionalPayloadParams: make(map[string]interface{}),
additionalQueryParams: make(map[string]interface{}),
maxPageSize: 0,
}
}
func (r *Query[ReturnType, Params]) WithPayloadParam(
name string,
value interface{},
) *Query[ReturnType, Params] {
r.additionalPayloadParams[name] = value
return r
}
func (r *Query[ReturnType, Params]) WithQueryParam(
name string,
value interface{},
) *Query[ReturnType, Params] {
r.additionalQueryParams[name] = value
return r
}
func (r *Query[ReturnType, Params]) WithMaxPageSize(maxPageSize int) *Query[ReturnType, Params] {
r.maxPageSize = maxPageSize
return r
}
func (r *Query[ReturnType, Params]) GetPageSize() int {
t := reflect.TypeOf((*ReturnType)(nil)).Elem()
if t.Kind() == reflect.Slice {
t = t.Elem()
}
complexity := GetTypeComplexity(t)
maxComplexity := r.c.MaxQueryComplexity()
layers := len(r.containerLayers)
computedPageSize := (maxComplexity - layers - 1) / complexity
if r.maxPageSize > 0 && r.maxPageSize < computedPageSize {
return r.maxPageSize
}
return computedPageSize
}
func (r *Query[ReturnType, Params]) Get(ctx context.Context, params Params) (ReturnType, error) {
paramsMap := convertParamsToMap(params)
for k, v := range r.additionalPayloadParams {
paramsMap[k] = v
}
gqltype := r.gqltype
if len(paramsMap) > 0 {
keys := make([]string, 0, len(paramsMap))
for k := range paramsMap {
keys = append(keys, fmt.Sprintf("%s:$%s", k, k))
}
gqltype = fmt.Sprintf("%s(%s)", gqltype, strings.Join(keys, ","))
}
for k, v := range r.additionalQueryParams {
paramsMap[k] = v
}
q := NewPayload[ReturnType](gqltype, r.containerLayers...)
err := r.c.Query(ctx, q, paramsMap)
if err != nil {
var res ReturnType
return res, errors.Wrap(err, "querying records")
}
return q.GetValue(), nil
}