@hapiness/core
Version:
Project to have a HapiJS (https://hapijs.com/) based framework to create easier NodeJS back-end with some awesome features
226 lines • 7.23 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const di_1 = require("../../core/di");
const hook_1 = require("../../core/hook");
const metadata_1 = require("../../core/metadata");
const module_1 = require("../../core/module");
const hapiness_1 = require("../../core/hapiness");
const enums_1 = require("./enums");
const lifecycle_1 = require("./lifecycle");
const route_1 = require("./route");
const rxjs_1 = require("rxjs");
const hapi_1 = require("hapi");
const core_1 = require("../../core");
class HttpServerExt {
static setConfig(config) {
return {
token: HttpServerExt,
config
};
}
/**
* Initialize HapiJS Server
*
* @param {CoreModule} module
* @param {HapiConfig} config
* @returns Observable
*/
onExtensionLoad(module, config) {
return rxjs_1.Observable
.of(new hapi_1.Server(config.options))
.flatMap(server => rxjs_1.Observable
.of(Object.assign({}, config, { options: undefined }))
.map(_ => this.formatConnections(_))
.do(_ => _.forEach(connection => server.connection(connection)))
.map(_ => server))
.flatMap(server => rxjs_1.Observable
.of({
instance: this,
token: HttpServerExt,
value: server
}));
}
/**
* Build Lifecycle components
* Add routes by modules
* Add Lifecycle handlers
* Start HapiJS Server
*
* @param {CoreModule} module
* @param {Server} server
* @returns Observable
*/
onModuleInstantiated(module, server) {
return rxjs_1.Observable
.from(module_1.ModuleManager.getModules(module))
.flatMap(_ => this.instantiateLifecycle(_, server))
.flatMap(_ => this.registerPlugin(_, server))
.reduce((a, c) => a.concat(c), [])
.do(_ => lifecycle_1.LifecycleManager.routeLifecycle(server, _))
.flatMap(_ => server.start());
}
/**
* Shutdown HapiJS server extension
*
* @param {CoreModule} module
* @param {Server} server
* @returns ExtensionShutdown
*/
onShutdown(module, server) {
return {
priority: core_1.ExtensionShutdownPriority.IMPORTANT,
resolver: rxjs_1.Observable.fromPromise(server.stop())
};
}
/**
* Format the config provided
* to a list of ConnectionOptions
*
* @param {HapiConfig} config
* @returns ConnectionOptions
*/
formatConnections(config) {
return []
.concat(!!config.connections ?
config.connections :
config)
.filter(_ => !!_)
.map(_ => _);
}
/**
* Register a HapiJS Plugin
*
* @param {CoreModule} module
* @param {Server} server
* @returns Observable
*/
registerPlugin(module, server) {
return this
.buildRoutes(module)
.filter(_ => !!_ && _.length > 0)
.flatMap(routes => rxjs_1.Observable
.of(this.registerHandler(routes))
.do(_ => _.attributes = { name: module.name, version: module.version })
.flatMap(_ => rxjs_1.Observable
.fromPromise(server.register(_))
.map(__ => routes)))
.defaultIfEmpty([]);
}
/**
* Add routes from CoreModule
*
* @param {CoreRoute[]} module
* @returns Observable
*/
registerHandler(routes = []) {
return (server, options, next) => {
routes
.forEach(_ => {
const _server = !!_.labels ? server.select(_.labels) : server;
_server.route({
method: _.method,
path: _.path,
config: Object.assign({
handler: (request, reply) => this.httpHandler(request, reply, _)
}, _.config)
});
});
next();
};
}
/**
* Build CoreRoute based on a module
*
* @param {CoreModule} module
* @returns Observable
*/
buildRoutes(module) {
return rxjs_1.Observable
.from(route_1.RouteBuilder.buildRoutes(module))
.toArray();
}
/**
* Trigger the http handler hook
* Reply automatically
*
* @param {Request} request
* @param {ReplyNoContinue} reply
* @param {CoreRoute} route
* @returns void
*/
httpHandler(request, reply, route) {
hook_1.HookManager
.triggerHook(enums_1.enumByMethod(request.method).toString(), route.token, request['_hapinessRoute'], [request, reply])
.map(_ => this.formatResponse(_))
.subscribe(_ => {
const repl = reply(_.response)
.code(this.isValid(_.response) ? _.statusCode : 204);
repl.headers = Object.assign(_.headers, repl.headers);
}, _ => {
hapiness_1.errorHandler(_, request);
reply(_);
});
}
/**
* Format response to HTTPHandlerResponse object
*
* @param {any} data
* @returns HTTPHandlerResponse
*/
formatResponse(data) {
return {
statusCode: !!data ? data.statusCode || 200 : 200,
headers: !!data ? data.headers || {} : {},
response: !!data ? data.response || data : data
};
}
/**
* Check of response is not empty
*
* @param {any} response
* @returns boolean
*/
isValid(response) {
return typeof (response) !== 'undefined' && response !== null;
}
/**
* Initialize and instantiate lifecycle components
*
* @param {CoreModule} module
* @param {Server} server
*/
instantiateLifecycle(module, server) {
return rxjs_1.Observable
.from([].concat(module.declarations))
.filter(_ => !!_ && !!metadata_1.extractMetadataByDecorator(_, 'Lifecycle'))
.map(_ => ({ metadata: metadata_1.extractMetadataByDecorator(_, 'Lifecycle'), token: _ }))
.do(_ => server.ext(_.metadata.event, (request, reply) => {
this
.eventHandler(_.token, module, request, reply)
.subscribe(() => { }, err => hapiness_1.errorHandler(err));
}))
.toArray()
.map(_ => module);
}
/**
* Lifecycle Event Handler
* Instantiate the Lifecycle component
* And trigger the hook
*
* @param {Type<any>} lifecycle
* @param {CoreModule} module
* @param {Request} request
* @param {ReplyWithContinue} reply
* @returns Observable
*/
eventHandler(lifecycle, module, request, reply) {
return rxjs_1.Observable
.of(lifecycle)
.flatMap(lc => di_1.DependencyInjection
.instantiateComponent(lc, module.di)
.flatMap(_ => hook_1.HookManager
.triggerHook(enums_1.LifecycleComponentEnum.OnEvent.toString(), lc, _, [request, reply])));
}
}
exports.HttpServerExt = HttpServerExt;
//# sourceMappingURL=extension.js.map