Plugins
Galbe provides a plugin system that lets you extend and customize the framework's behavior. Plugin hooks integrate directly with the Request Lifecycle.
Definition
Plugin Signature
type GalbePlugin = {
name: string
init?: (config: any, galbe: Galbe) => MaybePromise<void>
onFetch?: (context: Pick<Context, 'request' | 'set' | 'state'>) => MaybePromise<Response | void>
onRoute?: (context: Pick<Context, 'request' | 'set' | 'state' | 'route'>) => MaybePromise<Response | void>
beforeHandle?: (context: Context) => MaybePromise<Response | void>
afterHandle?: (response: Response, context: Context) => MaybePromise<Response | void>
cli?: (commands: GalbeCLICommand[]) => MaybePromise<GalbeCLICommand[] | void>
} name
The plugin name should be a Unique Plugin Identifier to prevent conflicts with other plugins. Ideally, it follows the format com.example.myplugin.
init
This method is called once when the server starts (after route discovery and before the first request is served). It receives two arguments:
config: The plugin-specific configuration (see thepluginconfiguration property).galbe: The Galbe server instance. From it you can read registered routes (galbe.router.routes) and route metadata (galbe.meta).
onFetch
This method is executed at the beginning of an incoming request. It receives a restricted context object containing request, set, and state.
It is preemptable, meaning that if a response is returned, it will be sent to the client immediately, bypassing further processing.
onRoute
Executed after the router identifies a matching route for the request. It takes a restricted context argument (same as onFetch plus route) and is preemptable, meaning it can return an early response.
beforeHandle
Runs after request validation but before route hooks and the handler are called. Like the previous lifecycle methods, it is preemptable.
afterHandle
Called after the route handler runs but before the response is sent. It receives two arguments:
It is also preemptable: any returned response overrides the original one.
cli
Lets a plugin register custom commands on the Galbe CLI. It receives the current list of GalbeCLICommand entries (one per registered route) and may return a modified list or void to keep the input as-is. Each GalbeCLICommand describes a command name, a list of tags, the route it targets, optional arguments / options, and an optional action callback that overrides the default behavior.
Plugin Registration
To register a plugin, use the use method on your Galbe instance.
const galbe = new Galbe()
galbe.use(plugin) Note
useonly stores the plugin. Each plugin'sinitruns when the server starts (e.g. whengalbe.listen()is called).
How to Create a Plugin
This section will walk you through the process of creating a plugin. Before creating a plugin, don't forget to check if there's an existing plugin that can be used. You can take a look at the official Plugin List.
1. Scaffolding
The Galbe starter CLI provides a template for setting up a plugin project:
$ bun create galbe my-plugin --template plugin
$ cd my-plugin $ bun install
2. Implementation
Below is an example of a plugin that handles routes tagged with @deprecated metadata (See Route Files for metadata usage).
deprecated.plugin.ts
import type { GalbePlugin, Route } from 'galbe'
import { walkMetaRoutes } from 'galbe/utils'
const PLUGIN_ID = 'dev.galbe.deprecated'
export default (): GalbePlugin => {
let deprecateds = new Set<string>()
const isRouteDeprecated = (route?: Route) =>
deprecateds.has(JSON.stringify({ method: route?.method, path: route?.path }))
return {
name: PLUGIN_ID,
// Init the plugin, check for deprecated metadata tags
init(_config, galbe) {
walkMetaRoutes(galbe.meta || [], (method, path, meta) => {
if (meta.deprecated) deprecateds.add(JSON.stringify({ method, path }))
})
},
// Check if the current route is deprecated; if so, flag it as such and log it
onRoute(context) {
let r = context.route
if (isRouteDeprecated(r)) {
console.warn(`Call to deprecated route "${r?.method} ${r?.path}"`)
}
},
// Add a header to the response if the route has been flagged as deprecated
afterHandle(response, context) {
if (isRouteDeprecated(context.route)) {
response.headers.set('x-deprecated', 'true')
}
}
} as GalbePlugin
} Register the plugin with your Galbe server:
import { Galbe } from 'galbe'
import deprecatedPlugin from './deprecated.plugin'
const galbe = new Galbe()
galbe.use(deprecatedPlugin())
export default galbe 3. Publishing
To submit your plugin to the official plugin list, follow these steps:
Create a public GitHub repository for your plugin, ensuring that the
README.mdincludes:- A clear description of your plugin.
- Installation and configuration instructions.
- Usage examples.
(Optional) Publish your plugin to NPM.
Submit a Pull Request to add your plugin configuration to plugins.json in the following format:
"plugin-id": {
"name": "Plugin Name",
"description": "Plugin description",
"repo": "https://github.com/<username>/<repo-name>",
"npm": "https://www.npmjs.com/package/<package-name>"
} Important
Provide all relevant details in the Pull Request description. It will be reviewed by project maintainers as soon as possible. Check the Galbe Contributing Guide before submitting.