Skip to content

Commit

Permalink
Merge pull request #139 from bandaloo/docker
Browse files Browse the repository at this point in the history
Docker
  • Loading branch information
Matt-Puentes authored Dec 21, 2021
2 parents 4cfb36e + b558717 commit 490116e
Show file tree
Hide file tree
Showing 7 changed files with 7,983 additions and 3,054 deletions.
18 changes: 18 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
FROM node:16-alpine
WORKDIR /usr/src/app

RUN mkdir /data

COPY package*.json ./
RUN npm ci --only=production

ENV NODE_PORT=4883
ENV SCORE_SERVER_SCHEME=https
ENV SCORE_SERVER_DOMAIN=afterlightcaves.com
ENV SCORE_DIR=/data

COPY index.js ./
COPY static ./static

EXPOSE 4883
CMD ["node", "index.js"]
133 changes: 127 additions & 6 deletions build-prod.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,134 @@
const npmRun = require("npm-run");
const fs = require("fs").promises;
const fse = require("fs-extra");
const path = require("path");

/**
* This script builds a production version of the game, compatible with
* older and more obscure browsers
*/

const buildTools = require("./build-tools.js");
/** @type{string} set these values to use a custom score server, e.g. "https" */
const SCORE_SERVER_SCHEME = process.env.SCORE_SERVER_SCHEME || undefined;
/** @type{string} set these values to use a custom score server, e.g. "example.com" */
const SCORE_SERVER_DOMAIN = process.env.SCORE_SERVER_DOMAIN || undefined;

/**
* wraps npmRun.run() in a function that has no options and returns a promise to
* avoid callback hell
* @param{string} script the npm script to run
* @return{Promise<void>}
*/
const runPromise = script => {
return new Promise((resolve, reject) => {
npmRun.exec(script, {}, (err, stdout, stderr) => {
if (err) {
console.error(`Error encountered while running command '${script}':`);
console.error(stderr);
process.exit(1);
}
resolve(stdout);
});
});
};

/**
* find and replace text within a file
* @param{string} path file path
* @param{RegExp} find regular expression to find
* @param{string} replace string to replace
* @return{Promise<void>}
*/
const replaceInFile = (path, find, replace) => {
return fs
.readFile(path, "utf8")
.then(contents => fs.writeFile(path, contents.replace(find, replace)));
};


/**
* builds a production version of the game, compatible with older and more
* obscure browsers
* @param{string} scoreServerScheme scheme for custom score server, e.g. "https"
* @param{string} scoreServerDomain domain for custom score server, e.g. "example.com"
* @return{Promise<void>}
*/
const buildProd = (
scoreServerScheme = undefined,
scoreServerDomain = undefined
) => {
console.log("Building production version with Babel...");
return new Promise(resolve => {
runPromise("babel static --out-dir build")
.then(() => runPromise("browserify -vd build/main.js -o dist/bundle.js"))
.then(() =>
fse.copy(
path.join("static", "index.html"),
path.join("dist", "index.html")
)
)
.then(() =>
fse.copy(
path.join("static", "style.css"),
path.join("dist", "style.css")
)
)
.then(() =>
fse.copy(
path.join("static", "license.txt"),
path.join("dist", "license.txt")
)
)
.then(() =>
fse.copy(
path.join("static", "favicon.ico"),
path.join("dist", "favicon.ico")
)
)
.then(() =>
fse.copy(
path.join("static", "anonymous-pro-b.ttf"),
path.join("dist", "anonymous-pro-b.ttf")
)
)
.then(() =>
replaceInFile(
path.join("dist", "index.html"),
/<script type="module" src="main.js"/,
'<script src="bundle.js"'
)
)
.then(() => {
if (
scoreServerScheme !== undefined &&
scoreServerDomain !== undefined
) {
return replaceInFile(
path.join("dist", "bundle.js"),
/var GAME_URL = ".*";/,
`var GAME_URL = "${scoreServerScheme}://${scoreServerDomain}";`
);
} else {
return Promise.resolve();
}
})
.then(() => replaceInFile(path.join("dist", "bundle.js"), /\.\./g, "."))
.then(() =>
fse.copy(path.join("static", "sounds"), path.join("dist", "sounds"))
)
.then(() =>
fse.copy(path.join("static", "images"), path.join("dist", "images"))
)
.then(() => {
console.log("Production version created at dist");
resolve();
})
.catch(reason => {
console.error("Error encountered in buildProd:");
console.error(reason);
});
});
};

/** @type{string} set these values to use a custom score server */
const SCORE_SERVER_SCHEME = undefined; // e.g. "https";
/** @type{string} set these values to use a custom score server */
const SCORE_SERVER_DOMAIN = undefined; // e.g. "example.com";
buildProd(SCORE_SERVER_SCHEME, SCORE_SERVER_DOMAIN).then();

