Skip to content
Apexify.jsDocs
Apexify.js version v5.4.5

Advanced / Composition · guide

Plugins (painter.plugins, painter.use)

Current Apexify.js 6.0.0 documentation for Plugins (painter.plugins, painter.use).

apexify.jsRuntime: nodeCURRENTSince 6.0.0

Apexify.js exposes two related extension mechanisms:

  1. painter.plugins (PluginHost) — a name → API-object registry.
  2. await painter.use(plugin) — transactional plugin installation with one installation per plugin name.

ApexPainter.use is asynchronous. Always await it. The method resolves to the painter instance only after plugin.install(host) has completed.


painter.plugins registry

SOURCEtypescript
typescript
Studio
import { ApexPainter } from "apexify.js"; const painter = new ApexPainter({ type: "buffer" }); const myToolkit = painter.plugins.use("analytics", {  track(_event: string, _payload?: Record<string, unknown>) {    /* ... */  },}); const tk = painter.plugins.get<typeof myToolkit>("analytics");tk?.track("render_ok");

Registry contract:

  • use(name, api) validates the name and rejects duplicate API names with ApexifyPluginError.
  • get<T>(name), has(name), list() inspect registered APIs.
  • remove(name) deletes an API entry.
  • isInstalled(name), listInstalled() inspect completed ApexifyPlugin installations.

API names and plugin names must be non-empty identifier-like strings.


await painter.use(plugin)

SOURCEtypescript
typescript
Studio
import { ApexPainter, type ApexifyPlugin, type SceneLayer } from "apexify.js"; const watermarkHelper: ApexifyPlugin<ApexPainter> = {  name: "watermark-kit",  async install(p) {    // Async setup is supported and awaited.    await Promise.resolve();     p.plugins.use("watermark-kit", {      cornerLabel(text: string): SceneLayer[] {        return p.components.watermark.toLayers({          text,          canvasWidth: 640,          canvasHeight: 360,          position: "bottom-right",          margin: 16,          fontSize: 12,          color: "#94a3b81a",        });      },    });  },}; const painter = new ApexPainter({ type: "buffer" });await painter.use(watermarkHelper); const kit = painter.plugins.get<{ cornerLabel: (text: string) => SceneLayer[] }>("watermark-kit");const layers = kit?.cornerLabel("staging") ?? []; await painter.renderScene({  width: 640,  height: 360,  background: { colorBg: "#020617" },  layers,});

Lifecycle and duplicate semantics

  • Calling painter.use() twice with the same plugin.name is rejected.
  • A second same-name call is also rejected while the first installation is still pending.
  • Different plugin installations are serialized so plugin transactions do not overlap.
  • A failed plugin name is released after cleanup, so the application may retry that plugin later.
  • The current lifecycle is install-only. Apexify.js does not provide plugin uninstall/teardown hooks.

Failure rollback

PluginHost uses an async-context transaction around plugin.install(host). If install() throws or rejects:

  • API registrations made through host.plugins.use(...) inside that plugin installation are removed.
  • Pre-existing PluginHost APIs removed by the failing plugin are restored.
  • Unrelated application registry writes that happen concurrently while the plugin is awaiting are preserved.
  • The plugin is not marked installed.
  • The caller receives ApexifyPluginError with the original error as its cause.

Rollback is intentionally limited to PluginHost registry mutations performed in the plugin installation context. Apexify.js cannot automatically undo arbitrary external side effects performed by plugin code (files, network calls, timers, mutations to unrelated application state). Plugins should perform irreversible side effects only after their own prerequisites are known to have succeeded, or provide their own compensation logic.


Type safety

SOURCEtypescript
typescript
Studio
import type { ApexifyPlugin, ApexPainter } from "apexify.js"; const plugin: ApexifyPlugin<ApexPainter> = {  name: "typed-plugin",  async install(host) {    host.plugins.use("typed-api", {      renderCount: 0,    });  },};

ApexifyPlugin<T> types the installation host. PluginHost.get<T>() lets consumers recover the registered API type at the lookup site.


When to use which

GoalTool
Attach a plain named helper objectpainter.plugins.use(name, api)
Run one-time synchronous or asynchronous setupawait painter.use(plugin)
Need automatic uninstall/teardownNot provided; manage that lifecycle in your application/plugin

Next steps