UNPKG

@akashic/akashic-sandbox

Version:
231 lines (230 loc) 9.63 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"); var utils_1 = require("./utils"); 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) { var _a; if (fs.existsSync(gameJsonPath)) { var configuration = JSON.parse(fs.readFileSync(gameJsonPath, "utf8")); return (_a = configuration.environment) !== null && _a !== void 0 ? _a : null; } 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/v:version/engineFilesV*.js", function (req, res, next) { var engineFilesPath = (0, utils_1.resolveEngineFilesPath)(req.params.version); if (fs.existsSync(engineFilesPath)) { var engineFilesSrc = fs.readFileSync(engineFilesPath).toString(); res.contentType("text/javascript"); res.send(engineFilesSrc); } else { next(); } }); 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 == null || 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"); res.render("engine", { host: host, externals: JSON.stringify(externals), engineFilesPath: "js/v".concat(version, "/").concat((0, utils_1.resolveEngineFilesVariable)(version), ".js") }); }); // TODO: `/test/`, `/start/`, `/next/`, `/finish/` の scenario オプションに関するパスは使われてないのでいずれ削除する。 app.use("^\/test$", function (_req, res, _next) { res.redirect("/test/"); }); app.use("/test/*.js$", function (req, _res, next) { var _a; var ssn = req.session; req.baseDir = app.scenario.benchmarks[(_a = ssn.cntr) !== null && _a !== void 0 ? _a : 0].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 _a, _b; var ssn = req.session; var elapse = Number(req.query.elapse); (_a = ssn.results) === null || _a === void 0 ? void 0 : _a.push({ "name": app.scenario.benchmarks[(_b = ssn.cntr) !== null && _b !== void 0 ? _b : 0].name, "elapse": elapse }); ssn.cntr = Number.isInteger(ssn.cntr) ? ssn.cntr + 1 : 0; if (ssn.cntr < app.scenario.benchmarks.length) { res.redirect("/test/"); } else { res.redirect("/finish/"); } }); app.use("/finish/", function (req, res, _next) { var _a; var ssn = req.session; console.log("you arrived at 'finish'"); res.render("finish", { "resultjson": JSON.stringify(ssn.results), "resultcsv": result2csv((_a = ssn.results) !== null && _a !== void 0 ? _a : []), "title": "finish" }); }); app.use("/test", jsRoute); app.use("/test", function (req, res, next) { var _a, _b, _c; var ssn = req.session; res.locals.maxAge = app.scenario.benchmarks[(_a = ssn.cntr) !== null && _a !== void 0 ? _a : 0].maxAge; res.locals.renderPerFrame = app.scenario.benchmarks[(_b = ssn.cntr) !== null && _b !== void 0 ? _b : 0].renderPerFrame; res.locals.renderPerFrame = (res.locals.renderPerFrame === undefined) ? "undefined" : res.locals.renderPerFrame; res.locals.loopCount = app.scenario.benchmarks[(_c = ssn.cntr) !== null && _c !== void 0 ? _c : 0].loopCount; res.locals.loopCount = (res.locals.loopCount === undefined) ? "undefined" : res.locals.loopCount; testRoute(req, res, next); }); app.use("/test/", function (req, res, next) { var _a; var ssn = req.session; express.static(app.scenario.benchmarks[(_a = ssn.cntr) !== null && _a !== void 0 ? _a : 0].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; };