@vepler/logger
Version:
A lightweight, type-safe logging wrapper around Pino, built by Vepler for modern TypeScript applications.
298 lines • 10.4 kB
JavaScript
;
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var pino_1 = __importDefault(require("pino"));
/**
* Default logger options
*/
var DEFAULT_OPTIONS = {
formatters: {
level: function (label) { return ({ level: label.toUpperCase() }); },
},
timestamp: pino_1.default.stdTimeFunctions.isoTime,
redact: {
paths: ['password', 'token', 'authorization', 'secret'],
remove: true
}
};
/**
* A lightweight, type-safe logging wrapper around Pino
*/
var PinoWrapper = /** @class */ (function () {
function PinoWrapper(logger) {
this.context = {};
this.logger = logger;
}
/**
* Initialize the logger with optional configuration
*/
PinoWrapper.initialize = function (options) {
if (!PinoWrapper.instance) {
var mergedOptions = __assign(__assign({}, DEFAULT_OPTIONS), options);
var logger = (0, pino_1.default)(mergedOptions);
PinoWrapper.instance = new PinoWrapper(logger);
}
};
/**
* Ensure the logger is initialized
*/
PinoWrapper.ensureInitialized = function () {
if (!PinoWrapper.instance) {
PinoWrapper.initialize();
}
};
/**
* Set global context that will be included in all subsequent logs
*/
PinoWrapper.setContext = function (context) {
PinoWrapper.ensureInitialized();
PinoWrapper.instance.context = __assign(__assign({}, PinoWrapper.instance.context), context);
};
/**
* Clear all global context
*/
PinoWrapper.clearContext = function () {
PinoWrapper.ensureInitialized();
PinoWrapper.instance.context = {};
};
/**
* Helper to merge context with additional fields
*/
PinoWrapper.mergeContext = function (additionalContext) {
return __assign(__assign({}, PinoWrapper.instance.context), additionalContext);
};
/**
* Format error objects for structured logging
*/
PinoWrapper.formatError = function (error) {
if (!(error instanceof Error)) {
if (error === null || error === undefined) {
return { message: 'Unknown error' };
}
if (typeof error === 'string') {
return { message: error };
}
if (typeof error === 'object') {
return __assign({}, error);
}
return { message: String(error) };
}
// Extract all enumerable properties from the error
var errorProperties = Object.getOwnPropertyNames(error).reduce(function (acc, key) {
if (key !== 'message' && key !== 'stack' && key !== 'name') {
acc[key] = error[key];
}
return acc;
}, {});
return __assign({ type: error.name, message: error.message, stack: error.stack }, errorProperties);
};
/**
* Core log method that all other methods use
*/
PinoWrapper.log = function (level, args) {
PinoWrapper.ensureInitialized();
// Handle different argument patterns
if (args.length === 0) {
// No arguments, just log empty message
PinoWrapper.instance.logger[level](PinoWrapper.instance.context, '');
return;
}
var first = args[0];
// Case 1: Just a message string
if (typeof first === 'string' && args.length === 1) {
PinoWrapper.instance.logger[level](PinoWrapper.instance.context, first);
return;
}
// Case 2: Error object (for error and fatal levels)
if (level === 'error' || level === 'fatal') {
if (first instanceof Error && args.length === 1) {
var errorData = this.formatError(first);
var context_1 = __assign(__assign({}, PinoWrapper.instance.context), { error: errorData });
PinoWrapper.instance.logger[level](context_1, first.message);
return;
}
if (first instanceof Error && args.length >= 2 && typeof args[1] === 'string') {
var errorData = this.formatError(first);
var message_1 = args[1];
var context_2 = __assign(__assign({}, PinoWrapper.instance.context), { error: errorData });
// Add additional context if provided
if (args.length > 2 && typeof args[2] === 'object' && args[2] !== null) {
context_2 = __assign(__assign({}, context_2), args[2]);
}
PinoWrapper.instance.logger[level](context_2, message_1);
return;
}
}
// Case 3: Message with context object
if (typeof first === 'string' && args.length >= 2 && typeof args[1] === 'object' && args[1] !== null) {
var message_2 = first;
var context_3 = args[1];
// Special handling for error contexts
if ((level === 'error' || level === 'fatal') && 'error' in context_3) {
var errorData = this.formatError(context_3.error);
var _error = context_3.error, restContext = __rest(context_3, ["error"]);
var mergedContext_1 = __assign(__assign(__assign({}, PinoWrapper.instance.context), restContext), { error: errorData });
PinoWrapper.instance.logger[level](mergedContext_1, message_2);
return;
}
var mergedContext = __assign(__assign({}, PinoWrapper.instance.context), context_3);
PinoWrapper.instance.logger[level](mergedContext, message_2);
return;
}
// Case 4: Just an object (no message)
if (typeof first === 'object' && first !== null && args.length === 1) {
var context_4 = __assign(__assign({}, PinoWrapper.instance.context), first);
PinoWrapper.instance.logger[level](context_4, '');
return;
}
// Fallback: Treat first arg as message, everything else as JSON
var message = String(first);
var context = PinoWrapper.instance.context;
PinoWrapper.instance.logger[level](context, message);
};
/**
* Log at INFO level
* Supports:
* - info(message)
* - info(message, context)
* - info(context)
*/
PinoWrapper.info = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
this.log('info', args);
};
/**
* Log at ERROR level
* Supports:
* - error(message)
* - error(error)
* - error(message, context)
* - error(context)
* - error(error, message)
* - error(error, message, context)
* - error(message, { error })
*/
PinoWrapper.error = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
this.log('error', args);
};
/**
* Log at DEBUG level
* Supports:
* - debug(message)
* - debug(message, context)
* - debug(context)
*/
PinoWrapper.debug = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
this.log('debug', args);
};
/**
* Log at WARN level
* Supports:
* - warn(message)
* - warn(message, context)
* - warn(context)
*/
PinoWrapper.warn = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
this.log('warn', args);
};
/**
* Log at FATAL level
* Supports:
* - fatal(message)
* - fatal(error)
* - fatal(message, context)
* - fatal(context)
* - fatal(error, message)
* - fatal(error, message, context)
* - fatal(message, { error })
*/
PinoWrapper.fatal = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
this.log('fatal', args);
};
/**
* Log at TRACE level
* Supports:
* - trace(message)
* - trace(message, context)
* - trace(context)
*/
PinoWrapper.trace = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
this.log('trace', args);
};
/**
* Create a child logger with bound context
*/
PinoWrapper.child = function (bindings) {
PinoWrapper.ensureInitialized();
var childLogger = PinoWrapper.instance.logger.child(bindings);
return new PinoWrapper(childLogger);
};
/**
* Get the underlying Pino logger instance
*/
PinoWrapper.getRawLogger = function () {
PinoWrapper.ensureInitialized();
return PinoWrapper.instance.logger;
};
/**
* Flush all buffered logs
*/
PinoWrapper.flush = function () {
PinoWrapper.ensureInitialized();
return new Promise(function (resolve) {
PinoWrapper.instance.logger.flush(function () {
resolve();
});
});
};
return PinoWrapper;
}());
exports.default = PinoWrapper;
//# sourceMappingURL=index.js.map