pagination.go

  1// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
  2
  3package pagination
  4
  5import (
  6	"net/http"
  7	"reflect"
  8
  9	"github.com/openai/openai-go/internal/apijson"
 10	"github.com/openai/openai-go/internal/requestconfig"
 11	"github.com/openai/openai-go/option"
 12	"github.com/openai/openai-go/packages/param"
 13	"github.com/openai/openai-go/packages/respjson"
 14)
 15
 16// aliased to make [param.APIUnion] private when embedding
 17type paramUnion = param.APIUnion
 18
 19// aliased to make [param.APIObject] private when embedding
 20type paramObj = param.APIObject
 21
 22type Page[T any] struct {
 23	Data   []T    `json:"data"`
 24	Object string `json:"object,required"`
 25	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
 26	JSON struct {
 27		Data        respjson.Field
 28		Object      respjson.Field
 29		ExtraFields map[string]respjson.Field
 30		raw         string
 31	} `json:"-"`
 32	cfg *requestconfig.RequestConfig
 33	res *http.Response
 34}
 35
 36// Returns the unmodified JSON received from the API
 37func (r Page[T]) RawJSON() string { return r.JSON.raw }
 38func (r *Page[T]) UnmarshalJSON(data []byte) error {
 39	return apijson.UnmarshalRoot(data, r)
 40}
 41
 42// GetNextPage returns the next page as defined by this pagination style. When
 43// there is no next page, this function will return a 'nil' for the page value, but
 44// will not return an error
 45func (r *Page[T]) GetNextPage() (res *Page[T], err error) {
 46	if len(r.Data) == 0 {
 47		return nil, nil
 48	}
 49	// This page represents a response that isn't actually paginated at the API level
 50	// so there will never be a next page.
 51	cfg := (*requestconfig.RequestConfig)(nil)
 52	if cfg == nil {
 53		return nil, nil
 54	}
 55	var raw *http.Response
 56	cfg.ResponseInto = &raw
 57	cfg.ResponseBodyInto = &res
 58	err = cfg.Execute()
 59	if err != nil {
 60		return nil, err
 61	}
 62	res.SetPageConfig(cfg, raw)
 63	return res, nil
 64}
 65
 66func (r *Page[T]) SetPageConfig(cfg *requestconfig.RequestConfig, res *http.Response) {
 67	if r == nil {
 68		r = &Page[T]{}
 69	}
 70	r.cfg = cfg
 71	r.res = res
 72}
 73
 74type PageAutoPager[T any] struct {
 75	page *Page[T]
 76	cur  T
 77	idx  int
 78	run  int
 79	err  error
 80	paramObj
 81}
 82
 83func NewPageAutoPager[T any](page *Page[T], err error) *PageAutoPager[T] {
 84	return &PageAutoPager[T]{
 85		page: page,
 86		err:  err,
 87	}
 88}
 89
 90func (r *PageAutoPager[T]) Next() bool {
 91	if r.page == nil || len(r.page.Data) == 0 {
 92		return false
 93	}
 94	if r.idx >= len(r.page.Data) {
 95		r.idx = 0
 96		r.page, r.err = r.page.GetNextPage()
 97		if r.err != nil || r.page == nil || len(r.page.Data) == 0 {
 98			return false
 99		}
100	}
101	r.cur = r.page.Data[r.idx]
102	r.run += 1
103	r.idx += 1
104	return true
105}
106
107func (r *PageAutoPager[T]) Current() T {
108	return r.cur
109}
110
111func (r *PageAutoPager[T]) Err() error {
112	return r.err
113}
114
115func (r *PageAutoPager[T]) Index() int {
116	return r.run
117}
118
119type CursorPage[T any] struct {
120	Data    []T  `json:"data"`
121	HasMore bool `json:"has_more"`
122	// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
123	JSON struct {
124		Data        respjson.Field
125		HasMore     respjson.Field
126		ExtraFields map[string]respjson.Field
127		raw         string
128	} `json:"-"`
129	cfg *requestconfig.RequestConfig
130	res *http.Response
131}
132
133// Returns the unmodified JSON received from the API
134func (r CursorPage[T]) RawJSON() string { return r.JSON.raw }
135func (r *CursorPage[T]) UnmarshalJSON(data []byte) error {
136	return apijson.UnmarshalRoot(data, r)
137}
138
139// GetNextPage returns the next page as defined by this pagination style. When
140// there is no next page, this function will return a 'nil' for the page value, but
141// will not return an error
142func (r *CursorPage[T]) GetNextPage() (res *CursorPage[T], err error) {
143	if len(r.Data) == 0 {
144		return nil, nil
145	}
146
147	if r.JSON.HasMore.Valid() && r.HasMore == false {
148		return nil, nil
149	}
150	items := r.Data
151	if items == nil || len(items) == 0 {
152		return nil, nil
153	}
154	cfg := r.cfg.Clone(r.cfg.Context)
155	value := reflect.ValueOf(items[len(items)-1])
156	field := value.FieldByName("ID")
157	err = cfg.Apply(option.WithQuery("after", field.Interface().(string)))
158	if err != nil {
159		return nil, err
160	}
161	var raw *http.Response
162	cfg.ResponseInto = &raw
163	cfg.ResponseBodyInto = &res
164	err = cfg.Execute()
165	if err != nil {
166		return nil, err
167	}
168	res.SetPageConfig(cfg, raw)
169	return res, nil
170}
171
172func (r *CursorPage[T]) SetPageConfig(cfg *requestconfig.RequestConfig, res *http.Response) {
173	if r == nil {
174		r = &CursorPage[T]{}
175	}
176	r.cfg = cfg
177	r.res = res
178}
179
180type CursorPageAutoPager[T any] struct {
181	page *CursorPage[T]
182	cur  T
183	idx  int
184	run  int
185	err  error
186	paramObj
187}
188
189func NewCursorPageAutoPager[T any](page *CursorPage[T], err error) *CursorPageAutoPager[T] {
190	return &CursorPageAutoPager[T]{
191		page: page,
192		err:  err,
193	}
194}
195
196func (r *CursorPageAutoPager[T]) Next() bool {
197	if r.page == nil || len(r.page.Data) == 0 {
198		return false
199	}
200	if r.idx >= len(r.page.Data) {
201		r.idx = 0
202		r.page, r.err = r.page.GetNextPage()
203		if r.err != nil || r.page == nil || len(r.page.Data) == 0 {
204			return false
205		}
206	}
207	r.cur = r.page.Data[r.idx]
208	r.run += 1
209	r.idx += 1
210	return true
211}
212
213func (r *CursorPageAutoPager[T]) Current() T {
214	return r.cur
215}
216
217func (r *CursorPageAutoPager[T]) Err() error {
218	return r.err
219}
220
221func (r *CursorPageAutoPager[T]) Index() int {
222	return r.run
223}