Table read functions and query options
View as MarkdownIdentity
Section titled “Identity”Table query builders are exported from @sapporta/frontend/table/query and from
the main @sapporta/frontend entry point. They compose the generated table HTTP
client with TanStack Query.
New Sapporta projects install @tanstack/react-query.
packages/frontend/src/query-client.ts exports one application QueryClient,
and main.tsx mounts it with QueryClientProvider. A feature
should reuse that provider and the public table query builders.
Read functions
Section titled “Read functions”import { fetchTableRow, fetchTableRows } from "@sapporta/frontend";
await fetchTableRow(tableName, recordId, { signal });await fetchTableRows( { tableName, page, limit, sort, filters, search }, { signal },);fetchTableRow() returns SingleRow. fetchTableRows() returns
PaginatedRows. Both functions call the generated, auth-aware table routes.
Their optional AbortSignal reaches the underlying fetch request.
Selection and page serializers
Section titled “Selection and page serializers”buildTableSelectionQuery() serializes the filter, sort, and search state
shared by paged reads and CSV exports. buildTableRowsQuery() starts with that
selection and adds page and limit:
import { buildTableRowsQuery, buildTableSelectionQuery,} from "@sapporta/frontend";
const selection = buildTableSelectionQuery({ filters, sort, search,});
const pageQuery = buildTableRowsQuery({ filters, sort, search, page: 2, limit: 25,});Both functions return QueryParamRecord from @sapporta/shared. Ordinary keys
remain strings, including the wire forms of numeric page and limit values. When
two typed conditions encode to the same filter key, that key becomes an ordered
string array. The typed client turns the array back into repeated URL keys, so a
pair such as title contains launch and title contains checklist reaches the
server as two AND predicates rather than one last-value-wins object property.
Page query keys use this same lossless serialized request shape. UI-only filter IDs do not create distinct cache entries for the same HTTP query, while repeated conditions remain distinct in the key.
fetchTableRow() and fetchTableRows() remain supported low-level primitives.
Use them when a non-React caller owns the request lifecycle directly. A React
feature screen normally composes the option builders below with useQuery() so
it shares cache keys, cancellation, and server state with the rest of the
application.
Query option builders
Section titled “Query option builders”import { useQuery } from "@tanstack/react-query";import { tableRecordQueryOptions, tableRecordsPageQueryOptions,} from "@sapporta/frontend/table/query";
const record = useQuery( tableRecordQueryOptions({ tableName: "tasks", recordId: String(taskId), decodeRow: decodeTask, }),);
const page = useQuery( tableRecordsPageQueryOptions({ tableName: "tasks", page: 1, limit: 50, filters, sort, search, decodeRow: decodeTask, }),);tableRecordQueryOptions() returns query options for one generated table
record. tableRecordsPageQueryOptions() returns options for one serialized
table query and preserves the response pagination metadata.
Without decodeRow, both builders return generic Row values. Supplying
decodeRow(row) changes the inferred query data to the application row type.
Each page row is decoded independently. Decoder failures reject the query.
Sapporta does not infer an application domain type from a generic table
response; the application declares it as a
row projection.
The page decoder uses ordinary array mapping, so one thrown decoder error fails
the whole query rather than publishing a shorter page. Partial results require a
separate wire contract and visible diagnostics.
Both query functions consume TanStack Query’s request signal. When TanStack Query aborts that signal, the generated table request receives the abort.
Exported types
Section titled “Exported types”TableRecordQueryArgscontainstableNameand stringrecordId.DecodedTableRecordQueryArgs<TRow>addsdecodeRow.DecodedTableRecordsPageQueryArgs<TRow>addsdecodeRowtoFetchTableRowsParams.TableRowDecoder<TRow>is(row: Row) => TRow.TableRecordsPage<TRow>preservesPaginatedRows.metaand replacesdatawithTRow[].TableRecordQueryKeyandTableRecordsPageQueryKeyare the inferred key tuple types returned by the matchingtableQueryKeysfunctions.TableFetchOptionsis the public{ signal?: AbortSignal }option accepted byfetchTableRow()andfetchTableRows().
The decoded overloads require decodeRow. Supplying a domain row generic
without a decoder is a type error.