Adding a plugin
The closure form of definePlugin is the shortest path from "I need a cross-cutting concern" to "it's wired in". This recipe walks through a minimal audit-log plugin that binds a service, reacts to a framework event, runs on boot, and flushes on shutdown.
Define the plugin
ts
// app/plugins/audit-log.plugin.ts
import { definePlugin } from "@nwire/app"
interface AuditLog {
entries: string[];
record(line: string): void;
flush(): Promise<void>;
}
export const auditLogPlugin = () =>
definePlugin("audit-log", ({ bind, container, boot, dispose }) => {
const log: AuditLog = {
entries: [],
record(line) { this.entries.push(line) },
async flush() { /* ship to durable store */ },
}
bind("auditLog", log)
boot(async () => {
log.record("booting")
})
dispose(async () => {
await log.flush()
})
})Register it
ts
// app/app.ts
import { createApp } from "@nwire/app"
import { auditLogPlugin } from "./plugins/audit-log.plugin"
export const app = createApp({
appName: "demo",
plugins: [auditLogPlugin()],
})To react to framework events, observe them inside the plugin via on — the payload is typed from the named hook:
ts
const auditLogPlugin = () =>
definePlugin("audit-log", ({ bind, on }) => {
const log = new AuditLog()
bind("auditLog", () => log)
on("AppBooted", ({ appName }) => log.record(`app booted: ${appName}`))
})Verify
bash
nwire ls pluginsYou should see audit-log listed with its contributed surfaces (provides: auditLog, on: AppReady, boot, shutdown). If you don't, check that the plugin is in the plugins array and that nwire cache ran against the right topology.