Asyncify everything so that we can do dependency injection

This commit is contained in:
Starbeamrainbowlabs 2019-07-10 14:11:46 +01:00
parent 121cfc2418
commit bd08aae1da
6 changed files with 131 additions and 91 deletions

1
.gitignore vendored
View File

@ -1,4 +1,5 @@
example-message.json example-message.json
*.sqlite
*.pcapng *.pcapng
*.png *.png
*.stl *.stl

72
server/bootstrap/cli.mjs Normal file
View File

@ -0,0 +1,72 @@
"use strict";
import show_help from '../help.mjs';
import { decode_payload } from '../ttn-app-server/DecodePayload.mjs';
export default async function(c) {
let { ansi: a, log: l, settings } = c.cradle;
// 2: CLI Argument Parsing
let args = process.argv.slice(2); // Slice out the node binary name and the filename
let extras = [];
for(let i = 0; i < args.length; i++) {
if(!args[i].startsWith("-")) {
extras.push(args[i]);
continue;
}
switch(args[i]) {
case "--help":
case "-h":
show_help(c.cradle);
process.exit();
break;
case "--version":
case "-v":
console.log(program.version);
break;
// Add more arguments here
}
}
// 3: Environment Variable Parsing
// process.env.XYZ
// 4: Run
if(extras.length < 1) {
console.error(`${a.fred}${a.hicol}Error: No subcommand specified.${a.reset}`);
show_help(c.cradle);
process.exit();
}
l.log(`${a.fgreen}${a.hicol}*** LoRaWAN Signal Mapper ***${a.reset}`);
switch(extras[0]) {
case "ttn-app-server":
l.log(`${a.fgreen}${a.hicol}Starting The Things Network application server${a.reset}`);
let app_server = c.resolve("TTNAppServer");
await app_server.run();
break;
case "decode-test":
l.log(`${a.fgreen}${a.hicol}Decoding message${a.reset}`);
if(process.argv.length < 4) {
l.error("No message specified. Specify the message to decode in single quotes directly after 'decode-test'.");
process.exit(1);
}
l.log("Input: ", process.argv[3]);
l.log("Output: ", decode_payload(process.argv[3]));
break;
default:
console.error(`${a.fred}${a.hicol}Error: Subcommand '${extras[0]}' not recognised.${a.reset}`);
console.error( `${a.fred}Perhaps you mistyped it, or it hasn't been implemented yet?`);
process.exit(1);
break;
}
}

View File

@ -1,5 +1,9 @@
"use strict"; "use strict";
import { promises as fs } from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
import a from 'awilix'; import a from 'awilix';
import Ansi from '../Helpers/Ansi.mjs'; import Ansi from '../Helpers/Ansi.mjs';
@ -10,22 +14,47 @@ import MessageHandler from '../ttn-app-server/MessageHandler.mjs';
import settings from './settings.mjs'; import settings from './settings.mjs';
import database_init from '../bootstrap/database_init.mjs'; import database_init from '../bootstrap/database_init.mjs';
const c = a.createContainer({ const root_dir = path.dirname(path.dirname(fileURLToPath(import.meta.url)));
injectionMode: a.InjectionMode.PROXY
});
c.register({ export default async function setup() {
settings: a.asValue(settings), const c = a.createContainer({
ansi: a.asClass(Ansi).singleton(), injectionMode: a.InjectionMode.PROXY
log: a.asClass(Log).singleton(), });
database: a.asFunction(database_init).singleton(),
TTNAppServer: a.asClass(TTNAppServer),
MessageHandler: a.asClass(MessageHandler)
});
c.loadModules("../Repos.SQLite/*.mjs", { c.register({
register: a.asClass, root_dir: a.asValue(root_dir),
lifetime: a.Lifetime.SINGLETON settings: a.asValue(settings),
}); ansi: a.asClass(Ansi).singleton(),
log: a.asClass(Log).singleton(),
export default c; database: a.asFunction(database_init).singleton(),
TTNAppServer: a.asClass(TTNAppServer),
MessageHandler: a.asClass(MessageHandler)
});
let repo_filenames = await fs.readdir(path.join(root_dir, "./Repos.SQLite"));
for(let repo_filename of repo_filenames) {
let class_root = await import(path.join(root_dir, `./Repos.SQLite/${repo_filename}`)),
class_name = class_root.default.prototype.constructor.name;
c.register(
class_name,
a.asClass(class_root.default).singleton(),
);
}
// console.log(c.registrations);
// c.loadModules([
// "./Repos.SQLite/*.mjs"
// // "./Repos.SQLite/ReadingRepo.mjs"
// ], {
// cwd: root_dir,
// resolverOptions: {
// register: a.asClass,
// lifetime: a.Lifetime.SINGLETON
// }
// });
return c;
}

