Restructuring folders [ Broken ]

This commit is contained in:
2018-10-22 17:21:29 +11:00
parent 36b7b8629e
commit 776395520d
148 changed files with 238 additions and 198 deletions

View File

@ -23,8 +23,7 @@
//Imports
const
path = require('path'),
ConfigurationManager = require('./../configuration/ConfigurationManager'),
Configuration = require('./../config/Configuration'),
DatabaseConnection = require('./../database/DatabaseConnection'),
Server = require('./../server/Server'),
Email = require('./../email/Email')
@ -35,45 +34,44 @@ const PUBLIC_PATH = path.join(__dirname, '..', '..', 'dist');
class App {
constructor() {
this.config = new Configuration(this);
this.database = new DatabaseConnection(this);
this.server = new Server(this);
this.email = new Email(this);
}
getConfig() { return this.config; }
getDatabase() { return this.db; }
getPublicDirectory() { return PUBLIC_PATH; }
getConfig() { return this.config; }
getDatabase() { return this.database; }
getServer() { return this.server; }
getAPI() { return this.getServer().getAPI(); }
getEmail() {return this.email;}
//Primary Functions
async start() {
//First, load our configuration.
async init() {
this.log('Starting App...');
//Load configuration...
this.log('Reading Configuration...');
try {
console.log("Loading Configuration...");
this.config = new ConfigurationManager(this);
this.config.loadConfig();
console.log("...Done!");
await this.config.loadConfig();
} catch(e) {
console.error("Failed to read config!");
throw new Error(e);
this.error('Failed to load configuration!');
this.error(e);
return;
}
//Next, connect to the database.
//Connect to the Database
this.log('Connecting to the Database...');
try {
console.log("Connecting to database...");
this.db = new DatabaseConnection(this);
this.db.loadQueries();//Load our prepared queries
await this.db.connect();//Connect to the DB.
console.log("...Done!");
await this.database.connect();
} catch(e) {
console.error("Failed to connect to the database!");
throw new Error(e);
this.error('Failed to connect to database!');
this.error(e);
return;
}
//Connect to our SMTP Host (For sending mail)
try {
console.log('Connecting to SMTP Server');
this.email = new Email(this);
this.log('Connecting to SMTP Server');
await this.email.connect();
console.log('...Done');
} catch(e) {
@ -84,19 +82,24 @@ class App {
//Now we need to start the server. This provides both a nice interface, as
//well as our API Handler (including 2auth callback urls)
try {
console.log("Starting Server...");
this.server = new Server(this);
this.log("Starting Server...");
await this.server.start();
console.log("...Done!");
} catch(e) {
console.error("Failed to start the server!");
throw new Error(e);
}
}
//Database Specific
onDatabaseConnected(db) { }
// Logging Functions //
log(e) {
//Will allow for extra logging
console.log(e)
}
error(e) {
console.error(e);
}
}
module.exports = App;

View File

@ -21,52 +21,59 @@
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
const fs = require('fs');
const CONFIG_PATH = './private/data/config.json';// TODO: Set this a... better way?
//Imports
const fs = require('fs');//Used for file based configurations (local testing)
const CONFIG_PATH = './private/data/config.json';// TODO: Set this a different way?
//Constructor
class ConfigurationManager {
class Configuration {
constructor(app) {
this.app = app;
this.data = {};
this.isHeroku = false;
}
loadConfig() {
//Is this a Heroku Server? I need a nicer way of doing this in the future
let process_variables = process.env;
getApp() { return this.app; }
async loadConfig(path) {
//First we need to check if this is Heroku or not...
let processVariabels = process.env;
this.isHeroku = false;
if(
process_variables !== typeof undefined &&
typeof process_variables.NODE_HOME !== typeof undefined &&
process_variables.NODE_HOME.indexOf("heroku") !== -1
processVariabels !== typeof undefined &&
typeof processVariabels.NODE_HOME !== typeof undefined &&
processVariabels.NODE_HOME.indexOf("heroku") !== -1
) {
this.isHeroku = true;
}
//Read config data
if(!this.isHeroku) {
if(this.isHeroku) {
this.data = processVariabels;
} else {
//TODO: Rather than use readSync, convert the whole function to async and use a library like fs-extra for async?
let dataRaw = fs.readFileSync(CONFIG_PATH, 'utf8');
let data = JSON.parse(dataRaw);
if(!data) throw new Error("Failed to parse Config JSON! Check for an error and try again.");
this.data = data;
} else {
this.data = process_variables;
}
}
getValueOf(key) {
has(key) {
let value = this.get(key);
if(typeof value === typeof undefined) return false;
if(!value) return false;
return value.length !== 0;
}
get(key) {
if(this.isHeroku) {
key = key.replace(/\./g, '_').toUpperCase();
if(typeof this.data[key] === typeof undefined) return null;
return this.data[key];
}
return this.getValueOfRecursive(key.split("."));
return this.getRecursive(key.split("."));
}
getValueOfRecursive(key_array, data_obj) {
getRecursive(key_array, data_obj) {
if(typeof data_obj === typeof undefined) data_obj = this.data;
if(typeof data_obj === typeof undefined) return null;
@ -78,10 +85,10 @@ class ConfigurationManager {
if(key_array.length > 1) {
if(typeof o !== typeof {}) return null;
key_array.shift();
return this.getValueOfRecursive(key_array, o);
return this.getRecursive(key_array, o);
}
return o;
}
}
module.exports = ConfigurationManager;//Export
module.exports = Configuration;

View File

@ -21,71 +21,57 @@
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
const
pgp = require('pg-promise')(),
fs = require('fs'),
path = require('path')
;
const pgp = require('pg-promise')();
const fs = require('fs');
const QUERIES_PATH = 'queries';
const QUERIES_DIRECTORY = "queries";
class DatabaseConnection {
constructor(app) {
this.app = app;
}
getConfig() {return this.app.getConfig();}//Short Hand Method
getApp() { return this.app; }
getConfig() {return this.getApp().getConfig();}
getQueriesPath() {
return path.join(__dirname, QUERIES_PATH);
}
loadQueries() {
//Load Queries
let queries = {};
if(fs.existsSync(this.getQueriesPath())) {
let queryFiles = fs.readdirSync(this.getQueriesPath());
for(var i = 0; i < queryFiles.length; i++) {
let file = queryFiles[i];
let x = fs.readFileSync(path.join(this.getQueriesPath(), file), 'utf8');
queries[file.replace(".sql", "")] = x;
}
}
this.queries = queries;
return queries;
}
isConnected() {
isConnnected() {
return typeof this.db !== typeof undefined;
}
async connect() {
await this.connectThen();
}
//Check Configuration
if(!this.getConfig().has("database.connection") && !this.getConfig().has("database.url")) throw new Error("Missing Database Connection URL!");
async connectThen() {
if(this.isConnected()) return true;
//Load queries into cache
let queries = {};
let types = fs.readdirSync(__dirname + '/' + QUERIES_DIRECTORY);
for(let i = 0; i < types.length; i++) {
//Now Scan each file in this directory
let dir = __dirname + '/' + QUERIES_DIRECTORY + '/' + types[i];
let dirContents = fs.readdirSync(dir);
for(let x = 0; x < dirContents.length; x++) {
//Now read each file within this dir..
let filePath = dir + '/' + dirContents[x];
console.log(filePath);
let query = fs.readFileSync(filePath, 'utf8');
if(
!this.getConfig().getValueOf("database.connection")
&& !this.getConfig().getValueOf("database.url")
) {
throw new Error("Missing DB Credentials.");
//Now Save our query as filename minus extension.
queries[dirContents[x].split('.')[0]] = query;
}
}
this.db = pgp(
this.getConfig().getValueOf("database.connection") ||
this.getConfig().getValueOf("database.url")
);
this.queries = queries;
//Fire the event
if(typeof this.app.onDatabaseConnected === "function") {
await this.app.onDatabaseConnected(this);
}
//Connect to Database
this.db = await pgp( this.getConfig().get("database.connection") || this.getConfig().get("database.url") );
return true;
//Now run any "Create" queries
let keys = Object.keys(queries);
for(let i = 0; i < keys.length; i++) {
let k = keys[i];
if(!k.startsWith("Create")) return;
await this.none(k);
};
}
getQuery(name) {
@ -121,6 +107,6 @@ class DatabaseConnection {
let x = await this.db.query(q, data);
return x;
}
};
}
module.exports = DatabaseConnection;

View File

@ -1,4 +1,3 @@
'use strict';
// Copyright (c) 2018 Dominic Masters
//
// MIT License
@ -22,19 +21,24 @@
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//Import
const
App = require('./app/App')
;
'use strict';
//Create
const App = require('./app/App');
//Attempt to make a global "Async Handler" for the app itself
const app = new App();
//Create entire app wrapper for safe logging and exiting from crashes etc.
(async () => {
//Start the app
return await app.start();
})().then((e) => console.log).catch((e) => {
if(!e) return;
console.error(e);
//Initialize the app
await app.init();
//Start the main thread
//End the app
})().then((e) => {
//Should never occur
}).catch((e) => {
//On Error
if(e) console.error(e);
});

View File