1.1
One lifecycle for remote data
Load, cache, background refresh, live merge — every collection moves through the same shared flow, so feature code stays domain code.
@tilia/query·On top of tilia·MIT
A query-state layer on top of tilia. Reads answer instantly from the cache and refresh in the background; writes apply on the spot and sync quietly. No spinners, no loading walls — and offline comes free.
sève /sɛv/ n., f. — the sap. Moves between root and crown; held through winter, flowing again at thaw.
const claims = make({
id: (claim) => claim.id,
local, // cache tier — answers first
remote, // authoritative — refreshes behind
matches: (q, claim) => claim.status === q.status
})
// live, cached, no spinner
const opened = claims.array({ status: 'open' })
// applies now, syncs quietly
claims.upsert({ ...claim, status: 'closed' })
let claims = TiliaQuery.make({
id: claim => claim.id,
local,
remote,
matches: (q, claim) => claim.status == q.status,
})
// live, cached, no spinner
let opened = claims.array({status: "open"})
// applies now, syncs quietly
claims.upsert({...claim, status: "closed"})
$ npm install @tilia/queryEvery feature ends up reinventing the same remote-data flow: load, cache, refresh, merge, survive offline. @tilia/query makes it one flow.
1.1
Load, cache, background refresh, live merge — every collection moves through the same shared flow, so feature code stays domain code.
1.2
Writes apply instantly and persist to a durable outbox. Close the app offline, reopen it next week — the sync resumes where it left off.
1.3
Results are memoized id lists: a refetch that changes nothing re-renders nothing, and changed objects move between queries in place — no refetch.