Restructuring folders [ Broken ]
This commit is contained in:
@ -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;
|
||||
|
@ -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;
|
@ -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;
|
||||
|
@ -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);
|
||||
});
|
||||
|
Reference in New Issue
Block a user