Skip to content

Commit

Permalink
Update to hapi v17, hoek v5, joi v13, and lab v15.
Browse files Browse the repository at this point in the history
Breaking Changes:
  - Remove "connections" and "onPreConnection" from manifest.
  - Return async function instead of using a callback or native Promise.
  - Change "preRegister" contract from callback to async function.
  - Change manifest shape from manifest.registrations array to manifest.register.plugins array.
  - Change expected plugin object shape to match hapi v17 expectations.

Non-Breaking Changes:
  - Hand plugin and registration options straight to hapi for validation at registration time.
  - Single server.register call instead of one per plugin.
  • Loading branch information
WesTyler committed Oct 31, 2017
1 parent 1aa5d15 commit 465939b
Show file tree
Hide file tree
Showing 9 changed files with 360 additions and 690 deletions.
3 changes: 1 addition & 2 deletions .travis.yml
Expand Up @@ -3,5 +3,4 @@ sudo: false
language: node_js

node_js:
- "4"
- "6"
- "8"
215 changes: 100 additions & 115 deletions API.md
@@ -1,31 +1,65 @@

## Interface

Glue exports a single function `compose` accepting a JSON `manifest` file specifying the hapi server options, connections, and registrations.
Glue exports a single function `compose` accepting a JSON `manifest` file specifying the hapi server options and plugin registrations and returns a hapi `server` object.
To start the server use the returned object to call `await server.start()`.

### `compose(manifest, [options], [callback])`
### `await compose(manifest, [options])`

