Extending BSB
Build custom plugins to extend BSB's capabilities. Create your own events transport, observability backends, and configuration providers.
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 BSBEventsObservable Plugin
Unified logging, metrics, and tracing. Implement Graylog, OpenTelemetry, Pino, Winston, or custom backends.
Extends BSBObservableConfig Plugin
Load configuration from external sources. Implement Consul, etcd, Vault, or custom config providers.
Extends BSBConfigCreating 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:
./src/plugins/- Local development plugins./lib/plugins/- Compiled plugins$BSB_PLUGIN_DIRS/- External plugin directories, comma-separated (for Docker)node_modules/- npm-installed plugins
Name your plugin folder with the appropriate prefix: events-*, observable-*, or config-*.