'use strict' ;
const Promise = require ( "bluebird" ) ;
const express = require ( "express" ) ;
// const expressWs = require("express-ws");
const knex = require ( "knex" ) ;
const path = require ( "path" ) ;
const bodyParser = require ( "body-parser" ) ;
const graphql = require ( "graphql" ) ;
const chalk = require ( "chalk" ) ;
const util = require ( "util" ) ;
const errorChain = require ( "error-chain" ) ;
const expressAsyncReact = require ( "./packages/express-async-react" ) ;
function projectPath ( targetPath ) {
return path . join ( _ _dirname , ".." , targetPath ) ;
}
module . exports = function ( ) {
let db = knex ( require ( "../knexfile" ) ) ;
let imageStore = require ( "./util/image-store" ) ( projectPath ( "./images" ) ) ;
let taskTracker = require ( "../lib/tasks/tracker" ) ( ) ;
let apiQuery = require ( "./api" ) ( ) ;
let state = { db , imageStore , taskTracker } ;
let app = express ( ) ;
// expressWs(app);
app . engine ( "jsx" , expressAsyncReact . createEngine ( {
prepare : ( template , locals ) => {
return Promise . try ( ( ) => {
if ( template . query != null ) {
let queryArguments = ( template . queryArguments != null )
? template . queryArguments ( locals )
: { } ;
return apiQuery ( template . query , queryArguments ) ;
}
} ) . then ( ( result ) => {
if ( result == null ) {
return { } ;
} else {
if ( result . errors != null && result . errors . length > 0 ) {
throw result . errors [ 0 ] ;
} else {
return {
data : result . data
} ;
}
}
} ) ;
}
} ) ) ;
app . set ( "view engine" , "jsx" ) ;
app . set ( "views" , projectPath ( "src/views" ) ) ;
app . locals [ expressAsyncReact . Settings ] = {
componentPath : "template"
} ;
app . use ( ( req , res , next ) => {
res . locals . currentPath = req . originalUrl ;
next ( ) ;
} ) ;
app . use ( express . static ( projectPath ( "public" ) ) ) ;
app . use ( bodyParser . urlencoded ( {
extended : true
} ) ) ;
app . use ( require ( "./routes/index" ) ) ;
app . use ( "/disk-images" , require ( "./routes/disk-images" ) ( state ) ) ;
app . use ( "/instances" , require ( "./routes/instances" ) ( state ) ) ;
app . use ( "/hardware/storage-devices" , require ( "./routes/storage-devices" ) ( state ) ) ;
app . use ( ( err , req , res , next ) => {
/* GraphQL will wrap any data-resolving errors in its own error type, and that'll break our `showChain` logic below. Note that some GraphQL errors may not *have* an originalError (eg. schema violations), so we account for that as well. */
let sourceError = ( err instanceof graphql . GraphQLError && err . originalError != null )
? err . originalError
: err ;
console . error ( errorChain . render ( sourceError ) ) ;
// FIXME: Render full context instead, according to error-chain?
for ( let key of Object . keys ( err ) ) {
console . error ( chalk . yellow . bold ( ` ${ key } : ` ) + util . inspect ( err [ key ] , { colors : true } ) ) ;
}
// if (sourceError.showChain != null) {
// console.log(sourceError.showChain());
// console.log("#####################");
// console.log(sourceError.getAllContext());
// } else {
// console.log(sourceError.stack);
// }
res . render ( "error" , {
error : err
} ) ;
debugger ;
} ) ;
return app ;
} ;