Composes a hapi server object where:
+ `manifest` - an object having:
* `server` - an object containing the options passed to [new Hapi.Server([options])](http://hapijs.com/api#new-serveroptions)
+ If `server.cache` is specified, Glue will parse the entry and replace any prototype function field (eg. `engine`) specified as string by calling `require()` with that string.
* `connections` - an array of connection options objects that are mapped to calls of [server.connection([options])](http://hapijs.com/api#serverconnectionoptions)
* `registrations` - an array of objects holding entries to register with [server.register(plugin, [options], callback)](http://hapijs.com/api#serverregisterplugins-options-callback). Each object has two fields that map directly to the `server.register` named parameters:
+ `plugin` - Glue will parse the entry and replace any plugin function field specified as a string by calling `require()` with that string or just put a plugin function to register it. The array form of this parameter accepted by `server.register()` is not allowed; use multiple registration objects instead.
+ `options` - optional option object passed to `server.register()`.
+ `options` - an object having
* `relativeTo` - a file-system path string that is used to resolve loading modules with `require`. Used in `server.cache` and `registrations[].plugin`
* `preConnections` - a callback function that is called prior to adding connections to the server. The function signature is `function (server, next)` where:
+ `server` - is the server object returned from `new Server(options)`.
+ `next`- the callback function the method must call to return control over to glue
* `preRegister` - a callback function that is called prior to registering plugins with the server. The function signature is `function (server, next)` where:
+ `server` - is the server object with all connections selected.
+ `next`- the callback function the method must call to return control over to glue
+ `callback` - the callback function with signature `function (err, server)` where:
* `err` - the error response if a failure occurred, otherwise `null`.
* `server` - the server object. Call `server.start()` to actually start the server.

If no `callback` is provided, a `Promise` object is returned where the value passed to the Promise resolve handler is the `server` object and the value passed to the Promise reject handler is the error response if a failure occurred.
* `register` - an object containing two properties: the `plugins` to be registered and `options` to pass to `server.register`
+ `plugins` - an array of entries to register with [await server.register(plugins, [options])](http://hapijs.com/api#-await-serverregisterplugins-options).
* each entry may be one of three alternatives:
1. A string to be `require()`d during composition.
```js
{
register: {
plugins: [ 'myplugin' ]
}
}
```
2. An object containing the `plugin` property which is a string to be `require`d during composition
```js
{
register: {
plugins: [ { plugin: 'myplugin' } ]
}
}
```
3. An object containing the `plugin` property which is the plugin object to be passed directly to `await server.register`*[]:
```js
{
register: {
plugins: [ { plugin: require('myplugin') } ]
}
}
```
* object entries may also contain the `options` property, which contains the plugin-level options passed to the plugin at registration time.
```js
{
register: {
plugins: [ { plugin: 'myplugin', options: { host: 'my-host.com' } } ]
}
}
```
* object entries may also contain override registration-options such as `routes`.
```js
{
register: {
plugins: [ { plugin: 'myplugin', routes: { prefix: '/test/' } } ]
}
}
```
+ `options` - optional registration-options object passed to `server.register()`.
+ `options` - an object containing the following `compose` options:
* `relativeTo` - a file-system path string that is used to resolve loading modules with `require`. Used in `server.cache` and `register.plugins[]`
* `preRegister` - an async function that is called prior to registering plugins with the server. The function signature is `async function (server)` where:
+ `server` - is the hapi server object.

`compose` returns the hapi server object. Call `await server.start()` to actually start the server.

### Notes

Expand All @@ -40,125 +74,76 @@ const Glue = require('glue');

const manifest = {
server: {
cache: 'redis'
cache: 'redis',
port: 8000
},
connections: [
{
port: 8000,
labels: ['web']
},
{
port: 8001,
labels: ['admin']
}
],
registrations: [
{
plugin: {
register: './assets',
register: {
plugins: [
'./awesome-plugin.js',
{
plugin: require('myplugin'),
options: {
uglify: true
}
}
},
{
plugin: './ui-user',
options: {
select: ['web']
}
},
{
plugin: {
register: './ui-admin',
},
{
plugin: './ui-user'
},
{
plugin: './ui-admin',
options: {
sessiontime: 500
}
},
options: {
select: ['admin'],
},
routes: {
prefix: '/admin'
}
}
},
{
plugin: {
register: require('./awesome-plugin.js'),
options: {
whyNot: true
}
}
},
]
]
}
};

const options = {
relativeTo: __dirname
};

Glue.compose(manifest, options, (err, server) => {

if (err) {
throw err;
}
server.start(() => {

console.log('hapi days!');
});
});
try {
const server = await Glue.compose(manifest, options);
await server.start();
console.log('hapi days!');
}
catch (err) {
console.error(err);
process.exit(1);
}
```

The above is translated into the following equivalent hapi API calls.

```javascript
'use strict';
try {
const server = Hapi.server({ cache: [{ engine: require('redis') }], port: 8000 });
const plugins = [];
const registerOptions = {};
let pluginPath;

pluginPath = Path.join(__dirname, './awesome-plugin.js');
plugins.push({ plugin: require(pluginPath) });

plugins.push({ plugin: require('myplugin'), options:{ uglify: true } });

const server = Hapi.Server({ cache: [{ engine: require('redis') }] });
server.connection({ port: 8000, labels: ['web'] });
server.connection({ port: 8001, labels: ['admin'] });
let plugin;
let pluginPath;
let pluginOptions;
let registerOptions;
pluginPath = Path.join(__dirname, './assets');
pluginOptions = { uglify: true };
plugin = { register: require(pluginPath), options: pluginOptions };
registerOptions = { };
server.register(plugin, registerOptions, (err) => {

if (err) {
throw err;
}
pluginPath = Path.join(__dirname, './ui-user');
pluginOptions = { };
plugin = { register: require(pluginPath), options: pluginOptions };
registerOptions = { select: ['web'] };
server.register(plugin, registerOptions, (err) => {
plugins.push({ plugin: require(pluginPath) });

if (err) {
throw err;
}
pluginPath = Path.join(__dirname, './ui-admin');
pluginOptions = { sessiontime: 500 };
plugin = { register: require(pluginPath), options: pluginOptions };
registerOptions = { select: ['admin'], routes: { prefix: '/admin' } };
server.register(plugin, registerOptions, (err) => {

if (err) {
throw err;
}
plugin = require('./awesome-plugin.js');
server.register(plugin, {whyNot: true}, (err) => {
pluginPath = Path.join(__dirname, './ui-admin');
plugins.push({ plugin: require(pluginPath), options: { sessiontime: 500 }, routes: { prefix: '/admin' } });

if (err) {
throw err;
}
server.start(() => {

console.log('hapi days!');
});
});
});
});
});
await server.register(plugins, registerOptions);

await server.start();
console.log('hapi days!');
}
catch (err)
console.error(err);
process.exit(1);
}
```
10 changes: 5 additions & 5 deletions README.md
Expand Up @@ -8,20 +8,20 @@ Lead Maintainer - [Chris Rempel](https://github.com/csrl)

Glue provides configuration based composition of hapi's Server object. Specifically it wraps

* `server = new Hapi.Server(Options)`
* one or more `server.connection(Options)`
* zero or more `server.register(Plugin, Options)`
* `server = Hapi.server(Options)`
* `server.register(Plugins, Options)`

calling each based on the configuration generated from the Glue manifest.

### Interface

Glue's [API](API.md) is a single function `compose` accepting a JSON `manifest` file specifying the hapi server options, connections, and registrations.
Glue's [API](API.md) is a single function `compose` accepting a JSON `manifest` specifying the hapi server options and registrations.

### hapi version dependency

Glue can support different versions of hapi. Adding support for a new version of hapi is considered a `minor` change. Removing support for a version of hapi is considered a `major` change.

By default NPM will resolve Glue's dependency on hapi using the most recent supported version of hapi. To force a specific supported hapi version for your project, include hapi in your package dependencies along side of Glue.

Glue currently supports hapi **11**, **12**, **13**, **14**, **15**, and **16**.
Glue version 5 currently only supports hapi **17**.
For support of hapi **11**, **12**, **13**, **14**, **15**, or **16** please use Glue@4.2.x .

0 comments on commit 465939b

Please sign in to comment.