Before this, only `release list` walked pages. `repo list`, `pr list` (the
non-filter branch), and `issue list` all passed `PageSize: limit` directly
to the gitea SDK — which silently caps PageSize at 50, so any request for
more than 50 results was truncated to 50 with no warning. `--limit` was
effectively a per-page hint, not a real limit.
## Changes
- New `cmd/paginate.go` — generic `paginateGitea[T any]` that walks pages
until the response is short or the limit is reached. Uses Go 1.20
generics so each list command keeps its existing typed slice without
conversion overhead.
- `repo list` — paginates ListUserRepos.
- `pr list` — paginates ListRepoPullRequests in both branches:
- With client-side filters (assignee, author, labels, search, draft,
head, base): pull all pages then filter+limit.
- Without filters: paginate up to limit.
- `issue list` — paginates ListRepoIssues. Overshoots 2x because the API
returns both issues AND PRs and we filter PRs out client-side; the
overshoot keeps us bounded but reduces the chance of returning fewer
results than `--limit`.
## `fj api --paginate`
Mirrors `gh api --paginate`:
- Follows RFC 5988 `Link: rel="next"` headers (Forgejo emits these on
list endpoints).
- Concatenates each page's JSON array into a single array via
`concatPaginatedJSON`. If a page is not a JSON array, errors with a
clear message — `--paginate` only makes sense for paginatable endpoints.
- GET-only (errors on POST/PUT/DELETE).
- Reuses the same auth and custom headers across pages; the body-size
limit applies per-page.
Refactored the request execution into a `doOnce` closure so the loop body
isn't a copy of the single-request path.
Verified live:
$ fj api 'repos/public/claude-code-proxy/commits?limit=2' \
--paginate --jq '. | length'
44
(44 = total commits in the repo, walked via Link headers from a 2-per-page
starting query.)
Out of scope for this commit, deferred:
- De-duplicating cmd/aliases.go ↔ cmd/actions.go subtrees (the type
mismatch they caused is already fixed in the prior commit; the
duplication itself is polish).