Set up Heroku deployment.
This commit is contained in:
+7
-1
@@ -9,10 +9,12 @@
|
||||
listenOn: 8081,
|
||||
// It is also possible to listen on a unix socket.
|
||||
// listenOn: "/tmp/sock",
|
||||
// This will be overwritten by the environment variable MD_LISTEN_ON, if set.
|
||||
|
||||
// The path this is hosted behind - only relevant when behind a reverse proxy, this won't actually host on a different
|
||||
// path. This should always have a trailing slash if it isn't empty, and never one at the start.
|
||||
basePath: "",
|
||||
// This will be overwritten by the environment variable MD_BASE_PATH, if set.
|
||||
|
||||
// Timeouts determine how long the server waits before taking certain actions.
|
||||
// These values are all ISO 8601 durations.
|
||||
@@ -87,7 +89,11 @@
|
||||
checkAfter: "PT5M"
|
||||
},
|
||||
|
||||
// A file to touch when the server is started. If null, we won't touch any files.
|
||||
touchOnStart: null,
|
||||
// This will be overwritten by the environment variable MD_TOUCH_ON_START, if set.
|
||||
|
||||
// The version of Massive Decks.
|
||||
// This will be overwritten by the environment variable MD_VERSION, if set.
|
||||
version: "dev"
|
||||
// This will be overwritten by the environment variable MD_VERSION, if set.
|
||||
}
|
||||
|
||||
Generated
+14
-14
@@ -1151,13 +1151,13 @@
|
||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
|
||||
},
|
||||
"eslint": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-6.0.0.tgz",
|
||||
"integrity": "sha512-SrrIfcd4tOgsspOKTSwamuTOAMZOUigHQhVMrzNjz4/B9Za6SHQDIocMIyIDfwDgx6MhS15nS6HC8kumCV2qBQ==",
|
||||
"version": "5.16.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz",
|
||||
"integrity": "sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.0.0",
|
||||
"ajv": "^6.10.0",
|
||||
"ajv": "^6.9.1",
|
||||
"chalk": "^2.1.0",
|
||||
"cross-spawn": "^6.0.5",
|
||||
"debug": "^4.0.1",
|
||||
@@ -1165,19 +1165,18 @@
|
||||
"eslint-scope": "^4.0.3",
|
||||
"eslint-utils": "^1.3.1",
|
||||
"eslint-visitor-keys": "^1.0.0",
|
||||
"espree": "^6.0.0",
|
||||
"espree": "^5.0.1",
|
||||
"esquery": "^1.0.1",
|
||||
"esutils": "^2.0.2",
|
||||
"file-entry-cache": "^5.0.1",
|
||||
"functional-red-black-tree": "^1.0.1",
|
||||
"glob-parent": "^3.1.0",
|
||||
"glob": "^7.1.2",
|
||||
"globals": "^11.7.0",
|
||||
"ignore": "^4.0.6",
|
||||
"import-fresh": "^3.0.0",
|
||||
"imurmurhash": "^0.1.4",
|
||||
"inquirer": "^6.2.2",
|
||||
"is-glob": "^4.0.0",
|
||||
"js-yaml": "^3.13.1",
|
||||
"js-yaml": "^3.13.0",
|
||||
"json-stable-stringify-without-jsonify": "^1.0.1",
|
||||
"levn": "^0.3.0",
|
||||
"lodash": "^4.17.11",
|
||||
@@ -1185,6 +1184,7 @@
|
||||
"mkdirp": "^0.5.1",
|
||||
"natural-compare": "^1.4.0",
|
||||
"optionator": "^0.8.2",
|
||||
"path-is-inside": "^1.0.2",
|
||||
"progress": "^2.0.0",
|
||||
"regexpp": "^2.0.1",
|
||||
"semver": "^5.5.1",
|
||||
@@ -1265,9 +1265,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"espree": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/espree/-/espree-6.0.0.tgz",
|
||||
"integrity": "sha512-lJvCS6YbCn3ImT3yKkPe0+tJ+mH6ljhGNjHQH9mRtiO6gjhVAOhVXW1yjnwqGwTkK3bGbye+hb00nFNmu0l/1Q==",
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz",
|
||||
"integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"acorn": "^6.0.7",
|
||||
@@ -4430,9 +4430,9 @@
|
||||
}
|
||||
},
|
||||
"tslib": {
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz",
|
||||
"integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==",
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
|
||||
"integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==",
|
||||
"dev": true
|
||||
},
|
||||
"tsutils": {
|
||||
|
||||
+19
-12
@@ -1,22 +1,29 @@
|
||||
{
|
||||
"name": "server",
|
||||
"description": "The game server for Massive Decks, a comedy party game.",
|
||||
"version": "2.0.0",
|
||||
"description": "Massive Decks server.",
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
"generate-json-validators": "npx typescript-json-validator src/ts/action/validation.ts --collection --noExtraProps--format=full --aliasRefs --ignoreErrors && sed -i '1s;^;/* eslint-disable */\\n;' src/ts/action/validation.validator.ts",
|
||||
"build": "tsc",
|
||||
"prestart": "npm run build",
|
||||
"dev": "nodemon .",
|
||||
"debug": "nodemon --inspect .",
|
||||
"generate-secret": "npm run prestart && node dist/secret.js"
|
||||
},
|
||||
"author": "Reread Games <team@rereadgames.com>",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"private": true,
|
||||
"repository": "github:Lattyware/massivedecks",
|
||||
"engines": {
|
||||
"node": ">=0.12"
|
||||
"node": ">=11 <12"
|
||||
},
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
"prepublishOnly": "npm run build",
|
||||
"build": "tsc",
|
||||
"prestart": "npm run build",
|
||||
"start": "node dist/index.js",
|
||||
"dev": "nodemon .",
|
||||
"debug": "nodemon --inspect .",
|
||||
"generate-json-validators": "npx typescript-json-validator src/ts/action/validation.ts --collection --noExtraProps--format=full --aliasRefs --ignoreErrors && sed -i '1s;^;/* eslint-disable */\\n;' src/ts/action/validation.validator.ts",
|
||||
"generate-secret": "npm run prestart && node dist/secret.js"
|
||||
},
|
||||
"files": [
|
||||
"dist/*",
|
||||
"config.json5"
|
||||
],
|
||||
"dependencies": {
|
||||
"ajv": "^6.10.0",
|
||||
"axios": "^0.19.0",
|
||||
@@ -52,7 +59,7 @@
|
||||
"@types/wu": "^2.1.39",
|
||||
"@typescript-eslint/eslint-plugin": "^1.10.2",
|
||||
"@typescript-eslint/parser": "^1.10.2",
|
||||
"eslint": "^6.0.0",
|
||||
"eslint": "^5.12.1",
|
||||
"eslint-config-prettier": "^5.0.0",
|
||||
"eslint-plugin-prettier": "^3.1.0",
|
||||
"nodemon": "^1.19.1",
|
||||
|
||||
@@ -21,15 +21,15 @@ export const Schema = {
|
||||
definitions: {
|
||||
Action: {
|
||||
anyOf: [
|
||||
{
|
||||
$ref: "#/definitions/Authenticate"
|
||||
},
|
||||
{
|
||||
$ref: "#/definitions/Judge"
|
||||
},
|
||||
{
|
||||
$ref: "#/definitions/Reveal"
|
||||
},
|
||||
{
|
||||
$ref: "#/definitions/Authenticate"
|
||||
},
|
||||
{
|
||||
$ref: "#/definitions/Submit"
|
||||
},
|
||||
@@ -64,7 +64,7 @@ export const Schema = {
|
||||
description: "Authenticate with the game.",
|
||||
properties: {
|
||||
action: {
|
||||
$ref: "#/definitions/NameType_2"
|
||||
$ref: "#/definitions/NameType"
|
||||
},
|
||||
token: {
|
||||
$ref: "#/definitions/Token"
|
||||
@@ -247,7 +247,7 @@ export const Schema = {
|
||||
description: "A user declares the winning play for a round.",
|
||||
properties: {
|
||||
action: {
|
||||
$ref: "#/definitions/NameType"
|
||||
$ref: "#/definitions/NameType_1"
|
||||
},
|
||||
winner: {
|
||||
$ref: "#/definitions/Id"
|
||||
@@ -263,15 +263,15 @@ export const Schema = {
|
||||
type: "string"
|
||||
},
|
||||
NameType: {
|
||||
enum: ["Judge"],
|
||||
enum: ["Authenticate"],
|
||||
type: "string"
|
||||
},
|
||||
NameType_1: {
|
||||
enum: ["Reveal"],
|
||||
enum: ["Judge"],
|
||||
type: "string"
|
||||
},
|
||||
NameType_2: {
|
||||
enum: ["Authenticate"],
|
||||
enum: ["Reveal"],
|
||||
type: "string"
|
||||
},
|
||||
NameType_3: {
|
||||
@@ -373,7 +373,7 @@ export const Schema = {
|
||||
description: "A user judges the winning play for a round.",
|
||||
properties: {
|
||||
action: {
|
||||
$ref: "#/definitions/NameType_1"
|
||||
$ref: "#/definitions/NameType_2"
|
||||
},
|
||||
play: {
|
||||
$ref: "#/definitions/Id"
|
||||
|
||||
+34
-7
@@ -5,11 +5,23 @@ type Duration = UnparsedDuration | ParsedDuration;
|
||||
type UnparsedDuration = string;
|
||||
type ParsedDuration = number;
|
||||
|
||||
export interface Config<D extends Duration> {
|
||||
const environmental: (keyof EnvironmentalConfig)[] = [
|
||||
"secret",
|
||||
"listenOn",
|
||||
"basePath",
|
||||
"version",
|
||||
"touchOnStart"
|
||||
];
|
||||
|
||||
export interface EnvironmentalConfig {
|
||||
secret: string;
|
||||
listenOn: number | string; // Port or unix socket path.
|
||||
basePath: string;
|
||||
version: string;
|
||||
touchOnStart: string;
|
||||
}
|
||||
|
||||
export interface Config<D extends Duration> extends EnvironmentalConfig {
|
||||
timeouts: Timeouts<D>;
|
||||
storage: BaseStorage<D>;
|
||||
cache: BaseCache<D>;
|
||||
@@ -98,9 +110,24 @@ export const parseTimeouts = (
|
||||
parseDuration(value)
|
||||
);
|
||||
|
||||
export const parse = (config: Unparsed): Parsed => ({
|
||||
...config,
|
||||
timeouts: parseTimeouts(config.timeouts),
|
||||
storage: parseStorage(config.storage),
|
||||
cache: parseCache(config.cache)
|
||||
});
|
||||
export const parse = (config: Unparsed): Parsed =>
|
||||
pullFromEnvironment({
|
||||
...config,
|
||||
timeouts: parseTimeouts(config.timeouts),
|
||||
storage: parseStorage(config.storage),
|
||||
cache: parseCache(config.cache)
|
||||
});
|
||||
|
||||
export const pullFromEnvironment = (config: Parsed): Parsed => {
|
||||
for (const name of environmental) {
|
||||
const envName = `MD_${name
|
||||
.split(/(?=[A-Z])/)
|
||||
.join("_")
|
||||
.toUpperCase()}`;
|
||||
const value = process.env[envName];
|
||||
if (value !== undefined) {
|
||||
config[name] = value;
|
||||
}
|
||||
}
|
||||
return config;
|
||||
};
|
||||
|
||||
+14
-15
@@ -37,25 +37,20 @@ process.on("unhandledRejection", function(reason, promise) {
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
function getConfigFilePath(): string {
|
||||
const configPath = process.env["MD_CONFIG_PATH"];
|
||||
return configPath === undefined ? "config.json5" : configPath;
|
||||
}
|
||||
|
||||
async function main(): Promise<void> {
|
||||
const config = serverConfig.parse(JSON5.parse(
|
||||
(await promisify(fs.readFile)("config.json5")).toString()
|
||||
(await promisify(fs.readFile)(getConfigFilePath())).toString()
|
||||
) as serverConfig.Unparsed);
|
||||
|
||||
const envSecret = process.env.MD_SECRET;
|
||||
if (envSecret !== undefined) {
|
||||
config.secret = envSecret;
|
||||
}
|
||||
|
||||
const envVersion = process.env.MD_VERSION;
|
||||
if (envVersion !== undefined) {
|
||||
config.version = envVersion;
|
||||
}
|
||||
|
||||
const { app } = ws(express());
|
||||
|
||||
app.use(helmet());
|
||||
app.set('trust proxy', true);
|
||||
app.set("trust proxy", true);
|
||||
|
||||
const environment = app.get("env");
|
||||
|
||||
@@ -199,9 +194,13 @@ async function main(): Promise<void> {
|
||||
.loadFromStore(state)
|
||||
.catch(error => logging.logException("Error running store tasks:", error));
|
||||
|
||||
app.listen(config.listenOn, () =>
|
||||
logging.logger.info(`Listening on ${config.listenOn}.`)
|
||||
);
|
||||
app.listen(config.listenOn, async () => {
|
||||
logging.logger.info(`Listening on ${config.listenOn}.`);
|
||||
if (config.touchOnStart !== null) {
|
||||
const f = await promisify(fs.open)(config.touchOnStart, "w");
|
||||
await promisify(fs.close)(f);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
main().catch(error => {
|
||||
|
||||
Reference in New Issue
Block a user