Asyncify everything so that we can do dependency injection
This commit is contained in:
parent
121cfc2418
commit
bd08aae1da
6 changed files with 131 additions and 91 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,4 +1,5 @@
|
|||
example-message.json
|
||||
*.sqlite
|
||||
*.pcapng
|
||||
*.png
|
||||
*.stl
|
||||
|
|
72
server/bootstrap/cli.mjs
Normal file
72
server/bootstrap/cli.mjs
Normal 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;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,9 @@
|
|||
"use strict";
|
||||
|
||||
import { promises as fs } from 'fs';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
import a from 'awilix';
|
||||
|
||||
import Ansi from '../Helpers/Ansi.mjs';
|
||||
|
@ -10,11 +14,15 @@ import MessageHandler from '../ttn-app-server/MessageHandler.mjs';
|
|||
import settings from './settings.mjs';
|
||||
import database_init from '../bootstrap/database_init.mjs';
|
||||
|
||||
const root_dir = path.dirname(path.dirname(fileURLToPath(import.meta.url)));
|
||||
|
||||
export default async function setup() {
|
||||
const c = a.createContainer({
|
||||
injectionMode: a.InjectionMode.PROXY
|
||||
});
|
||||
|
||||
c.register({
|
||||
root_dir: a.asValue(root_dir),
|
||||
settings: a.asValue(settings),
|
||||
ansi: a.asClass(Ansi).singleton(),
|
||||
log: a.asClass(Log).singleton(),
|
||||
|
@ -23,9 +31,30 @@ c.register({
|
|||
MessageHandler: a.asClass(MessageHandler)
|
||||
});
|
||||
|
||||
c.loadModules("../Repos.SQLite/*.mjs", {
|
||||
register: a.asClass,
|
||||
lifetime: a.Lifetime.SINGLETON
|
||||
});
|
||||
let repo_filenames = await fs.readdir(path.join(root_dir, "./Repos.SQLite"));
|
||||
|
||||
export default c;
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -5,9 +5,9 @@ import Database from 'better-sqlite3';
|
|||
|
||||
var db = null;
|
||||
|
||||
async function init({ settings: { database: { filename, options } } }) {
|
||||
function init({ settings: { 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
import path from 'path';
|
||||
|
||||
import c from './bootstrap/container.mjs';
|
||||
|
||||
const a = c.resolve("ansi");
|
||||
|
||||
export default function(settings) {
|
||||
export default function({ settings, ansi : a }) {
|
||||
|
||||
console.log(`${settings.program_name}, ${settings.version}
|
||||
${a.locol}By Starbeamrainbowlabs${a.reset}
|
||||
|
|
|
@ -2,74 +2,16 @@
|
|||
"use strict";
|
||||
|
||||
// 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';
|
||||
import { decode_payload } from './ttn-app-server/DecodePayload.mjs';
|
||||
|
||||
const settings = c.resolve("settings");
|
||||
const a = c.resolve("ansi");
|
||||
const l = c.resolve("log");
|
||||
|
||||
// 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
|
||||
async function run() {
|
||||
try {
|
||||
let c = await setup();
|
||||
await cli(c);
|
||||
} catch(error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
// 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(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;
|
||||
}
|
||||
run();
|
||||
|
|
Loading…
Reference in a new issue