@scayle/storefront-core
Version:
Collection of essential utilities to work with the Storefront API
131 lines (130 loc) • 3.44 kB
JavaScript
export class Log {
/**
* The default log instance, logging to the console with the `global` namespace.
*/
static default = new this({
space: "global",
handler: consoleLogHandler
});
_handler;
_space;
_type = "log";
/**
* Creates a new Log instance.
*
* @param options Options for the logger.
*/
constructor(options) {
this._handler = options?.handler || Log.default._handler;
this._space = options?.space || Log.default._space;
}
/**
* Logs a debug message.
*
* @param message The debug message.
* @param data Optional additional data.
*/
debug(message, data) {
this.write("debug", message, data);
}
/**
* Logs an informational message.
*
* @param message The informational message.
* @param data Optional additional data.
*/
info(message, data) {
this.write("info", message, data);
}
/**
* Logs a warning message.
*
* @param message The warning message.
* @param data Optional additional data.
*/
warn(message, data) {
this.write("warn", message, data);
}
/**
* Logs an error message.
*
* @param message The error message or an Error object.
* @param data Optional additional data.
*/
error(message, data) {
const error = message instanceof Error ? message : null;
if (error) {
data = {
error: message,
...data
};
}
this.write("error", error?.message ?? message, data);
}
/**
* Writes a log entry.
*
* @param level The log level.
* @param message The log message.
* @param data Optional additional data.
*/
write(level, message, data) {
if (typeof data !== "undefined") {
data = typeof data !== "object" ? { data } : data;
}
if (this._handler) {
this._handler({ level, message, data, space: this._space });
} else {
const logFunc = console[level] || console.log;
logFunc.apply(console, data ? [message, data] : [message]);
}
}
/**
* Creates a new Log instance with a sub-namespace.
* Namespaces are separated by dots (e.g., "global.api.getUser").
*
* @param subSpace The sub-namespace to add in camel-case (e.g. `api` and `api.getUser`)
*
* @returns A new Log instance with the updated namespace.
*/
space(subSpace) {
return new Log({
space: `${this._space}.${subSpace}`,
handler: this._handler
});
}
/**
* Measures the execution time of an asynchronous function and logs a debug message.
*
* @param message A message to include in the log output.
* @param func The asynchronous function to time.
*
* @returns A Promise that resolves with the result of the timed function.
*/
async time(message, func) {
const start = Date.now();
const result = await func();
const end = Date.now();
this.debug(`${message} took ${end - start}ms`);
return result;
}
/**
* Attaches the log instance to a request object.
* This is typically used in server middleware.
*
* @param req The request object.
* @param log The Log instance to attach.
*
* @example
* Log.attachToRequest(req, new Log({ space: 'myModule' }))
*
* @deprecated
*/
static attachToRequest(req, log) {
req.$log = log;
}
}
function consoleLogHandler({ level, message, data }) {
const logFunc = console[level] || console.log;
logFunc.apply(console, data ? [message, data] : [message]);
}