buildTools.buildProd(SCORE_SERVER_SCHEME, SCORE_SERVER_DOMAIN).then();
117 changes: 2 additions & 115 deletions build-tools.js
Original file line number Diff line number Diff line change
@@ -1,120 +1,8 @@
const npmRun = require("npm-run");
const packager = require("electron-packager");
const installerRedHat = require("electron-installer-redhat");
const fs = require("fs").promises;
const fse = require("fs-extra");
const path = require("path");
const packager = require("electron-packager");
const installerRedHat = require("electron-installer-redhat");

/**
* wraps npmRun.run() in a function that has no options and returns a promise to
* avoid callback hell
* @param{string} script the npm script to run
* @return{Promise<void>}
*/
const runPromise = script => {
return new Promise(resolve => {
npmRun.exec(script, {}, () => {
resolve();
});
});
};

/**
* find and replace text within a file
* @param{string} path file path
* @param{RegExp} find regular expression to find
* @param{string} replace string to replace
* @return{Promise<void>}
*/
const replaceInFile = (path, find, replace) => {
return fs
.readFile(path, "utf8")
.then(contents => fs.writeFile(path, contents.replace(find, replace)));
};

/**
* builds a production version of the game, compatible with older and more
* obscure browsers
* @param{string} scoreServerScheme scheme for custom score server, e.g. "https"
* @param{string} scoreServerDomain domain for custom score server, e.g. "example.com"
* @return{Promise<void>}
*/
const buildProd = (
scoreServerScheme = undefined,
scoreServerDomain = undefined
) => {
console.log("Building production version with Babel...");
return new Promise(resolve => {
runPromise("babel static --out-dir build")
.then(() => runPromise("browserify -vd build/main.js -o dist/bundle.js"))
.then(() =>
fse.copy(
path.join("static", "index.html"),
path.join("dist", "index.html")
)
)
.then(() =>
fse.copy(
path.join("static", "style.css"),
path.join("dist", "style.css")
)
)
.then(() =>
fse.copy(
path.join("static", "license.txt"),
path.join("dist", "license.txt")
)
)
.then(() =>
fse.copy(
path.join("static", "favicon.ico"),
path.join("dist", "favicon.ico")
)
)
.then(() =>
fse.copy(
path.join("static", "anonymous-pro-b.ttf"),
path.join("dist", "anonymous-pro-b.ttf")
)
)
.then(() =>
replaceInFile(
path.join("dist", "index.html"),
/<script type="module" src="main.js"/,
'<script src="bundle.js"'
)
)
.then(() => {
if (
scoreServerScheme !== undefined &&
scoreServerDomain !== undefined
) {
return replaceInFile(
path.join("dist", "bundle.js"),
/var GAME_URL = ".*";/,
`var GAME_URL = "${scoreServerScheme}://${scoreServerDomain}";`
);
} else {
return Promise.resolve();
}
})
.then(() => replaceInFile(path.join("dist", "bundle.js"), /\.\./g, "."))
.then(() =>
fse.copy(path.join("static", "sounds"), path.join("dist", "sounds"))
)
.then(() =>
fse.copy(path.join("static", "images"), path.join("dist", "images"))
)
.then(() => {
console.log("Production version created at dist");
resolve();
})
.catch(reason => {
console.error("Error encountered in buildProd:");
console.error(reason);
});
});
};

/**
* builds a desktop version of the game, but does not package it as a standalone
Expand Down Expand Up @@ -240,7 +128,6 @@ const cleanDirs = toRemove => {
};

module.exports = {
buildProd,
buildElectron,
cleanDirs,
packageDesktop,
Expand Down
10 changes: 7 additions & 3 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
const express = require("express");
const fs = require("fs");
const path = require("path");
const app = express();

/** @type{string} directory to store the scores.json file in, e.g. "/data" */
const SCORE_DIR = process.env.SCORE_DIR || ".";

/**
* @param {express.Response} res
* @param {string} message
Expand Down Expand Up @@ -40,7 +44,7 @@ const port = process.env.NODE_PORT || 4000;
* }
*/
app.get("/scores", (req, res) => {
fs.readFile("./scores.json", (err, data) => {
fs.readFile(path.join(SCORE_DIR, "scores.json"), (err, data) => {
if (err && err.code !== "ENOENT") {
console.error(err);
sendRes(res, 500, "Couldn't read scores file");
Expand Down Expand Up @@ -82,7 +86,7 @@ app.post("/score", (req, res) => {
sendRes(res, 400, "Missing score field");
return;
} else {
fs.readFile("./scores.json", (err, data) => {
fs.readFile(path.join(SCORE_DIR, "scores.json"), (err, data) => {
// ignore 'no such file' errors, we'll create a new one
if (err && err.code !== "ENOENT") {
sendRes(res, 500, "Failed to read scores file");
Expand All @@ -105,7 +109,7 @@ app.post("/score", (req, res) => {
score: body.score
});
fs.writeFile(
"./scores.json",
path.join(SCORE_DIR, "scores.json"),
JSON.stringify(currentScores),
{ encoding: "utf8", mode: 0o664 },
() => {
Expand Down
Loading

0 comments on commit 490116e

Please sign in to comment.