Environment
The globals, datasets and field names available to your page
Everything in the SDK hangs off the global Anfra. It is ready before your first <script> runs, so there is no import, no setup and no await.
Datasets
Anfra.datasets maps each dataset's fqn, as anfra show lists it, to a descriptor of what the current reader can use:
Anfra.datasets.sales
// {
// name, label,
// data_models: [{ name, label, fields: [{ name, label, type, is_custom_measure }] }],
// metrics: [{ name, label, type }]
// }is_custom_measure marks a model measure. Use the descriptors to build field pickers or to check a name before you use it. To list the same datasets from a terminal, run anfra show.
User
Anfra.user describes the reader:
Anfra.user
// { id, name, email, role, timezone, permissions: { canViewGeneratedSql, canExportData } }Under anfra serve, it is the machine's user, with every permission and the machine's time zone. Treat permissions as rendering hints only, such as hiding an export button. The backend re-checks every query as this reader.
Plugins
Anfra.plugins lists the plugins the host installed. A plugin adds its API under its own name, such as query.export or Anfra.lineage, and only where it is installed:
Anfra.plugins.has('lineage') // check before using an optional plugin
Anfra.plugins.list // [{ name, version }, ...]Anfra.features is deprecated. See Migrating from Anfra.features.
Field references
When you name a field to the SDK, in createFilter or mapControl, use:
model.fieldfor a model field, such asusers.region.- A bare
namefor a dataset-level metric, such asrevenue.
Names come from Anfra.datasets, never from labels.
Inside a query's AQL the same names apply. Everywhere else the SDK uses the aliases your AQL declared: result row keys, setSort, and the fields option of query.select.
A filter's field is checked immediately, and a typo throws a ValidationError with a "did you mean" suggestion. A mapControl field is not checked until the query runs, so a typo there arrives as a QueryError.
Creating an app
const app = Anfra.createApp({ title: 'Sales', timezone: 'Asia/Singapore' }) // both optionalOmit timezone to use anfra's default. Set it to an IANA zone to evaluate relative dates and date truncation in that zone. title names the app in tools such as the Inspect panel.
A page may create several apps, but one is almost always right. Names are unique per app across queries and controls.
The app object
Anfra.createApp() returns the app object. Its members:
| Member | Does |
|---|---|
app.createQuery(name, { dataset, aql, pageSize? }) | Declares a query. |
app.createFilter(name, decl) | Declares a filter. |
app.createDateDrill(name, { default?, label? }) | Declares a date drill. |
app.mapControl(control, query, { field, aggregation? }) | Applies a control to a query. |
app.mapCrossFilter(fromQuery, toQuery) | Applies selected rows in one query to another. See Cross-filtering. |
await app.execute() | Runs every query whose inputs changed. Resolves { succeeded, failed } and never rejects. |
await app.refresh() | Re-runs every query, whether or not its inputs changed. |
app.subscribe(fn) | Calls fn on any change in the app or its entities. Returns an unsubscribe function. |
app.hasChanges | true when a control or the selection changed since the last execute. Use it for an "Apply" button. |
app.selection / app.clearSelection() | The current cross-filter selection, and a way to clear it. |
app.abort() | Cancels in-flight queries. |
Related
- Semantic UI: how queries, controls and cross-filters work together.
- Build a data app: where
Anfracomes from and what the page can do. - Plugins: what the host installs, and how to check for a plugin.