You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
cvm/src/app.js

116 lines
3.0 KiB
JavaScript

'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);
// }
console.log(errorChain.getContext(sourceError));
res.render("error", {
error: err
});
debugger;
});
return app;
};