Plugin Types

BSB can be extended with three types of infrastructure plugins. Each plugin type has a specific base class and interface to implement.

Events Plugin

Route events between services. Implement RabbitMQ, Kafka, Redis Pub/Sub, or any message broker.

Extends BSBEvents

Observable Plugin

Unified logging, metrics, and tracing. Implement Graylog, OpenTelemetry, Pino, Winston, or custom backends.

Extends BSBObservable

Config Plugin

Load configuration from external sources. Implement Consul, etcd, Vault, or custom config providers.

Extends BSBConfig

Creating an Events Plugin

An events plugin routes messages between services. Here's a skeleton for a RabbitMQ implementation:

import { BSBEvents, BSBEventsConstructor, Observable } from "@bsb/base";
import { Readable } from "node:stream";

export class Plugin extends BSBEvents<null> {
  private connection: any; // Your RabbitMQ connection

  constructor(config: BSBEventsConstructor<null>) {
    super(config);
  }

  public async init(obs: Observable) {
    // Connect to RabbitMQ
    this.connection = await connect(process.env.RABBITMQ_URL);
    obs.log.info("Connected to RabbitMQ");
  }

  public async onBroadcast(
    obs: Observable,
    pluginName: string,
    event: string,
    listener: (obs: Observable, args: any[]) => Promise<void>
  ): Promise<void> {
    // Subscribe to a fanout exchange
  }

  public async emitBroadcast(
    obs: Observable,
    pluginName: string,
    event: string,
    args: any[]
  ): Promise<void> {
    // Publish to a fanout exchange
  }

  public async onEvent(
    obs: Observable,
    pluginName: string,
    event: string,
    listener: (obs: Observable, args: any[]) => Promise<void>
  ): Promise<void> {
    // Subscribe to a queue
  }

  public async emitEvent(
    obs: Observable,
    pluginName: string,
    event: string,
    args: any[]
  ): Promise<void> {
    // Publish to a queue
  }

  public async onReturnableEvent(
    obs: Observable,
    pluginName: string,
    event: string,
    listener: (obs: Observable, args: any[]) => Promise<any>
  ): Promise<void> {
    // Subscribe to RPC queue
  }

  public async emitEventAndReturn(
    obs: Observable,
    pluginName: string,
    event: string,
    timeoutSeconds: number,
    args: any[]
  ): Promise<any> {
    // Publish to RPC queue and wait for response
  }

  // Stream methods...
  public async receiveStream(...) { }
  public async sendStream(...) { }

  public dispose() {
    this.connection?.close();
  }
}

Creating an Observable Plugin

An observable plugin unifies logging, metrics, and tracing into a single backend. Implement the methods you support — all are optional, so you can build a logging-only plugin, a metrics-only plugin, or a full backend like OpenTelemetry:

import { BSBObservable, BSBObservableConstructor, createConfigSchema, BSBError } from "@bsb/base";
import { DTrace, LogMeta } from "@bsb/base";
import * as av from "anyvali";

const Config = createConfigSchema(
  {
    name: "observable-graylog",
    description: "Graylog observable plugin",
    tags: ["observable", "logging"]
  },
  av.object({
    host: av.string().default("localhost"),
    port: av.number().default(12201)
  })
);

export class Plugin extends BSBObservable<InstanceType<typeof Config>> {
  static Config = Config;

  constructor(cfg: BSBObservableConstructor<InstanceType<typeof Config>>) {
    super(cfg);
  }

  // Logging methods (all optional - implement what you need)
  debug(trace: DTrace, pluginName: string, message: string, meta: LogMeta<any>): void {
    this.sendToGraylog("debug", trace, pluginName, message, meta);
  }
  info(trace: DTrace, pluginName: string, message: string, meta: LogMeta<any>): void {
    this.sendToGraylog("info", trace, pluginName, message, meta);
  }
  warn(trace: DTrace, pluginName: string, message: string, meta: LogMeta<any>): void {
    this.sendToGraylog("warn", trace, pluginName, message, meta);
  }
  error(trace: DTrace, pluginName: string, message: string | BSBError<any>, meta?: LogMeta<any>): void {
    this.sendToGraylog("error", trace, pluginName, message, meta);
  }

  // Metrics methods (optional): createCounter, createGauge, createHistogram, etc.
  // Tracing methods (optional): startSpan, endSpan, etc.

  private sendToGraylog(level: string, trace: DTrace, plugin: string, message: any, meta: any): void {
    // Send to Graylog GELF endpoint
  }
}

Plugin Discovery

BSB discovers plugins in this order:

  1. ./src/plugins/ - Local development plugins
  2. ./lib/plugins/ - Compiled plugins
  3. $BSB_PLUGIN_DIRS/ - External plugin directories, comma-separated (for Docker)
  4. node_modules/ - npm-installed plugins

Name your plugin folder with the appropriate prefix: events-*, observable-*, or config-*.