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 }