@akashic/akashic-sandbox
Version:
Standalone runner for Akashic contents
216 lines (215 loc) • 8.62 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
var fs = require("fs");
var path = require("path");
var express = require("express");
var session = require("express-session");
var gameRoute = require("./routes/game");
var jsRoute = require("./routes/js");
var sandboxConfigRoute = require("./routes/sandboxConfig");
var testRoute = require("./routes/test");
function result2csv(results) {
var csv = "";
for (var i = 0; i < results.length; i++) {
csv += results[i].name + "," + results[i].elapse + "\n";
}
return csv;
}
function getContentModuleEnvironment(gameJsonPath) {
if (fs.existsSync(gameJsonPath)) {
var configuration = JSON.parse(fs.readFileSync(gameJsonPath, "utf8"));
return configuration.environment;
}
return null;
}
module.exports = function (options) {
if (options === void 0) { options = {}; }
var appBase = path.join(__dirname, "..");
var gameBase = options.gameBase ? options.gameBase : process.cwd();
var cascadeBases = options.cascadeBases || [];
var jsBase = options.jsBase ? options.jsBase : path.join(appBase, "js");
var cssBase = options.cssBase ? options.cssBase : path.join(appBase, "css");
var thridpartyBase = options.thirdpartyBase ? options.thirdpartyBase : path.join(appBase, "thirdparty");
var app = express();
var isDev = app.get("env") === "development";
var gameJsonPath = path.join(gameBase, "game.json");
var environment = getContentModuleEnvironment(gameJsonPath);
var version = environment && environment["sandbox-runtime"] ? environment["sandbox-runtime"] : "1";
if (!/^(1|2|3)$/.test(version)) {
// sandbox-runtime の値が "1", "2", "3" 以外の場合エラーとする
throw new Error("sandbox-runtime value is invalid. Please set the environment. sandbox-runtime value of game.json to 1, 2, or 3.");
}
// see https://github.com/expressjs/session#secret
app.use(session({
resave: false,
saveUninitialized: false,
secret: "to eat or no to eat"
}));
app.use(function (_req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.locals.environment = environment;
next();
});
app.gameBase = gameBase;
app.cascadeBases = cascadeBases;
// TODO: change to middleware
app.use("/game/*.js$", function (req, _res, next) {
req.baseDir = app.gameBase;
next();
});
app.use("/raw_game/*.js$", function (req, _res, next) {
req.baseDir = app.gameBase;
req.useRawScript = true;
next();
});
app.use("/cascade/:index/*.js$", function (req, _res, next) {
req.baseDir = app.cascadeBases[Number(req.params.index)];
next();
});
app.use("/raw_cascade/:index/*.js$", function (req, _res, next) {
req.baseDir = app.cascadeBases[Number(req.params.index)];
req.useRawScript = true;
next();
});
app.set("views", path.join(__dirname, "..", "views"));
app.set("view engine", "ejs");
app.use("^\/$", function (_req, res, _next) {
res.redirect("/game/");
});
app.use("^\/game$", function (_req, res, _next) {
res.redirect("/game/");
});
// /js/ /css/ /thirdparty/ を静的ファイルとして参照できるようにする
app.use("/js/", express.static(jsBase));
app.use("/css/", express.static(cssBase));
app.use("/thirdparty/", express.static(thridpartyBase));
app.use("/sandboxconfig/", function (req, _res, next) {
req.baseDir = app.gameBase;
next();
}, sandboxConfigRoute);
// /game/ は sandbox をブラウザで開く場合に利用、/raw_game/ は /engine のエンジン設定ファイルを使う場合に利用
app.use("/game", jsRoute);
app.use("/game", gameRoute);
app.use("/game/", express.static(app.gameBase));
app.use("/raw_game", jsRoute);
app.use("/raw_game/", express.static(app.gameBase));
app.use("/cascade/:index", jsRoute);
app.use("/raw_cascade/:index", jsRoute);
for (var i = 0; i < app.cascadeBases.length; ++i) {
app.use("/cascade/" + i + "/", express.static(app.cascadeBases[i]));
app.use("/raw_cascade/" + i + "/", express.static(app.cascadeBases[i]));
}
app.use("/configuration/", function (req, res, _next) {
var prefix = req.query.raw ? "/raw_" : "/";
if (app.cascadeBases.length === 0) {
res.redirect(prefix + "game/game.json");
return;
}
var defs = [prefix + "game/game.json"];
for (var i = 0; i < app.cascadeBases.length; ++i)
defs.push(prefix + "cascade/" + i + "/game.json");
res.json({ definitions: defs });
});
app.use("/basepath/", function (_req, res, _next) {
res.send(app.gameBase);
});
app.use("/engine", function (req, res, _next) {
var host = req.protocol + "://" + req.get("host");
res.type("application/json");
var externals = req.query.externals ? req.query.externals : ["audio", "xhr", "websocket"];
externals = Array.isArray(externals) ? externals : [externals];
if (typeof externals[0] !== "string" && externals[0] != null)
throw new Error("Invalid externals type");
// json の読み込みのため require の lint エラーを抑止
/* eslint-disable @typescript-eslint/no-var-requires */
var versionsJson = require("./engineFilesVersion.json");
res.render("engine", {
host: host,
version: version,
externals: JSON.stringify(externals),
engineFilesVariable: versionsJson["v" + version].variable
});
});
app.use("^\/test$", function (_req, res, _next) {
res.redirect("/test/");
});
app.use("/test/*.js$", function (req, _res, next) {
var ssn = req.session;
req.baseDir = app.scenario.benchmarks[ssn.cntr].target;
next();
});
app.use("/start/", function (req, res, _next) {
var scenarioJSONString = fs.readFileSync(app.settings.scenarioPath).toString();
app.scenario = JSON.parse(scenarioJSONString);
var ssn = req.session;
ssn.cntr = 0;
ssn.results = [];
res.redirect("/test/");
});
app.use("/next/", function (req, res, _next) {
var ssn = req.session;
var elapse = Number(req.query.elapse);
ssn.results.push({
"name": app.scenario.benchmarks[ssn.cntr].name,
"elapse": elapse
});
ssn.cntr++;
if (ssn.cntr < app.scenario.benchmarks.length) {
res.redirect("/test/");
}
else {
res.redirect("/finish/");
}
});
app.use("/finish/", function (req, res, _next) {
var ssn = req.session;
console.log("you arrived at 'finish'");
res.render("finish", {
"resultjson": JSON.stringify(ssn.results),
"resultcsv": result2csv(ssn.results),
"title": "finish"
});
});
app.use("/test", jsRoute);
app.use("/test", function (req, res, next) {
var ssn = req.session;
res.locals.maxAge = app.scenario.benchmarks[ssn.cntr].maxAge;
res.locals.renderPerFrame = app.scenario.benchmarks[ssn.cntr].renderPerFrame;
res.locals.renderPerFrame = (res.locals.renderPerFrame === undefined) ? "undefined" : res.locals.renderPerFrame;
res.locals.loopCount = app.scenario.benchmarks[ssn.cntr].loopCount;
res.locals.loopCount = (res.locals.loopCount === undefined) ? "undefined" : res.locals.loopCount;
testRoute(req, res, next);
});
app.use("/test/", function (req, res, next) {
var ssn = req.session;
express.static(app.scenario.benchmarks[ssn.cntr].target)(req, res, next);
});
app.use(function (_req, _res, next) {
var err = new Error("Not Found");
err.status = 404;
next(err);
});
var errorHandler;
if (isDev) {
errorHandler = function (err, _req, res, _next) {
res.status(err.status || 500);
res.render("error", {
title: "error",
message: err.message,
error: err
});
};
}
else {
errorHandler = function (err, _req, res, _next) {
res.status(err.status || 500);
res.render("error", {
title: "error",
message: err.message,
error: {}
});
};
}
app.use(errorHandler);
return app;
};