Source: backend/server.js

/**
	@namespace backend
	@since 23/10/2020
	@version 1.0
	@author Brennan Wilkes
*/


//Includes
const express = require('express');
const path = require("path");
const bodyParser = require('body-parser');


//Load backend config vars here
const CONFIG = require(path.join(__dirname,"..", "..","config","backend.json"));
exports.CONFIG = CONFIG

/**
	Prints to stdout if verbose config mode is set
	@param {string[]} content Content strings to print
	@memberof backend
*/
const print = (...content) => {
	if(CONFIG.verbose) console.log(...content);
};
exports.print = print


/**
	Server abstration object
	@class
	@memberof backend
*/
const server = {

	/**
		Port to use. Defaults to a "PORT" env variable if set (For heroku and other deployment methods),
		otherwise uses the port set in the config file. Defaults to 8080.
		@type {number}
	*/
	port : process.env.PORT || CONFIG.port || 8080,

	/**
		Express init object
		@type {object}
	*/
	app: express(),

	/**
		Creates a promise based express route.
		This abstraction makes repetitive routing more robust.
		Handles errors by default.
		@param {string} path URI to listen for
		@param {function} function A function which should return a promise to evaluate. The resolution value will be sent to the client with 200. Errors will be sent with 409.
		@param {string} method Routing method. Defaults to GET.
	*/
	route(path,promise,method="get"){

		//Cleanup path URI
		path = path.substring(0,1) === "/" ? path : "/"+path;

		//Set up route
		this.app[method](path, (req,res) => {

			//Run promise method
			promise(req).then(data => {

				//Send results to client
				res.send(data);
				res.end();
			}).catch(error => {

				//Error handling
				res.status(409);
				res.send("<h1>Internal Error</h1><br>"+error);
				res.end();
			});
		});

		//Debug
		print(`Setup ${method} route for ${path}`);
	},

	/**
		Basic express setup.
		Sets JSON encoding, url encoded bodies and static routing.
		Should be run prior to any routing.
	*/
	init(){

		// support json encoded bodies
		this.app.use(express.json());

		// support encoded bodies
		this.app.use(bodyParser.urlencoded({ extended: false }));

		//Static routing for public files
		this.app.use('/', express.static(path.join(__dirname,"..", "..", "public")));
	},

	/**
		Starts the webserver.
		This method should be run last, after init and routing.
	*/
	start(){

		//Create 404 messages for all uncaught routes
		this.app.get('*', (req, res) =>{

			//Debug
			print("Received invalid GET request for",req.url);

			//Response
			res.writeHead(404, {'Content-Type': 'text/html'});
			res.write("<h1>404: If you see this, it's already too late!</h1>");
			res.end();
		});

		//Initialize the server socket and start the webserver
		this.server = this.app.listen(this.port, () => {

			//Debug
			print('server is listening on port', this.server.address().port);
		});
	}
}

exports.server = server;