New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

another-logger

Package Overview
Dependencies
Maintainers
1
Versions
20
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

another-logger - npm Package Compare versions

Comparing version 3.0.0-pre2 to 3.0.0-pre3

.github/FUNDING.yml

177

index.js

@@ -17,2 +17,3 @@ 'use strict';

label: '',
stream: process.stdout,
};

@@ -22,3 +23,3 @@ const defaultLevels = {

info: {style: 'blue'},
log: {text: 'info', style: 'blue'},
log: {style: 'blue'},
success: {style: 'green'},

@@ -44,4 +45,4 @@ warn: {text: 'warning', style: 'yellow'},

baseLevels = Object.assign({}, defaultLevels, baseLevels);
// default config sets no ignored levels, so no assign necessary, but we do have
// to resolve arrays o objects
// Default config sets no ignored levels, so no assign necessary, but we do have
// to resolve arrays or objects
if (Array.isArray(baseConfig.ignoredLevels)) {

@@ -55,7 +56,8 @@ baseConfig.ignoredLevels = baseConfig.ignoredLevels.reduce((acc, val) => {

/**
* Applies a terminal color style to a bit of text via `chalk`.
* Applies a terminal color style to a bit of text via `chalk`. If `chalk` is
* not in the project, returns the text as-is.
* @todo support chalk's fn calls, e.g. .rgb()
*
* @param {string} text The text to apply the style to
* @param {string} styleString The style string to apply, a space- or
* @param {string} style The style string to apply, a space- or
* period-separated list of *named* (no custom rgb() calls, etc.) `chalk` styles

@@ -66,5 +68,6 @@ * (see the `chalk` package documentation for a list:

*/
function style (text, styleString) {
if (!chalk) return text;
const parts = styleString.split(/[. ]/g);
function applyStyle (text, style) {
if (!chalk || !style) return text;
if (typeof style === 'function') return style(text);
const parts = style.split(/[. ]/g);
let stylefn = chalk;

@@ -86,3 +89,29 @@ while (parts.length) {

let fakeConsole;
let lastResult;
/**
* Returns the output of console.table as a string isntead of writing it to
* stdout.
* @param {...any} contents Arguments as passed to `console.table`
* @returns {string}
*/
function consoleTable (...contents) {
if (!fakeConsole) {
// `Console.table` internally calls `Console.log` to display results, so
// we override the log function to store the result in a variable
// rather than sending it to stdout. Because we pass process.stdout to
// the console constructor, the output string will contain color codes.
// eslint-disable-next-line no-console
fakeConsole = new console.Console(process.stdout);
fakeConsole.log = result => {
lastResult = result;
};
}
// Calling the table function stores the result in `lastResult`...
fakeConsole.table(...contents);
// ...so we can just return that variable now!
return lastResult;
}
/**
* Returns a new logger object and stuff.

@@ -93,16 +122,17 @@ * @param {Object} config An object containing configuration options

* messages
* @param {string[] | Object} config.ignoredLevels A list of level names that
* should be excluded from the output
* @param {Object} levels An object containing levels to use for the logger.
* Keys of the object are level names as they're called from code, and each key
* should map to an object with options I can't document here because JSDoc is
* stupid and doesn't like custom object things
* @param {Object | string[]} config.ignoreLevels An object mapping level names
* to a boolean indicating whether or not the level should be ignored, or an
* array of level names to be ignored
* @param {Stream?} config.stream A writable stream (or any object that has a
* `.write()` method) that the output of this level is sent to
* @param {Object} config.levels An object containing levels to use for the
* logger. Keys of the object are level names as they're called from code, and
* each key should map to an object with options I can't document here because
* JSDoc is stupid and doesn't like custom object things
* @returns {Object} The logger object
*/
function createLogger (config, levels) {
function createLogger (config = {}) {
// Compute the calculated levels/config options by applying the defaults
levels = levels || config && config.levels || {};
levels = Object.assign({}, baseLevels, levels);
const levels = Object.assign({}, baseLevels, config.levels);
config = Object.assign({}, baseConfig, config);
delete config.levels; // don't rely on this since it may not be passed in

@@ -117,69 +147,58 @@ // Resolve ignoredLevels

}
// Merge with base config
// Merge with base config's ignored levels
config.ignoredLevels = Object.assign({}, baseConfig.ignoredLevels, config.ignoredLevels);
// Construct the base logger object
const logger = {
_config: Object.assign({}, baseConfig, config),
_log (level, ...contents) {
// If the log level is ignored, do nothing
if (this._config.ignoredLevels[level]) return;
// Assemble all the parts of the message prefix
const time = this._config.timestamps ? timestamp() : '';
const label = this._config.label || '';
const prefix = [
time,
label,
this[level]._text,
].filter(s => s).join(' ');
// Format contents and write message
contents = util.format(...contents);
// eslint-disable-next-line no-console
console.log(`${prefix} ${contents}`);
},
_trace (level, ...contents) {
if (this._config.ignoredLevels[level]) return;
// Remove the first two lines, leaving a newline as the first char
const stacktrace = new Error().stack.replace(/.*\n.*/, '');
this._log(level, util.format(...contents) + stacktrace);
},
_table (level, ...contents) {
if (this._config.ignoredLevels[level]) return;
// HACK: This code calls the built-in console.table() function but
// on a proxy that hijacks the output function and sends the
// generated table to our logger.
const fakeConsole = new Proxy(console, {
get: (c, prop) => {
// Replace the log function with our custom log
if (prop === 'log') {
return tableString => {
// If the table is multiline, add a newline at the
// beginning to preserve alignment
if (tableString.indexOf('\n') !== -1) {
tableString = `\n${tableString}`;
}
this._log(level, tableString);
};
}
// Symbol properties used in the table function need to be
// passed through as-is
return c[prop];
},
});
// this is literally a console logging utility, chill out eslint
// eslint-disable-next-line no-console
console.constructor.prototype.table.apply(fakeConsole, contents);
},
};
// Create the logger object
const logger = {};
// Add logging functions for each level
// Private functions - always called with `levelObj` (below) as `this`
function log (...contents) {
if (config.ignoredLevels[this.name]) return;
const time = config.timestamps ? timestamp() : '';
const label = config.label || '';
const prefix = [
time,
label,
this.cachedText,
].filter(s => s).join(' ');
contents = util.format(...contents);
this.stream.write(`${prefix} ${contents}\n`);
}
function trace (...contents) {
if (config.ignoredLevels[this.name]) return;
// Remove the first two lines, leaving a newline as the first char
const stacktrace = new Error().stack.replace(/.*\n.*/, '');
log.call(this, util.format(...contents) + stacktrace);
}
function table (...contents) {
if (config.ignoredLevels[this.name]) return;
let tableString = consoleTable(...contents);
// If the table is multiline, add a newline at the beginning to preserve
// alignment. `indexOf` check because passing e.g. a number to the table
// function results in that number being returned, and numbers don't
// have an `indexOf` method.
if (typeof tableString === 'string' && tableString.indexOf('\n') !== -1) {
tableString = `\n${tableString}`;
}
log.call(this, tableString);
}
// Add levels to the logger and cache some stuff
for (const level of Object.keys(levels)) {
// Bind the log functions for this level
logger[level] = logger._log.bind(logger, level);
logger[level].trace = logger._trace.bind(logger, level);
logger[level].table = logger._table.bind(logger, level);
// Bake in the styled text to save time later
logger[level]._text = style(levels[level].text || level, levels[level].style);
// Duplicate the object so we don't accidentally modify base config
const levelObj = {...levels[level]};
// Store extra options on the level object
levelObj.cachedText = applyStyle(levelObj.text || level, levelObj.style);
levelObj.name = level;
if (!levelObj.stream) {
levelObj.stream = config.stream || process.stdout;
}
// Bind private functions to the level object and put them on the logger
const levelFunc = log.bind(levelObj);
levelFunc.trace = trace.bind(levelObj);
levelFunc.table = table.bind(levelObj);
logger[level] = levelFunc;
}
// \o/
return logger;

@@ -186,0 +205,0 @@ }

{
"name": "another-logger",
"version": "3.0.0-pre2",
"version": "3.0.0-pre3",
"description": "Yet another Node console.log alternative.",

@@ -10,6 +10,8 @@ "main": "index.js",

"scripts": {
"test": "eslint . && mocha"
"lint": "eslint .",
"test": "ava"
},
"devDependencies": {
"@geo1088/eslint-config": "^3.0.8",
"ava": "^2.0.0",
"eslint": "^5.6.1"

@@ -16,0 +18,0 @@ },

@@ -37,3 +37,3 @@ # another-logger [![npm](https://img.shields.io/npm/v/another-logger.svg)](https://www.npmjs.com/package/another-logger)

},
ignoredLevels: ['debug']
ignoredLevels: ['debug'],
});

@@ -53,4 +53,4 @@

### `const log = require('another-logger')(config)`
### `const log = require('another-logger')`
### `const log = require('another-logger')(config);`
### `const log = require('another-logger');`

@@ -65,3 +65,3 @@ When requiring the module, you get two things in one: a default logger instance, and a constructor function that can be called to create additional logger instances. When calling the constructor function, the argument `config` is an object with the following properties:

- `style` - The style to use for displaying this level's name. This can be a function or a string; if it's a string, it will be parsed as a space and/or period-separated list of [`chalk`](https://npmjs.com/package/chalk)'s named styles (red, gray, bgBlue, etc). See that package's README for a full list.
- `style` - The style to use for displaying this level's name. This can be a function or a string; if it's a string, it will be parsed as a space- and/or period-separated list of [`chalk`](https://npmjs.com/package/chalk)'s named styles (red, gray, bgBlue, etc). See that package's README for a full list.

@@ -93,8 +93,8 @@ - `stream` - The stream this log should output to. Overrides the logger setting on a per-level basis.

levels: {
uhoh: {text: 'Uh-oh!', style: 'magenta'}
}
uhoh: {text: 'Uh-oh!', style: 'magenta'},
},
});
```
### `log.<name>(content...)`
### `log.<name>(content...);`

@@ -108,3 +108,3 @@ Execute a log. `name` can be any level name - one of the defaults of `debug`, `info`, `success`, `warn`, or `error`, or a custom one provided in the logger's config. Content arguments are processed via `require('util').format()` which means it works in the same way as `console.log` in regards to format strings, object previewing, etc.

### `log.<name>.trace(content...)`
### `log.<name>.trace(content...);`

@@ -120,3 +120,3 @@ The same as the normal log, but appends a stack trace to the log output. Essentially the same as `console.trace()`.

### `log.<name>.table(tabularData, properties?)`
### `log.<name>.table(tabularData, properties?);`

@@ -137,4 +137,6 @@ Tries to generate and display a table from the object or array `tabularData`, displaying only properties whose names are in `properties` if it is passed. Logs the argument plainly if a table can't be generated. Throws an error if `properties` is given and is not an array of strings. For more information, see the [Node.js `Console.table` docs](https://nodejs.org/docs/v11.6.0/api/console.html#console_console_table_tabulardata_properties).

//=> └─────────┴───┴───┴───┘
```
## License
MIT &copy; 2018 Geo1088
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc