import { Log } from './log' ; const bodyParser = require ( 'body-parser' ) ; const express = require ( 'express' ) ; const fs = require ( 'fs' ) ; const http = require ( 'http' ) ; const https = require ( 'https' ) ; const Redis = require ( 'ioredis' ) ; const io = require ( 'socket.io' ) ; const redisAdapter = require ( 'socket.io-redis' ) ; export class Server { type { any } public express : any ; type { object } public io : any ; param { any } options constructor ( protected options ) { } return { Promise < any > } initialize ( ) { return new Promise ( ( resolve , reject ) => { this . serverProtocol ( ) . then ( ( ) => { let host = this . options . host || '127.0.0.1' ; Log . success ( `Running at ${ host } on port ${ this . options . port }` ) ; this . configureAdapters ( ) ; this . configureSocketIdGeneration ( ) ; resolve ( this . io ) ; } , error => reject ( error ) ) ; } ) ; } return { Promise < any > } protected serverProtocol ( ) { return new Promise ( ( resolve , reject ) => { if ( this . options . protocol === 'https' ) { this . configureSecurity ( ) . then ( ( ) => { resolve ( this . buildServer ( true ) ) ; } , error => reject ( error ) ) ; } else { resolve ( this . buildServer ( false ) ) ; } } ) ; } return { Promise < any > } protected configureSecurity ( ) { return new Promise ( ( resolve , reject ) => { if ( ! this . options . ssl . certPath || ! this . options . ssl . keyPath ) { reject ( 'SSL paths are missing in server config.' ) ; } Object . assign ( this . options , { cert : fs . readFileSync ( this . options . ssl . certPath ) , key : fs . readFileSync ( this . options . ssl . keyPath ) , ca : ( this . options . ssl . caPath ) ? fs . readFileSync ( this . options . ssl . caPath ) : '' , passphrase : this . options . ssl . passphrase , } ) ; resolve ( this . options ) ; } ) ; } param { boolean } secure return { any } protected buildServer ( secure ) { this . express = express ( ) ; this . configureHeaders ( ) ; this . configureJsonBody ( ) ; let httpServer = secure ? https . createServer ( this . options , this . express ) : http . createServer ( this . express ) ; httpServer . listen ( this . options . port , this . options . host ) ; this . options . socketIoOptions = { ... this . options . socketIoOptions , ... { cors : this . options . cors , } , } ; return this . io = io ( httpServer , this . options . socketIoOptions ) ; } return { void } protected configureAdapters ( ) { if ( this . options . database . driver === 'redis' ) { let pubClient = new Redis ( this . options . database . redis ) ; let subClient = new Redis ( this . options . database . redis ) ; this . io . adapter ( redisAdapter ( { key : 'redis-adapter' , pubClient : pubClient , subClient : subClient , } ) ) ; } } return { void } protected configureSocketIdGeneration ( ) { let min = 0 ; let max = 10000000000 ; let randomNumber = ( min , max ) => Math . floor ( Math . random ( ) * ( max - min + 1 ) + min ) ; this . io . engine . generateId = req => randomNumber ( min , max ) + '.' + randomNumber ( min , max ) ; } return { void } protected configureHeaders ( ) { this . express . use ( ( req , res , next ) => { for ( let header in this . options . headers ) { res . setHeader ( header , this . options . headers [ header ] ) ; } next ( ) ; } ) ; } return { void } protected configureJsonBody ( ) { this . express . use ( bodyParser . json ( { strict : true , verify : ( req , res , buffer ) => { req . rawBody = buffer . toString ( ) ; } , } ) ) ; } }