Skip to main content
FDO_SDK is the abstract base class every plugin must extend. When you instantiate your subclass, the SDK automatically registers the plugin with PluginRegistry and emits an init event to the FDO host.

Complete example

import { FDO_SDK, PluginRegistry } from "@anikitenko/fdo-sdk";
import type { PluginMetadata } from "@anikitenko/fdo-sdk";

export class MyPlugin extends FDO_SDK {
  public metadata: PluginMetadata = {
    id: "my-plugin",
    name: "My Plugin",
    version: "1.0.0",
    author: "acme",
    description: "A minimal FDO plugin example.",
    icon: "cube",
  };

  init(): void {
    PluginRegistry.registerHandler("my-plugin.greet", async (data) => {
      return { message: `Hello, ${(data as { name: string }).name}!` };
    });
    this.log("Plugin initialized.");
  }

  render(): string {
    return `<div class="fdo-plugin"><h1>Hello from MyPlugin</h1></div>`;
  }

  renderOnLoad(): string {
    return `() => { console.log("MyPlugin UI loaded"); }`;
  }
}

export default new MyPlugin();

Static members

API_VERSION

public static readonly API_VERSION: string = "1.0.0"
The current SDK API version in major.minor.patch format. The FDO host validates major-version compatibility against this value at plugin init time.

TYPE_TAG

static readonly TYPE_TAG: symbol
A unique Symbol used internally to identify FDO_SDK instances. You do not use this directly.

Constructor

constructor()
Instantiating your plugin subclass automatically registers it with PluginRegistry and emits the init event to the host. You should never call super() with arguments — just call super() from your subclass constructor (or omit the constructor entirely if you have no setup logic).
Instantiate your plugin exactly once, at module load time. Registering multiple instances of the same plugin class in one module produces undefined behavior.

Lifecycle methods

init()

public init(): void
Called by the FDO host after the plugin is loaded. You must override this method — the base implementation throws immediately. Use init() to register handlers, configure stores, and perform any one-time setup your plugin needs.
The base class throws an Error if init() is not overridden. Your subclass must provide its own implementation.
init(): void {
  PluginRegistry.registerHandler("my-plugin.ping", async () => {
    return { pong: true };
  });
  this.log("ready");
}

render()

public render(): string
Called by the FDO host to obtain the plugin’s UI. You must override this method — the base implementation throws immediately. Return a complete HTML string. The host renders it inside a sandboxed iframe. render() must be synchronous; returning a Promise throws a runtime error.
The base class throws an Error if render() is not overridden. Do not return a Promise — async render is not supported.
render(): string {
  return `
    <div style="font-family: sans-serif; padding: 1rem;">
      <h2>Status: OK</h2>
      <p>Plugin is running.</p>
    </div>
  `;
}

renderOnLoad()

public renderOnLoad(): string
Override this method to return a JavaScript function string that the host executes after your plugin UI loads in the iframe. The default implementation returns '() => {}'. The return value must be a synchronous string representation of a function. The host evaluates it in the iframe context.
renderOnLoad(): string {
  return `() => {
    document.getElementById("status").textContent = "Loaded at " + new Date().toLocaleTimeString();
  }`;
}

serializeRender()

public serializeRender(): string
Serializes the output of render() for host transport. The FDO host calls this method — you do not call it yourself. Override render(), not this method. If render() returns a Promise, this method throws. Returns: A JSON-serialized string of the render() output.

serializeRenderOnLoad()

public serializeRenderOnLoad(): string
Serializes the output of renderOnLoad() for host transport. The FDO host calls this method — you do not call it yourself. Override renderOnLoad(), not this method. If renderOnLoad() returns a Promise, this method throws. Returns: A JSON-serialized string of the renderOnLoad() output.

Logging methods

All logging methods write to the plugin’s scoped log file and are safe to call from anywhere inside your plugin class.

log()

public log(message: string): void
message
string
required
The message to write at the default log level.
this.log("Handler registered successfully.");

error()

public error(error: Error): void
error
Error
required
An Error object. The message and stack trace are both captured.
try {
  riskyOperation();
} catch (err) {
  this.error(err instanceof Error ? err : new Error(String(err)));
}

info()

public info(message: string, ...meta: unknown[]): void
message
string
required
The log message.
meta
unknown[]
Optional additional metadata values to attach to the log entry.
this.info("User action received", { action: "click", target: "submit" });

warn()

public warn(message: string, ...meta: unknown[]): void
message
string
required
The warning message.
meta
unknown[]
Optional additional metadata values.
this.warn("Config value missing, using default.", { key: "timeout" });

debug()

public debug(message: string, ...meta: unknown[]): void
message
string
required
The debug message.
meta
unknown[]
Optional additional metadata values.
this.debug("Handler invoked", { handler: "my-plugin.greet", input });

verbose()

public verbose(message: string, ...meta: unknown[]): void
message
string
required
The verbose-level message.
meta
unknown[]
Optional additional metadata values.
this.verbose("Detailed trace", { step: 1, payload });

silly()

public silly(message: string, ...meta: unknown[]): void
message
string
required
The silly-level message (most verbose).
meta
unknown[]
Optional additional metadata values.
this.silly("Raw buffer dump", rawBytes);

Event tracking

event()

public event(name: string, payload?: Record<string, unknown>): string
Emits a named structured event to the plugin log and returns a correlation ID you can use to trace related log entries.
name
string
required
The event name. Use dot-separated namespacing (e.g., "my-plugin.action.start").
payload
Record<string, unknown>
Optional key-value metadata to attach to the event. Defaults to {}.
Returns: string — a correlation ID for the emitted event.
const correlationId = this.event("my-plugin.export.start", {
  format: "csv",
  rowCount: 1000,
});
this.info("Export started", { correlationId });

Log directory

getLogDirectory()

public getLogDirectory(): string
Returns the absolute path of the directory where the plugin’s log files are written. Use this to display or report the log location to users. Returns: string — the absolute path to the log directory.
const logDir = this.getLogDirectory();
this.info("Logs are at", { path: logDir });