From 15b5e61b875c75a8b98e59824806205fe14f1d69 Mon Sep 17 00:00:00 2001 From: Juneil Date: Tue, 28 Nov 2017 14:37:24 +0100 Subject: [PATCH 1/4] feat(socket): add possibility to use http server ext --- package-lock.json | 14 +-- src/extensions/socket-server/extension.ts | 20 +++- src/extensions/socket-server/server.ts | 52 ++++++--- .../socket-server-http-server-ext.test.ts | 107 ++++++++++++++++++ .../extensions/socket-server/rooms.test.ts | 3 +- 5 files changed, 171 insertions(+), 25 deletions(-) create mode 100644 test/integration/socket-server-http-server-ext.test.ts diff --git a/package-lock.json b/package-lock.json index 16135ee..cc99813 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@hapiness/core", - "version": "1.2.0", + "version": "1.2.2", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -2151,6 +2151,12 @@ } } }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", @@ -2162,12 +2168,6 @@ "strip-ansi": "3.0.1" } }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, "stringstream": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", diff --git a/src/extensions/socket-server/extension.ts b/src/extensions/socket-server/extension.ts index f517550..de32334 100644 --- a/src/extensions/socket-server/extension.ts +++ b/src/extensions/socket-server/extension.ts @@ -1,20 +1,21 @@ -import { CoreModule, Extension, ExtensionWithConfig, OnExtensionLoad } from '../../core/interfaces'; +import { CoreModule, Extension, ExtensionWithConfig, OnExtensionLoad, OnModuleInstantiated } from '../../core/interfaces'; import { Observable } from 'rxjs/Observable'; import { WebSocketServer } from './server'; export interface SocketConfig { - port: number; + port?: number; autoAcceptConnections?: boolean; keepaliveInterval?: number; keepaliveGracePeriod?: number; closeTimeout?: number; + useHttpExtension?: boolean; tls?: { key: Buffer; cert: Buffer; } } -export class SocketServerExt implements OnExtensionLoad { +export class SocketServerExt implements OnExtensionLoad, OnModuleInstantiated { public static setConfig(config: SocketConfig): ExtensionWithConfig { return { @@ -40,4 +41,17 @@ export class SocketServerExt implements OnExtensionLoad { value: _ })); } + + /** + * Start socket server + * + * @param {CoreModule} module + * @param {WebSocketServer} server + * @returns Observable + */ + onModuleInstantiated(module: CoreModule, server: WebSocketServer): Observable { + return Observable + .of(server) + .map(_ => _.start()); + } } diff --git a/src/extensions/socket-server/server.ts b/src/extensions/socket-server/server.ts index d221621..fa9c793 100644 --- a/src/extensions/socket-server/server.ts +++ b/src/extensions/socket-server/server.ts @@ -1,3 +1,4 @@ +import { Hapiness, HttpServerExt } from '../../'; import { Observable, Subject } from 'rxjs/Rx'; import { server, request } from 'websocket'; import { Socket } from './socket'; @@ -14,20 +15,11 @@ export class WebSocketServer { private rooms: WebSocketRooms; private secure: ((request: request) => Observable) = () => Observable.of(true); - constructor(config: SocketConfig) { - /* istanbul ignore next */ - const httpHandler = (_request, _response) => { - _response.writeHead(404); - _response.end(); - }; - if (!!config.tls) { - this.httpServer = https.createServer(config.tls, httpHandler); - } else { - this.httpServer = http.createServer(httpHandler); - } - this.httpServer.listen(config.port); - delete config.port; - const _config = Object.assign({ httpServer: this.httpServer }, config); + constructor(private config: SocketConfig) {} + + public start() { + this.httpServer = !!this.config.useHttpExtension ? this.getHttpServerExt() : this.createHttpServer(); + const _config = Object.assign({ httpServer: this.httpServer }, this.config, { port: undefined }); this.server = new server(_config); this.sockets = []; this.server.on('request', _request => { @@ -42,6 +34,38 @@ export class WebSocketServer { this.rooms = new WebSocketRooms(); } + /** + * Get Http Server Extension instance + * @FIXME Just take the first HapiJS connection for now + */ + private getHttpServerExt() { + const ext = Hapiness['extensions'].find(_ => _.token === HttpServerExt); + if (!!ext) { + return ext.value.connections[0].listener; + } else { + throw new Error('Cound not find Http Server Extension'); + } + } + + /** + * Create Http Server for websocket + * + * @returns http + */ + private createHttpServer(): http.Server | https.Server { + if (!this.config.port) { + throw new Error('WS port not provided'); + } + /* istanbul ignore next */ + const httpHandler = (_request, _response) => { + _response.writeHead(404); + _response.end(); + }; + const httpServer = !!this.config.tls ? https.createServer(this.config.tls, httpHandler) : http.createServer(httpHandler); + httpServer.listen(this.config.port); + return httpServer; + } + /** * Resquest handler * Accept the request diff --git a/test/integration/socket-server-http-server-ext.test.ts b/test/integration/socket-server-http-server-ext.test.ts new file mode 100644 index 0000000..419b710 --- /dev/null +++ b/test/integration/socket-server-http-server-ext.test.ts @@ -0,0 +1,107 @@ +import { Observable } from 'rxjs/Rx'; +import { suite, test } from 'mocha-typescript'; +import * as unit from 'unit.js'; +import { Hapiness, HapinessModule, OnStart } from '../../src/core'; +import { SocketServerExt, SocketServerService } from '../../src/extensions/socket-server'; +import { HttpServerExt } from '../../src/extensions/http-server'; + +@suite('Integration - Socket Server') +export class SocketServerIntegration { + + @test('use same http instance from HttpServerExt') + test1(done) { + + @HapinessModule({ + version: '1.0.0', + providers: [SocketServerService] + }) + class ModuleTest implements OnStart { + + constructor(private server: SocketServerService) {} + + onStart() { + this + .server + .instance() + .configure(_ => Observable.of(true)) + .subscribe( + socket => { + unit.array(this.server.instance().getSockets()) + .hasLength(1); + socket.emit('toto', 'test'); + socket.on('close', data => { + }); + socket.on('error', data => { + }); + socket.on('tata', data => { + }); + socket.on('ev', data => { + this.server.instance().broadcast('test', 'test'); + }); + socket.on('*', data => { + if (data.utf8Data === '123') { + unit.string(data.utf8Data) + .is('123'); + socket.emitBytes(new Buffer('test')); + } + }); + socket.onBytes(data => { + unit.string(data.toString()) + .is('test'); + socket.emit('obs', 'obs'); + }); + socket + .on$('FINAL') + .subscribe( + _ => { + unit.string(_).is('final'); + socket.close(); + this.server.stop().subscribe(() => done()); + } + ); + } + ); + + const W3CWebSocket = require('websocket').w3cwebsocket; + const client = new W3CWebSocket('ws://localhost:4555/'); + client.onmessage = (e) => { + if (e.data === JSON.stringify({ event: 'toto', data: 'test' })) { + client.send('{"event":"ev","data":"abc"}'); + } else if (e.data instanceof ArrayBuffer) { + client.send(e.data); + } else if (e.data === JSON.stringify({ event: 'test', data: 'test' })) { + client.send('123'); + } else { + client.send('{"event":"FINAL","data":"final"}'); + } + }; + } + } + + Hapiness.bootstrap(ModuleTest, [ + HttpServerExt.setConfig({ host: 'localhost', port: 4555 }), + SocketServerExt.setConfig({ useHttpExtension: true }) + ]); + } + + @test('use same http instance from HttpServerExt - no HttpServerExt instance') + test2(done) { + + @HapinessModule({ + version: '1.0.0' + }) + class ModuleTest { + } + + Hapiness.bootstrap(ModuleTest, [ + SocketServerExt.setConfig({ useHttpExtension: true }) + ]).catch(_ => { + unit + .object(_) + .isInstanceOf(Error) + .hasProperty('message', 'Cound not find Http Server Extension'); + done(); + }); + } + +} diff --git a/test/unit/extensions/socket-server/rooms.test.ts b/test/unit/extensions/socket-server/rooms.test.ts index e221043..3cbbfb7 100644 --- a/test/unit/extensions/socket-server/rooms.test.ts +++ b/test/unit/extensions/socket-server/rooms.test.ts @@ -68,7 +68,8 @@ export class WebSocketRoomsTestSuite { connection2.sendUTF = () => {}; unit.stub(connection1, 'sendUTF'); unit.stub(connection2, 'sendUTF'); - const webSocketServer = new WebSocketServer({ port: 0 }); + const webSocketServer = new WebSocketServer({ port: 2000 }); + webSocketServer.start(); unit.function(webSocketServer.to); const instance = webSocketServer['rooms']; const socket1 = new Socket({}, connection1, instance); From 7f30004e582daeec28bd8beafee467eb94d27655 Mon Sep 17 00:00:00 2001 From: Juneil Date: Thu, 30 Nov 2017 10:49:26 +0100 Subject: [PATCH 2/4] feat(connections): handle multiple connections --- src/extensions/http-server/decorators.ts | 4 +- src/extensions/http-server/extension.ts | 101 +++++++++++++---- src/extensions/http-server/interfaces.ts | 37 ++++-- src/extensions/http-server/lifecycle.ts | 22 ++++ src/extensions/http-server/route.ts | 1 + src/index.ts | 2 +- .../http-server-multiple-connections.test.ts | 106 ++++++++++++++++++ .../extensions/http-server/extension.test.ts | 2 +- 8 files changed, 240 insertions(+), 35 deletions(-) create mode 100644 test/integration/http-server-multiple-connections.test.ts diff --git a/src/extensions/http-server/decorators.ts b/src/extensions/http-server/decorators.ts index 8416c12..6854464 100644 --- a/src/extensions/http-server/decorators.ts +++ b/src/extensions/http-server/decorators.ts @@ -6,12 +6,14 @@ export interface Route { method: string | string[]; config?: RouteConfig; providers?: Array|any>; + labels?: string | string[]; } export const Route: CoreDecorator = createDecorator('Route', { path: undefined, method: undefined, config: undefined, - providers: undefined + providers: undefined, + labels: undefined }); export interface Lifecycle { diff --git a/src/extensions/http-server/extension.ts b/src/extensions/http-server/extension.ts index 1e1e223..f174ca4 100644 --- a/src/extensions/http-server/extension.ts +++ b/src/extensions/http-server/extension.ts @@ -9,7 +9,7 @@ import { Type } from '../../core/decorators'; import { enumByMethod, LifecycleComponentEnum } from './enums'; import { LifecycleManager } from './lifecycle'; import { RouteBuilder } from './route'; -import { CoreRoute, HapiConfig, HapinessHTTPHandlerResponse } from './interfaces'; +import { ConnectionOptions, CoreRoute, HapiConfig, HTTPHandlerResponse } from './interfaces'; import { Observable } from 'rxjs'; import { RouteConfiguration, Server, Request, ReplyNoContinue, ReplyWithContinue } from 'hapi'; @@ -32,7 +32,12 @@ export class HttpServerExt implements OnExtensionLoad, OnModuleInstantiated { onExtensionLoad(module: CoreModule, config: HapiConfig): Observable { return Observable .of(new Server(config.options)) - .do(_ => _.connection(Object.assign({}, config, { options: undefined }))) + .flatMap(server => Observable + .of(Object.assign({}, config, { options: undefined })) + .map(_ => this.formatConnections(_)) + .do(_ => _.forEach(connection => server.connection(connection))) + .map(_ => server) + ) .flatMap(server => Observable .of({ @@ -63,6 +68,23 @@ export class HttpServerExt implements OnExtensionLoad, OnModuleInstantiated { .flatMap(_ => server.start()); } + /** + * Format the config provided + * to a list of ConnectionOptions + * + * @param {HapiConfig} config + * @returns ConnectionOptions + */ + private formatConnections(config: HapiConfig): ConnectionOptions[] { + return [] + .concat(!!(config).connections ? + (config).connections : + { host: (config).host, port: (config).port } + ) + .filter(_ => !!_) + .map(_ => _); + } + /** * Register a HapiJS Plugin * @@ -71,36 +93,50 @@ export class HttpServerExt implements OnExtensionLoad, OnModuleInstantiated { * @returns Observable */ private registerPlugin(module: CoreModule, server: Server): Observable { - const register: any = (s, o, n) => n(); - register.attributes = { - name: module.name, - version: module.version - }; - return Observable - .fromPromise(server.register(register)) - .flatMap(_ => this.addRoutes(module, server)); + return this + .buildRoutes(module) + .flatMap(routes => Observable + .of(this.registerHandler(routes)) + .do(_ => _.attributes = { name: module.name, version: module.version }) + .flatMap(_ => Observable + .fromPromise(server.register(_)) + .map(__ => routes) + ) + ); } /** * Add routes from CoreModule * - * @param {CoreModule} module - * @param {Server} server + * @param {CoreRoute[]} module * @returns Observable */ - private addRoutes(module: CoreModule, server: Server): Observable { - return Observable - .from(RouteBuilder.buildRoutes(module)) - .do(_ => - server - .route({ + private registerHandler(routes: CoreRoute[] = []): (s, o, n) => void { + return (server: 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 + */ + private buildRoutes(module: CoreModule): Observable { + return Observable + .from(RouteBuilder.buildRoutes(module)) .toArray(); } @@ -135,7 +171,13 @@ export class HttpServerExt implements OnExtensionLoad, OnModuleInstantiated { ); } - private formatResponse(data: any): HapinessHTTPHandlerResponse { + /** + * Format response to HTTPHandlerResponse object + * + * @param {any} data + * @returns HTTPHandlerResponse + */ + private formatResponse(data: any): HTTPHandlerResponse { return { statusCode: !!data ? data.statusCode || 200 : 200, headers: !!data ? data.headers || {} : {}, @@ -143,6 +185,12 @@ export class HttpServerExt implements OnExtensionLoad, OnModuleInstantiated { }; } + /** + * Check of response is not empty + * + * @param {any} response + * @returns boolean + */ private isValid(response: any): boolean { return typeof(response) !== 'undefined' && response !== null; } @@ -172,6 +220,17 @@ export class HttpServerExt implements OnExtensionLoad, OnModuleInstantiated { .map(_ => module); } + /** + * Lifecycle Event Handler + * Instantiate the Lifecycle component + * And trigger the hook + * + * @param {Type} lifecycle + * @param {CoreModule} module + * @param {Request} request + * @param {ReplyWithContinue} reply + * @returns Observable + */ private eventHandler(lifecycle: Type, module: CoreModule, request: Request, reply: ReplyWithContinue): Observable { return Observable .of(lifecycle) diff --git a/src/extensions/http-server/interfaces.ts b/src/extensions/http-server/interfaces.ts index 5a56c29..458cf97 100644 --- a/src/extensions/http-server/interfaces.ts +++ b/src/extensions/http-server/interfaces.ts @@ -1,13 +1,27 @@ import { CoreModule, CoreProvide } from '../../core/interfaces'; import { Type } from '../../core/decorators'; -import { Request, ReplyWithContinue, ReplyNoContinue, ServerOptions, RouteAdditionalConfigurationOptions } from 'hapi'; import { Observable } from 'rxjs'; - -export interface HapiConfig { - host: string; +import { + Request, + ReplyWithContinue, + ReplyNoContinue, + ServerOptions, + RouteAdditionalConfigurationOptions, + ServerConnectionOptions +} from 'hapi'; + +export interface BaseHapiConfig { + host?: string; port: number; options?: ServerOptions } +export interface ExtendedHapiConfig { + connections: ConnectionOptions[] + options?: ServerOptions +} +export type HapiConfig = BaseHapiConfig | ExtendedHapiConfig; + +export interface ConnectionOptions extends ServerConnectionOptions {} export interface RouteConfig extends RouteAdditionalConfigurationOptions {} @@ -22,9 +36,10 @@ export interface CoreRoute { module: CoreModule; providers?: CoreProvide[]; config?: RouteConfig; + labels?: string | string[]; } -export interface HapinessHTTPHandlerResponse { +export interface HTTPHandlerResponse { response: any; statusCode?: number; headers?: { [key: string]: string } @@ -37,7 +52,7 @@ export interface HapinessHTTPHandlerResponse { * @returns void | Observable */ export interface OnGet { - onGet(request: Request, reply?: ReplyNoContinue): void | Observable; + onGet(request: Request, reply?: ReplyNoContinue): void | Observable; } /** @@ -47,7 +62,7 @@ export interface OnGet { * @returns void | Observable */ export interface OnPost { - onPost(request: Request, reply?: ReplyNoContinue): void | Observable; + onPost(request: Request, reply?: ReplyNoContinue): void | Observable; } /** @@ -58,7 +73,7 @@ export interface OnPost { * @returns void | Observable */ export interface OnPut { - onPut(request: Request, reply?: ReplyNoContinue): void | Observable; + onPut(request: Request, reply?: ReplyNoContinue): void | Observable; } /** @@ -69,7 +84,7 @@ export interface OnPut { * @returns void | Observable */ export interface OnPatch { - onPatch(request: Request, reply?: ReplyNoContinue): void | Observable; + onPatch(request: Request, reply?: ReplyNoContinue): void | Observable; } /** @@ -80,7 +95,7 @@ export interface OnPatch { * @returns void | Observable */ export interface OnOptions { - onOptions(request: Request, reply?: ReplyNoContinue): void | Observable; + onOptions(request: Request, reply?: ReplyNoContinue): void | Observable; } /** @@ -91,7 +106,7 @@ export interface OnOptions { * @returns void | Observable */ export interface OnDelete { - onDelete(request: Request, reply?: ReplyNoContinue): void | Observable; + onDelete(request: Request, reply?: ReplyNoContinue): void | Observable; } /** diff --git a/src/extensions/http-server/lifecycle.ts b/src/extensions/http-server/lifecycle.ts index 5ce0b59..51a8701 100644 --- a/src/extensions/http-server/lifecycle.ts +++ b/src/extensions/http-server/lifecycle.ts @@ -96,11 +96,33 @@ export class LifecycleManager { * @returns CoreRoute */ private static findRoute(request: Request, routes: CoreRoute[]): CoreRoute { + const labels = this.arrayify(request.connection.settings.labels); return routes .find(r => ((r.method === request.route.method || r.method.indexOf(request.route.method) > -1) && + (this.isRightLabels(labels, this.arrayify(r.labels))) && r.path === request.route.path)); } + /** + * Make sure to match the right route + * with the labels + * + * @param {string[]=[]} labels + * @param {string[]=[]} routeLabels + * @returns boolean + */ + private static isRightLabels(labels: string[] = [], routeLabels: string[] = []): boolean { + if (labels.length === 0 || routeLabels.length === 0) { + return true; + } else { + return routeLabels.some(_ => labels.indexOf(_) > -1); + } + } + + private static arrayify(data: any): any[] { + return [].concat(data).filter(_ => !!_); + } + /** * Find the route and call * the hook if the route component diff --git a/src/extensions/http-server/route.ts b/src/extensions/http-server/route.ts index 0107aa1..bcb6cfa 100644 --- a/src/extensions/http-server/route.ts +++ b/src/extensions/http-server/route.ts @@ -84,6 +84,7 @@ export class RouteBuilder { config: _.data.config, path: _.data.path, method: _.methods, + labels: _.data.labels, providers: [] .concat(_.data.providers) .filter(p => !!p) diff --git a/src/index.ts b/src/index.ts index 8e7012a..757801f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -29,7 +29,7 @@ export { export { HttpServerExt, HapiConfig, Route, Lifecycle, HttpRequestInfo, OnEvent, OnGet, OnDelete, OnOptions, OnPatch, OnPost, OnPut, OnPreAuth, OnPostAuth, OnPreHandler, OnPostHandler, OnPreResponse, Request, - ReplyWithContinue, ReplyNoContinue, Server, HttpServerService + ReplyWithContinue, ReplyNoContinue, Server, HttpServerService, HTTPHandlerResponse, ConnectionOptions } from './extensions/http-server'; export { diff --git a/test/integration/http-server-multiple-connections.test.ts b/test/integration/http-server-multiple-connections.test.ts new file mode 100644 index 0000000..08da42e --- /dev/null +++ b/test/integration/http-server-multiple-connections.test.ts @@ -0,0 +1,106 @@ +import { suite, test } from 'mocha-typescript'; +import * as unit from 'unit.js'; +import { Hapiness, HapinessModule, OnStart } from '../../src/core'; +import { HttpServerExt, HttpServerService, Route } from '../../src/extensions/http-server'; + +@suite('Integration - Http Server Multiple Connections') +export class SocketServerRoomIntegration { + + @test('should have 2 ports') + test1(done) { + @HapinessModule({ + version: '1.0.0', + providers: [ HttpServerService ] + }) + class ModuleTest implements OnStart { + + constructor(private server: HttpServerService) {} + + onStart() { + this + .server + .instance() + .connections + .forEach(_ => { _.inject('/', res => unit.number(res.statusCode).is(404)); }); + + this.server.stop().subscribe(_ => done()); + } + } + + Hapiness.bootstrap(ModuleTest, [ + HttpServerExt.setConfig({ + connections: [ + { port: 5555, labels: 'one' }, + { port: 6666 } + ] + }) + ]); + } + + @test('should have 2 ports and have one route each') + test2(done) { + + @Route({ + method: 'get', + path: '/', + labels: 'one' + }) + class Route1 { + onGet() { + return 'ok_1'; + } + } + + @Route({ + method: 'get', + path: '/', + labels: 'two' + }) + class Route2 { + onGet() { + return 'ok_2'; + } + } + + + @HapinessModule({ + version: '1.0.0', + providers: [ HttpServerService ], + declarations: [ Route1, Route2 ] + }) + class ModuleTest implements OnStart { + + constructor(private server: HttpServerService) {} + + onStart() { + this + .server + .instance() + .select('one') + .connections[0] + .inject('/', res => { + unit.string(res.result).is('ok_1'); + this + .server + .instance() + .select('two') + .connections[0] + .inject('/', _res => { + unit.string(_res.result).is('ok_2'); + this.server.stop().subscribe(_ => done()); + }); + }); + } + } + + Hapiness.bootstrap(ModuleTest, [ + HttpServerExt.setConfig({ + connections: [ + { port: 5555, labels: 'one' }, + { port: 6666, labels: 'two' } + ] + }) + ]); + } + +} diff --git a/test/unit/extensions/http-server/extension.test.ts b/test/unit/extensions/http-server/extension.test.ts index b04a0b9..2d18a2f 100644 --- a/test/unit/extensions/http-server/extension.test.ts +++ b/test/unit/extensions/http-server/extension.test.ts @@ -18,7 +18,7 @@ export class ModuleTestSuite { connection(config) { unit .object(config) - .is({ options: undefined }); + .is({ host: undefined, port: undefined }); } } From 0b76384f7fd4bd0ffdc4653c866429f2b17ad1d9 Mon Sep 17 00:00:00 2001 From: Juneil Date: Thu, 30 Nov 2017 11:01:54 +0100 Subject: [PATCH 3/4] doc(README): some docs + bump version --- README.md | 8 +++- package-lock.json | 28 +++++++------- package.json | 10 ++--- src/extensions/http-server/README.md | 16 +++++++- yarn.lock | 56 ++++++++++------------------ 5 files changed, 59 insertions(+), 59 deletions(-) diff --git a/README.md b/README.md index f6f480a..2d9db5e 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,7 @@ $ yarn add @hapiness/core rxjs ```javascript "dependencies": { - "@hapiness/core": "^1.2.2", + "@hapiness/core": "^1.3.0", //... } //... @@ -95,7 +95,7 @@ $ yarn add @hapiness/core rxjs ### Use Hapiness API -Actually, we're in : **v1.2.1** +Actually, we're in : **v1.3.0** See [API](https://github.com/hapinessjs/hapiness/blob/master/API.md) Reference to know what's already implemented. @@ -115,6 +115,10 @@ To set up your development environment: [Back to top](#table-of-contents) ## Change History +* v1.3.0 (2017-11-30) + * Option that allow WS Server Ext to share Http Server Ext port + * Handle HapiJS connections system to listen multiple ports + * Documentation * v1.2.2 (2017-11-20) * Export `createDecorator()`, `extractMetadata()`, `extractMetadataByDecorator`, `errorHandler()` methods and `DependencyInjection` class * Documentation diff --git a/package-lock.json b/package-lock.json index cc99813..5d459c4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@hapiness/core", - "version": "1.2.2", + "version": "1.3.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -33,7 +33,7 @@ "requires": { "@types/boom": "4.3.8", "@types/catbox": "7.1.4", - "@types/joi": "13.0.0", + "@types/joi": "13.0.1", "@types/mimos": "3.0.1", "@types/node": "8.0.53", "@types/podium": "1.0.0", @@ -46,9 +46,9 @@ "integrity": "sha1-0ZgtSPsNKg5dfp2Rg4Jk2OQo0zc=" }, "@types/joi": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/@types/joi/-/joi-13.0.0.tgz", - "integrity": "sha512-NME7RLjZDfOM9Ns7zAqRFcTQTNmi3Yg8cCfSAMOSGGlEii0Hyo6wQ8X8gYaytYAcjyRCuEBjG7NDC/yyLr5f5w==" + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/@types/joi/-/joi-13.0.1.tgz", + "integrity": "sha512-3sqbI3R1cb88fyL5N7JLL0pbNz4lO5+idWNVjVHMdQ4cMIjQYrGIlfKTyB9ViGk8pcaNSjAw1AmHzW9ONnyekw==" }, "@types/mime-db": { "version": "1.27.0", @@ -82,9 +82,9 @@ } }, "@types/websocket": { - "version": "0.0.34", - "resolved": "https://registry.npmjs.org/@types/websocket/-/websocket-0.0.34.tgz", - "integrity": "sha512-cvN32rSoC4aXpXHG2Gf8/f8/gtyA7PmE38E3ENsMymFPgoG8xD/kH/KAVhTINCZTPqmgaWN86c1MitMEsuHjnQ==", + "version": "0.0.35", + "resolved": "https://registry.npmjs.org/@types/websocket/-/websocket-0.0.35.tgz", + "integrity": "sha512-HaG4p0g1T6qQDgQNPMEeDNTbK2V7L54QsVecMlAYFRK6IHsusBknZ+vQMGAeN8mOTNaCqb0pXZQLAZu7kdifWg==", "requires": { "@types/node": "8.0.53" } @@ -995,9 +995,9 @@ "dev": true }, "injection-js": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/injection-js/-/injection-js-2.2.0.tgz", - "integrity": "sha512-23LPrLixBdX6Cy4j++zrFp6273jniw85onuhxztZaIag+olM9oFzXt/phQRlpff5U+X5jTq+o2lw+FVmkqgdFQ==" + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/injection-js/-/injection-js-2.2.1.tgz", + "integrity": "sha512-zHI+E+dM0PXix5FFTO1Y4/UOyAzE7zG1l/QwAn4jchTThOoBq+UYRFK4AVG7lQgFL+go62SbrzSsjXy9DFEZUg==" }, "invariant": { "version": "2.2.2", @@ -2518,9 +2518,9 @@ } }, "typescript": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.6.1.tgz", - "integrity": "sha1-7znN6ierrAtQAkLWcmq5DgyEZjE=", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.6.2.tgz", + "integrity": "sha1-PFtv1/beCRQmkCfwPAlGdY92c6Q=", "dev": true }, "uglify-js": { diff --git a/package.json b/package.json index 2d3395f..dc21e27 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hapiness/core", - "version": "1.2.2", + "version": "1.3.0", "description": "Project to have a HapiJS (https://hapijs.com/) based framework to create easier NodeJS back-end with some awesome features", "main": "commonjs/index.js", "types": "index.d.ts", @@ -75,12 +75,12 @@ "dependencies": { "@types/hapi": "^16.1.11", "@types/hoek": "^4.1.3", - "@types/joi": "^13.0.0", + "@types/joi": "^13.0.1", "@types/node": "^8.0.53", - "@types/websocket": "^0.0.34", + "@types/websocket": "^0.0.35", "debug": "^3.1.0", "hapi": "^16.6.2", - "injection-js": "^2.2.0", + "injection-js": "^2.2.1", "reflect-metadata": "^0.1.10", "websocket": "^1.0.25" }, @@ -95,7 +95,7 @@ "rxjs": "^5.5.2", "ts-node": "^3.3.0", "tslint": "^5.8.0", - "typescript": "^2.6.1", + "typescript": "^2.6.2", "unit.js": "^2.0.0" }, "engines": { diff --git a/src/extensions/http-server/README.md b/src/extensions/http-server/README.md index 13a8858..9a9b727 100644 --- a/src/extensions/http-server/README.md +++ b/src/extensions/http-server/README.md @@ -12,6 +12,19 @@ The extension is based on HapiJS ); ``` +``` +{ + host: string + port: number + options?: ServerOptions +} +//or +{ + connections: ConnectionOptions[] + options?: ServerOptions +} +``` + Configuration - [HapiJS Connection options](https://hapijs.com/api#serverconnectionoptions) ## Extension provider @@ -37,6 +50,7 @@ Declare HTTP routes - `method` - can be an array, values: (get, post, put, delete, patch, options) - `config` - partially implemented, see [HapiJS Route config](https://hapijs.com/api#route-configuration) - `providers` - Providers to add in the request DI, it means at each request a new instance of the provider will be created + - `labels`- `string | string[]` Used to attach a route to a connection for multiple connections - interfaces - see request and reply on [HapiJS Docs](https://hapijs.com/api#requests) @@ -82,7 +96,7 @@ Request lifecycle component - `event` - request lifecycle event, see [HapiJS Request lifecycle](https://hapijs.com/api#request-lifecycle) events: (onPreAuth, onPostAuth, onPreHandler, onPostHandler, onPreResponse) - + - interfaces - see request and reply on [HapiJS Docs](https://hapijs.com/api#requests) diff --git a/yarn.lock b/yarn.lock index df674f5..80d1009 100644 --- a/yarn.lock +++ b/yarn.lock @@ -34,10 +34,14 @@ version "4.1.3" resolved "https://registry.yarnpkg.com/@types/hoek/-/hoek-4.1.3.tgz#d1982d48fb0d2a0e5d7e9d91838264d8e428d337" -"@types/joi@*", "@types/joi@^13.0.0": +"@types/joi@*": version "13.0.0" resolved "https://registry.yarnpkg.com/@types/joi/-/joi-13.0.0.tgz#63c066d901e87f464fa075d02bf2f390344241fc" +"@types/joi@^13.0.1": + version "13.0.1" + resolved "https://registry.yarnpkg.com/@types/joi/-/joi-13.0.1.tgz#e6b01f9cf403845c86ffa43243a9c111884219c7" + "@types/mime-db@*": version "1.27.0" resolved "https://registry.yarnpkg.com/@types/mime-db/-/mime-db-1.27.0.tgz#9bc014a1fd1fdf47649c1a54c6dd7966b8284792" @@ -62,17 +66,13 @@ dependencies: "@types/node" "*" -"@types/websocket@^0.0.34": - version "0.0.34" - resolved "https://registry.yarnpkg.com/@types/websocket/-/websocket-0.0.34.tgz#25596764cec885eda070fdb6d19cd76fe582747c" +"@types/websocket@^0.0.35": + version "0.0.35" + resolved "https://registry.yarnpkg.com/@types/websocket/-/websocket-0.0.35.tgz#7734476e187660974d1d308213547bb3e21fd4b6" dependencies: "@types/node" "*" -abbrev@1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - -abbrev@1.0.x: +abbrev@1, abbrev@1.0.x: version "1.0.9" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" @@ -491,14 +491,10 @@ detect-indent@^4.0.0: dependencies: repeating "^2.0.0" -diff@3.3.1: +diff@3.3.1, diff@^3.1.0, diff@^3.2.0: version "3.3.1" resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.1.tgz#aa8567a6eed03c531fc89d3f711cd0e5259dec75" -diff@^3.1.0, diff@^3.2.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.4.0.tgz#b1d85507daf3964828de54b37d0d73ba67dda56c" - ecc-jsbn@~0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" @@ -748,9 +744,9 @@ inherits@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" -injection-js@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/injection-js/-/injection-js-2.2.0.tgz#25f3b81a94cf528c7a3679230b91e9d41e910ac4" +injection-js@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/injection-js/-/injection-js-2.2.1.tgz#a8d6a085b2f0b8d8650f6f4487f6abb8cc0d67ce" invariant@^2.2.2: version "2.2.2" @@ -1079,7 +1075,7 @@ minimatch@^3.0.3, minimatch@^3.0.4: dependencies: brace-expansion "^1.1.7" -minimist@0.0.8: +minimist@0.0.8, minimist@~0.0.1: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" @@ -1087,10 +1083,6 @@ minimist@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" -minimist@~0.0.1: - version "0.0.10" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" - mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" @@ -1384,14 +1376,10 @@ safe-buffer@^5.0.1, safe-buffer@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" -samsam@1.1.2: +samsam@1.1.2, samsam@~1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.1.2.tgz#bec11fdc83a9fda063401210e40176c3024d1567" -samsam@~1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.1.3.tgz#9f5087419b4d091f232571e7fa52e90b0f552621" - "semver@2 || 3 || 4 || 5", semver@^5.3.0: version "5.4.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" @@ -1584,7 +1572,7 @@ superagent@~0.21.0: methods "1.x" superagent "~0.21.0" -supports-color@4.4.0: +supports-color@4.4.0, supports-color@^4.0.0: version "4.4.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.4.0.tgz#883f7ddabc165142b2a61427f3352ded195d1a3e" dependencies: @@ -1600,12 +1588,6 @@ supports-color@^3.1.2: dependencies: has-flag "^1.0.0" -supports-color@^4.0.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b" - dependencies: - has-flag "^2.0.0" - symbol-observable@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.4.tgz#29bf615d4aa7121bdd898b22d4b3f9bc4e2aa03d" @@ -1694,9 +1676,9 @@ typedarray-to-buffer@^3.1.2: dependencies: is-typedarray "^1.0.0" -typescript@^2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.6.1.tgz#ef39cdea27abac0b500242d6726ab90e0c846631" +typescript@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.6.2.tgz#3c5b6fd7f6de0914269027f03c0946758f7673a4" uglify-js@^2.6: version "2.8.29" From d469cad07d0a05f8991c11248817cbd0b4e9c54c Mon Sep 17 00:00:00 2001 From: Juneil Date: Thu, 30 Nov 2017 14:54:06 +0100 Subject: [PATCH 4/4] fix(connections): simple connection coudnt provide full config --- src/extensions/http-server/extension.ts | 2 +- test/unit/extensions/http-server/extension.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/extensions/http-server/extension.ts b/src/extensions/http-server/extension.ts index f174ca4..f7fade7 100644 --- a/src/extensions/http-server/extension.ts +++ b/src/extensions/http-server/extension.ts @@ -79,7 +79,7 @@ export class HttpServerExt implements OnExtensionLoad, OnModuleInstantiated { return [] .concat(!!(config).connections ? (config).connections : - { host: (config).host, port: (config).port } + config ) .filter(_ => !!_) .map(_ => _); diff --git a/test/unit/extensions/http-server/extension.test.ts b/test/unit/extensions/http-server/extension.test.ts index 2d18a2f..b04a0b9 100644 --- a/test/unit/extensions/http-server/extension.test.ts +++ b/test/unit/extensions/http-server/extension.test.ts @@ -18,7 +18,7 @@ export class ModuleTestSuite { connection(config) { unit .object(config) - .is({ host: undefined, port: undefined }); + .is({ options: undefined }); } }