UNPKG

@akashic/akashic-sandbox

Version:
216 lines (215 loc) 8.62 kB
"use strict"; 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; };