From 754bfe3ca2d1eaa756a77b1f91d77317a76bd872 Mon Sep 17 00:00:00 2001 From: davidwells Date: Thu, 4 May 2017 16:03:18 -0700 Subject: [PATCH 01/57] add login command --- lib/plugins/Plugins.json | 1 + lib/plugins/login/login.js | 132 ++++++++++++++++++++++++++++++++ lib/plugins/login/login.test.js | 19 +++++ 3 files changed, 152 insertions(+) create mode 100644 lib/plugins/login/login.js create mode 100644 lib/plugins/login/login.test.js diff --git a/lib/plugins/Plugins.json b/lib/plugins/Plugins.json index af4fee885..6cdb2ce30 100644 --- a/lib/plugins/Plugins.json +++ b/lib/plugins/Plugins.json @@ -8,6 +8,7 @@ "./invoke/invoke.js", "./info/info.js", "./logs/logs.js", + "./login/login.js", "./metrics/metrics.js", "./remove/remove.js", "./rollback/index.js", diff --git a/lib/plugins/login/login.js b/lib/plugins/login/login.js new file mode 100644 index 000000000..89a8c2631 --- /dev/null +++ b/lib/plugins/login/login.js @@ -0,0 +1,132 @@ +'use strict'; + +const BbPromise = require('bluebird'); +const crypto = require('crypto'); +const readline = require('readline'); +const opn = require('opn'); +const fetch = require('node-fetch'); +const jwtDecode = require('jwt-decode'); +const chalk = require('chalk'); +const getFrameworkId = require('../../utils/getFrameworkId'); +const updateConfig = require('../../utils/config/update'); + +const config = { + AUTH0_CLIENT_ID: 'iiEYK0KB30gj94mjB8HP9lhhTgae0Rg3', + AUTH0_URL: 'https://serverlessinc.auth0.com', + AUTH0_CALLBACK_URL: 'https://serverless.com/welcome', +}; + +function base64url(url) { + return url.toString('base64') + .replace(/\+/g, '-') + .replace(/\//g, '_') + .replace(/=/g, ''); +} + +class Login { + constructor(serverless, options) { + this.serverless = serverless; + this.options = options; + + this.commands = { + login: { + usage: 'Login to your Serverless platform account', + lifecycleEvents: [ + 'login', + ], + }, + }; + + this.hooks = { + 'login:login': () => BbPromise.bind(this).then(this.login), + }; + } + openBrowser(url) { + let browser = process.env.BROWSER; + if (browser === 'none') { + return false; + } + if (process.platform === 'darwin' && browser === 'open') { + browser = undefined; + } + try { + const options = { app: browser }; + opn(url, options).catch(() => {}); + return true; + } catch (err) { + console.log('---------------------------'); // eslint-disable-line + console.log(`🙈 ${chalk.red("Unable to open browser automatically")}`); // eslint-disable-line + console.log(chalk.green("Please open your browser & open the URL below to login:")); // eslint-disable-line + console.log(chalk.yellow(url)); // eslint-disable-line + console.log('---------------------------'); // eslint-disable-line + return false; + } + } + login() { + this.serverless.cli.log('The Serverless login will open in your default browser...'); + + // Generate the verifier, and the corresponding challenge + const verifier = base64url(crypto.randomBytes(32)); + const verifierChallenge = base64url(crypto.createHash('sha256').update(verifier).digest()); + const frameworkId = getFrameworkId(); + // eslint-disable-next-line prefer-template + const authorizeUrl = + `${config.AUTH0_URL}/authorize?response_type=code&scope=openid%20email%20nickname&` + + `client_id=${config.AUTH0_CLIENT_ID}&redirect_uri=${config.AUTH0_CALLBACK_URL}` + + `&code_challenge=${verifierChallenge}&code_challenge_method=S256&state=${frameworkId}`; + + setTimeout(() => { + this.serverless.cli.log('Opening browser...'); + }, 300); + + setTimeout(() => { + // pop open default browser + this.openBrowser(authorizeUrl); + + // wait for token + const readlineInterface = readline.createInterface({ + input: process.stdin, + output: process.stdout, + }); + + readlineInterface.question('Please enter the authorization code here: ', (code) => { + const authorizationData = { + code, + code_verifier: verifier, + client_id: config.AUTH0_CLIENT_ID, + grant_type: 'authorization_code', + redirect_uri: config.AUTH0_CALLBACK_URL, + }; + // verify login + fetch(`${config.AUTH0_URL}/oauth/token`, { + method: 'POST', + body: JSON.stringify(authorizationData), + headers: { 'content-type': 'application/json' }, + }) + .then((response) => response.json()) + .then((platformResponse) => { + // console.log('data', platformResponse); + const decoded = jwtDecode(platformResponse.id_token); + this.serverless.cli.log('You are logged in'); + // alias for segment + + // update .serverlessrc + const rc = { + frameworkId, + userId: decoded.sub, + auth: platformResponse, + }; + + updateConfig(rc); + process.exit(0); + }) + .catch((e) => { + console.log(e); // eslint-disable-line + process.exit(0); + }); + }); + }, 2000); + } +} + +module.exports = Login; diff --git a/lib/plugins/login/login.test.js b/lib/plugins/login/login.test.js new file mode 100644 index 000000000..72c716fa4 --- /dev/null +++ b/lib/plugins/login/login.test.js @@ -0,0 +1,19 @@ +'use strict'; + +const expect = require('chai').expect; +const Login = require('./login'); +const Serverless = require('../../Serverless'); + +describe('Login', () => { + let login; + let serverless; + + beforeEach(() => { + serverless = new Serverless(); + login = new Login(serverless); + }); + + describe('#constructor()', () => { + it('should have commands', () => expect(login.commands).to.be.not.empty); + }); +}); From 7016d41ac59b9e2de461f96ca15e57008aa7b5c3 Mon Sep 17 00:00:00 2001 From: davidwells Date: Thu, 4 May 2017 16:03:49 -0700 Subject: [PATCH 02/57] add functional Util functions ported from Utils class --- lib/utils/config/getServerlessDir.js | 6 ++++ lib/utils/config/update.js | 10 ++++++ lib/utils/fs/fileExistsSync.js | 12 +++++++ lib/utils/fs/fileExistsSync.test.js | 19 +++++++++++ lib/utils/fs/fse.js | 7 +++++ lib/utils/fs/readFileSync.js | 22 +++++++++++++ lib/utils/fs/readFileSync.test.js | 43 +++++++++++++++++++++++++ lib/utils/fs/writeFileSync.js | 24 ++++++++++++++ lib/utils/fs/writeFileSync.test.js | 47 ++++++++++++++++++++++++++++ lib/utils/getFrameworkId.js | 27 ++++++++++++++++ 10 files changed, 217 insertions(+) create mode 100644 lib/utils/config/getServerlessDir.js create mode 100644 lib/utils/config/update.js create mode 100644 lib/utils/fs/fileExistsSync.js create mode 100644 lib/utils/fs/fileExistsSync.test.js create mode 100644 lib/utils/fs/fse.js create mode 100644 lib/utils/fs/readFileSync.js create mode 100644 lib/utils/fs/readFileSync.test.js create mode 100644 lib/utils/fs/writeFileSync.js create mode 100644 lib/utils/fs/writeFileSync.test.js create mode 100644 lib/utils/getFrameworkId.js diff --git a/lib/utils/config/getServerlessDir.js b/lib/utils/config/getServerlessDir.js new file mode 100644 index 000000000..a5d8cc461 --- /dev/null +++ b/lib/utils/config/getServerlessDir.js @@ -0,0 +1,6 @@ +const path = require('path'); +const os = require('os'); + +module.exports = function getServerlessDir() { + return path.join(os.homedir(), '.serverless'); +}; diff --git a/lib/utils/config/update.js b/lib/utils/config/update.js new file mode 100644 index 000000000..237d195a1 --- /dev/null +++ b/lib/utils/config/update.js @@ -0,0 +1,10 @@ +const path = require('path'); +const getServerlessDir = require('./getServerlessDir'); +const writeFileSync = require('../fs/writeFileSync'); + +function updateConfig(config) { + const configPath = path.join(getServerlessDir(), '.serverlessrc'); + return writeFileSync(configPath, JSON.stringify(config, null, 2)); +} + +module.exports = updateConfig; diff --git a/lib/utils/fs/fileExistsSync.js b/lib/utils/fs/fileExistsSync.js new file mode 100644 index 000000000..f0d6862a0 --- /dev/null +++ b/lib/utils/fs/fileExistsSync.js @@ -0,0 +1,12 @@ +const fse = require('./fse'); + +function fileExistsSync(filePath) { + try { + const stats = fse.lstatSync(filePath); + return stats.isFile(); + } catch (e) { + return false; + } +} + +module.exports = fileExistsSync; diff --git a/lib/utils/fs/fileExistsSync.test.js b/lib/utils/fs/fileExistsSync.test.js new file mode 100644 index 000000000..34ab7fefe --- /dev/null +++ b/lib/utils/fs/fileExistsSync.test.js @@ -0,0 +1,19 @@ +'use strict'; + +const path = require('path'); +const expect = require('chai').expect; +const fileExistsSync = require('./fileExistsSync'); + +describe('#fileExistsSync()', () => { + describe('When reading a file', () => { + it('should detect if a file exists', () => { + const file = fileExistsSync(__filename); + expect(file).to.equal(true); + }); + + it('should detect if a file doesn\'t exist', () => { + const noFile = fileExistsSync(path.join(__dirname, 'XYZ.json')); + expect(noFile).to.equal(false); + }); + }); +}); diff --git a/lib/utils/fs/fse.js b/lib/utils/fs/fse.js new file mode 100644 index 000000000..97ef536ce --- /dev/null +++ b/lib/utils/fs/fse.js @@ -0,0 +1,7 @@ +/** + * Promisified FSE + */ +const BbPromise = require('bluebird'); +const fse = BbPromise.promisifyAll(require('fs-extra')); + +module.exports = fse; diff --git a/lib/utils/fs/readFileSync.js b/lib/utils/fs/readFileSync.js new file mode 100644 index 000000000..c286f998a --- /dev/null +++ b/lib/utils/fs/readFileSync.js @@ -0,0 +1,22 @@ +const YAML = require('js-yaml'); +const fse = require('./fse'); + +function readFileSync(filePath) { + let contents; + + // Read file + contents = fse.readFileSync(filePath); + + // Auto-parse JSON + if (filePath.endsWith('.json')) { + contents = JSON.parse(contents); + } else if (filePath.endsWith('.yml') || filePath.endsWith('.yaml')) { + contents = YAML.load(contents.toString(), { filename: filePath }); + } else { + contents = contents.toString().trim(); + } + + return contents; +} + +module.exports = readFileSync; diff --git a/lib/utils/fs/readFileSync.test.js b/lib/utils/fs/readFileSync.test.js new file mode 100644 index 000000000..6a0252bac --- /dev/null +++ b/lib/utils/fs/readFileSync.test.js @@ -0,0 +1,43 @@ +const testUtils = require('../../../tests/utils'); +const expect = require('chai').expect; +const writeFileSync = require('./writeFileSync'); +const readFileSync = require('./readFileSync'); + +describe('#readFileSync()', () => { + it('should read a file synchronously', () => { + const tmpFilePath = testUtils.getTmpFilePath('anything.json'); + + writeFileSync(tmpFilePath, { foo: 'bar' }); + const obj = readFileSync(tmpFilePath); + + expect(obj.foo).to.equal('bar'); + }); + + it('should read a filename extension .yml', () => { + const tmpFilePath = testUtils.getTmpFilePath('anything.yml'); + + writeFileSync(tmpFilePath, { foo: 'bar' }); + const obj = readFileSync(tmpFilePath); + + expect(obj.foo).to.equal('bar'); + }); + + it('should read a filename extension .yaml', () => { + const tmpFilePath = testUtils.getTmpFilePath('anything.yaml'); + + writeFileSync(tmpFilePath, { foo: 'bar' }); + const obj = readFileSync(tmpFilePath); + + expect(obj.foo).to.equal('bar'); + }); + + it('should throw YAMLException with filename if yml file is invalid format', () => { + const tmpFilePath = testUtils.getTmpFilePath('invalid.yml'); + + writeFileSync(tmpFilePath, ': a'); + + expect(() => { + readFileSync(tmpFilePath); + }).to.throw(new RegExp('YAMLException:.*invalid.yml')); + }); +}); diff --git a/lib/utils/fs/writeFileSync.js b/lib/utils/fs/writeFileSync.js new file mode 100644 index 000000000..f393a0516 --- /dev/null +++ b/lib/utils/fs/writeFileSync.js @@ -0,0 +1,24 @@ +const path = require('path'); +const YAML = require('js-yaml'); +const fse = require('./fse'); + +function writeFileSync(filePath, conts) { + let contents = conts || ''; + + fse.mkdirsSync(path.dirname(filePath)); + + if (filePath.indexOf('.json') !== -1 && typeof contents !== 'string') { + contents = JSON.stringify(contents, null, 2); + } + + const yamlFileExists = (filePath.indexOf('.yaml') !== -1); + const ymlFileExists = (filePath.indexOf('.yml') !== -1); + + if ((yamlFileExists || ymlFileExists) && typeof contents !== 'string') { + contents = YAML.dump(contents); + } + + return fse.writeFileSync(filePath, contents); +} + +module.exports = writeFileSync; diff --git a/lib/utils/fs/writeFileSync.test.js b/lib/utils/fs/writeFileSync.test.js new file mode 100644 index 000000000..cc33dbf61 --- /dev/null +++ b/lib/utils/fs/writeFileSync.test.js @@ -0,0 +1,47 @@ +const testUtils = require('../../../tests/utils'); +const Serverless = require('../../../lib/Serverless'); +const expect = require('chai').expect; +const writeFileSync = require('./writeFileSync'); +const readFileSync = require('./readFileSync'); + +describe('#writeFileSync()', () => { + let serverless; + + beforeEach(() => { + serverless = new Serverless(); + serverless.init(); + }); + + it('should write a .json file synchronously', () => { + const tmpFilePath = testUtils.getTmpFilePath('anything.json'); + + writeFileSync(tmpFilePath, { foo: 'bar' }); + const obj = readFileSync(tmpFilePath); + + expect(obj.foo).to.equal('bar'); + }); + + it('should write a .yml file synchronously', () => { + const tmpFilePath = testUtils.getTmpFilePath('anything.yml'); + + writeFileSync(tmpFilePath, { foo: 'bar' }); + + return serverless.yamlParser.parse(tmpFilePath).then((obj) => { + expect(obj.foo).to.equal('bar'); + }); + }); + + it('should write a .yaml file synchronously', () => { + const tmpFilePath = testUtils.getTmpFilePath('anything.yaml'); + + writeFileSync(tmpFilePath, { foo: 'bar' }); + + return serverless.yamlParser.parse(tmpFilePath).then((obj) => { + expect(obj.foo).to.equal('bar'); + }); + }); + + it('should throw error if invalid path is provided', () => { + expect(() => { writeFileSync(null); }).to.throw(Error); + }); +}); diff --git a/lib/utils/getFrameworkId.js b/lib/utils/getFrameworkId.js new file mode 100644 index 000000000..90fbde0be --- /dev/null +++ b/lib/utils/getFrameworkId.js @@ -0,0 +1,27 @@ +const path = require('path'); +const getServerlessDir = require('./config/getServerlessDir'); +const readFileSync = require('./fs/readFileSync'); +const fileExistsSync = require('./fs/fileExistsSync'); + +function getFrameworkId() { + const serverlessHomePath = getServerlessDir(); + const statsEnabledFilePath = path.join(serverlessHomePath, 'stats-enabled'); + const statsDisabledFilePath = path.join(serverlessHomePath, 'stats-disabled'); + const serverlessRCFilePath = path.join(serverlessHomePath, '.serverlessrc'); + + if (fileExistsSync(statsEnabledFilePath)) { + return readFileSync(statsEnabledFilePath).toString(); + } + if (fileExistsSync(statsDisabledFilePath)) { + return readFileSync(statsDisabledFilePath).toString(); + } + if (fileExistsSync(serverlessRCFilePath)) { + const config = JSON.parse(readFileSync(serverlessRCFilePath)); + if (config && config.frameworkId) { + return config.frameworkId; + } + } + return null; +} + +module.exports = getFrameworkId; From 51da948b908678f08e11a51b5ece3e0dd0fa803c Mon Sep 17 00:00:00 2001 From: davidwells Date: Thu, 4 May 2017 16:04:02 -0700 Subject: [PATCH 03/57] add login deps --- package.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/package.json b/package.json index 6fa119cd7..ceeca757a 100644 --- a/package.json +++ b/package.json @@ -98,10 +98,12 @@ "https-proxy-agent": "^1.0.0", "js-yaml": "^3.6.1", "json-refs": "^2.1.5", + "jwt-decode": "^2.2.0", "lodash": "^4.13.1", "minimist": "^1.2.0", "moment": "^2.13.0", "node-fetch": "^1.6.0", + "opn": "^5.0.0", "replaceall": "^0.1.6", "resolve-from": "^2.0.0", "semver": "^5.0.3", From dc4f389b3c145927a7c8b385e8dfdcc19ca00c43 Mon Sep 17 00:00:00 2001 From: davidwells Date: Thu, 4 May 2017 16:32:17 -0700 Subject: [PATCH 04/57] use strict --- lib/utils/config/getServerlessDir.js | 2 ++ lib/utils/config/update.js | 2 ++ lib/utils/fs/fileExistsSync.js | 2 ++ lib/utils/fs/fse.js | 2 ++ lib/utils/fs/readFileSync.js | 2 ++ lib/utils/fs/readFileSync.test.js | 2 ++ lib/utils/fs/writeFileSync.js | 2 ++ lib/utils/fs/writeFileSync.test.js | 2 ++ lib/utils/getFrameworkId.js | 2 ++ 9 files changed, 18 insertions(+) diff --git a/lib/utils/config/getServerlessDir.js b/lib/utils/config/getServerlessDir.js index a5d8cc461..792acab7f 100644 --- a/lib/utils/config/getServerlessDir.js +++ b/lib/utils/config/getServerlessDir.js @@ -1,3 +1,5 @@ +'use strict'; + const path = require('path'); const os = require('os'); diff --git a/lib/utils/config/update.js b/lib/utils/config/update.js index 237d195a1..d97c43cf4 100644 --- a/lib/utils/config/update.js +++ b/lib/utils/config/update.js @@ -1,3 +1,5 @@ +'use strict'; + const path = require('path'); const getServerlessDir = require('./getServerlessDir'); const writeFileSync = require('../fs/writeFileSync'); diff --git a/lib/utils/fs/fileExistsSync.js b/lib/utils/fs/fileExistsSync.js index f0d6862a0..147300e7b 100644 --- a/lib/utils/fs/fileExistsSync.js +++ b/lib/utils/fs/fileExistsSync.js @@ -1,3 +1,5 @@ +'use strict'; + const fse = require('./fse'); function fileExistsSync(filePath) { diff --git a/lib/utils/fs/fse.js b/lib/utils/fs/fse.js index 97ef536ce..c1428e286 100644 --- a/lib/utils/fs/fse.js +++ b/lib/utils/fs/fse.js @@ -1,6 +1,8 @@ /** * Promisified FSE */ +'use strict'; + const BbPromise = require('bluebird'); const fse = BbPromise.promisifyAll(require('fs-extra')); diff --git a/lib/utils/fs/readFileSync.js b/lib/utils/fs/readFileSync.js index c286f998a..7d341b4c7 100644 --- a/lib/utils/fs/readFileSync.js +++ b/lib/utils/fs/readFileSync.js @@ -1,3 +1,5 @@ +'use strict'; + const YAML = require('js-yaml'); const fse = require('./fse'); diff --git a/lib/utils/fs/readFileSync.test.js b/lib/utils/fs/readFileSync.test.js index 6a0252bac..652432040 100644 --- a/lib/utils/fs/readFileSync.test.js +++ b/lib/utils/fs/readFileSync.test.js @@ -1,3 +1,5 @@ +'use strict'; + const testUtils = require('../../../tests/utils'); const expect = require('chai').expect; const writeFileSync = require('./writeFileSync'); diff --git a/lib/utils/fs/writeFileSync.js b/lib/utils/fs/writeFileSync.js index f393a0516..e9fefae59 100644 --- a/lib/utils/fs/writeFileSync.js +++ b/lib/utils/fs/writeFileSync.js @@ -1,3 +1,5 @@ +'use strict'; + const path = require('path'); const YAML = require('js-yaml'); const fse = require('./fse'); diff --git a/lib/utils/fs/writeFileSync.test.js b/lib/utils/fs/writeFileSync.test.js index cc33dbf61..5a685e263 100644 --- a/lib/utils/fs/writeFileSync.test.js +++ b/lib/utils/fs/writeFileSync.test.js @@ -1,3 +1,5 @@ +'use strict'; + const testUtils = require('../../../tests/utils'); const Serverless = require('../../../lib/Serverless'); const expect = require('chai').expect; diff --git a/lib/utils/getFrameworkId.js b/lib/utils/getFrameworkId.js index 90fbde0be..c9f034023 100644 --- a/lib/utils/getFrameworkId.js +++ b/lib/utils/getFrameworkId.js @@ -1,3 +1,5 @@ +'use strict'; + const path = require('path'); const getServerlessDir = require('./config/getServerlessDir'); const readFileSync = require('./fs/readFileSync'); From 24606e1cfa7db92e318c225fb439c6424a841ad9 Mon Sep 17 00:00:00 2001 From: davidwells Date: Fri, 5 May 2017 09:15:16 -0700 Subject: [PATCH 05/57] add docs --- docs/providers/aws/cli-reference/login.md | 24 +++++++++++++++++++ docs/providers/azure/cli-reference/login.md | 24 +++++++++++++++++++ .../openwhisk/cli-reference/login.md | 24 +++++++++++++++++++ 3 files changed, 72 insertions(+) create mode 100644 docs/providers/aws/cli-reference/login.md create mode 100644 docs/providers/azure/cli-reference/login.md create mode 100644 docs/providers/openwhisk/cli-reference/login.md diff --git a/docs/providers/aws/cli-reference/login.md b/docs/providers/aws/cli-reference/login.md new file mode 100644 index 000000000..40708a2b4 --- /dev/null +++ b/docs/providers/aws/cli-reference/login.md @@ -0,0 +1,24 @@ + + + +### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/aws/cli-reference/login) + + +# Login + +The `login` command logs users into the serverless platform. + +It will create a new serverless platform account if one doesn't already exist. + +```bash +serverless login + +# Shorthand +sls login +``` diff --git a/docs/providers/azure/cli-reference/login.md b/docs/providers/azure/cli-reference/login.md new file mode 100644 index 000000000..606f7c7db --- /dev/null +++ b/docs/providers/azure/cli-reference/login.md @@ -0,0 +1,24 @@ + + + +### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/azure/cli-reference/login) + + +# Login + +The `login` command logs users into the serverless platform. + +It will create a new serverless platform account if one doesn't already exist. + +```bash +serverless login + +# Shorthand +sls login +``` diff --git a/docs/providers/openwhisk/cli-reference/login.md b/docs/providers/openwhisk/cli-reference/login.md new file mode 100644 index 000000000..ca594cb44 --- /dev/null +++ b/docs/providers/openwhisk/cli-reference/login.md @@ -0,0 +1,24 @@ + + + +### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/openwhisk/cli-reference/login) + + +# Login + +The `login` command logs users into the serverless platform. + +It will create a new serverless platform account if one doesn't already exist. + +```bash +serverless login + +# Shorthand +sls login +``` From e93e976a806d19b06ef11288fcdd464854cfa3f7 Mon Sep 17 00:00:00 2001 From: davidwells Date: Fri, 5 May 2017 12:35:40 -0700 Subject: [PATCH 06/57] update Utils class with util functions --- lib/classes/Utils.js | 51 +++++++++++--------------------------------- 1 file changed, 13 insertions(+), 38 deletions(-) diff --git a/lib/classes/Utils.js b/lib/classes/Utils.js index 6790e6460..52cb4cd76 100644 --- a/lib/classes/Utils.js +++ b/lib/classes/Utils.js @@ -10,6 +10,9 @@ const _ = require('lodash'); const fetch = require('node-fetch'); const uuid = require('uuid'); const os = require('os'); +const fileExistsSync = require('../utils/fs/fileExistsSync'); +const writeFileSync = require('../utils/fs/writeFileSync'); +const readFileSync = require('../utils/fs/readFileSync'); const version = require('../../package.json').version; class Utils { @@ -31,35 +34,19 @@ class Utils { } fileExistsSync(filePath) { - try { - const stats = fse.lstatSync(filePath); - return stats.isFile(); - } catch (e) { - return false; - } + // console.log('this.serverless.utils.fileExistsSync being depricated in a future release') + // console.log('Please explicitly declare your plugin dependancies') + return fileExistsSync(filePath); } writeFileDir(filePath) { return fse.mkdirsSync(path.dirname(filePath)); } - writeFileSync(filePath, conts) { - let contents = conts || ''; - - fse.mkdirsSync(path.dirname(filePath)); - - if (filePath.indexOf('.json') !== -1 && typeof contents !== 'string') { - contents = JSON.stringify(contents, null, 2); - } - - const yamlFileExists = (filePath.indexOf('.yaml') !== -1); - const ymlFileExists = (filePath.indexOf('.yml') !== -1); - - if ((yamlFileExists || ymlFileExists) && typeof contents !== 'string') { - contents = YAML.dump(contents); - } - - return fse.writeFileSync(filePath, contents); + writeFileSync(filePath, contents) { + // console.log('this.serverless.utils.writeFileSync being depricated in a future release') + // console.log('Please explicitly declare your plugin dependancies') + return writeFileSync(filePath, contents); } writeFile(filePath, contents) { @@ -88,21 +75,9 @@ class Utils { } readFileSync(filePath) { - let contents; - - // Read file - contents = fse.readFileSync(filePath); - - // Auto-parse JSON - if (filePath.endsWith('.json')) { - contents = JSON.parse(contents); - } else if (filePath.endsWith('.yml') || filePath.endsWith('.yaml')) { - contents = YAML.load(contents.toString(), { filename: filePath }); - } else { - contents = contents.toString().trim(); - } - - return contents; + // console.log('this.serverless.utils.writeFileSync being depricated in a future release') + // console.log('Please explicitly declare your plugin dependancies') + return readFileSync(filePath); } readFile(filePath) { From 40dee9bba05e161de160f04b50482d24e33b34f4 Mon Sep 17 00:00:00 2001 From: davidwells Date: Wed, 10 May 2017 18:17:01 -0700 Subject: [PATCH 07/57] add logout command --- lib/plugins/Plugins.json | 1 + lib/plugins/logout/logout.js | 55 +++++++++++++++++++++++++++++++ lib/plugins/logout/logout.test.js | 19 +++++++++++ 3 files changed, 75 insertions(+) create mode 100644 lib/plugins/logout/logout.js create mode 100644 lib/plugins/logout/logout.test.js diff --git a/lib/plugins/Plugins.json b/lib/plugins/Plugins.json index 6cdb2ce30..48b655570 100644 --- a/lib/plugins/Plugins.json +++ b/lib/plugins/Plugins.json @@ -9,6 +9,7 @@ "./info/info.js", "./logs/logs.js", "./login/login.js", + "./logout/logout.js", "./metrics/metrics.js", "./remove/remove.js", "./rollback/index.js", diff --git a/lib/plugins/logout/logout.js b/lib/plugins/logout/logout.js new file mode 100644 index 000000000..466031414 --- /dev/null +++ b/lib/plugins/logout/logout.js @@ -0,0 +1,55 @@ +'use strict'; + +const getFrameworkId = require('../../utils/getFrameworkId'); +const segment = require('../../utils/segment') +const config = require('../../utils/config'); + +class Login { + constructor(serverless, options) { + this.serverless = serverless; + this.options = options; + + this.commands = { + logout: { + usage: 'Logout from the Serverless Platform', + lifecycleEvents: ['logout'] + }, + }; + + this.hooks = { + 'logout:logout': this.logout.bind(this), + }; + } + logout() { + const configuration = config.getAll() + + if (configuration && !configuration.auth) { + console.log('You are already logged out.') + return + } + const logout = () => { + try { + // TODO Once we start using refresh tokens we also need to implement an API endpoint + // that invalidate a refresh token in Auth0 (using the Auth0 Management API). + // This endpoint should be called when the user runs `serverless logout` in the CLI. + config.set('auth', null); + console.log('Successfully logged out.') + // Note no need to wait for any connections e.g. segment to close + process.exit(0); + } catch (e) { + console.log('Failed to logout. Please manually remove this file: '); + // Note no need to wait for any connections e.g. segment to close + process.exit(0); + } + } + logout() + // track('logout').then(() => { + // logout() + // }) + // .catch(() => { + // logout() + // }) + } +} + +module.exports = Login; diff --git a/lib/plugins/logout/logout.test.js b/lib/plugins/logout/logout.test.js new file mode 100644 index 000000000..a1d93defc --- /dev/null +++ b/lib/plugins/logout/logout.test.js @@ -0,0 +1,19 @@ +'use strict'; + +const expect = require('chai').expect; +const Logout = require('./logout'); +const Serverless = require('../../Serverless'); + +describe('Logout', () => { + let logout; + let serverless; + + beforeEach(() => { + serverless = new Serverless(); + logout = new Logout(serverless); + }); + + describe('#constructor()', () => { + it('should have commands', () => expect(login.commands).to.be.not.empty); + }); +}); From 82fd943a942a2d611320066cd42dff51e1fcb1f7 Mon Sep 17 00:00:00 2001 From: davidwells Date: Fri, 12 May 2017 17:05:12 -0700 Subject: [PATCH 08/57] update config util --- lib/utils/config/index.js | 72 ++++++++++++++++++++++ lib/utils/config/update.js | 12 ---- lib/utils/getFrameworkId.js | 2 +- lib/utils/{config => }/getServerlessDir.js | 9 +-- 4 files changed, 78 insertions(+), 17 deletions(-) create mode 100644 lib/utils/config/index.js delete mode 100644 lib/utils/config/update.js rename lib/utils/{config => }/getServerlessDir.js (52%) diff --git a/lib/utils/config/index.js b/lib/utils/config/index.js new file mode 100644 index 000000000..9991df5ed --- /dev/null +++ b/lib/utils/config/index.js @@ -0,0 +1,72 @@ +/** + * Config util + */ +const path = require('path'); +const os = require('os'); +const _ = require('lodash'); +const getFrameworkId = require('../getFrameworkId'); +const fileExistsSync = require('../fs/fileExistsSync'); +const writeFileSync = require('../fs/writeFileSync'); +const readFileSync = require('../fs/readFileSync'); + +const globalConfigPath = path.join(os.homedir(), '.serverlessrc'); + +function createConfig() { + // set default config options + const config = { + frameworkId: getFrameworkId(), + }; + // https://github.com/npm/write-file-atomic + writeFileSync(globalConfigPath, JSON.stringify(config, null, 2)); + return JSON.parse(readFileSync(globalConfigPath)); +} + +function getGlobalConfig() { + if (!fileExistsSync(globalConfigPath)) { + return createConfig(); + } + const config = readFileSync(globalConfigPath); + // if global config empty add defaults + if (!config) { + return createConfig(); + } + return JSON.parse(config); +} + +// get .serverlessrc config + local config if exists +function getConfig() { + if (!fileExistsSync(globalConfigPath)) { + return createConfig(); + } + return require('rc')('serverless'); // eslint-disable-line +} + +// set global .serverlessrc config value +function setConfigValue(key, value) { + let config = getGlobalConfig(); + if (key && typeof key === 'string' && typeof value !== 'undefined') { + config = _.set(config, key, value); + } else if (_.isObject(key)) { + config = _.merge(config, key); + } else if (typeof value !== 'undefined') { + config = _.merge(config, value); + } + // write file + writeFileSync(globalConfigPath, JSON.stringify(config, null, 2)); + return config; +} + +// set .serverlessrc config value +function getConfigValue(objectPath) { + const config = getConfig(); + if (objectPath && typeof objectPath === 'string') { + return _.get(config, objectPath); + } + return config; +} + +module.exports = { + set: setConfigValue, + get: getConfigValue, + getConfig, +}; diff --git a/lib/utils/config/update.js b/lib/utils/config/update.js deleted file mode 100644 index d97c43cf4..000000000 --- a/lib/utils/config/update.js +++ /dev/null @@ -1,12 +0,0 @@ -'use strict'; - -const path = require('path'); -const getServerlessDir = require('./getServerlessDir'); -const writeFileSync = require('../fs/writeFileSync'); - -function updateConfig(config) { - const configPath = path.join(getServerlessDir(), '.serverlessrc'); - return writeFileSync(configPath, JSON.stringify(config, null, 2)); -} - -module.exports = updateConfig; diff --git a/lib/utils/getFrameworkId.js b/lib/utils/getFrameworkId.js index c9f034023..db940400d 100644 --- a/lib/utils/getFrameworkId.js +++ b/lib/utils/getFrameworkId.js @@ -1,7 +1,7 @@ 'use strict'; const path = require('path'); -const getServerlessDir = require('./config/getServerlessDir'); +const getServerlessDir = require('./getServerlessDir'); const readFileSync = require('./fs/readFileSync'); const fileExistsSync = require('./fs/fileExistsSync'); diff --git a/lib/utils/config/getServerlessDir.js b/lib/utils/getServerlessDir.js similarity index 52% rename from lib/utils/config/getServerlessDir.js rename to lib/utils/getServerlessDir.js index 792acab7f..af1bae3fd 100644 --- a/lib/utils/config/getServerlessDir.js +++ b/lib/utils/getServerlessDir.js @@ -1,8 +1,9 @@ -'use strict'; - const path = require('path'); const os = require('os'); -module.exports = function getServerlessDir() { +// get .serverless home path +function getServerlessDir() { return path.join(os.homedir(), '.serverless'); -}; +} + +module.exports = getServerlessDir; From c7db6664215306a4ab829e4b6eb9eacd071ed897 Mon Sep 17 00:00:00 2001 From: davidwells Date: Fri, 12 May 2017 17:06:24 -0700 Subject: [PATCH 09/57] update login cmd --- lib/plugins/login/login.js | 35 ++++++++++++++++++++++++++--------- lib/utils/segment.js | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 9 deletions(-) create mode 100644 lib/utils/segment.js diff --git a/lib/plugins/login/login.js b/lib/plugins/login/login.js index 89a8c2631..8f12f894c 100644 --- a/lib/plugins/login/login.js +++ b/lib/plugins/login/login.js @@ -8,7 +8,8 @@ const fetch = require('node-fetch'); const jwtDecode = require('jwt-decode'); const chalk = require('chalk'); const getFrameworkId = require('../../utils/getFrameworkId'); -const updateConfig = require('../../utils/config/update'); +const segment = require('../../utils/segment') +const setConfig = require('../../utils/config').set; const config = { AUTH0_CLIENT_ID: 'iiEYK0KB30gj94mjB8HP9lhhTgae0Rg3', @@ -30,7 +31,7 @@ class Login { this.commands = { login: { - usage: 'Login to your Serverless platform account', + usage: 'Login or sign up for the Serverless Platform', lifecycleEvents: [ 'login', ], @@ -70,10 +71,12 @@ class Login { const verifierChallenge = base64url(crypto.createHash('sha256').update(verifier).digest()); const frameworkId = getFrameworkId(); // eslint-disable-next-line prefer-template + const state = `id%3D${frameworkId}`; + // refresh token docs https://auth0.com/docs/tokens/preview/refresh-token#get-a-refresh-token const authorizeUrl = - `${config.AUTH0_URL}/authorize?response_type=code&scope=openid%20email%20nickname&` + + `${config.AUTH0_URL}/authorize?response_type=code&scope=openid%20email%20nickname%20offline_access&` + `client_id=${config.AUTH0_CLIENT_ID}&redirect_uri=${config.AUTH0_CALLBACK_URL}` + - `&code_challenge=${verifierChallenge}&code_challenge_method=S256&state=${frameworkId}`; + `&code_challenge=${verifierChallenge}&code_challenge_method=S256&state=${state}`; setTimeout(() => { this.serverless.cli.log('Opening browser...'); @@ -88,7 +91,7 @@ class Login { input: process.stdin, output: process.stdout, }); - + // o get an access token and a refresh token from that code you need to call the oauth/token endpoint. Here's more info - https://auth0.com/docs/protocols#3-getting-the-access-token readlineInterface.question('Please enter the authorization code here: ', (code) => { const authorizationData = { code, @@ -107,17 +110,31 @@ class Login { .then((platformResponse) => { // console.log('data', platformResponse); const decoded = jwtDecode(platformResponse.id_token); + // console.log(decoded) this.serverless.cli.log('You are logged in'); // alias for segment - + // segment.alias({ + // previousId: frameworkId, + // userId: decoded.sub, + // }); + /* analytics.identify({ + userId: decoded.sub, + traits: { + email: profile.email, + }, + }) */ // update .serverlessrc - const rc = { + const userConfig = { + userId: decoded.sub, frameworkId, + users: {}, + }; + // set user auth + userConfig.users[decoded.sub] = { userId: decoded.sub, auth: platformResponse, }; - - updateConfig(rc); + setConfig(userConfig); process.exit(0); }) .catch((e) => { diff --git a/lib/utils/segment.js b/lib/utils/segment.js new file mode 100644 index 000000000..bf071f49f --- /dev/null +++ b/lib/utils/segment.js @@ -0,0 +1,33 @@ +const BbPromise = require('bluebird'); +const fetch = require('node-fetch'); +// TODO: Replace me before release +const writeKey = 'XXXX'; +const auth = `${writeKey}:`; + +function request(url, payload) { + return fetch('https://api.segment.io/v1/track', { + headers: { + Authorization: `Basic ${new Buffer(auth).toString('base64')}`, + 'content-type': 'application/json', + }, + method: 'POST', + timeout: '1000', + body: JSON.stringify(payload), + }) + .then((response) => response.json()) + .then(() => BbPromise.resolve()) + .catch(() => BbPromise.resolve()); +} + +function track(payload) { + return request('https://api.segment.io/v1/track', payload); +} + +function alias(payload) { + return request('https://api.segment.io/v1/alias', payload); +} + +module.exports = { + track, + alias, +}; From 4bef14d42f77d1e44e3ee8c7b3828cfb7cf1c410 Mon Sep 17 00:00:00 2001 From: davidwells Date: Fri, 12 May 2017 17:11:11 -0700 Subject: [PATCH 10/57] update linting --- lib/plugins/login/login.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/plugins/login/login.js b/lib/plugins/login/login.js index 8f12f894c..bc4435911 100644 --- a/lib/plugins/login/login.js +++ b/lib/plugins/login/login.js @@ -8,7 +8,7 @@ const fetch = require('node-fetch'); const jwtDecode = require('jwt-decode'); const chalk = require('chalk'); const getFrameworkId = require('../../utils/getFrameworkId'); -const segment = require('../../utils/segment') +const segment = require('../../utils/segment'); const setConfig = require('../../utils/config').set; const config = { @@ -112,12 +112,12 @@ class Login { const decoded = jwtDecode(platformResponse.id_token); // console.log(decoded) this.serverless.cli.log('You are logged in'); - // alias for segment + // alias for segment only works with mixpanel // segment.alias({ // previousId: frameworkId, // userId: decoded.sub, // }); - /* analytics.identify({ + /* segment.identify({ userId: decoded.sub, traits: { email: profile.email, From b5c0a332297c041a24703544a024c30d9a2a8e21 Mon Sep 17 00:00:00 2001 From: davidwells Date: Mon, 15 May 2017 18:31:30 -0700 Subject: [PATCH 11/57] add tests --- lib/plugins/login/login.js | 1 + lib/utils/config/config.test.js | 39 +++++++++++++++++++++++++++++++++ lib/utils/config/index.js | 24 ++++++++++++++++---- 3 files changed, 60 insertions(+), 4 deletions(-) create mode 100644 lib/utils/config/config.test.js diff --git a/lib/plugins/login/login.js b/lib/plugins/login/login.js index bc4435911..fd7102409 100644 --- a/lib/plugins/login/login.js +++ b/lib/plugins/login/login.js @@ -10,6 +10,7 @@ const chalk = require('chalk'); const getFrameworkId = require('../../utils/getFrameworkId'); const segment = require('../../utils/segment'); const setConfig = require('../../utils/config').set; +// const getConfig = require('../../utils/config').getConfig; const config = { AUTH0_CLIENT_ID: 'iiEYK0KB30gj94mjB8HP9lhhTgae0Rg3', diff --git a/lib/utils/config/config.test.js b/lib/utils/config/config.test.js new file mode 100644 index 000000000..ad28c8bcd --- /dev/null +++ b/lib/utils/config/config.test.js @@ -0,0 +1,39 @@ +'use strict'; + +const expect = require('chai').expect; +const config = require('./index'); + +describe.only('Config', () => { + describe('When reading config', () => { + it('should have slsConfigFilePath', () => { + const configPath = config.slsConfigFilePath; + expect(configPath).to.exist; // eslint-disable-line + }); + + it('should have frameworkId', () => { + const conf = config.getConfig(); + expect(conf).to.have.deep.property('frameworkId'); + }); + + // for future use + // it('should have slsStats', () => { + // const conf = config.getConfig(); + // expect(conf).to.have.deep.property('slsStats'); + // }); + }); + + describe('When writing config', () => { + it('should add new properties with "set"', () => { + config.set('foo', true); + const foo = config.get('foo'); + expect(foo).to.equal(true); + }); + + it('should delete properties with "delete"', () => { + // cleanup foo + config.delete('foo'); + const zaz = config.get('foo'); + expect(zaz).to.equal(undefined); + }); + }); +}); diff --git a/lib/utils/config/index.js b/lib/utils/config/index.js index 9991df5ed..7d243a1a5 100644 --- a/lib/utils/config/index.js +++ b/lib/utils/config/index.js @@ -4,9 +4,9 @@ const path = require('path'); const os = require('os'); const _ = require('lodash'); +const writeFileAtomic = require('write-file-atomic'); const getFrameworkId = require('../getFrameworkId'); const fileExistsSync = require('../fs/fileExistsSync'); -const writeFileSync = require('../fs/writeFileSync'); const readFileSync = require('../fs/readFileSync'); const globalConfigPath = path.join(os.homedir(), '.serverlessrc'); @@ -16,8 +16,7 @@ function createConfig() { const config = { frameworkId: getFrameworkId(), }; - // https://github.com/npm/write-file-atomic - writeFileSync(globalConfigPath, JSON.stringify(config, null, 2)); + writeFileAtomic.sync(globalConfigPath, JSON.stringify(config, null, 2)); return JSON.parse(readFileSync(globalConfigPath)); } @@ -52,10 +51,25 @@ function setConfigValue(key, value) { config = _.merge(config, value); } // write file - writeFileSync(globalConfigPath, JSON.stringify(config, null, 2)); + writeFileAtomic.sync(globalConfigPath, JSON.stringify(config, null, 2)); return config; } +function deleteConfigValue(key) { + let config = getGlobalConfig(); + if (key && typeof key === 'string') { + config = _.omit(config, [key]); + } else if (key && _.isArray(key)) { + config = _.omit(config, key); + } + // write file + writeFileAtomic.sync(globalConfigPath, JSON.stringify(config, null, 2)); + return config; +} + +// set local config value + + // set .serverlessrc config value function getConfigValue(objectPath) { const config = getConfig(); @@ -68,5 +82,7 @@ function getConfigValue(objectPath) { module.exports = { set: setConfigValue, get: getConfigValue, + delete: deleteConfigValue, getConfig, + slsConfigFilePath: globalConfigPath, }; From a80c8742d50037cc5356ee04c14aadc4a601d4ef Mon Sep 17 00:00:00 2001 From: davidwells Date: Tue, 16 May 2017 08:44:09 -0700 Subject: [PATCH 12/57] add clear console --- lib/utils/clearConsole.js | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 lib/utils/clearConsole.js diff --git a/lib/utils/clearConsole.js b/lib/utils/clearConsole.js new file mode 100644 index 000000000..3b412c68f --- /dev/null +++ b/lib/utils/clearConsole.js @@ -0,0 +1,7 @@ +/* Clear terminal output */ + +const clearConsole = function () { + process.stdout.write(process.platform !== 'win32' ? '\x1B[2J\x1B[3J\x1B[H' : '\x1Bc'); +}; + +module.exports = clearConsole; From c7d5373e585a2b0029c4fcfda7a0686b9480f965 Mon Sep 17 00:00:00 2001 From: davidwells Date: Tue, 16 May 2017 08:44:48 -0700 Subject: [PATCH 13/57] clear console on login --- lib/plugins/login/login.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/plugins/login/login.js b/lib/plugins/login/login.js index fd7102409..f867c6738 100644 --- a/lib/plugins/login/login.js +++ b/lib/plugins/login/login.js @@ -8,6 +8,7 @@ const fetch = require('node-fetch'); const jwtDecode = require('jwt-decode'); const chalk = require('chalk'); const getFrameworkId = require('../../utils/getFrameworkId'); +const clearConsole = require('../../utils/clearConsole'); const segment = require('../../utils/segment'); const setConfig = require('../../utils/config').set; // const getConfig = require('../../utils/config').getConfig; @@ -65,6 +66,7 @@ class Login { } } login() { + clearConsole(); this.serverless.cli.log('The Serverless login will open in your default browser...'); // Generate the verifier, and the corresponding challenge From 53933f89367ae6d8dc556742c934f7401ec04293 Mon Sep 17 00:00:00 2001 From: davidwells Date: Tue, 16 May 2017 13:00:26 -0700 Subject: [PATCH 14/57] add isDockerContainer util --- lib/utils/isDockerContainer.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 lib/utils/isDockerContainer.js diff --git a/lib/utils/isDockerContainer.js b/lib/utils/isDockerContainer.js new file mode 100644 index 000000000..cbbc992f1 --- /dev/null +++ b/lib/utils/isDockerContainer.js @@ -0,0 +1,18 @@ +const path = require('path'); +const readFileSync = require('./fs/readFileSync'); +const fileExistsSync = require('./fs/fileExistsSync'); + +/* Check if is inside docker container */ +module.exports = function isDockerContainer() { + // wrap in try catch to make sure that missing permissions won't break anything + try { + const cgroupFilePath = path.join('/', 'proc', '1', 'cgroup'); + if (fileExistsSync(cgroupFilePath)) { + const cgroupFileContent = readFileSync(cgroupFilePath).toString(); + return !!cgroupFileContent.match(/docker/); + } + } catch (exception) { + // do nothing + } + return false; +}; From c57cf03a09b8a300deddaf0bbad9acc058f0728a Mon Sep 17 00:00:00 2001 From: davidwells Date: Tue, 16 May 2017 13:00:55 -0700 Subject: [PATCH 15/57] clean up segment call --- lib/classes/Utils.js | 70 +++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 37 deletions(-) diff --git a/lib/classes/Utils.js b/lib/classes/Utils.js index 52cb4cd76..1bb601764 100644 --- a/lib/classes/Utils.js +++ b/lib/classes/Utils.js @@ -13,7 +13,9 @@ const os = require('os'); const fileExistsSync = require('../utils/fs/fileExistsSync'); const writeFileSync = require('../utils/fs/writeFileSync'); const readFileSync = require('../utils/fs/readFileSync'); +const isDockerContainer = require('../utils/isDockerContainer'); const version = require('../../package.json').version; +const configUtils = require('../utils/config'); class Utils { constructor(serverless) { @@ -139,6 +141,16 @@ class Utils { // the context in which serverless was executed (e.g. "install", "usage", "uninstall", ...) context = context || 'usage'; //eslint-disable-line + // Service values + const service = serverless.service; + const resources = service.resources; + const provider = service.provider; + const functions = service.functions; + + // CLI inputs + const options = serverless.processedInput.options; + const commands = serverless.processedInput.commands; + const log = (data) => { const writeKey = 'XXXX'; // TODO: Replace me before release const auth = `${writeKey}:`; @@ -165,7 +177,8 @@ class Utils { if (this.fileExistsSync(statsDisabledFilePath)) { return resolve(); } - + const config = configUtils.getConfig(); + console.log(config.slsStats); let userId = uuid.v1(); if (!this.fileExistsSync(statsEnabledFilePath)) { @@ -175,7 +188,6 @@ class Utils { } // filter out the whitelisted options - const options = serverless.processedInput.options; const whitelistedOptionKeys = ['help', 'disable', 'enable']; const optionKeys = Object.keys(options); @@ -189,11 +201,11 @@ class Utils { }); // function related information retrieval - const numberOfFunctions = _.size(serverless.service.functions); + const numberOfFunctions = _.size(functions); const memorySizeAndTimeoutPerFunction = []; if (numberOfFunctions) { - _.forEach(serverless.service.functions, (func) => { + _.forEach(functions, (func) => { const memorySize = Number(func.memorySize) || Number(this.serverless.service.provider.memorySize) || 1024; @@ -214,7 +226,7 @@ class Utils { const numberOfEventsPerType = []; const eventNamesPerFunction = []; if (numberOfFunctions) { - _.forEach(serverless.service.functions, (func) => { + _.forEach(functions, (func) => { if (func.events) { const funcEventsArray = []; @@ -239,18 +251,12 @@ class Utils { } let hasCustomResourcesDefined = false; - // check if configuration in resources.Resources is defined - if ((serverless.service.resources && - serverless.service.resources.Resources && - Object.keys(serverless.service.resources.Resources).length)) { + if ((resources && resources.Resources && Object.keys(resources.Resources).length)) { hasCustomResourcesDefined = true; } - // check if configuration in resources.Outputs is defined - if ((serverless.service.resources && - serverless.service.resources.Outputs && - Object.keys(serverless.service.resources.Outputs).length)) { + if ((resources && resources.Outputs && Object.keys(resources.Outputs).length)) { hasCustomResourcesDefined = true; } @@ -258,43 +264,32 @@ class Utils { const defaultVariableSyntax = '\\${([ :a-zA-Z0-9._,\\-\\/\\(\\)]+?)}'; // check if the variableSyntax in the provider section is defined - if (serverless.service.provider && - serverless.service.provider.variableSyntax && - serverless.service.provider.variableSyntax !== defaultVariableSyntax) { + if (provider && provider.variableSyntax + && provider.variableSyntax !== defaultVariableSyntax) { hasCustomVariableSyntaxDefined = true; } - // wrap in try catch to make sure that missing permissions won't break anything - let isDockerContainer = false; - try { - const cgroupFilePath = path.join('/', 'proc', '1', 'cgroup'); - const cgroupFileContent = fs.readFileSync(cgroupFilePath).toString(); - isDockerContainer = !!cgroupFileContent.match(/docker/); - } catch (exception) { - // do nothing - } - const data = { userId, event: 'framework_stat', properties: { version: 2, command: { - name: serverless.processedInput.commands.join(' '), + name: commands.join(' '), filteredOptions, isRunInService: (!!serverless.config.servicePath), }, service: { - numberOfCustomPlugins: _.size(serverless.service.plugins), + numberOfCustomPlugins: _.size(service.plugins), hasCustomResourcesDefined, - hasVariablesInCustomSectionDefined: (!!serverless.service.custom), + hasVariablesInCustomSectionDefined: (!!service.custom), hasCustomVariableSyntaxDefined, }, provider: { - name: serverless.service.provider.name, - runtime: serverless.service.provider.runtime, - stage: serverless.service.provider.stage, - region: serverless.service.provider.region, + name: provider.name, + runtime: provider.runtime, + stage: provider.stage, + region: provider.region, }, functions: { numberOfFunctions, @@ -314,9 +309,8 @@ class Utils { userAgent: (process.env.SERVERLESS_DASHBOARD) ? 'dashboard' : 'cli', serverlessVersion: serverless.version, nodeJsVersion: process.version, - isDockerContainer, - isCISystem: ci.isCI, - ciSystem: ci.name, + isDockerContainer: isDockerContainer(), + isCISystem: !!((process.env.CI || process.env.JENKINS_URL) || false), }, }, }; @@ -324,7 +318,9 @@ class Utils { return resolve(data); }).then((data) => { // only log the data if it's there - if (data) log(data); + if (data) { + log(data); + } }); } } From 8e0474ac3b5bfa0be2ff909640da5fef82bca8f5 Mon Sep 17 00:00:00 2001 From: davidwells Date: Tue, 16 May 2017 14:43:51 -0700 Subject: [PATCH 16/57] update message --- lib/plugins/login/login.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/plugins/login/login.js b/lib/plugins/login/login.js index f867c6738..6b01bccc1 100644 --- a/lib/plugins/login/login.js +++ b/lib/plugins/login/login.js @@ -95,7 +95,7 @@ class Login { output: process.stdout, }); // o get an access token and a refresh token from that code you need to call the oauth/token endpoint. Here's more info - https://auth0.com/docs/protocols#3-getting-the-access-token - readlineInterface.question('Please enter the authorization code here: ', (code) => { + readlineInterface.question('Please enter the verification code here: ', (code) => { const authorizationData = { code, code_verifier: verifier, @@ -111,9 +111,7 @@ class Login { }) .then((response) => response.json()) .then((platformResponse) => { - // console.log('data', platformResponse); const decoded = jwtDecode(platformResponse.id_token); - // console.log(decoded) this.serverless.cli.log('You are logged in'); // alias for segment only works with mixpanel // segment.alias({ From aa32df60ba8d591c40dbe6396776908379e87c9a Mon Sep 17 00:00:00 2001 From: davidwells Date: Tue, 16 May 2017 14:44:22 -0700 Subject: [PATCH 17/57] update config tests --- lib/utils/config/config.test.js | 37 +++++++++++++++++++++++---------- lib/utils/config/index.js | 17 ++++++++++++--- 2 files changed, 40 insertions(+), 14 deletions(-) diff --git a/lib/utils/config/config.test.js b/lib/utils/config/config.test.js index ad28c8bcd..51b59228f 100644 --- a/lib/utils/config/config.test.js +++ b/lib/utils/config/config.test.js @@ -4,25 +4,40 @@ const expect = require('chai').expect; const config = require('./index'); describe.only('Config', () => { - describe('When reading config', () => { - it('should have slsConfigFilePath', () => { - const configPath = config.slsConfigFilePath; - expect(configPath).to.exist; // eslint-disable-line - }); + it('should have CONFIG_FILE_PATH', () => { + const configPath = config.CONFIG_FILE_PATH; + expect(configPath).to.exist; // eslint-disable-line + }); + describe('When using config.getConfig', () => { it('should have frameworkId', () => { const conf = config.getConfig(); expect(conf).to.have.deep.property('frameworkId'); }); - // for future use - // it('should have slsStats', () => { - // const conf = config.getConfig(); - // expect(conf).to.have.deep.property('slsStats'); - // }); + it('should have settings', () => { + const conf = config.getConfig(); + expect(conf).to.have.deep.property('settings'); + }); + + it('should have settings.trackingDisabled', () => { + const conf = config.getConfig(); + expect(conf).to.have.deep.property('settings.trackingDisabled'); + }); }); - describe('When writing config', () => { + describe('When using config.get', () => { + it('should have frameworkId', () => { + const frameworkId = config.get('frameworkId'); + expect(frameworkId).to.exist; // eslint-disable-line + }); + it('should have not have a value that doesnt exist', () => { + const doesntExist = config.get('frameworkIdzzzz'); + expect(doesntExist).to.not.exist; // eslint-disable-line + }); + }); + + describe('When using config.set', () => { it('should add new properties with "set"', () => { config.set('foo', true); const foo = config.get('foo'); diff --git a/lib/utils/config/index.js b/lib/utils/config/index.js index 7d243a1a5..bba25a9ab 100644 --- a/lib/utils/config/index.js +++ b/lib/utils/config/index.js @@ -8,13 +8,24 @@ const writeFileAtomic = require('write-file-atomic'); const getFrameworkId = require('../getFrameworkId'); const fileExistsSync = require('../fs/fileExistsSync'); const readFileSync = require('../fs/readFileSync'); +const getServerlessDir = require('../getServerlessDir'); const globalConfigPath = path.join(os.homedir(), '.serverlessrc'); +function legacyIsTrackingDisabled() { + if (fileExistsSync(path.join(getServerlessDir(), 'stats-disabled'))) { + return true; + } + return false; +} + function createConfig() { // set default config options const config = { frameworkId: getFrameworkId(), + settings: { + trackingDisabled: legacyIsTrackingDisabled(), + }, }; writeFileAtomic.sync(globalConfigPath, JSON.stringify(config, null, 2)); return JSON.parse(readFileSync(globalConfigPath)); @@ -67,8 +78,8 @@ function deleteConfigValue(key) { return config; } -// set local config value - +// set local config value /project/.serverlessrc +// function setLocalConfig // set .serverlessrc config value function getConfigValue(objectPath) { @@ -84,5 +95,5 @@ module.exports = { get: getConfigValue, delete: deleteConfigValue, getConfig, - slsConfigFilePath: globalConfigPath, + CONFIG_FILE_PATH: globalConfigPath, }; From 8f0fd968f99e860f692ff3c1544b3803f6543eac Mon Sep 17 00:00:00 2001 From: davidwells Date: Tue, 16 May 2017 16:39:20 -0700 Subject: [PATCH 18/57] use strict --- lib/plugins/logout/logout.js | 16 ++++++++-------- lib/utils/clearConsole.js | 3 ++- lib/utils/config/config.test.js | 2 +- lib/utils/config/index.js | 6 +++--- lib/utils/getServerlessDir.js | 2 ++ lib/utils/isDockerContainer.js | 2 ++ 6 files changed, 18 insertions(+), 13 deletions(-) diff --git a/lib/plugins/logout/logout.js b/lib/plugins/logout/logout.js index 466031414..9dcea15a0 100644 --- a/lib/plugins/logout/logout.js +++ b/lib/plugins/logout/logout.js @@ -1,7 +1,7 @@ 'use strict'; const getFrameworkId = require('../../utils/getFrameworkId'); -const segment = require('../../utils/segment') +// const segment = require('../../utils/segment'); const config = require('../../utils/config'); class Login { @@ -12,7 +12,7 @@ class Login { this.commands = { logout: { usage: 'Logout from the Serverless Platform', - lifecycleEvents: ['logout'] + lifecycleEvents: ['logout'], }, }; @@ -21,11 +21,11 @@ class Login { }; } logout() { - const configuration = config.getAll() + const configuration = config.getAll(); if (configuration && !configuration.auth) { - console.log('You are already logged out.') - return + console.log('You are already logged out.'); + return; } const logout = () => { try { @@ -33,7 +33,7 @@ class Login { // that invalidate a refresh token in Auth0 (using the Auth0 Management API). // This endpoint should be called when the user runs `serverless logout` in the CLI. config.set('auth', null); - console.log('Successfully logged out.') + console.log('Successfully logged out.'); // Note no need to wait for any connections e.g. segment to close process.exit(0); } catch (e) { @@ -41,8 +41,8 @@ class Login { // Note no need to wait for any connections e.g. segment to close process.exit(0); } - } - logout() + }; + logout(); // track('logout').then(() => { // logout() // }) diff --git a/lib/utils/clearConsole.js b/lib/utils/clearConsole.js index 3b412c68f..aeb5b9f22 100644 --- a/lib/utils/clearConsole.js +++ b/lib/utils/clearConsole.js @@ -1,5 +1,6 @@ -/* Clear terminal output */ +'use strict'; +/* Clear terminal output */ const clearConsole = function () { process.stdout.write(process.platform !== 'win32' ? '\x1B[2J\x1B[3J\x1B[H' : '\x1Bc'); }; diff --git a/lib/utils/config/config.test.js b/lib/utils/config/config.test.js index 51b59228f..73ae55317 100644 --- a/lib/utils/config/config.test.js +++ b/lib/utils/config/config.test.js @@ -3,7 +3,7 @@ const expect = require('chai').expect; const config = require('./index'); -describe.only('Config', () => { +describe('Config', () => { it('should have CONFIG_FILE_PATH', () => { const configPath = config.CONFIG_FILE_PATH; expect(configPath).to.exist; // eslint-disable-line diff --git a/lib/utils/config/index.js b/lib/utils/config/index.js index bba25a9ab..b6eb8f931 100644 --- a/lib/utils/config/index.js +++ b/lib/utils/config/index.js @@ -1,6 +1,6 @@ -/** - * Config util - */ +'use strict'; + +/* Config util */ const path = require('path'); const os = require('os'); const _ = require('lodash'); diff --git a/lib/utils/getServerlessDir.js b/lib/utils/getServerlessDir.js index af1bae3fd..d38e63878 100644 --- a/lib/utils/getServerlessDir.js +++ b/lib/utils/getServerlessDir.js @@ -1,3 +1,5 @@ +'use strict'; + const path = require('path'); const os = require('os'); diff --git a/lib/utils/isDockerContainer.js b/lib/utils/isDockerContainer.js index cbbc992f1..57e89b282 100644 --- a/lib/utils/isDockerContainer.js +++ b/lib/utils/isDockerContainer.js @@ -1,3 +1,5 @@ +'use strict'; + const path = require('path'); const readFileSync = require('./fs/readFileSync'); const fileExistsSync = require('./fs/fileExistsSync'); From 7d98ead14950415a32a9d46e2a1fcf3190cabf5e Mon Sep 17 00:00:00 2001 From: davidwells Date: Wed, 17 May 2017 08:45:18 -0700 Subject: [PATCH 19/57] fix travis? --- lib/utils/config/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/utils/config/index.js b/lib/utils/config/index.js index b6eb8f931..d471d8683 100644 --- a/lib/utils/config/index.js +++ b/lib/utils/config/index.js @@ -51,7 +51,7 @@ function getConfig() { return require('rc')('serverless'); // eslint-disable-line } -// set global .serverlessrc config value +// set global .serverlessrc config value. function setConfigValue(key, value) { let config = getGlobalConfig(); if (key && typeof key === 'string' && typeof value !== 'undefined') { From f933e6e0c5660046679fe2b9cc15fa670ad4d7c7 Mon Sep 17 00:00:00 2001 From: davidwells Date: Wed, 17 May 2017 08:54:07 -0700 Subject: [PATCH 20/57] add deps --- package.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index ceeca757a..3fb80b2ea 100644 --- a/package.json +++ b/package.json @@ -104,11 +104,14 @@ "moment": "^2.13.0", "node-fetch": "^1.6.0", "opn": "^5.0.0", + "rc": "^1.2.1", "replaceall": "^0.1.6", "resolve-from": "^2.0.0", "semver": "^5.0.3", "semver-regex": "^1.0.0", "shelljs": "^0.6.0", - "uuid": "^2.0.2" + "traverse": "^0.6.6", + "uuid": "^2.0.2", + "write-file-atomic": "^2.1.0" } } From d849576b006bd3c2c9f3b885701ab02a517c5987 Mon Sep 17 00:00:00 2001 From: davidwells Date: Wed, 17 May 2017 09:15:38 -0700 Subject: [PATCH 21/57] travisssss! --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3fb80b2ea..116531767 100644 --- a/package.json +++ b/package.json @@ -104,7 +104,7 @@ "moment": "^2.13.0", "node-fetch": "^1.6.0", "opn": "^5.0.0", - "rc": "^1.2.1", + "rc": "^1.1.6", "replaceall": "^0.1.6", "resolve-from": "^2.0.0", "semver": "^5.0.3", From cb6d22e3e06ffdc52aa6c95a2ff314cf3c596181 Mon Sep 17 00:00:00 2001 From: davidwells Date: Wed, 17 May 2017 09:28:31 -0700 Subject: [PATCH 22/57] lint all the things --- lib/classes/Utils.js | 2 +- lib/plugins/login/login.js | 8 +++++--- lib/plugins/logout/logout.js | 8 ++++---- lib/plugins/logout/logout.test.js | 2 +- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/lib/classes/Utils.js b/lib/classes/Utils.js index 1bb601764..80c1e34a4 100644 --- a/lib/classes/Utils.js +++ b/lib/classes/Utils.js @@ -178,7 +178,7 @@ class Utils { return resolve(); } const config = configUtils.getConfig(); - console.log(config.slsStats); + console.log(config.slsStats); // eslint-disable-line let userId = uuid.v1(); if (!this.fileExistsSync(statsEnabledFilePath)) { diff --git a/lib/plugins/login/login.js b/lib/plugins/login/login.js index 6b01bccc1..005560848 100644 --- a/lib/plugins/login/login.js +++ b/lib/plugins/login/login.js @@ -9,7 +9,7 @@ const jwtDecode = require('jwt-decode'); const chalk = require('chalk'); const getFrameworkId = require('../../utils/getFrameworkId'); const clearConsole = require('../../utils/clearConsole'); -const segment = require('../../utils/segment'); +// const segment = require('../../utils/segment'); const setConfig = require('../../utils/config').set; // const getConfig = require('../../utils/config').getConfig; @@ -57,6 +57,7 @@ class Login { opn(url, options).catch(() => {}); return true; } catch (err) { + // https://github.com/sindresorhus/log-symbols console.log('---------------------------'); // eslint-disable-line console.log(`🙈 ${chalk.red("Unable to open browser automatically")}`); // eslint-disable-line console.log(chalk.green("Please open your browser & open the URL below to login:")); // eslint-disable-line @@ -77,8 +78,9 @@ class Login { const state = `id%3D${frameworkId}`; // refresh token docs https://auth0.com/docs/tokens/preview/refresh-token#get-a-refresh-token const authorizeUrl = - `${config.AUTH0_URL}/authorize?response_type=code&scope=openid%20email%20nickname%20offline_access&` + - `client_id=${config.AUTH0_CLIENT_ID}&redirect_uri=${config.AUTH0_CALLBACK_URL}` + + `${config.AUTH0_URL}/authorize?response_type=code` + + '&scope=openid%20email%20nickname%20offline_access' + + `&client_id=${config.AUTH0_CLIENT_ID}&redirect_uri=${config.AUTH0_CALLBACK_URL}` + `&code_challenge=${verifierChallenge}&code_challenge_method=S256&state=${state}`; setTimeout(() => { diff --git a/lib/plugins/logout/logout.js b/lib/plugins/logout/logout.js index 9dcea15a0..579972ef3 100644 --- a/lib/plugins/logout/logout.js +++ b/lib/plugins/logout/logout.js @@ -1,6 +1,6 @@ 'use strict'; -const getFrameworkId = require('../../utils/getFrameworkId'); +// const getFrameworkId = require('../../utils/getFrameworkId'); // const segment = require('../../utils/segment'); const config = require('../../utils/config'); @@ -24,7 +24,7 @@ class Login { const configuration = config.getAll(); if (configuration && !configuration.auth) { - console.log('You are already logged out.'); + console.log('You are already logged out.'); // eslint-disable-line return; } const logout = () => { @@ -33,11 +33,11 @@ class Login { // that invalidate a refresh token in Auth0 (using the Auth0 Management API). // This endpoint should be called when the user runs `serverless logout` in the CLI. config.set('auth', null); - console.log('Successfully logged out.'); + console.log('Successfully logged out.'); // eslint-disable-line // Note no need to wait for any connections e.g. segment to close process.exit(0); } catch (e) { - console.log('Failed to logout. Please manually remove this file: '); + console.log('Failed to logout. Please manually remove this file: '); // eslint-disable-line // Note no need to wait for any connections e.g. segment to close process.exit(0); } diff --git a/lib/plugins/logout/logout.test.js b/lib/plugins/logout/logout.test.js index a1d93defc..4df6b059d 100644 --- a/lib/plugins/logout/logout.test.js +++ b/lib/plugins/logout/logout.test.js @@ -14,6 +14,6 @@ describe('Logout', () => { }); describe('#constructor()', () => { - it('should have commands', () => expect(login.commands).to.be.not.empty); + it('should have commands', () => expect(logout.commands).to.be.not.empty); }); }); From bc8c3006cf5495735bd33ac0592d962355dd0b8b Mon Sep 17 00:00:00 2001 From: davidwells Date: Tue, 23 May 2017 19:56:52 -0700 Subject: [PATCH 23/57] add userstats & validation --- lib/utils/userStats.js | 87 ++++++++++++++++++++++++++++++++ lib/utils/userStatsValidation.js | 83 ++++++++++++++++++++++++++++++ 2 files changed, 170 insertions(+) create mode 100644 lib/utils/userStats.js create mode 100644 lib/utils/userStatsValidation.js diff --git a/lib/utils/userStats.js b/lib/utils/userStats.js new file mode 100644 index 000000000..6fe1e8cc4 --- /dev/null +++ b/lib/utils/userStats.js @@ -0,0 +1,87 @@ +const BbPromise = require('bluebird'); +const _ = require('lodash'); +const fetch = require('node-fetch'); +const configUtils = require('./config'); +const isTrackingDisabled = require('./isTrackingDisabled'); +const isValidEventName = require('./userStatsValidation'); + +const config = configUtils.getConfig(); +const TRACKING_IS_DISABLED = isTrackingDisabled(); +const TRACK_URL = 'https://serverless.com/api/framework/track'; +const IDENTIFY_URL = 'https://serverless.com/api/framework/identify'; + +/* note tracking swallows errors */ +function request(url, payload) { + return fetch(url, { + method: 'POST', + timeout: '1000', + body: JSON.stringify(payload), + }) + .then((response) => { + if (response.status === 404) { + return BbPromise.reject('404 api not found'); + } + return response.json(); + }) + .then((res) => BbPromise.resolve(res)) + .catch((e) => { + console.log('SLS Tracking Error, Please update to latest version of framework with `npm i serverless -g`'); // eslint-disable-line + return BbPromise.resolve(e); + }); +} + +function track(eventName, payload) { + const data = payload || {} + const userId = data.id || config.userId; + + // automatically add `framework:` prefix + if (eventName.indexOf('framework:') === -1) { + eventName = `${eventName}`; // eslint-disable-line + } + + // exit early if tracking disabled + if (TRACKING_IS_DISABLED || !userId) { + console.log('abort track'); + return BbPromise.resolve(); + } + + // exit early if no email found + if ((config.users && config.users[userId] && !config.users[userId].email)) { + return BbPromise.resolve(); + } + + // to ensure clean data, validate event name + if (!isValidEventName(eventName)) { + return BbPromise.resolve(); + } + + const defaultData = { + event: eventName, + id: userId, + email: config.users[userId].email, + data: { + id: userId, + timestamp: Math.round(+new Date() / 1000), + }, + }; + + const eventData = _.merge(defaultData, data); + console.log('run track in framework', eventData); + return BbPromise.resolve(); + return request(TRACK_URL, eventData); +} + +function identify(payload) { + if (TRACKING_IS_DISABLED) { + console.log('abort track'); + // exit early is tracking disabled + return BbPromise.resolve(); + } + console.log('run identify in framework'); + return request(IDENTIFY_URL, payload); +} + +module.exports = { + track, + identify, +}; diff --git a/lib/utils/userStatsValidation.js b/lib/utils/userStatsValidation.js new file mode 100644 index 000000000..80ad7cd53 --- /dev/null +++ b/lib/utils/userStatsValidation.js @@ -0,0 +1,83 @@ +/** + * Validate Event names to keep data clean + */ +const chalk = require('chalk'); + +const VALID_TRACKING_PROJECTS = ['framework']; +const VALID_TRACKING_OBJECTS = ['user']; + +function containsSeparators(eventName) { + const underscores = (eventName.match(/_/g) || []).length; + const colons = (eventName.match(/:/g) || []).length; + if (underscores !== 1) { + console.log(chalk.red('Tracking Error:')); // eslint-disable-line + console.log(chalk.red(`Event name must have single underscore. "${eventName}" contains ${underscores}`)); // eslint-disable-line + return false; + } + if (colons !== 1) { + console.log(chalk.red('Tracking Error:')); // eslint-disable-line + console.log(chalk.red(`Event name must have single colon. "${eventName}" contains ${colons}`)); // eslint-disable-line + return false; + } + return true; +} + +// Validate tracking project for clean events +function isValidProject(project) { + const isValid = VALID_TRACKING_PROJECTS.indexOf(project) !== -1; + if (!isValid) { + console.log(chalk.red('Tracking Error:')); // eslint-disable-line + console.log(`"${project}" is invalid project. Must be one of`, VALID_TRACKING_PROJECTS); // eslint-disable-line + } + return isValid; +} + +// Validate tracking objects for clean events +function isValidObject(key) { + const isValid = VALID_TRACKING_OBJECTS.indexOf(key) !== -1; + if (!isValid) { + console.log(chalk.red('Tracking Error:')); // eslint-disable-line + console.log(`"${key}" is invalid tracking object. Must be one of`, VALID_TRACKING_OBJECTS); // eslint-disable-line + } + return isValid; +} + +function formattingWarning(eventName) { + /*eslint-disable */ + console.log(chalk.red(`Incorrect tracking event format: "${eventName}"`)); + console.log('Tracking event must match ' + chalk.yellow("product:objectName_actionName")); + console.log('It must be all camelCase: ' + chalk.yellow("camelCase:camelCase_camelCase")); + console.log('Here is an Example ' + chalk.green("framework:user_loggedIn")); + console.log('Note: `framework:` is automatically prepended'); + console.log('Usage:', chalk.yellow(`track('user_loggedIn', { ..extraData });`)); + console.log('-----------------------------'); + /*eslint-enable */ + return false; +} + +// validate events to naming conventions. clean data FTW! +module.exports = function isValidEventName(eventName) { + // match framework:objectName_actionName + const matches = eventName.match(/([a-zA-Z]*):([a-zA-Z]*)_(.*)/); + if (!containsSeparators(eventName) || !matches) { + return formattingWarning(eventName); + } + const project = matches[1]; + const object = matches[2]; + const action = matches[3]; + // console.log(`${project}:${object}_${action}`) + + // if missing any parts of event, exit; + if (!project || !object || !action) { + return formattingWarning(eventName); + } + // validate project name + if (!isValidProject(project)) { + return formattingWarning(eventName); + } + // validate object name + if (!isValidObject(object)) { + return formattingWarning(eventName); + } + return true; +}; From 9b0679eebf491e93d68b728830c9e53b6f0a7ea8 Mon Sep 17 00:00:00 2001 From: davidwells Date: Tue, 23 May 2017 19:57:00 -0700 Subject: [PATCH 24/57] update segment --- lib/utils/segment.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/utils/segment.js b/lib/utils/segment.js index bf071f49f..8436c801a 100644 --- a/lib/utils/segment.js +++ b/lib/utils/segment.js @@ -1,11 +1,14 @@ const BbPromise = require('bluebird'); const fetch = require('node-fetch'); +const isTrackingDisabled = require('./isTrackingDisabled'); // TODO: Replace me before release const writeKey = 'XXXX'; const auth = `${writeKey}:`; +const TRACKING_IS_DISABLED = isTrackingDisabled(); +/* note segment call swallows errors */ function request(url, payload) { - return fetch('https://api.segment.io/v1/track', { + return fetch(url, { headers: { Authorization: `Basic ${new Buffer(auth).toString('base64')}`, 'content-type': 'application/json', @@ -20,14 +23,13 @@ function request(url, payload) { } function track(payload) { + // exit early is tracking disabled + if (TRACKING_IS_DISABLED) { + return BbPromise.resolve(); + } return request('https://api.segment.io/v1/track', payload); } -function alias(payload) { - return request('https://api.segment.io/v1/alias', payload); -} - module.exports = { track, - alias, }; From e91042194a6f5171a07f56924fdc926fea68b898 Mon Sep 17 00:00:00 2001 From: davidwells Date: Tue, 23 May 2017 19:57:09 -0700 Subject: [PATCH 25/57] add utils --- lib/utils/isTrackingDisabled.js | 11 +++++++++++ lib/utils/openBrowser.js | 30 ++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 lib/utils/isTrackingDisabled.js create mode 100644 lib/utils/openBrowser.js diff --git a/lib/utils/isTrackingDisabled.js b/lib/utils/isTrackingDisabled.js new file mode 100644 index 000000000..4d521b0c6 --- /dev/null +++ b/lib/utils/isTrackingDisabled.js @@ -0,0 +1,11 @@ +const path = require('path'); +const fileExistsSync = require('./fs/fileExistsSync'); +const getServerlessDir = require('./getServerlessDir'); + +module.exports = function isTrackingDisabled() { + // to be updated to .serverlessrc + if (fileExistsSync(path.join(getServerlessDir(), 'stats-disabled'))) { + return true; + } + return false; +}; diff --git a/lib/utils/openBrowser.js b/lib/utils/openBrowser.js new file mode 100644 index 000000000..9e36b1873 --- /dev/null +++ b/lib/utils/openBrowser.js @@ -0,0 +1,30 @@ +const opn = require('opn'); +const chalk = require('chalk'); +const isDockerContainer = require('./isDockerContainer'); + +function displayManualOpenMessage(url) { + // https://github.com/sindresorhus/log-symbols + console.log('---------------------------'); // eslint-disable-line + console.log(`🙈 ${chalk.red("Unable to open browser automatically")}`); // eslint-disable-line + console.log(chalk.green("Please open your browser & open the URL below to login:")); // eslint-disable-line + console.log(chalk.yellow(url)); // eslint-disable-line + console.log('---------------------------'); // eslint-disable-line + return false; +} + +module.exports = function openBrowser(url) { + let browser = process.env.BROWSER; + if (browser === 'none' || isDockerContainer()) { + return displayManualOpenMessage(url); + } + if (process.platform === 'darwin' && browser === 'open') { + browser = undefined; + } + try { + const options = { app: browser }; + opn(url, options).catch(() => {}); + return true; + } catch (err) { + return displayManualOpenMessage(url); + } +}; From fd657fc4a80c0f4e2b8ec20b4b92d293d3a970be Mon Sep 17 00:00:00 2001 From: davidwells Date: Tue, 23 May 2017 19:57:22 -0700 Subject: [PATCH 26/57] update config --- lib/utils/config/index.js | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/lib/utils/config/index.js b/lib/utils/config/index.js index d471d8683..bf0cc646f 100644 --- a/lib/utils/config/index.js +++ b/lib/utils/config/index.js @@ -8,24 +8,16 @@ const writeFileAtomic = require('write-file-atomic'); const getFrameworkId = require('../getFrameworkId'); const fileExistsSync = require('../fs/fileExistsSync'); const readFileSync = require('../fs/readFileSync'); -const getServerlessDir = require('../getServerlessDir'); +const isTrackingDisabled = require('../isTrackingDisabled'); const globalConfigPath = path.join(os.homedir(), '.serverlessrc'); -function legacyIsTrackingDisabled() { - if (fileExistsSync(path.join(getServerlessDir(), 'stats-disabled'))) { - return true; - } - return false; -} - function createConfig() { // set default config options const config = { + userId: null, // currentUserId frameworkId: getFrameworkId(), - settings: { - trackingDisabled: legacyIsTrackingDisabled(), - }, + trackingDisabled: isTrackingDisabled(), }; writeFileAtomic.sync(globalConfigPath, JSON.stringify(config, null, 2)); return JSON.parse(readFileSync(globalConfigPath)); @@ -79,7 +71,7 @@ function deleteConfigValue(key) { } // set local config value /project/.serverlessrc -// function setLocalConfig +// function setLocalConfig() {} // set .serverlessrc config value function getConfigValue(objectPath) { @@ -95,5 +87,6 @@ module.exports = { get: getConfigValue, delete: deleteConfigValue, getConfig, + getGlobalConfig, CONFIG_FILE_PATH: globalConfigPath, }; From 69fd7c4e2b6530b13a593994cb73c40f4836b8ed Mon Sep 17 00:00:00 2001 From: davidwells Date: Tue, 23 May 2017 19:57:33 -0700 Subject: [PATCH 27/57] update logout --- lib/plugins/logout/logout.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/plugins/logout/logout.js b/lib/plugins/logout/logout.js index 579972ef3..4421c0def 100644 --- a/lib/plugins/logout/logout.js +++ b/lib/plugins/logout/logout.js @@ -2,7 +2,7 @@ // const getFrameworkId = require('../../utils/getFrameworkId'); // const segment = require('../../utils/segment'); -const config = require('../../utils/config'); +const configUtils = require('../../utils/config'); class Login { constructor(serverless, options) { @@ -21,18 +21,18 @@ class Login { }; } logout() { - const configuration = config.getAll(); + const config = configUtils.getConfig(); + const globalConfig = configUtils.getGlobalConfig(); + const currentUserId = config.currentUserId; - if (configuration && !configuration.auth) { - console.log('You are already logged out.'); // eslint-disable-line - return; - } const logout = () => { try { // TODO Once we start using refresh tokens we also need to implement an API endpoint // that invalidate a refresh token in Auth0 (using the Auth0 Management API). // This endpoint should be called when the user runs `serverless logout` in the CLI. - config.set('auth', null); + if (globalConfig && globalConfig.users && globalConfig.users[currentUserId]) { + configUtils.set(`users.${currentUserId}.auth`, null); + } console.log('Successfully logged out.'); // eslint-disable-line // Note no need to wait for any connections e.g. segment to close process.exit(0); From f115fc87abbd1342222073afbaeeb674148351ef Mon Sep 17 00:00:00 2001 From: davidwells Date: Tue, 23 May 2017 19:57:47 -0700 Subject: [PATCH 28/57] update segment --- lib/classes/Utils.js | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/lib/classes/Utils.js b/lib/classes/Utils.js index 80c1e34a4..08273965c 100644 --- a/lib/classes/Utils.js +++ b/lib/classes/Utils.js @@ -15,6 +15,7 @@ const writeFileSync = require('../utils/fs/writeFileSync'); const readFileSync = require('../utils/fs/readFileSync'); const isDockerContainer = require('../utils/isDockerContainer'); const version = require('../../package.json').version; +const segment = require('../utils/segment'); const configUtils = require('../utils/config'); class Utils { @@ -151,24 +152,6 @@ class Utils { const options = serverless.processedInput.options; const commands = serverless.processedInput.commands; - const log = (data) => { - const writeKey = 'XXXX'; // TODO: Replace me before release - const auth = `${writeKey}:`; - - return fetch('https://api.segment.io/v1/track', { - headers: { - Authorization: `Basic ${new Buffer(auth).toString('base64')}`, - 'content-type': 'application/json', - }, - method: 'POST', - timeout: '1000', - body: JSON.stringify(data), - }) - .then((response) => response.json()) - .then(() => BbPromise.resolve()) - .catch(() => BbPromise.resolve()); - }; - return new BbPromise((resolve) => { const serverlessDirPath = path.join(os.homedir(), '.serverless'); const statsEnabledFilePath = path.join(serverlessDirPath, 'stats-enabled'); @@ -178,7 +161,7 @@ class Utils { return resolve(); } const config = configUtils.getConfig(); - console.log(config.slsStats); // eslint-disable-line + console.log(config.settings); // eslint-disable-line let userId = uuid.v1(); if (!this.fileExistsSync(statsEnabledFilePath)) { @@ -319,7 +302,7 @@ class Utils { }).then((data) => { // only log the data if it's there if (data) { - log(data); + segment.track(data); } }); } From 8487a22905a076638a9f92b696a38254eef7b302 Mon Sep 17 00:00:00 2001 From: davidwells Date: Tue, 23 May 2017 19:59:17 -0700 Subject: [PATCH 29/57] update login --- lib/plugins/login/login.js | 103 ++++++++++++++++++++----------------- 1 file changed, 56 insertions(+), 47 deletions(-) diff --git a/lib/plugins/login/login.js b/lib/plugins/login/login.js index 005560848..63704de09 100644 --- a/lib/plugins/login/login.js +++ b/lib/plugins/login/login.js @@ -3,20 +3,21 @@ const BbPromise = require('bluebird'); const crypto = require('crypto'); const readline = require('readline'); -const opn = require('opn'); const fetch = require('node-fetch'); const jwtDecode = require('jwt-decode'); const chalk = require('chalk'); +const openBrowser = require('../../utils/openBrowser'); const getFrameworkId = require('../../utils/getFrameworkId'); const clearConsole = require('../../utils/clearConsole'); -// const segment = require('../../utils/segment'); +const userStats = require('../../utils/userStats'); const setConfig = require('../../utils/config').set; -// const getConfig = require('../../utils/config').getConfig; +// segment for future use +// const segment = require('../../utils/segment'); const config = { AUTH0_CLIENT_ID: 'iiEYK0KB30gj94mjB8HP9lhhTgae0Rg3', AUTH0_URL: 'https://serverlessinc.auth0.com', - AUTH0_CALLBACK_URL: 'https://serverless.com/welcome', + AUTH0_CALLBACK_URL: 'https://serverless.com/auth', }; function base64url(url) { @@ -44,42 +45,19 @@ class Login { 'login:login': () => BbPromise.bind(this).then(this.login), }; } - openBrowser(url) { - let browser = process.env.BROWSER; - if (browser === 'none') { - return false; - } - if (process.platform === 'darwin' && browser === 'open') { - browser = undefined; - } - try { - const options = { app: browser }; - opn(url, options).catch(() => {}); - return true; - } catch (err) { - // https://github.com/sindresorhus/log-symbols - console.log('---------------------------'); // eslint-disable-line - console.log(`🙈 ${chalk.red("Unable to open browser automatically")}`); // eslint-disable-line - console.log(chalk.green("Please open your browser & open the URL below to login:")); // eslint-disable-line - console.log(chalk.yellow(url)); // eslint-disable-line - console.log('---------------------------'); // eslint-disable-line - return false; - } - } login() { clearConsole(); this.serverless.cli.log('The Serverless login will open in your default browser...'); - // Generate the verifier, and the corresponding challenge const verifier = base64url(crypto.randomBytes(32)); const verifierChallenge = base64url(crypto.createHash('sha256').update(verifier).digest()); const frameworkId = getFrameworkId(); // eslint-disable-next-line prefer-template - const state = `id%3D${frameworkId}`; + const version = this.serverless.version; + const state = `id%3D${frameworkId}%26version%3D${version}%26platform%3D${process.platform}`; // refresh token docs https://auth0.com/docs/tokens/preview/refresh-token#get-a-refresh-token const authorizeUrl = - `${config.AUTH0_URL}/authorize?response_type=code` + - '&scope=openid%20email%20nickname%20offline_access' + + `${config.AUTH0_URL}/authorize?response_type=code&scope=openid%20profile%20offline_access` + `&client_id=${config.AUTH0_CLIENT_ID}&redirect_uri=${config.AUTH0_CALLBACK_URL}` + `&code_challenge=${verifierChallenge}&code_challenge_method=S256&state=${state}`; @@ -89,7 +67,7 @@ class Login { setTimeout(() => { // pop open default browser - this.openBrowser(authorizeUrl); + openBrowser(authorizeUrl); // wait for token const readlineInterface = readline.createInterface({ @@ -114,34 +92,65 @@ class Login { .then((response) => response.json()) .then((platformResponse) => { const decoded = jwtDecode(platformResponse.id_token); - this.serverless.cli.log('You are logged in'); - // alias for segment only works with mixpanel - // segment.alias({ - // previousId: frameworkId, - // userId: decoded.sub, - // }); - /* segment.identify({ - userId: decoded.sub, + // console.log('decoded', decoded); + this.serverless.cli.log('You are now logged in'); + console.log('Run `serverless` or `sls` to see a list of commands`'); // eslint-disable-line + + // because platform only support github + const id = decoded.original_user_id || decoded.sub; + + /* For future use + segment.identify({ + userId: id, traits: { email: profile.email, }, }) */ - // update .serverlessrc + const userConfig = { - userId: decoded.sub, + userId: id, frameworkId, users: {}, }; - // set user auth - userConfig.users[decoded.sub] = { - userId: decoded.sub, + // set user auth in global .serverlessrc file + userConfig.users[id] = { + userId: id, + name: decoded.name, + email: decoded.email, auth: platformResponse, }; + + // update .serverlessrc setConfig(userConfig); - process.exit(0); + + const userID = new Buffer(id).toString('base64'); + const email = new Buffer(decoded.email).toString('base64'); + const name = new Buffer(decoded.name).toString('base64'); + const loginCount = decoded.login_count; + const createdAt = decoded.created_at; + const successUrl = `https://serverless.com/success?u=${userID}&e=${email}&n=${name}&c=${loginCount}&v=${version}&d=${createdAt}&id=${frameworkId}`; // eslint-disable-line + + openBrowser(successUrl); + // identify user for better onboarding + userStats.identify({ + id, + frameworkId, + email: decoded.email, + // unix timestamp + created_at: Math.round(+new Date(createdAt) / 1000), + }).then(() => { + userStats.track('user_loggedIn', { + id, + email: decoded.email, + }).then(() => { + // console.log('login complete'); + // then exit process + process.exit(0); + }); + }); }) - .catch((e) => { - console.log(e); // eslint-disable-line + .catch(() => { + console.log(chalk.red('Incorrect token value supplied. Please run `serverless login` again')); // eslint-disable-line process.exit(0); }); }); From 0fbaad67c40797933ef13146fff99454205c45ff Mon Sep 17 00:00:00 2001 From: davidwells Date: Tue, 23 May 2017 20:15:15 -0700 Subject: [PATCH 30/57] linting --- lib/utils/userStats.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/utils/userStats.js b/lib/utils/userStats.js index 6fe1e8cc4..8731aaf63 100644 --- a/lib/utils/userStats.js +++ b/lib/utils/userStats.js @@ -31,12 +31,12 @@ function request(url, payload) { } function track(eventName, payload) { - const data = payload || {} + const data = payload || {}; const userId = data.id || config.userId; // automatically add `framework:` prefix if (eventName.indexOf('framework:') === -1) { - eventName = `${eventName}`; // eslint-disable-line + eventName = `framework:${eventName}`; // eslint-disable-line } // exit early if tracking disabled @@ -67,7 +67,7 @@ function track(eventName, payload) { const eventData = _.merge(defaultData, data); console.log('run track in framework', eventData); - return BbPromise.resolve(); + // return BbPromise.resolve(); return request(TRACK_URL, eventData); } From 736d780bf0d6023a484240e358b1c277974e44c0 Mon Sep 17 00:00:00 2001 From: davidwells Date: Tue, 23 May 2017 20:15:21 -0700 Subject: [PATCH 31/57] linting --- lib/utils/openBrowser.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/utils/openBrowser.js b/lib/utils/openBrowser.js index 9e36b1873..87f1f9066 100644 --- a/lib/utils/openBrowser.js +++ b/lib/utils/openBrowser.js @@ -3,12 +3,14 @@ const chalk = require('chalk'); const isDockerContainer = require('./isDockerContainer'); function displayManualOpenMessage(url) { + /* eslint-disable */ // https://github.com/sindresorhus/log-symbols - console.log('---------------------------'); // eslint-disable-line - console.log(`🙈 ${chalk.red("Unable to open browser automatically")}`); // eslint-disable-line - console.log(chalk.green("Please open your browser & open the URL below to login:")); // eslint-disable-line - console.log(chalk.yellow(url)); // eslint-disable-line - console.log('---------------------------'); // eslint-disable-line + console.log('---------------------------'); + console.log(`🙈 ${chalk.red("Unable to open browser automatically")}`); + console.log(chalk.green("Please open your browser & open the URL below to login:")); + console.log(chalk.yellow(url)); + console.log('---------------------------'); + /* eslint-enable */ return false; } From c8dbd7a4a676b26ff83a22ccfc1a7438f0b702f2 Mon Sep 17 00:00:00 2001 From: davidwells Date: Tue, 23 May 2017 20:15:35 -0700 Subject: [PATCH 32/57] add id --- lib/classes/Utils.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/classes/Utils.js b/lib/classes/Utils.js index 08273965c..40b7e177d 100644 --- a/lib/classes/Utils.js +++ b/lib/classes/Utils.js @@ -7,7 +7,6 @@ const ci = require('ci-info'); const BbPromise = require('bluebird'); const fse = BbPromise.promisifyAll(require('fs-extra')); const _ = require('lodash'); -const fetch = require('node-fetch'); const uuid = require('uuid'); const os = require('os'); const fileExistsSync = require('../utils/fs/fileExistsSync'); @@ -160,8 +159,7 @@ class Utils { if (this.fileExistsSync(statsDisabledFilePath)) { return resolve(); } - const config = configUtils.getConfig(); - console.log(config.settings); // eslint-disable-line + // Todo update with new user id let userId = uuid.v1(); if (!this.fileExistsSync(statsEnabledFilePath)) { @@ -298,6 +296,11 @@ class Utils { }, }; + const config = configUtils.getConfig(); + if (config.userId && data.properties && data.properties.general) { + data.properties.general.platformId = config.userId; + } + return resolve(data); }).then((data) => { // only log the data if it's there From d5085f1793eebfa2bbf92a024605aab798377276 Mon Sep 17 00:00:00 2001 From: davidwells Date: Tue, 23 May 2017 20:22:22 -0700 Subject: [PATCH 33/57] update docs --- docs/providers/aws/cli-reference/login.md | 2 +- docs/providers/azure/cli-reference/login.md | 2 +- docs/providers/openwhisk/cli-reference/login.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/providers/aws/cli-reference/login.md b/docs/providers/aws/cli-reference/login.md index 40708a2b4..22af8e5d5 100644 --- a/docs/providers/aws/cli-reference/login.md +++ b/docs/providers/aws/cli-reference/login.md @@ -1,6 +1,6 @@ + + +### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/google/cli-reference/login) + + +# Login + +The `login` command logs users into the serverless platform. + +It will create a new serverless platform account if one doesn't already exist. + +```bash +serverless login + +# Shorthand +sls login +``` From 9e7a1e929795055f6d10a80ff431adf340b90696 Mon Sep 17 00:00:00 2001 From: davidwells Date: Wed, 24 May 2017 00:49:13 -0700 Subject: [PATCH 47/57] change tildes --- lib/plugins/login/login.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/plugins/login/login.js b/lib/plugins/login/login.js index b608583c8..65e4850ea 100644 --- a/lib/plugins/login/login.js +++ b/lib/plugins/login/login.js @@ -92,7 +92,6 @@ class Login { .then((response) => response.json()) .then((platformResponse) => { const decoded = jwtDecode(platformResponse.id_token); - // console.log('decoded', decoded); this.serverless.cli.log('You are now logged in'); // because platform only support github @@ -144,14 +143,13 @@ class Login { email: decoded.email, force: true, }).then(() => { - // console.log('login complete'); // then exit process process.exit(0); }); }); }) .catch(() => { - console.log(chalk.red('Incorrect token value supplied. Please run `serverless login` again')); // eslint-disable-line + console.log(chalk.red('Incorrect token value supplied. Please run "serverless login" again')); // eslint-disable-line process.exit(0); }); }); From 710ff6fff28517f3d1fc0b5210b005f070609906 Mon Sep 17 00:00:00 2001 From: davidwells Date: Wed, 24 May 2017 00:52:59 -0700 Subject: [PATCH 48/57] update test --- lib/utils/config/config.test.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/utils/config/config.test.js b/lib/utils/config/config.test.js index 73ae55317..8b747d1ca 100644 --- a/lib/utils/config/config.test.js +++ b/lib/utils/config/config.test.js @@ -3,26 +3,26 @@ const expect = require('chai').expect; const config = require('./index'); -describe('Config', () => { +describe.only('Config', () => { it('should have CONFIG_FILE_PATH', () => { const configPath = config.CONFIG_FILE_PATH; expect(configPath).to.exist; // eslint-disable-line }); describe('When using config.getConfig', () => { - it('should have frameworkId', () => { + it('should have userId key', () => { + const conf = config.getConfig(); + expect(conf).to.have.deep.property('userId'); + }); + + it('should have frameworkId key', () => { const conf = config.getConfig(); expect(conf).to.have.deep.property('frameworkId'); }); - it('should have settings', () => { + it('should have trackingDisabled key', () => { const conf = config.getConfig(); - expect(conf).to.have.deep.property('settings'); - }); - - it('should have settings.trackingDisabled', () => { - const conf = config.getConfig(); - expect(conf).to.have.deep.property('settings.trackingDisabled'); + expect(conf).to.have.deep.property('trackingDisabled'); }); }); From 1b8b8ae0aef6ab12308011f07bb761438211e04c Mon Sep 17 00:00:00 2001 From: davidwells Date: Wed, 24 May 2017 00:53:45 -0700 Subject: [PATCH 49/57] update test --- lib/utils/config/config.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/utils/config/config.test.js b/lib/utils/config/config.test.js index 8b747d1ca..7ed4d1e46 100644 --- a/lib/utils/config/config.test.js +++ b/lib/utils/config/config.test.js @@ -3,7 +3,7 @@ const expect = require('chai').expect; const config = require('./index'); -describe.only('Config', () => { +describe('Config', () => { it('should have CONFIG_FILE_PATH', () => { const configPath = config.CONFIG_FILE_PATH; expect(configPath).to.exist; // eslint-disable-line From e97285a5c76695cadb24225369b7b22dbc806b60 Mon Sep 17 00:00:00 2001 From: davidwells Date: Wed, 24 May 2017 01:03:10 -0700 Subject: [PATCH 50/57] add createdTimestamp --- lib/utils/config/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/utils/config/index.js b/lib/utils/config/index.js index bf0cc646f..694f7835b 100644 --- a/lib/utils/config/index.js +++ b/lib/utils/config/index.js @@ -18,6 +18,7 @@ function createConfig() { userId: null, // currentUserId frameworkId: getFrameworkId(), trackingDisabled: isTrackingDisabled(), + created: Math.round(+new Date() / 1000), }; writeFileAtomic.sync(globalConfigPath, JSON.stringify(config, null, 2)); return JSON.parse(readFileSync(globalConfigPath)); From b4aced36d936fd07848303663476503da6bbb07d Mon Sep 17 00:00:00 2001 From: davidwells Date: Wed, 24 May 2017 01:16:49 -0700 Subject: [PATCH 51/57] add file meta --- lib/utils/config/index.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/utils/config/index.js b/lib/utils/config/index.js index 694f7835b..67d2536b7 100644 --- a/lib/utils/config/index.js +++ b/lib/utils/config/index.js @@ -18,7 +18,10 @@ function createConfig() { userId: null, // currentUserId frameworkId: getFrameworkId(), trackingDisabled: isTrackingDisabled(), - created: Math.round(+new Date() / 1000), + meta: { + created_at: Math.round(+new Date() / 1000), + updated_at: null, + } }; writeFileAtomic.sync(globalConfigPath, JSON.stringify(config, null, 2)); return JSON.parse(readFileSync(globalConfigPath)); @@ -54,6 +57,7 @@ function setConfigValue(key, value) { } else if (typeof value !== 'undefined') { config = _.merge(config, value); } + config.meta.updated_at = Math.round(+new Date() / 1000); // write file writeFileAtomic.sync(globalConfigPath, JSON.stringify(config, null, 2)); return config; From ac7515fb1079603f0f5144e2046de9a54449948d Mon Sep 17 00:00:00 2001 From: davidwells Date: Wed, 24 May 2017 01:18:10 -0700 Subject: [PATCH 52/57] add empty obj --- lib/utils/config/index.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/utils/config/index.js b/lib/utils/config/index.js index 67d2536b7..0815e38bc 100644 --- a/lib/utils/config/index.js +++ b/lib/utils/config/index.js @@ -57,6 +57,8 @@ function setConfigValue(key, value) { } else if (typeof value !== 'undefined') { config = _.merge(config, value); } + // update config meta + config.meta = config.meta || {}; config.meta.updated_at = Math.round(+new Date() / 1000); // write file writeFileAtomic.sync(globalConfigPath, JSON.stringify(config, null, 2)); From 3f1c8b47ebf70883343ac51a36b69f5f20915827 Mon Sep 17 00:00:00 2001 From: Philipp Muens Date: Wed, 24 May 2017 12:51:25 +0200 Subject: [PATCH 53/57] Add login CLI command to TOCs --- docs/providers/aws/README.md | 1 + docs/providers/azure/README.md | 1 + docs/providers/google/README.md | 1 + docs/providers/openwhisk/README.md | 1 + 4 files changed, 4 insertions(+) diff --git a/docs/providers/aws/README.md b/docs/providers/aws/README.md index f25b4437e..d464d02fc 100644 --- a/docs/providers/aws/README.md +++ b/docs/providers/aws/README.md @@ -62,6 +62,7 @@ If you have questions, join the [chat in gitter](https://gitter.im/serverless/se
  • Invoke
  • Invoke Local
  • Logs
  • +
  • Login
  • Metrics
  • Info
  • Rollback
  • diff --git a/docs/providers/azure/README.md b/docs/providers/azure/README.md index 3466edb5a..6991b338d 100644 --- a/docs/providers/azure/README.md +++ b/docs/providers/azure/README.md @@ -54,6 +54,7 @@ If you have questions, join the [chat in gitter](https://gitter.im/serverless/se
  • Deploy
  • Deploy Function
  • Invoke
  • +
  • Login
  • Logs
  • Remove
  • diff --git a/docs/providers/google/README.md b/docs/providers/google/README.md index 107047353..cfaf54714 100644 --- a/docs/providers/google/README.md +++ b/docs/providers/google/README.md @@ -54,6 +54,7 @@ If you have questions, join the [chat in gitter](https://gitter.im/serverless/se
  • Deploy
  • Info
  • Invoke
  • +
  • Login
  • Logs
  • Remove
  • diff --git a/docs/providers/openwhisk/README.md b/docs/providers/openwhisk/README.md index be09487b9..a8c78d06f 100644 --- a/docs/providers/openwhisk/README.md +++ b/docs/providers/openwhisk/README.md @@ -59,6 +59,7 @@ If you have questions, join the [chat in gitter](https://gitter.im/serverless/se
  • Deploy Function
  • Invoke
  • Invoke Local
  • +
  • Login
  • Logs
  • Info
  • Remove
  • From a5d81e0a436d7da2bc37341180da2ee915d6c3bd Mon Sep 17 00:00:00 2001 From: Philipp Muens Date: Wed, 24 May 2017 13:01:48 +0200 Subject: [PATCH 54/57] Remove commented out code --- lib/classes/Utils.js | 6 ------ lib/plugins/login/login.js | 2 -- lib/plugins/logout/logout.js | 2 -- lib/utils/config/index.js | 5 +---- lib/utils/userStatsValidation.js | 1 - 5 files changed, 1 insertion(+), 15 deletions(-) diff --git a/lib/classes/Utils.js b/lib/classes/Utils.js index 18e76a1f3..a5092c59e 100644 --- a/lib/classes/Utils.js +++ b/lib/classes/Utils.js @@ -35,8 +35,6 @@ class Utils { } fileExistsSync(filePath) { - // console.log('this.serverless.utils.fileExistsSync being depricated in a future release') - // console.log('Please explicitly declare your plugin dependancies') return fileExistsSync(filePath); } @@ -45,8 +43,6 @@ class Utils { } writeFileSync(filePath, contents) { - // console.log('this.serverless.utils.writeFileSync being depricated in a future release') - // console.log('Please explicitly declare your plugin dependancies') return writeFileSync(filePath, contents); } @@ -76,8 +72,6 @@ class Utils { } readFileSync(filePath) { - // console.log('this.serverless.utils.writeFileSync being depricated in a future release') - // console.log('Please explicitly declare your plugin dependancies') return readFileSync(filePath); } diff --git a/lib/plugins/login/login.js b/lib/plugins/login/login.js index 65e4850ea..0f30b990a 100644 --- a/lib/plugins/login/login.js +++ b/lib/plugins/login/login.js @@ -11,8 +11,6 @@ const getFrameworkId = require('../../utils/getFrameworkId'); const clearConsole = require('../../utils/clearConsole'); const userStats = require('../../utils/userStats'); const setConfig = require('../../utils/config').set; -// segment for future use -// const segment = require('../../utils/segment'); const config = { AUTH0_CLIENT_ID: 'iiEYK0KB30gj94mjB8HP9lhhTgae0Rg3', diff --git a/lib/plugins/logout/logout.js b/lib/plugins/logout/logout.js index 47f192cf1..dd561c1fa 100644 --- a/lib/plugins/logout/logout.js +++ b/lib/plugins/logout/logout.js @@ -1,7 +1,5 @@ 'use strict'; -// const getFrameworkId = require('../../utils/getFrameworkId'); -// const segment = require('../../utils/segment'); const userStats = require('../../utils/userStats'); const configUtils = require('../../utils/config'); diff --git a/lib/utils/config/index.js b/lib/utils/config/index.js index 0815e38bc..53906f08b 100644 --- a/lib/utils/config/index.js +++ b/lib/utils/config/index.js @@ -21,7 +21,7 @@ function createConfig() { meta: { created_at: Math.round(+new Date() / 1000), updated_at: null, - } + }, }; writeFileAtomic.sync(globalConfigPath, JSON.stringify(config, null, 2)); return JSON.parse(readFileSync(globalConfigPath)); @@ -77,9 +77,6 @@ function deleteConfigValue(key) { return config; } -// set local config value /project/.serverlessrc -// function setLocalConfig() {} - // set .serverlessrc config value function getConfigValue(objectPath) { const config = getConfig(); diff --git a/lib/utils/userStatsValidation.js b/lib/utils/userStatsValidation.js index 712915b85..677704e51 100644 --- a/lib/utils/userStatsValidation.js +++ b/lib/utils/userStatsValidation.js @@ -67,7 +67,6 @@ module.exports = function isValidEventName(eventName) { const project = matches[1]; const object = matches[2]; const action = matches[3]; - // console.log(`${project}:${object}_${action}`) // if missing any parts of event, exit; if (!project || !object || !action) { From 9dd5dc39f41aa93ded4fbb2a4f0ae582d877964a Mon Sep 17 00:00:00 2001 From: Philipp Muens Date: Wed, 24 May 2017 13:13:24 +0200 Subject: [PATCH 55/57] Update console.log statements and add file based eslint ignore comments --- lib/plugins/login/login.js | 3 ++- lib/plugins/logout/logout.js | 7 ++++--- lib/utils/openBrowser.js | 8 ++++---- lib/utils/userStats.js | 10 ++++++---- lib/utils/userStatsValidation.js | 31 ++++++++++++++++--------------- 5 files changed, 32 insertions(+), 27 deletions(-) diff --git a/lib/plugins/login/login.js b/lib/plugins/login/login.js index 0f30b990a..902164475 100644 --- a/lib/plugins/login/login.js +++ b/lib/plugins/login/login.js @@ -147,7 +147,8 @@ class Login { }); }) .catch(() => { - console.log(chalk.red('Incorrect token value supplied. Please run "serverless login" again')); // eslint-disable-line + this.serverless.cli.consoleLog( + chalk.red('Incorrect token value supplied. Please run "serverless login" again')); process.exit(0); }); }); diff --git a/lib/plugins/logout/logout.js b/lib/plugins/logout/logout.js index dd561c1fa..c362275bb 100644 --- a/lib/plugins/logout/logout.js +++ b/lib/plugins/logout/logout.js @@ -34,15 +34,16 @@ class Login { configUtils.set(`users.${currentId}.auth`, null); // log stat userStats.track('user_loggedOut').then(() => { - console.log('Successfully logged out.'); // eslint-disable-line + this.serverless.cli.consoleLog('Successfully logged out.'); process.exit(0); }); } else { - console.log('You are already logged out'); // eslint-disable-line + this.serverless.cli.consoleLog('You are already logged out'); } } } catch (e) { - console.log('Failed to logout. Please report bug in https://github.com/serverless/serverless/issues'); // eslint-disable-line + this.serverless.cli.consoleLog( + 'Failed to logout. Please report bug in https://github.com/serverless/serverless/issues'); // Note no need to wait for any connections e.g. segment to close process.exit(0); } diff --git a/lib/utils/openBrowser.js b/lib/utils/openBrowser.js index 88532f34c..bc419d194 100644 --- a/lib/utils/openBrowser.js +++ b/lib/utils/openBrowser.js @@ -1,18 +1,18 @@ 'use strict'; +/* eslint-disable no-console */ + const opn = require('opn'); const chalk = require('chalk'); const isDockerContainer = require('./isDockerContainer'); function displayManualOpenMessage(url) { - /* eslint-disable */ // https://github.com/sindresorhus/log-symbols console.log('---------------------------'); - console.log(`🙈 ${chalk.red("Unable to open browser automatically")}`); - console.log(chalk.green("Please open your browser & open the URL below to login:")); + console.log(`🙈 ${chalk.red('Unable to open browser automatically')}`); + console.log(chalk.green('Please open your browser & open the URL below to login:')); console.log(chalk.yellow(url)); console.log('---------------------------'); - /* eslint-enable */ return false; } diff --git a/lib/utils/userStats.js b/lib/utils/userStats.js index 059f5b253..962465e68 100644 --- a/lib/utils/userStats.js +++ b/lib/utils/userStats.js @@ -1,5 +1,7 @@ 'use strict'; +/* eslint-disable no-console */ + const BbPromise = require('bluebird'); const _ = require('lodash'); const fetch = require('node-fetch'); @@ -13,7 +15,7 @@ const IDENTIFY_URL = 'https://serverless.com/api/framework/identify'; const DEBUG = false; function debug() { - if (DEBUG) console.log(arguments); // eslint-disable-line + if (DEBUG) console.log(arguments); } /* note tracking swallows errors */ @@ -41,7 +43,7 @@ function track(eventName, payload) { // exit early if tracking disabled if (TRACKING_IS_DISABLED && !data.force) { - debug('abort .track call TRACKING_IS_DISABLED'); // eslint-disable-line + debug('abort .track call TRACKING_IS_DISABLED'); return BbPromise.resolve(); } @@ -90,14 +92,14 @@ function identify(payload) { const data = payload || {}; if (TRACKING_IS_DISABLED && !data.force) { if (DEBUG) { - console.log('abort .identify call'); // eslint-disable-line + console.log('abort .identify call'); } // exit early is tracking disabled return BbPromise.resolve(); } delete data.force; if (DEBUG) { - console.log('.identify call', data); // eslint-disable-line + console.log('.identify call', data); return BbPromise.resolve(); } return request(IDENTIFY_URL, data); diff --git a/lib/utils/userStatsValidation.js b/lib/utils/userStatsValidation.js index 677704e51..16693b5bc 100644 --- a/lib/utils/userStatsValidation.js +++ b/lib/utils/userStatsValidation.js @@ -1,5 +1,7 @@ 'use strict'; +/* eslint-disable no-console */ + /** * Validate Event names to keep data clean */ @@ -12,13 +14,14 @@ function containsSeparators(eventName) { const underscores = (eventName.match(/_/g) || []).length; const colons = (eventName.match(/:/g) || []).length; if (underscores !== 1) { - console.log(chalk.red('Tracking Error:')); // eslint-disable-line - console.log(chalk.red(`Event name must have single underscore. "${eventName}" contains ${underscores}`)); // eslint-disable-line + console.log(chalk.red('Tracking Error:')); + console.log( + chalk.red(`Event name must have single underscore. "${eventName}" contains ${underscores}`)); return false; } if (colons !== 1) { - console.log(chalk.red('Tracking Error:')); // eslint-disable-line - console.log(chalk.red(`Event name must have single colon. "${eventName}" contains ${colons}`)); // eslint-disable-line + console.log(chalk.red('Tracking Error:')); + console.log(chalk.red(`Event name must have single colon. "${eventName}" contains ${colons}`)); return false; } return true; @@ -28,8 +31,8 @@ function containsSeparators(eventName) { function isValidProject(project) { const isValid = VALID_TRACKING_PROJECTS.indexOf(project) !== -1; if (!isValid) { - console.log(chalk.red('Tracking Error:')); // eslint-disable-line - console.log(`"${project}" is invalid project. Must be one of`, VALID_TRACKING_PROJECTS); // eslint-disable-line + console.log(chalk.red('Tracking Error:')); + console.log(`"${project}" is invalid project. Must be one of`, VALID_TRACKING_PROJECTS); } return isValid; } @@ -38,22 +41,20 @@ function isValidProject(project) { function isValidObject(key) { const isValid = VALID_TRACKING_OBJECTS.indexOf(key) !== -1; if (!isValid) { - console.log(chalk.red('Tracking Error:')); // eslint-disable-line - console.log(`"${key}" is invalid tracking object. Must be one of`, VALID_TRACKING_OBJECTS); // eslint-disable-line + console.log(chalk.red('Tracking Error:')); + console.log(`"${key}" is invalid tracking object. Must be one of`, VALID_TRACKING_OBJECTS); } return isValid; } function formattingWarning(eventName) { - /*eslint-disable */ console.log(chalk.red(`Incorrect tracking event format: "${eventName}"`)); - console.log('Tracking event must match ' + chalk.yellow("product:objectName_actionName")); - console.log('It must be all camelCase: ' + chalk.yellow("camelCase:camelCase_camelCase")); - console.log('Here is an Example ' + chalk.green("framework:user_loggedIn")); - console.log('Note: `framework:` is automatically prepended'); - console.log('Usage:', chalk.yellow(`track('user_loggedIn', { ..extraData });`)); + console.log(`Tracking event must match ${chalk.yellow('product:objectName_actionName')}`); + console.log(`It must be all camelCase: ${chalk.yellow('camelCase:camelCase_camelCase')}`); + console.log(`Here is an Example ${chalk.green('framework:user_loggedIn')}`); + console.log('Note: "framework:" is automatically prepended'); + console.log(`Usage: ${chalk.yellow('track("user_loggedIn", { ..extraData });')}`); console.log('-----------------------------'); - /*eslint-enable */ return false; } From a66397427183c96dc603d843113615eb41b536e7 Mon Sep 17 00:00:00 2001 From: Philipp Muens Date: Wed, 24 May 2017 14:01:07 +0200 Subject: [PATCH 56/57] Fix broken Utils tests --- lib/classes/Utils.test.js | 120 ++++++++++++++++++-------------------- 1 file changed, 56 insertions(+), 64 deletions(-) diff --git a/lib/classes/Utils.test.js b/lib/classes/Utils.test.js index 6dd47b1be..d6ee6141f 100644 --- a/lib/classes/Utils.test.js +++ b/lib/classes/Utils.test.js @@ -6,21 +6,22 @@ const expect = require('chai').expect; const fse = require('fs-extra'); const fs = require('fs'); const sinon = require('sinon'); -const proxyquire = require('proxyquire'); const Serverless = require('../../lib/Serverless'); const testUtils = require('../../tests/utils'); const serverlessVersion = require('../../package.json').version; +const segment = require('../utils/segment'); +const proxyquire = require('proxyquire'); describe('Utils', () => { let utils; let serverless; - let fetchStub; + let isDockerContainerStub; let Utils; beforeEach(() => { - fetchStub = sinon.stub().resolves(); + isDockerContainerStub = sinon.stub().returns(true); Utils = proxyquire('../../lib/classes/Utils.js', { - 'node-fetch': fetchStub, + '../utils/isDockerContainer': isDockerContainerStub, }); serverless = new Serverless(); utils = new Utils(serverless); @@ -294,6 +295,7 @@ describe('Utils', () => { describe('#logStat()', () => { let serverlessDirPath; let homeDir; + let trackStub; beforeEach(() => { serverless.init(); @@ -313,6 +315,12 @@ describe('Utils', () => { // set the properties for the processed inputs serverless.processedInput.commands = []; serverless.processedInput.options = {}; + + trackStub = sinon.stub(segment, 'track'); + }); + + afterEach(() => { + segment.track.restore(); }); it('should resolve if a file called stats-disabled is present', () => { @@ -323,7 +331,7 @@ describe('Utils', () => { ); return utils.logStat(serverless).then(() => { - expect(fetchStub.calledOnce).to.equal(false); + expect(trackStub.calledOnce).to.equal(false); }); }); @@ -358,36 +366,23 @@ describe('Utils', () => { serverless.processedInput.options = options; return utils.logStat(serverless).then(() => { - expect(fetchStub.calledOnce).to.equal(true); - expect(fetchStub.args[0][0]).to.equal('https://api.segment.io/v1/track'); - expect(fetchStub.args[0][1].method).to.equal('POST'); - expect(fetchStub.args[0][1].timeout).to.equal('1000'); + expect(trackStub.calledOnce).to.equal(true); - const parsedBody = JSON.parse(fetchStub.args[0][1].body); + const data = trackStub.args[0][0]; - expect(parsedBody.properties.command.filteredOptions) - .to.deep.equal({ help: true }); + expect(data.properties.command.filteredOptions).to.deep.equal({ help: true }); }); }); - it('should be able to detect Docker containers', () => { - const cgroupFileContent = '6:devices:/docker/3601745b3bd54d9780436faa5f0e4f72'; - const cgroupFilePath = path.join('/', 'proc', '1', 'cgroup'); - const cgroupFileContentStub = sinon.stub(fs, 'readFileSync') - .withArgs(cgroupFilePath) - .returns(cgroupFileContent); + it('should be able to detect Docker containers', () => utils + .logStat(serverless).then(() => { + expect(isDockerContainerStub.calledOnce).to.equal(true); + expect(trackStub.calledOnce).to.equal(true); - utils.logStat(serverless).then(() => { - expect(cgroupFileContentStub.calledOnce).to.equal(true); - - const parsedBody = JSON.parse(fetchStub.args[0][1].body); - - expect(parsedBody.properties.general.isDockerContainer) - .to.equal(true); - - fs.readFileSync.restore(); - }); - }); + const data = trackStub.args[0][0]; + expect(data.properties.general.isDockerContainer).to.equal(true); + }) + ); it('should send the gathered information', () => { serverless.service = { @@ -436,55 +431,52 @@ describe('Utils', () => { }; return utils.logStat(serverless).then(() => { - expect(fetchStub.calledOnce).to.equal(true); - expect(fetchStub.args[0][0]).to.equal('https://api.segment.io/v1/track'); - expect(fetchStub.args[0][1].method).to.equal('POST'); - expect(fetchStub.args[0][1].timeout).to.equal('1000'); + expect(trackStub.calledOnce).to.equal(true); - const parsedBody = JSON.parse(fetchStub.args[0][1].body); + const data = trackStub.args[0][0]; - expect(parsedBody.userId.length).to.be.at.least(1); + expect(data.userId.length).to.be.at.least(1); // command property - expect(parsedBody.properties.command.name) + expect(data.properties.command.name) .to.equal(''); - expect(parsedBody.properties.command + expect(data.properties.command .isRunInService).to.equal(false); // false because CWD is not a service - expect(parsedBody.properties.command.filteredOptions) + expect(data.properties.command.filteredOptions) .to.deep.equal({}); // service property - expect(parsedBody.properties.service.numberOfCustomPlugins).to.equal(0); - expect(parsedBody.properties.service.hasCustomResourcesDefined).to.equal(true); - expect(parsedBody.properties.service.hasVariablesInCustomSectionDefined).to.equal(false); - expect(parsedBody.properties.service.hasCustomVariableSyntaxDefined).to.equal(true); + expect(data.properties.service.numberOfCustomPlugins).to.equal(0); + expect(data.properties.service.hasCustomResourcesDefined).to.equal(true); + expect(data.properties.service.hasVariablesInCustomSectionDefined).to.equal(false); + expect(data.properties.service.hasCustomVariableSyntaxDefined).to.equal(true); // functions property - expect(parsedBody.properties.functions.numberOfFunctions).to.equal(2); - expect(parsedBody.properties.functions.memorySizeAndTimeoutPerFunction[0] + expect(data.properties.functions.numberOfFunctions).to.equal(2); + expect(data.properties.functions.memorySizeAndTimeoutPerFunction[0] .memorySize).to.equal(1024); - expect(parsedBody.properties.functions.memorySizeAndTimeoutPerFunction[0] + expect(data.properties.functions.memorySizeAndTimeoutPerFunction[0] .timeout).to.equal(6); - expect(parsedBody.properties.functions.memorySizeAndTimeoutPerFunction[1] + expect(data.properties.functions.memorySizeAndTimeoutPerFunction[1] .memorySize).to.equal(16); - expect(parsedBody.properties.functions.memorySizeAndTimeoutPerFunction[1] + expect(data.properties.functions.memorySizeAndTimeoutPerFunction[1] .timeout).to.equal(200); // events property - expect(parsedBody.properties.events.numberOfEvents).to.equal(3); - expect(parsedBody.properties.events.numberOfEventsPerType[0].name).to.equal('http'); - expect(parsedBody.properties.events.numberOfEventsPerType[0].count).to.equal(2); - expect(parsedBody.properties.events.numberOfEventsPerType[1].name).to.equal('s3'); - expect(parsedBody.properties.events.numberOfEventsPerType[1].count).to.equal(1); - expect(parsedBody.properties.events.numberOfEventsPerType[2].name).to.equal('sns'); - expect(parsedBody.properties.events.numberOfEventsPerType[2].count).to.equal(1); - expect(parsedBody.properties.events.eventNamesPerFunction[0][0]).to.equal('http'); - expect(parsedBody.properties.events.eventNamesPerFunction[0][1]).to.equal('s3'); - expect(parsedBody.properties.events.eventNamesPerFunction[1][0]).to.equal('http'); - expect(parsedBody.properties.events.eventNamesPerFunction[1][1]).to.equal('sns'); + expect(data.properties.events.numberOfEvents).to.equal(3); + expect(data.properties.events.numberOfEventsPerType[0].name).to.equal('http'); + expect(data.properties.events.numberOfEventsPerType[0].count).to.equal(2); + expect(data.properties.events.numberOfEventsPerType[1].name).to.equal('s3'); + expect(data.properties.events.numberOfEventsPerType[1].count).to.equal(1); + expect(data.properties.events.numberOfEventsPerType[2].name).to.equal('sns'); + expect(data.properties.events.numberOfEventsPerType[2].count).to.equal(1); + expect(data.properties.events.eventNamesPerFunction[0][0]).to.equal('http'); + expect(data.properties.events.eventNamesPerFunction[0][1]).to.equal('s3'); + expect(data.properties.events.eventNamesPerFunction[1][0]).to.equal('http'); + expect(data.properties.events.eventNamesPerFunction[1][1]).to.equal('sns'); // general property - expect(parsedBody.properties.general.userId.length).to.be.at.least(1); - expect(parsedBody.properties.general.timestamp).to.match(/[0-9]+/); - expect(parsedBody.properties.general.timezone.length).to.be.at.least(1); - expect(parsedBody.properties.general.operatingSystem.length).to.be.at.least(1); - expect(parsedBody.properties.general.serverlessVersion).to.equal(serverlessVersion); - expect(parsedBody.properties.general.nodeJsVersion.length).to.be.at.least(1); + expect(data.properties.general.userId.length).to.be.at.least(1); + expect(data.properties.general.timestamp).to.match(/[0-9]+/); + expect(data.properties.general.timezone.length).to.be.at.least(1); + expect(data.properties.general.operatingSystem.length).to.be.at.least(1); + expect(data.properties.general.serverlessVersion).to.equal(serverlessVersion); + expect(data.properties.general.nodeJsVersion.length).to.be.at.least(1); }); }); From f9e3a99ca4be3c3e8f032e36d28fa32550761509 Mon Sep 17 00:00:00 2001 From: Philipp Muens Date: Wed, 24 May 2017 14:19:06 +0200 Subject: [PATCH 57/57] Shrinkwrapping --- npm-shrinkwrap.json | 2038 +++++++++++++++++++++++++++++-------------- 1 file changed, 1363 insertions(+), 675 deletions(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 68f5063d1..dce12a188 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -5,27 +5,32 @@ "abab": { "version": "1.0.3", "from": "abab@>=1.0.3 <2.0.0", - "resolved": "https://registry.npmjs.org/abab/-/abab-1.0.3.tgz" + "resolved": "https://registry.npmjs.org/abab/-/abab-1.0.3.tgz", + "dev": true }, "abbrev": { "version": "1.0.9", "from": "abbrev@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz" + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "dev": true }, "acorn": { "version": "5.0.3", "from": "acorn@>=5.0.1 <6.0.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.0.3.tgz" + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.0.3.tgz", + "dev": true }, "acorn-globals": { "version": "3.1.0", "from": "acorn-globals@>=3.1.0 <4.0.0", "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-3.1.0.tgz", + "dev": true, "dependencies": { "acorn": { - "version": "4.0.11", + "version": "4.0.13", "from": "acorn@>=4.0.4 <5.0.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.11.tgz" + "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", + "dev": true } } }, @@ -33,11 +38,13 @@ "version": "3.0.1", "from": "acorn-jsx@>=3.0.0 <4.0.0", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "dev": true, "dependencies": { "acorn": { "version": "3.3.0", "from": "acorn@>=3.0.4 <4.0.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz" + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "dev": true } } }, @@ -56,37 +63,43 @@ "ajv": { "version": "4.11.8", "from": "ajv@>=4.7.0 <5.0.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz" + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "dev": true }, "ajv-keywords": { "version": "1.5.1", "from": "ajv-keywords@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz" + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", + "dev": true }, "align-text": { "version": "0.1.4", "from": "align-text@>=0.1.3 <0.2.0", - "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz" + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "dev": true }, "amdefine": { "version": "1.0.1", "from": "amdefine@>=0.0.4", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "dev": true }, "ansi-escapes": { "version": "1.4.0", "from": "ansi-escapes@>=1.1.0 <2.0.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz" + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", + "dev": true }, "ansi-red": { "version": "0.1.1", "from": "ansi-red@>=0.1.1 <0.2.0", - "resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz" + "resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz", + "dev": true }, "ansi-regex": { - "version": "2.0.0", + "version": "2.1.1", "from": "ansi-regex@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz" }, "ansi-styles": { "version": "2.2.1", @@ -96,27 +109,30 @@ "ansi-wrap": { "version": "0.1.0", "from": "ansi-wrap@0.1.0", - "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz" + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "dev": true }, "ansicolors": { "version": "0.2.1", "from": "ansicolors@>=0.2.1 <0.3.0", - "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.2.1.tgz" + "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.2.1.tgz", + "dev": true }, "append-transform": { "version": "0.4.0", "from": "append-transform@>=0.4.0 <0.5.0", - "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-0.4.0.tgz" + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-0.4.0.tgz", + "dev": true }, "archiver": { - "version": "1.2.0", + "version": "1.3.0", "from": "archiver@>=1.1.0 <2.0.0", - "resolved": "https://registry.npmjs.org/archiver/-/archiver-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-1.3.0.tgz", "dependencies": { "async": { - "version": "2.1.4", + "version": "2.4.1", "from": "async@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/async/-/async-2.1.4.tgz" + "resolved": "https://registry.npmjs.org/async/-/async-2.4.1.tgz" } } }, @@ -133,17 +149,20 @@ "arr-diff": { "version": "2.0.0", "from": "arr-diff@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "dev": true }, "arr-flatten": { "version": "1.0.3", "from": "arr-flatten@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.0.3.tgz" + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.0.3.tgz", + "dev": true }, "array-equal": { "version": "1.0.0", "from": "array-equal@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", + "dev": true }, "array-union": { "version": "1.0.2", @@ -158,37 +177,44 @@ "array-unique": { "version": "0.2.1", "from": "array-unique@>=0.2.1 <0.3.0", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz" + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "dev": true }, "array.prototype.find": { "version": "2.0.4", "from": "array.prototype.find@>=2.0.1 <3.0.0", - "resolved": "https://registry.npmjs.org/array.prototype.find/-/array.prototype.find-2.0.4.tgz" + "resolved": "https://registry.npmjs.org/array.prototype.find/-/array.prototype.find-2.0.4.tgz", + "dev": true }, "arrify": { "version": "1.0.1", "from": "arrify@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "dev": true }, "asap": { "version": "2.0.5", "from": "asap@>=2.0.3 <2.1.0", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.5.tgz" + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.5.tgz", + "dev": true }, "asn1": { "version": "0.2.3", "from": "asn1@>=0.2.3 <0.3.0", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz" + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "dev": true }, "assert-plus": { "version": "0.2.0", "from": "assert-plus@>=0.2.0 <0.3.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz" + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "dev": true }, "assertion-error": { "version": "1.0.2", "from": "assertion-error@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.2.tgz", + "dev": true }, "async": { "version": "1.5.2", @@ -203,44 +229,50 @@ "autolinker": { "version": "0.15.3", "from": "autolinker@>=0.15.0 <0.16.0", - "resolved": "https://registry.npmjs.org/autolinker/-/autolinker-0.15.3.tgz" + "resolved": "https://registry.npmjs.org/autolinker/-/autolinker-0.15.3.tgz", + "dev": true }, "aws-sdk": { - "version": "2.7.13", - "from": "aws-sdk@>=2.3.17 <3.0.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.7.13.tgz", + "version": "2.56.0", + "from": "aws-sdk@>=2.7.13 <3.0.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.56.0.tgz", "dependencies": { "uuid": { - "version": "3.0.0", - "from": "uuid@3.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.0.0.tgz" + "version": "3.0.1", + "from": "uuid@3.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.0.1.tgz" } } }, "aws-sign2": { "version": "0.6.0", "from": "aws-sign2@>=0.6.0 <0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz" + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "dev": true }, "aws4": { "version": "1.6.0", "from": "aws4@>=1.2.1 <2.0.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz" + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "dev": true }, "babel-code-frame": { "version": "6.22.0", "from": "babel-code-frame@>=6.16.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz" + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz", + "dev": true }, "babel-core": { "version": "6.24.1", "from": "babel-core@>=6.0.0 <7.0.0", "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.24.1.tgz", + "dev": true, "dependencies": { "source-map": { "version": "0.5.6", "from": "source-map@>=0.5.0 <0.6.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz" + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", + "dev": true } } }, @@ -248,73 +280,87 @@ "version": "6.24.1", "from": "babel-generator@>=6.18.0 <7.0.0", "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.24.1.tgz", + "dev": true, "dependencies": { "source-map": { "version": "0.5.6", "from": "source-map@>=0.5.0 <0.6.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz" + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", + "dev": true } } }, "babel-helpers": { "version": "6.24.1", "from": "babel-helpers@>=6.24.1 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz" + "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", + "dev": true }, "babel-jest": { "version": "18.0.0", "from": "babel-jest@>=18.0.0 <19.0.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-18.0.0.tgz" + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-18.0.0.tgz", + "dev": true }, "babel-messages": { "version": "6.23.0", "from": "babel-messages@>=6.23.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz" + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "dev": true }, "babel-plugin-istanbul": { "version": "3.1.2", "from": "babel-plugin-istanbul@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-3.1.2.tgz" + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-3.1.2.tgz", + "dev": true }, "babel-plugin-jest-hoist": { "version": "18.0.0", "from": "babel-plugin-jest-hoist@>=18.0.0 <19.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-18.0.0.tgz" + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-18.0.0.tgz", + "dev": true }, "babel-preset-jest": { "version": "18.0.0", "from": "babel-preset-jest@>=18.0.0 <19.0.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-18.0.0.tgz" + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-18.0.0.tgz", + "dev": true }, "babel-register": { "version": "6.24.1", "from": "babel-register@>=6.24.1 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.24.1.tgz" + "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.24.1.tgz", + "dev": true }, "babel-runtime": { "version": "6.23.0", "from": "babel-runtime@>=6.22.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz" + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "dev": true }, "babel-template": { "version": "6.24.1", "from": "babel-template@>=6.16.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.24.1.tgz" + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.24.1.tgz", + "dev": true }, "babel-traverse": { "version": "6.24.1", "from": "babel-traverse@>=6.18.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.24.1.tgz" + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.24.1.tgz", + "dev": true }, "babel-types": { "version": "6.24.1", "from": "babel-types@>=6.18.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.24.1.tgz" + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.24.1.tgz", + "dev": true }, "babylon": { "version": "6.17.1", "from": "babylon@>=6.13.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.17.1.tgz" + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.17.1.tgz", + "dev": true }, "balanced-match": { "version": "0.4.2", @@ -329,66 +375,67 @@ "bcrypt-pbkdf": { "version": "1.0.1", "from": "bcrypt-pbkdf@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "dev": true, + "optional": true }, "bl": { - "version": "1.1.2", + "version": "1.2.1", "from": "bl@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.1.2.tgz", - "dependencies": { - "readable-stream": { - "version": "2.0.6", - "from": "readable-stream@>=2.0.5 <2.1.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz" - } - } + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.1.tgz" }, "bluebird": { - "version": "3.4.6", + "version": "3.5.0", "from": "bluebird@>=3.4.0 <4.0.0", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.6.tgz" + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.0.tgz" }, "boom": { "version": "2.10.1", "from": "boom@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz" + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "dev": true }, "brace-expansion": { - "version": "1.1.6", - "from": "brace-expansion@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz" + "version": "1.1.7", + "from": "brace-expansion@>=1.1.7 <2.0.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.7.tgz" }, "braces": { "version": "1.8.5", "from": "braces@>=1.8.2 <2.0.0", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz" + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "dev": true }, "browser-resolve": { "version": "1.11.2", "from": "browser-resolve@>=1.11.2 <2.0.0", "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.2.tgz", + "dev": true, "dependencies": { "resolve": { "version": "1.1.7", "from": "resolve@1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz" + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "dev": true } } }, "browser-stdout": { "version": "1.3.0", "from": "browser-stdout@1.3.0", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz" + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", + "dev": true }, "bser": { "version": "1.0.2", "from": "bser@1.0.2", - "resolved": "https://registry.npmjs.org/bser/-/bser-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/bser/-/bser-1.0.2.tgz", + "dev": true }, "buffer": { - "version": "4.9.1", - "from": "buffer@4.9.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz" + "version": "5.0.6", + "from": "buffer@5.0.6", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.0.6.tgz" }, "buffer-crc32": { "version": "0.2.13", @@ -397,33 +444,39 @@ }, "buffer-shims": { "version": "1.0.0", - "from": "buffer-shims@>=1.0.0 <2.0.0", + "from": "buffer-shims@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz" }, "builtin-modules": { "version": "1.1.1", "from": "builtin-modules@>=1.1.1 <2.0.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz" + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "dev": true }, "caller-id": { "version": "0.1.0", "from": "caller-id@>=0.1.0 <0.2.0", - "resolved": "https://registry.npmjs.org/caller-id/-/caller-id-0.1.0.tgz" + "resolved": "https://registry.npmjs.org/caller-id/-/caller-id-0.1.0.tgz", + "dev": true }, "caller-path": { "version": "0.1.0", "from": "caller-path@>=0.1.0 <0.2.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz" + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "dev": true }, "callsites": { "version": "0.2.0", "from": "callsites@>=0.2.0 <0.3.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz" + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "dev": true }, "camelcase": { "version": "1.2.1", "from": "camelcase@>=1.0.2 <2.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz" + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "dev": true, + "optional": true }, "capture-stack-trace": { "version": "1.0.0", @@ -433,12 +486,14 @@ "cardinal": { "version": "1.0.0", "from": "cardinal@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-1.0.0.tgz", + "dev": true }, "caseless": { "version": "0.11.0", "from": "caseless@>=0.11.0 <0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz" + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", + "dev": true }, "caw": { "version": "2.0.0", @@ -448,7 +503,21 @@ "center-align": { "version": "0.1.3", "from": "center-align@>=0.1.1 <0.2.0", - "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz" + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "dev": true, + "optional": true + }, + "chai": { + "version": "3.5.0", + "from": "chai@>=3.5.0 <4.0.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", + "dev": true + }, + "chai-as-promised": { + "version": "6.0.0", + "from": "chai-as-promised@>=6.0.0 <7.0.0", + "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-6.0.0.tgz", + "dev": true }, "chalk": { "version": "1.1.3", @@ -458,7 +527,8 @@ "check-error": { "version": "1.0.2", "from": "check-error@>=1.0.2 <2.0.0", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "dev": true }, "ci-info": { "version": "1.0.0", @@ -468,59 +538,72 @@ "circular-json": { "version": "0.3.1", "from": "circular-json@>=0.3.1 <0.4.0", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.1.tgz" + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.1.tgz", + "dev": true }, "cli-cursor": { "version": "1.0.2", "from": "cli-cursor@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "dev": true }, "cli-table": { "version": "0.3.1", "from": "cli-table@>=0.3.1 <0.4.0", - "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz" + "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz", + "dev": true }, "cli-usage": { "version": "0.1.4", "from": "cli-usage@>=0.1.1 <0.2.0", - "resolved": "https://registry.npmjs.org/cli-usage/-/cli-usage-0.1.4.tgz" + "resolved": "https://registry.npmjs.org/cli-usage/-/cli-usage-0.1.4.tgz", + "dev": true }, "cli-width": { "version": "2.1.0", "from": "cli-width@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.1.0.tgz" + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.1.0.tgz", + "dev": true }, "cliui": { "version": "2.1.0", "from": "cliui@>=2.1.0 <3.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "dev": true, + "optional": true, "dependencies": { "wordwrap": { "version": "0.0.2", "from": "wordwrap@0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz" + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "dev": true, + "optional": true } } }, "co": { "version": "4.6.0", "from": "co@>=4.6.0 <5.0.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz" + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "dev": true }, "code-point-at": { "version": "1.1.0", "from": "code-point-at@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz" + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "dev": true }, "coffee-script": { "version": "1.12.6", "from": "coffee-script@>=1.12.4 <2.0.0", - "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.6.tgz" + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.6.tgz", + "dev": true }, "colors": { "version": "1.0.3", "from": "colors@1.0.3", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz" + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "dev": true }, "combined-stream": { "version": "1.0.5", @@ -534,13 +617,13 @@ }, "component-emitter": { "version": "1.2.1", - "from": "component-emitter@>=1.2.0 <1.3.0", + "from": "component-emitter@>=1.2.0 <2.0.0", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz" }, "compress-commons": { - "version": "1.1.0", + "version": "1.2.0", "from": "compress-commons@>=1.1.0 <2.0.0", - "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-1.1.0.tgz" + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-1.2.0.tgz" }, "concat-map": { "version": "0.0.1", @@ -550,42 +633,72 @@ "concat-stream": { "version": "1.6.0", "from": "concat-stream@>=1.5.2 <2.0.0", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz" + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", + "dev": true }, "contains-path": { "version": "0.1.0", "from": "contains-path@>=0.1.0 <0.2.0", - "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz" + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "dev": true }, "content-type-parser": { "version": "1.0.1", "from": "content-type-parser@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/content-type-parser/-/content-type-parser-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/content-type-parser/-/content-type-parser-1.0.1.tgz", + "dev": true }, "convert-source-map": { "version": "1.5.0", "from": "convert-source-map@>=1.1.0 <2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.0.tgz" + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.0.tgz", + "dev": true }, "cookiejar": { - "version": "2.0.6", - "from": "cookiejar@2.0.6", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.0.6.tgz" + "version": "2.1.1", + "from": "cookiejar@>=2.0.6 <3.0.0", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.1.tgz" }, "core-js": { "version": "2.4.1", "from": "core-js@>=2.4.0 <3.0.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.4.1.tgz" + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.4.1.tgz", + "dev": true }, "core-util-is": { "version": "1.0.2", "from": "core-util-is@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" }, + "coveralls": { + "version": "2.13.1", + "from": "coveralls@>=2.12.0 <3.0.0", + "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-2.13.1.tgz", + "dev": true, + "dependencies": { + "esprima": { + "version": "2.7.3", + "from": "esprima@>=2.6.0 <3.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "dev": true + }, + "js-yaml": { + "version": "3.6.1", + "from": "js-yaml@3.6.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.6.1.tgz", + "dev": true + } + } + }, + "crc": { + "version": "3.4.4", + "from": "crc@>=3.4.4 <4.0.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.4.tgz" + }, "crc32-stream": { - "version": "1.0.0", - "from": "crc32-stream@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-1.0.0.tgz" + "version": "2.0.0", + "from": "crc32-stream@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-2.0.0.tgz" }, "create-error-class": { "version": "3.0.2", @@ -595,7 +708,8 @@ "cryptiles": { "version": "2.0.5", "from": "cryptiles@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz" + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "dev": true }, "crypto-browserify": { "version": "1.0.9", @@ -605,49 +719,56 @@ "cssom": { "version": "0.3.2", "from": "cssom@>=0.3.2 <0.4.0", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.2.tgz" + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.2.tgz", + "dev": true }, "cssstyle": { "version": "0.2.37", "from": "cssstyle@>=0.2.37 <0.3.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-0.2.37.tgz" + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-0.2.37.tgz", + "dev": true }, "d": { "version": "1.0.0", "from": "d@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", + "dev": true }, "damerau-levenshtein": { "version": "1.0.4", "from": "damerau-levenshtein@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.4.tgz" + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.4.tgz", + "dev": true }, "dashdash": { "version": "1.14.1", "from": "dashdash@>=1.12.0 <2.0.0", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "dev": true, "dependencies": { "assert-plus": { "version": "1.0.0", "from": "assert-plus@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "dev": true } } }, "debug": { - "version": "2.3.3", + "version": "2.6.8", "from": "debug@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz" + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz" }, "decamelize": { "version": "1.2.0", "from": "decamelize@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz" + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "dev": true }, "decompress": { - "version": "4.0.0", + "version": "4.2.0", "from": "decompress@>=4.0.0 <5.0.0", - "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.0.0.tgz" + "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.0.tgz" }, "decompress-tar": { "version": "4.1.0", @@ -660,68 +781,91 @@ "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.0.tgz" }, "decompress-targz": { - "version": "4.0.0", + "version": "4.1.0", "from": "decompress-targz@>=4.0.0 <5.0.0", - "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.0.0.tgz" + "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.0.tgz", + "dependencies": { + "file-type": { + "version": "4.3.0", + "from": "file-type@>=4.3.0 <5.0.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-4.3.0.tgz" + } + } }, "decompress-unzip": { "version": "4.0.1", "from": "decompress-unzip@>=4.0.1 <5.0.0", - "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz" + "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz", + "dependencies": { + "get-stream": { + "version": "2.3.1", + "from": "get-stream@>=2.2.0 <3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz" + } + } }, "deep-eql": { "version": "0.1.3", "from": "deep-eql@>=0.1.3 <0.2.0", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", + "dev": true, "dependencies": { "type-detect": { "version": "0.1.1", "from": "type-detect@0.1.1", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz" + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", + "dev": true } } }, "deep-extend": { - "version": "0.4.1", + "version": "0.4.2", "from": "deep-extend@>=0.4.0 <0.5.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.1.tgz" + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz" }, "deep-is": { "version": "0.1.3", "from": "deep-is@>=0.1.3 <0.2.0", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz" + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "dev": true }, "deepmerge": { "version": "1.3.2", "from": "deepmerge@>=1.3.0 <2.0.0", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-1.3.2.tgz" + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-1.3.2.tgz", + "dev": true }, "default-require-extensions": { "version": "1.0.0", "from": "default-require-extensions@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-1.0.0.tgz", + "dev": true, "dependencies": { "strip-bom": { "version": "2.0.0", "from": "strip-bom@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "dev": true } } }, "define-properties": { "version": "1.1.2", "from": "define-properties@>=1.1.2 <2.0.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz" + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", + "dev": true }, "del": { "version": "2.2.2", "from": "del@>=2.0.2 <3.0.0", "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "dev": true, "dependencies": { "globby": { "version": "5.0.0", "from": "globby@>=5.0.0 <6.0.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz" + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "dev": true } } }, @@ -733,27 +877,31 @@ "detect-indent": { "version": "4.0.0", "from": "detect-indent@>=4.0.0 <5.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz" + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "dev": true }, "diacritics-map": { "version": "0.1.0", "from": "diacritics-map@>=0.1.0 <0.2.0", - "resolved": "https://registry.npmjs.org/diacritics-map/-/diacritics-map-0.1.0.tgz" + "resolved": "https://registry.npmjs.org/diacritics-map/-/diacritics-map-0.1.0.tgz", + "dev": true }, "diff": { "version": "3.2.0", "from": "diff@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz" + "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", + "dev": true }, "doctrine": { "version": "2.0.0", "from": "doctrine@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.0.0.tgz", + "dev": true }, "download": { - "version": "5.0.2", + "version": "5.0.3", "from": "download@>=5.0.2 <6.0.0", - "resolved": "https://registry.npmjs.org/download/-/download-5.0.2.tgz" + "resolved": "https://registry.npmjs.org/download/-/download-5.0.3.tgz" }, "duplexer3": { "version": "0.1.4", @@ -763,7 +911,9 @@ "ecc-jsbn": { "version": "0.1.1", "from": "ecc-jsbn@>=0.1.1 <0.2.0", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz" + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "dev": true, + "optional": true }, "encoding": { "version": "0.1.12", @@ -771,71 +921,75 @@ "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz" }, "end-of-stream": { - "version": "1.1.0", + "version": "1.4.0", "from": "end-of-stream@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.1.0.tgz", - "dependencies": { - "once": { - "version": "1.3.3", - "from": "once@>=1.3.0 <1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz" - } - } + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.0.tgz" }, "errno": { "version": "0.1.4", "from": "errno@>=0.1.1 <0.2.0-0", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.4.tgz" + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.4.tgz", + "dev": true }, "error-ex": { "version": "1.3.1", "from": "error-ex@>=1.2.0 <2.0.0", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz" + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "dev": true }, "es-abstract": { "version": "1.7.0", "from": "es-abstract@>=1.7.0 <2.0.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.7.0.tgz" + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.7.0.tgz", + "dev": true }, "es-to-primitive": { "version": "1.1.1", "from": "es-to-primitive@>=1.1.1 <2.0.0", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz" + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz", + "dev": true }, "es5-ext": { - "version": "0.10.18", + "version": "0.10.21", "from": "es5-ext@>=0.10.14 <0.11.0", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.18.tgz" + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.21.tgz", + "dev": true }, "es6-iterator": { "version": "2.0.1", "from": "es6-iterator@>=2.0.1 <2.1.0", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.1.tgz" + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.1.tgz", + "dev": true }, "es6-map": { "version": "0.1.5", "from": "es6-map@>=0.1.3 <0.2.0", - "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz" + "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", + "dev": true }, "es6-promise": { "version": "3.0.2", "from": "es6-promise@>=3.0.2 <3.1.0", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz" + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz", + "dev": true }, "es6-set": { "version": "0.1.5", "from": "es6-set@>=0.1.5 <0.2.0", - "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz" + "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", + "dev": true }, "es6-symbol": { "version": "3.1.1", "from": "es6-symbol@>=3.1.1 <3.2.0", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz" + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "dev": true }, "es6-weak-map": { "version": "2.0.2", "from": "es6-weak-map@>=2.0.1 <3.0.0", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz" + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", + "dev": true }, "escape-string-regexp": { "version": "1.0.5", @@ -846,120 +1000,201 @@ "version": "1.8.1", "from": "escodegen@>=1.8.0 <1.9.0", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", + "dev": true, "dependencies": { + "esprima": { + "version": "2.7.3", + "from": "esprima@>=2.7.1 <3.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "dev": true + }, "estraverse": { "version": "1.9.3", "from": "estraverse@>=1.9.1 <2.0.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz" + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "dev": true } } }, "escope": { "version": "3.6.0", "from": "escope@>=3.6.0 <4.0.0", - "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz" + "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", + "dev": true + }, + "eslint": { + "version": "3.19.0", + "from": "eslint@>=3.3.1 <4.0.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-3.19.0.tgz", + "dev": true, + "dependencies": { + "shelljs": { + "version": "0.7.7", + "from": "shelljs@>=0.7.5 <0.8.0", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.7.tgz", + "dev": true + } + } + }, + "eslint-config-airbnb": { + "version": "10.0.1", + "from": "eslint-config-airbnb@>=10.0.1 <11.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-10.0.1.tgz", + "dev": true }, "eslint-config-airbnb-base": { "version": "5.0.3", "from": "eslint-config-airbnb-base@>=5.0.2 <6.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-5.0.3.tgz" + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-5.0.3.tgz", + "dev": true }, "eslint-import-resolver-node": { "version": "0.2.3", "from": "eslint-import-resolver-node@>=0.2.0 <0.3.0", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.2.3.tgz" + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.2.3.tgz", + "dev": true + }, + "eslint-plugin-import": { + "version": "1.16.0", + "from": "eslint-plugin-import@>=1.13.0 <2.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-1.16.0.tgz", + "dev": true, + "dependencies": { + "doctrine": { + "version": "1.3.0", + "from": "doctrine@>=1.3.0 <1.4.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.3.0.tgz", + "dev": true + } + } + }, + "eslint-plugin-jsx-a11y": { + "version": "2.2.3", + "from": "eslint-plugin-jsx-a11y@>=2.1.0 <3.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-2.2.3.tgz", + "dev": true + }, + "eslint-plugin-react": { + "version": "6.10.3", + "from": "eslint-plugin-react@>=6.1.1 <7.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-6.10.3.tgz", + "dev": true, + "dependencies": { + "doctrine": { + "version": "1.5.0", + "from": "doctrine@>=1.2.2 <2.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "dev": true + } + } }, "espree": { "version": "3.4.3", "from": "espree@>=3.4.0 <4.0.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-3.4.3.tgz" + "resolved": "https://registry.npmjs.org/espree/-/espree-3.4.3.tgz", + "dev": true }, "esprima": { - "version": "2.7.3", - "from": "esprima@>=2.6.0 <3.0.0", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz" + "version": "3.1.3", + "from": "esprima@>=3.1.1 <4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz" }, "esquery": { "version": "1.0.0", "from": "esquery@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz", + "dev": true }, "esrecurse": { "version": "4.1.0", "from": "esrecurse@>=4.1.0 <5.0.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.1.0.tgz", + "dev": true, "dependencies": { "estraverse": { "version": "4.1.1", "from": "estraverse@>=4.1.0 <4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.1.1.tgz" + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.1.1.tgz", + "dev": true } } }, "estraverse": { "version": "4.2.0", "from": "estraverse@>=4.2.0 <5.0.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz" + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "dev": true }, "esutils": { "version": "2.0.2", "from": "esutils@>=2.0.2 <3.0.0", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz" + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "dev": true }, "event-emitter": { "version": "0.3.5", "from": "event-emitter@>=0.3.5 <0.4.0", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz" + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "dev": true }, "exec-sh": { "version": "0.2.0", "from": "exec-sh@>=0.2.0 <0.3.0", - "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.2.0.tgz" + "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.2.0.tgz", + "dev": true }, "exit-hook": { "version": "1.1.1", "from": "exit-hook@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz" + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", + "dev": true }, "expand-brackets": { "version": "0.1.5", "from": "expand-brackets@>=0.1.4 <0.2.0", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz" + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "dev": true }, "expand-range": { "version": "1.8.2", "from": "expand-range@>=1.8.1 <2.0.0", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz" + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "dev": true }, "extend": { - "version": "3.0.0", + "version": "3.0.1", "from": "extend@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz" + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz" }, "extend-shallow": { "version": "2.0.1", "from": "extend-shallow@>=2.0.1 <3.0.0", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz" + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "dev": true }, "extglob": { "version": "0.3.2", "from": "extglob@>=0.3.1 <0.4.0", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz" + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "dev": true }, "extsprintf": { "version": "1.0.2", "from": "extsprintf@1.0.2", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz", + "dev": true }, "fast-levenshtein": { "version": "2.0.6", "from": "fast-levenshtein@>=2.0.4 <2.1.0", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz" + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "dev": true }, "fb-watchman": { "version": "1.9.2", "from": "fb-watchman@>=1.9.0 <2.0.0", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-1.9.2.tgz" + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-1.9.2.tgz", + "dev": true }, "fd-slicer": { "version": "1.0.1", @@ -969,12 +1204,14 @@ "figures": { "version": "1.7.0", "from": "figures@>=1.3.5 <2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz" + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "dev": true }, "file-entry-cache": { "version": "2.0.0", "from": "file-entry-cache@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "dev": true }, "file-type": { "version": "3.9.0", @@ -984,82 +1221,93 @@ "filename-regex": { "version": "2.0.1", "from": "filename-regex@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz" + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "dev": true }, "filename-reserved-regex": { - "version": "1.0.0", - "from": "filename-reserved-regex@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-1.0.0.tgz" + "version": "2.0.0", + "from": "filename-reserved-regex@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz" }, "filenamify": { - "version": "1.2.1", - "from": "filenamify@>=1.2.1 <2.0.0", - "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-1.2.1.tgz" + "version": "2.0.0", + "from": "filenamify@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-2.0.0.tgz" }, "fileset": { "version": "2.0.3", "from": "fileset@>=2.0.2 <3.0.0", - "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz" + "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz", + "dev": true }, "filesize": { - "version": "3.3.0", + "version": "3.5.10", "from": "filesize@>=3.3.0 <4.0.0", - "resolved": "https://registry.npmjs.org/filesize/-/filesize-3.3.0.tgz" + "resolved": "https://registry.npmjs.org/filesize/-/filesize-3.5.10.tgz" }, "fill-keys": { "version": "1.0.2", "from": "fill-keys@>=1.0.2 <2.0.0", - "resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz", + "dev": true }, "fill-range": { "version": "2.2.3", "from": "fill-range@>=2.1.0 <3.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz" + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", + "dev": true }, "find-up": { "version": "1.1.2", "from": "find-up@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz" + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "dev": true }, "flat-cache": { "version": "1.2.2", "from": "flat-cache@>=1.2.1 <2.0.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.2.2.tgz" + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.2.2.tgz", + "dev": true }, "for-in": { "version": "1.0.2", "from": "for-in@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "dev": true }, "for-own": { "version": "0.1.5", "from": "for-own@>=0.1.4 <0.2.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz" + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "dev": true }, "foreach": { "version": "2.0.5", "from": "foreach@>=2.0.5 <3.0.0", - "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz" + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "dev": true }, "forever-agent": { "version": "0.6.1", "from": "forever-agent@>=0.6.1 <0.7.0", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz" + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "dev": true }, "form-data": { - "version": "1.0.0-rc3", - "from": "form-data@1.0.0-rc3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-1.0.0-rc3.tgz" + "version": "2.1.4", + "from": "form-data@>=2.1.1 <3.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz" }, "formatio": { "version": "1.1.1", "from": "formatio@1.1.1", - "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.1.1.tgz" + "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.1.1.tgz", + "dev": true }, "formidable": { - "version": "1.0.17", - "from": "formidable@>=1.0.14 <1.1.0", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.0.17.tgz" + "version": "1.1.1", + "from": "formidable@>=1.1.1 <2.0.0", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.1.1.tgz" }, "fs-extra": { "version": "0.26.7", @@ -1074,22 +1322,26 @@ "function-bind": { "version": "1.1.0", "from": "function-bind@>=1.0.2 <2.0.0", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.0.tgz" + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.0.tgz", + "dev": true }, "generate-function": { "version": "2.0.0", "from": "generate-function@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", + "dev": true }, "generate-object-property": { "version": "1.2.0", "from": "generate-object-property@>=1.1.0 <2.0.0", - "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz" + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "dev": true }, "get-caller-file": { "version": "1.0.2", "from": "get-caller-file@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", + "dev": true }, "get-proxy": { "version": "1.1.0", @@ -1102,41 +1354,46 @@ "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz" }, "get-stream": { - "version": "2.3.1", - "from": "get-stream@>=2.2.0 <3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz" + "version": "3.0.0", + "from": "get-stream@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz" }, "getpass": { "version": "0.1.7", "from": "getpass@>=0.1.1 <0.2.0", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "dev": true, "dependencies": { "assert-plus": { "version": "1.0.0", "from": "assert-plus@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "dev": true } } }, "glob": { - "version": "7.1.1", + "version": "7.1.2", "from": "glob@>=7.0.0 <8.0.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz" + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz" }, "glob-base": { "version": "0.3.0", "from": "glob-base@>=0.3.0 <0.4.0", - "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz" + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "dev": true }, "glob-parent": { "version": "2.0.0", "from": "glob-parent@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "dev": true }, "globals": { "version": "9.17.0", "from": "globals@>=9.14.0 <10.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-9.17.0.tgz" + "resolved": "https://registry.npmjs.org/globals/-/globals-9.17.0.tgz", + "dev": true }, "globby": { "version": "6.1.0", @@ -1144,9 +1401,9 @@ "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz" }, "got": { - "version": "6.6.3", + "version": "6.7.1", "from": "got@>=6.3.0 <7.0.0", - "resolved": "https://registry.npmjs.org/got/-/got-6.6.3.tgz" + "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz" }, "graceful-fs": { "version": "4.1.11", @@ -1158,42 +1415,40 @@ "from": "graceful-readlink@>=1.0.0", "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz" }, + "graphlib": { + "version": "2.1.1", + "from": "graphlib@>=2.1.1 <3.0.0", + "resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.1.tgz" + }, "gray-matter": { "version": "2.1.1", "from": "gray-matter@>=2.1.0 <3.0.0", "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-2.1.1.tgz", - "dependencies": { - "esprima": { - "version": "3.1.3", - "from": "esprima@>=3.1.1 <4.0.0", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz" - }, - "js-yaml": { - "version": "3.8.4", - "from": "js-yaml@>=3.8.1 <4.0.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.8.4.tgz" - } - } + "dev": true }, "growl": { "version": "1.9.2", "from": "growl@1.9.2", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz" + "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", + "dev": true }, "growly": { "version": "1.3.0", "from": "growly@>=1.2.0 <2.0.0", - "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz" + "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", + "dev": true }, "handlebars": { - "version": "4.0.8", + "version": "4.0.10", "from": "handlebars@>=4.0.1 <5.0.0", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.8.tgz", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.10.tgz", + "dev": true, "dependencies": { "source-map": { "version": "0.4.4", "from": "source-map@>=0.4.4 <0.5.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz" + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "dev": true } } }, @@ -1201,18 +1456,21 @@ "version": "2.0.6", "from": "har-validator@>=2.0.6 <2.1.0", "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", + "dev": true, "dependencies": { "commander": { "version": "2.9.0", "from": "commander@>=2.9.0 <3.0.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz" + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "dev": true } } }, "has": { "version": "1.0.1", "from": "has@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", + "dev": true }, "has-ansi": { "version": "2.0.0", @@ -1222,47 +1480,56 @@ "has-flag": { "version": "1.0.0", "from": "has-flag@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "dev": true }, "hawk": { "version": "3.1.3", "from": "hawk@>=3.1.3 <3.2.0", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz" + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "dev": true }, "hoek": { "version": "2.16.3", "from": "hoek@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz" + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "dev": true }, "home-or-tmp": { "version": "2.0.0", "from": "home-or-tmp@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", + "dev": true }, "hosted-git-info": { "version": "2.4.2", "from": "hosted-git-info@>=2.1.4 <3.0.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.4.2.tgz" + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.4.2.tgz", + "dev": true }, "html-encoding-sniffer": { "version": "1.0.1", "from": "html-encoding-sniffer@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.1.tgz", + "dev": true }, "http-basic": { "version": "2.5.1", "from": "http-basic@>=2.5.1 <3.0.0", - "resolved": "https://registry.npmjs.org/http-basic/-/http-basic-2.5.1.tgz" + "resolved": "https://registry.npmjs.org/http-basic/-/http-basic-2.5.1.tgz", + "dev": true }, "http-response-object": { "version": "1.1.0", "from": "http-response-object@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/http-response-object/-/http-response-object-1.1.0.tgz" + "resolved": "https://registry.npmjs.org/http-response-object/-/http-response-object-1.1.0.tgz", + "dev": true }, "http-signature": { "version": "1.1.1", "from": "http-signature@>=1.1.0 <1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz" + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "dev": true }, "https-proxy-agent": { "version": "1.0.0", @@ -1270,9 +1537,9 @@ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz" }, "iconv-lite": { - "version": "0.4.15", + "version": "0.4.17", "from": "iconv-lite@>=0.4.13 <0.5.0", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz" + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.17.tgz" }, "ieee754": { "version": "1.1.8", @@ -1280,14 +1547,16 @@ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz" }, "ignore": { - "version": "3.3.0", + "version": "3.3.3", "from": "ignore@>=3.2.0 <4.0.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.0.tgz" + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.3.tgz", + "dev": true }, "immediate": { "version": "3.0.6", "from": "immediate@>=3.0.5 <3.1.0", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz" + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "dev": true }, "imurmurhash": { "version": "0.1.4", @@ -1312,147 +1581,169 @@ "inquirer": { "version": "0.12.0", "from": "inquirer@>=0.12.0 <0.13.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz" + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", + "dev": true }, "interpret": { "version": "1.0.3", "from": "interpret@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.3.tgz" + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.3.tgz", + "dev": true }, "invariant": { "version": "2.2.2", "from": "invariant@>=2.2.0 <3.0.0", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz" + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz", + "dev": true }, "invert-kv": { "version": "1.0.0", "from": "invert-kv@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz" - }, - "is-absolute": { - "version": "0.1.7", - "from": "is-absolute@>=0.1.5 <0.2.0", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-0.1.7.tgz" + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "dev": true }, "is-arrayish": { "version": "0.2.1", "from": "is-arrayish@>=0.2.1 <0.3.0", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz" + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "dev": true }, "is-buffer": { "version": "1.1.5", "from": "is-buffer@>=1.1.5 <2.0.0", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz" + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", + "dev": true }, "is-builtin-module": { "version": "1.0.0", "from": "is-builtin-module@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "dev": true }, "is-callable": { "version": "1.1.3", "from": "is-callable@>=1.1.3 <2.0.0", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz" + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz", + "dev": true }, "is-ci": { "version": "1.0.10", "from": "is-ci@>=1.0.9 <2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.0.10.tgz" + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.0.10.tgz", + "dev": true }, "is-date-object": { "version": "1.0.1", "from": "is-date-object@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "dev": true }, "is-dotfile": { "version": "1.0.2", "from": "is-dotfile@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.2.tgz", + "dev": true }, "is-equal-shallow": { "version": "0.1.3", "from": "is-equal-shallow@>=0.1.3 <0.2.0", - "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz" + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "dev": true }, "is-extendable": { "version": "0.1.1", "from": "is-extendable@>=0.1.1 <0.2.0", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz" + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "dev": true }, "is-extglob": { "version": "1.0.0", "from": "is-extglob@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "dev": true }, "is-finite": { "version": "1.0.2", "from": "is-finite@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "dev": true }, "is-fullwidth-code-point": { "version": "1.0.0", "from": "is-fullwidth-code-point@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "dev": true }, "is-glob": { "version": "2.0.1", "from": "is-glob@>=2.0.1 <3.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz" + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "dev": true }, "is-local-path": { "version": "0.1.6", "from": "is-local-path@>=0.1.6 <0.2.0", - "resolved": "https://registry.npmjs.org/is-local-path/-/is-local-path-0.1.6.tgz" + "resolved": "https://registry.npmjs.org/is-local-path/-/is-local-path-0.1.6.tgz", + "dev": true }, "is-my-json-valid": { "version": "2.16.0", "from": "is-my-json-valid@>=2.12.4 <3.0.0", - "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.0.tgz" + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.0.tgz", + "dev": true }, "is-natural-number": { - "version": "2.1.1", - "from": "is-natural-number@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-2.1.1.tgz" + "version": "4.0.1", + "from": "is-natural-number@>=4.0.1 <5.0.0", + "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz" }, "is-number": { "version": "2.1.0", "from": "is-number@>=2.1.0 <3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz" + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "dev": true }, "is-object": { "version": "1.0.1", "from": "is-object@>=1.0.1 <1.1.0", - "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", + "dev": true }, "is-path-cwd": { "version": "1.0.0", "from": "is-path-cwd@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "dev": true }, "is-path-in-cwd": { "version": "1.0.0", "from": "is-path-in-cwd@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", + "dev": true }, "is-path-inside": { "version": "1.0.0", "from": "is-path-inside@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz", + "dev": true }, "is-posix-bracket": { "version": "0.1.1", "from": "is-posix-bracket@>=0.1.0 <0.2.0", - "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz" + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "dev": true }, "is-primitive": { "version": "2.0.0", "from": "is-primitive@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "dev": true }, "is-property": { "version": "1.0.2", "from": "is-property@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "dev": true }, "is-redirect": { "version": "1.0.0", @@ -1462,17 +1753,14 @@ "is-regex": { "version": "1.0.4", "from": "is-regex@>=1.0.3 <2.0.0", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz" - }, - "is-relative": { - "version": "0.1.3", - "from": "is-relative@>=0.1.0 <0.2.0", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-0.1.3.tgz" + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "dev": true }, "is-resolvable": { "version": "1.0.0", "from": "is-resolvable@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz", + "dev": true }, "is-retry-allowed": { "version": "1.1.0", @@ -1487,17 +1775,20 @@ "is-symbol": { "version": "1.0.1", "from": "is-symbol@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", + "dev": true }, "is-typedarray": { "version": "1.0.0", "from": "is-typedarray@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "dev": true }, "is-utf8": { "version": "0.2.1", "from": "is-utf8@>=0.2.0 <0.3.0", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz" + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "dev": true }, "is-wsl": { "version": "1.1.0", @@ -1512,54 +1803,96 @@ "isexe": { "version": "2.0.0", "from": "isexe@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "dev": true }, "isobject": { "version": "2.1.0", "from": "isobject@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz" + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "dev": true }, "isstream": { "version": "0.1.2", "from": "isstream@>=0.1.2 <0.2.0", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz" + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "dev": true + }, + "istanbul": { + "version": "0.4.5", + "from": "istanbul@>=0.4.4 <0.5.0", + "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", + "dev": true, + "dependencies": { + "esprima": { + "version": "2.7.3", + "from": "esprima@>=2.7.0 <2.8.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "dev": true + }, + "glob": { + "version": "5.0.15", + "from": "glob@>=5.0.15 <6.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "dev": true + }, + "resolve": { + "version": "1.1.7", + "from": "resolve@>=1.1.0 <1.2.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "from": "supports-color@>=3.1.0 <4.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "dev": true + } + } }, "istanbul-api": { "version": "1.1.8", "from": "istanbul-api@>=1.1.0-alpha.1 <2.0.0", "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.1.8.tgz", + "dev": true, "dependencies": { "async": { - "version": "2.4.0", + "version": "2.4.1", "from": "async@>=2.1.4 <3.0.0", - "resolved": "https://registry.npmjs.org/async/-/async-2.4.0.tgz" + "resolved": "https://registry.npmjs.org/async/-/async-2.4.1.tgz", + "dev": true } } }, "istanbul-lib-coverage": { "version": "1.1.0", "from": "istanbul-lib-coverage@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.0.tgz" + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.0.tgz", + "dev": true }, "istanbul-lib-hook": { "version": "1.0.6", "from": "istanbul-lib-hook@>=1.0.6 <2.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.0.6.tgz" + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.0.6.tgz", + "dev": true }, "istanbul-lib-instrument": { "version": "1.7.1", "from": "istanbul-lib-instrument@>=1.1.1 <2.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.7.1.tgz" + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.7.1.tgz", + "dev": true }, "istanbul-lib-report": { "version": "1.1.0", "from": "istanbul-lib-report@>=1.1.0 <2.0.0", "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.0.tgz", + "dev": true, "dependencies": { "supports-color": { "version": "3.2.3", - "from": "supports-color@^3.1.2", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz" + "from": "supports-color@>=3.1.2 <4.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "dev": true } } }, @@ -1567,130 +1900,169 @@ "version": "1.2.0", "from": "istanbul-lib-source-maps@>=1.2.0 <2.0.0", "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.0.tgz", + "dev": true, "dependencies": { - "debug": { - "version": "2.6.6", - "from": "debug@>=2.6.3 <3.0.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.6.tgz" - }, - "ms": { - "version": "0.7.3", - "from": "ms@0.7.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.3.tgz" - }, - "rimraf": { - "version": "2.6.1", - "from": "rimraf@>=2.6.1 <3.0.0", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz" - }, "source-map": { "version": "0.5.6", "from": "source-map@>=0.5.3 <0.6.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz" + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", + "dev": true } } }, "istanbul-reports": { "version": "1.1.0", "from": "istanbul-reports@>=1.1.0 <2.0.0", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.1.0.tgz" + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.1.0.tgz", + "dev": true }, "jest-changed-files": { "version": "17.0.2", "from": "jest-changed-files@>=17.0.2 <18.0.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-17.0.2.tgz" + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-17.0.2.tgz", + "dev": true + }, + "jest-cli": { + "version": "18.1.0", + "from": "jest-cli@>=18.0.0 <19.0.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-18.1.0.tgz", + "dev": true, + "dependencies": { + "callsites": { + "version": "2.0.0", + "from": "callsites@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "dev": true + }, + "camelcase": { + "version": "3.0.0", + "from": "camelcase@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "dev": true + }, + "cliui": { + "version": "3.2.0", + "from": "cliui@>=3.2.0 <4.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "dev": true + }, + "yargs": { + "version": "6.6.0", + "from": "yargs@>=6.3.0 <7.0.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz", + "dev": true + } + } }, "jest-config": { "version": "18.1.0", "from": "jest-config@>=18.1.0 <19.0.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-18.1.0.tgz" + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-18.1.0.tgz", + "dev": true }, "jest-diff": { "version": "18.1.0", "from": "jest-diff@>=18.1.0 <19.0.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-18.1.0.tgz" + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-18.1.0.tgz", + "dev": true }, "jest-environment-jsdom": { "version": "18.1.0", "from": "jest-environment-jsdom@>=18.1.0 <19.0.0", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-18.1.0.tgz" + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-18.1.0.tgz", + "dev": true }, "jest-environment-node": { "version": "18.1.0", "from": "jest-environment-node@>=18.1.0 <19.0.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-18.1.0.tgz" + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-18.1.0.tgz", + "dev": true }, "jest-file-exists": { "version": "17.0.0", "from": "jest-file-exists@>=17.0.0 <18.0.0", - "resolved": "https://registry.npmjs.org/jest-file-exists/-/jest-file-exists-17.0.0.tgz" + "resolved": "https://registry.npmjs.org/jest-file-exists/-/jest-file-exists-17.0.0.tgz", + "dev": true }, "jest-haste-map": { "version": "18.1.0", "from": "jest-haste-map@>=18.1.0 <19.0.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-18.1.0.tgz" + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-18.1.0.tgz", + "dev": true }, "jest-jasmine2": { "version": "18.1.0", "from": "jest-jasmine2@>=18.1.0 <19.0.0", - "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-18.1.0.tgz" + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-18.1.0.tgz", + "dev": true }, "jest-matcher-utils": { "version": "18.1.0", "from": "jest-matcher-utils@>=18.1.0 <19.0.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-18.1.0.tgz" + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-18.1.0.tgz", + "dev": true }, "jest-matchers": { "version": "18.1.0", "from": "jest-matchers@>=18.1.0 <19.0.0", - "resolved": "https://registry.npmjs.org/jest-matchers/-/jest-matchers-18.1.0.tgz" + "resolved": "https://registry.npmjs.org/jest-matchers/-/jest-matchers-18.1.0.tgz", + "dev": true }, "jest-mock": { "version": "18.0.0", "from": "jest-mock@>=18.0.0 <19.0.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-18.0.0.tgz" + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-18.0.0.tgz", + "dev": true }, "jest-resolve": { "version": "18.1.0", "from": "jest-resolve@>=18.1.0 <19.0.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-18.1.0.tgz" + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-18.1.0.tgz", + "dev": true }, "jest-resolve-dependencies": { "version": "18.1.0", "from": "jest-resolve-dependencies@>=18.1.0 <19.0.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-18.1.0.tgz" + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-18.1.0.tgz", + "dev": true }, "jest-runtime": { "version": "18.1.0", "from": "jest-runtime@>=18.1.0 <19.0.0", "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-18.1.0.tgz", + "dev": true, "dependencies": { "camelcase": { "version": "3.0.0", "from": "camelcase@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz" + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "dev": true }, "cliui": { "version": "3.2.0", "from": "cliui@>=3.2.0 <4.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz" + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "dev": true }, "yargs": { "version": "6.6.0", "from": "yargs@>=6.3.0 <7.0.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz" + "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz", + "dev": true } } }, "jest-snapshot": { "version": "18.1.0", "from": "jest-snapshot@>=18.1.0 <19.0.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-18.1.0.tgz" + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-18.1.0.tgz", + "dev": true }, "jest-util": { "version": "18.1.0", "from": "jest-util@>=18.1.0 <19.0.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-18.1.0.tgz" + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-18.1.0.tgz", + "dev": true }, "jmespath": { "version": "0.15.0", @@ -1700,49 +2072,52 @@ "jodid25519": { "version": "1.0.2", "from": "jodid25519@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz", + "dev": true, + "optional": true }, "js-tokens": { "version": "3.0.1", "from": "js-tokens@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.1.tgz" + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.1.tgz", + "dev": true }, "js-yaml": { - "version": "3.7.0", + "version": "3.8.4", "from": "js-yaml@>=3.6.1 <4.0.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.7.0.tgz" + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.8.4.tgz" }, "jsbn": { "version": "0.1.1", "from": "jsbn@>=0.1.0 <0.2.0", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz" + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "dev": true, + "optional": true }, "jsdom": { "version": "9.12.0", "from": "jsdom@>=9.9.1 <10.0.0", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-9.12.0.tgz", + "dev": true, "dependencies": { "acorn": { - "version": "4.0.11", + "version": "4.0.13", "from": "acorn@>=4.0.4 <5.0.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.11.tgz" - }, - "sax": { - "version": "1.2.2", - "from": "sax@>=1.2.1 <2.0.0", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.2.tgz" + "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", + "dev": true } } }, "jsesc": { "version": "1.3.0", "from": "jsesc@>=1.3.0 <2.0.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz" + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "dev": true }, "json-refs": { - "version": "2.1.6", + "version": "2.1.7", "from": "json-refs@>=2.1.5 <3.0.0", - "resolved": "https://registry.npmjs.org/json-refs/-/json-refs-2.1.6.tgz", + "resolved": "https://registry.npmjs.org/json-refs/-/json-refs-2.1.7.tgz", "dependencies": { "commander": { "version": "2.9.0", @@ -1754,27 +2129,32 @@ "json-schema": { "version": "0.2.3", "from": "json-schema@0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz" + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "dev": true }, "json-stable-stringify": { "version": "1.0.1", "from": "json-stable-stringify@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "dev": true }, "json-stringify-safe": { "version": "5.0.1", "from": "json-stringify-safe@>=5.0.1 <5.1.0", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz" + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "dev": true }, "json3": { "version": "3.3.2", "from": "json3@3.3.2", - "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz" + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", + "dev": true }, "json5": { "version": "0.5.1", "from": "json5@>=0.5.0 <0.6.0", - "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz" + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "dev": true }, "jsonfile": { "version": "2.4.0", @@ -1784,29 +2164,60 @@ "jsonify": { "version": "0.0.0", "from": "jsonify@>=0.0.0 <0.1.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz" + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "dev": true }, "jsonpointer": { "version": "4.0.1", "from": "jsonpointer@>=4.0.0 <5.0.0", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz" + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "dev": true }, "jsprim": { "version": "1.4.0", "from": "jsprim@>=1.2.2 <2.0.0", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.0.tgz", + "dev": true, "dependencies": { "assert-plus": { "version": "1.0.0", "from": "assert-plus@1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "dev": true } } }, "jsx-ast-utils": { "version": "1.4.1", "from": "jsx-ast-utils@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-1.4.1.tgz" + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-1.4.1.tgz", + "dev": true + }, + "jszip": { + "version": "3.1.3", + "from": "jszip@>=3.1.2 <4.0.0", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.1.3.tgz", + "dev": true, + "dependencies": { + "core-js": { + "version": "2.3.0", + "from": "core-js@>=2.3.0 <2.4.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.3.0.tgz", + "dev": true + }, + "readable-stream": { + "version": "2.0.6", + "from": "readable-stream@>=2.0.6 <2.1.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "from": "string_decoder@>=0.10.0 <0.11.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "dev": true + } + } }, "jwt-decode": { "version": "2.2.0", @@ -1814,9 +2225,10 @@ "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-2.2.0.tgz" }, "kind-of": { - "version": "3.2.0", + "version": "3.2.2", "from": "kind-of@>=3.0.2 <4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.0.tgz" + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "dev": true }, "klaw": { "version": "1.3.1", @@ -1826,7 +2238,9 @@ "lazy-cache": { "version": "1.0.4", "from": "lazy-cache@>=1.0.3 <2.0.0", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz" + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "dev": true, + "optional": true }, "lazystream": { "version": "1.0.0", @@ -1836,37 +2250,44 @@ "lcid": { "version": "1.0.0", "from": "lcid@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "dev": true }, "lcov-parse": { "version": "0.0.10", "from": "lcov-parse@0.0.10", - "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-0.0.10.tgz" + "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-0.0.10.tgz", + "dev": true }, "levn": { "version": "0.3.0", "from": "levn@>=0.3.0 <0.4.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz" + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "dev": true }, "lie": { "version": "3.1.1", "from": "lie@>=3.1.0 <3.2.0", - "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz" + "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz", + "dev": true }, "list-item": { "version": "1.1.1", "from": "list-item@>=1.1.1 <2.0.0", - "resolved": "https://registry.npmjs.org/list-item/-/list-item-1.1.1.tgz" + "resolved": "https://registry.npmjs.org/list-item/-/list-item-1.1.1.tgz", + "dev": true }, "load-json-file": { "version": "1.1.0", "from": "load-json-file@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "dev": true, "dependencies": { "strip-bom": { "version": "2.0.0", "from": "strip-bom@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "dev": true } } }, @@ -1874,215 +2295,281 @@ "version": "2.0.0", "from": "locate-path@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "dev": true, "dependencies": { "path-exists": { "version": "3.0.0", "from": "path-exists@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz" + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "dev": true } } }, "lodash": { - "version": "4.17.2", + "version": "4.17.4", "from": "lodash@>=4.13.1 <5.0.0", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.2.tgz" + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz" }, "lodash._arraycopy": { "version": "3.0.0", "from": "lodash._arraycopy@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/lodash._arraycopy/-/lodash._arraycopy-3.0.0.tgz" + "resolved": "https://registry.npmjs.org/lodash._arraycopy/-/lodash._arraycopy-3.0.0.tgz", + "dev": true }, "lodash._arrayeach": { "version": "3.0.0", "from": "lodash._arrayeach@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/lodash._arrayeach/-/lodash._arrayeach-3.0.0.tgz" + "resolved": "https://registry.npmjs.org/lodash._arrayeach/-/lodash._arrayeach-3.0.0.tgz", + "dev": true }, "lodash._baseassign": { "version": "3.2.0", "from": "lodash._baseassign@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz" + "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", + "dev": true }, "lodash._baseclone": { "version": "3.3.0", "from": "lodash._baseclone@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/lodash._baseclone/-/lodash._baseclone-3.3.0.tgz" + "resolved": "https://registry.npmjs.org/lodash._baseclone/-/lodash._baseclone-3.3.0.tgz", + "dev": true }, "lodash._basecopy": { "version": "3.0.1", "from": "lodash._basecopy@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz" + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "dev": true }, "lodash._basecreate": { "version": "3.0.3", "from": "lodash._basecreate@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz" + "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", + "dev": true }, "lodash._basefor": { "version": "3.0.3", "from": "lodash._basefor@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/lodash._basefor/-/lodash._basefor-3.0.3.tgz" + "resolved": "https://registry.npmjs.org/lodash._basefor/-/lodash._basefor-3.0.3.tgz", + "dev": true }, "lodash._bindcallback": { "version": "3.0.1", "from": "lodash._bindcallback@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz" + "resolved": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz", + "dev": true }, "lodash._getnative": { "version": "3.9.1", "from": "lodash._getnative@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz" + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "dev": true }, "lodash._isiterateecall": { "version": "3.0.9", "from": "lodash._isiterateecall@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz" + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "dev": true }, "lodash.assign": { "version": "4.2.0", "from": "lodash.assign@>=4.2.0 <5.0.0", - "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz" + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", + "dev": true }, "lodash.clonedeep": { "version": "3.0.2", "from": "lodash.clonedeep@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-3.0.2.tgz" + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-3.0.2.tgz", + "dev": true }, "lodash.cond": { "version": "4.5.2", "from": "lodash.cond@>=4.3.0 <5.0.0", - "resolved": "https://registry.npmjs.org/lodash.cond/-/lodash.cond-4.5.2.tgz" + "resolved": "https://registry.npmjs.org/lodash.cond/-/lodash.cond-4.5.2.tgz", + "dev": true }, "lodash.create": { "version": "3.1.1", "from": "lodash.create@3.1.1", - "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz" + "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", + "dev": true }, "lodash.endswith": { "version": "4.2.1", "from": "lodash.endswith@>=4.0.1 <5.0.0", - "resolved": "https://registry.npmjs.org/lodash.endswith/-/lodash.endswith-4.2.1.tgz" + "resolved": "https://registry.npmjs.org/lodash.endswith/-/lodash.endswith-4.2.1.tgz", + "dev": true }, "lodash.find": { "version": "4.6.0", "from": "lodash.find@>=4.3.0 <5.0.0", - "resolved": "https://registry.npmjs.org/lodash.find/-/lodash.find-4.6.0.tgz" + "resolved": "https://registry.npmjs.org/lodash.find/-/lodash.find-4.6.0.tgz", + "dev": true }, "lodash.findindex": { "version": "4.6.0", "from": "lodash.findindex@>=4.3.0 <5.0.0", - "resolved": "https://registry.npmjs.org/lodash.findindex/-/lodash.findindex-4.6.0.tgz" + "resolved": "https://registry.npmjs.org/lodash.findindex/-/lodash.findindex-4.6.0.tgz", + "dev": true }, "lodash.isarguments": { "version": "3.1.0", "from": "lodash.isarguments@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz" + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "dev": true }, "lodash.isarray": { "version": "3.0.4", "from": "lodash.isarray@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz" + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "dev": true }, "lodash.keys": { "version": "3.1.2", "from": "lodash.keys@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz" + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "dev": true }, "log-driver": { "version": "1.2.5", "from": "log-driver@1.2.5", - "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.5.tgz" + "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.5.tgz", + "dev": true }, "lolex": { "version": "1.3.2", "from": "lolex@1.3.2", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.3.2.tgz" + "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.3.2.tgz", + "dev": true }, "longest": { "version": "1.0.1", "from": "longest@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "dev": true }, "loose-envify": { "version": "1.3.1", "from": "loose-envify@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz" + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", + "dev": true }, "lowercase-keys": { "version": "1.0.0", "from": "lowercase-keys@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz" }, + "make-dir": { + "version": "1.0.0", + "from": "make-dir@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.0.0.tgz" + }, "makeerror": { "version": "1.0.11", "from": "makeerror@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz" + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz", + "dev": true }, "markdown-link": { "version": "0.1.1", "from": "markdown-link@>=0.1.1 <0.2.0", - "resolved": "https://registry.npmjs.org/markdown-link/-/markdown-link-0.1.1.tgz" + "resolved": "https://registry.npmjs.org/markdown-link/-/markdown-link-0.1.1.tgz", + "dev": true + }, + "markdown-magic": { + "version": "0.1.15", + "from": "markdown-magic@>=0.1.15 <0.2.0", + "resolved": "https://registry.npmjs.org/markdown-magic/-/markdown-magic-0.1.15.tgz", + "dev": true, + "dependencies": { + "commander": { + "version": "2.9.0", + "from": "commander@>=2.9.0 <3.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "dev": true + }, + "find-up": { + "version": "2.1.0", + "from": "find-up@>=2.1.0 <3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "dev": true + }, + "fs-extra": { + "version": "1.0.0", + "from": "fs-extra@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz", + "dev": true + } + } }, "markdown-toc": { "version": "1.1.0", "from": "markdown-toc@>=1.0.2 <2.0.0", "resolved": "https://registry.npmjs.org/markdown-toc/-/markdown-toc-1.1.0.tgz", + "dev": true, "dependencies": { "lazy-cache": { "version": "2.0.2", "from": "lazy-cache@>=2.0.2 <3.0.0", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz" + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz", + "dev": true } } }, "marked": { "version": "0.3.6", "from": "marked@>=0.3.6 <0.4.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.6.tgz" + "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.6.tgz", + "dev": true }, "marked-terminal": { "version": "1.7.0", "from": "marked-terminal@>=1.6.2 <2.0.0", - "resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-1.7.0.tgz" + "resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-1.7.0.tgz", + "dev": true }, "merge": { "version": "1.2.0", "from": "merge@>=1.1.3 <2.0.0", - "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.0.tgz" + "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.0.tgz", + "dev": true }, "merge-descriptors": { "version": "1.0.1", "from": "merge-descriptors@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "dev": true }, "methods": { "version": "1.1.2", - "from": "methods@>=1.1.1 <1.2.0", + "from": "methods@>=1.1.1 <2.0.0", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz" }, "micromatch": { "version": "2.3.11", "from": "micromatch@>=2.3.11 <3.0.0", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz" + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "dev": true }, "mime": { - "version": "1.3.4", - "from": "mime@1.3.4", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz" + "version": "1.3.6", + "from": "mime@>=1.3.4 <2.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.6.tgz" }, "mime-db": { - "version": "1.25.0", - "from": "mime-db@>=1.25.0 <1.26.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.25.0.tgz" + "version": "1.27.0", + "from": "mime-db@>=1.27.0 <1.28.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.27.0.tgz" }, "mime-types": { - "version": "2.1.13", - "from": "mime-types@>=2.1.3 <3.0.0", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.13.tgz" + "version": "2.1.15", + "from": "mime-types@>=2.1.12 <3.0.0", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.15.tgz" }, "minimatch": { - "version": "3.0.3", - "from": "minimatch@>=3.0.2 <4.0.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz" + "version": "3.0.4", + "from": "minimatch@>=3.0.4 <4.0.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz" }, "minimist": { "version": "1.2.0", @@ -2092,7 +2579,8 @@ "mixin-deep": { "version": "1.2.0", "from": "mixin-deep@>=1.1.3 <2.0.0", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.2.0.tgz" + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.2.0.tgz", + "dev": true }, "mkdirp": { "version": "0.5.1", @@ -2106,25 +2594,77 @@ } } }, + "mocha": { + "version": "3.4.1", + "from": "mocha@>=3.0.2 <4.0.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.4.1.tgz", + "dev": true, + "dependencies": { + "commander": { + "version": "2.9.0", + "from": "commander@2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "dev": true + }, + "debug": { + "version": "2.6.0", + "from": "debug@2.6.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.0.tgz", + "dev": true + }, + "glob": { + "version": "7.1.1", + "from": "glob@7.1.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", + "dev": true + }, + "ms": { + "version": "0.7.2", + "from": "ms@0.7.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", + "dev": true + }, + "supports-color": { + "version": "3.1.2", + "from": "supports-color@3.1.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", + "dev": true + } + } + }, + "mocha-lcov-reporter": { + "version": "1.3.0", + "from": "mocha-lcov-reporter@>=1.2.0 <2.0.0", + "resolved": "https://registry.npmjs.org/mocha-lcov-reporter/-/mocha-lcov-reporter-1.3.0.tgz", + "dev": true + }, + "mock-require": { + "version": "1.3.0", + "from": "mock-require@>=1.3.0 <2.0.0", + "resolved": "https://registry.npmjs.org/mock-require/-/mock-require-1.3.0.tgz", + "dev": true + }, "module-not-found-error": { "version": "1.0.1", "from": "module-not-found-error@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/module-not-found-error/-/module-not-found-error-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/module-not-found-error/-/module-not-found-error-1.0.1.tgz", + "dev": true }, "moment": { - "version": "2.17.0", + "version": "2.18.1", "from": "moment@>=2.13.0 <3.0.0", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.17.0.tgz" + "resolved": "https://registry.npmjs.org/moment/-/moment-2.18.1.tgz" }, "ms": { - "version": "0.7.2", - "from": "ms@0.7.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz" + "version": "2.0.0", + "from": "ms@2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" }, "mute-stream": { "version": "0.0.5", "from": "mute-stream@0.0.5", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz" + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", + "dev": true }, "native-promise-only": { "version": "0.8.1", @@ -2134,87 +2674,95 @@ "natural-compare": { "version": "1.4.0", "from": "natural-compare@>=1.4.0 <2.0.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "dev": true }, "node-emoji": { "version": "1.5.1", "from": "node-emoji@>=1.4.1 <2.0.0", - "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.5.1.tgz" + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.5.1.tgz", + "dev": true }, "node-fetch": { - "version": "1.6.3", - "from": "node-fetch@>=1.5.3 <2.0.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.6.3.tgz" + "version": "1.7.0", + "from": "node-fetch@>=1.6.0 <2.0.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.0.tgz" }, "node-int64": { "version": "0.4.0", "from": "node-int64@>=0.4.0 <0.5.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz" + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "dev": true }, "node-notifier": { "version": "4.6.1", "from": "node-notifier@>=4.6.1 <5.0.0", - "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-4.6.1.tgz" - }, - "node-status-codes": { - "version": "2.0.1", - "from": "node-status-codes@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/node-status-codes/-/node-status-codes-2.0.1.tgz" + "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-4.6.1.tgz", + "dev": true }, "nopt": { "version": "3.0.6", "from": "nopt@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz" + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "dev": true }, "normalize-package-data": { "version": "2.3.8", "from": "normalize-package-data@>=2.3.2 <3.0.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.3.8.tgz" + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.3.8.tgz", + "dev": true }, "normalize-path": { - "version": "2.0.1", + "version": "2.1.1", "from": "normalize-path@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.0.1.tgz" + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz" }, "number-is-nan": { "version": "1.0.1", "from": "number-is-nan@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "dev": true }, "nwmatcher": { - "version": "1.3.9", + "version": "1.4.0", "from": "nwmatcher@>=1.3.9 <2.0.0", - "resolved": "https://registry.npmjs.org/nwmatcher/-/nwmatcher-1.3.9.tgz" + "resolved": "https://registry.npmjs.org/nwmatcher/-/nwmatcher-1.4.0.tgz", + "dev": true }, "oauth-sign": { "version": "0.8.2", "from": "oauth-sign@>=0.8.1 <0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz" + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "dev": true }, "object-assign": { - "version": "4.1.0", + "version": "4.1.1", "from": "object-assign@>=4.0.1 <5.0.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz" + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" }, "object-keys": { "version": "1.0.11", "from": "object-keys@>=1.0.8 <2.0.0", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz" + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", + "dev": true }, "object.assign": { "version": "4.0.4", "from": "object.assign@>=4.0.4 <5.0.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.0.4.tgz" + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.0.4.tgz", + "dev": true }, "object.omit": { "version": "2.0.1", "from": "object.omit@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz" + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "dev": true }, "object.pick": { "version": "1.2.0", "from": "object.pick@>=1.2.0 <2.0.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.2.0.tgz" + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.2.0.tgz", + "dev": true }, "once": { "version": "1.4.0", @@ -2224,7 +2772,8 @@ "onetime": { "version": "1.1.0", "from": "onetime@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz" + "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "dev": true }, "opn": { "version": "5.0.0", @@ -2235,73 +2784,87 @@ "version": "0.6.1", "from": "optimist@>=0.6.1 <0.7.0", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "dev": true, "dependencies": { "minimist": { "version": "0.0.10", "from": "minimist@>=0.0.1 <0.1.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz" + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "dev": true }, "wordwrap": { "version": "0.0.3", "from": "wordwrap@>=0.0.2 <0.1.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz" + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "dev": true } } }, "optionator": { "version": "0.8.2", "from": "optionator@>=0.8.2 <0.9.0", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz" + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "dev": true }, "os-homedir": { "version": "1.0.2", "from": "os-homedir@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "dev": true }, "os-locale": { "version": "1.4.0", "from": "os-locale@>=1.4.0 <2.0.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz" + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "dev": true }, "os-tmpdir": { "version": "1.0.2", "from": "os-tmpdir@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "dev": true }, "p-limit": { "version": "1.1.0", "from": "p-limit@>=1.1.0 <2.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.1.0.tgz" + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.1.0.tgz", + "dev": true }, "p-locate": { "version": "2.0.0", "from": "p-locate@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "dev": true }, "pako": { "version": "1.0.5", "from": "pako@>=1.0.2 <1.1.0", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.5.tgz" + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.5.tgz", + "dev": true }, "parse-glob": { "version": "3.0.4", "from": "parse-glob@>=3.0.4 <4.0.0", - "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz" + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "dev": true }, "parse-json": { "version": "2.2.0", "from": "parse-json@>=2.2.0 <3.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz" + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "dev": true }, "parse5": { "version": "1.5.1", "from": "parse5@>=1.5.1 <2.0.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-1.5.1.tgz" + "resolved": "https://registry.npmjs.org/parse5/-/parse5-1.5.1.tgz", + "dev": true }, "path-exists": { "version": "2.1.0", "from": "path-exists@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz" + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "dev": true }, "path-is-absolute": { "version": "1.0.1", @@ -2311,22 +2874,25 @@ "path-is-inside": { "version": "1.0.2", "from": "path-is-inside@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "dev": true }, "path-loader": { - "version": "1.0.1", - "from": "path-loader@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/path-loader/-/path-loader-1.0.1.tgz" + "version": "1.0.2", + "from": "path-loader@>=1.0.2 <2.0.0", + "resolved": "https://registry.npmjs.org/path-loader/-/path-loader-1.0.2.tgz" }, "path-parse": { "version": "1.0.5", "from": "path-parse@>=1.0.5 <2.0.0", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz" + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "dev": true }, "path-type": { "version": "1.1.0", "from": "path-type@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz" + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "dev": true }, "pend": { "version": "1.2.0", @@ -2351,22 +2917,26 @@ "pkg-dir": { "version": "1.0.0", "from": "pkg-dir@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", + "dev": true }, "pkg-up": { "version": "1.0.0", "from": "pkg-up@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-1.0.0.tgz", + "dev": true }, "pluralize": { "version": "1.2.1", "from": "pluralize@>=1.2.1 <2.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz" + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz", + "dev": true }, "prelude-ls": { "version": "1.1.2", "from": "prelude-ls@>=1.1.2 <1.2.0", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz" + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "dev": true }, "prepend-http": { "version": "1.0.4", @@ -2376,17 +2946,20 @@ "preserve": { "version": "0.2.0", "from": "preserve@>=0.2.0 <0.3.0", - "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz" + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "dev": true }, "pretty-format": { "version": "18.1.0", "from": "pretty-format@>=18.1.0 <19.0.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-18.1.0.tgz" + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-18.1.0.tgz", + "dev": true }, "private": { "version": "0.1.7", "from": "private@>=0.1.6 <0.2.0", - "resolved": "https://registry.npmjs.org/private/-/private-0.1.7.tgz" + "resolved": "https://registry.npmjs.org/private/-/private-0.1.7.tgz", + "dev": true }, "process-nextick-args": { "version": "1.0.7", @@ -2396,17 +2969,34 @@ "progress": { "version": "1.1.8", "from": "progress@>=1.1.8 <2.0.0", - "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz" + "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", + "dev": true }, "promise": { "version": "7.1.1", "from": "promise@>=7.1.1 <8.0.0", - "resolved": "https://registry.npmjs.org/promise/-/promise-7.1.1.tgz" + "resolved": "https://registry.npmjs.org/promise/-/promise-7.1.1.tgz", + "dev": true + }, + "proxyquire": { + "version": "1.8.0", + "from": "proxyquire@>=1.7.10 <2.0.0", + "resolved": "https://registry.npmjs.org/proxyquire/-/proxyquire-1.8.0.tgz", + "dev": true, + "dependencies": { + "resolve": { + "version": "1.1.7", + "from": "resolve@>=1.1.7 <1.2.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "dev": true + } + } }, "prr": { "version": "0.0.0", "from": "prr@>=0.0.0 <0.1.0", - "resolved": "https://registry.npmjs.org/prr/-/prr-0.0.0.tgz" + "resolved": "https://registry.npmjs.org/prr/-/prr-0.0.0.tgz", + "dev": true }, "punycode": { "version": "1.3.2", @@ -2414,9 +3004,9 @@ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz" }, "qs": { - "version": "2.3.3", - "from": "qs@2.3.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz" + "version": "6.4.0", + "from": "qs@>=6.1.0 <7.0.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz" }, "querystring": { "version": "0.2.0", @@ -2426,91 +3016,105 @@ "randomatic": { "version": "1.1.6", "from": "randomatic@>=1.1.3 <2.0.0", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.6.tgz" + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.6.tgz", + "dev": true }, "rc": { - "version": "1.1.6", - "from": "rc@>=1.1.2 <2.0.0", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.1.6.tgz" + "version": "1.2.1", + "from": "rc@>=1.1.6 <2.0.0", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.1.tgz" }, "read-pkg": { "version": "1.1.0", "from": "read-pkg@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz" + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "dev": true }, "read-pkg-up": { "version": "1.0.1", "from": "read-pkg-up@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "dev": true }, "readable-stream": { - "version": "2.2.2", + "version": "2.2.9", "from": "readable-stream@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.2.tgz" + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.9.tgz" }, "readline2": { "version": "1.0.1", "from": "readline2@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", + "dev": true }, "rechoir": { "version": "0.6.2", "from": "rechoir@>=0.6.2 <0.7.0", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz" + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "dev": true }, "redeyed": { "version": "1.0.1", "from": "redeyed@>=1.0.0 <1.1.0", "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-1.0.1.tgz", + "dev": true, "dependencies": { "esprima": { "version": "3.0.0", "from": "esprima@>=3.0.0 <3.1.0", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.0.0.tgz" + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.0.0.tgz", + "dev": true } } }, - "reduce-component": { - "version": "1.0.1", - "from": "reduce-component@1.0.1", - "resolved": "https://registry.npmjs.org/reduce-component/-/reduce-component-1.0.1.tgz" - }, "regenerator-runtime": { "version": "0.10.5", "from": "regenerator-runtime@>=0.10.0 <0.11.0", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz" + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", + "dev": true }, "regex-cache": { "version": "0.4.3", "from": "regex-cache@>=0.4.2 <0.5.0", - "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.3.tgz" + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.3.tgz", + "dev": true }, "remarkable": { "version": "1.7.1", "from": "remarkable@>=1.7.1 <2.0.0", "resolved": "https://registry.npmjs.org/remarkable/-/remarkable-1.7.1.tgz", + "dev": true, "dependencies": { "argparse": { "version": "0.1.16", "from": "argparse@>=0.1.15 <0.2.0", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-0.1.16.tgz" + "resolved": "https://registry.npmjs.org/argparse/-/argparse-0.1.16.tgz", + "dev": true } } }, + "remove-trailing-separator": { + "version": "1.0.1", + "from": "remove-trailing-separator@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.0.1.tgz" + }, "repeat-element": { "version": "1.1.2", "from": "repeat-element@>=1.1.2 <2.0.0", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz" + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "dev": true }, "repeat-string": { "version": "1.6.1", "from": "repeat-string@>=1.5.2 <2.0.0", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz" + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "dev": true }, "repeating": { "version": "2.0.1", "from": "repeating@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz" + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "dev": true }, "replaceall": { "version": "0.1.6", @@ -2521,50 +3125,53 @@ "version": "2.79.0", "from": "request@2.79.0", "resolved": "https://registry.npmjs.org/request/-/request-2.79.0.tgz", + "dev": true, "dependencies": { - "form-data": { - "version": "2.1.4", - "from": "form-data@>=2.1.1 <2.2.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz" - }, "qs": { "version": "6.3.2", "from": "qs@>=6.3.0 <6.4.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz" + "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz", + "dev": true }, "uuid": { "version": "3.0.1", "from": "uuid@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.0.1.tgz" + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.0.1.tgz", + "dev": true } } }, "require-directory": { "version": "2.1.1", "from": "require-directory@>=2.1.1 <3.0.0", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz" + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "dev": true }, "require-main-filename": { "version": "1.0.1", "from": "require-main-filename@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "dev": true }, "require-uncached": { "version": "1.0.3", "from": "require-uncached@>=1.0.2 <2.0.0", "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "dev": true, "dependencies": { "resolve-from": { "version": "1.0.1", "from": "resolve-from@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "dev": true } } }, "resolve": { "version": "1.3.3", "from": "resolve@>=1.1.6 <2.0.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.3.3.tgz" + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.3.3.tgz", + "dev": true }, "resolve-from": { "version": "2.0.0", @@ -2574,42 +3181,54 @@ "restore-cursor": { "version": "1.0.1", "from": "restore-cursor@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "dev": true }, "right-align": { "version": "0.1.3", "from": "right-align@>=0.1.1 <0.2.0", - "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz" + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "dev": true, + "optional": true }, "rimraf": { - "version": "2.5.4", + "version": "2.6.1", "from": "rimraf@>=2.2.8 <3.0.0", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.4.tgz" + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz" }, "run-async": { "version": "0.1.0", "from": "run-async@>=0.1.0 <0.2.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz" + "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", + "dev": true }, "rx-lite": { "version": "3.1.2", "from": "rx-lite@>=3.1.2 <4.0.0", - "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz" + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", + "dev": true + }, + "safe-buffer": { + "version": "5.0.1", + "from": "safe-buffer@>=5.0.1 <6.0.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.0.1.tgz" }, "samsam": { "version": "1.1.2", "from": "samsam@1.1.2", - "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.1.2.tgz" + "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.1.2.tgz", + "dev": true }, "sane": { "version": "1.4.1", "from": "sane@>=1.4.1 <1.5.0", - "resolved": "https://registry.npmjs.org/sane/-/sane-1.4.1.tgz" + "resolved": "https://registry.npmjs.org/sane/-/sane-1.4.1.tgz", + "dev": true }, "sax": { - "version": "1.1.5", - "from": "sax@1.1.5", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.1.5.tgz" + "version": "1.2.1", + "from": "sax@1.2.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz" }, "seek-bzip": { "version": "1.0.5", @@ -2629,12 +3248,14 @@ "set-blocking": { "version": "2.0.0", "from": "set-blocking@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "dev": true }, "set-getter": { "version": "0.1.0", "from": "set-getter@>=0.1.0 <0.2.0", - "resolved": "https://registry.npmjs.org/set-getter/-/set-getter-0.1.0.tgz" + "resolved": "https://registry.npmjs.org/set-getter/-/set-getter-0.1.0.tgz", + "dev": true }, "shelljs": { "version": "0.6.1", @@ -2644,7 +3265,26 @@ "shellwords": { "version": "0.1.0", "from": "shellwords@>=0.1.0 <0.2.0", - "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.0.tgz" + "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.0.tgz", + "dev": true + }, + "sinon": { + "version": "1.17.7", + "from": "sinon@>=1.17.5 <2.0.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.17.7.tgz", + "dev": true + }, + "sinon-bluebird": { + "version": "3.1.0", + "from": "sinon-bluebird@>=3.1.0 <4.0.0", + "resolved": "https://registry.npmjs.org/sinon-bluebird/-/sinon-bluebird-3.1.0.tgz", + "dev": true + }, + "sinon-chai": { + "version": "2.10.0", + "from": "sinon-chai@>=2.9.0 <3.0.0", + "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-2.10.0.tgz", + "dev": true }, "slash": { "version": "1.0.0", @@ -2654,7 +3294,8 @@ "slice-ansi": { "version": "0.0.4", "from": "slice-ansi@0.0.4", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz" + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "dev": true }, "slide": { "version": "1.1.6", @@ -2664,39 +3305,47 @@ "sntp": { "version": "1.0.9", "from": "sntp@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz" + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "dev": true }, "source-map": { "version": "0.2.0", "from": "source-map@>=0.2.0 <0.3.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz" + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", + "dev": true, + "optional": true }, "source-map-support": { "version": "0.4.15", "from": "source-map-support@>=0.4.2 <0.5.0", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.15.tgz", + "dev": true, "dependencies": { "source-map": { "version": "0.5.6", "from": "source-map@>=0.5.6 <0.6.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz" + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", + "dev": true } } }, "spdx-correct": { "version": "1.0.2", "from": "spdx-correct@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", + "dev": true }, "spdx-expression-parse": { "version": "1.0.4", "from": "spdx-expression-parse@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz" + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", + "dev": true }, "spdx-license-ids": { "version": "1.2.2", "from": "spdx-license-ids@>=1.0.2 <2.0.0", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz" + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", + "dev": true }, "sprintf-js": { "version": "1.0.3", @@ -2707,38 +3356,44 @@ "version": "1.13.0", "from": "sshpk@>=1.7.0 <2.0.0", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.0.tgz", + "dev": true, "dependencies": { "assert-plus": { "version": "1.0.0", "from": "assert-plus@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "dev": true } } }, "stack-trace": { "version": "0.0.10", "from": "stack-trace@>=0.0.7 <0.1.0", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz" + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "dev": true }, "string_decoder": { - "version": "0.10.31", - "from": "string_decoder@>=0.10.0 <0.11.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + "version": "1.0.1", + "from": "string_decoder@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.1.tgz" }, "string-width": { "version": "1.0.2", "from": "string-width@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "dev": true }, "string.prototype.codepointat": { "version": "0.2.0", "from": "string.prototype.codepointat@>=0.2.0 <0.3.0", - "resolved": "https://registry.npmjs.org/string.prototype.codepointat/-/string.prototype.codepointat-0.2.0.tgz" + "resolved": "https://registry.npmjs.org/string.prototype.codepointat/-/string.prototype.codepointat-0.2.0.tgz", + "dev": true }, "stringstream": { "version": "0.0.5", "from": "stringstream@>=0.0.4 <0.1.0", - "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz" + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "dev": true }, "strip-ansi": { "version": "3.0.1", @@ -2748,56 +3403,34 @@ "strip-bom": { "version": "3.0.0", "from": "strip-bom@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz" + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "dev": true }, "strip-color": { "version": "0.1.0", "from": "strip-color@>=0.1.0 <0.2.0", - "resolved": "https://registry.npmjs.org/strip-color/-/strip-color-0.1.0.tgz" + "resolved": "https://registry.npmjs.org/strip-color/-/strip-color-0.1.0.tgz", + "dev": true }, "strip-dirs": { - "version": "1.1.1", - "from": "strip-dirs@>=1.1.1 <2.0.0", - "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-1.1.1.tgz", - "dependencies": { - "get-stdin": { - "version": "4.0.1", - "from": "get-stdin@>=4.0.1 <5.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz" - } - } + "version": "2.0.0", + "from": "strip-dirs@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.0.0.tgz" }, "strip-json-comments": { - "version": "1.0.4", - "from": "strip-json-comments@>=1.0.4 <1.1.0", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz" + "version": "2.0.1", + "from": "strip-json-comments@>=2.0.1 <2.1.0", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz" }, "strip-outer": { "version": "1.0.0", "from": "strip-outer@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.0.tgz" }, - "sum-up": { - "version": "1.0.3", - "from": "sum-up@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/sum-up/-/sum-up-1.0.3.tgz" - }, "superagent": { - "version": "1.8.4", - "from": "superagent@>=1.6.1 <2.0.0", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-1.8.4.tgz", - "dependencies": { - "isarray": { - "version": "0.0.1", - "from": "isarray@0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" - }, - "readable-stream": { - "version": "1.0.27-1", - "from": "readable-stream@1.0.27-1", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.27-1.tgz" - } - } + "version": "3.5.2", + "from": "superagent@>=3.5.2 <4.0.0", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.5.2.tgz" }, "supports-color": { "version": "2.0.0", @@ -2807,61 +3440,63 @@ "symbol-tree": { "version": "3.2.2", "from": "symbol-tree@>=3.2.1 <4.0.0", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz" + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz", + "dev": true }, "sync-request": { "version": "3.0.1", "from": "sync-request@>=3.0.1 <4.0.0", - "resolved": "https://registry.npmjs.org/sync-request/-/sync-request-3.0.1.tgz" + "resolved": "https://registry.npmjs.org/sync-request/-/sync-request-3.0.1.tgz", + "dev": true }, "table": { "version": "3.8.3", "from": "table@>=3.7.8 <4.0.0", "resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz", + "dev": true, "dependencies": { "is-fullwidth-code-point": { "version": "2.0.0", "from": "is-fullwidth-code-point@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "dev": true }, "string-width": { "version": "2.0.0", "from": "string-width@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.0.0.tgz", + "dev": true } } }, "tar-stream": { - "version": "1.5.2", + "version": "1.5.4", "from": "tar-stream@>=1.5.0 <2.0.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.5.2.tgz" + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.5.4.tgz" }, "test-exclude": { "version": "3.3.0", "from": "test-exclude@>=3.3.0 <4.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-3.3.0.tgz" + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-3.3.0.tgz", + "dev": true }, "text-table": { "version": "0.2.0", "from": "text-table@>=0.2.0 <0.3.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "dev": true }, "then-request": { "version": "2.2.0", "from": "then-request@>=2.0.1 <3.0.0", "resolved": "https://registry.npmjs.org/then-request/-/then-request-2.2.0.tgz", - "dependencies": { - "qs": { - "version": "6.4.0", - "from": "qs@>=6.1.0 <7.0.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz" - } - } + "dev": true }, "throat": { "version": "3.0.0", "from": "throat@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/throat/-/throat-3.0.0.tgz" + "resolved": "https://registry.npmjs.org/throat/-/throat-3.0.0.tgz", + "dev": true }, "through": { "version": "2.3.8", @@ -2869,46 +3504,53 @@ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz" }, "timed-out": { - "version": "3.0.0", - "from": "timed-out@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-3.0.0.tgz" + "version": "4.0.1", + "from": "timed-out@>=4.0.0 <5.0.0", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz" }, "tmpl": { "version": "1.0.4", "from": "tmpl@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz" + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", + "dev": true }, "to-fast-properties": { "version": "1.0.3", "from": "to-fast-properties@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz" + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "dev": true }, "to-object-path": { "version": "0.3.0", "from": "to-object-path@>=0.3.0 <0.4.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz" + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "dev": true }, "toml": { "version": "2.3.2", "from": "toml@>=2.3.2 <3.0.0", - "resolved": "https://registry.npmjs.org/toml/-/toml-2.3.2.tgz" + "resolved": "https://registry.npmjs.org/toml/-/toml-2.3.2.tgz", + "dev": true }, "tough-cookie": { "version": "2.3.2", "from": "tough-cookie@>=2.3.0 <2.4.0", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz", + "dev": true, "dependencies": { "punycode": { "version": "1.4.1", "from": "punycode@>=1.4.1 <2.0.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz" + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "dev": true } } }, "tr46": { "version": "0.0.3", "from": "tr46@>=0.0.3 <0.1.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz" + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "dev": true }, "trim-repeated": { "version": "1.0.0", @@ -2918,12 +3560,14 @@ "trim-right": { "version": "1.0.1", "from": "trim-right@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "dev": true }, "tryit": { "version": "1.0.3", "from": "tryit@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz" + "resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz", + "dev": true }, "tunnel-agent": { "version": "0.4.3", @@ -2933,44 +3577,55 @@ "tweetnacl": { "version": "0.14.5", "from": "tweetnacl@>=0.14.0 <0.15.0", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz" + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "dev": true, + "optional": true }, "type-check": { "version": "0.3.2", "from": "type-check@>=0.3.2 <0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz" + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "dev": true }, "type-detect": { "version": "1.0.0", "from": "type-detect@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz", + "dev": true }, "typedarray": { "version": "0.0.6", "from": "typedarray@>=0.0.6 <0.0.7", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz" + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "dev": true }, "uglify-js": { - "version": "2.8.26", + "version": "2.8.27", "from": "uglify-js@>=2.6.0 <3.0.0", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.26.tgz", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.27.tgz", + "dev": true, + "optional": true, "dependencies": { "source-map": { "version": "0.5.6", "from": "source-map@>=0.5.1 <0.6.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz" + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", + "dev": true, + "optional": true } } }, "uglify-to-browserify": { "version": "1.0.2", "from": "uglify-to-browserify@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "dev": true, + "optional": true }, "unbzip2-stream": { - "version": "1.0.10", + "version": "1.2.4", "from": "unbzip2-stream@>=1.0.9 <2.0.0", - "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.0.10.tgz", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.2.4.tgz", "dependencies": { "base64-js": { "version": "0.0.8", @@ -2987,12 +3642,14 @@ "underscore": { "version": "1.7.0", "from": "underscore@>=1.7.0 <1.8.0", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz" + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", + "dev": true }, "underscore.string": { "version": "2.4.0", "from": "underscore.string@>=2.4.0 <2.5.0", - "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.4.0.tgz" + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.4.0.tgz", + "dev": true }, "unzip-response": { "version": "2.0.1", @@ -3000,9 +3657,16 @@ "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz" }, "uri-js": { - "version": "2.1.1", - "from": "uri-js@>=2.1.1 <3.0.0", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-2.1.1.tgz" + "version": "3.0.2", + "from": "uri-js@>=3.0.2 <4.0.0", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-3.0.2.tgz", + "dependencies": { + "punycode": { + "version": "2.1.0", + "from": "punycode@>=2.1.0 <3.0.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.0.tgz" + } + } }, "url": { "version": "0.10.3", @@ -3017,17 +3681,20 @@ "user-home": { "version": "2.0.0", "from": "user-home@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz", + "dev": true }, "util": { "version": "0.10.3", "from": "util@>=0.10.3 <1.0.0", "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "dev": true, "dependencies": { "inherits": { "version": "2.0.1", "from": "inherits@2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "dev": true } } }, @@ -3044,37 +3711,49 @@ "validate-npm-package-license": { "version": "3.0.1", "from": "validate-npm-package-license@>=3.0.1 <4.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz" + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", + "dev": true }, "verror": { "version": "1.3.6", "from": "verror@1.3.6", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz" + "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz", + "dev": true + }, + "walkdir": { + "version": "0.0.11", + "from": "walkdir@>=0.0.11 <0.0.12", + "resolved": "https://registry.npmjs.org/walkdir/-/walkdir-0.0.11.tgz" }, "walker": { "version": "1.0.7", "from": "walker@>=1.0.5 <1.1.0", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz" + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz", + "dev": true }, "watch": { "version": "0.10.0", "from": "watch@>=0.10.0 <0.11.0", - "resolved": "https://registry.npmjs.org/watch/-/watch-0.10.0.tgz" + "resolved": "https://registry.npmjs.org/watch/-/watch-0.10.0.tgz", + "dev": true }, "webidl-conversions": { "version": "4.0.1", "from": "webidl-conversions@>=4.0.0 <5.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.1.tgz" + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.1.tgz", + "dev": true }, "whatwg-encoding": { "version": "1.0.1", "from": "whatwg-encoding@>=1.0.1 <2.0.0", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.1.tgz", + "dev": true, "dependencies": { "iconv-lite": { "version": "0.4.13", "from": "iconv-lite@0.4.13", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz" + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", + "dev": true } } }, @@ -3082,43 +3761,52 @@ "version": "4.8.0", "from": "whatwg-url@>=4.3.0 <5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-4.8.0.tgz", + "dev": true, "dependencies": { "webidl-conversions": { "version": "3.0.1", "from": "webidl-conversions@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz" + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "dev": true } } }, "which": { "version": "1.2.14", "from": "which@>=1.1.1 <2.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz" + "resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz", + "dev": true }, "which-module": { "version": "1.0.0", "from": "which-module@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "dev": true }, "window-size": { "version": "0.1.0", "from": "window-size@0.1.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz" + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "dev": true, + "optional": true }, "wordwrap": { "version": "1.0.0", "from": "wordwrap@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "dev": true }, "worker-farm": { "version": "1.3.1", "from": "worker-farm@>=1.3.1 <2.0.0", - "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.3.1.tgz" + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.3.1.tgz", + "dev": true }, "wrap-ansi": { "version": "2.1.0", "from": "wrap-ansi@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz" + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "dev": true }, "wrappy": { "version": "1.0.2", @@ -3128,7 +3816,8 @@ "write": { "version": "0.2.1", "from": "write@>=0.2.1 <0.3.0", - "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz" + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "dev": true }, "write-file-atomic": { "version": "2.1.0", @@ -3138,24 +3827,18 @@ "xml-name-validator": { "version": "2.0.1", "from": "xml-name-validator@>=2.0.1 <3.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-2.0.1.tgz" + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-2.0.1.tgz", + "dev": true }, "xml2js": { - "version": "0.4.15", - "from": "xml2js@0.4.15", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.15.tgz" + "version": "0.4.17", + "from": "xml2js@0.4.17", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.17.tgz" }, "xmlbuilder": { - "version": "2.6.2", - "from": "xmlbuilder@2.6.2", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-2.6.2.tgz", - "dependencies": { - "lodash": { - "version": "3.5.0", - "from": "lodash@>=3.5.0 <3.6.0", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.5.0.tgz" - } - } + "version": "4.2.1", + "from": "xmlbuilder@4.2.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-4.2.1.tgz" }, "xtend": { "version": "4.0.1", @@ -3165,34 +3848,39 @@ "y18n": { "version": "3.2.1", "from": "y18n@>=3.2.1 <4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz" + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "dev": true }, "yargs": { "version": "3.10.0", "from": "yargs@>=3.10.0 <3.11.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz" + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "dev": true, + "optional": true }, "yargs-parser": { "version": "4.2.1", "from": "yargs-parser@>=4.2.0 <5.0.0", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz", + "dev": true, "dependencies": { "camelcase": { "version": "3.0.0", "from": "camelcase@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz" + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "dev": true } } }, "yauzl": { - "version": "2.7.0", + "version": "2.8.0", "from": "yauzl@>=2.4.2 <3.0.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.7.0.tgz" + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.8.0.tgz" }, "zip-stream": { - "version": "1.1.0", + "version": "1.1.1", "from": "zip-stream@>=1.1.0 <2.0.0", - "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-1.1.0.tgz" + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-1.1.1.tgz" } } }