Comparing version 2.0.0 to 2.0.1
@@ -15,11 +15,11 @@ 'use strict'; | ||
if(_.isNull(data)) { | ||
console.log('creating table', tableName); | ||
model.log.info('creating table: %s', tableName); | ||
return model.createTable(options, function (error) { | ||
if(error) { | ||
console.error('failed to created table ' + tableName, error); | ||
model.log.warn({err : error}, 'failed to create table %s: %s', tableName, error); | ||
return callback(error); | ||
} | ||
console.log('waiting for table ' + tableName + ' to become ACTIVE'); | ||
model.log.info('waiting for table: %s to become ACTIVE', tableName); | ||
internals.waitTillActive(model, callback); | ||
@@ -26,0 +26,0 @@ }); |
@@ -12,3 +12,4 @@ 'use strict'; | ||
Item = require('./item'), | ||
createTables = require('./createTables'); | ||
createTables = require('./createTables'), | ||
bunyan = require('bunyan'); | ||
@@ -21,2 +22,8 @@ var vogels = module.exports; | ||
vogels.log = bunyan.createLogger({ | ||
name: 'vogels', | ||
serializers : {err: bunyan.stdSerializers.err}, | ||
level : bunyan.FATAL | ||
}); | ||
vogels.dynamoDriver = internals.dynamoDriver = function (driver) { | ||
@@ -68,4 +75,6 @@ if(driver) { | ||
var table = new Table(tableName, schema, serializer, internals.loadDocClient()); | ||
var log = vogels.log.child({model: name}); | ||
var table = new Table(tableName, schema, serializer, internals.loadDocClient(), log); | ||
var Model = function (attrs) { | ||
@@ -97,2 +106,4 @@ Item.call(this, attrs, table); | ||
Model.log = log; | ||
// hooks | ||
@@ -99,0 +110,0 @@ Model.after = _.bind(table.after, table); |
@@ -161,4 +161,12 @@ 'use strict'; | ||
this.request.AttributesToGet = attrs; | ||
var expressionAttributeNames = _.reduce(attrs, function (result, attr) { | ||
var path = '#' + attr; | ||
result[path] = attr; | ||
return result; | ||
}, {}); | ||
this.request.ProjectionExpression = _.keys(expressionAttributeNames).join(','); | ||
this.request.ExpressionAttributeNames = _.merge({}, expressionAttributeNames, this.request.ExpressionAttributeNames); | ||
return this; | ||
@@ -165,0 +173,0 @@ }; |
@@ -80,4 +80,12 @@ 'use strict'; | ||
this.request.AttributesToGet = attrs; | ||
var expressionAttributeNames = _.reduce(attrs, function (result, attr) { | ||
var path = '#' + attr; | ||
result[path] = attr; | ||
return result; | ||
}, {}); | ||
this.request.ProjectionExpression = _.keys(expressionAttributeNames).join(','); | ||
this.request.ExpressionAttributeNames = _.merge({}, expressionAttributeNames, this.request.ExpressionAttributeNames); | ||
return this; | ||
@@ -84,0 +92,0 @@ }; |
@@ -15,3 +15,3 @@ 'use strict'; | ||
var Table = module.exports = function (name, schema, serializer, docClient) { | ||
var Table = module.exports = function (name, schema, serializer, docClient, logger) { | ||
this.config = {name : name}; | ||
@@ -22,2 +22,3 @@ this.schema = schema; | ||
this._dynamodb = docClient.service; | ||
this.log = logger; | ||
@@ -53,2 +54,21 @@ this._before = new EventEmitter(); | ||
Table.prototype.sendRequest = function (method, params, callback) { | ||
var self = this; | ||
var startTime = Date.now(); | ||
self.log.info({params : params}, 'vogels %s request', method.toUpperCase()); | ||
self.docClient[method].call(self.docClient, params, function (err, data) { | ||
var elapsed = Date.now() - startTime; | ||
if (err) { | ||
self.log.warn({err : err}, 'vogels %s error', method.toUpperCase()); | ||
return callback(err); | ||
} else { | ||
self.log.info({data : data}, 'vogels %s response - %sms', method.toUpperCase(), elapsed); | ||
return callback(null, data); | ||
} | ||
}); | ||
}; | ||
Table.prototype.get = function (hashKey, rangeKey, options, callback) { | ||
@@ -77,3 +97,3 @@ var self = this; | ||
self.docClient.get(params, function (err, data) { | ||
self.sendRequest('get', params, function (err, data) { | ||
if(err) { | ||
@@ -146,3 +166,3 @@ return callback(err); | ||
self.docClient.put(params, function (err) { | ||
self.sendRequest('put', params, function (err) { | ||
if(err) { | ||
@@ -250,3 +270,3 @@ return callback(err); | ||
self.docClient.update(params, function (err, data) { | ||
self.sendRequest('update', params, function (err, data) { | ||
if(err) { | ||
@@ -309,3 +329,3 @@ return callback(err); | ||
self.docClient.delete(params, function (err, data) { | ||
self.sendRequest('delete', params, function (err, data) { | ||
if(err) { | ||
@@ -373,3 +393,3 @@ return callback(err); | ||
self.docClient.query(params, internals.deserializeItems(self, callback)); | ||
self.sendRequest('query', params, internals.deserializeItems(self, callback)); | ||
}; | ||
@@ -380,3 +400,3 @@ | ||
self.docClient.scan(params, internals.deserializeItems(self, callback)); | ||
self.sendRequest('scan', params, internals.deserializeItems(self, callback)); | ||
}; | ||
@@ -387,3 +407,3 @@ | ||
var self = this; | ||
self.docClient.batchGet(params, callback); | ||
self.sendRequest('batchGet', params, callback); | ||
}; | ||
@@ -390,0 +410,0 @@ |
{ | ||
"name": "vogels", | ||
"version": "2.0.0", | ||
"version": "2.0.1", | ||
"author": "Ryan Fitzgerald <ryan@codebrewstudios.com>", | ||
@@ -23,7 +23,8 @@ "description": "DynamoDB data mapper", | ||
"dependencies": { | ||
"async": "1.5.x", | ||
"aws-sdk": "2.2.x", | ||
"bunyan": "1.5.x", | ||
"joi": "5.x.x", | ||
"lodash": "3.10.x", | ||
"joi": "5.x.x", | ||
"node-uuid": "1.4.x", | ||
"async": "1.5.x" | ||
"node-uuid": "1.4.x" | ||
}, | ||
@@ -30,0 +31,0 @@ "devDependencies": { |
@@ -26,9 +26,31 @@ # vogels [](https://travis-ci.org/ryanfitz/vogels) | ||
You can also directly pass in your access key id and secret | ||
When running on EC2 its recommended to leverage EC2 IAM roles. If you have configured your instance to use IAM roles, Vogels will automatically select these credentials for use in your application, and you do not need to manually provide credentials in any other format. | ||
```js | ||
var vogels = require('vogels'); | ||
vogels.AWS.config.update({accessKeyId: 'AKID', secretAccessKey: 'SECRET'}); | ||
vogels.AWS.config.update({region: "REGION"}); // region must be set | ||
``` | ||
You can also directly pass in your access key id, secret and region. | ||
* Its recommend you not hard-code credentials inside an application. Use this method only for small personal scripts or for testing purposes. | ||
```js | ||
var vogels = require('vogels'); | ||
vogels.AWS.config.update({accessKeyId: 'AKID', secretAccessKey: 'SECRET', region: "REGION"}); | ||
``` | ||
Currently the following region codes are available in Amazon: | ||
| Code | Name | | ||
| -------------- | ------------------------ | | ||
| ap-northeast-1 | Asia Pacific (Tokyo) | | ||
| ap-southeast-1 | Asia Pacific (Singapore) | | ||
| ap-southeast-2 | Asia Pacific (Sydney) | | ||
| eu-central-1 | EU (Frankfurt) | | ||
| eu-west-1 | EU (Ireland) | | ||
| sa-east-1 | South America (Sao Paulo)| | ||
| us-east-1 | US East (N. Virginia) | | ||
| us-west-1 | US West (N. California) | | ||
| us-west-2 | US West (Oregon) | | ||
### Define a Model | ||
@@ -936,2 +958,19 @@ Models are defined through the toplevel define method. | ||
### Logging | ||
Logging can be enabled to provide detailed information on data being sent and returned from DynamoDB. | ||
By default logging is turned off. | ||
```js | ||
vogels.log.level('info'); // enabled INFO log level | ||
``` | ||
Logging can also be enabled / disabled at the model level. | ||
```js | ||
var Account = vogels.define('Account', {hashKey : 'email'}); | ||
var Event = vogels.define('Account', {hashKey : 'name'}); | ||
Account.log.level('warn'); // enable WARN log level for Account model operations | ||
``` | ||
## Examples | ||
@@ -938,0 +977,0 @@ |
@@ -372,2 +372,16 @@ 'use strict'; | ||
it('should return users tweets with specific attributes', function(done) { | ||
Tweet.query('userid-1').attributes(['num', 'content']).exec(function (err, data) { | ||
expect(err).to.not.exist; | ||
expect(data.Items).to.have.length.above(0); | ||
_.each(data.Items, function (t) { | ||
expect(t.get('UserId')).to.not.exist; | ||
expect(t.get()).to.include.keys('num', 'content'); | ||
}); | ||
return done(); | ||
}); | ||
}); | ||
it('should return tweets using secondaryIndex', function(done) { | ||
@@ -510,3 +524,16 @@ Tweet.query('userid-1') | ||
}); | ||
}); | ||
it('should return users with specific attributes', function(done) { | ||
User.scan() | ||
.where('age').gt(18) | ||
.attributes(['email', 'roles', 'age']).exec(function (err, data) { | ||
expect(err).to.not.exist; | ||
expect(data.Items).to.have.length.above(0); | ||
_.each(data.Items, function (u) { | ||
expect(u.get()).to.include.keys('email', 'roles', 'age'); | ||
}); | ||
return done(); | ||
}); | ||
}); | ||
@@ -513,0 +540,0 @@ |
@@ -28,3 +28,3 @@ 'use strict'; | ||
table = new Table('mockTable', schema, serializer, helper.mockDocClient()); | ||
table = new Table('mockTable', schema, serializer, helper.mockDocClient(), helper.testLogger()); | ||
}); | ||
@@ -31,0 +31,0 @@ |
@@ -29,3 +29,3 @@ 'use strict'; | ||
table = new Table('mockTable', schema, serializer, helper.mockDynamoDB()); | ||
table = new Table('mockTable', schema, serializer, helper.mockDynamoDB(), helper.testLogger()); | ||
}); | ||
@@ -32,0 +32,0 @@ |
@@ -25,2 +25,3 @@ 'use strict'; | ||
table.docClient = helper.mockDocClient(); | ||
table.log = helper.testLogger(); | ||
}); | ||
@@ -62,3 +63,3 @@ | ||
var s = new Schema(config); | ||
var t = new Table('accounts', s, Serializer, helper.mockDocClient()); | ||
var t = new Table('accounts', s, Serializer, helper.mockDocClient(), helper.testLogger()); | ||
@@ -86,3 +87,3 @@ t.docClient.query.yields(new Error('Fail')); | ||
var t = new Table('accounts', s, Serializer, helper.mockDocClient()); | ||
var t = new Table('accounts', s, Serializer, helper.mockDocClient(), helper.testLogger()); | ||
@@ -116,3 +117,3 @@ t.docClient.query.yields(new Error('Fail')); | ||
var t = new Table('accounts', s, Serializer, helper.mockDocClient()); | ||
var t = new Table('accounts', s, Serializer, helper.mockDocClient(), helper.testLogger()); | ||
@@ -346,4 +347,5 @@ var err = new Error('RetryableException'); | ||
it('should set array attributes to get', function () { | ||
var query = new Query('tim', table, serializer).attributes(['created']); | ||
query.request.AttributesToGet.should.eql(['created']); | ||
var query = new Query('tim', table, serializer).attributes(['created', 'email']); | ||
query.request.ProjectionExpression.should.eql('#created,#email'); | ||
query.request.ExpressionAttributeNames.should.eql({'#created' : 'created', '#email' : 'email'}); | ||
}); | ||
@@ -353,3 +355,4 @@ | ||
var query = new Query('tim', table, serializer).attributes('email'); | ||
query.request.AttributesToGet.should.eql(['email']); | ||
query.request.ProjectionExpression.should.eql('#email'); | ||
query.request.ExpressionAttributeNames.should.eql({'#email' : 'email'}); | ||
}); | ||
@@ -356,0 +359,0 @@ |
@@ -139,4 +139,5 @@ 'use strict'; | ||
it('should set array attributes to get', function () { | ||
var scan = new Scan(table, serializer).attributes(['created']); | ||
scan.request.AttributesToGet.should.eql(['created']); | ||
var scan = new Scan(table, serializer).attributes(['created', 'email']); | ||
scan.request.ProjectionExpression.should.eql('#created,#email'); | ||
scan.request.ExpressionAttributeNames.should.eql({'#created' : 'created', '#email' : 'email'}); | ||
}); | ||
@@ -146,3 +147,4 @@ | ||
var scan = new Scan(table, serializer).attributes('email'); | ||
scan.request.AttributesToGet.should.eql(['email']); | ||
scan.request.ProjectionExpression.should.eql('#email'); | ||
scan.request.ExpressionAttributeNames.should.eql({'#email' : 'email'}); | ||
}); | ||
@@ -355,3 +357,2 @@ | ||
console.log('scan info', scan.request); | ||
scan.request.ExpressionAttributeNames.should.eql({'#created' : 'created'}); | ||
@@ -358,0 +359,0 @@ scan.request.ExpressionAttributeValues.should.eql({':created' : d.toISOString()}); |
@@ -22,3 +22,4 @@ 'use strict'; | ||
docClient, | ||
dynamodb; | ||
dynamodb, | ||
logger; | ||
@@ -29,2 +30,3 @@ beforeEach(function () { | ||
dynamodb = docClient.service; | ||
logger = helper.testLogger(); | ||
}); | ||
@@ -41,3 +43,3 @@ | ||
table = new Table('accounts', s, realSerializer, docClient); | ||
table = new Table('accounts', s, realSerializer, docClient, logger, logger); | ||
@@ -72,3 +74,3 @@ var request = { | ||
table = new Table('accounts', s, realSerializer, docClient); | ||
table = new Table('accounts', s, realSerializer, docClient, logger); | ||
@@ -105,3 +107,3 @@ var request = { | ||
table = new Table('accounts', s, realSerializer, docClient); | ||
table = new Table('accounts', s, realSerializer, docClient, logger); | ||
@@ -137,3 +139,3 @@ var request = { | ||
table = new Table('accounts', s, realSerializer, docClient); | ||
table = new Table('accounts', s, realSerializer, docClient, logger); | ||
@@ -175,3 +177,3 @@ var request = { | ||
table = new Table('accounts', s, realSerializer, docClient); | ||
table = new Table('accounts', s, realSerializer, docClient, logger); | ||
@@ -205,3 +207,3 @@ var request = { | ||
table = new Table('accounts', s, realSerializer, docClient); | ||
table = new Table('accounts', s, realSerializer, docClient, logger); | ||
@@ -233,3 +235,3 @@ docClient.get.yields(new Error('Fail')); | ||
table = new Table('accounts', s, realSerializer, docClient); | ||
table = new Table('accounts', s, realSerializer, docClient, logger); | ||
@@ -270,3 +272,3 @@ var request = { | ||
table = new Table('accounts', s, realSerializer, docClient); | ||
table = new Table('accounts', s, realSerializer, docClient, logger); | ||
@@ -309,3 +311,3 @@ var request = { | ||
table = new Table('accounts', s, realSerializer, docClient); | ||
table = new Table('accounts', s, realSerializer, docClient, logger); | ||
@@ -357,3 +359,3 @@ var numberSet = sinon.match(function (value) { | ||
table = new Table('accounts', s, realSerializer, docClient); | ||
table = new Table('accounts', s, realSerializer, docClient, logger); | ||
@@ -392,3 +394,3 @@ var request = { | ||
table = new Table('accounts', s, realSerializer, docClient); | ||
table = new Table('accounts', s, realSerializer, docClient, logger); | ||
@@ -428,3 +430,3 @@ var request = { | ||
table = new Table('accounts', s, realSerializer, docClient); | ||
table = new Table('accounts', s, realSerializer, docClient, logger); | ||
@@ -461,3 +463,3 @@ var request = { | ||
table = new Table('accounts', s, realSerializer, docClient); | ||
table = new Table('accounts', s, realSerializer, docClient, logger); | ||
@@ -496,3 +498,3 @@ var request = { | ||
table = new Table('accounts', s, realSerializer, docClient); | ||
table = new Table('accounts', s, realSerializer, docClient, logger); | ||
@@ -525,3 +527,3 @@ var request = { | ||
table = new Table('accounts', s, realSerializer, docClient); | ||
table = new Table('accounts', s, realSerializer, docClient, logger); | ||
@@ -554,3 +556,3 @@ table.create({email : 'test@test.com', name : [1, 2, 3]}, function (err, account) { | ||
table = new Table('accounts', s, realSerializer, docClient); | ||
table = new Table('accounts', s, realSerializer, docClient, logger); | ||
@@ -600,3 +602,3 @@ var request = { | ||
table = new Table('accounts', s, realSerializer, docClient); | ||
table = new Table('accounts', s, realSerializer, docClient, logger); | ||
@@ -650,3 +652,3 @@ var request = { | ||
table = new Table('accounts', s, realSerializer, docClient); | ||
table = new Table('accounts', s, realSerializer, docClient, logger); | ||
@@ -705,3 +707,3 @@ var request = { | ||
table = new Table('accounts', s, realSerializer, docClient); | ||
table = new Table('accounts', s, realSerializer, docClient, logger); | ||
@@ -745,3 +747,3 @@ var request = { | ||
table = new Table('accounts', s, realSerializer, docClient); | ||
table = new Table('accounts', s, realSerializer, docClient, logger); | ||
@@ -775,3 +777,3 @@ docClient.update.yields(new Error('Fail')); | ||
table = new Table('accounts', s, serializer, docClient); | ||
table = new Table('accounts', s, serializer, docClient, logger); | ||
@@ -796,3 +798,3 @@ table.query('Bob').should.be.instanceof(Query); | ||
table = new Table('accounts', s, serializer, docClient); | ||
table = new Table('accounts', s, serializer, docClient, logger); | ||
@@ -817,3 +819,3 @@ table.scan().should.be.instanceof(Scan); | ||
table = new Table('accounts', s, serializer, docClient); | ||
table = new Table('accounts', s, serializer, docClient, logger); | ||
@@ -851,3 +853,3 @@ var request = { | ||
table = new Table('accounts', s, serializer, docClient); | ||
table = new Table('accounts', s, serializer, docClient, logger); | ||
@@ -886,3 +888,3 @@ var request = { | ||
table = new Table('accounts', s, serializer, docClient); | ||
table = new Table('accounts', s, serializer, docClient, logger); | ||
@@ -930,3 +932,3 @@ var request = { | ||
table = new Table('accounts', s, serializer, docClient); | ||
table = new Table('accounts', s, serializer, docClient, logger); | ||
@@ -976,3 +978,3 @@ var request = { | ||
table = new Table('accounts', s, serializer, docClient); | ||
table = new Table('accounts', s, serializer, docClient, logger); | ||
@@ -1022,3 +1024,3 @@ var request = { | ||
table = new Table('accounts', s, serializer, docClient); | ||
table = new Table('accounts', s, serializer, docClient, logger); | ||
@@ -1060,3 +1062,3 @@ var request = { | ||
table = new Table('accounts', s, realSerializer, docClient); | ||
table = new Table('accounts', s, realSerializer, docClient, logger); | ||
@@ -1090,3 +1092,3 @@ var request = { | ||
table = new Table('accounts', s, realSerializer, docClient); | ||
table = new Table('accounts', s, realSerializer, docClient, logger); | ||
@@ -1124,3 +1126,3 @@ var request = { | ||
table = new Table('accounts', s, serializer, docClient); | ||
table = new Table('accounts', s, serializer, docClient, logger); | ||
@@ -1160,3 +1162,3 @@ var request = { | ||
table = new Table('accounts', s, serializer, docClient); | ||
table = new Table('accounts', s, serializer, docClient, logger); | ||
@@ -1202,3 +1204,3 @@ var request = { | ||
table = new Table('accounts', s, serializer, docClient); | ||
table = new Table('accounts', s, serializer, docClient, logger); | ||
@@ -1369,3 +1371,3 @@ var request = { | ||
table = new Table('accounts', s, serializer, docClient); | ||
table = new Table('accounts', s, serializer, docClient, logger); | ||
@@ -1400,3 +1402,3 @@ var request = { | ||
table = new Table('accounts', s, serializer, docClient); | ||
table = new Table('accounts', s, serializer, docClient, logger); | ||
}); | ||
@@ -1446,3 +1448,3 @@ | ||
table = new Table('accounts', s, serializer, docClient); | ||
table = new Table('accounts', s, serializer, docClient, logger); | ||
}); | ||
@@ -1490,3 +1492,3 @@ | ||
table = new Table('accounts', s, serializer, docClient); | ||
table = new Table('accounts', s, serializer, docClient, logger); | ||
@@ -1508,3 +1510,3 @@ table.tableName().should.eql('accounts'); | ||
table = new Table('accounts', s, serializer, docClient); | ||
table = new Table('accounts', s, serializer, docClient, logger); | ||
@@ -1533,3 +1535,3 @@ table.tableName().should.eql('accounts-2014-03'); | ||
table = new Table('accounts', s, serializer, docClient); | ||
table = new Table('accounts', s, serializer, docClient, logger); | ||
@@ -1558,3 +1560,3 @@ table.tableName().should.eql('accounts_' + dateString); | ||
table = new Table('accounts', s, serializer, docClient); | ||
table = new Table('accounts', s, serializer, docClient, logger); | ||
@@ -1601,3 +1603,3 @@ var item = {email : 'test@test.com', name : 'Tim Test', age : 23}; | ||
table = new Table('accounts', s, serializer, docClient); | ||
table = new Table('accounts', s, serializer, docClient, logger); | ||
@@ -1628,3 +1630,3 @@ table.before('create', function (data, next) { | ||
table = new Table('accounts', s, serializer, docClient); | ||
table = new Table('accounts', s, serializer, docClient, logger); | ||
@@ -1660,3 +1662,3 @@ var item = {email : 'test@test.com', name : 'Tim Test', age : 23}; | ||
table = new Table('accounts', s, serializer, docClient); | ||
table = new Table('accounts', s, serializer, docClient, logger); | ||
@@ -1702,3 +1704,3 @@ var item = {email : 'test@test.com', name : 'Tim Test', age : 23}; | ||
table = new Table('accounts', s, serializer, docClient); | ||
table = new Table('accounts', s, serializer, docClient, logger); | ||
@@ -1729,3 +1731,3 @@ table.before('update', function (data, next) { | ||
table = new Table('accounts', s, serializer, docClient); | ||
table = new Table('accounts', s, serializer, docClient, logger); | ||
@@ -1763,3 +1765,3 @@ var item = {email : 'test@test.com', name : 'Tim Test', age : 23}; | ||
table = new Table('accounts', s, serializer, docClient); | ||
table = new Table('accounts', s, serializer, docClient, logger); | ||
@@ -1766,0 +1768,0 @@ docClient.delete.yields(null, {}); |
'use strict'; | ||
var sinon = require('sinon'), | ||
AWS = require('aws-sdk'), | ||
Table = require('../lib/table'), | ||
_ = require('lodash'); | ||
var sinon = require('sinon'), | ||
AWS = require('aws-sdk'), | ||
Table = require('../lib/table'), | ||
_ = require('lodash'), | ||
bunyan = require('bunyan'); | ||
@@ -33,3 +34,2 @@ exports.mockDynamoDB = function () { | ||
exports.mockDocClient = function () { | ||
@@ -96,1 +96,9 @@ var client = new AWS.DynamoDB.DocumentClient({service : exports.mockDynamoDB()}); | ||
}; | ||
exports.testLogger = function() { | ||
return bunyan.createLogger({ | ||
name: 'vogels-tests', | ||
serializers : {err: bunyan.stdSerializers.err}, | ||
level : bunyan.FATAL | ||
}); | ||
}; |
299832
7817
1050
6
+ Addedbunyan@1.5.x
+ Addedbalanced-match@1.0.2(transitive)
+ Addedbrace-expansion@1.1.11(transitive)
+ Addedbunyan@1.5.1(transitive)
+ Addedconcat-map@0.0.1(transitive)
+ Addeddtrace-provider@0.6.0(transitive)
+ Addedglob@6.0.4(transitive)
+ Addedinflight@1.0.6(transitive)
+ Addedinherits@2.0.4(transitive)
+ Addedminimatch@3.1.2(transitive)
+ Addedminimist@1.2.8(transitive)
+ Addedmkdirp@0.5.6(transitive)
+ Addedmv@2.1.1(transitive)
+ Addednan@2.22.0(transitive)
+ Addedncp@2.0.0(transitive)
+ Addedonce@1.4.0(transitive)
+ Addedpath-is-absolute@1.0.1(transitive)
+ Addedrimraf@2.4.5(transitive)
+ Addedsafe-json-stringify@1.2.0(transitive)
+ Addedwrappy@1.0.2(transitive)