Skip to main content

DomainTableClient<TRow, TInsert, TColumn, TExpand, TUpdate>

Defined in: js-api/src/dapi.ts:1443

Row CRUD for one domain table. Reads return only rows and columns the current user can see; writes are validated, permission-checked, and audited server-side. Pass a row interface as TRow for typed reads/writes, and an insert interface as TInsert so insert enforces required columns (grok api-generated clients pass both; see DomainsDataSource.table).

Type Parameters

Type ParameterDefault type
TRowany
TInsertDomainRowInsert<TRow>
TColumn extends stringstring
TExpand extends objectobject
TUpdatePartial<TRow>

Constructors

Constructor

new DomainTableClient<TRow, TInsert, TColumn, TExpand, TUpdate>(dart, schema, table, options?): DomainTableClient<TRow, TInsert, TColumn, TExpand, TUpdate>

Defined in: js-api/src/dapi.ts:1455

Parameters

ParameterType
dartany
schemastring
tablestring
options?DomainTableClientOptions

Returns

DomainTableClient<TRow, TInsert, TColumn, TExpand, TUpdate>

Properties

PropertyModifierTypeDefined in
dartpublicanyjs-api/src/dapi.ts:1447
schemareadonlystringjs-api/src/dapi.ts:1455
tablereadonlystringjs-api/src/dapi.ts:1455

Accessors

filters

Get Signature

get filters(): DomainSavedFiltersClient

Defined in: js-api/src/dapi.ts:1976

Saved filter presets of this table — shareable entities carrying filter panel states.

Returns

DomainSavedFiltersClient

Methods

access()

access(): Promise<DomainAccess>

Defined in: js-api/src/dapi.ts:1859

Effective DomainAccess of the CURRENT user on this table, composed by the server from the predicates its reads and writes apply (GET /domains/{schema}/{table}/access). Cached per registry generation + user; grant changes made through this client drop the cache automatically, out-of-band changes require DomainsDataSource.invalidateUiCaches. Rejects with a DomainValidationError for unknown tables. Also carries DomainAccess.support — what the TABLE can do at all, which does not depend on the caller and is what a client gates optional affordances on.

Returns

Promise<DomainAccess>


aggregate()

aggregate<TGroup, TAlias>(spec): Promise<DomainAggregateRow<TGroup | TAlias>[]>

Defined in: js-api/src/dapi.ts:1580

Grouped aggregation over the rows and columns visible to the caller (10k row cap); resolves to result rows named by group column / measure alias. Alias measures with as (and pass literal groupBy) to get typed result keys; without them, cast or use aggregateDf. The spec carries a whole DomainReadScope: search and deleted narrow the aggregated rows exactly as they narrow query, so a summary and a list agree.

Type Parameters

Type ParameterDefault type
TGroup extends stringnever
TAlias extends stringnever

Parameters

ParameterType
specDomainAggregateSpec<TColumn, TGroup, TAlias>

Returns

Promise<DomainAggregateRow<TGroup | TAlias>[]>


aggregateDf()

aggregateDf(spec): Promise<DataFrame>

Defined in: js-api/src/dapi.ts:1804

aggregate returning a typed d42 DataFrame (10k row cap, both formats).

Parameters

ParameterType
specDomainAggregateSpec<TColumn>

Returns

Promise<DataFrame>


audit()

audit(id): Promise<DomainAuditEntry[]>

Defined in: js-api/src/dapi.ts:1726

Returns the row's audit trail (before/after diffs, in-transaction with each write).

Parameters

ParameterType
idstring

Returns

Promise<DomainAuditEntry[]>


auditLog()

auditLog(options?): Promise<DomainAuditEntry[]>

Defined in: js-api/src/dapi.ts:1816

Table-wide audit trail, newest first; limit clamps to [1, 1000].

Parameters

ParameterType
options?{ limit?: number; }
options.limit?number

Returns

Promise<DomainAuditEntry[]>


batch()

Call Signature

batch(data, options): Promise<DomainBatchValidation>

Defined in: js-api/src/dapi.ts:1649

