configManager now supports logging via tslog / cleanup / loglevel 0 in devmode 3 in prod

This commit is contained in:
Leon Meier 2025-02-24 22:55:18 +01:00
parent 744ab40a6b
commit 611a4a0ead
4 changed files with 55 additions and 52 deletions

View File

@ -1,7 +1,7 @@
import log from './log.js';
import ConfigManager from '../libs/configManager.js';
import __path from './path.js';
import _ from 'lodash';
import log from './log.js';
// Create a new config instance.
const config = new ConfigManager(__path + '/config.json', true, {
@ -11,8 +11,6 @@ const config = new ConfigManager(__path + '/config.json', true, {
http_domain: 'example.org',
http_enable_hsts: false,
devmode: true
});
!config.global.devmode && log.core.error('devmode active! Do NOT use this in prod!');
});//, log.core); // Disabled due to Cyclic dependencies with log handler (specifically-> devmode for loglevel)
export default config;

View File

@ -1,42 +1,43 @@
import { Logger,ISettingsParam } from "tslog";
import config from './config.js';
import { Logger, ISettingsParam } from 'tslog';
// You can ignore every log message from being processed until a certain severity. Default severities are:
// 0: silly, 1: trace, 2: debug, 3: info, 4: warn, 5: error, 6: fatal
function loggerConfig(name: string): ISettingsParam<unknown> {
return {
type: "pretty", // pretty, json, hidden
type: 'pretty', // pretty, json, hidden
name: name,
hideLogPositionForProduction: true,
prettyLogTemplate: "{{dateIsoStr}} {{logLevelName}} {{nameWithDelimiterPrefix}} "
}
prettyLogTemplate: '{{dateIsoStr}} {{logLevelName}} {{nameWithDelimiterPrefix}} ',
minLevel: config.global.devmode ? 0 : 3 // Only display info, warn, error, fatal in production mode
};
}
type log = {
core: Logger<unknown>
db: Logger<unknown>
web: Logger<unknown>
S3: Logger<unknown>
auth: Logger<unknown>
api?: Logger<unknown>
frontend?: Logger<unknown>
core: Logger<unknown>;
db: Logger<unknown>;
web: Logger<unknown>;
auth: Logger<unknown>;
api?: Logger<unknown>;
frontend?: Logger<unknown>;
};
// FIXME: any type
let log: log = {
core: new Logger(loggerConfig("Core")),
db: new Logger(loggerConfig("DB")),
web: new Logger(loggerConfig("Web")),
S3: new Logger(loggerConfig("S3")),
auth: new Logger(loggerConfig("Auth")),
// helper: new Logger(loggerConfig("HELPER")),
core: new Logger(loggerConfig('Core')),
db: new Logger(loggerConfig('DB')),
web: new Logger(loggerConfig('Web')),
auth: new Logger(loggerConfig('Auth'))
// helper: new Logger(loggerConfig("HELPER")),
};
log["api"] = log.web.getSubLogger({ name: "API" });
log["frontend"] = log.web.getSubLogger({ name: "Frontend" });
log['api'] = log.web.getSubLogger({ name: 'API' });
log['frontend'] = log.web.getSubLogger({ name: 'Frontend' });
// log.core.silly("Hello from core");
//log.api.trace("Hello from api");
//log.frontend.trace("Hello from frontend");
// log.api.trace("Hello from api");
// log.frontend.trace("Hello from frontend");
// log.core.debug("Hello from core");
// log.core.info("Hello from core");
// log.core.warn("Hello from core");

View File

