Home Reference Source Repository

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)), []);
	}
}