Comparing version 1.0.7 to 2.0.0
91
index.js
"use strict"; | ||
var _ = require('lodash'); | ||
var moment = require('moment'); | ||
const _ = require('lodash'); | ||
const moment = require('moment'); | ||
const flatten = require('flat'); | ||
// Error objects have a lot of non-enumerable properties | ||
// Here's we include them (plus whatever properties the user set) | ||
function getKeys(obj) { | ||
var keys = _.keys(obj); | ||
if (_.isError(obj)) { | ||
var errKeys = _.filter([ | ||
'message', // standard keys | ||
'name', | ||
'description', // Microsoft keys | ||
'number', | ||
'fileName', // Mozilla keys | ||
'lineNumber', | ||
'columnNumber', | ||
], function (key) { | ||
return _.has(obj, key); | ||
}); | ||
keys = _.uniq(keys.concat(errKeys)); | ||
} | ||
return keys; | ||
} | ||
function toString(str) { | ||
@@ -48,42 +22,33 @@ try { | ||
module.exports = function logformat(obj) { | ||
if (_.isString(obj)) { | ||
return obj; | ||
} else if (_.isNumber(obj) || _.isBoolean(obj) || _.isRegExp(obj)) { | ||
module.exports = function logformat(obj, opts) { | ||
const flatOpts = { maxDepth: _.get(opts, 'maxDepth') }; | ||
if (obj === null || obj === undefined) { | ||
return ''; | ||
} else if (typeof obj !== 'object' || _.isRegExp(obj)) { | ||
return toString(obj); | ||
} else if (_.isDate(obj)) { | ||
return moment(obj).format(); | ||
} else if (_.isObject(obj)) { | ||
var r = []; | ||
} | ||
var keys = getKeys(obj); | ||
if (_.isError(obj)) { | ||
r.push('ERROR'); | ||
r.push(toString(obj.message)); | ||
keys = _.difference(keys, ['stack', 'message']); | ||
try { | ||
obj = flatten(obj, flatOpts); // flatten object | ||
} catch (err) { | ||
return '[Circular]'; | ||
} | ||
obj = _.toPairs(obj); // convert to array of key/value pairs | ||
obj = obj.map((pair) => { // manipulate values for better output | ||
switch (true) { | ||
case _.isString(pair[1]): pair[1] = applyQuotes(pair[1]); break; | ||
case _.isDate(pair[1]): pair[1] = moment(pair[1]).format(); break; | ||
default: pair[1] = applyQuotes(toString(pair[1])); break; | ||
} | ||
return pair; | ||
}); | ||
obj = obj.map((pair) => pair.join('=')); // join key/value pairs with equal sign | ||
obj = obj.join(' '); // join all pairs with space | ||
_.each(keys, function (key) { | ||
var val = obj[key]; | ||
if (_.isNull(val) || _.isUndefined(val)) { | ||
r.push(key + '=' + val); | ||
} else if (_.isDate(val)) { | ||
r.push(key + '=' + moment(val).format()); | ||
} else if (_.isObject(val) && !_.isRegExp(val)) { | ||
_.each(getKeys(val), function (innerKey) { | ||
var innerVal = val[innerKey]; | ||
if (_.isNull(innerVal) || _.isUndefined(innerVal)) { | ||
r.push(key + '.' + innerKey + '=' + innerVal); | ||
} else if (!_.isFunction(innerVal)) { | ||
r.push(key + '.' + innerKey + '=' + applyQuotes(toString(innerVal))); | ||
} | ||
}); | ||
} else if (!_.isFunction(val)) { | ||
r.push(key + '=' + applyQuotes(toString(val))); | ||
} | ||
}); | ||
return r.join(' '); | ||
} else { | ||
return ''; | ||
} | ||
return obj; | ||
}; |
{ | ||
"name": "logformat", | ||
"version": "1.0.7", | ||
"version": "2.0.0", | ||
"description": "stringify objects into searchable strings", | ||
@@ -30,2 +30,3 @@ "main": "index.js", | ||
"dependencies": { | ||
"flat": "^4.0.0", | ||
"lodash": "^4.17.5", | ||
@@ -37,5 +38,6 @@ "moment": "^2.21.0" | ||
"jshint": "^2.9.5", | ||
"mocha": "^5.0.4" | ||
"mocha": "^5.0.5" | ||
}, | ||
"jshintConfig": { | ||
"esversion": 6, | ||
"bitwise": true, | ||
@@ -42,0 +44,0 @@ "curly": true, |
@@ -38,3 +38,3 @@ # logformat | ||
### logformat(any) | ||
### logformat(any [, opts]) | ||
@@ -44,2 +44,4 @@ Parameters: | ||
* `any` anything you wish to stringify... booleans, strings, numbers, objects, arrays, etc. | ||
* `opts` options for controlling the behaviour of the function. Object. Optional. | ||
- `maxDepth` maximum depth that should be formatted. positive integer. Optional. | ||
@@ -50,2 +52,4 @@ Returns: | ||
NOTE: if `any` is an object with a circular reference, this function returns `'[Circular]'`; | ||
## Example | ||
@@ -59,3 +63,3 @@ | ||
// -> 'dev=287613608 mode=8630 nlink=1 uid=0 gid=0 rdev=50331650 blksize=131072 ino=303 size=0 blocks=0' | ||
// -> 'dev=6 mode=8630 nlink=1 uid=0 gid=0 rdev=259 blksize=4096 ino=1029 size=0 blocks=0 atime=2017-07-12T00:21:34-04:00 mtime=2017-07-12T00:21:34-04:00 ctime=2017-07-12T00:21:34-04:00 birthtime=2017-07-12T00:21:34-04:00' | ||
``` | ||
@@ -62,0 +66,0 @@ |
"use strict"; | ||
var expect = require('expect.js'); | ||
var logformat = require('../'); | ||
const expect = require('expect.js'); | ||
const logformat = require('../'); | ||
describe('logformat', function () { | ||
it('should be defined as a function', function () { | ||
describe('logformat', () => { | ||
it('should be defined as a function', () => { | ||
expect(logformat).not.to.be(undefined); | ||
expect(logformat).to.be.a('function'); | ||
}); | ||
it('should return a string when given a string', function () { | ||
it('should return a string when given a string', () => { | ||
expect(logformat('Hello, World!')).to.be('Hello, World!'); | ||
}); | ||
it('should return a string when given a number', function () { | ||
it('should format an Object which does not inherit from Object', () => { | ||
const obj = Object.create(null); | ||
obj.foo = 'bar'; | ||
expect(logformat(obj)).to.be('foo=bar'); | ||
const nested = { foo: Object.create(null) }; | ||
nested.foo.bar = 'baz'; | ||
expect(logformat(nested)).to.be('foo.bar=baz'); | ||
const doubleNested = { foo: Object.create(null) }; | ||
doubleNested.foo = { bar: Object.create(null) }; | ||
doubleNested.foo.bar = 'baz'; | ||
expect(logformat(doubleNested)).to.be('foo.bar=baz'); | ||
}); | ||
it('should return a string when given a number', () => { | ||
expect(logformat(42)).to.be('42'); | ||
}); | ||
it('should return an empty string when given null', function () { | ||
it('should return an empty string when given null', () => { | ||
expect(logformat(null)).to.be(''); | ||
}); | ||
it('should return an empty string when given undefined', function () { | ||
it('should return an empty string when given undefined', () => { | ||
expect(logformat(undefined)).to.be(''); | ||
}); | ||
it('should return a regular express as a string when given a RegExp', function () { | ||
it('should return a regular express as a string when given a RegExp', () => { | ||
expect(logformat(/^foobar$/)).to.be('/^foobar$/'); | ||
expect(logformat(new RegExp("^foobar$"))).to.be('/^foobar$/'); | ||
}); | ||
it('should return true/false when given true/false', function () { | ||
it('should return true/false when given true/false', () => { | ||
var obj = { is_it_true: true }; | ||
@@ -33,17 +47,10 @@ expect(logformat(obj.is_it_true)).to.be('true'); | ||
}); | ||
it('should return an ISO8601 formatted string when given a Date object', function () { | ||
it('should return an ISO8601 formatted string when given a Date object', () => { | ||
expect(logformat(new Date('Tue Jun 21 2016 08:37:16 GMT-0400 (EDT)'))).to.be('2016-06-21T08:37:16-04:00'); | ||
expect(logformat({ date: new Date('Tue Jun 21 2016 08:37:16 GMT-0400 (EDT)') })).to.be('date=2016-06-21T08:37:16-04:00'); | ||
}); | ||
it('should return a string when given an Error object', function () { | ||
var err = new Error('Test'); | ||
err.name = 'logformat.test.err'; | ||
expect(logformat(err)).to.be('ERROR Test name=logformat.test.err'); | ||
expect(logformat({ err: err })).to.be('err.name=logformat.test.err err.message=Test'); | ||
}); | ||
it('should return a string of key=value pairs for objects', function () { | ||
it('should return a string of key=value pairs for objects', () => { | ||
expect(logformat({ | ||
foo: undefined, // maps to foo=undefined | ||
bar: null, // maps to baz=null | ||
baz: function () { return 0xc0ffee; }, // not included in output | ||
abc: true, // maps to abc=true | ||
@@ -57,3 +64,2 @@ def: 'Hello, World!', // maps to def="Hello, World!" | ||
d: 'apple sauce', // maps to jkl.d="apple sauce" | ||
e: function () { return 23; }, // not included in output | ||
f: [ 4, 'life' ] | ||
@@ -67,5 +73,5 @@ }, | ||
pqr: /^foobar$/ // maps to pqr="/^foobar$/" | ||
})).to.be('foo=undefined bar=null abc=true def="Hello, World!" ghi=cheese jkl.a=null jkl.b=undefined jkl.c=howdy jkl.d="apple sauce" jkl.f=4,life mno.0=this mno.1=is mno.2="a test" pqr=/^foobar$/'); | ||
})).to.be('foo=undefined bar=null abc=true def="Hello, World!" ghi=cheese jkl.a=null jkl.b=undefined jkl.c=howdy jkl.d="apple sauce" jkl.f.0=4 jkl.f.1=life mno.0=this mno.1=is mno.2="a test" pqr=/^foobar$/'); | ||
}); | ||
it('should return a string of key=value pairs for arrays', function () { | ||
it('should return a string of key=value pairs for arrays', () => { | ||
expect(logformat([ | ||
@@ -77,19 +83,18 @@ true, | ||
'quoted test', | ||
function () { return null; }, | ||
42 | ||
])).to.be('0=true 1=null 2=undefined 3=test 4="quoted test" 6=42'); | ||
])).to.be('0=true 1=null 2=undefined 3=test 4="quoted test" 5=42'); | ||
}); | ||
it('should not choke on curicular references', function () { | ||
var a = {}; | ||
var b = {}; | ||
var c = {}; | ||
it('should respect maxDepth option', () => { | ||
const obj = { foo: { bar: { baz: 1} } }; | ||
expect(logformat(obj, { maxDepth: 2 })).to.be('foo.bar="[object Object]"'); | ||
expect(logformat(obj, { maxDepth: 10 })).to.be('foo.bar.baz=1'); | ||
expect(logformat(obj)).to.be('foo.bar.baz=1'); | ||
}); | ||
it('should not crash on a circular reference', () => { | ||
const a = {}; | ||
const b = {}; | ||
a.b = b; | ||
b.a = a; | ||
c.b = b; | ||
expect(function () { logformat(a) }).not.to.throwException(); | ||
expect(function () { logformat(b) }).not.to.throwException(); | ||
expect(function () { logformat(c) }).not.to.throwException(); | ||
expect(logformat(a)).to.be('[Circular]'); | ||
}); | ||
}); |
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
11196
8
72
3
136
1
+ Addedflat@^4.0.0
+ Addedflat@4.1.1(transitive)
+ Addedis-buffer@2.0.5(transitive)