Judges the same payload and writes NOTHING (see DomainBatchOptions.validateOnly): the server runs the whole commit path and rolls it back, so the per-row predicted verdicts are the ones a real commit would produce. No row, no audit entry, no auto-number, no notification — and no id, because the id of a rolled-back insert does not exist. The verdicts are a prediction against the table as it is NOW; a concurrent write can change them before the commit. Needs DomainSupport.writes like the commit does.

Parameters
ParameterType
datastring | Uint8Array<ArrayBufferLike> | DataFrame | object[]
optionsDomainBatchOptions & object
Returns

Promise<DomainBatchValidation>

Call Signature

batch(data, options?): Promise<DomainBatchReport>

Defined in: js-api/src/dapi.ts:1658

Bulk upload: a DataFrame (sent as d42), a CSV string, an array of row objects, or raw bytes (options.format: 'd42' default, 'parquet' converted via the Arrow package). options.mode: 'upsert' merges by the table's business key. Resolves to the batch report; a failure that carries the per-row report (e.g. an allOrNothing abort) resolves with error set, report-less failures reject. Declared many-to-many relations are REJECTED here (the set diff is per row and would defeat the set-based load) — link with insert / update.

Parameters
ParameterType
datastring | Uint8Array<ArrayBufferLike> | DataFrame | object[]
options?DomainBatchOptions
Returns

Promise<DomainBatchReport>


count()

Call Signature

count(scope?): Promise<number>

Defined in: js-api/src/dapi.ts:1746

Rows matching one DomainReadScope — the same {filter, search, deleted} object query takes, so a paged source's total (a trash list's included) can never disagree with the rows it counts. Omit it for the whole table.

Parameters
ParameterType
scope?DomainReadScope<TColumn>
Returns

Promise<number>

Call Signature

count(filter?, options?): Promise<number>

Defined in: js-api/src/dapi.ts:1748

Parameters
ParameterType
filter?DomainFilter<TColumn>
options?{ deleted?: "exclude" | "include" | "only"; search?: string; }
options.deleted?"exclude" | "include" | "only"
options.search?string
Returns

Promise<number>

Deprecated

pass one scope: count({filter, search, deleted}).


delete()

delete(id): Promise<void>

Defined in: js-api/src/dapi.ts:1669

Soft-deletes a row (engine-enforced cascade/restrict/setnull for declared relations; a restrict reference rejects with a DomainRestrictError).

Parameters

ParameterType
idstring

Returns

Promise<void>


deleteWhere()

deleteWhere(filter, options?): Promise<DomainDeleteReport>

Defined in: js-api/src/dapi.ts:1690

