Utilities for treating hapi plugins as standalone libraries.
Note
Ahem is intended for use with hapi v20+ and nodejs v16+ (see v2 for lower support). Ensure you've installed @hapi/hapi within your project.
Returns an instance of plugin
, i.e. a plugin-server, where plugin
is a hapi plugin.
server
- an optional hapi server, typically used to control the returned plugin instance. See alsocompose.controlled
below.plugin
- a hapi plugin.options
- plugin options forplugin
.compose
- options related to the composition ofserver
,plugin
, and the returned plugin instance.compose.server
- hapi server options. These options will be used to create the root server forplugin
to live on. Note that this cannot be set whenserver
is passed butcompose.controlled
isfalse
: in that caseplugin
is registered directly toserver
, and an additional hapi server will not be created.compose.register
- additional plugins to register to the same server asplugin
, usually to fulfillplugin
's dependencies. This may take the shape{ plugins, options }
or justplugins
, whereplugins
andoptions
are defined as the arguments toserver.register(plugins, [options])
.compose.controlled
- when aserver
is specified but this is set tofalse
,plugin
will be registered directly toserver
. By defaultplugin
will be instanced on a separate server, but controlled byserver
, meaning that it's tied toserver
's initialize/start/stop lifecycle.compose.initialize
- may be set totrue
orfalse
to determine whether to initialize the plugin instance. In a controlled situation (percompose.controlled
) this option defaults tofalse
; when set totrue
,server
will be initialized (in turn the plugin instance is also intialized). In a non-controlled situation this option defaults totrue
; when set tofalse
, the returned plugin instance will not be initialized.compose.decorateRoot
- determines whether or not the returned plugin instance should have aroot
decoration that references the root server to which it is registered. Defaults totrue
unlessserver
is specified butcompose.controlled
isfalse
.compose.decorateController
- determines whether or not the returned plugin instance should have acontroller
decoration that references the controllingserver
. Defaults totrue
when in a controlled situation (percompose.controlled
).
// npm install @hapipal/ahem @hapi/hapi @hapi/vision handlebars
const Vision = require('@hapi/vision');
const Handlebars = require('handlebars');
const Ahem = require('@hapipal/ahem');
// Before continuing, create a template:
// mkdir templates && echo 'Hello, {{name}}!' > templates/hello.hbs
(async () => {
const vision = await Ahem.instance(Vision, {
engines: { hbs: Handlebars },
relativeTo: __dirname,
path: 'templates'
});
const message = await vision.render('hello', { name: 'Clarice' });
console.log(message); // Hello, Clarice!
})();
Returns a function async function([server], [options, [compose]])
identical in behavior to Ahem.instance([server], plugin, [options, [compose]])
but with plugin
fixed. This allows hapi plugins to easily provide an interface for standalone usage.
// my-plugin.js
const Ahem = require('@hapipal/ahem');
exports.plugin = {
name: 'my-plugin',
register(server, options) {
// ...
}
};
exports.create = Ahem.toFactory(exports.plugin);
// index.js
const Hapi = require('@hapi/hapi');
const MyPlugin = require('./my-plugin');
(async () => {
// Your plugin can be used without explicitly utilizing hapi or ahem:
const app = await MyPlugin.create({/* options */});
// Or it can be registered normally as a hapi plugin:
const server = Hapi.server();
await server.register({
plugin: MyPlugin,
options: {/* options */}
});
})();
The purpose of this plugin is to expose the functionality of Ahem.instance()
as a server decoration.
Ahem may be registered multiple times—it should be registered in any plugin that would like to use any of its features. It takes no plugin options.
Identical in behavior to Ahem.instance([server], plugin, [options, [compose]])
but with server
fixed. This is typically used to instance plugin
while ensuring it's controlled by server
. It can be thought of as the less effectful version of server.register()
: rather than registering plugin
to server
, we instead create an instance of plugin
and tie it to server
's initialize/start/stop lifecycle.
// npm install @hapipal/ahem @hapi/hapi
const Hapi = require('@hapi/hapi');
const Ahem = require('@hapipal/ahem');
const App = require('./app');
(async () => {
const server = Hapi.server();
await server.register(Ahem);
const app = await server.instance(App);
// app is not yet initialized
await server.initialize();
// app is now initialized too
await server.stop();
// app is now stopped too
})();
// This is a hapi plugin
exports.plugin = {
name: 'my-plugin',
register(server, options) {
// ^^^^^^ This is a plugin-server
}
};
If you've written a hapi plugin then you're already familiar with this idea, although you might not have a name for it. Every hapi plugin defines a register()
function: async register(server, options)
. The server
passed to this function by hapi is what we call the "plugin-server." It is different from the server returned by Hapi.server()
, sometimes called the "root server", because plugin-servers are scoped to a realm created by hapi specific to the registration of that plugin.