src/components/server.js
import Hapi from 'hapi'
import good from 'good'
import goodConsole from 'good-console'
import {Endpoint} from './endpoint'
function createServer(endpoints, hapiConfig) {
const server = new Hapi.Server(hapiConfig);
server.connection({port: 3000});
endpoints.forEach(endpoint => endpoint.routes.forEach(route => {
server.route(route);
}));
return server;
}
const defaultOptions = {
connections: {
router: {
stripTrailingSlash: true
}
}
};
/**
* This component is responsible for configuring and controlling the test-rest server.
*/
export class RestTestServer {
_serverConfig;
_hapiConfig;
_endpoints;
_server = null;
/**
* Creates a new instance of RestTestServer.
* @param {ServerConfig} serverConfig The server configuration object.
* @param {Object} [hapiConfig] Optional configuration for the underlying Hapi-server.
* See http://hapijs.com/api#new-serveroptions for more information.
*/
constructor(serverConfig, hapiConfig = {}) {
if (serverConfig === undefined) throw new Error('Missing required configuration object.');
this._serverConfig = serverConfig;
this._hapiConfig = hapiConfig;
this._endpoints = this._serverConfig.routes.map(endpoint =>
new Endpoint({
identifierKey: this._serverConfig.identifierKey,
identifierFunc: this._serverConfig.identifierFunc,
...endpoint
}));
}
/**
* Starts the server.
* @param {Function} [callback] An optional callback that will be executed after a successful startup.
*/
start(callback) {
if (this._server !== null) throw new Error('Server already running.');
this._server = createServer(this._endpoints, Object.assign({}, defaultOptions, this._hapiConfig));
this._server.register({
register: good,
options: {
opsInterval: 1000,
reporters: [{
reporter: goodConsole,
events: {log: '*', request: '*', response: '*', error: '*'}
}]
}
},
err => {
if (err) throw err;
this._server.start(() => {
console.log('REST API Test Server listening on ' + this._server.info.uri);
if (callback !== undefined) callback();
})
});
}
/**
* Stops the server.
* @param {Function} [callback] An optional callback that will be executed after a successful halt.
*/
stop(callback) {
this._server.stop({timeout: 0}, () => {
this._server = null;
if (callback !== undefined) callback();
});
}
/**
* Restarts the server.
* @param {Function} [callback] An optional callback that will be executed after a successful restart.
*/
restart(callback) {
this.stop(() => this.start(callback));
}
/**
* Returns all the endpoints configured for the server.
* @type {Array<Endpoint>}
*/
get endpoints() {
return this._endpoints;
}
/**
* Returns all endpoint and nested endpoints generated routes as an array.
* Note that to ensure routing the array returned is from bottom-up.
* @type {Array<T>}
*/
get routes() {
return this._endpoints.reduce(((result, endpoint) => result.concat(endpoint.routes)), []);
}
}