diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..3a264c22 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,22 @@ +Change Log +========== + +`apns2` follows [Semantic Versioning](http://semver.org/) + +--- + +## [4.0.0](https://github.com/AndrewBarba/apns2/releases/tag/4.0.0) + +1. Remove support for Node versions less than v8.10 +2. High-performance connection pool using [tarn](https://github.com/vincit/tarn.js) +3. More friendly require API, see README for updated usage + +## [3.0.1](https://github.com/AndrewBarba/apns2/releases/tag/3.0.1) + +1. Fix Typescript definitions + +## [3.0.0](https://github.com/AndrewBarba/apns2/releases/tag/3.0.1) + +1. Introduces support for the native `http2` module in Node.js v8.4.0 or later with fall back to `node-spdy` in earlier versions of Node.js. + +To use the new `http2` library you must start your node process with `node --expose-http2` and apns2 will automatically use the native module. Later versions of Node.js may expose the native module without the need for a command line flag. In this case, apns2 will automatically use the native module without any additional steps on your end. diff --git a/Makefile b/Makefile deleted file mode 100644 index ad3f33b3..00000000 --- a/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -lint: - ./node_modules/eslint/bin/eslint.js ./ - -test-all: test-http2 test-spdy - -test-http2: - @NODE_ENV=test \ - node --expose-http2 \ - ./node_modules/.bin/_mocha \ - --slow 2000 \ - --timeout 20000 \ - ./test/test.js - -test-spdy: - @NODE_ENV=test \ - node \ - ./node_modules/.bin/_mocha \ - --slow 2000 \ - --timeout 20000 \ - ./test/test.js diff --git a/README.md b/README.md index 59e25cd9..bca67b22 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,7 @@ APNS2 Node client for connecting to Apple's Push Notification Service using the new HTTP/2 protocol with JSON web tokens. -> Now uses the native `http2` module in Node.js v8.4.0 when exposed with `--expose-http2` - -> On earlier versions of Node.js we fallback to the `node-spdy` module +> Now uses the native `http2` module in Node.js v8.10 or later --- @@ -17,14 +15,14 @@ Node client for connecting to Apple's Push Notification Service using the new HT Create an APNS client using a signing key: ```javascript -const APNS = require('apns2'); +const { APNS } = require('apns2') let client = new APNS({ team: `TFLP87PW54`, keyId: `123ABC456`, signingKey: fs.readFileSync(`${__dirname}/path/to/auth.p8`), defaultTopic: `com.tablelist.Tablelist` -}); +}) ``` ## Sending Notifications @@ -34,34 +32,34 @@ let client = new APNS({ Send a basic notification with message: ```javascript -const { BasicNotification } = APNS; +const { BasicNotification } = require('apns2') -let bn = new BasicNotification(deviceToken, 'Hello, World'); +let bn = new BasicNotification(deviceToken, 'Hello, World') client.send(bn).then(() => { // sent successfully }).catch(err => { - console.error(err.reason); -}); + console.error(err.reason) +}) ``` Send a basic notification with message and options: ```javascript -const { BasicNotification } = APNS; +const { BasicNotification } = require('apns2') let bn = new BasicNotification(deviceToken, 'Hello, World', { badge: 4, data: { userId: user.getUserId } -}); +}) client.send(bn).then(() => { // sent successfully }).catch(err => { - console.error(err.reason); -}); + console.error(err.reason) +}) ``` #### Silent @@ -69,15 +67,15 @@ client.send(bn).then(() => { Send a silent notification using `content-available` key: ```javascript -const { SilentNotification } = APNS; +const { SilentNotification } = require('apns2') -let sn = new SilentNotification(deviceToken); +let sn = new SilentNotification(deviceToken) client.send(sn).then(() => { // sent successfully }).catch(err => { - console.error(err.reason); -}); + console.error(err.reason) +}) ``` Note: [Apple recommends](https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/TheNotificationPayload.html#//apple_ref/doc/uid/TP40008194-CH107-SW1) that no options other than the `content-available` flag be sent in order for a notification to truly be silent and wake up your app in the background. Therefore this class does not accept any additional options in the constructor. @@ -87,17 +85,17 @@ Note: [Apple recommends](https://developer.apple.com/library/ios/documentation/N For complete control over the push notification packet use the base `Notification` class: ```javascript -const { Notification } = APNS; +const { Notification } = require('apns2') let notification = new Notification(deviceToken, { aps: { ... } -}); +}) client.send(notification).then(() => { // sent successfully }).catch(err => { - console.error(err.reason); -}); + console.error(err.reason) +}) ``` Available options can be found at [APNS Payload Options](https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/PayloadKeyReference.html#//apple_ref/doc/uid/TP40008194-CH17-SW1) @@ -109,19 +107,19 @@ All errors are defined in `./lib/errors.js` and come directly from [APNS Table 8 You can easily listen for these errors by attaching an error handler to the APNS client: ```javascript -const errors = APNS.errors; +const { Errors } = require('apns2') // Listen for a specific error -client.on(errors.badDeviceToken, err => { +client.on(Errors.badDeviceToken, err => { // Handle accordingly... // Perhaps delete token from your database - console.error(err.reason, err.statusCode, err.notification.deviceToken); -}); + console.error(err.reason, err.statusCode, err.notification.deviceToken) +}) // Listen for any error -client.on(errors.error, err => { - console.error(err.reason, err.statusCode, err.notification.deviceToken); -}); +client.on(Errors.error, err => { + console.error(err.reason, err.statusCode, err.notification.deviceToken) +}) ``` ## Environments @@ -133,7 +131,7 @@ let client = new APNS({ host: 'api.push.apple.com', port: 443, ... -}); +}) ``` To connect to the development push notification server, pass the options: @@ -142,13 +140,9 @@ To connect to the development push notification server, pass the options: let client = new APNS({ host: 'api.development.push.apple.com' ... -}); +}) ``` ## Requirements -`apns2` requires Node.js v6 - -#### Native http2 - -To use the new built in `http2` library in Node.js v8.4.0 you must start your node process with `node --expose-http2`. apns2 will automatically pick up the native module and use it instead of `node-spdy`. +`apns2` requires Node.js v8.10 or later diff --git a/lib/apns.js b/lib/apns.js index 023807b7..1095dea3 100644 --- a/lib/apns.js +++ b/lib/apns.js @@ -1,25 +1,14 @@ const _ = require('lodash') -const apnsErrors = require('./errors') -const EventEmitter = require('events').EventEmitter -const jwt = require('jsonwebtoken') const Promise = require('bluebird') - -// Notifications +const { EventEmitter } = require('events') +const { Pool } = require('tarn') +const jwt = require('jsonwebtoken') +const Http2Client = require('./http2-client') +const Errors = require('./errors') const Notification = require('./notifications/notification') const BasicNotification = require('./notifications/basic-notification') const SilentNotification = require('./notifications/silent-notification') -// HTTP/2 Client -const HTTP2Client = (() => { - try { - // try native module - return require('./http2-client') - } catch(err) { - // else fallback to spdy - return require('./spdy-client') - } -})() - /** * @const * @desc APNS version @@ -30,13 +19,13 @@ const API_VERSION = 3 * @const * @desc Number of connections to open up with apns API */ -const MAX_CONNECTIONS = 8 +const MAX_CONNECTIONS = 10 /** * @const * @desc Max notifications to send concurrently */ -const CONCURRENCY = 32 +const CONCURRENCY = 64 /** * @const @@ -67,38 +56,6 @@ const RESET_TOKEN_INTERVAL = 20 * 60 * 1000 */ class APNS extends EventEmitter { - /** - * @static - * @prop {Class} Notification - */ - static get Notification() { - return Notification - } - - /** - * @static - * @prop {Class} BasicNotification - */ - static get BasicNotification() { - return BasicNotification - } - - /** - * @static - * @prop {Class} SilentNotification - */ - static get SilentNotification() { - return SilentNotification - } - - /** - * @static - * @prop {Object} errors - */ - static get errors() { - return apnsErrors - } - /** * @constructor * @param {Object} options @@ -119,10 +76,35 @@ class APNS extends EventEmitter { this._signingKey = signingKey this._defaultTopic = defaultTopic this._concurrency = concurrency - this._clients = _.times(connections, () => new HTTP2Client(host, port)) - this._clientIndex = 0 + this._clients = this._createClientPool({ host, port, connections }) this._interval = setInterval(() => this._resetSigningToken(), RESET_TOKEN_INTERVAL).unref() - this.on(apnsErrors.expiredProviderToken, () => this._resetSigningToken()) + this.on(Errors.expiredProviderToken, () => this._resetSigningToken()) + } + + /** + * @private + * @method _createClientPool + * @param {String} host + * @param {Number} port + * @return {Pool} + */ + _createClientPool({ host, port, connections }) { + return new Pool({ + create: cb => new Http2Client(host, port).connect().asCallback(cb), + validate: client => client.ready, + destroy: client => client.destroy(), + min: 0, + max: connections + }) + } + + /** + * @private + * @method _acquireClient + * @return {Promise} + */ + _acquireClient() { + return Promise.resolve(this._clients.acquire().promise) } /** @@ -142,17 +124,6 @@ class APNS extends EventEmitter { }) } - /** - * @private - * @param {HTTP2Client} _nextClient - */ - get _nextClient() { - let client = this._clients[this._clientIndex] - let nextIndex = this._clientIndex + 1 - this._clientIndex = nextIndex < this._clients.length ? nextIndex : 0 - return client - } - /** * @private * @method _send @@ -179,7 +150,8 @@ class APNS extends EventEmitter { let body = JSON.stringify(notification.APNSOptions()) - return this._nextClient.post(options, body) + return this._acquireClient() + .then(client => client.post(options, body)) .then(res => this._handleServerResponse(res, notification)) } @@ -199,14 +171,14 @@ class APNS extends EventEmitter { try { json = JSON.parse(res.body) } catch(err) { - json = { reason: apnsErrors.unknownError } + json = { reason: Errors.unknownError } } json.statusCode = res.statusCode json.notification = notification this.emit(json.reason, json) - this.emit(apnsErrors.error, json) + this.emit(Errors.error, json) return Promise.reject(json) } @@ -242,7 +214,7 @@ class APNS extends EventEmitter { token = this._token = jwt.sign(claims, key, options) } catch(err) { token = this._token = null - this.emit(apnsErrors.invalidSigningKey) + this.emit(Errors.invalidSigningKey) } return token @@ -258,4 +230,10 @@ class APNS extends EventEmitter { } } -module.exports = APNS +module.exports = { + APNS, + Errors, + Notification, + BasicNotification, + SilentNotification +} diff --git a/lib/http2-client.js b/lib/http2-client.js index 8ce1c394..4b947674 100644 --- a/lib/http2-client.js +++ b/lib/http2-client.js @@ -3,7 +3,9 @@ const Promise = require('bluebird') const http2 = require('http2') // Check to make sure this is the native http2 -if (!http2.constants || !http2.constants.NGHTTP2_SESSION_CLIENT) throw new Error('Invalid http2 library') +if (!http2.constants || !http2.constants.NGHTTP2_SESSION_CLIENT) { + throw new Error('Invalid http2 library, must be running Node v8.10 or later') +} const { HTTP2_HEADER_METHOD, @@ -23,7 +25,48 @@ class HTTP2Client { if (!host) throw new Error('host is required') this._url = new URL(`https://${host}:${port}`) this._timeout = timeout - this.client() + this._ready = false + this._session = null + } + + /** + * @param {Boolean} ready + */ + get ready() { + return this._ready && this._session && !this._session.destroyed + } + + /** + * @param {Http2Session} + */ + get session() { + return this._session + } + + /** + * @method connect + * @return {Promise} + */ + connect() { + return new Promise((resolve, reject) => { + let session = http2.connect(this._url) + session.once('socketError', reject) + session.once('connect', () => { + this._connected(session) + resolve(this) + }) + }) + } + + /** + * @method destroy + */ + destroy() { + if (this._session && !this._session.destroyed) { + this._session.destroy() + } + this._ready = false + this._session = null } /** @@ -67,24 +110,25 @@ class HTTP2Client { * @return {Promise} */ request({ method, path, headers={} }, body=null) { - if (!method) return Promise.reject(`method is required`) - if (!path) return Promise.reject(`path is required`) + if (!method) throw new Error('method is required') + if (!path) throw new Error('path is required') + if (!this._session) throw new Error('Must call connect() before making a request') return new Promise((resolve, reject) => { headers[HTTP2_HEADER_METHOD] = method headers[HTTP2_HEADER_PATH] = path - - let req = this.client().request(headers) - + + let req = this._session.request(headers) + // Cancel request after timeout req.setTimeout(this._timeout, () => req.rstWithCancel()) // Response handling req.on('response', headers => { let body = '' - + req.on('data', chunk => body += chunk) - + req.on('end', () => { resolve({ statusCode: headers[HTTP2_HEADER_STATUS], @@ -109,20 +153,17 @@ class HTTP2Client { /** * @private - * @return {Http2Session} + * @method _connected + * @param {Http2Session} session */ - client() { - if (this._client && this._client.destroyed === false) { - return this._client - } - - // Create client - let client = this._client = http2.connect(this._url) - - // Events - client.on('goaway', () => client.destroy()) - - return client + _connected(session) { + session.on('close', () => this.destroy()) + session.on('frameError', () => this.destroy()) + session.on('goaway', () => this.destroy()) + session.on('socketError', () => this.destroy()) + session.on('timeout', () => this.destroy()) + this._session = session + this._ready = true } } diff --git a/lib/spdy-client.js b/lib/spdy-client.js deleted file mode 100644 index 7de5b7fb..00000000 --- a/lib/spdy-client.js +++ /dev/null @@ -1,120 +0,0 @@ -const https = require('https') -const spdy = require('spdy') -const Promise = require('bluebird') - -/** - * @class SpdyClient - */ -class SpdyClient { - - /** - * @constructor - */ - constructor(host, port=443) { - if (!host) throw new Error('host is required') - this._host = host - this._port = port - this.agent() - } - - /** - * @method get - */ - get(options) { - options.method = `GET` - return this.request(options) - } - - /** - * @method post - */ - post(options, body) { - options.method = `POST` - return this.request(options, body) - } - - /** - * @method put - */ - put(options, body) { - options.method = `PUT` - return this.request(options, body) - } - - /** - * @method delete - */ - delete(options) { - options.method = `DELETE` - return this.request(options) - } - - /** - * @method request - * @param {Object} options - * @param {String} options.method - * @param {String} options.host - * @param {String|Buffer} [body] - * @return {Promise} - */ - request(options, body) { - if (!options) return Promise.reject(`options is required`) - if (!options.method) return Promise.reject(`options.method is required`) - if (!options.path) return Promise.reject(`options.path is required`) - - options.agent = this.agent() - - return new Promise((resolve, reject) => { - this._reject = reject - - let req = https.request(options, res => { - let body = '' - - res.on('data', chunk => body += chunk) - - res.on('end', () => { - resolve({ - statusCode: res.statusCode, - headers: res.headers, - body - }) - }) - }) - - req.on('error', reject) - - if (body) { - req.write(body) - } - - req.end() - }) - } - - /** - * @private - * @return {Http2Session} - */ - agent() { - if (this._agent && this._agent._spdyState.connection && this._agent._spdyState.connection._spdyState.goaway === false) { - return this._agent - } - - let agent = this._agent = spdy.createAgent({ - host: this._host, - port: this._port, - spdy: { - protocols: ['h2'] - } - }) - - agent.on('error', err => { - if (!this._reject) return - this._reject(err) - }) - - return agent - } -} - -module.exports = SpdyClient diff --git a/package.json b/package.json index 3cba3c43..196f05f9 100644 --- a/package.json +++ b/package.json @@ -1,30 +1,30 @@ { "name": "apns2", - "version": "3.0.1", + "version": "4.0.0", "description": "Node client for connecting to Apple's Push Notification Service using the new HTTP/2 protocol with JSON web tokens.", "author": "Andrew Barba ", "main": "lib/apns.js", "types": "lib/apns.d.ts", "license": "MIT", "engines": { - "node": ">=6.0.0" + "node": ">=8.10.0" }, "repository": { "url": "https://github.com/AndrewBarba/apns2" }, "dependencies": { - "bluebird": "^3.4.1", - "jsonwebtoken": "^7.0.1", - "lodash": "^4.13.1", - "spdy": "^3.4.7" + "bluebird": "3.5.1", + "jsonwebtoken": "8.2.1", + "lodash": "4.17.10", + "tarn": "1.1.4" }, "devDependencies": { - "eslint": "^4.5.0", - "mocha": "^3.3.0", - "should": "^12.0.0" + "eslint": "4.19.1", + "mocha": "5.1.1", + "should": "13.2.1" }, "scripts": { - "lint": "make lint", - "test": "make test-all" + "lint": "npx eslint ./", + "test": "npx mocha --exit --bail --slow 1000 --timeout 5000 ./test/test.js" } } diff --git a/test/test.js b/test/test.js index ec824430..c117d46b 100644 --- a/test/test.js +++ b/test/test.js @@ -2,15 +2,14 @@ const fs = require('fs') const should = require('should') // Package -const APNS = require('../') -const errors = APNS.errors -const HTTP2Client = (() => { - try { - return require('../lib/http2-client') - } catch(err) { - return require('../lib/spdy-client') - } -})() +const HTTP2Client = require('../lib/http2-client') +const { + APNS, + Notification, + BasicNotification, + SilentNotification, + Errors +} = require('../') describe('http2', () => { @@ -19,6 +18,7 @@ describe('http2', () => { before(() => { client = new HTTP2Client('www.google.com', 443) + return client.connect() }) it('should make a get request', () => { @@ -45,14 +45,12 @@ describe('http2', () => { client = new HTTP2Client('bogus.google.com', 443, { timeout: 500 }) }) - it('should not make a get request', () => { - return client.get({ - path: '/' - }).then(() => { - throw new Error('Failed') - }).catch(() => { - // good - }) + it('should not connect', () => { + return client.connect() + .then(() => { + throw new Error('Failed') + }) + .catch(() => {}) }) }) }) @@ -75,19 +73,19 @@ describe('apns', () => { }) it('should send a basic notification', () => { - let basicNotification = new APNS.BasicNotification(deviceToken, `Hello, Basic`) + let basicNotification = new BasicNotification(deviceToken, `Hello, Basic`) return apns.send(basicNotification) }) it('should send a basic notification with options', () => { - let basicNotification = new APNS.BasicNotification(deviceToken, `Hello, 1`, { + let basicNotification = new BasicNotification(deviceToken, `Hello, 1`, { badge: 1 }) return apns.send(basicNotification) }) it('should send a basic notification with additional data', () => { - let basicNotification = new APNS.BasicNotification(deviceToken, `Hello, ICON`, { + let basicNotification = new BasicNotification(deviceToken, `Hello, ICON`, { badge: 0, data: { url: `venue/icon` @@ -97,12 +95,12 @@ describe('apns', () => { }) it('should send a silent notification', () => { - let silentNotification = new APNS.SilentNotification(deviceToken) + let silentNotification = new SilentNotification(deviceToken) return apns.send(silentNotification) }) it('should send a notification', () => { - let notification = new APNS.Notification(deviceToken, { + let notification = new Notification(deviceToken, { aps: { alert: { body: `Hello, Tablelist` @@ -113,8 +111,8 @@ describe('apns', () => { }) it('should send both notifications', () => { - let basicNotification = new APNS.BasicNotification(deviceToken, `Hello, Multiple`) - let silentNotification = new APNS.SilentNotification(deviceToken) + let basicNotification = new BasicNotification(deviceToken, `Hello, Multiple`) + let silentNotification = new SilentNotification(deviceToken) return apns.send([basicNotification, silentNotification]).then(result => { should.exist(result) result.length.should.equal(2) @@ -122,22 +120,22 @@ describe('apns', () => { }) it('should fail to send a notification', () => { - let noti = new APNS.BasicNotification(`fakedevicetoken`, `Hello, bad token`) + let noti = new BasicNotification(`fakedevicetoken`, `Hello, bad token`) return apns.send(noti).catch(err => { should.exist(err) - err.reason.should.equal(errors.badDeviceToken) + err.reason.should.equal(Errors.badDeviceToken) }) }) it('should fail to send a notification and emit an error', done => { - apns.once(errors.error, err => { + apns.once(Errors.error, err => { should.exist(err) - err.reason.should.equal(errors.badDeviceToken) + err.reason.should.equal(Errors.badDeviceToken) done() }) - let noti = new APNS.BasicNotification(`fakedevicetoken`, `Hello, bad token`) + let noti = new BasicNotification(`fakedevicetoken`, `Hello, bad token`) apns.send(noti).catch(err => { should.exist(err) }) @@ -145,13 +143,13 @@ describe('apns', () => { it('should fail to send a notification and emit an error', done => { - apns.once(errors.badDeviceToken, err => { + apns.once(Errors.badDeviceToken, err => { should.exist(err) - err.reason.should.equal(errors.badDeviceToken) + err.reason.should.equal(Errors.badDeviceToken) done() }) - let noti = new APNS.BasicNotification(`fakedevicetoken`, `Hello, bad token`) + let noti = new BasicNotification(`fakedevicetoken`, `Hello, bad token`) apns.send(noti).catch(err => { should.exist(err) }) diff --git a/yarn.lock b/yarn.lock index 550ff856..473cc954 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12,29 +12,22 @@ acorn@^3.0.4: version "3.3.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" -acorn@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.1.1.tgz#53fe161111f912ab999ee887a90a0bc52822fd75" - -ajv-keywords@^1.0.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" +acorn@^5.5.0: + version "5.5.3" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.5.3.tgz#f473dd47e0277a08e28e9bec5aeeb04751f0b8c9" -ajv@^4.7.0: - version "4.11.8" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" - dependencies: - co "^4.6.0" - json-stable-stringify "^1.0.1" +ajv-keywords@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762" -ajv@^5.2.0: - version "5.2.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.2.2.tgz#47c68d69e86f5d953103b0074a9430dc63da5e39" +ajv@^5.2.3, ajv@^5.3.0: + version "5.5.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" dependencies: co "^4.6.0" fast-deep-equal "^1.0.0" + fast-json-stable-stringify "^2.0.0" json-schema-traverse "^0.3.0" - json-stable-stringify "^1.0.1" ansi-escapes@^2.0.0: version "2.0.0" @@ -94,9 +87,9 @@ base64url@2.0.0, base64url@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/base64url/-/base64url-2.0.0.tgz#eac16e03ea1438eff9423d69baa36262ed1f70bb" -bluebird@^3.4.1: - version "3.5.0" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c" +bluebird@3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" brace-expansion@^1.1.7: version "1.1.8" @@ -105,9 +98,9 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -browser-stdout@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" buffer-equal-constant-time@1.0.1: version "1.0.1" @@ -123,7 +116,7 @@ callsites@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" -chalk@^1.1.1, chalk@^1.1.3: +chalk@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" dependencies: @@ -169,11 +162,9 @@ color-name@^1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" -commander@2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" - dependencies: - graceful-readlink ">= 1.0.0" +commander@2.11.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" concat-map@0.0.1: version "0.0.1" @@ -199,9 +190,9 @@ cross-spawn@^5.1.0: shebang-command "^1.2.0" which "^1.2.9" -debug@2.6.8, debug@^2.6.8: - version "2.6.8" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" +debug@3.1.0, debug@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" dependencies: ms "2.0.0" @@ -221,20 +212,15 @@ del@^2.0.2: pinkie-promise "^2.0.0" rimraf "^2.2.8" -detect-node@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.3.tgz#a2033c09cc8e158d37748fbde7507832bd6ce127" - -diff@3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9" +diff@3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" -doctrine@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.0.0.tgz#c73d8d2909d22291e1a007a395804da8b665fe63" +doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" dependencies: esutils "^2.0.2" - isarray "^1.0.0" ecdsa-sig-formatter@1.0.9: version "1.0.9" @@ -254,32 +240,36 @@ eslint-scope@^3.7.1: esrecurse "^4.1.0" estraverse "^4.1.1" -eslint@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.5.0.tgz#bb75d3b8bde97fb5e13efcd539744677feb019c3" +eslint-visitor-keys@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d" + +eslint@4.19.1: + version "4.19.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.19.1.tgz#32d1d653e1d90408854bfb296f076ec7e186a300" dependencies: - ajv "^5.2.0" + ajv "^5.3.0" babel-code-frame "^6.22.0" chalk "^2.1.0" concat-stream "^1.6.0" cross-spawn "^5.1.0" - debug "^2.6.8" - doctrine "^2.0.0" + debug "^3.1.0" + doctrine "^2.1.0" eslint-scope "^3.7.1" - espree "^3.5.0" + eslint-visitor-keys "^1.0.0" + espree "^3.5.4" esquery "^1.0.0" - estraverse "^4.2.0" esutils "^2.0.2" file-entry-cache "^2.0.0" functional-red-black-tree "^1.0.1" glob "^7.1.2" - globals "^9.17.0" + globals "^11.0.1" ignore "^3.3.3" imurmurhash "^0.1.4" inquirer "^3.0.6" is-resolvable "^1.0.0" js-yaml "^3.9.1" - json-stable-stringify "^1.0.1" + json-stable-stringify-without-jsonify "^1.0.1" levn "^0.3.0" lodash "^4.17.4" minimatch "^3.0.2" @@ -287,20 +277,21 @@ eslint@^4.5.0: natural-compare "^1.4.0" optionator "^0.8.2" path-is-inside "^1.0.2" - pluralize "^4.0.0" + pluralize "^7.0.0" progress "^2.0.0" + regexpp "^1.0.1" require-uncached "^1.0.3" semver "^5.3.0" strip-ansi "^4.0.0" strip-json-comments "~2.0.1" - table "^4.0.1" + table "4.0.2" text-table "~0.2.0" -espree@^3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.0.tgz#98358625bdd055861ea27e2867ea729faf463d8d" +espree@^3.5.4: + version "3.5.4" + resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7" dependencies: - acorn "^5.1.1" + acorn "^5.5.0" acorn-jsx "^3.0.0" esprima@^4.0.0: @@ -320,7 +311,7 @@ esrecurse@^4.1.0: estraverse "^4.1.0" object-assign "^4.0.1" -estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: +estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1: version "4.2.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" @@ -340,6 +331,10 @@ fast-deep-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" +fast-json-stable-stringify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" + fast-levenshtein@~2.0.4: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" @@ -374,18 +369,7 @@ functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" -glob@7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.2" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.0.3, glob@^7.0.5, glob@^7.1.2: +glob@7.1.2, glob@^7.0.3, glob@^7.0.5, glob@^7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" dependencies: @@ -396,9 +380,9 @@ glob@^7.0.3, glob@^7.0.5, glob@^7.1.2: once "^1.3.0" path-is-absolute "^1.0.0" -globals@^9.17.0: - version "9.18.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" +globals@^11.0.1: + version "11.5.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.5.0.tgz#6bc840de6771173b191f13d3a9c94d441ee92642" globby@^5.0.0: version "5.0.0" @@ -415,17 +399,9 @@ graceful-fs@^4.1.2: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" -"graceful-readlink@>= 1.0.0": - version "1.0.1" - resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" - -growl@1.9.2: - version "1.9.2" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" - -handle-thing@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-1.2.5.tgz#fd7aad726bf1a5fd16dfc29b2f7a6601d27139c4" +growl@1.10.3: + version "1.10.3" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.3.tgz#1926ba90cf3edfe2adb4927f5880bc22c66c790f" has-ansi@^2.0.0: version "2.0.0" @@ -433,30 +409,13 @@ has-ansi@^2.0.0: dependencies: ansi-regex "^2.0.0" -has-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" - has-flag@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" -hoek@2.x.x: - version "2.16.3" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" - -hpack.js@^2.1.6: - version "2.1.6" - resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" - dependencies: - inherits "^2.0.1" - obuf "^1.0.0" - readable-stream "^2.0.1" - wbuf "^1.1.0" - -http-deceiver@^1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" +he@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" iconv-lite@^0.4.17: version "0.4.18" @@ -477,7 +436,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3: +inherits@2, inherits@^2.0.3, inherits@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" @@ -530,27 +489,14 @@ is-resolvable@^1.0.0: dependencies: tryit "^1.0.1" -isarray@^1.0.0, isarray@~1.0.0: +isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" -isemail@1.x.x: - version "1.2.0" - resolved "https://registry.yarnpkg.com/isemail/-/isemail-1.2.0.tgz#be03df8cc3e29de4d2c5df6501263f1fa4595e9a" - isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" -joi@^6.10.1: - version "6.10.1" - resolved "https://registry.yarnpkg.com/joi/-/joi-6.10.1.tgz#4d50c318079122000fe5f16af1ff8e1917b77e06" - dependencies: - hoek "2.x.x" - isemail "1.x.x" - moment "2.x.x" - topo "1.x.x" - js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" @@ -570,28 +516,23 @@ json-schema-traverse@^0.3.0: version "0.3.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" -json-stable-stringify@^1.0.1: +json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" - dependencies: - jsonify "~0.0.0" - -json3@3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" -jsonify@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" - -jsonwebtoken@^7.0.1: - version "7.4.3" - resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-7.4.3.tgz#77f5021de058b605a1783fa1283e99812e645638" +jsonwebtoken@8.2.1: + version "8.2.1" + resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.2.1.tgz#333ee39aa8f238f32fa41693e7a2fb7e42f82b31" dependencies: - joi "^6.10.1" jws "^3.1.4" + lodash.includes "^4.3.0" + lodash.isboolean "^3.0.3" + lodash.isinteger "^4.0.4" + lodash.isnumber "^3.0.3" + lodash.isplainobject "^4.0.6" + lodash.isstring "^4.0.1" lodash.once "^4.0.0" - ms "^2.0.0" + ms "^2.1.1" xtend "^4.0.1" jwa@^1.1.4: @@ -618,58 +559,39 @@ levn@^0.3.0, levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" -lodash._baseassign@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e" - dependencies: - lodash._basecopy "^3.0.0" - lodash.keys "^3.0.0" - -lodash._basecopy@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" +lodash.includes@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" -lodash._basecreate@^3.0.0: +lodash.isboolean@^3.0.3: version "3.0.3" - resolved "https://registry.yarnpkg.com/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz#1bc661614daa7fc311b7d03bf16806a0213cf821" - -lodash._getnative@^3.0.0: - version "3.9.1" - resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" + resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" -lodash._isiterateecall@^3.0.0: - version "3.0.9" - resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" +lodash.isinteger@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" -lodash.create@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/lodash.create/-/lodash.create-3.1.1.tgz#d7f2849f0dbda7e04682bb8cd72ab022461debe7" - dependencies: - lodash._baseassign "^3.0.0" - lodash._basecreate "^3.0.0" - lodash._isiterateecall "^3.0.0" - -lodash.isarguments@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" +lodash.isnumber@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc" -lodash.isarray@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" +lodash.isplainobject@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" -lodash.keys@^3.0.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" - dependencies: - lodash._getnative "^3.0.0" - lodash.isarguments "^3.0.0" - lodash.isarray "^3.0.0" +lodash.isstring@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" lodash.once@^4.0.0: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" -lodash@^4.0.0, lodash@^4.13.1, lodash@^4.17.4, lodash@^4.3.0: +lodash@4.17.10: + version "4.17.10" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7" + +lodash@^4.17.4, lodash@^4.3.0: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" @@ -684,11 +606,7 @@ mimic-fn@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18" -minimalistic-assert@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz#702be2dda6b37f4836bcb3f5db56641b64a1d3d3" - -minimatch@^3.0.2, minimatch@^3.0.4: +minimatch@3.0.4, minimatch@^3.0.2, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" dependencies: @@ -704,30 +622,30 @@ mkdirp@0.5.1, mkdirp@^0.5.1: dependencies: minimist "0.0.8" -mocha@^3.3.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.5.0.tgz#1328567d2717f997030f8006234bce9b8cd72465" +mocha@5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.1.1.tgz#b774c75609dac05eb48f4d9ba1d827b97fde8a7b" dependencies: - browser-stdout "1.3.0" - commander "2.9.0" - debug "2.6.8" - diff "3.2.0" + browser-stdout "1.3.1" + commander "2.11.0" + debug "3.1.0" + diff "3.5.0" escape-string-regexp "1.0.5" - glob "7.1.1" - growl "1.9.2" - json3 "3.3.2" - lodash.create "3.1.1" + glob "7.1.2" + growl "1.10.3" + he "1.1.1" + minimatch "3.0.4" mkdirp "0.5.1" - supports-color "3.1.2" + supports-color "4.4.0" -moment@2.x.x: - version "2.18.1" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.18.1.tgz#c36193dd3ce1c2eed2adb7c802dbbc77a81b1c0f" - -ms@2.0.0, ms@^2.0.0: +ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" +ms@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + mute-stream@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" @@ -740,10 +658,6 @@ object-assign@^4.0.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" -obuf@^1.0.0, obuf@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.1.tgz#104124b6c602c6796881a042541d36db43a5264e" - once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -793,9 +707,9 @@ pinkie@^2.0.0: version "2.0.4" resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" -pluralize@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-4.0.0.tgz#59b708c1c0190a2f692f1c7618c446b052fd1762" +pluralize@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" prelude-ls@~1.1.2: version "1.1.2" @@ -813,7 +727,7 @@ pseudomap@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" -readable-stream@^2.0.1, readable-stream@^2.2.2, readable-stream@^2.2.9: +readable-stream@^2.2.2: version "2.3.3" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" dependencies: @@ -825,6 +739,10 @@ readable-stream@^2.0.1, readable-stream@^2.2.2, readable-stream@^2.2.9: string_decoder "~1.0.3" util-deprecate "~1.0.1" +regexpp@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-1.1.0.tgz#0e3516dd0b7904f413d2d4193dce4618c3a689ab" + require-uncached@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" @@ -869,10 +787,6 @@ safe-buffer@^5.0.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" -select-hose@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" - semver@^5.3.0: version "5.4.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" @@ -915,9 +829,9 @@ should-util@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/should-util/-/should-util-1.0.0.tgz#c98cda374aa6b190df8ba87c9889c2b4db620063" -should@^12.0.0: - version "12.0.0" - resolved "https://registry.yarnpkg.com/should/-/should-12.0.0.tgz#846667cd241691a6509fff0820f44d39143ddcf7" +should@13.2.1: + version "13.2.1" + resolved "https://registry.yarnpkg.com/should/-/should-13.2.1.tgz#84e6ebfbb145c79e0ae42307b25b3f62dcaf574e" dependencies: should-equal "^2.0.0" should-format "^3.0.3" @@ -929,38 +843,17 @@ signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" -slice-ansi@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" - -spdy-transport@^2.0.18: - version "2.0.20" - resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-2.0.20.tgz#735e72054c486b2354fe89e702256004a39ace4d" - dependencies: - debug "^2.6.8" - detect-node "^2.0.3" - hpack.js "^2.1.6" - obuf "^1.1.1" - readable-stream "^2.2.9" - safe-buffer "^5.0.1" - wbuf "^1.7.2" - -spdy@^3.4.7: - version "3.4.7" - resolved "https://registry.yarnpkg.com/spdy/-/spdy-3.4.7.tgz#42ff41ece5cc0f99a3a6c28aabb73f5c3b03acbc" +slice-ansi@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d" dependencies: - debug "^2.6.8" - handle-thing "^1.2.5" - http-deceiver "^1.2.7" - safe-buffer "^5.0.1" - select-hose "^2.0.0" - spdy-transport "^2.0.18" + is-fullwidth-code-point "^2.0.0" sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" -string-width@^2.0.0, string-width@^2.1.0: +string-width@^2.1.0, string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" dependencies: @@ -989,11 +882,11 @@ strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" -supports-color@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5" +supports-color@4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.4.0.tgz#883f7ddabc165142b2a61427f3352ded195d1a3e" dependencies: - has-flag "^1.0.0" + has-flag "^2.0.0" supports-color@^2.0.0: version "2.0.0" @@ -1005,16 +898,20 @@ supports-color@^4.0.0: dependencies: has-flag "^2.0.0" -table@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/table/-/table-4.0.1.tgz#a8116c133fac2c61f4a420ab6cdf5c4d61f0e435" +table@4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/table/-/table-4.0.2.tgz#a33447375391e766ad34d3486e6e2aedc84d2e36" dependencies: - ajv "^4.7.0" - ajv-keywords "^1.0.0" - chalk "^1.1.1" - lodash "^4.0.0" - slice-ansi "0.0.4" - string-width "^2.0.0" + ajv "^5.2.3" + ajv-keywords "^2.1.0" + chalk "^2.1.0" + lodash "^4.17.4" + slice-ansi "1.0.0" + string-width "^2.1.1" + +tarn@1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/tarn/-/tarn-1.1.4.tgz#aeeb85964b1afa0bbf381359c1167df237c27b6a" text-table@~0.2.0: version "0.2.0" @@ -1030,12 +927,6 @@ tmp@^0.0.31: dependencies: os-tmpdir "~1.0.1" -topo@1.x.x: - version "1.1.0" - resolved "https://registry.yarnpkg.com/topo/-/topo-1.1.0.tgz#e9d751615d1bb87dc865db182fa1ca0a5ef536d5" - dependencies: - hoek "2.x.x" - tryit@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/tryit/-/tryit-1.0.3.tgz#393be730a9446fd1ead6da59a014308f36c289cb" @@ -1054,12 +945,6 @@ util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" -wbuf@^1.1.0, wbuf@^1.7.2: - version "1.7.2" - resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.2.tgz#d697b99f1f59512df2751be42769c1580b5801fe" - dependencies: - minimalistic-assert "^1.0.0" - which@^1.2.9: version "1.3.0" resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a"