Refactor of dashboardAPI to use BaseNodeAdapter + commandRegistry + statusBadge. dashboardAPI follows the platform refactor plan in .claude/refactor/MODULE_SPLIT.md. Tests stay green; CONTRACT.md generated; legacy aliases preserved. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3.7 KiB
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 requestnode:Re-emits the inbound{ topic: 'create', url: <grafanaUpsertUrl>, // 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 } }msgfields 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/<softwareType>.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 callsconfigManager.getConfig(ctor.name)and would throw. The localdependencies/dashboardapi/dashboardapiConfig.jsonis for the editor menu endpoint, not the runtime config pipeline. - No periodic output —
BaseNodeAdapter's_emitOutputs()/outputUtils.formatMsgpipeline assumes a delta-compressed Port 0/1 stream; dashboardAPI emits HTTP-shaped messages instead. - No registration to a parent —
BaseNodeAdapter._scheduleRegistrationwould emit a spuriouschild.registerof 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.