View File

@ -5,9 +5,9 @@ import Database from 'better-sqlite3';
var db = null; var db = null;
async function init({ settings: { database: { filename, options } } }) { function init({ settings: { database: { filename, options } } }) {
db = new Database(filename, options); db = new Database(filename, options);
db.exec(await fs.promises.readFile("../db_template.sql", "utf8")); db.exec(fs.readFileSync("../db_template.sql", "utf8"));
return db; return db;
} }

View File

@ -1,10 +1,6 @@
import path from 'path'; import path from 'path';
import c from './bootstrap/container.mjs'; export default function({ settings, ansi : a }) {
const a = c.resolve("ansi");
export default function(settings) {
console.log(`${settings.program_name}, ${settings.version} console.log(`${settings.program_name}, ${settings.version}
${a.locol}By Starbeamrainbowlabs${a.reset} ${a.locol}By Starbeamrainbowlabs${a.reset}

View File

@ -2,74 +2,16 @@
"use strict"; "use strict";
// 1: Setup & Imports // 1: Setup & Imports
import c from './bootstrap/container.mjs'; import setup from './bootstrap/container.mjs';
import cli from './bootstrap/cli.mjs';
import show_help from './help.mjs'; async function run() {
import { decode_payload } from './ttn-app-server/DecodePayload.mjs'; try {
let c = await setup();
const settings = c.resolve("settings"); await cli(c);
const a = c.resolve("ansi"); } catch(error) {
const l = c.resolve("log"); console.error(error);
// 2: CLI Argument Parsing
let args = process.argv.slice(2); // Slice out the node binary name and the filename
let extras = [];
for(let i = 0; i < args.length; i++) {
if(!args[i].startsWith("-")) {
extras.push(args[i]);
continue;
}
switch(args[i]) {
case "--help":
case "-h":
show_help(settings);
process.exit();
break;
case "--version":
case "-v":
console.log(program.version);
break;
// Add more arguments here
} }
} }
// 3: Environment Variable Parsing run();
// process.env.XYZ
// 4: Run
if(extras.length < 1) {
console.error(`${a.fred}${a.hicol}Error: No subcommand specified.${a.reset}`);
show_help(settings);
process.exit();
}
l.log(`${a.fgreen}${a.hicol}*** LoRaWAN Signal Mapper ***${a.reset}`);
switch(extras[0]) {
case "ttn-app-server":
l.log(`${a.fgreen}${a.hicol}Starting The Things Network application server${a.reset}`);
let app_server = c.resolve("TTNAppServer");
app_server.run();
break;
case "decode-test":
l.log(`${a.fgreen}${a.hicol}Decoding message${a.reset}`);
if(process.argv.length < 4) {
l.error("No message specified. Specify the message to decode in single quotes directly after 'decode-test'.");
process.exit(1);
}
l.log("Input: ", process.argv[3]);
l.log("Output: ", decode_payload(process.argv[3]));
break;
default:
console.error(`${a.fred}${a.hicol}Error: Subcommand '${extras[0]}' not recognised.${a.reset}`);
console.error( `${a.fred}Perhaps you mistyped it, or it hasn't been implemented yet?`);
process.exit(1);
break;
}