50 lines
1.1 KiB
Go
50 lines
1.1 KiB
Go
|
|
package bookstack
|
||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"encoding/json"
|
||
|
|
"fmt"
|
||
|
|
"iter"
|
||
|
|
)
|
||
|
|
|
||
|
|
const defaultPageSize = 100
|
||
|
|
|
||
|
|
// listAllResponse is used internally to get both data and total from paginated endpoints.
|
||
|
|
type listAllResponse struct {
|
||
|
|
Data json.RawMessage `json:"data"`
|
||
|
|
Total int `json:"total"`
|
||
|
|
}
|
||
|
|
|
||
|
|
// listAll returns an iterator that paginates through all results for the given path.
|
||
|
|
func listAll[T any](ctx context.Context, c *Client, path string) iter.Seq2[T, error] {
|
||
|
|
return func(yield func(T, error) bool) {
|
||
|
|
offset := 0
|
||
|
|
for {
|
||
|
|
var resp listAllResponse
|
||
|
|
url := fmt.Sprintf("%s?count=%d&offset=%d", path, defaultPageSize, offset)
|
||
|
|
if err := c.do(ctx, "GET", url, nil, &resp); err != nil {
|
||
|
|
var zero T
|
||
|
|
yield(zero, err)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
var items []T
|
||
|
|
if err := json.Unmarshal(resp.Data, &items); err != nil {
|
||
|
|
var zero T
|
||
|
|
yield(zero, fmt.Errorf("unmarshaling page data: %w", err))
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
for _, item := range items {
|
||
|
|
if !yield(item, nil) {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
offset += len(items)
|
||
|
|
if offset >= resp.Total || len(items) == 0 {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|