confetti / confetti/confetti-node

List responses carry no meta.total, so counting requires fetching every record

Open
#38 0 comments 0 reactions 0 assignees View on GitHub

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

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.