tally-adapters holds client data sources. Each one implements the DataSource contract from tally-core, so the grid works the same over every backend. Data sources compares them; this page covers each one in full.
HTTP
connectHttpSource fetches GET /schema once and returns a schema and a source for any server that speaks the protocol, such as tally-server or tally/laravel. Data sources shows it with useGrid.
When the capabilities are already known,
createHttpSource builds the source without the schema round trip. fetchSchema returns the raw SchemaResponse.
http.ts
HttpSourceError with status, code, message and details from the error body. A body that is not a protocol error gets the code http_error.
The grid’s AbortSignal is passed to fetch, so a superseded query is cancelled on the wire. Live patches arrive over server-sent events. The stream sends the same headers, reconnects on its own and closes when the grid disposes. A server that reports live: false gives a source without subscribe, and a read-only server gives one without mutate.
TanStack Query
createQuerySource wraps any source so its requests go through a QueryClient from @tanstack/query-core. Identical requests are deduped, results are cached by request, and the devtools show every grid query.
query.ts
Queries are keyed
[...queryKey, 'query', request] and the schema [...queryKey, 'schema'].
An accepted mutation or a live patch invalidates every query under the key, so the next request refetches. source.invalidate() does the same by hand, for example after a write made outside the grid.
TanStack DB
createCollectionSource(collection, schema, options?) runs the grid over a TanStack DB collection. Filters, sorts, groups, aggregates and facets execute locally with the reference engine. Collection changes arrive as live patches. Edits go through the collection’s insert, update and delete, so its persistence handlers and optimistic state apply.
db.ts
Any collection works, whatever its sync. Virtual properties the collection adds to items, such as
$hasPendingWrites, are stripped from rows. A mutation resolves when every transaction it started is persisted.
Supabase
createSupabaseSource runs the grid against a Supabase table with no server of your own. Filters, search, sorts and pages compile to PostgREST query strings, edits go through the table API, and Supabase Realtime delivers live patches.
supabase.ts
Text comparisons are case insensitive through
ilike, with wildcards escaped, so % and _ in values match literally. Negation is pushed down to each condition, so empty cells behave like the reference engine.
Writing your own source
A source is an object withcapabilities and query. mutate and subscribe are optional. The contract is in Data sources and protocol.
accounts-source.ts
- Declare only what you do. The grid sends the parts of the view the capabilities allow and runs the rest over the rows it received. This source sorts and pages, so the grid never sends a filter and filters the loaded page itself.
- Honour every field you receive. A request carries only the features you declared. Answer
total,matched,groups,aggregatesandfacetsfor the ones you support. - Respect the signal.
queryreceives anAbortSignalthat fires when a newer query supersedes it. - Return canonical rows.
mutateanswers{ accepted, rows?, errors? }. The grid replaces its rows withrows, and rolls the mutation back whenacceptedisfalse. - Patch by key.
subscribedelivers{ upserts?, deletes? }. Upserts replace the row with the same key or add it.
Passing the conformance suite
runConformance(handler, options) runs every case in tally-protocol against handler and compares each answer with the in-memory executor over conformanceRows. Load those rows into your backend, under conformanceSchema, and resolve relative dates against CONFORMANCE_TODAY. The reference source passes, so the check below exits with 0:
conformance.ts
Offset sources also run the page cases. Cursor sources are walked page by page until the cursor runs out. The report has
passed, results and failures, and every failure lists what differed, by path. Replace the array source with yours and run it in your test suite.