# dashboardAPI — Contract dashboardAPI is an EVOLV utility node that listens for child-registration events from other EVOLV nodes and emits Grafana dashboard upsert HTTP requests on Port 0. It has **no domain measurements, no tick loop, and no parent of its own** — it is a one-shot HTTP emitter. Per OPEN_QUESTIONS.md (2026-05-10) it does NOT extend `BaseNodeAdapter` / `BaseDomain`; it uses the shared command registry only. ## Inputs (msg.topic on Port 0) | Canonical | Aliases (deprecated) | Payload | Effect | |---|---|---|---| | `child.register` | `registerChild` | string (child node id) **or** `{ source: {...} }` **or** `{ config: {...} }` (optionally `msg.includeChildren: boolean`, default `true`) | Resolves the child source (`RED.nodes.getNode` → `node._flow.getNode` → inline payload), calls `source.generateDashboardsForGraph(child, { includeChildren })`, then emits one `topic: 'create'` HTTP-upsert message on Port 0 per generated dashboard. | Aliases log a one-time deprecation warning the first time they fire. ## Outputs (msg.topic on Port 0/1/2) - **Port 0 (process):** one message per generated dashboard, shaped for a downstream `http request` node: ```js { topic: 'create', url: , // e.g. http://grafana:3000/api/dashboards/db method: 'POST', headers: { Accept: 'application/json', 'Content-Type': 'application/json', Authorization: 'Bearer …' // only when bearerToken is set }, payload: { dashboard: {…}, folderId: 0, overwrite: true }, meta: { nodeId, softwareType, uid, title } } ``` Re-emits the inbound `msg` fields by spread (`{...msg, ...}`) so any caller-supplied correlation/trace fields propagate. - **Port 1 (InfluxDB telemetry):** **not used.** dashboardAPI has no measurements; nothing is emitted on Port 1. - **Port 2 (registration / control plumbing):** **not used.** dashboardAPI is a sink for `child.register`, not a source — it does not register itself with any parent. ## Events emitted by `source.emitter` None. The specificClass (`DashboardApi`) exposes no `EventEmitter` — it is a passive service that responds to method calls and returns built dashboard payloads. ## Children accepted Any EVOLV node whose `nodeSource.config` includes `functionality.softwareType`. The graph walk reads children via `nodeSource.childRegistrationUtils.registeredChildren.values()`. A dashboard template is loaded from `config/.json` (with case-insensitive fallback and a `machineGroupControl → machineGroup.json` alias); a missing template is logged at `warn` and the dashboard is skipped. The dashboard's templating variables `measurement` and `bucket` are filled from the child's id and `positionVsParent` (or `config.defaultBucket` / `config.bucketMap[position]` overrides). The root dashboard is augmented with `links[]` entries pointing at each direct child dashboard. ## Why no BaseNodeAdapter / BaseDomain - No `generalFunctions/src/configs/dashboardapi.json` — `BaseDomain`'s constructor unconditionally calls `configManager.getConfig(ctor.name)` and would throw. The local `dependencies/dashboardapi/dashboardapiConfig.json` is for the editor menu endpoint, not the runtime config pipeline. - No periodic output — `BaseNodeAdapter`'s `_emitOutputs()` / `outputUtils.formatMsg` pipeline assumes a delta-compressed Port 0/1 stream; dashboardAPI emits HTTP-shaped messages instead. - No registration to a parent — `BaseNodeAdapter._scheduleRegistration` would emit a spurious `child.register` of its own. - No status badge / tick / measurements / children of its own. dashboardAPI uses the shared `commandRegistry` (canonical topic naming + alias-with-deprecation) and stops there.