winston
Advanced tools
Comparing version 3.0.0-rc6 to 3.0.0
# CHANGELOG | ||
## v3.0.0 / 2018-06-12 | ||
### GET IN THE CHOPPA EDITION | ||
- [#1332], (@DABH): logger.debug is sent to stderr (Fixed [#1024]) | ||
- [#1328], (@ChrisAlderson): Logger level doesn't update transports level (Fixes [#1191]). | ||
- [#1356], (@indexzero) Move splat functionality into logform. (Fixes [#1298]). | ||
- [#1340], (@indexzero): Check log.length when evaluating "legacyness" of transports (Fixes [#1280]). | ||
- [#1346], (@indexzero): Implement `_final` from Node.js streams. (Related to winston-transport#24, Fixes [#1250]). | ||
- [#1347], (@indexzero): Wrap calls to `format.transform` with try / catch (Fixes [#1261]). | ||
- [#1357], (@indexzero): Remove paddings as we have no use for it in the current API. | ||
- [TODO]: REMAINS OPEN, NO PR (Fixes [#1289]) | ||
- Documentation | ||
- [#1301], (@westonpace) Cleaned up some of the documentation on `colorize` | ||
to address concerns in [#1095]. | ||
- First pass at a heavy refactor of `docs/transports.md`. | ||
- Dependency management | ||
- Regenerate `package-lock.json`. | ||
- Upgrade to `logform@^1.9.0`. | ||
## v3.0.0-rc6 / 2018-05-30 | ||
@@ -4,0 +23,0 @@ ### T-MINUS 6-DAY TO WINSTON@3 EDITION |
@@ -25,4 +25,4 @@ // Type definitions for winston 3.0 | ||
handle(): void; | ||
unhandle(): void; | ||
handle(...transports: Transport[]): void; | ||
unhandle(...transports: Transport[]): void; | ||
getAllInfo(err: string | Error): object; | ||
@@ -90,3 +90,2 @@ getProcessInfo(): object; | ||
transports: Transport[]; | ||
paddings: string[]; | ||
exceptions: ExceptionHandler; | ||
@@ -167,3 +166,2 @@ profilers: object; | ||
let exceptions: ExceptionHandler; | ||
let paddings: string[]; | ||
let exitOnError: Function | boolean; | ||
@@ -173,2 +171,2 @@ // let default: object; | ||
export = winston; | ||
export = winston; |
@@ -135,3 +135,2 @@ /** | ||
[ | ||
'paddings', | ||
'exitOnError' | ||
@@ -138,0 +137,0 @@ ].forEach(prop => { |
@@ -13,16 +13,2 @@ /** | ||
/** | ||
* Captures the number of format (i.e. %s strings) in a given string. | ||
* Based on `util.format`, see Node.js source: | ||
* https://github.com/nodejs/node/blob/b1c8f15c5f169e021f7c46eb7b219de95fe97603/lib/util.js#L201-L230 | ||
* @type {RegExp} | ||
*/ | ||
exports.formatRegExp = /%[sdjifoO%]/g; | ||
/** | ||
* Captures the number of escaped % signs in a format string (i.e. %s strings). | ||
* @type {RegExp} | ||
*/ | ||
exports.escapedPercent = /%%/g; | ||
/** | ||
* Set of simple deprecation notices and a way to expose them for a set of | ||
@@ -29,0 +15,0 @@ * properties. |
@@ -94,4 +94,2 @@ // Type definitions for winston 3.0 | ||
addColors(colors: AbstractConfigSetColors): void; | ||
colorize(level: number, message?: string): string; | ||
} | ||
@@ -98,0 +96,0 @@ } |
@@ -10,3 +10,3 @@ /** | ||
const { Writable } = require('stream'); | ||
const Writable = require('readable-stream/writable'); | ||
@@ -26,5 +26,3 @@ /** | ||
constructor(transport) { | ||
super({ | ||
objectMode: true | ||
}); | ||
super({ objectMode: true }); | ||
@@ -31,0 +29,0 @@ if (!transport) { |
@@ -10,5 +10,5 @@ /** | ||
const stream = require('stream'); | ||
const stream = require('readable-stream'); | ||
const asyncForEach = require('async/forEach'); | ||
const { LEVEL } = require('triple-beam'); | ||
const { LEVEL, SPLAT } = require('triple-beam'); | ||
const isStream = require('is-stream'); | ||
@@ -18,3 +18,3 @@ const ExceptionHandler = require('./exception-handler'); | ||
const Profiler = require('./profiler'); | ||
const { clone, escapedPercent, formatRegExp, warn } = require('./common'); | ||
const { clone, warn } = require('./common'); | ||
const config = require('./config'); | ||
@@ -71,16 +71,4 @@ | ||
levels = levels || this.levels || config.npm.levels; | ||
const maxLength = Math.max(...Object.keys(levels).map(lev => lev.length)); | ||
this.paddings = Object.keys(levels).reduce((acc, lev) => { | ||
const pad = lev.length !== maxLength | ||
? new Array(maxLength - lev.length + 1).join(' ') | ||
: ''; | ||
acc[lev] = pad; | ||
return acc; | ||
}, {}); | ||
// Hoist other options onto this instance. | ||
this.levels = levels; | ||
this.levels = levels || this.levels || config.npm.levels; | ||
this.level = level; | ||
@@ -113,5 +101,6 @@ this.exceptions = new ExceptionHandler(this); | ||
/* eslint-disable valid-jsdoc */ | ||
/** | ||
* Ensure backwards compatibility with a `log` method | ||
* @param {mixed} level - TODO: add param description. | ||
* @param {mixed} level - Level the log message is written at. | ||
* @param {mixed} msg - TODO: add param description. | ||
@@ -122,3 +111,3 @@ * @param {mixed} meta - TODO: add param description. | ||
* @example | ||
* // Supports the existing API, which is now DEPRECATED: | ||
* // Supports the existing API: | ||
* logger.log('info', 'Hello world', { custom: true }); | ||
@@ -134,11 +123,11 @@ * logger.log('info', new Error('Yo, it\'s on fire')); | ||
* message: '%s %d%%', | ||
* splat: ['A string', 50], | ||
* [SPLAT]: ['A string', 50], | ||
* meta: { thisIsMeta: true } | ||
* }); | ||
* | ||
*/ | ||
// log(level, msg, meta) { | ||
log(...args) { | ||
const [level, msg, meta] = args; | ||
/* eslint-enable valid-jsdoc */ | ||
log(level, msg, ...splat) { // eslint-disable-line max-params | ||
// Optimize for the hotpath of logging JSON literals | ||
if (args.length === 1) { | ||
if (arguments.length === 1) { | ||
// Yo dawg, I heard you like levels ... seriously ... | ||
@@ -153,3 +142,3 @@ // In this context the LHS `level` here is actually the `info` so read | ||
// Slightly less hotpath, but worth optimizing for. | ||
if (args.length === 2) { | ||
if (arguments.length === 2) { | ||
if (msg && typeof msg === 'object') { | ||
@@ -165,21 +154,19 @@ msg[LEVEL] = msg.level = level; | ||
// Separation of the splat from { level, message, meta } must be done at | ||
// this point in the objectMode stream since we only ever write a single | ||
// object. | ||
const tokens = msg && msg.match && msg.match(formatRegExp); | ||
if (tokens) { | ||
this._splat({ | ||
const [meta] = splat; | ||
if (typeof meta === 'object' && meta !== null) { | ||
this.write(Object.assign({}, meta, { | ||
[LEVEL]: level, | ||
[SPLAT]: splat.slice(0), | ||
level, | ||
message: msg | ||
}, tokens, args.slice(2)); | ||
return this; | ||
})); | ||
} else { | ||
this.write(Object.assign({}, { | ||
[LEVEL]: level, | ||
[SPLAT]: splat, | ||
level, | ||
message: msg | ||
})); | ||
} | ||
const info = Object.assign({}, meta, { | ||
[LEVEL]: level, | ||
level, | ||
message: msg | ||
}); | ||
this.write(info); | ||
return this; | ||
@@ -192,3 +179,3 @@ } | ||
* @param {mixed} enc - TODO: add param description. | ||
* @param {mixed} callback - TODO: add param description. | ||
* @param {mixed} callback - Continues stream processing. | ||
* @returns {undefined} | ||
@@ -228,48 +215,27 @@ * @private | ||
// Here we write to the `format` pipe-chain, which on `readable` above will | ||
// push the formatted `info` Object onto the buffer for this instance. | ||
this.push(this.format.transform(info, this.format.options)); | ||
callback(); | ||
// push the formatted `info` Object onto the buffer for this instance. We trap | ||
// (and re-throw) any errors generated by the user-provided format, but also | ||
// guarantee that the streams callback is invoked so that we can continue flowing. | ||
try { | ||
this.push(this.format.transform(info, this.format.options)); | ||
} catch (ex) { | ||
throw ex; | ||
} finally { | ||
// eslint-disable-next-line callback-return | ||
callback(); | ||
} | ||
} | ||
/** | ||
* Check to see if tokens <= splat.length, assign { splat, meta } into the | ||
* `info` accordingly, and write to this instance. | ||
* @param {mixed} info - TODO: add param description. | ||
* @param {mixed} tokens - TODO: add param description. | ||
* @param {mixed} splat - TODO: add param description. | ||
* @returns {undefined} | ||
* @private | ||
* Delays the 'finish' event until all transport pipe targets have | ||
* also emitted 'finish' or are already finished. | ||
* @param {mixed} callback - Continues stream processing. | ||
*/ | ||
_splat(info, tokens, splat) { | ||
const percents = info.message.match(escapedPercent); | ||
const escapes = percents && percents.length || 0; | ||
// The expected splat is the number of tokens minus the number of escapes | ||
// e.g. | ||
// - { expectedSplat: 3 } '%d %s %j' | ||
// - { expectedSplat: 5 } '[%s] %d%% %d%% %s %j' | ||
// | ||
// Any "meta" will be arugments in addition to the expected splat size | ||
// regardless of type. e.g. | ||
// | ||
// logger.log('info', '%d%% %s %j', 100, 'wow', { such: 'js' }, { thisIsMeta: true }); | ||
// would result in splat of four (4), but only three (3) are expected. Therefore: | ||
// | ||
// extraSplat = 3 - 4 = -1 | ||
// metas = [100, 'wow', { such: 'js' }, { thisIsMeta: true }].splice(-1, -1 * -1); | ||
// splat = [100, 'wow', { such: 'js' }] | ||
const expectedSplat = tokens.length - escapes; | ||
const extraSplat = expectedSplat - splat.length; | ||
const metas = extraSplat < 0 | ||
? splat.splice(extraSplat, -1 * extraSplat) | ||
: []; | ||
// Now that { splat } has been separated from any potential { meta }. we | ||
// can assign this to the `info` object and write it to our format stream. | ||
info.splat = splat; | ||
if (metas.length) { | ||
info.meta = metas[0]; | ||
} | ||
this.write(info); | ||
_final(callback) { | ||
const transports = this.transports.slice(); | ||
asyncForEach(transports, (transport, next) => { | ||
if (!transport || transport.finished) return setImmediate(next); | ||
transport.once('finish', next); | ||
transport.end(); | ||
}, callback); | ||
} | ||
@@ -283,6 +249,8 @@ | ||
add(transport) { | ||
// Support backwards compatibility with all existing `winston@1.x.x` | ||
// transport. All NEW transports should inherit from | ||
// `winston.TransportStream`. | ||
const target = !isStream(transport) | ||
// Support backwards compatibility with all existing `winston < 3.x.x` | ||
// transports which meet one of two criteria: | ||
// 1. They inherit from winston.Transport in < 3.x.x which is NOT a stream. | ||
// 2. They expose a log method which has a length greater than 2 (i.e. more then | ||
// just `log(info, callback)`. | ||
const target = !isStream(transport) || transport.log.length > 2 | ||
? new LegacyTransportStream({ transport }) | ||
@@ -313,3 +281,3 @@ : transport; | ||
let target = transport; | ||
if (!isStream(transport)) { | ||
if (!isStream(transport) || transport.log.length > 2) { | ||
target = this.transports | ||
@@ -316,0 +284,0 @@ .filter(match => match.transport === transport)[0]; |
@@ -12,3 +12,3 @@ /** | ||
const { StringDecoder } = require('string_decoder'); | ||
const { Stream } = require('stream'); | ||
const { Stream } = require('readable-stream'); | ||
@@ -15,0 +15,0 @@ /** |
@@ -31,6 +31,3 @@ /* eslint-disable no-console */ | ||
this.name = 'console'; | ||
this.stderrLevels = this._getStderrLevels( | ||
options.stderrLevels, | ||
options.debugStdout | ||
); | ||
this.stderrLevels = this._stringArrayToSet(options.stderrLevels); | ||
this.eol = options.eol || os.EOL; | ||
@@ -78,33 +75,2 @@ } | ||
/** | ||
* Convert stderrLevels into an Object for faster key-lookup times than an | ||
* Array. For backwards compatibility, stderrLevels defaults to | ||
* ['error', 'debug'] or ['error'] depending on whether options.debugStdout | ||
* is true. | ||
* @param {mixed} levels - TODO: add param description. | ||
* @param {mixed} debugStdout - TODO: add param description. | ||
* @returns {mixed} - TODO: add return description. | ||
* @private | ||
*/ | ||
_getStderrLevels(levels, debugStdout) { | ||
const defaultMsg = 'Cannot have non-string elements in stderrLevels Array'; | ||
if (debugStdout) { | ||
if (levels) { | ||
// Don't allow setting both debugStdout and stderrLevels together, | ||
// since this could cause behaviour a programmer might not expect. | ||
throw new Error('Cannot set debugStdout and stderrLevels together'); | ||
} | ||
return this._stringArrayToSet(['error'], defaultMsg); | ||
} | ||
if (!levels) { | ||
return this._stringArrayToSet(['error', 'debug'], defaultMsg); | ||
} else if (!(Array.isArray(levels))) { | ||
throw new Error('Cannot set stderrLevels to type other than Array'); | ||
} | ||
return this._stringArrayToSet(levels, defaultMsg); | ||
} | ||
/** | ||
* Returns a Set-like object with strArray's elements as keys (each with the | ||
@@ -118,4 +84,11 @@ * value true). | ||
_stringArrayToSet(strArray, errMsg) { | ||
errMsg = errMsg || 'Cannot make set from Array with non-string elements'; | ||
if (!strArray) | ||
return {}; | ||
errMsg = errMsg || 'Cannot make set from type other than Array of string elements'; | ||
if (!Array.isArray(strArray)) { | ||
throw new Error(errMsg); | ||
} | ||
return strArray.reduce((set, el) => { | ||
@@ -122,0 +95,0 @@ if (typeof el !== 'string') { |
@@ -15,3 +15,3 @@ /** | ||
const { MESSAGE } = require('triple-beam'); | ||
const { Stream, PassThrough } = require('stream'); | ||
const { Stream, PassThrough } = require('readable-stream'); | ||
const TransportStream = require('winston-transport'); | ||
@@ -51,2 +51,3 @@ const debug = require('diagnostics')('winston:file'); | ||
this._stream = new PassThrough(); | ||
this._stream.setMaxListeners(30); | ||
@@ -495,2 +496,3 @@ // Bind this context for listener methods. | ||
this._stream = new PassThrough(); | ||
this._stream.setMaxListeners(30); | ||
this._rotateFile(); | ||
@@ -497,0 +499,0 @@ this.rotatedWhileOpening = false; |
@@ -12,3 +12,3 @@ /** | ||
const https = require('https'); | ||
const { Stream } = require('stream'); | ||
const { Stream } = require('readable-stream'); | ||
const TransportStream = require('winston-transport'); | ||
@@ -15,0 +15,0 @@ |
{ | ||
"name": "winston", | ||
"description": "A multi-transport async logging library for Node.js", | ||
"version": "3.0.0-rc6", | ||
"description": "A logger for just about everything.", | ||
"version": "3.0.0", | ||
"author": "Charlie Robbins <charlie.robbins@gmail.com>", | ||
"maintainers": [ | ||
"Jarrett Cruger <jcrugzz@gmail.com>", | ||
"Alberto Pose <albertopose@gmail.com>" | ||
"Chris Alderson <chrisalderson@protonmail.com>", | ||
"David Hyde <dabh@stanford.edu>" | ||
], | ||
@@ -16,5 +17,12 @@ "repository": { | ||
"winston", | ||
"logger", | ||
"logging", | ||
"logs", | ||
"sysadmin", | ||
"tools" | ||
"bunyan", | ||
"pino", | ||
"loglevel", | ||
"tools", | ||
"json", | ||
"stream" | ||
], | ||
@@ -25,7 +33,8 @@ "dependencies": { | ||
"is-stream": "^1.1.0", | ||
"logform": "^1.7.0", | ||
"logform": "^1.9.0", | ||
"one-time": "0.0.4", | ||
"readable-stream": "^2.3.6", | ||
"stack-trace": "0.0.x", | ||
"triple-beam": "^1.3.0", | ||
"winston-transport": "^4.0.0" | ||
"winston-transport": "^4.2.0" | ||
}, | ||
@@ -32,0 +41,0 @@ "devDependencies": { |
@@ -11,11 +11,4 @@ # winston | ||
## winston@3.0.0-rc6 | ||
## winston@3.0.0 | ||
**We are pushing for a June 5th, 2018 release of `winston@3.0.0`**, currently | ||
`winston@3.0.0-rc6`. | ||
``` | ||
npm i winston@next --save | ||
``` | ||
See the [Upgrade Guide](UPGRADE-3.0.md) for more information. Bug reports and | ||
@@ -103,4 +96,4 @@ PRs welcome! | ||
* [Using the default logger](#using-the-default-logger) | ||
* [Events and Callbacks in `winston`](#events-and-callbacks-in-winston) | ||
* [Working with multiple Loggers in winston](#working-with-multiple-loggers-in-winston) | ||
* [Awaiting logs to be written in `winston`](#awaiting-logs-to-be-written-in-winston) | ||
* [Working with multiple Loggers in `winston`](#working-with-multiple-loggers-in-winston) | ||
* [Installation](#installation) | ||
@@ -123,3 +116,3 @@ * [Run Tests](#run-tests) | ||
silly: 5 | ||
} | ||
}; | ||
``` | ||
@@ -509,2 +502,3 @@ | ||
const logger = winston.createLogger({ | ||
levels: winston.config.syslog.levels, | ||
transports: [ | ||
@@ -581,3 +575,3 @@ new winston.transports.Console({ level: 'error' }), | ||
This enables transports with the 'colorize' option set to appropriately color and style | ||
This enables loggers using the `colorize` formatter to appropriately color and style | ||
the output of custom levels. | ||
@@ -610,5 +604,5 @@ | ||
winston.format.json() | ||
) | ||
); | ||
``` | ||
where `winston.format.json()` is whatever other formatter you want to use. | ||
where `winston.format.json()` is whatever other formatter you want to use. The `colorize` formatter must come before any formatters adding text you wish to color. | ||
@@ -726,3 +720,3 @@ ## Transports | ||
// | ||
// You can add a separate exception logger by passing it to `.handleExceptions` | ||
// You can add a separate exception logger by passing it to `.exceptions.handle` | ||
// | ||
@@ -734,5 +728,4 @@ winston.exceptions.handle( | ||
// | ||
// Alternatively you can set `.handleExceptions` to true when adding transports | ||
// to winston. You can use the `.humanReadableUnhandledException` option to | ||
// get more readable exceptions. | ||
// Alternatively you can set `handleExceptions` to true when adding transports | ||
// to winston. | ||
// | ||
@@ -926,7 +919,8 @@ winston.add(new winston.transports.File({ | ||
### Events and Callbacks in `winston` | ||
### Awaiting logs to be written in `winston` | ||
Each instance of winston.Logger is also an instance of an [EventEmitter]. A | ||
`logged` event will be raised each time a transport successfully logs a | ||
message: | ||
Often it is useful to wait for your logs to be written before exiting the | ||
process. Each instance of `winston.Logger` is also a [Node.js stream]. A | ||
`finished` event will be raised when all logs have flushed to all transports | ||
after the stream has been ended. | ||
@@ -939,7 +933,8 @@ ``` js | ||
transport.on('logged', function (info) { | ||
// `info` log message has now been logged | ||
transport.on('finished', function (info) { | ||
// All `info` log messages has now been logged | ||
}); | ||
logger.info('CHILL WINSTON!', { seriously: true }); | ||
logger.end(); | ||
``` | ||
@@ -979,3 +974,2 @@ | ||
level: 'silly', | ||
colorize: true, | ||
label: 'category one' | ||
@@ -1021,4 +1015,3 @@ }, | ||
console: { | ||
level: 'silly', | ||
colorize: true | ||
level: 'silly' | ||
}, | ||
@@ -1043,4 +1036,4 @@ file: { | ||
All of the winston tests are written with [`mocha`][mocha], [`nyc`][nyc], and [`assume`][assume]. They | ||
can be run with `npm`. | ||
All of the winston tests are written with [`mocha`][mocha], [`nyc`][nyc], and | ||
[`assume`][assume]. They can be run with `npm`. | ||
@@ -1052,3 +1045,3 @@ ``` bash | ||
#### Author: [Charlie Robbins] | ||
#### Contributors: [Jarrett Cruger], [David Hyde] | ||
#### Contributors: [Jarrett Cruger], [David Hyde], [Chris Alderson] | ||
@@ -1064,3 +1057,2 @@ [Transports]: #transports | ||
[RFC5424]: https://tools.ietf.org/html/rfc5424 | ||
[EventEmitter]: https://nodejs.org/dist/latest/docs/api/events.html#events_class_eventemitter | ||
[util.format]: https://nodejs.org/dist/latest/docs/api/util.html#util_util_format_format_args | ||
@@ -1076,1 +1068,2 @@ [mocha]: https://mochajs.org | ||
[David Hyde]: https://github.com/dabh | ||
[Chris Alderson]: https://github.com/chrisalderson |
@@ -22,3 +22,2 @@ 'use strict'; | ||
noStderr: new winston.transports.Console({ stderrLevels: [] }), | ||
debugStdout: new winston.transports.Console({ debugStdout: true }), | ||
stderrLevels: new winston.transports.Console({ | ||
@@ -60,3 +59,3 @@ stderrLevels: ['info', 'warn'] | ||
describe('with defaults', function () { | ||
it('logs all levels (EXCEPT error and debug) to stdout', function () { | ||
it('logs all levels to stdout', function () { | ||
stdMocks.use(); | ||
@@ -79,10 +78,10 @@ transports.defaults.levels = defaultLevels; | ||
assume(output.stderr).is.an('array'); | ||
assume(output.stderr).length(2); | ||
assume(output.stderr).length(0); | ||
assume(output.stdout).is.an('array'); | ||
assume(output.stdout).length(5); | ||
assume(output.stdout).length(7); | ||
}); | ||
it("should set stderrLevels to ['error', 'debug'] by default", assertStderrLevels( | ||
it("should set stderrLevels to [] by default", assertStderrLevels( | ||
transports.defaults, | ||
['error', 'debug'] | ||
[] | ||
)); | ||
@@ -92,18 +91,8 @@ }); | ||
describe('throws an appropriate error when', function () { | ||
it('if both debugStdout and stderrLevels are set { debugStdout, stderrLevels }', function () { | ||
assume(function () { | ||
let throwing = new winston.transports.Console({ | ||
stderrLevels: ['foo', 'bar'], | ||
debugStdout: true | ||
}) | ||
}).throws(/Cannot set debugStdout and stderrLevels/); | ||
}); | ||
it("if stderrLevels is set, but not an Array { stderrLevels: 'Not an Array' }", function () { | ||
assume(function () { | ||
let throwing = new winston.transports.Console({ | ||
stderrLevels: 'Not an Array', | ||
debugStdout: false | ||
stderrLevels: 'Not an Array' | ||
}) | ||
}).throws(/Cannot set stderrLevels to type other than Array/); | ||
}).throws(/Cannot make set from type other than Array of string elements/); | ||
}); | ||
@@ -114,6 +103,5 @@ | ||
let throwing = new winston.transports.Console({ | ||
stderrLevels: ['good', /^invalid$/, 'valid'], | ||
debugStdout: false | ||
stderrLevels: ['good', /^invalid$/, 'valid'] | ||
}) | ||
}).throws(/Cannot have non-string elements in stderrLevels Array/); | ||
}).throws(/Cannot make set from type other than Array of string elements/); | ||
}); | ||
@@ -120,0 +108,0 @@ }); |
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
611998
70
4047
0
5
9
1054
14
+ Addedreadable-stream@^2.3.6
+ Addedcore-util-is@1.0.3(transitive)
+ Addedisarray@1.0.0(transitive)
+ Addedprocess-nextick-args@2.0.1(transitive)
+ Addedreadable-stream@2.3.8(transitive)
+ Addedsafe-buffer@5.1.2(transitive)
+ Addedstring_decoder@1.1.1(transitive)
- Removedsafe-buffer@5.2.1(transitive)
- Removedstring_decoder@1.3.0(transitive)
Updatedlogform@^1.9.0
Updatedwinston-transport@^4.2.0