Plugins
Plugins are composable groups of registrations (actions, routes, subscriptions, workers, crons, workflows). They provide a way to package and distribute reusable functionality.
Creating a Plugin
import { action, onStart, onStop, plugin, route, subscription, worker } from "@chimpbase/runtime";
export function myPlugin(options: MyPluginOptions) {
const entries = [];
entries.push(
action("myPlugin.doSomething", async (ctx) => {
// ...
}),
);
entries.push(
route("myPlugin.api", async (request, env) => {
// return Response or null
}),
);
return plugin({ name: "my-plugin" }, ...entries);
}Using Plugins
Register plugins in your app's registrations array:
import { myPlugin } from "./my-plugin";
export default {
registrations: [
myPlugin({ /* options */ }),
// ... other registrations
],
};Lifecycle Hooks
Plugins can run code on startup and shutdown:
import { onStart, onStop, plugin, action } from "@chimpbase/runtime";
function myPlugin() {
return plugin(
{ name: "my-plugin" },
onStart("my-plugin.init", async (ctx) => {
ctx.log.info("plugin starting");
await ctx.kv.set("my-plugin.version", "1.0");
}),
onStop("my-plugin.cleanup", async () => {
console.log("plugin shutting down");
}),
action("myAction", async (ctx) => { /* ... */ }),
);
}onStart(name, handler)
Runs after the engine is initialized, before serving requests. The handler receives a full ChimpbaseContext with access to db, kv, collection, etc.
Use cases: seed data, validate config, warm caches, run health checks.
onStop(name, handler)
Runs during graceful shutdown, before the server and worker stop.
Use cases: flush buffers, close connections, log final metrics.
Hooks run in registration order. If an onStop hook throws, the error is logged but shutdown continues.
Plugin Dependencies
Plugins can declare dependencies on other plugins to ensure ordering:
plugin(
{
name: "webhooks",
dependsOn: [{ name: "auth" }],
},
...entries,
);Official Plugins
| Plugin | Package | Description |
|---|---|---|
| Auth | @chimpbase/auth | API key authentication, user management, scopes, rate limiting |
| Webhooks | @chimpbase/webhooks | Outbound + inbound webhooks with HMAC and dedup |
| REST Collections | @chimpbase/rest-collections | Expose collections as REST APIs |
| Mesh | @chimpbase/mesh | Services and distributed registry across multiple nodes |
Middleware in Plugins
Plugins often register middleware — routes that set request context or short-circuit before downstream handlers run. Use middleware() instead of route() to signal this intent:
import { middleware, plugin, action } from "@chimpbase/runtime";
function corsPlugin() {
return plugin(
{ name: "cors" },
middleware("cors.preflight", async (request, env) => {
if (request.method === "OPTIONS") {
return new Response(null, {
headers: {
"access-control-allow-origin": "*",
"access-control-allow-methods": "GET, POST, PATCH, DELETE",
"access-control-allow-headers": "content-type, x-api-key, authorization",
},
});
}
return null; // pass through
}),
);
}Middleware runs in registration order. A plugin registered first in the registrations array runs before later plugins. This is how the auth plugin's guard route protects all other routes.
Middleware can also pass data to downstream handlers via request context:
middleware("requestLogger", async (request, env) => {
env.set("request.startedAt", Date.now());
return null;
});See the Routes page for full request context documentation.
Plugin Pattern
The standard plugin pattern used by all official plugins:
- Export a function that accepts options and returns
ChimpbasePluginRegistration - Build an array of registrations (actions, routes, subscriptions, workers, middleware, lifecycle hooks)
- Wrap with
plugin()to group and name them - Use internal collection/KV namespaces prefixed with
__chimpbase.{pluginName}.* - Use internal action names prefixed with
__chimpbase.{pluginName}.*
export function chimpbaseExample(options: ExampleOptions): ChimpbasePluginRegistration {
const entries: ChimpbaseRegistrationSource[] = [];
// Add actions, routes, workers, etc.
entries.push(action("__chimpbase.example.doStuff", handler));
return plugin({ name: "chimpbase-example" }, ...entries);
}