'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; };