@ -1,28 +1,22 @@
// MARK: Imports
import path from 'node:path';
import fs from 'node:fs';
import ChildProcess from 'child_process';
import __path from './handlers/path.js';
import log from './handlers/log.js';
import db from './handlers/db.js';
//import db from './handlers/db.js';
import config from './handlers/config.js';
// Express & more
import express from 'express';
import cors from 'cors';
import helmet from 'helmet';
import session from 'express-session';
import fileUpload from 'express-fileupload';
import bodyParser, { Options } from 'body-parser';
import { Eta } from 'eta';
import passport from 'passport';
import ChildProcess from 'child_process';
//import fileUpload from 'express-fileupload';
import bodyParser from 'body-parser';
import { Eta, Options } from 'eta';
import routes from './routes/index.js';
import fs from 'node:fs';
log.core.trace('Running from path: ' + __path);
// MARK: Express
const app = express();
@ -84,7 +78,7 @@ if (!config.global.devmode) {
); // Add headers
}
app.use(fileUpload());
//app.use(fileUpload());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
@ -95,6 +89,10 @@ app.listen(config.global.http_port, config.global.http_listen_address, () => {
log.web.info(`Listening at http://${config.global.http_listen_address}:${config.global.http_port}`);
});
log.core.trace('Running from path: ' + __path);
config.global.devmode && log.core.error('DEVMODE ACTIVE! Do NOT use this in prod!');
// MARK: Helper Functions
function buildEtaEngine() {
return (path: string, opts: Options, callback: CallableFunction) => {

View File

@ -1,6 +1,7 @@
import fs from 'node:fs';
import _ from 'lodash';
import { randomUUID, randomBytes } from 'crypto';
import { randomBytes } from 'crypto';
import { Logger } from 'tslog';
export type configObject = Record<any, any>;
@ -17,18 +18,25 @@ export default class config {
global: configObject;
replaceSecrets: boolean;
#logger: Logger<unknown> | typeof console;
/**
* Creates an instance of config.
*
* @constructor
* @param {string} configPath Path to config file.
* @param {boolean} replaceSecrets Whether to replace secrets with generated values.
* @param {object} configPreset Default config object with default values.
* @param {Logger<unknown> | typeof console} [logger] Optional (tslog) logger.
*/
constructor(configPath: string, replaceSecrets: boolean, configPreset: object) {
constructor(configPath: string, replaceSecrets: boolean, configPreset: object, logger?: Logger<unknown> | typeof console) {
this.#configPath = configPath;
this.global = configPreset;
this.replaceSecrets = replaceSecrets;
this.#logger = logger ?? console;
this.#logger.info(`Initializing config manager with path: ${this.#configPath}`);
try {
// Read config
const data = fs.readFileSync(this.#configPath, 'utf8');
@ -40,11 +48,11 @@ export default class config {
} catch (err: any) {
// If file does not exist, create it.
if (err.code === 'ENOENT') {
console.log(`Config file does not exist. Creating it at ${this.#configPath} now.`);
this.#logger.info(`Config file does not exist. Creating it at ${this.#configPath} now.`);
this.save_config();
return;
}
console.error(`Could not read config file at ${this.#configPath} due to: ${err}`);
this.#logger.error(`Could not read config file at ${this.#configPath} due to: ${err}`);
// Exit process.
process.exit(1);
}
@ -58,15 +66,15 @@ export default class config {
// If enabled replace tokens defines as "gen" with random token
if (this.replaceSecrets) {
// Replace tokens with value "gen"
this.generate_secrets(this.global, 'gen')
this.generate_secrets(this.global, 'gen');
}
fs.writeFileSync(this.#configPath, JSON.stringify(this.global, null, 8));
} catch (err) {
console.error(`Could not write config file at ${this.#configPath} due to: ${err}`);
this.#logger.error(`Could not write config file at ${this.#configPath} due to: ${err}`);
return;
}
console.log(`Successfully written config file to ${this.#configPath}`);
this.#logger.info(`Successfully written config file to ${this.#configPath}`);
}
/**
@ -77,11 +85,10 @@ export default class config {
generate_secrets(obj: configObject, placeholder: string) {
const stack = [obj];
while (stack?.length > 0) {
const currentObj:any = stack.pop();
const currentObj: any = stack.pop();
Object.keys(currentObj).forEach((key) => {
if (currentObj[key] === placeholder) {
console.log('Generating secret: ' + key);
this.#logger.info('Generating secret: ' + key);
currentObj[key] = randomBytes(48).toString('base64').replace(/\W/g, '');
}
@ -93,7 +100,6 @@ export default class config {
}
}
/*
**** Example ****