confetti / confetti/confetti-node
List responses carry no meta.total, so counting requires fetching every record
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 0
- Forks
- 0
- Avg merge
- 1h 51m
- Merged PRs (30d)
- 2
Description
What happens
List endpoints return data with no meta block, so there is no way to learn how many records match a filter without fetching them all. Verified against the live API — a /events list response contains no meta.total, meta.totalCount, or meta.count, and no links.next.
The client compounds this: store.sync(body) in src/adapter.ts returns only the flattened record array, so even if the API did send meta, a consumer using the default (non-raw) path could not see it.
Why it matters
Counting is one of the most common things asked of an API, and right now it costs a full fetch. Answering "which upcoming event has the most attending tickets?" against a workspace with 42 events took:
- 1 call to list events
- 42 calls to
/tickets?filter[eventId]=…&filter[status]=attending, each transferring complete ticket records
...to produce 42 integers. With meta.total it would be 42 calls transferring one record each — or, with a cross-event filter, one call.
The cost lands hardest on LLM tooling, where every fetched record is context spent. It also makes truncation ambiguous: with page[size]=25 and 25 records returned, a caller cannot distinguish "exactly 25 exist" from "the first 25 of 300", so any count derived from a list is unreliable unless the caller pages to exhaustion.
Ask
Include a meta block on list responses:
{ "meta": { "total": 137 }, "data": [ /* … */ ] }
JSON:API defines meta for exactly this, and links.next alongside it would let a caller detect more pages without the guesswork.
With total present, page[size]=1 becomes a cheap count, and paging becomes deterministic rather than heuristic.
Consumer note
This is already anticipated downstream: our shaping layer reads meta.total / meta.totalCount / meta.count from the raw body and surfaces it, falling back to a more: "likely" heuristic when the page comes back full. The field is absent purely because the API does not send it — no client change would be needed on our side the day it does.
Related: #37 (array filters) and #34 (the shared store) both come from the same area of adapter.ts.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading src/adapter.ts, especially the store.sync(body) path and how raw and non-raw responses are handled. Trace where list response metadata would need to be produced or exposed, and verify the behavior against a paginated list response. Done means list responses provide meta.total and links.next, while consumers can access the metadata without fetching every record.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- api
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100