Soft-deletes up to options.limit (≤1000, default 1000) matching rows you may delete, oldest first, in ONE transaction; referential actions apply per row and a restrict reference rejects the whole call (DomainRestrictError — nothing is deleted). The filter is required — an empty one rejects with a DomainValidationError. Each row runs through the per-row engine (cascade fan-out, audit), so this is not a free bulk sweep: prefer a narrow filter and a modest limit, and loop while hasMore for larger sets. A row already gone by its turn (deleted concurrently, or eaten by an earlier row's cascade) is skipped, not an error.

Parameters

ParameterType
filterDomainFilter<TColumn>
options?{ limit?: number; }
options.limit?number

Returns

Promise<DomainDeleteReport>


exists()

Call Signature

exists(scope?): Promise<boolean>

Defined in: js-api/src/dapi.ts:1766

True when at least one row matches the scope.

Parameters
ParameterType
scope?DomainReadScope<TColumn>
Returns

Promise<boolean>

Call Signature

exists(filter?, options?): Promise<boolean>

Defined in: js-api/src/dapi.ts:1768

Parameters
ParameterType
filter?DomainFilter<TColumn>
options?{ deleted?: "exclude" | "include" | "only"; search?: string; }
options.deleted?"exclude" | "include" | "only"
options.search?string
Returns

Promise<boolean>

Deprecated

pass one scope: exists({filter, search, deleted}).


facets()

facets<TId, TKind>(spec): Promise<{ facets: { [K in string]: DomainFacetResultOf<TKind> }; }>

Defined in: js-api/src/dapi.ts:1738

Batched facet computation for filter panels: category counts, histograms, min/max, row count, and column profiling in one round trip — counts under all other filters, bounds under the row predicate only (the stable-axis exception; see DomainFacetsSpec). All results respect the row predicate and column security. Resolves to {facets: {<id>: <result>}}'categories' results as {categories: DomainFacetCategory[], hasMore}, 'histogram' as {min, max, buckets, totalBuckets, nulls}buckets counted under the other filters, totalBuckets under the row predicate only (datetime bounds are ISO-8601 strings), 'minMax' as {min, max}, 'count' as {count}, 'plan' as {columns: [{name, distinct, min?, max?}]}.

Type Parameters

Type ParameterDefault type
TId extends stringstring
TKind extends DomainFacetKindDomainFacetKind

Parameters

ParameterType
specDomainFacetsSpec<TColumn, TId, TKind>

Returns

Promise<{ facets: { [K in string]: DomainFacetResultOf<TKind> }; }>


fetchFields()

fetchFields(ids, fields?): Promise<DataFrame>

Defined in: js-api/src/dapi.ts:1799

Rows for [ids] as a typed DataFrame: the 'id' column plus [fields] (default: all visible columns). Chunked client-side at 100k ids; row predicate + column security apply (missing/invisible ids are absent rows). An empty [ids] list short-circuits to an empty ZERO-COLUMN frame — even when [fields] are requested.

Parameters

ParameterType
idsstring[]
fields?TColumn[]

Returns

Promise<DataFrame>


first()

first(spec?): Promise<TRow | null>

Defined in: js-api/src/dapi.ts:1783

First matching row or null; shorthand for query({...spec, limit: 1}).

Parameters

ParameterType
spec?DomainQuerySpec<TColumn, keyof TExpand & string>

Returns

Promise<TRow | null>


get()

Call Signature

get(id): Promise<TRow>

Defined in: js-api/src/dapi.ts:1587

Fetches one row by id; resolves to null if the row does not exist or is not visible (typed TRow for backward compatibility — guard against null, or use first).

Parameters
ParameterType
idstring
Returns

Promise<TRow>

Call Signature

get(id, options): Promise<TRow & DomainRowAccess & object>

Defined in: js-api/src/dapi.ts:1590

get with the row's DOMAIN_ACCESS_COLUMNS (~can_edit, ~can_delete, ~can_share) — the DomainRowAccess keys beside the row's own.

Parameters
ParameterType
idstring
options{ deleted: "include" | "only"; withAccess: true; }
options.deleted"include" | "only"
options.withAccesstrue
Returns

Promise<TRow & DomainRowAccess & object>

Call Signature

get(id, options): Promise<TRow & DomainRowAccess>

Defined in: js-api/src/dapi.ts:1592

Fetches one row by id; resolves to null if the row does not exist or is not visible (typed TRow for backward compatibility — guard against null, or use first).

Parameters
ParameterType
idstring
options{ deleted?: "exclude"; withAccess: true; }
options.deleted?"exclude"
options.withAccesstrue
Returns

Promise<TRow & DomainRowAccess>

Call Signature

get(id, options): Promise<TRow & object>

Defined in: js-api/src/dapi.ts:1596

get scoped by options.deleted (see DomainQuerySpec.deleted): 'include' or 'only' make a soft-deleted row addressable — it comes back carrying ~is_deleted and is read-only until restore brings it back.

Parameters
ParameterType
idstring
options{ deleted: "include" | "only"; withAccess?: false; }
options.deleted"include" | "only"
options.withAccess?false
Returns

Promise<TRow & object>

Call Signature

get(id, options?): Promise<TRow>

Defined in: js-api/src/dapi.ts:1598

Fetches one row by id; resolves to null if the row does not exist or is not visible (typed TRow for backward compatibility — guard against null, or use first).

Parameters
ParameterType
idstring
options?{ deleted?: "exclude" | "include" | "only"; withAccess?: boolean; }
options.deleted?"exclude" | "include" | "only"
options.withAccess?boolean
Returns

Promise<TRow>


getByKey()

getByKey(keyValues): Promise<TRow | null>

Defined in: js-api/src/dapi.ts:1789

Business-key (or any equality-set) lookup; ambiguous or absent → null.

Parameters

ParameterType
keyValuesPartial<TRow>

Returns

Promise<TRow | null>


grant()

grant(group, permission): Promise<void>

Defined in: js-api/src/dapi.ts:1869

Idempotently grants [permission] on this table to [group] (a group id). Requires Share.

Parameters

ParameterType
groupstring
permissionDomainPermission

Returns

Promise<void>


grants()

grants(): Promise<DomainGrant[]>

Defined in: js-api/src/dapi.ts:1864

Direct permission rows on this table's registry entity. Requires Share.

Returns

Promise<DomainGrant[]>


insert()

insert(rows, options?): Promise<DomainInsertResult[]>

Defined in: js-api/src/dapi.ts:1621

Inserts a single row or a small array of rows; resolves to per-row reports ({id, created}, or {status: 'duplicate', existingId} on a business-key match — pass options.errorOnDuplicate to reject duplicates with a DomainValidationError instead, its isDuplicate set). For tables that declare "idempotency": true, pass an idempotencyKey (UUID) row field to make retries safe: a replay returns the existing id with status: 'idempotent-replay'.

A payload may carry declared many-to-many relations as lists of target row ids ({title: 'Crash', labels: [id1, id2]}); the junction rows are written in the same transaction as the row, so a target that is missing or invisible fails the WHOLE row with code: 'not-visible-or-missing'. A row that dedups to an existing one (status: 'duplicate' / 'idempotent-replay') IGNORES its relation values — a replay never mutates the existing row's links. Creating the target and linking it in one shot is a DomainsDataSource.transaction with '$ref' placeholders inside the list. batch does NOT accept relation keys — use insert/update.

Parameters

ParameterType
rowsTInsert | TInsert[]
options?{ errorOnDuplicate?: boolean; }
options.errorOnDuplicate?boolean

Returns

Promise<DomainInsertResult[]>


isWatching()

isWatching(id?): Promise<boolean>

Defined in: js-api/src/dapi.ts:1847

Whether the current user watches the table (or row, when [id] is given).

Parameters

ParameterType
id?string

Returns

Promise<boolean>


pathTo()

pathTo(id): Promise<object[]>

Defined in: js-api/src/dapi.ts:1716

Ancestors of [id] in a table that declares a hierarchy (DomainTableInfo.hierarchy), root first — what a breadcrumb renders in front of the row. The row ITSELF is not in the list, so a root resolves to []. Every level passes the View predicate, so a chain through an ancestor the caller cannot see is TRUNCATED (the visible tail, no hole and no leak), and a non-hierarchy table rejects with a DomainFilterError. Depth is capped at 64.

Parameters

ParameterType
idstring

Returns

Promise<object[]>


promote()

promote(id): Promise<{ id: string; promoted: boolean; }>

Defined in: js-api/src/dapi.ts:1721

Creates the entities row for a domain row so it can be individually shared.

Parameters

ParameterType
idstring

Returns

Promise<{ id: string; promoted: boolean; }>


query()

Call Signature

query(): DomainQueryBuilder<TRow, TColumn, TExpand, TRow, DataFrame>

Defined in: js-api/src/dapi.ts:1534

Bare query() returns an awaitable DomainQueryBuilder (it used to resolve all-defaults rows — await table.query() behaves identically, and everything chains: await table.query().where('sku', '=', key).orderBy('created_on', true).top(5)). Prefer the builder's condition forms and the cond/and/or helpers over template-built filter strings — condition values are bound server-side, so any string value is safe (apostrophes included).

Returns

DomainQueryBuilder<TRow, TColumn, TExpand, TRow, DataFrame>

Call Signature

query(spec): Promise<TRow & DomainRowAccess[]>

Defined in: js-api/src/dapi.ts:1536

query with withAccess: every row also carries the DomainRowAccess keys.

Parameters
ParameterType
specDomainQuerySpec<TColumn, keyof TExpand & string> & object
Returns

Promise<TRow & DomainRowAccess[]>

Call Signature

query(spec): Promise<TRow[]>

Defined in: js-api/src/dapi.ts:1542

Runs a filtered, sorted, paginated query; resolves to an array of row objects (10k row cap). A declared many-to-many relation expands under its own name into a DomainRelationLink[] (expand: ['labels']row.labels = [{id, name}, ...], capped at 100, ordered by display name, [] when there are no visible links).

Parameters
ParameterType
specDomainQuerySpec<TColumn, keyof TExpand & string>
Returns

Promise<TRow[]>


queryDf()

queryDf(spec?): Promise<DataFrame>

Defined in: js-api/src/dapi.ts:1562

Runs the same query as query but resolves to a typed DataFrame (d42 wire format, 10M row cap). Columns carry the db property tags (dbPropertySchema/dbPropertyName), .choices, and semantic types; system columns are untagged. 'details:' expand is JSON-only — use query; master expand yields flat '<fk_column>.<name>' columns. A relation expand yields TWO columns: '<relation>' with the display names joined by ', ' (tagged so the grid draws chips) and the hidden companion '~<relation>.id' with the ids in the same order — the ids are the source of truth (see DomainRelationLink).

Parameters

ParameterType
specDomainQuerySpec<TColumn, keyof TExpand & string>

Returns

Promise<DataFrame>


restore()

restore(id): Promise<DomainRestoreResult>

Defined in: js-api/src/dapi.ts:1678

Brings a soft-deleted row back (the Delete right is what restores, and the audit trail gets an 'undelete' entry). A row whose reference points at a still-deleted parent is refused with a DomainRestrictError naming that column — restore the parent first; nothing deleted under that id rejects like a missing row. Find the candidates with query({deleted: 'only'}) (DomainQuerySpec.deleted).

Parameters

ParameterType
idstring

Returns

Promise<DomainRestoreResult>


restoreColumnVisibility()

restoreColumnVisibility(column): Promise<void>

Defined in: js-api/src/dapi.ts:1903

Deletes the per-column schema with its grants; the column rejoins the everyone-visible core schema.

Parameters

ParameterType
columnTColumn

Returns

Promise<void>


restrictColumn()

restrictColumn(column): Promise<{ id: string; name: string; }>

Defined in: js-api/src/dapi.ts:1895

Restricts [column] without granting anyone (inverse: restoreColumnVisibility).

Parameters

ParameterType
columnTColumn

Returns

Promise<{ id: string; name: string; }>


revoke()

revoke(group, permission?): Promise<void>

Defined in: js-api/src/dapi.ts:1875

Revokes [permission] (or all four when omitted) from [group]. Requires Share.

Parameters

ParameterType
groupstring
permission?DomainPermission

Returns

Promise<void>


save()

save(row): Promise<TRow>

Defined in: js-api/src/dapi.ts:1921

Insert-or-update by row identity: no id → insert; id → version-checked partial update (uses row.version when present). System columns other than the addressing id/version are stripped from the payload, so spreading a read row is safe. Resolves to the row merged with the new id/version — NB: re-saving an OLD object after a successful save carries its stale version and rejects with a DomainVersionConflictError; keep the resolved row. An id-less save whose business key matches an existing row is a TRUE insert-or-update: the values are applied to the existing row as a versioned update (retried on conflict), so save() never resolves a version-less row. An idempotency-key replay applies nothing — the original insert already did — and resolves the existing row's fresh version (rejects DomainNotFoundError when that row is no longer visible). The unversioned (last-write-wins) update remains available ONLY by deliberately constructing {id} without a version — never as a side effect of a duplicate.

Parameters

ParameterType
rowPartial<TRow> & object

Returns

Promise<TRow>


shareColumn()

shareColumn(column, group, permission?): Promise<{ id: string; name: string; }>

Defined in: js-api/src/dapi.ts:1887

Restricts [column] to its own single-column property schema and grants [group] View on it — afterwards only grantees (and admins) see the column. Returns the per-column schema {id, name} (a further grants target). Requires Share on the core schema; jsonb columns are managed via their property schema (DomainError). Out of scope on this surface: listing a per-column schema's own grants (keep the returned id), and property-schema grants in general (server-supported; no JS surface yet).

Parameters

ParameterType
columnTColumn
groupstring
permission?DomainPermission

Returns

Promise<{ id: string; name: string; }>


unwatch()

unwatch(id?): Promise<boolean>

Defined in: js-api/src/dapi.ts:1842

Removes the table (or row, when [id] is given) subscription; resolves to whether the server confirmed the removal.

Parameters

ParameterType
id?string

Returns

Promise<boolean>


update()

update(id, values, options?): Promise<DomainUpdateResult>

Defined in: js-api/src/dapi.ts:1639

Partially updates a row; pass options.version (the version the client last read) for optimistic concurrency — the update fails with a DomainVersionConflictError if the row has changed since. Resolves to {id, version} (version increments on every update).

values may also carry declared many-to-many relations as lists of target row ids, with SET-REPLACE semantics over the links you can SEE: the list becomes the visible link set, [] clears it, and an ABSENT relation key leaves the relation untouched. Links whose junction row or target row the caller cannot view are never diffed and therefore never removed — a replace can only destroy links its author knows about, so "the replace didn't remove that label" is the design, not a bug. A relations-only update still bumps the row version, so options.version covers the links too. grok api-generated clients name the relations in their <Table>Update type and pass it as the client's fifth generic; untyped callers keep Partial<TRow>.

Parameters

ParameterType
idstring
valuesTUpdate
options?{ version?: number; }
options.version?number

Returns

Promise<DomainUpdateResult>


updateWhere()

updateWhere(filter, values, options?): Promise<DomainUpdateReport>

Defined in: js-api/src/dapi.ts:1705

Applies [values] to up to options.limit (≤1000, default 1000) matching rows you may edit, oldest first, in ONE transaction — the bulk-edit primitive (updateWhere('id in ("…","…")', {status_id: closedId}) for a selection, a real filter for everything that matches). The filter is required — an empty one rejects with a DomainValidationError — and rows you may see but not edit are silently not selected. values is validated once, like an update payload: an immutable, system or ~ column, a relation name, or a value the column refuses rejects the WHOLE call (DomainValidationError); so does any row that fails on its turn — nothing is written. A row gone by then (deleted concurrently) is skipped, not an error. Each row runs through the per-row engine (validation, audit), so prefer a narrow filter and a modest limit, and loop while hasMore.

Parameters

ParameterType
filterDomainFilter<TColumn>
valuesTUpdate
options?{ limit?: number; }
options.limit?number

Returns

Promise<DomainUpdateReport>


updateWithRetry()

updateWithRetry(id, mutate, options?): Promise<DomainUpdateResult | null>

Defined in: js-api/src/dapi.ts:1957

Read-modify-write with optimistic retry: fetches the fresh row, applies [mutate], writes with the fresh version; retries on DomainVersionConflictError (maxRetries counts retries after the initial attempt — default 5 retries = up to 6 attempts, no backoff). [mutate] returning null skips the write (resolves null). Rejects DomainNotFoundError when the row is invisible/absent, and DomainError (code 'no-version') when the fresh row carries no version — the write never silently degrades to an unversioned (last-write-wins) update. For multi-op flows (e.g. a guarded transaction), use DG.retryOnVersionConflict directly with the fresh read inside the action.

Parameters

ParameterType
idstring
mutate(fresh) => TUpdate | null
options?{ maxRetries?: number; }
options.maxRetries?number

Returns

Promise<DomainUpdateResult | null>


upsert()

upsert(row): Promise<{ id: string; status: "inserted" | "updated"; }>

Defined in: js-api/src/dapi.ts:1811

Inserts or merges ONE row by the table's business key (requires businessKey). Rides the batch engine in upsert mode; failures (invalid values, missing business-key column) reject with a DomainValidationError.

Parameters

ParameterType
rowTInsert

Returns

Promise<{ id: string; status: "inserted" | "updated"; }>


version()

version(): Promise<DomainTableVersion>

Defined in: js-api/src/dapi.ts:1829

The table's change token — "did anything change?" as ONE indexed read instead of an aggregate per open list. seq moves by exactly one per write TRANSACTION that touched this table's rows (a 50-row batch and a 3-op transaction each move it once, a rolled-back or validate-only write not at all), and at is when it last moved — null until the first write. A poll compares seq with the one it held; anything else about the change (which rows, by whom) comes from a re-read or auditLog.

Needs View on the securing entity: a caller that reaches rows only through per-row grants is refused with a DomainForbiddenError and has to fall back to counting.

Returns

Promise<DomainTableVersion>


watch()

watch(id?): Promise<boolean>

Defined in: js-api/src/dapi.ts:1836

Subscribes the current user to change notifications for the table (or one row when [id] is given; row watch requires the table's audit trail). Resolves to whether the server confirmed the subscription.

Parameters

ParameterType
id?string

Returns

Promise<boolean>