import session from "client-sessions" ; import * as turbolinks from "turbolinks-express" ; import bodyParser from "body-parser" ; import express , { Request , Response , NextFunction , Express , Handler , } from "express" ; import path from "path" ; import csurf from "csurf" ; import "express-async-errors" ; import { logRequests } from "./middleware" ; import { Application , probot , AppOptions } from "./probot" ; import { Dispatcher } from "./application" ; import { Services } from "./services" ; export interface Dependencies extends Services { robot : Application ; app : Express ; csrf : Handler ; registerHelper : ( name : string , h : ( ctx : any ) => string ) => void ; registerPartial : ( name : string , val : string ) => void ; config : { [ k ] : string | undefined ; } ; } export type RegisterFunc = ( d : Dependencies ) => void ; export interface Options extends AppOptions { production : boolean ; root : string ; scripts : string ; serve : [ string , string ] [ ] ; locals : any ; config : { [ k ] : string | undefined ; } ; dispatcher ? : Dispatcher ; } export function load ( services , apps , opts ) { const app = express ( ) ; const robot = probot ( opts , app ) ; app . use ( logRequests ) ; app . use ( ( req , res , next ) => { if ( req . secure ) ( req . connection as any ) . proxySecure = true ; next ( ) ; } ) ; app . locals . info = opts . locals ; app . use ( ( req , res , next ) => { res . setHeader ( "cache-control" , "private" ) ; res . setHeader ( "vary" , "accept" ) ; next ( ) ; } ) ; app . use ( session ( { requestKey : "session" , cookieName : "__session" , secret : opts . appSecret , duration : 24 * 60 * 60 * 1000 , cookie : { maxAge : 24 * 60 * 60 * 1000 , httpOnly : true , secure : opts . production , } , } ) ) ; app . use ( bodyParser . urlencoded ( { verify : rawBodyBuffer , extended : true } ) ) ; app . use ( bodyParser . json ( { verify : rawBodyBuffer } ) ) ; opts . serve . forEach ( val => { app . use ( val [ 0 ] , express . static ( val [ 1 ] ) ) ; } ) ; const root = opts . root ; app . use ( "/static/" , express . static ( path . join ( root , "public" , "static" ) ) ) ; const error5xx = path . join ( root , "public" , "static" , "5xx.html" ) ; const error404 = path . join ( root , "public" , "static" , "404.html" ) ; app . set ( "error404" , error404 ) ; app . set ( "error5xx" , error5xx ) ; app . set ( "trust proxy" , true ) ; app . set ( "view engine" , "hbs" ) ; app . set ( "views" , path . join ( root , "views" ) ) ; const hbs = require ( "hbs" ) ; hbs . localsAsTemplateData ( app ) ; hbs . registerPartial ( "scripts" , opts . scripts ) ; hbs . registerPartials ( path . join ( root , "views" , "partials" ) , ( ) => { app . emit ( "app.partials-loaded" ) ; } ) ; app . use ( turbolinks . redirect ) ; app . use ( turbolinks . location ) ; apps . forEach ( register => register ( { ... services , registerHelper : hbs . registerHelper . bind ( hbs ) , registerPartial : hbs . registerPartial . bind ( hbs ) , config : opts . config , csrf : csurf ( ) , app , robot , } ) ) ; app . use ( ( err , req , res , next ) => { if ( err . status === 404 ) { res . status ( 404 ) . sendFile ( error404 ) ; return ; } next ( err ) ; } ) ; app . use ( ( err , req , res , next ) => { req . log . error ( { fields : err , error : err . message , stack : err . stack } , "request failed" ) ; if ( process . env . NODE_ENV === "development" ) { console . error ( err ) ; } res . status ( 500 ) . sendFile ( error5xx ) ; } ) ; app . use ( ( req , res ) => { res . status ( 404 ) . sendFile ( error404 ) ; } ) ; if ( opts . dispatcher ) robot . withDispatcher ( opts . dispatcher ) ; return { express : app , probot : robot , loaded : ( ) => { return new Promise ( ( resolve , reject ) => { app . on ( "app.partials-loaded" , ( ) => { resolve ( ) ; } ) ; } ) ; } , } ; } export function rawBodyBuffer ( req , res , buf , encoding ) { if ( buf && buf . length ) { req . rawBody = buf . toString ( encoding || "utf8" ) ; } }