feat(bookstack-api-m6n): implement pagination iterator with iter.Seq2
Add generic listAll helper using Go 1.23+ iter.Seq2 for memory-efficient pagination. Implement ListAll() on BooksService and PagesService. Tests cover multi-page iteration, early break, errors, and empty results.
This commit is contained in:
parent
1a26e9035a
commit
6944d50512
6 changed files with 170 additions and 5 deletions
50
iterator.go
Normal file
50
iterator.go
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue