Skip to main content
A data source answers queries for a grid. The contract is one interface in tally-core, and the Tally Query Protocol is that interface as JSON over HTTP.

The DataSource interface

custom-source.ts

Capabilities

The grid plans every query against the capabilities. It sends the parts the source supports and runs the rest itself over the rows it received. The source above declares nothing, so it returns every row once and the grid does all the work. A filter that contains a flag is always applied by the grid, since flags are resolved on the client.
Work the grid does locally sees only the loaded page. A source that pages but cannot filter shows the matches within the current page, not across the table.

Requests

A QueryRequest carries the view’s query and the page:
The grid asks for the footer aggregates of the view and for facets of every filterable column whose type has a facet. A cursor page is { cursor?, limit }. The page size defaults to 100 and is set with pageSize on the grid.

Responses

Pagination

With offset, the grid shows one page at a time and grid.setPage(index) moves between pages. With cursor, grid.loadMore() appends the next page until the source returns no cursor. grid.fetchAll(max?) walks every page, up to 100,000 rows by default, for export.

Mutations and live patches

mutate receives the mutations the grid committed and answers { accepted, rows?, errors? }. A rejected mutation is rolled back in the grid. See Mutations and undo. subscribe delivers { upserts?, deletes? } patches. Upserts replace rows with the same key or add new ones, and deletes remove rows by key.

The protocol over HTTP

The Tally Query Protocol puts the same contract on four routes. tally-server and tally/laravel serve it, and connectHttpSource in tally-adapters consumes it. tally-protocol holds the Zod schemas of every body, validation of a request against a schema, the generated JSON Schema files for servers in other languages, and a conformance suite. An adapter is conformant when it returns the same rows, totals, groups, aggregates and facets as the in-memory executor for the fixture dataset, so a filter means the same thing on every backend. Invalid requests are answered with 400 and { code, message, details }, where every detail names the path of a problem.