Plugin
Reion plugin hooks for request lifecycle, middleware resolution, events, CLI lifecycle, and optional add-time setup.
Plugin
Plugins let you run code at specific points in Reion's lifecycle.
Setup script (reion add)
If you publish a plugin package (npm), you can ship a setup entry that runs when someone runs:
reion add -p your-package-nameReion loads your-package-name/setup (the ./setup export), installs the package (unless --skip-install), then calls your exported setup function.
1. Expose ./setup in package.json
{
"exports": {
".": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
},
"./setup": {
"types": "./dist/setup.d.ts",
"default": "./dist/setup.js"
}
}
}Paths should point at your built files (for example after tsc emits dist/setup.js).
2. Implement setup
Export a named setup or a default function. Type it with ReionPluginSetupFn from reion:
import type { ReionPluginSetupFn } from "reion";
export const setup: ReionPluginSetupFn = async (ctx) => {
ctx.log.info(`Setting up ${ctx.packageName} in ${ctx.cwd}`);
// Optional: install extra deps (only when the user did not pass --skip-install)
ctx.installDependencies?.(["some-optional-dep"]);
// Optional: merge imports and append to plugins: [] in reion.config.ts
const result = await ctx.addPluginToReionConfig({
imports: [{ kind: "named", names: ["myPlugin"], module: "./src/plugins/my-plugin" }],
pluginExpressions: ["myPlugin"],
});
if (!result.ok) {
ctx.log.warn(result.error);
}
};Context (ReionPluginSetupContext):
| Field | Purpose |
|---|---|
cwd | Project root where reion add was run |
packageName | Same string passed to -p |
skipInstall | true if reion add --skip-install was used |
installDependencies | Call with package names to run the same install command as reion add (omitted when --skip-install) |
addPluginToReionConfig | Programmatically edit reion.config.ts (TypeScript only) |
log | info / warn / error loggers |
addPluginToReionConfig can add a plugins: [] property if it is missing, then append your plugin expression. See existing packages such as @reionjs/better-auth for full examples.
3. App authors
They only need the CLI command; no setup file is required in their app unless you document extra steps.
reion add -p @your-scope/your-reion-pluginConfigure plugins
In reion.config.ts:
import type { ReionPlugin } from "reion";
const plugin: ReionPlugin = {
name: "my-plugin",
onRequest(ctx) {
ctx.logger.info("request entered");
},
onError(ctx, err) {
ctx.logger.error({ err }, "request failed");
},
};
export default {
plugins: [plugin],
};Plugins are executed in the order they appear in plugins: [].
Request lifecycle hooks
onRequest(ctx)— after request context + body parsing, before route resolutiononRouteMatch(ctx)— after a route is resolved andctx.paramsis setbeforeHandler(ctx)— right before the route handler (or pipeline) runsafterHandler(ctx, result)— after the handler returnsbeforeResponse(ctx)— runs right before Reion serializes/sends the response (only if the response hasn't been sent yet)afterResponse(ctx)— runs in Reion'sfinallyblock after the response path (success or error)onError(ctx, error)— when an error is thrown/handled
Middleware hook
If you need to observe which middleware will run:
onMiddlewareResolved(ctx, { pathname, method, count })
This runs after Reion resolves middleware for a matched route.
Event hooks
onEventEmit(ctx, { name, payload })- fires when
ctx.emit(name, payload)is called ctx.trace.traceIdis available for correlation (if emitted from a request)
- fires when
CLI lifecycle hooks
Plugins can also react to command execution:
- Dev:
onDevStart,onDevFileChange,onDevRestart,onDevStop - Build:
onBuildStart,onBuildComplete,onBuildError - Start:
onStartStart,onStartListening,onStartStop,onStartError
Hook ordering
If you have multiple plugins configured, Reion runs each hook in the same order as the plugins appear in reion.config.ts (plugins: [...]).