khutzpa
Version:
Node powered, cross-platform, drop-in replacement for Chutzpah.exe
159 lines (136 loc) • 4.51 kB
JavaScript
const fs = require("fs");
const { isString } = require("./stringManipulation");
const settingsCue = "x:";
let areDebugging = false;
let logLevel = 50;
let logAllToFile = false;
// TODO: Probably should nix the logLevel stuff. Just verbose or no.
let verboseLogging = false;
function csvToLiteral(csv) {
// we're not escaping commas for now.
// csvs are fun, though. https://stackoverflow.com/a/23574271/1028230
var values = csv.split(",");
var literal = {};
var ignore = [];
values.forEach((x, i) => {
if (ignore.indexOf(i) === -1) {
switch (x) {
case "logLevel":
literal[x] = parseInt(values[i + 1], 10);
ignore.push(i + 1);
break;
default:
literal[x] = true;
}
}
});
return literal;
}
function setVerboseLogging(value) {
verboseLogging = value;
}
// https://stackoverflow.com/a/20392392/1028230
// If you don't care about primitives and only objects then this function
// is for you, otherwise look elsewhere.
// This function will return `false` for any valid json primitive.
// EG, 'true' -> false
// '123' -> false
// 'null' -> false
// '"I'm a string"' -> false
function isParseable(jsonString) {
try {
var o = JSON.parse(jsonString);
// Handle non-exception-throwing cases:
// Neither JSON.parse(false) or JSON.parse(1234) throw errors, hence the type-checking,
// but... JSON.parse(null) returns null, and typeof null === "object",
// so we must check for that, too. Thankfully, null is falsey, so this suffices:
if (o && typeof o === "object") {
return o;
}
} catch (e) {
// ain't json
}
return false;
}
function debugLog() {
if (verboseLogging) {
alwaysLog(...arguments);
}
}
// yes, we lose the settings hack here.
function alwaysLog() {
logit(`${settingsCue}alwaysLog`, ...arguments);
}
function log50() {
logit(`${settingsCue}logLevel,50`, ...arguments);
}
function logit() {
var args = [].slice.call(arguments);
// eslint-disable-next-line
var settings = logAllToFile
? // eslint-disable-next-line
{
tofile: true,
}
: {};
// this is really dumb, but it's useful-ish if I want to preserve
// the equiv of what's left of arguments...
if (isString(args[0]) || settings.tofile) {
try {
// why in heavens name is the first arg for settings
// have to be a json string and not an object literal?
// what in the world was your plan here? sheesh. ;)
var wasParseable = isParseable(args[0]);
settings = args[0].startsWith(settingsCue)
? csvToLiteral(args[0].substring(settingsCue.length))
: wasParseable
? Object.assign(settings, wasParseable)
: settings;
// Now throw away the settings so we don't log it.
if (wasParseable || args[0].startsWith(settingsCue)) {
args.shift();
}
if (settings.tofile) {
args.forEach((arg) =>
fs.appendFileSync(
"./log.txt",
`${Date().toString()}:: ${
isString(arg) ? arg : JSON.stringify(arg, null, " ")
}\n`
)
);
}
} catch (e) {
// then the first arg probably wasn't settings
// just log it.
}
}
if (settings.logLevel >= logLevel || logLevel === 0 || settings.alwaysLog) {
if (settings.asjson || args.length === 1) {
args.forEach((arg) =>
console.log(isString(arg) ? arg : JSON.stringify(arg, null, " "))
);
} else {
console.log(...args);
}
}
}
// this is just so we can make eslint shaddup.
function mcDebugger() {
if (areDebugging) {
// eslint-disable-next-line no-debugger
debugger;
}
}
module.exports = {
alwaysLog,
areDebugging,
debugLog,
isParseable,
log50,
logAllToFile,
logit,
logLevel,
mcDebugger,
setVerboseLogging,
};