mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 20:42:43 +00:00
Twelve routes answer a capped list with meta.truncated / meta.limit on the envelope, and the web client read only data, so no surface said a list had stopped short. apiGetList / apiPostList are now the one client reader of the cap and ListCapNotice the one line that shows it; every capped list on the web reads its cap and shows the notice under the list, the paged readers (side effects, illness episodes) stop on the route's answer instead of a full-page guess, and the ECG list moves its five readers onto one hook. The record activity feed sent its cap twice, in data and on the envelope; it rides the envelope alone now. A guard derives the capped routes from the tree and binds each to a client that reads its cap.
23 lines
869 B
TypeScript
23 lines
869 B
TypeScript
/**
|
|
* The wire shape of a list cap, safe for the client bundle.
|
|
*
|
|
* A capped list answers with `meta: { truncated, limit }` on the envelope
|
|
* (`apiListSuccess` in `./list-cap.ts`). That is the one place the signal
|
|
* rides; `readListCap` is the one place a client reads it.
|
|
*/
|
|
export interface ListCap {
|
|
/** A row past `limit` exists and was not returned. */
|
|
truncated: boolean;
|
|
/** The most rows this response could carry. */
|
|
limit: number;
|
|
}
|
|
|
|
/** The cap an envelope's `meta` carries, or null when it carries none. */
|
|
export function readListCap(meta: unknown): ListCap | null {
|
|
if (!meta || typeof meta !== "object") return null;
|
|
const { truncated, limit } = meta as Record<string, unknown>;
|
|
if (typeof truncated !== "boolean") return null;
|
|
if (typeof limit !== "number" || !Number.isFinite(limit)) return null;
|
|
return { truncated, limit };
|
|
}
|