The plugin class
You need this page for every plugin: the class that owns what its signals share.
The plugin class is the entry point and the place that owns what the signals share: an API client, a poller, a connection.
import { Plugin, secret, z } from "@lox-nexus/plugin-sdk"
const config = z.object({
host: z.url(),
token: secret(z.string()),
pollInterval: z.number().min(1).default(5)
})
export class MyPlugin extends Plugin<z.infer<typeof config>> {
static readonly config = config
static readonly sensors = [PowerSensor]
static readonly actuators = [SwitchActuator]
readonly api = new Api(this.config.host, this.config.token)
readonly poller = this.own(new Poller(this.api))
override start() {
void this.poller.poll()
this.every(this.config.pollInterval * 1000, () => void this.poller.poll())
}
}
(Api, Poller, PowerSensor and SwitchActuator are your own classes.)
Static declarations
config, sensors, actuators and watches are static fields of your class, all optional. They
are static so Nexus can describe the plugin (to build forms and JSON Schema) without starting it.
On each sensor and actuator the static fields are id (required), label, description,
params, and valueType (sensors) or accepts and concurrency (actuators).
Give each sensor and actuator a description. Users pick from a list of them, and one sentence on
what it reads or does tells them more than a label alone.
What the instance gives you
| Member | What it is for |
|---|---|
this.config |
The validated settings. Never changes during a run; saving new settings restarts the instance. |
this.log |
Log lines that show on the instance's page. See Logging, store and status. |
this.store |
Small state that survives restarts, such as a token or a cursor. |
this.status |
Reports degraded or running to the UI. |
this.http |
Registers webhook routes. |
this.slug |
The instance's slug (its topic segment and webhook path), for example to show the hook URL. |
this.clock, this.timeZone |
The time to use instead of Date.now() and the installation's zone, see Time. |
this.watch |
The signals the user chose, for watching plugins. |
this.context.instanceId |
The instance's stable id. The slug can change; the id cannot. |
The methods you can override
| Method | When it is called |
|---|---|
start() |
Once per run, after construction. See lifecycle. |
catalog() |
When the user browses what to add. See Catalog. |
panel() |
Every 3 s while the instance page is open, or, with static panelUpdates = "push", when you call panelChanged() (and every 30 s). See Panel. |
watched(), watchChanged() |
For plugins that declare watches. See Watching. |
unhandledRejection(reason) |
When a promise anywhere in the worker rejects without a handler. |
unhandledRejection() exists because Node ends a thread on an unhandled rejection, and one
forgotten .catch would put your plugin into a crash loop. Nexus catches the rejection, calls this
method and keeps the worker running. The default logs an error with the stack. Override it to
say more, or to report a degraded state; it must not throw.
override unhandledRejection(reason: unknown) {
super.unhandledRejection(reason)
this.status.set("degraded", "an internal error occurred, see the log")
}