import * as express from 'express' ; import * as morgan from 'morgan' ; import * as helmet from 'helmet' ; import * as bodyParser from 'body-parser' ; import * as hpp from 'hpp' ; import * as cors from 'cors' ; import * as compress from 'compression' ; import * as http from 'http' ; import { defaultRoutes , proxyRoutes , discoverRoute } from '../router' ; export const start = async ( options ) : Promise < { server : http . Server ; } > => { if ( ! options . repo ) { Promise . reject ( new Error ( 'The server must be started with a connected repository' ) ) ; } if ( ! options . serverConfig . port ) { Promise . reject ( new Error ( 'The server must be started with an available port' ) ) ; } const corsOptions = { origin : ( origin , callback ) => { callback ( null , true ) ; } , optionsSuccessStatus : 200 } ; const app = express ( ) . use ( helmet ( ) ) . disable ( 'x-powered-by' ) . use ( bodyParser . json ( ) ) . use ( bodyParser . json ( { limit : '50mb' , type : 'application/vnd.api+json' } ) ) . use ( bodyParser . urlencoded ( { limit : '50mb' , extended : true } ) ) . use ( hpp ( ) ) . use ( ( ! ! process . env . NODE_ENV && process . env . NODE_ENV === 'test' ) ? ( req , res , next ) => next ( ) : morgan ( 'dev' ) ) . use ( compress ( ) ) . use ( cors ( corsOptions ) ) . use ( ( req , res , next ) => { ( req as any ) . serverConfig = { } ; ( req as any ) . serverConfig . backendToken = options . serverConfig . backendToken ; next ( ) ; } ) . use ( '/' , defaultRoutes ( ) ) . use ( '/' , discoverRoute ( options ) ) . use ( '/' , proxyRoutes ( options ) ) ; await catchErrors ( app , options ) ; const server = await app . listen ( options . serverConfig . port , ( ) => Promise . resolve ( server ) ) ; return { server } ; } ; export const catchErrors = ( app , option ) : Promise < any > => { return Promise . resolve ( app . use ( ( err , req , res , next ) => { if ( err && err . code ) { const response = { message : err . message || err . toString ( ) , code : err . code || 500 , stack : err . stack } ; console . log ( response . message , option . serverConfig . verbose ) ; return res . status ( response . code ) . json ( response ) ; } if ( option . serverConfig . verbose ) { let errmsg = err . toString ( ) ; if ( typeof err === 'object' ) { try { errmsg = JSON . stringify ( err , null , 2 ) ; } catch ( e ) { } } console . log ( `[ERROR]: {SERVER} Internal Server Error: ${ errmsg }` , option . serverConfig . verbose ) ; } res . status ( 500 ) . json ( { code : 500 , data : err , message : 'Internal Server Error' } ) ; } ) . use ( ( req , res , next ) => { console . log ( `[Error]: 404 API not found` , option . serverConfig . verbose ) ; res . status ( 404 ) . json ( { code : 404 , message : 'API not found' } ) ; } ) ) ; } ;