Core
Dashboards & data
Push rows from an external system into named datasets, define dashboards as code, and set threshold alerts on your metrics. The programmatic twin of the in-product dashboard.publish tool.
Publish a dataset#
rows is an array of flat { column: value } objects. mode: "append" accumulates (time-series); the default "replace" overwrites. Reusing a dataset id updates the same widgets bound to it. Requires a write-scoped key.
await bahini.publishDataset({
dataset: "store-sales",
rows: [
{ store: "Dhaka", revenue: 128400, orders: 512 },
{ store: "Chittagong", revenue: 96150, orders: 388 },
],
});Have a CSV instead? publishDatasetFromCsv parses it client-side (quoted fields, CRLF, BOM, numeric coercion) then publishes.
await bahini.publishDatasetFromCsv("store-sales", csvString, {
mode: "append",
});redactedCount tells you how many were touched.Define a dashboard as code#
upsertDashboard matches by title (create-or-update). Widgets are flat: a type, the datasetKey they chart, and field mappings. Reusing a title updates that board.
const board = await bahini.upsertDashboard({
title: "Store performance",
widgets: [
{ type: "number", datasetKey: "store-sales", y: "revenue",
agg: "sum", format: "currency", title: "Total revenue" },
{ type: "bar", datasetKey: "store-sales", x: "store", y: "revenue",
sort: "desc", title: "Revenue by store" },
],
});
console.log(board.url);Read data back#
const { datasets } = await bahini.listDatasets();
const data = await bahini.getDataset("store-sales"); // includes rows
const full = await bahini.getDashboard(board.id); // widgets + resolved rowsMetric alerts#
createAlert(input)
Fires when agg(column) of a dataset crosses the threshold on the next publish. mode: "change" compares the % change vs the previous publish; "stale"fires when a dataset hasn't published in threshold hours.
await bahini.createAlert({
name: "Revenue dropped",
datasetKey: "store-sales",
column: "revenue",
agg: "sum",
op: "lt",
threshold: 100_000,
});