Plugins#
Extend BunTok apps with isolated, named plugins. Plugins can add middleware, routes, context properties, or any other functionality to the app.
Imports#
typescript
import { createPlugin } from "@buntok/core";
import type { Plugin } from "@buntok/core";Plugin Interface#
typescript
interface Plugin<DI extends Record<string, unknown> = Record<string, unknown>> {
name: string;
install: (app: App<DI>) => void | Promise<void>;
}name— unique identifier, used for dedup (same name = install once only)install(app)— receives the app instance, can be asyncDIgeneric — constrains the app's dependency injection type
Creating a Plugin#
Simple plugin — add middleware#
typescript
const loggerPlugin = createPlugin({
name: "logger",
install: (app) => {
app.use(async (ctx, next) => {
const start = Date.now();
await next();
const ms = Date.now() - start;
console.log(`${ctx.request.method} ${ctx.request.url} - ${ms}ms`);
});
},
});Plugin with routes#
typescript
const healthPlugin = createPlugin({
name: "health",
install: (app) => {
app.get("/health", () => ({ status: "ok", timestamp: Date.now() }));
app.get("/health/ready", () => ({ ready: true }));
},
});Plugin with async dependencies (lazy import)#
typescript
const authPlugin = createPlugin({
name: "@buntok/auth",
install: async (app) => {
// Lazy import — zero startup cost if plugin not installed
const { JwtService } = await import("@buntok/core");
const jwt = new JwtService(process.env.JWT_SECRET!);
app.use(requireAuth(jwt));
},
});Installing Plugins#
typescript
app.plugin(loggerPlugin);
app.plugin(healthPlugin);Info
- Dedup by
name— installing same plugin twice is a no-op install()runs immediately whenapp.plugin()is called- Async
install()is awaited — server won't start until all plugins finish - Installed names tracked in
app.installedPlugins(Set)
Checking Installed Plugins#
typescript
if (app.installedPlugins.has("logger")) {
console.log("Logger plugin is installed");
}Plugin Order Matters#
Plugins run in order of app.plugin() calls. Middleware added by earlier plugins runs before later ones:
typescript
app.plugin(corsPlugin); // CORS runs first
app.plugin(authPlugin); // Auth runs second
app.plugin(loggerPlugin); // Logger runs third