@mdfriday/foundry
Version:
The core engine of MDFriday. Convert Markdown and shortcodes into fully themed static sites – Hugo-style, powered by TypeScript.
183 lines • 6.55 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.Logger = void 0;
exports.New = New;
exports.NewWithConfig = NewWithConfig;
const util = __importStar(require("util"));
const types_1 = require("./types");
class Logger {
constructor(config) {
this.config = {
enableCaller: true,
jsonFormat: true,
...config
};
this.fields = {};
}
shouldLog(level) {
const levels = [types_1.LogLevel.DEBUG, types_1.LogLevel.INFO, types_1.LogLevel.WARN, types_1.LogLevel.ERROR, types_1.LogLevel.FATAL];
const configLevelIndex = levels.indexOf(this.config.level);
const msgLevelIndex = levels.indexOf(level);
return msgLevelIndex >= configLevelIndex;
}
getCaller() {
if (!this.config.enableCaller) {
return undefined;
}
const stack = new Error().stack;
if (!stack)
return undefined;
const lines = stack.split('\n');
// Skip the first 4 lines (Error, getCaller, log method, actual caller)
const callerLine = lines[4];
if (!callerLine)
return undefined;
// Extract file and line info from stack trace
const match = callerLine.match(/at .* \((.+):(\d+):(\d+)\)/);
if (match) {
const [, file, line] = match;
const filename = file.split('/').pop();
return `${filename}:${line}`;
}
// Fallback pattern
const simpleMatch = callerLine.match(/at (.+):(\d+):(\d+)/);
if (simpleMatch) {
const [, file, line] = simpleMatch;
const filename = file.split('/').pop();
return `${filename}:${line}`;
}
return undefined;
}
formatMessage(template, args) {
if (args.length === 0) {
return template;
}
return util.format(template, ...args);
}
writeLog(level, message) {
if (!this.shouldLog(level)) {
return;
}
const entry = {
level,
timestamp: new Date().toISOString(),
message,
...this.fields
};
const caller = this.getCaller();
if (caller) {
entry.caller = caller;
}
const output = this.config.jsonFormat
? JSON.stringify(entry)
: this.formatPlainText(entry);
// Route error and fatal to stderr, others to stdout (like Go implementation)
if (level === types_1.LogLevel.ERROR || level === types_1.LogLevel.FATAL) {
process.stderr.write(output + '\n');
}
else {
process.stdout.write(output + '\n');
}
// Exit on fatal error
if (level === types_1.LogLevel.FATAL) {
process.exit(1);
}
}
formatPlainText(entry) {
const parts = [entry.timestamp, entry.level.toUpperCase()];
if (entry.caller) {
parts.push(`[${entry.caller}]`);
}
parts.push(entry.message);
// Add extra fields
const extraFields = Object.keys(entry)
.filter(key => !['level', 'timestamp', 'message', 'caller'].includes(key))
.map(key => `${key}=${JSON.stringify(entry[key])}`)
.join(' ');
if (extraFields) {
parts.push(extraFields);
}
return parts.join(' ');
}
// Direct logging methods
debug(message, ...args) {
this.writeLog(types_1.LogLevel.DEBUG, this.formatMessage(message, args));
}
info(message, ...args) {
this.writeLog(types_1.LogLevel.INFO, this.formatMessage(message, args));
}
warn(message, ...args) {
this.writeLog(types_1.LogLevel.WARN, this.formatMessage(message, args));
}
error(message, ...args) {
this.writeLog(types_1.LogLevel.ERROR, this.formatMessage(message, args));
}
fatal(message, ...args) {
this.writeLog(types_1.LogLevel.FATAL, this.formatMessage(message, args));
}
// Formatted logging methods (printf-style)
debugf(template, ...args) {
this.writeLog(types_1.LogLevel.DEBUG, this.formatMessage(template, args));
}
infof(template, ...args) {
this.writeLog(types_1.LogLevel.INFO, this.formatMessage(template, args));
}
warnf(template, ...args) {
this.writeLog(types_1.LogLevel.WARN, this.formatMessage(template, args));
}
errorf(template, ...args) {
this.writeLog(types_1.LogLevel.ERROR, this.formatMessage(template, args));
}
fatalf(template, ...args) {
this.writeLog(types_1.LogLevel.FATAL, this.formatMessage(template, args));
}
// Create a new logger with additional fields
with(fields) {
const newLogger = new Logger(this.config);
newLogger.fields = { ...this.fields, ...fields };
return newLogger;
}
}
exports.Logger = Logger;
// Factory function similar to Go's New function
function New(level = types_1.LogLevel.INFO) {
return new Logger({ level });
}
// Create logger with custom config
function NewWithConfig(config) {
return new Logger(config);
}
//# sourceMappingURL=logger.js.map